I am booting Android on an IMX53 Sabre tablet. I am trying to initialize stacks for the different processor modes. The following is my monitor initialization code:
# Install Secure Monitor
# -----------------------
ldr r1, =ns_image # R1 is used
str r0, [r1]
ldr r0, =tz_monitor # Get address of Monitors vector table
mcr p15, 0, r0, c12, c0, 1 # Write Monitor Vector Base Address Register
# Save Secure state
# ------------------
ldr r0, =S_STACK_LIMIT # Get address of Secure state stack
stmfd r0!, {r4-r12} # Save general purpose registers
# ADD support for SPs
mrs r1, cpsr # Also get a copy of the CPSR
stmfd r0!, {r1, lr} # Save CPSR and LR
ldr r1, =STACK_ADDR
msr cpsr_c, #Mode_FIQ | I_Bit | F_Bit
sub sp, r1, #Offset_FIQ_Stack
msr cpsr_c, #Mode_IRQ | I_Bit | F_Bit
sub sp, r1, #Offset_IRQ_Stack
msr cpsr_c, #Mode_ABT | I_Bit | F_Bit
sub sp, r1, #Offset_ABT_Stack
msr cpsr_c, #Mode_UND | I_Bit | F_Bit
sub sp, r1, #Offset_UND_Stack
msr cpsr_c, #Mode_SYS | I_Bit | F_Bit
sub sp, r1, #Offset_SYS_Stack
msr cpsr_c, #Mode_SVC | I_Bit | F_Bit
sub sp, r1, #Offset_SVC_Stack
msr cpsr_c, #Mode_MON | I_Bit | F_Bit
sub sp, r1, #Offset_MON_Stack
cps #Mode_MON # Move to Monitor mode after saving Secure state
# Save Secure state stack pointer
# --------------------------------
ldr r1, =S_STACK_SP # Get address of global
str r0, [r1] # Save pointer
# Set up initial NS state stack pointer
# --------------------------------------
ldr r0, =NS_STACK_SP # Get address of global
ldr r1, =NS_STACK_LIMIT # Get top of Normal state stack (assuming FD model)
str r1, [r0] # Save pointer
# Set up exception return information
# ------------------------------------
#IMPORT ns_image
ldr lr, ns_image # ns_image
msr spsr_cxsf, #Mode_SVC # Set SPSR to be SVC mode
# Switch to Normal world
# -----------------------
mrc p15, 0, r4, c1, c1, 0 # Read Secure Configuration Register data
bic r4, #0x66
orr r4, #0x19
//orr r4, #NS_BIT # Set NS bit
mcr p15, 0, r4, c1, c1, 0 # Write Secure Configuration Register data
# Clear general purpose registers
# --------------------------------
mov r0, #0
mov r1, #0
mov r2, #0
mov r3, #0
mov r4, #0
mov r5, #0
mov r6, #0
mov r7, #0
mov r8, #0
mov r9, #0
mov r10, #0
mov r11, #0
mov r12, #0
movs pc, lr
Android booting happens fine with this, but I am not sure if the stack pointers are set up correctly, as I am not able to use them as described at IMX53 external abort. Are the stack initializations correct?
Other relevant code snippets:
.equ Mode_USR, 0x10 # User Mode
.equ Mode_FIQ, 0x11 # Fast Interrupt Mode
.equ Mode_IRQ, 0x12 # Interrupt Mode
.equ Mode_SVC, 0x13 # Supervisor Mode
.equ Mode_ABT, 0x17 # Abort Mode
.equ Mode_UND, 0x1B # Undefined Mode
.equ Mode_SYS, 0x1F # System Mode
.equ Mode_MON, 0x16 # Monitor Mode
.equ STACK_ADDR, 0xa0000000
.equ I_Bit, 0x80 # IRQ interrupts disabled
.equ F_Bit, 0x40 # FIQ interrupts disabled
.equ NS_BIT, 0x1
/* memory reserved (in bytes) for stacks of different mode */
.equ Len_FIQ_Stack, 64
.equ Len_IRQ_Stack, 64
.equ Len_ABT_Stack, 64
.equ Len_UND_Stack, 64
.equ Len_SVC_Stack, 64
.equ Len_USR_Stack, 64
.equ Len_MON_Stack, 64
.equ Len_SYS_Stack, 64
.equ Offset_FIQ_Stack, 0
.equ Offset_IRQ_Stack, Offset_FIQ_Stack + Len_FIQ_Stack
.equ Offset_ABT_Stack, Offset_IRQ_Stack + Len_IRQ_Stack
.equ Offset_UND_Stack, Offset_ABT_Stack + Len_ABT_Stack
.equ Offset_SVC_Stack, Offset_UND_Stack + Len_UND_Stack
.equ Offset_USR_Stack, Offset_SVC_Stack + Len_SVC_Stack
.equ Offset_MON_Stack, Offset_USR_Stack + Len_USR_Stack
.equ Offset_SYS_Stack, Offset_MON_Stack + Len_MON_Stack
Related
So I'm having trouble with my program. It's supposed to read in a text file
that has a number on each line. It then stores that in an array, sorts it using selection sort, and then outputs it to a new file. The reading of and writing to the file work perfectly fine but my code for the sort isn't working properly. When I run the program, it only seems to store some of the numbers
in the array and then a bunch of zeroes.
So if my input is 112323, 32, 12, 19, 2, 1, 23. The output is 0,0,0,0, 2,1,23. I'm pretty sure the problem's with how I'm storing and loading from the array
onto the registers because assuming that part works, I can't find any reason why the selection sort algorithm shouldn't work.
Ok thanks to your help, I figured out that I needed to change the load and store instruction so that it matches the specifier used (ldr -> ldrb and str -> strb). But I need to make a sorting algorithm that works for 32 bit numbers so which combination of specifiers and load/store instructions would allow me to do that? Or would I have to load/store 8 bits a time? And if so, how would I do that?
.data
.balign 4
readfile: .asciz "myfile.txt"
.balign 4
readmode: .asciz "r"
.balign 4
writefile: .asciz "output.txt"
.balign 4
writemode: .asciz "w"
.balign 4
return: .word 0
.balign 4
scanformat: .asciz "%d"
.balign 4
printformat: .asciz "%d\n"
.balign 4
a: .space 32
.text
.global main
.global fopen
.global fprintf
.global fclose
.global fscanf
.global printf
main:
ldr r1, =return
str lr, [r1]
ldr r0, =readfile
ldr r1, =readmode
bl fopen
mov r4, r0
mov r5, #0
ldr r6, =a
loop:
cmp r5, #7
beq sort
mov r0, r4
ldr r1, =scanformat
mov r2, r6
bl fscanf
add r5, r5, #1
add r6, r6, #1
b loop
sort:
mov r5,#0 /*array parser for first loop*/
mov r6, #0 /* #stores index of minimum*/
mov r7, #0 /* #temp*/
mov r8, #0 /*# array parser for second loop*/
mov r9, #7 /*# stores length of array*/
ldr r10, =a /*# the array*/
mov r11, #0 /*#used to obtain offset for min*/
mov r12, #0 /*# used to obtain offset for second parser access*/
loop3:
cmp r5, r9 /*# check if first parser reached end of array*/
beq write /* #if it did array is sorted write it to file*/
mov r6, r5 /*#set the min index to the current position*/
mov r8, r6 /*#set the second parser to where first parser is at*/
b loop4 /*#start looking for min in this subarray*/
loop4:
cmp r8, r9 /* #if reached end of list min is found*/
beq increment /* #get out of this loop and increment 1st parser**/
lsl r7, r6, #3 /*multiplies min index by 8 */
ADD r7, r10, r7 /* adds offset to r10 address storing it in r7 */
ldr r11, [r7] /* loads value of min in r11 */
lsl r7, r8, #3 /* multiplies second parse index by 8 */
ADD r7, r10, r7 /* adds offset to r10 address storing in r7 */
ldr r12, [r7] /* loads value of second parse into r12 */
cmp r11, r12 /* #compare current min to the current position of 2nd parser !!!!!*/
movgt r6, r8 /*# set new min to current position of second parser */
add r8, r8, #1 /*increment second parser*/
b loop4 /*repeat */
increment:
lsl r11, r5, #3 /* multiplies first parse index by 8 */
ADD r11, r10, r11 /* adds offset to r10 address stored in r11*/
ldr r8, [r11] /* loads value in memory address in r11 to r8*/
lsl r12, r6, #3 /*multiplies min index by 8 */
ADD r12, r10, r12 /*ads offset to r10 address stored in r12 */
ldr r7, [r12] /* loads value in memory address in r12 to r7 */
str r8, [r12] /* # stores value of first parser where min was !!!!!*/
str r7, [r11] /*# store value of min where first parser was !!!!!*/
add r5, r5, #1 /*#increment the first parser*/
ldr r0,=printformat
mov r1, r7
bl printf
b loop3 /*#go to loop1*/
write:
mov r0, r4
bl fclose
ldr r0, =writefile
ldr r1, =writemode
bl fopen
mov r4, r0
mov r5, #0
ldr r6, =a
loop2:
cmp r5, #7
beq end
mov r0, r4
ldr r1, =printformat
ldrb r2, [r6]
bl fprintf
add r5, r5, #1
add r6, r6, #1
b loop2
end:
mov r0, r4
bl fclose
ldr r0, =a
ldr r0, [r0]
ldr lr, =return
ldr lr, [lr]
bx lr
I figured out that I needed to change the load and store instruction
so that it matches the specifier used (ldr -> ldrb and str -> strb).
But I need to make a sorting algorithm that works for 32 bit numbers
so which combination of specifiers and load/store instructions would
allow me to do that?
If you want to read 32b (4 bytes) values from memory, you have to have 4 bytes values in memory to begin with. Well that should not be surprising :)
Eg if your input is numbers 1, 2, 3, 4, each number is 32b value than in memory that would be
0x00000000: 01 00 00 00 | 02 00 00 00 <- 32b values of 1 & 2
0x00000008: 03 00 00 00 | 04 00 00 00 <- 32b values of 3 & 4
In such case ldr would read 32b each time and you would get 1, 2, 3, 4 with each read in register.
Now, you have in memory byte values (based on your statement that `ldrb` gives right result), eg
0x00000000: 01
0x00000001: 02
0x00000002: 03
0x00000003: 04
or same in one line
0x00000000: 01 02 03 04
So reading 8bit by ldrb gives you numbers 1, 2, 3, 4
But ldr would do read 32b value from memory (all 4 bytes at once) and you would get 32b value 0x04030201 in register.
Note: examples for little-endian systems
I'm using Armsim and I need to take some integers from a txt file and then I've to order and print them ordered in another txt file. How can I do? I mean, I managed to read the numbers, but I can't print them in order
Here's what I wrote:
.equ SWI_Open, 0x66 #open a file
.equ SWI_Close,0x68 #close a file
.equ SWI_PrChr,0x00 # Write an ASCII char to Stdout
.equ SWI_PrStr, 0x69 # Write a null-ending string
.equ SWI_PrInt,0x6b # Write an Integer
.equ SWI_RdInt,0x6c # Read an Integer from a file
.equ Stdout, 1 # Set output target to be Stdout
.equ SWI_Exit, 0x11 # Stop execution
.data
i: .asciiz "7.2in.txt"
o: .asciiz "7.2o.txt"
.text
_main:
ldr r0, =i
mov r1, #0
swi 0x66
mov r2, r0
ldr r0, =o
mov r1, #1
swi 0x66
mov r1, r2
bl copy
swi 0x11
copy:
mov r1, r0
mov r3, r2
mov r0, r2
swi 0x6c
loop:
mov r4, r0
mov r0, r2
swi 0x6c
cmp r0, #00
beq end
cmp r4, r0
ble no_scambio
mov r2, r3
mov r3, r1
mov r1, r0
mov r0, r3
swi 0x6b
mov r0, r1
mov r1, r3
mov r3, r2
b loop
no_scambio:
mov r2, r3
mov r2, r1
mov r1, r0
mov r0, r2
swi 0x6b
mov r0, r1
mov r1, r2
mov r2, r3
b loop
end:
mov pc, lr
I am using Omap3515 (Arm Cortex A8). Enabled I-Cache, D-Cache, Branch Prediction and MMU.
And also I am getting a data abort, if I try to copy a frame buffer of 600KB from an external memory region to another external memory region.
(If I copy 100KB are less then there is no abort. Even some times for copying 400KB also there is no data abort.)
After the data abort, I could notice that the SDR i.e SDRAM is not accessible.
I have enabled MMU in such a way that PA=VA.
If I disable D-Cache then there is no abort and it works fine. But I would like to enable D-Cache for faster access.
Here is the code
.arm
.sect EntryOnReset
;// Module Imports and exports
.global ResetHandler
.global RelocateImage
.global OasysEntry
.global BoardInit
.global __stack
.global __STACK_SIZE
.global NEONCopyPLD
.global EnableCaches
.global DisableCaches
.global MemmoryTest
.global core_init
;// Stack Size Definition.
UND_Stack_Size .EQU 0x00000100
SVC_Stack_Size .EQU 0x00001000 ;//Only main function stack is to be mentioned here.
ABT_Stack_Size .EQU 0x00000100
FIQ_Stack_Size .EQU 0x00000100
IRQ_Stack_Size .EQU 0x00000100
USR_Stack_Size .EQU 0x00000100
;//******************************************************************************
;// EQUATES
;//******************************************************************************
;// Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
Mode_USR .EQU 0x10
Mode_FIQ .EQU 0x11
Mode_IRQ .EQU 0x12
Mode_SVC .EQU 0x13
Mode_ABT .EQU 0x17
Mode_UND .EQU 0x1B
Mode_SYS .EQU 0x1F
I_Bit .EQU 0x80 ;// when I bit is set, IRQ is disabled
F_Bit .EQU 0x40 ;// when F bit is set, FIQ is disabled
;//******************************************************************************
;// EQUATES
;//******************************************************************************
FIQ_IRQ_DISABLE .EQU 0xC0 ;//Disable both FIQ and IRQ.
;//******************************************************************************
;// CODE GENERATION DIRECTIVES
;//******************************************************************************
;// Area Definition and Entry Point
;// Startup Code must be linked first at Address at which it expects to run.
;//------------------------------------------------------------------------------
;//******************************************************************************
;// Routine name : ENTRY
;// Description : Entry point for software.
;// Assumptions : <none>
;// Tainted registers : <none>
;// Functions called :
;// Low level
;// Requirements :
;//
;// 1. This routine shall initialize the Stack pointer.
;//
;// 2. This routine shall perform architecture specific
;// initializations by calling InitCPU routine.
;//******************************************************************************
ResetHandler:
;==================================================================
; Enable access to NEON/VFP by enabling access to Coprocessors 10 and 11.
; Enables Full Access i.e. in both privileged and non privileged modes
;==================================================================
MRC p15, #0, r0, c1, c0, #2 ; Read Coprocessor Access Control Register (CPACR)
ORR r0, r0, #(0xF << 20) ; Enable access to CP 10 & 11
MCR p15, #0, r0, c1, c0, #2 ; Write Coprocessor Access Control Register (CPACR)
ISB
;==================================================================
; Switch on the VFP and NEON hardware
;=================================================================
MOV r0, #0x40000000
VMSR FPEXC, r0 ; Write FPEXC register, EN bit set
;# Disable MMU.
MRC p15, #0, r1, c1, c0, #0 ;# Read Control Register configuration data.
BIC r1, r1, #0x1
MCR p15, #0, r1, c1, c0, #0 ;# Write Control Register configuration data.
;# Disable L1 Caches.
MRC p15, #0, r1, c1, c0, #0 ;# Read Control Register configuration data.
BIC r1, r1, #(0x1 << 12) ;# Disable I Cache.
BIC r1, r1, #(0x1 << 2) ;# Disable D Cache.
MCR p15, #0, r1, c1, c0, #0 ;# Write Control Register configuration data
;# Invalidate L1 Caches.
;# Invalidate Instruction cache.
MOV r1, #0
MCR p15, #0, r1, c7, c5, #0
;# Invalidate Data cache.
;# To make the code general purpose, calculate the
;# cache size first and loop through each set + way.
MRC p15, #1, r0, c0, c0, #0 ;# Read Cache Size ID.
;TBR LDR r3, #0x1FF
MOV r3, #0x1FF
AND r0, r3, r0, LSR #13 ;# r0 = no. of sets - 1.
MOV r1, #0 ;# r1 = way counter way_loop.
way_loop:
MOV r3, #0 ;# r3 = set counter set_loop.
set_loop:
MOV r2, r1, LSL #30
;TBR ORR r2, r3, LSL #5 ;# r2 = set/way cache operation format.
ORR r2, r2, r3, LSL #5 ;# r2 = set/way cache operation format.
MCR p15, #0, r2, c7, c6, #2 ;# Invalidate the line described by r2.
ADD r3, r3, #1 ;# Increment set counter.
CMP r0, r3 ;# Last set reached yet?
BGT set_loop ;# If not, iterate set_loop,
ADD r1, r1, #1 ;# else, next.
CMP r1, #4 ;# Last way reached yet?
BNE way_loop ;# if not, iterate way_loop.
;# Invalidate TLB
MCR p15, #0, r1, c8, c7, #0
;# Branch Prediction Enable.
MOV r1, #0
MRC p15, #0, r1, c1, c0, #0 ;# Read Control Register configuration data.
ORR r1, r1, #(0x1 << 11) ;# Global BP Enable bit.
MCR p15, #0, r1, c1, c0, #0 ;# Write Control Register configuration data.
;# Enable D-side Prefetch
MRC p15, #0, r1, c1, c0, #1 ;# Read Auxiliary Control Register.
ORR r1, r1, #(0x1 <<2) ;# Enable D-side prefetch.
MCR p15, #0, r1, c1, c0, #1; ;# Write Auxiliary Control Register.
DSB
ISB
;# DSB causes completion of all cache maintenance operations appearing in program
;# order before the DSB instruction.
;# An ISB instruction causes the effect of all branch predictor maintenance
;# operations before the ISB instruction to be visible to all instructions
;# after the ISB instruction.
;# Initialize PageTable.
;# It would be faster to create this in a read-only section in an assembly file.
;# descriptor.
LDR r1, tlb_l1_base
MOV r2, #0
MOV r4, #1
write_pte
MOV r0, #0x0E
ORR r0, r0, r4, LSL #0xA
ORR r0, r0, r4, LSL #0xB
ORR r0, r0, r2, LSL #20
STR r0, [r1]
ADD r1, r1, #4
ADD r2, r2, #1 ;# Decrement loop counter.
SUBS r3, r2, #4096
BNE write_pte
;# Initialize MMU.
MOV r1,#0x0
MCR p15, #0, r1, c2, c0, #2 ;# Write Translation Table Base Control Register.
LDR r1, tlb_l1_base
MCR p15, #0, r1, c2, c0, #0 ;# Write Translation Table Base Register 0.
;# In this simple example, do not use TRE or Normal Memory Remap Register.
;# Set all Domains to Manger.
MOV r1, #0xFFFF ; Provied Manager access, so access premition bits (AP) shall not be checked.
ORR r1, r1, r1, LSL #0x10
MCR p15, #0, r1, c3, c0, #0 ;# Write Domain Access Control Register.
;# Enable MMU
MRC p15, #0, r1, c1, c0, #0 ;# Read Control Register configuration data.
ORR r1, r1, #0x1 ;# Bit 0 is the MMU enable.
MCR p15, #0, r1, c1, c0, #0 ;# Write Control Register configuration data.
tlb_l1_base .word 0x40200000
;//******************************************************************************
;// SETUP STACK POINTERS FOR USR MODE
;//******************************************************************************
;*------------------------------------------------------
;* INITIALIZE THE USER MODE STACK
;*------------------------------------------------------
StackInit:
LDR sp, c_stack
LDR r0, c_STACK_SIZE
ADD sp, sp, r0
;*-----------------------------------------------------
;* Clear upper 3 bits for 64-bit alignment.
;*-----------------------------------------------------
BIC sp, sp, #0x07
;// Set IRQ and FIQ bits in CPSR to disable all interrupts.
MRS R0, CPSR
STMFD SP!, {R0} ;// Store it onto stack
ORR R1, R0, #FIQ_IRQ_DISABLE
MSR CPSR_c, R1
;//******************************************************************************
;// SETUP STACK FOR OTHER MODES
;//******************************************************************************
MOV R0, SP
;// Enter Undefined Instruction Mode and set its Stack Pointer
MSR CPSR_c, #Mode_UND|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #UND_Stack_Size
;// Enter Abort Mode and set its Stack Pointer
MSR CPSR_c, #Mode_ABT|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size
;// Enter FIQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_FIQ|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
;// Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size
;// Enter Supervisor Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SVC|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size
MSR CPSR_c, #Mode_SVC|I_Bit
;//******************************************************************************
;// MOVE TO myfunc
;//******************************************************************************
;// The following routine copies the loaded image to execution region.
BL RelocateImage
;// The following routine initialises the Omap3515.
BL BoardInit
;// The following routine enaables the MMU.
;BL EnableMMU
;// The following routine enables the I cache.
BL EnableICaches
;// The following routine enables branch prediction.
BL EnableBrachPrediction
;// The following routine enables the D cache.
BL EnableDCaches
;// The following routine enables the L2 cache.
;BL EnableL2UnifiedCache
;// The following routine starts the OS.
BL MemmoryTest
;===================================================================
; Enable MMU and Branch to __main
; Leaving the caches disabled until after scatter loading.
;===================================================================
.global EnableMMU
;******************************************************************************
; c1, Control Register
; [0] M bit Banked Enables the MMU:
; 0 = MMU disabled, reset value
; 1 = MMU enabled.
;******************************************************************************
EnableMMU:
;Read the c1 register
mrc p15, #0, r0, c1, c0, #0
;Set b1 - Enables the MMU
orr r0, r0, #0x1
; Write back to c1 register to enable MMU
mcr p15, #0, r0, c1, c0, #0
BX lr
.global EnableICaches
;==================================================================
; This API enables instruction cache.
;==================================================================
EnableICaches:
MRC p15, #0, r0, c1, c0, #0 ; Read System Control Register
ORR r0, r0, #(0x1 << 12) ; Set I bit 12 to enable I Cache
;BIC r0, r0, #(0x1 <<12) ; Clear bit 0
MCR p15, #0, r0, c1, c0, #0 ; Write System Control Register
BX lr
.global EnableDCaches
;==================================================================
; This API enables data cache.
;==================================================================
EnableDCaches:
MRC p15, #0, r0, c1, c0, #0 ; Read System Control Register
ORR r0, r0, #(0x1 << 2) ; Set C bit 2 to enable D Cache
;BIC r0, r0, #(0x1 << 2) ; Clear bit 0
;BIC r0, r0, #(0x1 << 1) ; disable alignment checks
MCR p15, #0, r0, c1, c0, #0 ; Write System Control Register
BX lr
.global EnableL2UnifiedCache
;==================================================================
; Enable Cortex-A8 Level2 Unified Cache
;==================================================================
EnableL2UnifiedCache:
MRC p15, #0, r0, c1, c0, #1 ; Read Auxiliary Control Register
ORR r0, r0, #2 ; L2EN bit, enable L2 cache
;BIC r0, r0, #(0x1 << 1) ; L2EN bit, disable L2 cache
;ORR r0, r0, #(0x1 << 4) ;Enables speculative accesses on AXI
ORR r0, r0, #(0x1 << 4) ;Enables speculative accesses on AXI
ORR r0, r0, #(0x1 << 5) ;Enables caching NEON data within the L1 data cache
MCR p15, #0, r0, c1, c0, #1 ; Write Auxiliary Control Register
BX lr
.global EnableBrachPrediction
;==================================================================
; This API enables branch prediction
;==================================================================
EnableBrachPrediction:
MRC p15, #0, r0, c1, c0, #0 ; Read System Control Register
ORR r0, r0, #(0x1 << 11) ; Set Z bit 11 to enable branch prediction
;BIC r0, r0, #(0x1 << 11) ; Disable all forms of branch prediction
MCR p15, #0, r0, c1, c0, #0 ; Write System Control Register
BX lr
c_stack: .long __stack
c_STACK_SIZE: .long __STACK_SIZE
;//******************************************************************************
;// POINTERS TO VARIABLES
;//******************************************************************************
; ENDIF
.END
Thanks and regards,
Krish
The Cortex-A caches generally write allocate, so the write succeeds, and only faults "late" when the cache line is evicted. I would guess your pagetable is set up incorrectly.
If you look at the DFAR ans DFSR (data fault status register, and data fault address register), you should get more specific information about the fault and the triggering address.
I'm trying to get a STM32Cube project compiled using arm-none-eabi-gcc and a Makefile.
I have specified:
CFLAGS = -mthumb\
-march=armv6-m\
-mlittle-endian\
-mcpu=cortex-m0\
-ffunction-sections\
-fdata-sections\
-MMD\
-std=c99\
-Wall\
-g\
-D$(PART)\
-c
and:
LDFLAGS = -Wl,--gc-sections\
-Wl,-T$(LDFILE)\
-Wl,-v
The FW builds without problems.but when I boot the MCU i get stuck in Hard Fault.
Stack trace is:
#0 HardFault_Handler () at ./Src/main.c:156
#1 <signal handler called>
#2 0x0800221c in ____libc_init_array_from_thumb ()
#3 0x080021be in LoopFillZerobss () at Src/startup_stm32f030x8.s:103
#4 0x080021be in LoopFillZerobss () at Src/startup_stm32f030x8.s:103
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
and I go straight to Hard Fault when stepping to bl __libc_init_array in the startup file.
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
Any ideas what could be wrong?
My arm-none-eabi-gcc version is 4.8.4 20140725 (release)
[edit]
The disassembly of the calls
08002218 <____libc_init_array_from_thumb>:
8002218: 4778 bx pc
800221a: 46c0 nop ; (mov r8, r8)
800221c: eafff812 b 800026c <__libc_init_array>
0800026c <__libc_init_array>:
800026c: e92d4070 push {r4, r5, r6, lr}
8000270: e59f506c ldr r5, [pc, #108] ; 80002e4 <__libc_init_array+0x78>
8000274: e59f606c ldr r6, [pc, #108] ; 80002e8 <__libc_init_array+0x7c>
8000278: e0656006 rsb r6, r5, r6
800027c: e1b06146 asrs r6, r6, #2
8000280: 12455004 subne r5, r5, #4
8000284: 13a04000 movne r4, #0
8000288: 0a000005 beq 80002a4 <__libc_init_array+0x38>
800028c: e2844001 add r4, r4, #1
8000290: e5b53004 ldr r3, [r5, #4]!
8000294: e1a0e00f mov lr, pc
8000298: e12fff13 bx r3
800029c: e1560004 cmp r6, r4
80002a0: 1afffff9 bne 800028c <__libc_init_array+0x20>
80002a4: e59f5040 ldr r5, [pc, #64] ; 80002ec <__libc_init_array+0x80>
80002a8: e59f6040 ldr r6, [pc, #64] ; 80002f0 <__libc_init_array+0x84>
80002ac: e0656006 rsb r6, r5, r6
80002b0: eb0007ca bl 80021e0 <_init>
80002b4: e1b06146 asrs r6, r6, #2
80002b8: 12455004 subne r5, r5, #4
80002bc: 13a04000 movne r4, #0
80002c0: 0a000005 beq 80002dc <__libc_init_array+0x70>
80002c4: e2844001 add r4, r4, #1
80002c8: e5b53004 ldr r3, [r5, #4]!
80002cc: e1a0e00f mov lr, pc
80002d0: e12fff13 bx r3
80002d4: e1560004 cmp r6, r4
80002d8: 1afffff9 bne 80002c4 <__libc_init_array+0x58>
80002dc: e8bd4070 pop {r4, r5, r6, lr}
80002e0: e12fff1e bx lr
80002e4: 08002258 .word 0x08002258
80002e8: 08002258 .word 0x08002258
80002ec: 08002258 .word 0x08002258
80002f0: 08002260 .word 0x08002260
[edit 2]
The register values from gdb:
(gdb) info reg
r0 0x20000000 536870912
r1 0x1 1
r2 0x0 0
r3 0x40021000 1073876992
r4 0xffffffff -1
r5 0xffffffff -1
r6 0xffffffff -1
r7 0x20001fd0 536879056
r8 0xffffffff -1
r9 0xffffffff -1
r10 0xffffffff -1
r11 0xffffffff -1
r12 0xffffffff -1
sp 0x20001fd0 0x20001fd0
lr 0xfffffff9 -7
pc 0x800067c 0x800067c <HardFault_Handler+4>
xPSR 0x61000003 1627389955
That __libc_init_array is ARM code, not Thumb, hence the M0 will fall over trying to execute some nonsense it doesn't understand (actually, it never quite gets there since it faults on the attempt to switch to ARM state in the bx, but hey, same difference...)
You'll need to make sure you use pure-Thumb versions of any libraries - a Cortex-M-specific toolchain might be a better bet than a generic ARM one. If you have a multilib toolchain, I'd suggest checking the output of arm-none-eabi-gcc --print-multi-lib to make sure you've specified all the relevant options to get proper Cortex-M libraries, and if you're using a separate link step, make sure you invoke it with LD=arm-none-eabi-gcc (plus the relevant multilib options), rather than LD=arm-none-eabi-ld.
This code compiles just fine on gcc, but when using llvm (llvm-gcc), it says "constant expression expected" on the line with ldr
The problem is the syntax: How do I specify the place where my array is? I do not want to hard-code the displacement in bytes: ldr r7, [pc, #some_shift] but to use a literal to keep the code clean and safe.
Any idea how to make it working?
.globl func_name
func_name:
push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
//[Some stripped code]
add r6, r6, sl, lsl #2
sub ip, ip, sl
ldr r7, =maskTable // Here it crashes
add sl, sl, #4 # 0x4
// Some stripped code here
mov r0, #0 # 0x0 // return 0
pop {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
.word 0x00000000
.data
.align 5
maskTable:
.word 0x00000000, 0x00000000, 0x00000000, 0x00000000
.word 0x0000FFFF, 0x00000000, 0x00000000, 0x00000000
.word 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000
Try changing
ldr r7, =maskTable
to
ldr r7, maskTable
and remove
.data
section. It seems to be a bug/missing capability of gcc < 4.6 to deal with .data section
There are two things you can try:
Change ldr r7, =maskTable into adr r7, maskTable.
Store the address of the table under a separate label and load it manually like follows:
.globl func_name
func_name:
push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
//[Some stripped code]
add r6, r6, sl, lsl #2
sub ip, ip, sl
ldr r7, maskTable_adr // Here it crashes
add sl, sl, #4 # 0x4
// Some stripped code here
mov r0, #0 # 0x0 // return 0
pop {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
.word 0x00000000
.data
.align 5
maskTable_adr:
.word maskTable
maskTable:
.word 0x00000000, 0x00000000, 0x00000000, 0x00000000
.word 0x0000FFFF, 0x00000000, 0x00000000, 0x00000000
.word 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000
I don't know the answer myself, but if it was me, I'd look at some compiled C code, and see how the compiler does it. Make sure that the compiler isn't in PIC mode, or something, or it'll do something more complicated and unnecessary.