AnsweredAssumed Answered

hard fault caused by op near SRAM_L and SRAM_U boundary?

Question asked by Frank Zhao on Mar 3, 2014
Latest reply on Mar 19, 2014 by Norm Davies

I am using a K10DX128, there is 16 KB of RAM available total, according to the reference manual, the SRAM is split into SRAM_L and SRAM_U

 

But my linker script simply states that

 

RAM  (rwx) : ORIGIN = 0x1FFFE000, LENGTH = 16K"

 

I have a bit of code that will malloc a piece of memory, by sheer coincidence, this bit of memory will occupy a bit of both regions. The memory contains an array of a struct, actually a list of files

 

This is a sample of my debug output as I am using memcpy to populate the file's information

 

file 1960 memcpy 0 addr 0x1FFFFCC0...done
file 1970 memcpy 1 addr 0x1FFFFCE6...done
file 1980 memcpy 2 addr 0x1FFFFD0C...done
file misc2 memcpy 3 addr 0x1FFFFD32...done
file 1990 memcpy 4 addr 0x1FFFFD58...done
file ABC_YA~1 memcpy 5 addr 0x1FFFFD7E...done
file AMBSTR~1 memcpy 6 addr 0x1FFFFDA4...done
file amoeba memcpy 7 addr 0x1FFFFDCA...done
file commod64 memcpy 8 addr 0x1FFFFDF0...done
file CUBES_~1 memcpy 9 addr 0x1FFFFE16...done
file EXPRIBB memcpy 10 addr 0x1FFFFE3C...done
file finlshot memcpy 11 addr 0x1FFFFE62...done
file GRAF_4KS memcpy 12 addr 0x1FFFFE88...done
file haduken memcpy 13 addr 0x1FFFFEAE...done
file intro memcpy 14 addr 0x1FFFFED4...done
file kickstar memcpy 15 addr 0x1FFFFEFA...done
file KS_HAL~1 memcpy 16 addr 0x1FFFFF20...done
file KS_TOGET memcpy 17 addr 0x1FFFFF46...done
file KSFINA~1 memcpy 18 addr 0x1FFFFF6C...done
file KSHELLOS memcpy 19 addr 0x1FFFFF92...done
file KSNINT memcpy 20 addr 0x1FFFFFB8...done
file lavapixe memcpy 21 addr 0x1FFFFFDE...

 Exception Handler, source: 1
r0: 0x00000000, r1: 0x1FFFFA80, r2: 0x20000002, r3: 0x00000000, r12: 0x20001D8F
LR: 0x0000482F, PC: 0x0000484C, PSR: 0x61000000, 

 

notice how the memcpy failed for 0x1FFFFFDE , near the edge of the boundary.

 

then, I replaced memcpy with my own version, a trick to get my compiler to force 8 bit writes instead of 32 bit writes, it then works fine

 

_PTR memcpy_safe(void* dest, void* src, int cnt)
{
     int start = (int)dest;
     int end = start + cnt;
     if (start <= 0x1FFFFFFF && end >= 0x20000000) // if memory lies over SRAM_L and SRAM_U boundary
     {
          volatile uint8_t useless = 0; // force 8 bit copy instead of optimized 32 bit copy
          volatile uint8_t c;
          volatile int i = 0;
          volatile uint8_t* src_p = (uint8_t*)src;
          volatile uint8_t* dest_p = (uint8_t*)dest;
          for (i = 0; i < cnt && useless == 0; i++) {
               c = src_p[i];
               dest_p[i] = c;
          }
     }
     else
     {
          return memcpy(dest, src, cnt);
     }
}

 

it works fine

 

file KSFINA~1 memcpy 18 addr 0x1FFFFF6C...done
file KSHELLOS memcpy 19 addr 0x1FFFFF92...done
file KSNINT memcpy 20 addr 0x1FFFFFB8...done
file lavapixe memcpy 21 addr 0x1FFFFFDE...done
file leon memcpy 22 addr 0x20000004...done
file lilypad memcpy 23 addr 0x2000002A...done
file LOGOAN01 memcpy 24 addr 0x20000050...done
file LOGOAN02 memcpy 25 addr 0x20000076...done

 

so I then run this bit of code

 

volatile uint32_t* foo;
foo = (volatile uint32_t*)0x1FFFFFFF; // right at the boundary between SRAM_L and SRAM_U
*foo = 0x12345678; // perform a 32 bit write

 

bam! instant crash hard fault. this almost confirms my suspicion that the crash is caused by the boundary between SRAM_L and SRAM_U.

 

volatile uint32_t* foo;
foo = (volatile uint32_t*)(0x1FFFFFFF - 4);
*foo = 0x12345678;

 

this does not crash/hardfault

 

so my question is: is cross-boundary operations like this disallowed on K10 and K20 hardware?

how can I make sure that the compiler is aware of this? I am using GCC 4.7.2

Outcomes