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.

TI-RTOS 2.10 and 1382400 baud UART with DMA, fail to transmit

Other Parts Discussed in Thread: TM4C1233H6PM

This post is related to a previous post http://e2e.ti.com/support/embedded/tirtos/f/355/t/385765#pi239031349=2

  • Custom board
  • TM4C1233H6PM processor
  • 80MHz external clock
  • WT32i bluetooth radio on UART1 running at 1382400 baud
  • TI-RTOS 2.10 and UART DMA driver 

Brief problem description: when attempting to communicate to the external module at a speed of 1382400 using the 2.10 UART DMA driver no data is sent out over the UART and no data is received. 

The processor interfaces to a Blue giga wt32i bluetooth radio using UART1. Previously I was having problems receiving "large frames" (48 bytes) in callback mode and was getting a FIFO overflow. Only part of the frame was being received. One of the suggestions to fix this problem was to upgrade to the latest version of TI-RTOS and use the new UART DMA driver. The project required DMA to be added to the UART so this change was to be done eventually anyway. 

During the BT radio setup I check its settings to determine if the radio is pre-set and can therefore skip a more in-depth setup process (RFD, connectivity mode, etc). The settings can't be individually checked but can be all requested at once. When the settings are requested the radio responds with several strings (about 650 bytes in all) of all the radios current settings. In the past the code would parse the incoming stream and at each newline the setting would be checked, buffers reset and the uart input read again for the next setting. This method allowed me to avoid the "large frame" problem I was having since each individual setting was usually only about 24 bytes long or so. With the DMA driver, checking the individually received bytes cannot be simply done. So, instead I put the UART into callback mode, give the UART driver a large buffer to get all 650+ bytes at once and then monitor the buffer until all of the settings were received. The callback mode is used to notify the system that the receive buffer filled up (and mainly I use it to determine if I need to give the UART a larger buffer during the read). Once the settings are received I would then do the frame parsing for the pre-set check.

The problem is that at high speeds (1382400) the frame sent to the radio to receive its settings is actually never sent and therefore the radio does not respond with the requested data. I hooked up the uart tx line to an O-scope and monitored it to trigger on any transition high or low. When Uart_write() function was called the O-scope never triggered, the UART line remained quiet.

At lower speeds (115200) the UART DMA driver works just as expected. Traffic is sent and received over the UART interface, and data frames are fully formed.

Things to note:

  1. I ensured the speed that radio is communicating at is the correct speed for the micro processor by using a previous non-dma version of the code to set the speed. 115200 for the radio and uP running DMA, and 1382400 for the radio and uP running DMA.
  2. The bytes transmitted in the return value of Uart_write() is not 0. The length of the frame sent to the radio is the same as the return value (in this case 8 bytes). So even though no data is sent out of the uart at 1382400 (verified via O-scope) the return value is still set to 8.
  3. If I set a break point on or just before the Uart_write() function and wait for a second (or so) the transmit works. If I put a Task_sleep() of about 1 second just before the Uart_write() the transmit works. This seems to imply that the UART or UART driver is not ready to transmit in some way but I am not sure of what. All of the control and status registers seem to be properly set and the uart handle is not NULL.

Snippet of my code:

ERROR_CODE eRadio_chk_settings (void)
{
#define SETTINGS_BUFF_SZ  1024
#define SET_SETTING_BUFF_SZ 64

  ERROR_CODE eEC = ER_OK;
  int iCmp_rslt = 0;
  uint16_t uiRcvd_len;
  int iStr_Len = 0;
  char cEcho_Check = 0;
  char * cBT_Rcvd_Settings = NULL;
  eEC = eUsing_radio_uart_dma();
  char * cSetting = NULL;
  char cBT_setting[SET_SETTING_BUFF_SZ ];
  int i = 0;

  memset(cBT_setting, 0x00, SET_SETTING_BUFF_SZ );
  eBSP_Set_radio_uart_to_callback();

  cBT_Rcvd_Settings = calloc(SETTINGS_BUFF_SZ, sizeof(char));
  if(cBT_Rcvd_Settings == NULL)
  {
    System_abort("Radio settings buffer failed allocation");
  }

  memcpy(cBT_setting, "SET BT\r\n", strlen("SET BT\r\n"));
//  Task_sleep(1000);  //With this delay in the code works at 1382400

  i = UART_write(sRadio_UART_handle, cBT_setting, strlen(cBT_setting));
  if(i == 0)
  {
    System_abort("Radio request settings not sent");
  }

  UART_read(sRadio_UART_handle, (uint8_t *)cBT_Rcvd_Settings, SETTINGS_BUFF);

  for(i = 0; i<30; i++)
  {
    if(strstr(cBT_Rcvd_Settings, "SET\r\n) != NULL)
    {
      eEC = ER_OK;
      break;
    }
    else
    {
      Task_sleep(100);
      eEC = ER_FAIL;
      continue;
    }
  }
  
  //cancel the read callback mode since the entire buffer was received and an overflow notification is not needed
  UART_readCancel(sRadio_UART_handle);

  eEC = eParse_Radio_Settings(cBT_Rcvd_Settings);
  
  if(eEC == ER_FAIL)
  { 
    //radio not set, perform in-depth setup
  }
  else
  {
    //radio pre-set, continue to application
  }

  //free the receive buffer
  free(cBT_Rcvd_Settings);
  return eEC;
}

void vRadio_read_cb(UART_Handle sHandle, void *buf, size_t count)
{

  if(count >= SETTINGS_BUFF_SZ)
  {
    System_abort("Radio receive buffer limit reached, assign a bigger buffer");
  }
  else
  {
    return;
  }
}

  • Hi Matt,

    how are you opening the UART? I'm curious to see your UART_Params.

    I was able to send data out at 1382400 baud via the UART Echo example, so I think the driver is capable of that baud rate. Are you sending anything onto the UART before the 1st UART_write() call in eRadio_chk_settings on line 29? Can you check if UART_write() returns "UART_ERROR"? (-1)?
  • My UART setup code is:

    #define RADIO_UART_BAUD_1382400  1382400
    #define RADIO_UART_BAUD_115200   115200
    #define RADIO_UART_BAUD          RADIO_UART_BAUD_1382400
    
    UART_Handle sRadio_UART_handle = NULL;
    UART_Params sRadio_UART_params;
    
    ERROR_CODE  eBSP_RadioUARTEnable(void)
    {
      ERROR_CODE eEC = ER_FAIL;
    
      if(sRadio_UART_handle != NULL)
      {
        UART_close(sRadio_UART_handle);
      }else{/*do nothing*/}
    
      sRadio_UART_handle = NULL;
      UART_Params_init(&sRadio_UART_params);
    
      sRadio_UART_params.readMode       = UART_MODE_BLOCKING;              /*!< Mode for all read calls */
      sRadio_UART_params.writeMode      = UART_MODE_BLOCKING;              /*!< Mode for all write calls */
      sRadio_UART_params.readTimeout    = 1000;                            /*!< Timeout for read semaphore */
      sRadio_UART_params.writeTimeout   = 1000;                            /*!< Timeout for write semaphore */
      sRadio_UART_params.readCallback   = NULL;          /*!< Pointer to read callback */
      sRadio_UART_params.writeCallback  = NULL;         /*!< Pointer to write callback */
      sRadio_UART_params.readReturnMode = UART_RETURN_FULL;             /*!< Receive return mode */
      sRadio_UART_params.readDataMode   = UART_DATA_BINARY;                /*!< Type of data being read */
      sRadio_UART_params.writeDataMode  = UART_DATA_BINARY;                /*!< Type of data being written */
      sRadio_UART_params.readEcho       = UART_ECHO_OFF;                   /*!< Echo received data back */
      sRadio_UART_params.baudRate       = INEEDMD_RADIO_UART_BAUD;              /*!< Baud rate for UART */
      sRadio_UART_params.dataLength     = UART_LEN_8;                      /*!< Data length for UART */
      sRadio_UART_params.stopBits       = UART_STOP_ONE;                   /*!< Stop bits for UART */
      sRadio_UART_params.parityType     = UART_PAR_NONE;                   /*!< Parity bit type for UART */
    
      if(sRadio_UART_handle == NULL)
      {
        sRadio_UART_handle = UART_open(INEEDMD_RADIO_UART_INDEX, &sRadio_UART_params);
      }
    
      if(sRadio_UART_handle == NULL)
      {
        eEC = ER_FAIL;
      }
      else
      {
        eEC = ER_OK;
      }
    
      return eEC;
    }

    And when I put it in callback mode the function is:

    ERROR_CODE  eBSP_Set_radio_uart_to_callback(void)
    {
      ERROR_CODE eEC = ER_FAIL;
    
      if(sRadio_UART_handle != NULL)
      {
        UART_close(sRadio_UART_handle);
      }else{/*do nothing*/}
    
      UART_Params_init(&sRadio_UART_params);
    
      sRadio_UART_params.readMode       = UART_MODE_CALLBACK;              /*!< Mode for all read calls */
      sRadio_UART_params.writeMode      = UART_MODE_BLOCKING;              /*!< Mode for all write calls */
      sRadio_UART_params.readTimeout    = BIOS_WAIT_FOREVER;                            /*!< Timeout for read semaphore */
      sRadio_UART_params.writeTimeout   = 1000;                            /*!< Timeout for write semaphore */
      sRadio_UART_params.readCallback   = vRadio_read_cb;          /*!< Pointer to read callback */
      sRadio_UART_params.writeCallback  = NULL;         /*!< Pointer to write callback */
      sRadio_UART_params.readReturnMode = UART_RETURN_FULL;             /*!< Receive return mode */
      sRadio_UART_params.readDataMode   = UART_DATA_BINARY;                /*!< Type of data being read */
      sRadio_UART_params.writeDataMode  = UART_DATA_BINARY;                /*!< Type of data being written */
      sRadio_UART_params.readEcho       = UART_ECHO_OFF;                   /*!< Echo received data back */
      sRadio_UART_params.baudRate       = INEEDMD_RADIO_UART_BAUD;              /*!< Baud rate for UART */
      sRadio_UART_params.dataLength     = UART_LEN_8;                      /*!< Data length for UART */
      sRadio_UART_params.stopBits       = UART_STOP_ONE;                   /*!< Stop bits for UART */
      sRadio_UART_params.parityType     = UART_PAR_NONE;                   /*!< Parity bit type for UART */
    
      sRadio_UART_handle = UART_open(INEEDMD_RADIO_UART_INDEX, &sRadio_UART_params);
    
      if(sRadio_UART_handle == NULL)
      {
        eEC = ER_FAIL;
      }
      else
      {
        eEC = ER_OK;
      }
      return eEC;
    }

  • I also threw up an assert after each write and it is not failing.

      i = UART_write(sRadio_UART_handle, cBT_setting, strlen(SET_BT_GET));
      vDEBUG_ASSERT("eRadio_chk_settings write fail", ((i != -1)|(i != 0)));
    
    
    
    void vDEBUG_ASSERT(char * cMsg,int iAssert)
    {
      ERROR_CODE eEC;
      uint16_t uiLen = 0;
      uiLen = 0;
    
      if(iAssert)
      {
        return;
      }
      else
      {
        eEC = eBSP_debugger_detect();
        if(eEC == ER_OK)
        {
          uiLen = strlen(cMsg);
          UART_writePolling(sDebug_UART_handle, SYS_HALT_MSG, strlen(SYS_HALT_MSG));
          UART_writePolling(sDebug_UART_handle, cMsg, uiLen);
          UART_writePolling(sDebug_UART_handle, "\r\n", strlen("\r\n"));
    
          System_printf(SYS_HALT_MSG);
          System_flush();
          System_abort(cMsg);
    
          ROM_IntMasterDisable();
          ROM_SysTickIntDisable();
          ROM_SysTickDisable();
          while(1){};
        }
        else
        {
          uiLen = strlen(cMsg);
          UART_writePolling(sDebug_UART_handle, SYS_ASSERT_RST_MSG, strlen(SYS_ASSERT_RST_MSG));
          UART_writePolling(sDebug_UART_handle, cMsg, uiLen);
          UART_writePolling(sDebug_UART_handle, "\r\n", strlen("\r\n"));
    
          ROM_IntMasterDisable();
          ROM_SysCtlReset();
        }
      }
    }

  • I'll try to isolate the UART_write() and ensure no traffic is being sent previous. Will reply with findings.
  • Turns out there was code being called previously that closed and reopened the UART. The above code works as expected.