2016-09-27 05:48 AM
Hello,
I am using STM32Cube_FW_L4_V1.5.1 library and I am trying to test the STM32Cube_FW_L4_V1.5.0\Projects\STM32L476G_EVAL\Applications\USB_Device\DFU_Standalone application. I have STM32L476RG-Nucleo + NUCLEO-CCA02M1 (for the USB support). I had to modify few small items in the DFU_Standalone application (as it is intended for STM32L476G_EVAL).What I have achieved so far:1. The DFU_Standalone builds and loads properly on my target2. My Windows PC with DfuSe Demo recognize the connected target as DFU device3. I have build a small LED blinking application and tested it works OK if loaded using ST-link/v24. I have converted the blink.bin ->blink.dfu using DfuFileMgr.exe. I have set loading address to 0x0800C000 so it matches the USBD_DFU_APP_DEFAULT_ADD in DFU_Standalon5. I am able to load blink.dfu using DfuSe Demo and I see the blinking code at offset 0x0800C000 exactly as I have in my bin file6. If I set using the debugger the PC to 0x0800C000 and start the execution I see my blinking working fine.7. If I reset the CPU the DFU_Standalon properly find application at 0x0800C000 and tries to jump to it and now my question. Jumping to my application (in DFU_Standalon) is done like this and it doesn't work but hit HardFault_Handler. JumpAddress = *(__IO uint32_t*) (USBD_DFU_APP_DEFAULT_ADD + 4); JumpToApplication = (pFunction) JumpAddress; __set_MSP(*(__IO uint32_t*) USBD_DFU_APP_DEFAULT_ADD); JumpToApplication(); Should my application code starts with stack pointer and then a jump to the actual code? It seems it is not true in my case. Or more general is there somewhere a description about the way user application needs to be written and linked to bin, so after loading it (as dfu) using DFU_Standalone will start properly. Thank you!Dimitar2016-09-27 06:15 AM
If you want your app to run properly on a Cortex-M4 with interrupts and fault handling then it needs to be built with a vector table at the front of the image, and you need to point SCB->VTOR at this table. Build the image like you would a stand-alone one, but with an address deeper into FLASH, and on a 512-byte boundary.
The processor provides all the context needed to see what caused the Hard Fault, a while(1) will not decode this, review examples from Joseph Yiu. When you hand over control you will want to do so without assorted interrupts firing, so make sure you tear-down things that can't be handled by the app when it first starts.2016-09-27 06:43 AM
Hi Clive1,
Thank you for the response. I am not clear how to place the vector table at the beginning of my bin file. Is this a matter of linker configuration file? Sorry if this is very basic. Could you please point me to an example (probably included in STM32Cube_FW_L4_V1.5.1) which I can check? As for the Joseph Yiu example do you refer to the code in https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fHardFault%20Exception%20Why%20oh%20why%21&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD... ?Thank you very much!Dimitar2016-09-27 11:42 AM
The linker script and startup_stm32l4xx.s should control the vector table. The address usually in SystemInit().
Joseph had authored several books and articles covering the Cortex-Mx parts. Hard Fault Handlers being an often covered topic.In Keil, I do it this way..
//*****************************************************************************
/*
HardFault_Handler\
PROC
EXPORT HardFault_Handler
TST lr, #4 ; Determine correct stack
ITE EQ
MRSEQ R0, MSP ; Read MSP (Main)
MRSNE R0, PSP ; Read PSP (Process)
MOV R1, R4 ; Registers R4-R6
MOV R2, R5
MOV R3, R6 ; sourcer32@gmail.com
EXTERN hard_fault_handler_c
B hard_fault_handler_c
ENDP
*/
void hard_fault_handler_c(unsigned int * hardfault_args, unsigned int r4, unsigned int r5, unsigned int r6)
{
printf (''[Hard Fault]
''); // After Joseph Yiu
printf (''r0 = %08X, r1 = %08X, r2 = %08X, r3 = %08
X'',
hardfault_args[0], hardfault_args[1], hardfault_args[2], hardfault_args[3]);
printf (''r4 = %08X, r5 = %08X, r6 = %08X, sp = %08
X'',
r4, r5, r6, (unsigned int)&hardfault_args[8]);
printf (''r12= %08X, lr = %08X, pc = %08X, psr= %08
X'',
hardfault_args[4], hardfault_args[5], hardfault_args[6], hardfault_args[7]);
printf (''bfar=%08X, cfsr=%08X, hfsr=%08X, dfsr=%08X, afsr=%08
X'',
*((volatile unsigned int *)(0xE000ED38)),
*((volatile unsigned int *)(0xE000ED28)),
*((volatile unsigned int *)(0xE000ED2C)),
*((volatile unsigned int *)(0xE000ED30)),
*((volatile unsigned int *)(0xE000ED3C)) );
while(1);
}
//****************************************************************************