Unknown function 0xA60: seems to happen while calling a particular application API only

OK I'm seeing this weird behavior that I'm trying to understand

I have a sensor task that reads sensor data continuously every 4 seconds. The value is then notified to the subscriber (NotificationManager) which then sends the data to UART, (and later to BLE custom service. 

Until I connect the BLE service from nRF Connect app, it all works ok (I see the UART print fine)

But when I attempt to connect to the BLE service via nRF Connect App, the program halts at 0xA60. (I have previously dealt with issues around logging and I wonder if it's related to it). Note that when I comment out the Notify call, the BLE connects OK. What does that tell us?

void MCP9808::Run()
{
    Write(Register::AMBIENT, 1);
    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

    while(true)
    {
        Read();
        
        uint32_t taskNotify = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

        ParseTempInC();
        //Notify();  // uncommenting out results in A60 error upon BLE connection

        vTaskDelay(pdMS_TO_TICKS(DELAY_MS_PER_READ));
    }
}

void NotificationManager::Update(Publisher* publisher) 
{
    // retrieve the publisher's category
    auto category = publisher->GetCategory();

    switch (category)
    {
      case Publisher::Category::TEMPERATURE:
      {
	    MCP9808* mcp9808 = dynamic_cast<MCP9808*>(publisher);
	    if (!mcp9808) return;
	    
	    uint16_t value = mcp9808->GetTempInC();

	    char msg[100] = {0};
	    snprintf (msg, sizeof(msg) - 1, "Temp = %uC", value);
	    PushNotification(MakeNotification(msg), 
      }
    }
}  

Notification NotificationManager::MakeNotification(char* msg)
{
    Notification notification = {0};
    strncpy(notification.msg, msg, sizeof(notification.msg));
    notification.category = category;
    return notification; 
}

void NotificationManager::PushNotification(Notification notification)
{
    // write data to UART
    mUART.Write(notification.msg);
    
    // updating the custom value in the BLE characteristic table
    // mBLENotifierSrv.UpdateValue(reinterpret_cast<uint8_t*>(notification.msg));
}

Parents
  • 0XA60 is a halt instruction in the MBR hardfault handler, which means that your application somehow hardfaulted. 

    It could be many reasons but most likely are stack overflow or your tried to call an SVC (sd_xxx) call from a higher priority.

    Can I get your project to replicate the issue? Have your reviewed all the priorities of tasks from which you call softdevice API?

    Have you checked if your have any stack overflow?

  • The stack size is 2048 bytes, yes?

    I filled it in with 0xAA and I still see 0xAA during runtime (doesn't get overwritten) so probably no stack overflow.

    #define STACK_PATTERN 0xAA  // Use the byte pattern 0xAA for the stack initialization
    #define STACK_SIZE    2048  // Assuming a stack size of 2048 bytes for demonstration
    #define STACK_LIMIT   128   // The limit in bytes that we don't want the stack to approach
    
    uint8_t stack[STACK_SIZE];
    
    void initializeStackWithPattern() 
    {
        for (int i = 0; i < STACK_SIZE; i++) {
            stack[i] = STACK_PATTERN;
        }
    }
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
        initializeStackWithPattern();
        // ...
    }

    I'm using the same priority for the two tasks I have i.e, 0.

    I can certainly attach a project once you make this thread private. Appreciate it a lot, Susheel

    Looking forward to solving this together

  • I increased configTOTAL_HEAP_SIZE to 8192 and the tasks' stack depth to 200 and I no longer see the issue.

    But why do you think increasing the heap size is a temporary solution? I changed the heap size back to 4096 with 200 stack depth and it still works. Previously just increasing the stack depth resulted in  NRF_ERROR_NO_MEM.

    Can you make up a conclusion?

  • morpho said:
    But why do you think increasing the heap size is a temporary solution? I changed the heap size back to 4096 with 200 stack depth and it still works. Previously just increasing the stack depth resulted in  NRF_ERROR_NO_MEM.

    I might have confused you there. What I meant to say is that increase the HEAP size to a large number temporarily and when we know which task stack was overflowing, then you can calibrate the increase in heap size and increase in the stack size of that task to a value that is not too big.

    While debugging I normally change the heap size to 4096 and the stack size of every task to atleast 512 bytes. But on application with tight available memory, this might be too much. 

    So my use of temporary was only to temporarily increase the heap size to a very big number and the temporarily increase to the task size to a very big number just to pinpoint  the rogue task that is using more stack than ancipated. And then for release version of your application you can fine tune the the heap and stack size (hence moving away from the temporary high values)

  • While debugging I normally change the heap size to 4096 and the stack size of every task to atleast 512 bytes. But on application with tight available memory, this might be too much. 

    I already am on 4096 heap and 400 bytes of stack for a task.

    Anyways, there's one task named "Process" but here, buff contains "Pro". Do you see why it could be?

    extern "C"
     {
        void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
        {
            ( void ) pcTaskName;
            ( void ) xTask;
    
            char buff[100] = {0};
            strncpy(buff, (const char *)pcTaskName, sizeof(buff) - 1); // buff = "Pro"
    
            UBaseType_t uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);
        
            while(1);
        }
    }

  • maybe do a strncpy like below instead

    strncpy(buff, (const char *)pcTaskName, configMAX_TASK_NAME_LEN); 

    Or check in the memory if there is only Pro in the sequential address of the memory of if it has the whole "Process" name and it is just the matter of using the right size in the API.

  • Copying configMAX_TASK_NAME_LEN bytes still produces Pro.

    What memory view would you look into? 
    No way anyone can decode this

Reply Children
Related