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.

CC1310 Cortex-M, TI-RTOS, memcpy crash

Other Parts Discussed in Thread: CC2650

I'm having some odd behavior here.  My program includes a library (which I'm writing/debugging) which processes incoming NMEA data from a GPS module.  Part of it involves copying the Talker and Message ID into a couple char arrays inside a struct which will be returned to the caller.  During one of these memcpy() operations, the CPU jumps to the Hwi exception handler and the RTOS crashes.

Software versions:

TI-RTOS 2.20.0.06 for CC13xx

TI ARM compiler v15.12.3.LTS

Here's the C code around the portion of the crash:

	outs = &parsedSentencePool[i];

	if (cinsent[0] != '$') {
		mtkgps_parse_errno = NMEA_PARSE_ERR_INVALID_STARTCHAR;
		return NULL;
	}

	if (cinsent[slen-1] == '\n') {
		slen--;
	}
	if (cinsent[slen-1] == '\r') {
		slen--;
	}

	if (!strncmp(cinsent+1, "GP", 2)) {
		memcpy(outs->Talker, cinsent+1, 2);
		outs->Talker[2] = '\0';
		pst = 3;  // First byte after "$GP"
	}
	if (!strncmp(cinsent+1, "PMTK", 4)) {
		System_printf("Matched\n"); System_flush();
		memcpy(outs->Talker, cinsent+1, 4);
		outs->Talker[4] = '\0';
		System_printf("Copy complete\n"); System_flush();
		pst = 5;  // First byte after "$PMTK"
	}

It is that memcpy(outs->Talker, cinsent+1, 4) which crashes.  Disassembly of this code:

It looks as if the memcpy() was optimized into a 32-bit load & store operation, which is pretty clever on the compiler's part.  Doing assembly step-into, we see R1 eventually becomes 0x2000128D (0x2000128C is the start of the nmea buffer, which contains the $, but we want the next 4 chars after that):

Note R1 is now 0x2000128D.  Here's the memory at that location:

Looks correct.  That's the NMEA message for MTK3339 GPS's indicating that it has powered on.

But when I step one more, the "ldr r1, [r1]" crashes:

Actual crash (just hit 'run' after this):

I am not an assembly language expert, so I don't know why that happened or if it's normal behavior.  I have seen references to the LDR instruction having restrictions that the Rt, Rn registers must differ but it indicated under one of the addressing schemes that doesn't appear to be present here.  Any expert advice?  I can use strncpy which I have validated does work, I'm just puzzled why memcpy() doesn't work here.

  • Eric Brundick said:
    It looks as if the memcpy() was optimized into a 32-bit load & store operation

    Yes.  The compiler generated this on purpose, with full knowledge that the addresses may not be aligned on 32-bit boundaries at run time.  It has worked this way for a long time.  So it is unlikely the compiler alone is the cause of the problem.  Something else must be contributing to this crash.  

    One possibility to consider is that this device has somehow become configured to not support unaligned access with the LDR instruction.  Another possibility is that the HW interface to this range of memory does not supported unaligned access.  Both of these are outside the expertise of us compiler experts.  I recommend you start a new thread in the Sub 1-Ghz device forum, or if you prefer, I can move this thread into that forum.

    Yet another possibility is to just turn off the compiler optimization which generates the unaligned access.  You can do that with the build option --unaligned_access=off.  

    Thanks and regards,

    -George

  • Eric Brundick said:
    I am not an assembly language expert, so I don't know why that happened or if it's normal behavior.

    On the exception trace which appeared in the CIO console, the UNALIGNED bit is set in the FSR register, which means the exception occurred on a trap to an unaligned memory access.

    On Cortex-M3 devices, TI-RTOS has a control for if the process traps on an unaligned access, or performs the unaligned access. On a new project the default is that "Trap on all unaligned accesses" is not ticked, which means the processor should perform the unaligned access:

    With a Cortex-M3 based CC2650 a test program was created to perform an unaligned access via memcpy() similar to your program. With the TI-RTOS default of "Trap on all unaligned accesses" not ticked then the program successfully performed an unaligned ldr from the RAM address 0x20004FE1:

    When the TI-RTOS configuration was changed to tick the "Trap on all unaligned accesses" option then the program generated an UNALIGNED exception.

    Therefore, can you check the TI-RTOS configuration to see if the "Trap on all unaligned accesses" option is ticked.

  • Thanks, that was it, I found that setting and turned it off... must've turned it on earlier without realizing what it was for.  I had tinkered with the RTOS cfg at one point since I believe the default project had ROM enabled (and CIO didn't work).