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.

CC2340R5: Sending about 800 bytes in UART2 each 500ms is triggerring ICall_abort

Part Number: CC2340R5
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hello

I´m using the basic BLE project from SDK version 08.10.01.02 set as central role.

I did modify it to connect to 8 peripherals at the same time and enable indications to receive data each 150 ms from each device. The data is received asynchronously inside the ATT_HANDLE_VALUE_IND event, parsed and stored into structs for each connection.

This works fine and I have left this system running, connected to 8 peripherals for days without running into any serious problem (aside from reconnections needed). I now need to send about 800 bytes based on these acquired data over the serial port each 500 ms because I will have to update a graphic display and I´m testing this uart transmission requirement using the Display Module provided by the SDK.

When I insert this feature into the project, the system runs but eventually will hit ICall_abort function.

Data is sent for a varied period of time and the ICall_abort is called. The function stack does not have any trace, just showing icall abort and nothing more.

I´m doing this serial transmission using a timer set as below:

void appMain(void)
{
   /* // Setup periodic timer 
    ClockP_Params_init(&clockpParams);
    uint32_t clockTicks = GATTLIMIT_TIME_UNIT * (CLOCK_MS);
    clockpParams.period = clockTicks; //0 = one-shot timer
    clockpParams.startFlag = true;
    clockpParams.arg = (uintptr_t)periodicTimer;
    // Initialize clock instance.
    gattLimit_clkHandle = ClockP_construct(&gattLimit_clkStruct, (ClockP_Fxn)BLEAppUtil_invokeFunctionNoData, clockTicks, &clockpParams);
    */
  
  LGPTimerLPF3_Handle lgptHandle;
   LGPTimerLPF3_Params params;
   uint32_t counterTarget;
   // Initialize parameters and assign callback function to be used
   LGPTimerLPF3_Params_init(&params);
   params.hwiCallbackFxn = periodicTimer;
   params.prescalerDiv = 10;
   // Open driver
   lgptHandle = LGPTimerLPF3_open(0, &params);
   // Set counter target
   counterTarget = 480000 - 1;  // 100 ms with a system clock of 48 MHz
   LGPTimerLPF3_setInitialCounterTarget(lgptHandle, counterTarget, true);
   // Enable counter target interrupt
   LGPTimerLPF3_enableInterrupt(lgptHandle, LGPTimerLPF3_INT_TGT);
   // Start counter in count-up-periodic mode
   LGPTimerLPF3_start(lgptHandle, LGPTimerLPF3_CTL_MODE_UP_PER);
  
    // Call the BLEAppUtil module init function
    BLEAppUtil_init(&criticalErrorHandler, &App_StackInitDoneHandler,
                    &appMainParams, &appMainPeriCentParams);
}

void showDisplay(void)
{
#ifdef  USE_WEIGHT_HUD             
  char *colorB, *colorT, *colorL,i;
  char format[80];
  App_connInfo * currConnList = Connection_getConnList();
              
  for(i=0;i<MAX_NUM_BLE_CONNS;i++)
  {
    int line = APP_MENU_PROFILE_STATUS_LINE1+5*i;
#ifdef DEBUG_INDICATION 
    line = APP_MENU_PROFILE_STATUS_LINE3+5*i;
#endif
    if(currConnList[i].pFlags&BT_CONNECTED && currConnList[i].connHandle!=LINKDB_CONNHANDLE_INVALID)
    {
      //Mostra pesos
      if(currConnList[i].pFlags&FLAG_ERRO_AD)
      {
        MenuModule_printf(line++, 0, 
        MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_RED 
        "        REPORTADO ERRO AD       "
        MENU_MODULE_COLOR_RESET);
      }
      else if(currConnList[i].pFlags&FLAG_OVER)
      {
        MenuModule_printf(line++, 0, 
        MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_RED 
        "           OVERLOAD!!!          "
        MENU_MODULE_COLOR_RESET);
      }
      else
      {
        if(currConnList[i].pFlags&FLAG_BRUTO)
        {
          colorB=MENU_MODULE_COLOR_GREEN;
          colorL=MENU_MODULE_COLOR_WHITE;
        }
        else
        {
          colorL=MENU_MODULE_COLOR_GREEN;
          colorB=MENU_MODULE_COLOR_WHITE;
        }
        colorT=MENU_MODULE_COLOR_WHITE;
        sprintf(format, "%s%sB: %%07ld %s%sT: %%07ld %s%sL: %%07ld",MENU_MODULE_BORDER_COLOR_BLUE,colorB,MENU_MODULE_BORDER_COLOR_BLUE,colorT,MENU_MODULE_BORDER_COLOR_BLUE,colorL);
        MenuModule_printf(line++, 0,format, currConnList[i].pesoBruto, currConnList[i].pesoTara, currConnList[i].pesoLiq);
      }
      //Mostra estabilidade        
      if(currConnList[i].pFlags&FLAG_STABLE)
      {
        MenuModule_printf(line++, 0, 
        MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_GREEN 
        "             ESTAVEL            "
        MENU_MODULE_COLOR_RESET);
      }
      else
      {
        MenuModule_printf(line++, 0, 
        MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_YELLOW 
        "            INSTAVEL            "
        MENU_MODULE_COLOR_RESET);
      }
      //Mostra nível de bateria e RSSI
      if(currConnList[i].batLevel>=60)
      {
        colorB=MENU_MODULE_COLOR_GREEN;
      }
      else if(currConnList[i].batLevel>=30)
      {
        colorB=MENU_MODULE_COLOR_YELLOW;
      }
      else
      {
        colorB=MENU_MODULE_COLOR_RED;
      }
               
      if(currConnList[i].rssi>=-65)
      {
        colorT=MENU_MODULE_COLOR_GREEN;
      }
      else if(currConnList[i].rssi>=-80)
      {
         colorT=MENU_MODULE_COLOR_YELLOW;
      }
      else
      {
        colorT=MENU_MODULE_COLOR_RED;
      }
                
      if(currConnList[i].batLevel<100)
        sprintf(format, "%s%s   RSSI: %%d dBm   %s%sBat: %%d %%%%    ",MENU_MODULE_BORDER_COLOR_BLUE,colorT,MENU_MODULE_BORDER_COLOR_BLUE,colorB);
      else
        sprintf(format, "%s%s   RSSI: %%d dBm   %s%sBat: %%d %%%%   ",MENU_MODULE_BORDER_COLOR_BLUE,colorT,MENU_MODULE_BORDER_COLOR_BLUE,colorB);
      MenuModule_printf(line++, 0,format, currConnList[i].rssi,currConnList[i].batLevel);
      usleep(10000);
    }
    else
    {
      //Mostrar HUD desconectado
      MenuModule_printf(line++, 0, 
        MENU_MODULE_BORDER_COLOR_RED MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_YELLOW 
        "                                "
        MENU_MODULE_COLOR_RESET);

      MenuModule_printf(line++, 0, 
        MENU_MODULE_BORDER_COLOR_RED MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_YELLOW 
        "        DESCONECTADO!!!         "
        MENU_MODULE_COLOR_RESET);

      MenuModule_printf(line++, 0, 
        MENU_MODULE_BORDER_COLOR_RED MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_YELLOW 
        "                                "
        MENU_MODULE_COLOR_RESET);
    }
  }

#endif
}

void connectionHandler(void)
{
  App_connInfo * currConnList = Connection_getConnList();
  static uint8 i=0;
  uint8 j;
  
  App_scanResults *menuScanRes;
  uint8 size = Scan_getScanResList(&menuScanRes);
  
  for(j=0;j<MAX_NUM_BLE_CONNS;j++)
  {
    if(!memcmp(menuScanRes[i].address,currConnList[j].peerAddress,B_ADDR_LEN ))// && currConnList[j].connHandle!=LINKDB_CONNHANDLE_INVALID)
    {
      //Achou endereço MAC do elemento dentro do menu de conexão, abortar tentativa
      i++;
      if(i>=MAX_NUM_BLE_CONNS)
        i=0;
      break;
    }
  }
  
  if(j>=MAX_NUM_BLE_CONNS)
  {
    //MAC não existe na lista, connectar!!!
    //if(!(currConnList[i].pFlags&BT_CONNECTED))
    {
      //Não está conectado... CONECTAR!!!!
      BLEAppUtil_ConnectParams_t connParams =
      {
        .peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID,
        .phys = DEFAULT_INIT_PHY,
        .timeout = 1000
      };
      // Copy the selected address
      memcpy(connParams.pPeerAddress, menuScanRes[i].address, B_ADDR_LEN);
      BLEAppUtil_connect(&connParams);
      i++;
      if(i>=MAX_NUM_BLE_CONNS)
        i=0;
    }
  }
}

static void periodicTimer(LGPTimerLPF3_Handle lgptHandle, LGPTimerLPF3_IntMask interruptMask)
{
  static char displayRefresh = 0, connCnt = 0;
    //GPIO_toggle(CONFIG_GPIO_LED_RED);
  
  //Observador de auto conexão
  if(connCnt>=5)
  {
    BLEAppUtil_invokeFunctionNoData((void(*)(char*))connectionHandler);
    connCnt=0;
  }
  else
    connCnt++;
  
  //Fica atualizando o display com os dados de indicação
  if(displayRefresh>=DISPLAY_DELAY)
  {
    BLEAppUtil_invokeFunctionNoData((void(*)(char*))showDisplay);
    displayRefresh=0;
  }
  else
    displayRefresh++;
  
  
   
}

The serial port baudrate is set to max rate (921600 bps) and the tx ring buffer was even set to 1024 bytes (based on what I read on other threads) but the issue remains. Eventually, lets say inside 1 to 2 minutes of constant operation, this problem happens.

<in ti_drivers_config.c>

/*
 *  ============================= Display =============================
 */

#include <ti/display/Display.h>
#include <ti/display/DisplayUart2.h>

#define CONFIG_Display_COUNT 1


#define Display_UART2BUFFERSIZE 128
static char displayUART2Buffer[Display_UART2BUFFERSIZE];

DisplayUart2_Object displayUart2Object;

const DisplayUart2_HWAttrs displayUart2HWAttrs = {
    .uartIdx      = CONFIG_DISPLAY_UART,
    .baudRate     = 921600,
    .mutexTimeout = (unsigned int)(-1),
    .strBuf       = displayUART2Buffer,
    .strBufLen    = Display_UART2BUFFERSIZE
};

const Display_Config Display_config[CONFIG_Display_COUNT] = {
    /* CONFIG_Display_0 */
    /* XDS110 UART */
    {
        .fxnTablePtr = &DisplayUart2Ansi_fxnTable,
        .object      = &displayUart2Object,
        .hwAttrs     = &displayUart2HWAttrs
    },
};

const uint_least8_t Display_count = CONFIG_Display_COUNT;

.....................

#define CONFIG_UART2_COUNT 1

UART2LPF3_Object UART2LPF3_objects[CONFIG_UART2_COUNT];

static unsigned char uart2RxRingBuffer0[16];
/* TX ring buffer allocated to be used for nonblocking mode */
static unsigned char uart2TxRingBuffer0[1024];

..................

I don´t know if the problem is related to how I invoke the transmission over the serial port (entire related code is above) but I did try two types of timers with the same result.

Any help in order to avoid this is welcome.

Thank you

  • This is how the info shows up in a VT100 terminal and also the call stack when the problem happens.

  • Hi, 

    Thank you for reaching out. 

    May I kindly ask you to re-upload the image you have provided in your previous message? It does not seem to have gone through.

    Looking at your code, may I ask if changing Display_UART2BUFFERSIZE value has been tested (you can alter this value in SysConfig > Display > UART Buffer Size?

    Also, if not already done, could you use the ROV to ensure no memory overflow has occurred for the heap and stack? This is documented here.

    To finish, could you specify if you are using the display driver for debug only, or if you will also use it in your final implementation? The reason I am asking is because this driver is fairly large weight and may not be totally adapted to debug printing. 

    Best regards, 

  • Hi Clément

    Thanks for trying to help. It´s actually a shame since I did create this problem for myself, as usually.

    The problem is related to this line inside my first code snippet:

    usleep(10000);

    It was there because the display update function was being called from another place, not timer related, in an effort to try to avoid a flow control violation problem I´m having and I´m discussing in another thread. There is no point in calling a delay inside a timer ISR.

    I then moved the function call to a timer but didn´t pay attention to that little line.

    System is running since yesterday up to now with no problems related to ICall_abort anymore.

    I can confirm it works with default Display_UART2BUFFERSIZE as 128 and with ClockP timer and also LGPTimer implementations, so it is not a timer related problem.

  • Hi Alexandre,

    System is running since yesterday up to now with no problems related to ICall_abort anymore.

    Great you got this sorted out! 

    Let me know if more support is required. 

    Best regards,