AnsweredAssumed Answered

MQX releasing a semaphore in a interrupt handler

Question asked by Vivek Srinivasan on Aug 24, 2015
Latest reply on Sep 3, 2015 by Carlos_Musich

Hello everyone,

 

I'm using KSDK_1.2.0 with twrk65f180m.

 

Initially I tested the uart_edma_blocking example with bare metal and it worked fine.

 

Then I copied the example under a thread in an application which uses MQX operating system.

 

Basically I copied the below code into a thread (this is the only thread in that application). I commented out hardware_init() and OSA_Init() since they are already done. I have also disabled BSPCFG_ENABLE_IO_SUBSYSTEM since I want to use the uart_edma_blocking  example instead.

 

    uint8_t dmaRxChar  = 0;

    uint32_t byteCountBuff = 0;

 

 

    // Store runtime state structure for the eDMA driver

    edma_state_t                state;

    // Store runtime state structure for UART driver with EDMA

    uart_edma_state_t           uartStateEdma;

 

 

    // Config the eDMA driver

    edma_user_config_t          userConfig = {

        .chnArbitration  = kEDMAChnArbitrationRoundrobin,

        .notHaltOnError  = false

    };

 

 

    // Config the UART driver

    uart_edma_user_config_t     uartConfig = {

        .bitCountPerChar = kUart8BitsPerChar,

        .parityMode      = kUartParityDisabled,

        .stopBitCount    = kUartOneStopBit,

        .baudRate        = BOARD_DEBUG_UART_BAUD

    };

 

 

    // Enable clock for PORTs, setup board clock source, config pin

    //hardware_init();

 

 

    // Call OSA_Init to setup LP Timer for timeout

    //OSA_Init();

   

#if defined (TEST_CODE)

    semaphore_t testSemaphore;   

    OSA_SemaCreate(&testSemaphore, 0);   

    osa_status_t syncStatus = OSA_SemaWait(&testSemaphore, 1000u);

#endif

   

    // Initialize EDMA module for UART

    EDMA_DRV_Init(&state, &userConfig);

    UART_DRV_EdmaInit(BOARD_DEBUG_UART_INSTANCE, &uartStateEdma, &uartConfig);

 

 

    // Inform to start dma-uart blocking example

    byteCountBuff = sizeof(buffStart);

    UART_DRV_EdmaSendDataBlocking(BOARD_DEBUG_UART_INSTANCE, buffStart, byteCountBuff, 0u);

 

 

    // Inform user of what to do

    byteCountBuff = sizeof(bufferData1);

    UART_DRV_EdmaSendDataBlocking(BOARD_DEBUG_UART_INSTANCE, bufferData1, byteCountBuff, 0u);

 

 

    while(true)

    {

        // Wait to receive input data

        if (kStatus_UART_Success == UART_DRV_EdmaReceiveDataBlocking(BOARD_DEBUG_UART_INSTANCE, &dmaRxChar,1, OSA_WAIT_FOREVER))

        {

            // Echo received character

            UART_DRV_EdmaSendDataBlocking(BOARD_DEBUG_UART_INSTANCE, &dmaRxChar, 1u, 0u);

        }

    }

 

It sends the first set of data (buffStart) to the terminal after which it crashes and goes to hardfault handler.

 

The problem is when I step through the code it does not crash. I can see that the DMA interrupt happens. The call back function (UART_DRV_EdmaCompleteSendData) is called which posts the semaphore (txIrqSync). It continues to send the second set of data (bufferData1).

 

I'm not sure if I'm doing something wrong here. If I create, pend and release the semaphore outside an interrupt handler, I don't see this issue happening.

 

I'm not sure if I have to do some kind of critical section protection here. Not much information available on the MQX reference manual.

 

Any help is greatly appreciated.

 

 

Thank you.

Outcomes