cancel
Showing results for 
Search instead for 
Did you mean: 

ClassB example hard fault

Monika KUNCOVA
Visitor II
[FAQ][STM32F4]: During debugging ClassB library example is giving me hard-faults. What is the problem?Issue can be caused by corruption of CPU registers that modern compiler produced code uses during run-time. One of the requirements is that each subroutine keeps the content of core registers R4 to R11. Information regarding this issue can be found also in document AN4435 chapter 6.
Testing subroutines for ClassB libraries are located in assembly files (XXX is name of compiler. For example GCC, IAR).

 
  • stm32f4xx_STLcpustartXXX.s
    • STL_StartUpCPUTest routine
  • stm32fxx_STLRamMcMxXXX.s
    • STL_FullRamMarchC routine

Assembly files need to be modified to store register content at the beginning of test routines and restore the content at the end of test routines.
For memory test (STL_FullRamMarchC routine in stm32fxx_STLRamMcMxXXX.s file) SRAM memory cannot be used as backup location because its content is destroyed during test routine. One of the approaches can be to use some MCU peripheral to store register content. It can be for example DMA controller, because it is present in most of microcontrollers and has enough 32-bit registers. DMA memory address registers can be used for that purpose.
For CPU test(STL_StartUpCPUTest routine in stm32f4xx_STLcpustartXXX.s file) stack or peripheral(DMA) can be used for registry backup.

The registry store process needs to include
  • DMA enable
  • Store registers into DMA controller channel memory address registers
The registry restore process needs to include
  • Restore of registers from DMA controller channel memory address registers
  • Restore DMA state before assembly routine call (most probably disable DMA)

Example for STM32F4 family and IAR compiler:
Backing-up the registers in 
STL_FullRamMarchC procedure in file stm32fxx_STLRamMcMxIAR.s.
STL_FullRamMarchC:

  //-----R4 - R7 BACKUP SEQUENCE-----
  //backup R2 and R3, used in following DMA backup procedure
  PUSH {R1-R3}
  //store R4-R7
  //enable DMA1 to store backup of registers
  LDR R3, =0x40021030 //AHBENR register address
  LDR R1, [R3]          //R1 backup of AHBENR
  LDR R3, [R3]
  MOVS R2, #0x01 	  //DMA1EN clock enable bit position
  ORRS R3, R3, R2	  //set DMA1EN bit, default after MCU reset
  LDR R2, =0x40021030
  STR R3, [R2]
  //store registers R4-R7
  LDR R3, =0x40020000     // DMA1 base address -> R3
  STR R4, [R3, #+0x14]    // R4 -> DMA CMAR1
  STR R5, [R3, #+0x28]    // R5 -> DMA CMAR2
  STR R6, [R3, #+0x3C]    // R6 -> DMA CMAR3
  STR R7, [R3, #+0x50]    // R7 -> DMA CMAR4
  STR R1, [R3, #+0x64]    // R1 -> DMA CMAR5
  //restore R1 - R3 backup
  POP {R1-R3}
  //---------------------------------

Restoring the registers at the end of procedure:
  //-----R4 - R7 RESTORE SEQUENCE------
  //backup R2 and R3, used in following DMA backup procedure
  PUSH {R2-R3}
  //restore R4-R7
  LDR R3, =0x40020000   // DMA1 base address -> R3
  MOVS R2, #0 			//default CMAR value by reference manual
  LDR R4, [R3, #+0x14]    // DMA CMAR1 -> R4
  LDR R5, [R3, #+0x28]    // DMA CMAR2 -> R5
  LDR R6, [R3, #+0x3C]    // DMA CMAR3 -> R6
  LDR R7, [R3, #+0x50]    // DMA CMAR4 -> R7
  LDR R2, [R3, #+0x64]    // DMA CMAR5 -> R2
  //restore AHBENR
  LDR R3, =0x40021030 //AHBENR register address
  STR R2, [R3]
  //restore R2 and R3 backup
  POP {R2-R3}
  //------------------------------------

Backing-up the registers in STL_StartUpCPUTest procedure in file stm32l0xx_STLcpustartIAR.s:
    PUSH {R4-R7}               /* Safe critical registers */

    //R8 - R11 BACKUP SEQUENCRE
    //backup R1 - R3, used in following DMA backup procedure
    PUSH {R1-R3}
    //BACKUP R8-R11
    //enable DMA1 to store backup of registers
    LDR R3, =0x40021030 	//AHBENR register address
    LDR R1, [R3]          //R1 backup of AHBENR
    LDR R3, [R3]
    MOVS R2, #0x01 	  		//DMA1EN clock enable bit position
    ORRS R3, R3, R2		  	//set DMA1EN bit, default after MCU reset
    LDR R2, =0x40021030		//AHBENR register address
    STR R3, [R2]
    //store registers
    LDR R3, =0x40020000   // DMA1 base address -> R3
    MOV R2,R8
    STR R2, [R3, #+0x14]    // R8 -> DMA CMAR1
    MOV R2,R9
    STR R2, [R3, #+0x28]    // R9 -> DMA CMAR2
    MOV R2,R10
    STR R2, [R3, #+0x3C]   // R10 -> DMA CMAR3
    MOV R2,R11
    STR R2, [R3, #+0x50]   // R11 -> DMA CMAR4
    STR R1, [R3, #+0x64]   // R1 -> DMA CMAR5
    //restore R1 - R3 backup
    POP {R1-R3}

Restoring the registers at the end of procedure:
    POP {R4-R7}			 /* Restore critical registers */
   
    //------R8 - R11 RESTORE SEQUENCE------
    //backup R2 and R3, used in following DMA backup procedure
    PUSH {R2-R3}
    //RESTORE BACKUP OF R8-R11
    //restore registers
    LDR R3, =0x40020000   // DMA1 base address -> R3
    LDR R2, [R3, #+0x14]    // DMA CMAR1 -> R8
    MOV R8, R2
    LDR R2, [R3, #+0x28]    // DMA CMAR2 -> R9
    MOV R9, R2
    LDR R2, [R3, #+0x3C] 	// DMA CMAR3 -> R10
    MOV R10, R2
    LDR R2, [R3, #+0x50]   // DMA CMAR4 -> R11
    MOV R11, R2
    LDR R2, [R3, #+0x64]   // DMA CMAR5 -> R2, CMAR5 contained AHBENR backup
    //RESTORE AHBENR (DMA state)
    LDR R3, =0x40021030 	//AHBENR register address
    STR R2, [R3]			//write to AHBENR
    //restore R2 and R3 backup
    POP {R2-R3}
    //---------------------------------------------------
Version history
Last update:
‎2020-11-13 03:05 AM
Updated by: