cancel
Showing results for 
Search instead for 
Did you mean: 

Why are calls to strcat() not actually calling strcat()? (and why do I sometimes get a Hard Fault)

MButsch
Associate III

I am using STM32CubeIDE v1.6.1 and am seeing some strangeness.

When I call strcat(), I get a hardfault if the end of the string (where the nul is) being catted to is at an odd address?

Here is code from the .list file:

		  char s1[20];
		  strcpy(s1, "--");
 800ab50:	f107 030c 	add.w	r3, r7, #12
 800ab54:	4a65      	ldr	r2, [pc, #404]	; (800acec <sd_cmdproc_process_packet+0x374>)
 800ab56:	6812      	ldr	r2, [r2, #0]
 800ab58:	4611      	mov	r1, r2
 800ab5a:	8019      	strh	r1, [r3, #0]
 800ab5c:	3302      	adds	r3, #2
 800ab5e:	0c12      	lsrs	r2, r2, #16
 800ab60:	701a      	strb	r2, [r3, #0]
		  strcat(s1, "1");
 800ab62:	f107 030c 	add.w	r3, r7, #12
 800ab66:	4618      	mov	r0, r3
 800ab68:	f7f5 fbc4 	bl	80002f4 <strlen>
 800ab6c:	4603      	mov	r3, r0
 800ab6e:	461a      	mov	r2, r3
 800ab70:	f107 030c 	add.w	r3, r7, #12
 800ab74:	4413      	add	r3, r2
 800ab76:	495e      	ldr	r1, [pc, #376]	; (800acf0 <sd_cmdproc_process_packet+0x378>)
 800ab78:	461a      	mov	r2, r3
 800ab7a:	460b      	mov	r3, r1
 800ab7c:	881b      	ldrh	r3, [r3, #0]
 800ab7e:	8013      	strh	r3, [r2, #0]
		  strcat(s1, "2");
 800ab80:	f107 030c 	add.w	r3, r7, #12
 800ab84:	4618      	mov	r0, r3
 800ab86:	f7f5 fbb5 	bl	80002f4 <strlen>
 800ab8a:	4603      	mov	r3, r0
 800ab8c:	461a      	mov	r2, r3
 800ab8e:	f107 030c 	add.w	r3, r7, #12
 800ab92:	4413      	add	r3, r2
 800ab94:	4957      	ldr	r1, [pc, #348]	; (800acf4 <sd_cmdproc_process_packet+0x37c>)
 800ab96:	461a      	mov	r2, r3
 800ab98:	460b      	mov	r3, r1
 800ab9a:	881b      	ldrh	r3, [r3, #0]
 800ab9c:	8013      	strh	r3, [r2, #0]
 800ab9e:	e1c4      	b.n	800af2a <sd_cmdproc_process_packet+0x5b2>
  }

the strcat of "1" works, but the strcat of "2" hard faults. I suspect it isalignment error with the "strh".

It is also curious that the calls to strcat() (and strcpy()) do not call the actual functions.

I appologize if I have missed something obvious.

Thanks,

mark

13 REPLIES 13
MButsch
Associate III

OK, so I have resolved it.

In tracking down the Hard Fault, the Usage Fault Status Regsiter indicated it was UNALIGNED.

So I disabled trapping of unaligned accesses by setting the UNALIGN_TRP bit in the CCR to 0. Now it does not Hard Fault.

However, WHY does it generate code like this? And using STM32CubeIDE, is there a way to prevent it from generating code like this?

AFAIK SCB_CCR.UNALIGN_TRP is 0 by default after reset for Cortex-M7. So you must have enabled it in your code - startup code, library, whatever.

That's also why compilers work with the default assumption that unaligned accesses are mostly OK for the Cortex-M7 - and, IMO, having unaligned accesses is a major relief in most of the cases.

If you insist on having strictly aligned code, you can try gcc's -mno-unaligned-access switch.

JW

MButsch
Associate III

thank you for the discussion.

This is my first time using an STM32F7 and the first time I have had to delve this deep in an STM32 part. Lots to learn.

My project was started by selecting the  STM32F769I-DISCO board from the new project selector and having it generate the .ioc file and code.

If the generated code is setting the SCB_CCR.UNALIGN_TRP bit, I have been unable to find where. I searched the project and didn't find anything.

I set a breakpoint at "Reset_Handler:" in startup_stm32F769nihx.s (thinking that this is where execution will start and the SCB_CCR.UNALIGN_TRP is already set there (inspecting in the SFR tab). So I am not sure how/where that bit gets set.

If the default behavior of STM32CubeIDE is to configure checking for aligned accesses, then why does it generate code that will fault? Does anyone know WHY it generates code like this?

Thanks,

Mark

The "compiler" doesn't know what address any given piece of data or code will be assigned, the "linker" often has more control of that, although it's only party to the details given to it.

In the general case unaligned 16 and 32-bit access is safe. The compiler/optimizer tend to assume this as it yields faster/smaller code.

Might want to look at code generation settings for the Cortex-M0 as that is very unforgiving.

Most of the Cortex-Mx give me headaches with unaligned (byte aligned) data structures in files or serial streams, 64-bit word (doubles) being a particular issue. Although this is still less tedious than the old ARM7 and ARM9, and cases where people wanted to port x86 C code

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..