cancel
Showing results for 
Search instead for 
Did you mean: 

HAL-based FSMC setup code causing Hard Fault: Periph Library doesn't!

ken239955_st
Associate II
Posted on July 27, 2016 at 23:29

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:52

FSMC_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-fault
6 REPLIES 6
Posted on July 27, 2016 at 23:48

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.

JW

Posted on July 28, 2016 at 00:46

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ken239955_st
Associate II
Posted on July 28, 2016 at 16:48

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

ken239955_st
Associate II
Posted on July 28, 2016 at 17:04

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=false
Posted on July 28, 2016 at 17:39

> 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