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:
- 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.
- 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.
- 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; } }