Interrupt driven UART with PEx

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Interrupt driven UART with PEx

Jump to solution
2,600 Views
drew_k
Contributor III

I'm trying to setup an interrupt driven UART comm system over UART1 on a TWR-K64F120M. I'm running into trouble getting the generated code to execute properly. It's likely I've missed something but I'm obviously not sure what.

 

Here's what I've setup:

 

1) Created a new KDS project for the TWR-K64F120M

2) Added an fsl_uart component

3) Set the RxD and TxD to the proper pins.

4) Configured baud rate for 115200bps

5) Enabled a callback (currently empty)

6) Enabled the RX_TX IRQ

7) Built and run the program.

8) Runs properly (just blinking an LED) until I transmit a character, at which point the IRQ fires (checked with a breakpoint), and calls the default peripheral driver IRQ handler (UART_DRV_IRQHandler). At this point, my LED stops blinking and if I pause the debugger, I'm sitting at the start of the Default_Handler section of the startup.MK64F12.S file. I'm also not getting to my callback function which should toggle a second LED each time it fires.

 

I know my UART is configured to the correct clock/baud settings because I was able to successfully implement a polling receiver by just looping and looking for data in the RxD register.

 

If I comment out the autogenerated function then the program doesn't crash. It does just spin in the IRQ though because the flag is never being cleared with a read. Specifically, the issue seems to be with the call to UART_HAL_Getchar which is responsible for reading the register and clearing the flag. If I comment out solely that line (and the while loop around it, as this chip supports a UART FIFO), then again, I just spin with repeated IRQ fires but at least I'm not apparently resetting.

 

Update (1/19/15): I replaced the call to the UART_DV_IRQHandler with a while loop that just reads UART1's data register while the RDRF flag is set and this works just fine for receiving characters. So it seems like there's something misconfigured with my UART HAL Driver. Not sure what though...

 

Any ideas?

 

-Drew

 

Message was edited by: Drew Kelley

Labels (1)
1 Solution
1,121 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Drew,

I see your question now, but I am not sure if it is a bug or not. In the interrupt service routine function void UART_DRV_IRQHandler(uint32_t instance), there is the line:

  if((UART_HAL_GetRxDataRegFullIntCmd(baseAddr))

      && (UART_HAL_IsRxDataRegFull(baseAddr)))

    {

          UART_HAL_Getchar(baseAddr, uartState->rxBuff);

}

it gives the information, after the Kinetis UART receive a char, the  function UART_HAL_Getchar()     will be executed, the uartState->rxBuff pointer should have been initializerd, but in some case, it is not. Of course, the uartState structure pointer has been initialized in the UART_DRV_Init(), but the uartState->rxBuff is not initialized if you do not call the two function:

static uart_status_t UART_DRV_StartReceiveData(uint32_t instance,

                                               uint8_t * rxBuff,

                                               uint32_t rxSize)

or

uart_rx_callback_t UART_DRV_InstallRxCallback(uint32_t instance,

                                              uart_rx_callback_t function,

                                              uint8_t * rxBuff,

                                              void * callbackParam,

                                              bool alwaysEnableRxIrq)

Pls call the UART_DRV_StartReceiveData() function after the UART_DRV_Init() so that the rxBuff pointer can be initialized if your UART want to receive data.

Pls have a try.

BR

XiangJun Rong

typedef struct UartState {

    uint8_t txFifoEntryCount;      /*!< Number of data word entries in TX FIFO. */

    const uint8_t * txBuff;        /*!< The buffer of data being sent.*/

    uint8_t * rxBuff;              /*!< The buffer of received data. */

    volatile size_t txSize;        /*!< The remaining number of bytes to be transmitted. */

    volatile size_t rxSize;        /*!< The remaining number of bytes to be received. */

    volatile bool isTxBusy;        /*!< True if there is an active transmit. */

    volatile bool isRxBusy;        /*!< True if there is an active receive. */

    volatile bool isTxBlocking;    /*!< True if transmit is blocking transaction. */

    volatile bool isRxBlocking;    /*!< True if receive is blocking transaction. */

    semaphore_t txIrqSync;         /*!< Used to wait for ISR to complete its TX business. */

    semaphore_t rxIrqSync;         /*!< Used to wait for ISR to complete its RX business. */

    uart_rx_callback_t rxCallback; /*!< Callback to invoke after receiving byte.*/

    void * rxCallbackParam;        /*!< Receive callback parameter pointer.*/

} uart_state_t;

View solution in original post

8 Replies
1,121 Views
dave408
Senior Contributor II

Hi drew.k​, I know your post is old, but since XiangJun's response wasn't marked as correct, I thought I'd post up a reply.  I had the same problem that you had initially, and in stepping through the SDK, I found the same issue that XiangJun has referred to.

More specifically, to solve this problem in PEx, you just have to specify the buffer.  Here's what mine looks like:

pastedImage_0.png

Once you do this and declare the buffer in your code somewhere, the crashing will be resolved.

1,121 Views
kyizawwin
Contributor II

Thanks, Dave! This really help me. Not sure why. Could you please share your opinion?

Bryan

0 Kudos
1,121 Views
dave408
Senior Contributor II

Hi kyizawwin​, you just have to drill down into the SDK code for the UART driver.  In there, you'll see that it needs to put the incoming data somewhere and wants to write to a buffer.  That's the buffer that gets enabled when you check the checkbox for Rx Buffer and declare it in your code (which is necessary or the array is uninitialized).

0 Kudos
1,121 Views
kyizawwin
Contributor II

Hi Dave,

I am facing pretty strange problem with call back buffer.

Everytime the data received, rx_callback_buff will add into the buffer. For example, if the data receive is "abc", on second time the buffer become "abcabc". So, I tried to reset by following statement.

UART_DRV_ReceiveData(FSL_BLE, rx_callback_buff , sizeof(rx_callback_buff ));

It works well but on 2nd data receive, it come like "aac" instead of "abc". Do you encounter similar problem? Which step did I do wrongly?

Thanks,

0 Kudos
1,121 Views
dave408
Senior Contributor II

I don't call UART_DRV_ReceiveData.  I've enabled the Rx callback function, so it's there where I look at the RX buffer.  In the ISR context, you'll use something like this:

uart_state_t* uart = (uart_state_t*)uartState;

to get at the UART struct.  Then you can access the data in the buffer by looking at uart->rxBuff.

0 Kudos
1,121 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Regaring your question, as far as I know if you call the UART_DRV_SendData() api function, the SDK will use interrupt mode to transfer UART data, if you call the UART_DRV_SendDataBlocking(), the SDK will use polling mode to transfer data.

Pls use the following code and add the toggling GPIO in UART_DRV_IRQHandler(), I think you can enter the ISR.

BR

Xiangjun Rong

/* Including needed modules to compile this module/procedure */

#include "Cpu.h"

#include "Events.h"

#include "pin_init.h"

#include "uartCom1.h"

#if CPU_INIT_CONFIG

  #include "Init_Config.h"

#endif

/* User includes (#include below this line is not maintained by Processor Expert) */

/*lint -save  -e970 Disable MISRA rule (6.3) checking. */

char outputBuffer[]="hello world\r\n";

int main(void)

/*lint -restore Enable MISRA rule (6.3) checking. */

{

  /* Write your local variable definition here */

  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/

  PE_low_level_init();

  /*** End of Processor Expert internal initialization.                    ***/

// UART_DRV_SendData(FSL_UARTCOM1,&outputBuffer[0],sizeof(outputBuffer));

  /* Write your code here */

  /* For example: for(;;) { } */

  /*** Don't write any code pass this line, or it will be deleted during code generation. ***/

  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/

  #ifdef PEX_RTOS_START

    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */

  #endif

  /*** End of RTOS startup code.  ***/

  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/

  for(;;)

  {

      UART_DRV_SendData(FSL_UARTCOM1,&outputBuffer[0],sizeof(outputBuffer));

  }

  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/

} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

0 Kudos
1,121 Views
drew_k
Contributor III

Thanks for the reply but I think you missed the problem in my original question.I don't have any issue sending characters through whatever avenue the SDK utilizes.


My issue is with the receipt of characters from the computer. The RX_TX Interrupt is triggering properly when a byte is received and the code does enter the UART_DRV_IRQHANDLER function just fine. However when it gets to the call to UART_HAL_Getchar something strange happens and the program crashes/hangs. If I specifically replace the call to UART_HAL_Getchar with a manual read of the UART1 data register, everything works just fine. There's something wrong, specifically with that call to UART_HAL_Getchar, and I'd guess the issue is with my config, but I don't know where.


-Drew

0 Kudos
1,122 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Drew,

I see your question now, but I am not sure if it is a bug or not. In the interrupt service routine function void UART_DRV_IRQHandler(uint32_t instance), there is the line:

  if((UART_HAL_GetRxDataRegFullIntCmd(baseAddr))

      && (UART_HAL_IsRxDataRegFull(baseAddr)))

    {

          UART_HAL_Getchar(baseAddr, uartState->rxBuff);

}

it gives the information, after the Kinetis UART receive a char, the  function UART_HAL_Getchar()     will be executed, the uartState->rxBuff pointer should have been initializerd, but in some case, it is not. Of course, the uartState structure pointer has been initialized in the UART_DRV_Init(), but the uartState->rxBuff is not initialized if you do not call the two function:

static uart_status_t UART_DRV_StartReceiveData(uint32_t instance,

                                               uint8_t * rxBuff,

                                               uint32_t rxSize)

or

uart_rx_callback_t UART_DRV_InstallRxCallback(uint32_t instance,

                                              uart_rx_callback_t function,

                                              uint8_t * rxBuff,

                                              void * callbackParam,

                                              bool alwaysEnableRxIrq)

Pls call the UART_DRV_StartReceiveData() function after the UART_DRV_Init() so that the rxBuff pointer can be initialized if your UART want to receive data.

Pls have a try.

BR

XiangJun Rong

typedef struct UartState {

    uint8_t txFifoEntryCount;      /*!< Number of data word entries in TX FIFO. */

    const uint8_t * txBuff;        /*!< The buffer of data being sent.*/

    uint8_t * rxBuff;              /*!< The buffer of received data. */

    volatile size_t txSize;        /*!< The remaining number of bytes to be transmitted. */

    volatile size_t rxSize;        /*!< The remaining number of bytes to be received. */

    volatile bool isTxBusy;        /*!< True if there is an active transmit. */

    volatile bool isRxBusy;        /*!< True if there is an active receive. */

    volatile bool isTxBlocking;    /*!< True if transmit is blocking transaction. */

    volatile bool isRxBlocking;    /*!< True if receive is blocking transaction. */

    semaphore_t txIrqSync;         /*!< Used to wait for ISR to complete its TX business. */

    semaphore_t rxIrqSync;         /*!< Used to wait for ISR to complete its RX business. */

    uart_rx_callback_t rxCallback; /*!< Callback to invoke after receiving byte.*/

    void * rxCallbackParam;        /*!< Receive callback parameter pointer.*/

} uart_state_t;