Sorry for answering late.
@aggarg the vTaskDelay() in vTask_Video_DMA_App is just for debugging, I made many versions adding vTaskDelay() in the tasks just to understand what is going on here. I attached the compete code at the bottom of the message
Yes, I did it , but nothing changed , all tasks work perfectly as long as I don’t use vTaskDelay()
In debugging mode, I noticed that:
- If I use the all tasks without vTaskDelay , everything work well, but FreeRTOS_Tick_Handler() is not called, but FreeRTOS_SWI_Handler → vTaskSwitchContext() is called .
- If I don’t create the task vTask_Video_DMA_App, The FreeRTOS_Tick_Handler() is called only if i use vTaskDelay().
- If I use VDMA interruptions and vTaskDelay() , The FreeRTOS_Tick_Handler() is not called. but FreeRTOS_SWI_Handler → vTaskSwitchContext() is called, and vTask_Video_DMA_App() is called also.
I am confused, it is not supposed that The FreeRTOS_Tick_Handler() has to be called ? even if vTaslDelay is not used?
I added FreeRTOS_SetupTickInterrupt() in the SetupIntrSystem_WR_RD() function just in case, but nothing changed
Here is the code :
int main( void )
{
SemVDMARd = xSemaphoreCreateBinary(); // Declared as Global variable
SemVDMAWr = xSemaphoreCreateBinary(); // Declared as Global variable
if(xTaskCreate( prvTxTask, ( const char * ) "Tx", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &xTxTask ) != pdPASS)
{
xil_printf("Tx Task was not created\r\n");
for(;;);
}
if(xTaskCreate( prvRxTask, ( const char * ) "GB", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, &xRxTask ) != pdPASS)
{
xil_printf("Rx Task was not created\r\n");
for(;;);
}
if( xTaskCreate( vTask_Video_DMA_App, ( const char * ) "VDMA", 10*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3, &xHandler_VDMA ) != pdPASS )
{
xil_printf("VDMA Task was not created\r\n");
for(;;);
}
xQueue = xQueueCreate( 4,sizeof( HWstring ) );
configASSERT( xQueue );
vTaskStartScheduler();
for( ;; );
}
static void prvTxTask( void *pvParameters )
{
for( ;; )
{
TxTaskEnterCounter++;
vTaskDelay(pdMS_TO_TICKS(500));
if(xQueueSend( xQueue, HWstring, 0L )){
TxTaskSendStringCounter++;
}
TxTaskExitCounter++;
}
}
static void prvRxTask( void *pvParameters )
{
char Recdstring[15] = "";
const TickType_t x1second = pdMS_TO_TICKS( DELAY_1_SECOND );
//xil_printf("Rx Task started\r\n");
for( ;; )
{ RxTaskEnterCounter++;
Tick_Cnt_dbg = xTaskGetTickCount();
if(xQueueReceive( xQueue, Recdstring, portMAX_DELAY))//portMAX_DELAY
{
RxTaskReceivedStringCounter++;
}
RxTaskExitCounter++;
}
}
The VDMA code and the interruption config ( as suggested in zynq-7020-interrupts-under-freertos :
void vTask_Video_DMA_App(void *args){
int status;
int Index;
u32 Addr;
XAxiVdma myVDMA;
ptr_myVDMA = &myVDMA;
XAxiVdma_Config *config = XAxiVdma_LookupConfig(XPAR_AXIVDMA_0_DEVICE_ID);
XAxiVdma_DmaSetup ReadCfg;
XAxiVdma_DmaSetup WriteCfg;
uint32_t VDMA_TaskEnterCounter = 0;
uint32_t VDMA_TookSmphr = 0;
uint32_t VDMA_TaskExitCounter = 0;
xil_printf("Task VDMA Started\r\n");
if(SemVDMARd==NULL){
xil_printf("Could not create semaphore SemVDMARd\n");
for(;;);
}
if(SemVDMAWr==NULL){
xil_printf("Could not create semaphore SemVDMAWr\n");
for(;;);
}
status = XAxiVdma_CfgInitialize(&myVDMA, config, config->BaseAddress);
if(status != XST_SUCCESS){
xil_printf("DMA Initialization failed");
for(;;);
}
status = XAxiVdma_SetFrmStore(&myVDMA, myVDMA.MaxNumFrames, XAXIVDMA_WRITE);
if (status != XST_SUCCESS) {
xil_printf(
"Setting Frame Store Number Failed in Write Channel"
" %d\r\n", status);
for(;;);
}
status = XAxiVdma_SetFrmStore(&myVDMA, myVDMA.MaxNumFrames, XAXIVDMA_READ);
if (status != XST_SUCCESS) {
xil_printf(
"Setting Frame Store Number Failed in Read Channel"
" %d\r\n", status);
for(;;);
}
// READ CHANNEL CONFIG
ReadCfg.VertSizeInput = VSize;
ReadCfg.HoriSizeInput = HSize*Bytes_Per_Data;
ReadCfg.Stride = HSize*Bytes_Per_Data;
ReadCfg.FrameDelay = 0;
ReadCfg.EnableCircularBuf = 1;
ReadCfg.EnableSync = 1;
ReadCfg.PointNum = 0;
ReadCfg.EnableFrameCounter = 0;
ReadCfg.FixedFrameStoreAddr = 0;
ReadCfg.GenLockRepeat = 0;
status = XAxiVdma_DmaConfig(&myVDMA, XAXIVDMA_READ, &ReadCfg);
if (status != XST_SUCCESS) {
xil_printf("Read channel config failed %d\r\n", status);
for(;;);
}
Addr = (u32)&(Buffer[0]);
for(Index = 0; Index < myVDMA.MaxNumFrames; Index++) {
ReadCfg.FrameStoreStartAddr[Index] = Addr;
Addr += FrameSize;
}
status = XAxiVdma_DmaSetBufferAddr(&myVDMA, XAXIVDMA_READ,ReadCfg.FrameStoreStartAddr);
if (status != XST_SUCCESS) {
xil_printf("Read channel set buffer address failed %d\r\n", status);
for(;;);
}
XAxiVdma_IntrEnable(&myVDMA, XAXIVDMA_IXR_COMPLETION_MASK, XAXIVDMA_READ);
WriteCfg.VertSizeInput = VSize;
WriteCfg.HoriSizeInput = HSize*Bytes_Per_Data;
WriteCfg.Stride = HSize*Bytes_Per_Data;
WriteCfg.FrameDelay = 0;
WriteCfg.EnableCircularBuf = 1;
WriteCfg.EnableSync = 1;
WriteCfg.PointNum = 0;
WriteCfg.EnableFrameCounter = 0;
WriteCfg.FixedFrameStoreAddr = 0;
WriteCfg.GenLockRepeat = 0;
status = XAxiVdma_DmaConfig(&myVDMA, XAXIVDMA_WRITE, &WriteCfg);
if (status != XST_SUCCESS) {
xil_printf("Write channel config failed %d\r\n", status);
for(;;);
}
Addr = (u32)&(Buffer[0]);
for(Index = 0; Index < myVDMA.MaxNumFrames; Index++) {
WriteCfg.FrameStoreStartAddr[Index] = Addr;
Addr += FrameSize;
}
status = XAxiVdma_DmaSetBufferAddr(&myVDMA, XAXIVDMA_WRITE,WriteCfg.FrameStoreStartAddr);
if (status != XST_SUCCESS) {
xil_printf("write channel set buffer address failed %d\r\n", status);
for(;;);
}
XAxiVdma_IntrEnable(&myVDMA, XAXIVDMA_IXR_COMPLETION_MASK, XAXIVDMA_WRITE);
memset((void *)Buffer, 0,FrameSize);
Xil_DCacheFlush();
//Xil_DCacheFlushRange(WriteFrameAddr, FRAME_HORIZONTAL_LEN * FRAME_VERTICAL_LEN * WriteCount);
status = SetupIntrSystem_WR_RD(&myVDMA, WRITE_INTR_ID, READ_INTR_ID);
if (status != XST_SUCCESS) {
xil_printf(
"Setup interrupt system failed %d\r\n", status);
for(;;);
}
status = XAxiVdma_DmaStart(&myVDMA, XAXIVDMA_WRITE);
if (status != XST_SUCCESS) {
xil_printf("Start Write transfer failed %d\r\n", status);
for(;;);
}
status = XAxiVdma_DmaStart(&myVDMA,XAXIVDMA_READ);
if (status != XST_SUCCESS) {
if(status == XST_VDMA_MISMATCH_ERROR) xil_printf("Start Read transfer failed %d\r\n",status);
for(;;);
}
// Binary semaphores are set in main()
for(;;){
VDMA_TaskEnterCounter++;
//vTaskDelay( pdMS_TO_TICKS(500) ); JUTS FOR DEBUGGING
if( xSemaphoreTake( SemVDMAWr, portMAX_DELAY) == pdTRUE ){//portMAX_DELAY
VDMA_TookSmphr++;
//xil_printf("VDMA: Semphr took \r\n");
}
VDMA_TaskExitCounter++;
}
}
static void WriteCallBack(void *CallbackRef, u32 Mask)
{
static BaseType_t xHigherPriorityTaskWoken2 = pdFALSE;
static int counterTx = 0;
xHigherPriorityTaskWoken2 = pdFALSE;
counterTx++;
//xSemaphoreGiveFromISR(SemVDMAWr, &xHigherPriorityTaskWoken2);
if(counterTx > 30){
counterTx = 0;
xSemaphoreGiveFromISR(SemVDMAWr, &xHigherPriorityTaskWoken2);
}
portYIELD_FROM_ISR( xHigherPriorityTaskWoken2);
}
static void WriteErrorCallBack(void *CallbackRef, u32 Mask)
{
xil_printf("W_ERR\r\n");
}
static void ReadCallBack(void *CallbackRef, u32 Mask)
{
static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
static int counterRx = 0;
xHigherPriorityTaskWoken = pdFALSE;
counterRx++;
if(counterRx>100){
xSemaphoreGiveFromISR(SemVDMARd, &xHigherPriorityTaskWoken);
}
portYIELD_FROM_ISR( xHigherPriorityTaskWoken);
}
static void ReadErrorCallBack(void *CallbackRef, u32 Mask)
{
/* User can add his code in this call back function */
xil_printf("R_ERR\r\n");
}
static int SetupIntrSystem_WR_RD(XAxiVdma *AxiVdmaPtr, u16 ReadIntrId, u16 WriteIntrId)
{
int Status;
configSETUP_TICK_INTERRUPT();
/* Instance of the Interrupt Controller */
XScuGic *IntcInstancePtr = &xInterruptController;
Status = xPortInstallInterruptHandler( ReadIntrId, (XInterruptHandler) XAxiVdma_ReadIntrHandler, AxiVdmaPtr);
Status = xPortInstallInterruptHandler( WriteIntrId, (XInterruptHandler) XAxiVdma_WriteIntrHandler, AxiVdmaPtr);
XScuGic_SetPriorityTriggerType(IntcInstancePtr, ReadIntrId, 0xA0, 0x3);//(configMAX_API_CALL_INTERRUPT_PRIORITY + 1) << portPRIORITY_SHIFT
XScuGic_SetPriorityTriggerType(IntcInstancePtr, WriteIntrId, 0xA0, 0x3);
//Xil_ExceptionInit();
// Connect the interrupt controller interrupt handler to the hardware interrupt handling logic in the processor.
//Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,IntcInstancePtr);
Xil_ExceptionEnable();//Enable interrupts in the Processor.
/* Register callback functions
*/
XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_GENERAL, ReadCallBack, (void *)AxiVdmaPtr, XAXIVDMA_READ);
XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_ERROR, ReadErrorCallBack, (void *)AxiVdmaPtr, XAXIVDMA_READ);
XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_GENERAL, WriteCallBack, (void *)AxiVdmaPtr, XAXIVDMA_WRITE);
XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_ERROR, WriteErrorCallBack, (void *)AxiVdmaPtr, XAXIVDMA_WRITE);
vPortEnableInterrupt(ReadIntrId);
vPortEnableInterrupt(WriteIntrId);
return XST_SUCCESS;
}