Skip to main content
Monika KUNCOVA
Visitor II
November 13, 2020

ClassB example hard fault

  • November 13, 2020
  • 0 replies
  • 2263 views

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}
 //---------------------------------------------------

 

This topic has been closed for replies.