Hard faults using sprintf with float numbers

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

I am heavily using float32 on SAME70 MCU and now experience hard faults when printing floats to a buffer. Running this (simplified) piece of code for a while the application crashes after some minutes if USE_FLOAT is set to 1. If USE_FLOAT is 0 then the same application runs for hours without troubles. Assert() never happens.

My first guess was that the sprintf() runs out of memory but the odd address in "lr  = 0x00444591" which does not cover any assembly code address makes me wonder. Am I wrong ?

Any idea in which direction I should search for the problem ? Memory allocation / stack ? A bug in sprintf() ? How can I dig deeper ?

BTW the app is using FreeRTOS and lwip.

Thanks,

Joe

#define TX_REQ_BUFLEN 			1024
static uint8_t tx_buf[TX_REQ_BUFLEN];

	uint32_t length = 0;
	
	//send entire selected buffer
	uint8_t bChunks = ADC_HV_VOLT_BUFLEN;		

	for (uint32_t i = 0; i < bChunks; ++i) {
#if USE_FLOAT==1
		length += sprintf((char *)tx_buf + length, "%.3e,", abVoltData[bVoltDataRdBufSelect][i]);
#else
		length += sprintf((char *)tx_buf + length, "%ld,", (int32_t)abVoltData[bVoltDataRdBufSelect][i]);
#endif
	}
	
	
	ASSERT(length < TX_REQ_BUFLEN);

  This is what the hard fault says:

SCB->HFSR = 0x40000000
Forced Hard Fault
SCB->CFSR = 0x00008200
Bus fault:
r0  = 0x32393800
r1  = 0x00000000
r2  = 0x00000018
r3  = 0x204579a0
r12 = 0xe06719ae
lr  = 0x00444591
pc  = 0x00444fd0
psr = 0x21000000

The assembly output:


00444fa6 <_Balloc>:
_Balloc():
  444fa6:	b570      	push	{r4, r5, r6, lr}
  444fa8:	6a45      	ldr	r5, [r0, #36]	; 0x24
  444faa:	4604      	mov	r4, r0
  444fac:	460e      	mov	r6, r1
  444fae:	b93d      	cbnz	r5, 444fc0 <_Balloc+0x1a>
  444fb0:	2010      	movs	r0, #16
  444fb2:	f7fd feb7 	bl	442d24 <malloc>
  444fb6:	6260      	str	r0, [r4, #36]	; 0x24
  444fb8:	6045      	str	r5, [r0, #4]
  444fba:	6085      	str	r5, [r0, #8]
  444fbc:	6005      	str	r5, [r0, #0]
  444fbe:	60c5      	str	r5, [r0, #12]
  444fc0:	6a65      	ldr	r5, [r4, #36]	; 0x24
  444fc2:	68eb      	ldr	r3, [r5, #12]
  444fc4:	b143      	cbz	r3, 444fd8 <_Balloc+0x32>
  444fc6:	6a63      	ldr	r3, [r4, #36]	; 0x24
  444fc8:	68db      	ldr	r3, [r3, #12]
  444fca:	f853 0026 	ldr.w	r0, [r3, r6, lsl #2]
  444fce:	b178      	cbz	r0, 444ff0 <_Balloc+0x4a>
  444fd0:	6802      	ldr	r2, [r0, #0]
  444fd2:	f843 2026 	str.w	r2, [r3, r6, lsl #2]
  444fd6:	e017      	b.n	445008 <_Balloc+0x62>


  44458c:	f000 fd0b 	bl	444fa6 <_Balloc>
  444590:	f8da 3024 	ldr.w	r3, [sl, #36]	; 0x24
  444594:	6020      	str	r0, [r4, #0]
  444596:	681b      	ldr	r3, [r3, #0]
  444598:	9306      	str	r3, [sp, #24]
  44459a:	9b05      	ldr	r3, [sp, #20]
  44459c:	2b0e      	cmp	r3, #14
  44459e:	f200 815d 	bhi.w	44485c <_dtoa_r+0x5b4>
  4445a2:	2d00      	cmp	r5, #0
  4445a4:	f000 815a 	beq.w	44485c <_dtoa_r+0x5b4>
  4445a8:	e9dd 3402 	ldrd	r3, r4, [sp, #8]
  4445ac:	f1bb 0f00 	cmp.w	fp, #0
  4445b0:	e9cd 340e 	strd	r3, r4, [sp, #56]	; 0x38
  4445b4:	dd31      	ble.n	44461a <_dtoa_r+0x372>
  4445b6:	4aa0      	ldr	r2, [pc, #640]	; (444838 <_dtoa_r+0x590>)
  4445b8:	f00b 030f 	and.w	r3, fp, #15
  4445bc:	eb02 03c3 	add.w	r3, r2, r3, lsl #3
  4445c0:	e9d3 3400 	ldrd	r3, r4, [r3]
  4445c4:	ea4f 152b 	mov.w	r5, fp, asr #4
  4445c8:	06e8      	lsls	r0, r5, #27
  4445ca:	e9cd 3408 	strd	r3, r4, [sp, #32]
  4445ce:	d50c      	bpl.n	4445ea <_dtoa_r+0x342>

The stack/heap memory allocation:

.stack          0x20423370     0x2000 load address 0x00575360
                0x20423370                . = ALIGN (0x8)
                0x20423370                _sstack = .
                0x20425370                . = (. + STACK_SIZE)
 *fill*         0x20423370     0x2000 
                0x20425370                . = ALIGN (0x8)
                0x20425370                _estack = .

.heap           0x20425370    0x38000 load address 0x00577360
                0x20425370                . = ALIGN (0x8)
                0x20425370                _sheap = .
                0x2045d370                . = (. + HEAP_SIZE)
 *fill*         0x20425370    0x38000 
                0x2045d370                . = ALIGN (0x8)
                0x2045d370                _eheap = .
                0x2045d370                . = ALIGN (0x4)
                0x2045d370                _end = .
                0x2045ffff                _ram_end_ = ((ORIGIN (ram) + LENGTH (ram)) - 0x1)

 

SAME newbie

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Reading this post

https://sourceforge.net/p/freertos/discussion/382005/thread/98fa4372/

I guess that my problem has something to do with dynamic memory allocation. As far as I understand the newlib provided by the GNU toolchain should use the memory allocation provided by the ASF which in my case was installed by Atmel Studio installation (which has been updated in the past several times). In my opinion this should be _sbrk() in \ASF\sam\utils\syscalls\gcc\syscalls.csyscalls.c (which I had to adapt to work with the provided linker script as described in a previous post).

To my surprise the _sbrk() is called by malloc() but neither when using printf() nor sprintf(). So which memory is meant to be allocated by _Balloc() which seems to cause the hard fault shown above ??

 

I guess that I have to step thru the newlib code... Has anybody succeeded in adding the newlib to the project that it can be debugged in Atmel Studio ? Where do I find a suitable newlib source ? Do I need a patched version (by ARM, Atmel, ... ?) or ... ?

SAME newbie

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Me again. I recompiled the newlib stuff but couldn't link the library. I see that sprintf() is allocating dynamic memory using the provided FreeRTOS malloc() functions which should make the sprintf() thread safe in my understanding, ..., nevertheless the hard fault occurs after ca. 1-10 minutes and I could not get rid of this behaviour.

Finally I succeeded (thanks for the PM) by controlling sprintf() access from multiple tasks using a semaphore.

BTW: found this thread here, maybe this is related somehow to my problem.

http://community.atmel.com/forum/how-printf-double-cortex-m-7-0

Thanks,

Joe

SAME newbie

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Joe, usually it's enough to provide a priority mutex in malloc_lock and malloc_unlock since default sprintf uses heap allocation. I'm now seeing similar issues with printf causing Bus/Mem faults, still trying to find the problem. Based on one of your previous posts, I moved to FreeRTOS 9.0.0, noticed in Sourceforge there's a new port.c and portmacro.h for M7 r0p1 core which adds more memory barriers to interrupts disabling. It doesn't seem to fix this issue though.