2021-09-17 10:32 AM
Greetings!
I've got custom hardware running on an ST32H7. I'm trying to load an image from the sdcard into off-chip RAM for execution.
RAM's at 0xC0000000, and I think I've set the MPU configuration correctly:
// Region 2 is the external RAM
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.BaseAddress = 0xC0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;
MPU_InitStruct.SubRegionDisable = 0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
I'm building the RAM image and linking to 0xC0000000, as this output from readelf confirms:
There are 41 section headers, starting at offset 0x3c2ca8:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .bss NOBITS 24000000 0000c0 01e334 00 WA 0 0 32
[ 2] .tbss NOBITS 2401e334 0000b4 000004 00 WAT 0 0 4
[ 3] .heap NOBITS 2401e338 0000b4 027100 00 WA 0 0 1
[ 4] .stack NOBITS 24045438 0000b4 000800 00 WA 0 0 1
[ 5] .stack_process PROGBITS 24045c38 0297a0 000000 00 W 0 0 1
[ 6] .vectors PROGBITS c0000000 0000b8 000298 00 AX 0 0 1
[ 7] .rel.vectors REL 00000000 31d310 0004b0 08 I 38 6 4
[ 8] .init PROGBITS c0000298 000350 0002d8 00 AX 0 0 4
[ 9] .rel.init REL 00000000 31d7c0 000120 08 I 38 8 4
[10] .text PROGBITS c0000570 000628 027cf8 00 WAX 0 0 8
[11] .rel.text REL 00000000 31d8e0 006f40 08 I 38 10 4
[12] .ctors INIT_ARRAY c0028268 028320 00002c 04 WA 0 0 4
[13] .rel.ctors REL 00000000 324820 000058 08 I 38 12 4
[14] .data PROGBITS c0028294 02834c 0000a4 00 WA 0 0 4
[15] .rel.data REL 00000000 324878 000058 08 I 38 14 4
[16] .rodata PROGBITS c0028338 0283f0 0013b0 00 A 0 0 8
[17] .rel.rodata REL 00000000 3248d0 000068 08 I 38 16 4
[18] .ARM.attributes ARM_ATTRIBUTES 00000000 0297a0 000033 00 0 0 1
[19] .comment PROGBITS 00000000 0297d3 000025 01 MS 0 0 1
[20] .debug_line PROGBITS 00000000 0297f8 049626 00 0 0 1
[21] .rel.debug_line REL 00000000 324938 003b48 08 I 38 20 4
[22] .debug_info PROGBITS 00000000 072e1e 06777b 00 0 0 1
[23] .rel.debug_info REL 00000000 328480 039c20 08 I 38 22 4
[24] .debug_abbrev PROGBITS 00000000 0da599 00c9e0 00 0 0 1
[25] .debug_aranges PROGBITS 00000000 0e6f80 0042f8 00 0 0 8
[26] .rel.debug_a[...] REL 00000000 3620a0 003dd8 08 I 38 25 4
[27] .debug_str PROGBITS 00000000 0eb278 19d5ce 01 MS 0 0 1
[28] .debug_ranges PROGBITS 00000000 288848 003f18 00 0 0 8
[29] .rel.debug_ranges REL 00000000 365e78 007840 08 I 38 28 4
[30] .debug_frame PROGBITS 00000000 28c760 010a94 00 0 0 4
[31] .rel.debug_frame REL 00000000 36d6b8 007580 08 I 38 30 4
[32] .debug_pubnames PROGBITS 00000000 29d1f4 016260 00 0 0 1
[33] .rel.debug_p[...] REL 00000000 374c38 000280 08 I 38 32 4
[34] .debug_pubtypes PROGBITS 00000000 2b3454 00d424 00 0 0 1
[35] .rel.debug_p[...] REL 00000000 374eb8 000280 08 I 38 34 4
[36] .debug_macro PROGBITS 00000000 2c0878 04801c 00 0 0 1
[37] .rel.debug_macro REL 00000000 375138 04da28 08 I 38 36 4
[38] .symtab SYMTAB 00000000 308894 00cc40 10 39 2059 4
[39] .strtab STRTAB 00000000 3154d4 007e3a 00 0 0 1
[40] .shstrtab STRTAB 00000000 3c2b60 000145 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (purecode), p (processor specific)
When I attempt to invoke the loaded memory location, the CPU hangs; it's not faulting. Here's the startup code I'm using. I cribbed this from the ExtMem_Boot sample on the web.
const UInt32 kSegmentStart = 0xC0000000;
#define IMAGE_FILE "IMAGE.BIN"
#define TEST_FILE "test.txt"
typedef void (*pFunction)(void);
pFunction JumpToApplication;
void LoadApplicationImage()
{
g_sdMgr.Mount();
char *buffer=(char*)(kSegmentStart);
uint32_t readCount = 0;
readCount = g_sdMgr.ReadFile(IMAGE_FILE, buffer, 0x2FFFF);
Logger::Print("Read %d bytes", readCount);
if (0) for(int i = 0; i < 8; i++)
{
Logger::Print("%02x%02x%02x%02x %02x%02x%02x%02x", buffer[i * 8 + 0], buffer[i * 8 + 1], buffer[i * 8 + 2], buffer[i * 8 + 3], buffer[i * 8 + 4], buffer[i * 8 + 5], buffer[i * 8 + 6], buffer[i * 8 + 7]);
}
JumpToApplication = (pFunction) (*(__IO uint32_t*) (kSegmentStart + 4));
__set_MSP(*(__IO uint32_t*) kSegmentStart);
JumpToApplication();
}
It's hanging on the call to JumpToApplication(); it's not hitting any of the fault handlers, which leads me to believe that I'm incorrectly clobbering the interrupt vectors --- could my application's link map be wrong? What else may I be missing to debug this?
Thanks in advance!
Any input as to what to check would
2021-09-17 11:15 AM
From C/GCC I'd probably skip the set_MSP, and just load the SP in ResetHandler on the app side.
Also with SDRAM, I'd entirely skip the clock and PLL set up the second time, ditto any set up of SDRAM or QSPI, just going to cause headaches.
Watch what SystemInit() is doing, have SCB->VTOR set to the base of the SDRAM Image, ideally using the linker symbols, not defines.
Skip SystemClock_Config() core side stuff, just focus on the peripheral clocks, or things the loader didn't bring up.
Checksum or CRC the image to confirm it matches PC side expectations for content.
Watch for SysTick and other interrupts with RAM based structures, instances, dependencies as these will all be wrong for the app.
Step into the transition, and into your code on the far side.
2021-09-20 05:54 PM
Excellent! Thanks for the tips. I'll look into those and post back what I learn from others for help.
I did discover that the MPU setup was causing problems --- not initializing the MPU at least gives me a hard fault dispatching to RAM, rather than the CPU hang I'd seen before. So I suspect that I have both that and other problems to look at.
Cheers!