This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

UART on cc2540

Hi,

I try to add some UART code to the SimpleBLEPeripheral project that runs on a smartRF05 rev1.8.1. The smartRF05 DB9 connector is connected to the serial port of the computer with a serial cable.

The problem is that the hal_uart doesn't call the callback function passed from the configuration structure until I stop the debugger by pressing the 'break' button and then the 'go' button. I can also make the UART working by disabling the T2IE (just after HAL_ENABLE_INTERRUPTS() into the SimpleBLEPeripheral_Main.c file). This interrupt enable is set into the LL_Init() function, so it is something from the BLE stack itself so it is not an option to stop it.

I have tried with hal_uart_dma and hal_uart_isr without any hope.

So what I have missing ?

 

-------------------------------------------------------------------------------

Bellow are the steps I have done:

First of all I enabled the uart api with HAL_UART=TRUE in project options.

I created two files (see lower) that use provided UART functions.

I have replaced the HCI_Init( taskID++ ) with uartInit(taskID++)  inside the OSAL_simpleBLECentral.c file.

I have replaced the HCI_ProcessEvent handler with uartProcessEvent handler into the tasksArr structure from the same file.

Test #1:

Compiling, loading and debug the project from the IAR software v8.10.3.

Set breakpoint to line 59 (uartParse();)  in file uart.c

Press F5 to launch the program.

From a serial console send a char. The debugger should stop on the breakpoint but it doesn't.

Click on the 'break' button. Click on the 'go' button.

From a serial console send a char. The debugger should stop on the breakpoint and it does.

Test #2:

Add   T2IE = 0; after  HAL_ENABLE_INTERRUPTS(); in file SimpleBLEPeripheral_Main.c

Compiling, loading and debug the project from the IAR software v8.10.3.

Set breakpoint to line 59 (uartParse();)  in file uart.c

Press F5 to launch the program.

From a serial console send a char. The debugger should stop on the breakpoint and it does.

 

-------------------------------------------------------------------------------

uart.h

-------------------------------------------------------------------------------

#ifndef UART_H

#define UART_H

#ifdef __cplusplus
extern "C"
{
#endif

extern void uartInit( uint8 task_id );
extern uint16 uartProcessEvent( uint8 task_id, uint16 events );

#ifdef __cplusplus
}
#endif

#endif /* UART_H */

-------------------------------------------------------------------------------

uart.c

-------------------------------------------------------------------------------



#include "hal_uart.h"
#include "uart.h"

/*********************************************************************
 * CONSTANTS
 */

/*********************************************************************
 * LOCAL FUNCTIONS
 */
static void uartCB(uint8 port, uint8 event);
static void uartParse();

/*********************************************************************
 * LOCAL VARIABLES
 */
static uint8 uartTaskID = 0xff;
static uint8 uartMsg[256];
static uint8 *uartMsgWr = &uartMsg[0];

static halUARTCfg_t com0 =
{
  FALSE,
  HAL_UART_BR_9600,
  FALSE,
  0,
  0,
  {
    0,
    0,
    0,
    NULL,
  },
  {
    0,
    0,
    0,
    NULL,
  },
  0,
  0,
  uartCB,
};


static void uartCB(uint8 port, uint8 event) {
  if (port != HAL_UART_PORT_0)
    return;
 
  switch (event) {
    case HAL_UART_RX_FULL:
      // hmm we are too slow
      break;
    case HAL_UART_RX_ABOUT_FULL:
    case HAL_UART_RX_TIMEOUT:
      // new message I hope :)
      uartParse(); // good for breakpoint
      break;
    case HAL_UART_TX_FULL:
      // wait until tx empty
      break;
    case HAL_UART_TX_EMPTY:
      // we are sure that the message is sent
      break;
  }
}

static void uartParse()
{
  uint16 bufLen = Hal_UART_RxBufLen(HAL_UART_PORT_0);
  uint16 i;
  uint8 c;
  for (i=0; i<bufLen; i++)
  {

    // read one char
    HalUARTRead(HAL_UART_PORT_0, &c, 1);

    // check if we got a LF
    if (c == 0x0a) {
      c = 0;
    }

    // save into the buffer
    *uartMsgWr++ = c;
  }
}

void uartInit( uint8 task_id )
{
    uint8 status;
   
    status = HalUARTOpen(HAL_UART_PORT_0, &com0);
    if ((status != HAL_UART_SUCCESS) || (com0.configured == FALSE)) {
      // find a way to signal an error to the host
      return;
    }
}

uint16 uartProcessEvent( uint8 task_id, uint16 events )
{
  // hmm some timing here or just process
  if (task_id == uartTaskID)
    return 0;
 
  return events;
}

  • Note for others and myself.

    Actually, the problem is that when power management is on, the system clock switches to 16Mhz. Of course the UART baud rate also need to change... Somehow, TI should found a solution to this as the power mode is changed by the stack.

    The tricky part is that if the clock changes during a byte rx or tx, the result is ugly.

    Any solution to that, other than disabling the power management ?