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.

Compiler/CC2642R: M4_0 IMPRECISERR: Delayed BusFault

Part Number: CC2642R

Tool/software: TI C/C++ Compiler

Hello,

As the title shows, I am consistently getting an IMPRECISERR that causes a fault on the processor and (under debug conditions) abort code to be executed and the registers to be dumped in the console as shown below.

[Cortex_M4_0] usFault: IMPRECISERR: Delayed Bus Fault, exact addr unknown, address: e000ed38
Exception occurred in background thread at PC = 0x00002da4.
Core 0: Exception occurred in ThreadType_Task.
Task name: {unknown-instance-name}, handle: 0x20001bc0.
Task stack base: 0x20001c10.
Task stack size: 0x800.
R0 = 0x0d000148  R8  = 0x20004d7c
R1 = 0x0000000e  R9  = 0x20001b80
R2 = 0x00000000  R10 = 0x000186a0
R3 = 0x00000000  R11 = 0x0000c350
R4 = 0xffffffff  R12 = 0x20002330
R5 = 0xffffffff  SP(R13) = 0x20002358
R6 = 0xffffffff  LR(R14) = 0x00009da5
R7 = 0x0000ffff  PC(R15) = 0x00002da4
PSR = 0x01001000
ICSR = 0x00400803
MMFSR = 0x00
BFSR = 0x04
UFSR = 0x0000
HFSR = 0x40000000
DFSR = 0x00000001
MMAR = 0xe000ed34
BFAR = 0xe000ed38
AFSR = 0x00000000
Terminating execution...

The task stack base is pointing to the location of our main task loop stack, the same task that is calling a function we use for logging events on our product, which causes the failure. This segment of code was working properly with no issues when we were logging events on internal flash, but due to design considerations and our growing program size, we are implementing the log on an external SPI flash chip, the AT25SF041 from Adesto. Attached is the code for some of the relevant functions, as well as the disassembly of this function and the register/stack contents at various points of execution.

I have stepped through the disassembly and found the issue lies in that the processor is popping invalid data off of the stack into the PC and instead of returning back to our main task. This is then attempting execution of a memory location that is invalid, causing the fault. What I don't see is the relevant portion of the stack (what should be popped into our registers) being modified, or where this invalid memory location is coming from. 

Another bit of information I have noticed is that if I comment out the last line of the C code that increments our indexing for the event log (EventLogPtr.lastEntry += log_entry_index), the code will succeed, but obviously our pointer never moves so we can't have a contiguous log, just one log entry that can be overwritten indefinitely. Another "fix" I've seen (which still leads to similar issues later) is that if you turn of code optimizations on this function, it will manage to execute properly. It isn't until a later usage of the same code that a similar issue arises, and I'd also like to avoid having to use #pragmas to save the day if possible.

From all of this my questions are - what exactly does this imprecise error mean? Is there anything in our relevant code that would point to a possible issue? Could this be a compiler based issue that is handling our code incorrectly? 

Any tips or info on where to start/go next on debugging this issue would be greatly appreciated.

Regards,
Tyler Witt

struct event_log_ptr
{
  uint32_t firstEntry;    // "head" of event log - oldest event log entry (memory offset)
  uint32_t lastEntry;     // "tail" of event log - current event log entry (memory offset)
  uint32_t lastUploaded;  // Memory offset for end of last uploaded event
  uint16_t lastSeqNumber; // Last counter value used for sequential counter of entries
} __attribute__((packed));
typedef struct event_log_ptr event_log_ptr;

// Global Variables
struct event_log_ptr EventLogPtr = {0,0,0,0};

/*
*  ======== LogEvent ========
*
*  This fxn will log an event to the event log
*
*  uint8_t data_type   = log type code for event entry
*  uint32_t rcid       = user credential for action being logged
*  uint8_t data_len    = extra data length
*  uint8_t *extra_data = pointer to extra data
*
*  NOTE: THIS CODE REQUIRES THE AT25SF041 TO BE POPULATED
*
*/
void LogEvent(uint8_t data_type, uint32_t rcid, uint8_t data_len, uint8_t *extra_data)
{
    bool new_sector = FALSE;
    volatile uint8_t log_entry_index = 0;
    uint32_t pageOffset;
    GPFlashRow1Obj row1;

    // Test EventLogPtr for legitimacy - if out of range of event log entirely, reset them
    if (EventLogPtr.lastEntry >= XMEM_SECTOR_2 || EventLogPtr.firstEntry >= XMEM_SECTOR_2)
    {
        InitEventLogPtr();
    }

    // If entry won't fit on this page, we need a new page
    pageOffset = (EventLogPtr.lastEntry >> 8) * XMEM_PAGE_SIZE;
    if( EventLogPtr.lastEntry + data_len + CRC_SIZE + sizeof(struct event_log_entry) >= XMEM_PAGE_SIZE)
    {
        // Set the lastEntry to the start of the next fresh page
        EventLogPtr.lastEntry = pageOffset + XMEM_PAGE_SIZE; // Last page offset plus size of page
    }

    // If new page is in new sector, then we need an erased sector, and we need to increment other pointers
    if (!(EventLogPtr.lastEntry & 0xFFF)) // lastEntry is on an even sector border, new sector required
    {
        new_sector = TRUE;

        // Do we need to wrap the log back around to the start of the event log?
        if ( EventLogPtr.lastEntry >= XMEM_LOG_SIZE)
        {
            EventLogPtr.firstEntry = EventLogPtr.firstEntry + XMEM_4kB_OFFSET; // Set firstEntry to start of next sector of flash
            if ( EventLogPtr.lastUploaded <= EventLogPtr.firstEntry && EventLogPtr.lastUploaded >= EventLogPtr.lastEntry)
            {   // First entry advancing past the last uploaded entry means no entries in the log have been uploaded
                EventLogPtr.lastUploaded = EventLogPtr.firstEntry; // Set last uploaded entry to first entry
                if((lastUploadedOffset + LAST_UPLOADED_WITH_INDEX) > MAX_LAST_UPLOADED_OFFSET) // If entry won't fit...
                {
                    reinitFlashMemory(); // Reinitialize flash so it is ready to go for the next entry
                }
                readFlashPg(FLASH_PAGE(GPFLASH_BASE),(BASE_LAST_UPLOADED_OFFSET + lastUploadedOffset),(uint8_t *)&row1.index,LAST_UPLOADED_WITH_INDEX); // Read the old index/value
                lastUploadedOffset = lastUploadedOffset + LAST_UPLOADED_WITH_INDEX; // Update offset
                row1.index++; // Update index
                row1.lastUploaded = EventLogPtr.lastUploaded; // Update Value
                writeFlashPg(FLASH_PAGE(GPFLASH_BASE),(BASE_LAST_UPLOADED_OFFSET + lastUploadedOffset),(uint8_t *)&row1.index,LAST_UPLOADED_WITH_INDEX); // Write new entry
            }
            EventLogPtr.lastEntry = XMEM_LOG_BASE; // Set lastEntry to zero offset from base of event log
        }
        // Have we previously wrapped around and need to bump the first entry forwards?
        if ( EventLogPtr.lastEntry == EventLogPtr.firstEntry )
        {
            EventLogPtr.firstEntry = EventLogPtr.firstEntry + XMEM_4kB_OFFSET; // Set firstEntry to start of next page of flash
            // Do we need to wrap the firstEntry back to the start?
            if ( EventLogPtr.firstEntry >= XMEM_LOG_SIZE)
            {
                EventLogPtr.firstEntry = XMEM_LOG_BASE;
            }
            if ( EventLogPtr.lastUploaded <= EventLogPtr.firstEntry && EventLogPtr.lastUploaded >= EventLogPtr.lastEntry)
            {   // First entry advancing past the last uploaded entry means no entries in the log have been uploaded
                EventLogPtr.lastUploaded = EventLogPtr.firstEntry; // Set last uploaded entry to first entry
                if((lastUploadedOffset + LAST_UPLOADED_WITH_INDEX) > MAX_LAST_UPLOADED_OFFSET) // If entry won't fit...
                {
                    reinitFlashMemory(); // Reinitialize flash so it is ready to go for the next entry
                }
                readFlashPg(FLASH_PAGE(GPFLASH_BASE),(BASE_LAST_UPLOADED_OFFSET + lastUploadedOffset),(uint8_t *)&row1.index,LAST_UPLOADED_WITH_INDEX); // Read the old index/value
                lastUploadedOffset = lastUploadedOffset + LAST_UPLOADED_WITH_INDEX; // Update offset
                row1.index++; // Update index
                row1.lastUploaded = EventLogPtr.lastUploaded; // Update Value
                writeFlashPg(FLASH_PAGE(GPFLASH_BASE),(BASE_LAST_UPLOADED_OFFSET + lastUploadedOffset),(uint8_t *)&row1.index,LAST_UPLOADED_WITH_INDEX); // Write new entry
            }
        }
    }

    // If we are using a new sector, make sure it is clean
    if ( new_sector )
    {
        xmemWake(); // Wake up the thing and wait a bit
        xmemSendOpCode(XMEM_WRITE_ENABLE, NO_ADDRESS, 0); // Enable external memory  to be written
        xmemSendOpCode(XMEM_BLOCK_ERASE_4K, EventLogPtr.lastEntry, 0); // Clear this page out
        xmemPowerDown(); // Put external memory in Power Down mode
    }

    ++EventLogPtr.lastSeqNumber;                          // Increment the sequence number

    uint32_t temp = 0;                                    // For transporting data to log_entry array

    // Fill log entry data
    log_entry[log_entry_index++] = data_len;              // Write the extra data length
    log_entry[log_entry_index++] = data_type;             // Write new log entry
    temp = EventLogPtr.lastSeqNumber;                     // Get sequence number
    log_entry[log_entry_index++] = (uint8_t) temp;        // LSByte First
    log_entry[log_entry_index++] = (uint8_t) (temp >> 8); // MSByte Last
    temp = getRTC_epoch();                                // Get time
    log_entry[log_entry_index++] = (uint8_t) temp;        // LSByte First
    log_entry[log_entry_index++] = (uint8_t) (temp >> 8);
    log_entry[log_entry_index++] = (uint8_t) (temp >> 16);
    log_entry[log_entry_index++] = (uint8_t) (temp >> 24);// MSByte Last
    log_entry[log_entry_index++] = (uint8_t) rcid;        // RCID - LSByte First
    log_entry[log_entry_index++] = (uint8_t) (rcid >> 8);
    log_entry[log_entry_index++] = (uint8_t) (rcid >> 16);
    log_entry[log_entry_index++] = (uint8_t) (rcid >> 24);// MSByte Last

    // Append Xdata if necessary
    for(temp = 0; temp < data_len; temp++)
    {
        log_entry[log_entry_index++] = *extra_data;       // Add data
        extra_data++;                                     // Point to next byte
    }

    // Run the whole CRC, append it to the entry
    EventCRCInit();
    eventCRC = ComputeCRC16(&log_entry[0], log_entry_index,CRC16_PRESET);
    log_entry[log_entry_index++] = (uint8_t) eventCRC;
    log_entry[log_entry_index++] = (uint8_t) (eventCRC >> 8);

    // Write log entry to Flash
    xmemWake(); // Wake up the thing and wait a bit
    xmemSendOpCode(XMEM_WRITE_ENABLE, NO_ADDRESS, 0); // Enable external memory  to be written
    xmemWrite(EventLogPtr.lastEntry,&log_entry[0],log_entry_index); // Write it to the external memory
    xmemPowerDown(); // Put external memory in Power Down mode

    // Push lastEntry forward
    EventLogPtr.lastEntry += log_entry_index;
}

Disassembly: 
___________________________________________________________________________
Beginning of function:

          LogEvent():
00002abc:   E92D41FF            push.w     {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr}
361           if (EventLogPtr.lastEntry >= XMEM_SECTOR_2 || EventLogPtr.firstEntry >= XMEM_SECTOR_2)
00002ac0:   4CBC                ldr        r4, [pc, #0x2f0]
00002ac2:   4EB9                ldr        r6, [pc, #0x2e4]
356           volatile uint8_t log_entry_index = 0;
00002ac4:   2500                movs       r5, #0
361           if (EventLogPtr.lastEntry >= XMEM_SECTOR_2 || EventLogPtr.firstEntry >= XMEM_SECTOR_2)
00002ac6:   462F                mov        r7, r5
00002ac8:   F8D41006            ldr.w      r1, [r4, #6]
356           volatile uint8_t log_entry_index = 0;
00002acc:   F88D500A            strb.w     r5, [sp, #0xa]
361           if (EventLogPtr.lastEntry >= XMEM_SECTOR_2 || EventLogPtr.firstEntry >= XMEM_SECTOR_2)
00002ad0:   428E                cmp        r6, r1
00002ad2:   D303                blo        $C$L769
00002ad4:   F8D40002            ldr.w      r0, [r4, #2]
00002ad8:   4286                cmp        r6, r0
00002ada:   D203                bhs        $C$L770
363               InitEventLogPtr();
          $C$L769:
00002adc:   F00CF848            bl         #0xeb70
00002ae0:   F8D41006            ldr.w      r1, [r4, #6]
368           if( EventLogPtr.lastEntry + data_len + CRC_SIZE + sizeof(struct event_log_entry) >= XMEM_PAGE_SIZE)
          $C$L770:
00002ae4:   F101000E            add.w      r0, r1, #0xe
00002ae8:   28FF                cmp        r0, #0xff
00002aea:   D905                bls        $C$L771

End of function:

466           xmemWake(); // Wake up the thing and wait a bit
00002d7a:   F00FFC61            bl         #0x12640
467           xmemSendOpCode(XMEM_WRITE_ENABLE, NO_ADDRESS, 0); // Enable external memory  to be written
00002d7e:   2006                movs       r0, #6
00002d80:   F04F31FF            mov.w      r1, #-1
00002d84:   F00BF9E2            bl         #0xe14c
468           xmemWrite(EventLogPtr.lastEntry,&log_entry[0],log_entry_index); // Write it to the external memory
00002d88:   F89D000A            ldrb.w     r0, [sp, #0xa]
00002d8c:   F00BFE48            bl         #0xea20
469           xmemPowerDown(); // Put external memory in Power Down mode
00002d90:   F012FB1E            bl         #0x153d0
472           EventLogPtr.lastEntry += log_entry_index;
00002d94:   F89D100A            ldrb.w     r1, [sp, #0xa]
00002d98:   F8D40006            ldr.w      r0, [r4, #6]
00002d9c:   1840                adds       r0, r0, r1
00002d9e:   F8C40006            str.w      r0, [r4, #6]
00002da2:   9000                str        r0, [sp]
00002da4:   E8BD81FF            pop.w      {r0, r1, r2, r3, r4, r5, r6, r7, r8, pc}

(Registers & Stack Contents:)
Beginning of Function: 
	PC	0x00002ABC	Program Counter [Core]	
	SP	0x20002380	General Purpose Register 13 - Stack Pointer [Core]	
	LR	0x00002141	General Purpose Register 14 - Link Register [Core]	
	xPSR	0x61000000	Stores the status of interrupt enables and critical processor status signals [Core]	
	R0	0x02000000	General Purpose Register 0 [Core]	
	R1	0x20004AE8	General Purpose Register 1 [Core]	
	R2	0x2000D28C	General Purpose Register 2 [Core]	
	R3	0x02000000	General Purpose Register 3 [Core]	
	R4	0x00000064	General Purpose Register 4 [Core]	
	R5	0x00000000	General Purpose Register 5 [Core]	
	R6	0x20004454	General Purpose Register 6 [Core]	
	R7	0x000003E8	General Purpose Register 7 [Core]	
	R8	0x20004D7E	General Purpose Register 8 [Core]	
	R9	0x20001B80	General Purpose Register 9 [Core]	
	R10	0x000186A0	General Purpose Register 10 [Core]	
	R11	0x0000C350	General Purpose Register 11 [Core]	
	R12	0x00020BCC	General Purpose Register 12 [Core]	
	R13	0x20002380	General Purpose Register 13 [Core]	
	R14	0x00002141	General Purpose Register 14 [Core]	
	MSP	0x20013FF8	MSP Register [Core]	
	PSP	0x20002380	PSP Register [Core]	
	DSP	0x20002380	DSP Register [Core]	
	CTRL_FAULT_BASE_PRI	0x02000000	CM4 Special Registers [Core]	

@0x200021E8
FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF
FF	FF	FF	FF	FF	FF	90	00	00	00	0C	4C	00	20	18	4C	00	20	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF
FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF
FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF
FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF
FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	C0	1B	00	20	B1	B4	00	00	58	49	00	20	C0	48	00	20	00	00	00	00	00	00	00	00
90	03	00	00	42	0D	02	00	EB	D0	00	00	00	00	00	00	C0	48	00	20	57	A3	01	00	92	11	0A	00	58	49	00	20	90	03
00	00	00	00	00	00	00	00	00	00	00	00	00	00	E3	82	01	00	00	00	00	00	3F	2A	00	00	00	00	00	00	00	00	00	00
07	00	00	FF	80	4A	5D	05	00	00	00	00	00	00	00	00	00	00	00	00	E8	4A	00	20	8C	D2	00	20	80	4A	5D	05	5B	5C
67	05	00	00	00	00	00	00	02	00	F5	7D	01	00	30	23	00	20	E3	82	01	00	94	1B	00	20	94	1B	00	20	C0	1B	00	20
00	00	00	00	01	C3	00	20	00	00	00	02	00	00	00	00	07	00	00	FF	90	00	00	00	39	00	00	00	94	1B	00	20	64	00
00	00	00	00	00	00	54	44	00	20	E8	03	00	00	7E	4D	00	20	80	1B	00	20	A0	86	01	00	50	C3	00	00	F1	20	00	00
05	07	19	F9	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00
00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00
00	00	00	00	80	4A	5D	05	40	1F	00	00	10	27	00	00	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF
FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	7D	FA	00	00	00	00	00	00	00	00	00	00	35	1E	00	00	7D	FA	00	00
59	93	01	00	BE	BE	BE	BE

End of Function:
	PC	0x00002D94	Program Counter [Core]	
	SP	0x20002358	General Purpose Register 13 - Stack Pointer [Core]	
	LR	0x00009DA5	General Purpose Register 14 - Link Register [Core]	
	xPSR	0x21000000	Stores the status of interrupt enables and critical processor status signals [Core]	
	R0	0x00000001	General Purpose Register 0 [Core]	
	R1	0x00000390	General Purpose Register 1 [Core]	
	R2	0x00000000	General Purpose Register 2 [Core]	
	R3	0x00000000	General Purpose Register 3 [Core]	
	R4	0xFFFFFFFF	General Purpose Register 4 [Core]	
	R5	0xFFFFFFFF	General Purpose Register 5 [Core]	
	R6	0xFFFFFFFF	General Purpose Register 6 [Core]	
	R7	0x0000FFFF	General Purpose Register 7 [Core]	
	R8	0x20004D7C	General Purpose Register 8 [Core]	
	R9	0x20001B80	General Purpose Register 9 [Core]	
	R10	0x000186A0	General Purpose Register 10 [Core]	
	R11	0x0000C350	General Purpose Register 11 [Core]	
	R12	0x20002330	General Purpose Register 12 [Core]	
	R13	0x20002358	General Purpose Register 13 [Core]	
	R14	0x00009DA5	General Purpose Register 14 [Core]	
	MSP	0x20013FF8	MSP Register [Core]	
	PSP	0x20002358	PSP Register [Core]	
	DSP	0x20002358	DSP Register [Core]	
	CTRL_FAULT_BASE_PRI	0x02000000	CM4 Special Registers [Core]	

@0x200021E8
FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	00	00	00	00	00	00	00	10	00	00	00	00	FF	FF	FF	FF	90	00
00	00	0C	4C	00	20	18	4C	00	20	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF
FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF
FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	C0	1B	00	20	B1	B4	00	00	58	49	00	20	9C	DE	00	20	00	00	00	00
F0	0B	02	00	00	00	00	00	20	00	00	00	EB	D0	00	00	00	00	00	00	9C	DE	00	20	FD	D7	00	00	35	1E	00	00	58	49
00	20	90	03	00	00	00	00	00	00	10	00	C2	04	00	00	00	00	E3	82	01	00	00	00	00	00	17	38	00	00	00	00	00	00
FF	FF	FF	FF	00	00	00	00	00	00	00	00	00	E0	00	20	2D	99	01	00	1B	80	00	00	6F	BB	00	00	00	00	00	00	A3	08
07	00	00	E0	00	20	39	BB	00	00	F0	0B	02	00	E8	0B	02	00	48	0D	02	00	EC	0B	02	00	00	E0	00	20	A5	9D	00	00
00	00	00	00	00	00	00	00	30	23	00	20	C4	DF	00	20	40	DE	00	20	FF	FF	00	00	7C	4D	00	20	80	1B	00	20	A0	86
01	00	3F	19	01	00	00	DE	00	20	FF	FF	FF	FF	FF	FF	FF	FF	0D	54	01	00	00	BE	BE	BE	48	23	00	20	02	01	00	20
44	23	00	20	48	23	00	20	B9	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	95	2D	00	00	01	00	10	00	00	4A
00	20	57	1F	0E	20	00	00	00	02	64	00	00	00	00	00	00	00	54	44	00	20	E8	03	00	00	7E	4D	00	20	41	21	00	00
05	07	19	F9	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00
00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00	00
00	00	00	00	80	4A	5D	05	40	1F	00	00	10	27	00	00	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF
FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	FF	7D	FA	00	00	00	00	00	00	00	00	00	00	35	1E	00	00	7D	FA	00	00
59	93	01	00	BE	BE	BE	BE

  • Just to add to the thread, as usual I find the most telling examples of similar issues after posting:
    e2e.ti.com/.../458078
    e2e.ti.com/.../1662725

    I'm not sure if this is the same path - but this is what I will begin to investigate, in which case this post may need to be moved over to the BLE forum.

    I should note, similar to the prevous issues, I am also using two iterations of the SPI module and only seeing this issue with the second SPI (both are setup as master configurations with sensors/flash on the bus). I am also running the simplelink_cc13x2_26x2_sdk_2_40_00_81 BLE5 simple peripheral as the base for our TI-RTOS, but all BLE functionality is commented out currently.
  • Following one of the attached threads and getting the IMPRECISERR to become a PRECISERR, the below is the output. I'm not sure what I gained from that exercise, but if it means anything to anyone in the know, the BFAR was 0x5... which is in the middle of the reset vector, which makes even less sense than before.

    _busFault: PRECISERR: Immediate Bus Fault, exact addr known, address: 00000005
    Exception occurred in background thread at PC = 0x00002dce.
    Core 0: Exception occurred in ThreadType_Task.
    Task name: {unknown-instance-name}, handle: 0x20001bc0.
    Task stack base: 0x20001c10.
    Task stack size: 0x800.
    R0 = 0x1d000146 R8 = 0x20004a78
    R1 = 0x0000000e R9 = 0x20001b80
    R2 = 0x00000000 R10 = 0x000186a0
    R3 = 0x00000000 R11 = 0x0000c350
    R4 = 0xffffffff R12 = 0x20002330
    R5 = 0xffffffff SP(R13) = 0x20002358
    R6 = 0xffffffff LR(R14) = 0x00009dd5
    R7 = 0x0000ffff PC(R15) = 0x00002dce
    PSR = 0x01000000
    ICSR = 0x00400803
    MMFSR = 0x00
    BFSR = 0x82
    UFSR = 0x0000
    HFSR = 0x40000000
    DFSR = 0x00000001
    MMAR = 0x00000005
    BFAR = 0x00000005
    AFSR = 0x00000000
    Terminating execution...
  • From the post you linked to:
    "A CPU exception can happen due to a number of reasons: Bus Faults, stack overflows, memory corruption ++. There is a guide in the BLE Software developers guide (SWRU393) chapter 9.8 which might be useful to find the reason for the exception.

    The exceptions often show up as an imprecise error due to the CM3 write buffering which causes the error occur at a later time then when the write was executed so the CPU gets confused.

    Suggestion on what to look for in addition to checking what you already have done:

    - Check for bus faults using the guide above (Chapter 9.8)
    - Check for memory heap overflows (see chapter 9.6 in guide above)"

    An online version of the debugging guide could be found here: dev.ti.com/.../ble-index.html

    Did you check the items highlighted above? Did you also check that your task stack is large enough?

    I have also experienced that a NULL pointer somewhere in the code could cause a IMPRECISERR error. Check all functions calls that they don't have a NULL pointer in the call.
  • TER, 

    Thanks for the response - I was beating my head on the desk all week for this so I had to step away for the weekend and gain clear eyes to hopefully spot something different.

    I will consult the guide to see if I can ascertain if and where bus faults are occurring, but I think our memory allocation is sufficient - we are using the debug configuration with the static 30kB heap allocation, so I'm pretty confident that should not be overflowing.

    TER said:

    Did you also check that your task stack is large enough?

    Our stack allocation is 2kB for our main task, and this seems to top out around only 512B when we are at the end of the event log write command.

    TER said:

    I have also experienced that a NULL pointer somewhere in the code could cause a IMPRECISERR error. Check all functions calls that they don't have a NULL pointer in the call.

    I will look into this for sure - we are only sending a NULL pointer because there is no data to be sent, but I can just point at a dummy variable or something to get around this.

    I'll continue to work with the debug guide and report back with findings or any questions I have along the way.

    Regards,
    Tyler Witt

  • All - I have found a solution, and it's a bit obvious in hindsight.

    In my SPI driver I was allocating dummy buffers for my receive-side buffer for write commands where I didn't care about the received data. This data length I arbitrarily wrote out as 2 bytes, because, well, I didn't care about any of the data and didn't want to allocate memory unnecessarily.

    Well if you are writing 18 bytes on the SPI bus, the SPI driver is going to write 18 bytes to the memory location you specify for the receive-side buffer, regardless of if you have allocated enough space to catch that data. 

    So - the data (lots of FF's likely) was overwriting up the stack to some of the bytes within what I was wanting to pop back into registers on completion of the event log write command. This is what caused the imprecise bus fault error and an attempted write to addres 0x5.

    I've tested multiple times by shortening and lengthening this buffer and adding in the transmit length fixes my issue.