2016-07-27 02:29 PM
I have code that drives the FSMC & in turn an SSD1305 LCD controller. Trouble is, in order to integrate it with the rest of my application, it needs to use the HAL, as all of my SPI, I2C etc is HAL-based.
I've written a HAL-based FSMC setup equivalent & it hard faults on the 2nd access to the LCD if the FSMC setup code is called. If its not called, it loops around trying to access the LCD forever, which it can't quite do, as, because the FSMC isn't setup, the control lines wont actually do anything. I've added the Hard Fault handler that I found in Joseph Yiu's M3 book (I don't think the M4 will be much different, but I don't have that version), and relating the Link Register [R14] contents, 0x1840 to the .map file, the HAL GPIO routines seem to be there, on both sides of that address by a few hundred bytes, but that depends upon me correctly interpreting the sections at the end of the file, of which there are many e.g. .debug_info, .debug_arrange, frame etc etc. (I'm out of my depth trying to figure out what the registers are telling me until I do some more googling!). Can anybody more expert than I, see anything obvious with this HAL code? FSMCTest built on Jul 27 2016 at 21:36:52FSMC_NORSRAM_Init:: OK.
FSMC_NORSRAM_Timing_Init:: OK.
[Hard fault handler - all numbers in hex]
R0 = 16a9000
R1 = 0
R2 = 3fff000
R3 = 1400000
R12 = 985f
LR [R14] = 1840 subroutine call return address
PC [R15] = 0 program counter
PSR = 0
BFAR = e000ed38
CFSR = 400
HFSR = 40000000
DFSR = b
AFSR = 0
SCB_SHCSR = 0
Info : dropped 'gdb' connection
#fsmc-f407-lcd-hard-fault2016-07-27 02:48 PM
Once you've narrowed down where does the problem occur, single-step in assembler to spot the very instruction with the problem. Check repeatibility. Mark the content of relevant registers (those used by that instruction) and look up that instruction in the disassembly.
With inadequate hardware (supply/ground/decoupling/shorts/zillions of other potential problems), funny (read: from purely sw point of view inexplicable) things may occur when you enable a certain module or start to pull levels on pins. JW2016-07-27 03:46 PM
The Hard Fault output doesn't help without the complete context of the project. The numbers for LR/PC look bogus, so I'm not entirely convinced you have that working properly. Same handler would work with M3/M4 cores.
Check differences with Linker Scripts, and where stacks are placed. Check regions in .MAP file. Compare and contrast the FSMC registers between the two cases, confirm those are at least identical.2016-07-27 08:06 PM
Posted on July 28, 2016 at 05:06
Yeah, I think you are vectoring directly to your handler, that isn't going to work as parameter#1 isn't set to anything, you need code to check LR and determine which stack to use.
In Keil, I do it this way..
//*****************************************************************************
/* Add ASM code to startup.s and remove C Handler from stm32fxyz_it.c
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]\n"); // After Joseph Yiu
printf ("r0 = %08X, r1 = %08X, r2 = %08X, r3 = %08X\n",
hardfault_args[0], hardfault_args[1], hardfault_args[2], hardfault_args[3]);
printf ("r4 = %08X, r5 = %08X, r6 = %08X, sp = %08X\n",
r4, r5, r6, (unsigned int)&hardfault_args[8]);
printf ("r12= %08X, lr = %08X, pc = %08X, psr= %08X\n",
hardfault_args[4], hardfault_args[5], hardfault_args[6], hardfault_args[7]);
printf ("bfar=%08X, cfsr=%08X, hfsr=%08X, dfsr=%08X, afsr=%08X\n",
*((volatile unsigned int *)(0xE000ED38)),
*((volatile unsigned int *)(0xE000ED28)),
*((volatile unsigned int *)(0xE000ED2C)),
*((volatile unsigned int *)(0xE000ED30)),
*((volatile unsigned int *)(0xE000ED3C)) );
while(1);
}
//****************************************************************************
And usually look at the instruction immediately preceding the one described by PC
Edit: Fixed formatting, ******* ******* forum.
2016-07-28 07:48 AM
The hard fault happens in line 233,
// write data LCD_REG = 0xA5; LCD_REG = 0x00; // -> Hard Fault Handler (doesnt rtn on 2nd memory access)I checked the settings between the legacy Peripheral library & HAL very carefully - they are the same.
I put a scope on the CS# & WR# lines that go to the LCD & they don't actually do anything on the first access.
I can't see how to open the disassembly window in Visual GDB, but I think that
LCD_REG = 0xA5; will expand to 2 or 3 lines of assembler & that the only address that will be accessed will be 0x6000 0000 (the address of the bottom of the 64Meg block mapped to NOR, or in this case, the LCD.I'm going to try bit banging it using the HAL in order to be sure that the problem is the FSMC.
I'll attach the Peripheral code that works in a few minutes, once I've removed anything irrelevant to do with the end application.
Regards
Ken
2016-07-28 08:04 AM
This works, driving the LCD via the FSMC & bit banged, so I'll try bit-banging the LCD via the HAL....
________________ Attachments : FSMC_LCD_PeriphLib.c : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I1CK&d=%2Fa%2F0X0000000bjm%2FLd86d3xRx1NzRbQ_abyj4lxLR7dOcTykdOyMMxh8dtc&asPdf=false2016-07-28 08:39 AM
> I put a scope on the CS# & WR# lines that go to the LCD & they don't actually do anything on the first access.
Because that was not an access, just the ''cursor'' walked through that line, probably in some preparation step. You ought to do what you are told. I told you to single-step in assembler (i.e. disassembly window). The processor does not care what is in your C source. > I can't see how to open the disassembly window in Visual GDB, Then don't use Visual GDB. Use GDB or any other tool which allows you to do what you need to do. My guess now is that FSMC simply is not configured. > I checked the settings between the legacy Peripheral library & HAL very carefully - they are the same. Did you read back the FSMC's registers for the two cases? If not, you *did not* check anything. The FSMC does not care about your peripheral or other libraries. JW