;This is the port code for the PXA270 processor. ;It is written in the ARM assembly language, and follows the ;example listed in application note AN-1011 and AN-1014 ; ;NOTE: ; 1) I am not sure whether or not I need any of the following lines: ; LDR R4, [SP], #4 ;Get the new task SPSR ; MSR SPSR_cxsf, R4 ;Put the value of SPSR back ; In fact, I get a warning when I include them, but I think it is good to save the ; SPSR on the stack. However, I should not pop this after an interrupt or FIQ. ; Also, if I choose to disable this, I need to remove the SPSR line from OSTaskStkInit ; in os_cpu_c.c. I DO NOT NEED THESE LINES!!!!! THEY DON"T ALLOW OSCTXSWT TO DO ITS JOB!!!! ; ; ;This file contains definitions for the following functions: ; ;----------------------------------------------------------------------------------- ;Externally defined C functions, with addresses needed here in assembly EXTERN OSTaskSwHook EXTERN OSRunning EXTERN OSTCBHighRdy EXTERN OSTCBCur EXTERN OSPrioCur EXTERN OSPrioHighRdy EXTERN OSIntExit EXTERN OSIntNesting EXTERN OS_CPU_IRQ_ISR_Handler EXTERN OS_CPU_FIQ_ISR_Handler EXTERN MMU_SectionTable; ;Nine public functions, written in assembly, available to C code PUBLIC OS_CPU_SR_Save PUBLIC OS_CPU_SR_Restore PUBLIC OS_CPU_IRQ_ISR PUBLIC OS_CPU_FIQ_ISR PUBLIC OSStartHighRdy PUBLIC OSCtxSw PUBLIC OSIntCtxSw PUBLIC DISABLE_CACHE PUBLIC Return_MMU_Table_ADDR PUBLIC Update_MMU_Table ;---------------------------------------------------------------------------- ; ;1) OS_CPU_SR_Save ; This function disables interrupts and returns the value of the ; Core Program Status Register back to R0 ; ; Note: we may have to enable Supervisor mode in order to set these bits ; to disable interrupts. This would be done with the following lines ; MRS R0, CPSR ; BIC R0, R0, #0x1F ; ORR R0, R0, #0x13 ; MSR CPSR_c, R0 ; ; Also note that the examples in the ARM architecture manual show that ; we only have to write 0x80 to the CPSR, thus setting the I(7) (disables ; IRQ interrupts when it is set) bit. However, if we want to disable ; all interrupts, we should set the F(6) (disables FIQ interrupts ; when it is set) bit as well. See p. 43 of manual (A2-9) ;---------------------------------------------------------------------------- ; SECTION `.text`:CODE:NOROOT(2) CODE32 OS_CPU_SR_Save: MRS R0, CPSR ;Move CPSR to the general purpose register R0 (p.160) ORR R1, R0, #0xC0 ;Set the interrupt disable bit with an ORR MSR CPSR_c, R1 ;Update the control bits in the CPSR, (IRQ now disabled) MRS R1, CPSR ;Confirm that CPSR contains the proper IRQ disable flags AND R1, R1, #0xC0 ;AND R1 with 0x80 and leave it in R1 CMP R1, #0xC0 ;Only 0xC0 should be set BNE OS_CPU_SR_Save ;Not disabled, so try again MOV PC, LR ;Disabled properly so return with the original CPSR in R0 ;---------------------------------------------------------------------------- ; ;2) OS_CPU_SR_Restore() ; This function enables interrupts, or more properly, it restores the value of ; the CSPR register to what it was before interrupts were disabled ; ;----------------------------------------------------------------------------- SECTION `.text`:CODE:NOROOT(2) CODE32 OS_CPU_SR_Restore: MSR CPSR_c, R0 ;Return the control bits of CPSR (uncommenting this allows MOV PC, LR ;the code to work without servicing interrupts ;---------------------------------------------------------------------------- ; ;3) OSStartHighRdy ; OSStartHighRdy() is called by OSStart() to start the highest priority ; task ready to run. It only does half a context switch since we are not ; saving the registers of any previous task ; ; In this function, we must: ; 1) Call user definable OSTaskSwHook(). At this point OSRunning=FALSE ; 2) Set OSRunning = TRUE ; 3) Get the stack pointer of the task to resume (Stack pointer = OSTCBHighRdy->OSTCBStkPtr;0 ; 4) Restore all the processor registers from the new task stack ; 5) Execute a return from interrupt instructions, i.e. load the PC with the new task address ; ; The order of registers can be seen easily from the comments on the right to be ; SPSR, CPSR, R0, R1, R2, ..... R14 (LR), R13 (PC) ; ; NOTE: This function is basically the reverse order of OSTaskStkInit located in os_cpu_c.c ; Also, the author states that #1 and #2 above should actually be done in OSStart(), but ; he made a mistake and it is too late to change it. Boohoo. ; ;---------------------------------------------------------------------------- SECTION `.text`:CODE:NOROOT(2) CODE32 OSStartHighRdy: MSR CPSR_cxsf, #0xDF ;Switch to SYS momde with IRQ & FIQ disabled BL OSTaskSwHook ;Branch with a link to the user defined task switch hook. ;BL causes a branch to the target address and stores a return ;address in the link register (LR = R14) LDR R4, ??OSRunning ;Need to set OSRunning true, but we cannot handle 32 bit address (see AN-1011) MOV R5, #1 ;Put a boolean to set it true STRB R5, [R4] ;Store Register Byte R5 (=0x01) into variable OSRunning LDR R4, ??OSTCBHighRdy ;Load the highest priority task TCB address into R4 (again, this is a 32 bit address) LDR R4, [R4] ;Put the value pointed to into R4 LDR SP, [R4] ;Put the value of R4 into the Stack Pointer LDR R4, [SP], #4 ;Get the new task CPSR MSR CPSR_cxsf, R4 ;Put the value of CPSR back LDR R0, [SP], #4 ;Put R0 back (this was pdata) LDR R1, [SP], #4 ;Put R1 back LDR R2, [SP], #4 ;Put R2 back LDR R3, [SP], #4 ;Put R3 back LDR R4, [SP], #4 ;Put R4 back LDR R5, [SP], #4 ;Put R5 back LDR R6, [SP], #4 ;Put R6 back LDR R7, [SP], #4 ;Put R7 back LDR R8, [SP], #4 ;Put R8 back LDR R9, [SP], #4 ;Put R9 back LDR R10, [SP], #4 ;Put R10 back LDR R11, [SP], #4 ;Put R11 back LDR R12, [SP], #4 ;Put R12 back LDR LR, [SP], #4 ;Put R14=LR back LDR PC, [SP], #4 ;Put R13=PC back, this will start the instructions running again ;---------------------------------------------------------------------------- ; ;4) OSCtxSw ; OsCtxSw() is called when a task-level context switch is issued. This can be from ; a software-interrupt or a TRAP instruction. ; ; To accomplish the context switch, the following must be done ; 1) Save the current processor registers on the current task stack ; 2) Save the current task stack pointer into the current task OS_TCB ; 3) Jump to OSTaskSwHook in case the port needs to extend functionality of the context switch ; 4) Make the pointer of the current OSTCB point to the OSTCB of the task being resumed ; (the new task becomes the current task) ; 5) Copy the new task priority into the current task prioirty (Note in AN1101 4 and 5 are switched) ; 6) Get the stack pointer of the task to resume (retrieved from the new task OSTCB) ; 7) Restore the value of the CPU registers for the task that is being resumed ; 8) ;---------------------------------------------------------------------------- SECTION `.text`:CODE:NOROOT(2) CODE32 OSCtxSw: STR LR, [SP, #-4]! ;Put the return address on the stack, ! updates the value of SP STR LR, [SP, #-4]! ;and decrements it. Both R14 and R13 have the value of LR STR R12, [SP, #-4]! ;Store R12 on the stack STR R11, [SP, #-4]! ;Store R11 on the stack STR R10, [SP, #-4]! ;Store R10 on the stack STR R9, [SP, #-4]! ;Store R9 on the stack STR R8, [SP, #-4]! ;Store R8 on the stack STR R7, [SP, #-4]! ;Store R7 on the stack STR R6, [SP, #-4]! ;Store R6 on the stack STR R5, [SP, #-4]! ;Store R5 on the stack STR R4, [SP, #-4]! ;Store R4 on the stack STR R3, [SP, #-4]! ;Store R3 on the stack STR R2, [SP, #-4]! ;Store R2 on the stack STR R1, [SP, #-4]! ;Store R1 on the stack STR R0, [SP, #-4]! ;Store R0 on the stack MRS R4, CPSR ;Push the current CPSR STR R4, [SP, #-4]! LDR R4, ??OSTCBCur ;Get the current task OSTCB address LDR R5, [R4] ;Put the value it points in R5 STR SP, [R5] ;Store the SP in the OSTCB of the current task BL OSTaskSwHook ;Branch with a Link to OSTaskWwHook LDR R4, ??OSPrioCur ;Load R4 with the current task priority LDR R5, ??OSPrioHighRdy ;Load R5 with the high priority task LDRB R6, [R5] ;Put the high priority in R6 (only need a byte since priority < 64) STRB R6, [R4] ;Store R6 into the current priority (OSPrioCur=OSPrioHighRdy) LDR R4, ??OSTCBCur ;Load R4 with the current task TCB LDR R6, ??OSTCBHighRdy ;Load R6 with the high priority task TCB LDR R6, [R6] ;Put the high priority task in R6 STR R6, [R4] ;Store R6 into the current priority TCB (OSTCBCur=OSTCBHighRdy) LDR SP, [R6] ;Load the new task stack pointer (SP) LDR R4, [SP], #4 ;Get the new task CPSR MSR CPSR_cxsf, R4 ;Put the value of CPSR back LDR R0, [SP], #4 ;Put R0 back (this was pdata) LDR R1, [SP], #4 ;Put R1 back LDR R2, [SP], #4 ;Put R2 back LDR R3, [SP], #4 ;Put R3 back LDR R4, [SP], #4 ;Put R4 back LDR R5, [SP], #4 ;Put R5 back LDR R6, [SP], #4 ;Put R6 back LDR R7, [SP], #4 ;Put R7 back LDR R8, [SP], #4 ;Put R8 back LDR R9, [SP], #4 ;Put R9 back LDR R10, [SP], #4 ;Put R10 back LDR R11, [SP], #4 ;Put R11 back LDR R12, [SP], #4 ;Put R12 back LDR LR, [SP], #4 ;Put R14=LR back LDR PC, [SP], #4 ;Put R13=PC back, this will start the instructions running again ;---------------------------------------------------------------------------- ; ;5) OSIntCtxSw ; OsIntCtxSw() is called by OSIntExit() to perform a context switch from an ISR. ; Because it is called from an ISR, we assume that all the processor registers ; are properly saved onto the interrupted tasks stack (see OSTickISR) ; ; The code is the exact same as the second half of OSCtxSw() ; ;---------------------------------------------------------------------------- SECTION `.text`:CODE:NOROOT(2) CODE32 OSIntCtxSw: BL OSTaskSwHook ;Branch with a Link to OSTaskWwHook LDR R4, ??OSPrioCur ;Load R4 with the current task priority LDR R5, ??OSPrioHighRdy ;Load R5 with the high priority task LDRB R6, [R5] ;Put the high priority in R6 (only need a byte since priority < 64) STRB R6, [R4] ;Store R6 into the current priority (OSPrioCur=OSPrioHighRdy) LDR R4, ??OSTCBCur ;Load R4 with the current task TCB LDR R6, ??OSTCBHighRdy ;Load R6 with the high priority task TCB LDR R6, [R6] ;Put the high priority task in R6 STR R6, [R4] ;Store R6 into the current priority TCB (OSTCBCur=OSTCBHighRdy) LDR SP, [R6] ;Load the new task stack pointer (SP) LDR R4, [SP], #4 ;Get the new task CPSR MSR CPSR_cxsf, R4 ;Put the value of CPSR back LDR R0, [SP], #4 ;Put R0 back (this was pdata) LDR R1, [SP], #4 ;Put R1 back LDR R2, [SP], #4 ;Put R2 back LDR R3, [SP], #4 ;Put R3 back LDR R4, [SP], #4 ;Put R4 back LDR R5, [SP], #4 ;Put R5 back LDR R6, [SP], #4 ;Put R6 back LDR R7, [SP], #4 ;Put R7 back LDR R8, [SP], #4 ;Put R8 back LDR R9, [SP], #4 ;Put R9 back LDR R10, [SP], #4 ;Put R10 back LDR R11, [SP], #4 ;Put R11 back LDR R12, [SP], #4 ;Put R12 back LDR LR, [SP], #4 ;Put R14=LR back LDR PC, [SP], #4 ;Put R13=PC back, this will start the instructions running again ;---------------------------------------------------------------------------- ; ;6) OS_CPU_IRQ_ISR ; This is the interrupt service routine written in assembly code. It is well described in ; AN-1011-PPT.pdf on pages 15-30, AN-1011.pdf on page 29, and the text MicroC-OSII on page 104-105 ; ; It does the following: ; 1) Pushes the working registers (R1-R3) onto the ISR stack because they will be used by the ISR ; 2) Adjusts them to account for offsets ; 3) Save the interrupted tasks registers to its stack ; 4) Increment OSNesting to tell mC/OS-II that we are starting an ISR ; Note: the text says we can do this by either ; a) entering OSIntEnter() ; b) incrementing OSIntNesting (it turns out this is faster than a) ; 5) Check to see if this leve is the first interrupt level ; If it is: immediately save the stack pointer into the current task OS_TC ; 6) Clear the interrupt source so as not to re-enter the ISR ; 7) Switch back to system mode and return to task level code ; 8) Call the uC/OS-II schedule to determine whether this or any other nested interrupt made ; a higher priority task ready to run ; 9) Restore all the registers ; ; NOTE: This command actually could replace a whole bunch of store operations: ; STMFD SP!,{R4-R12,LR} ; Push task's LR,R12-R4 ; ;---------------------------------------------------------------------------- SECTION `.text`:CODE:NOROOT(2) CODE32 OS_CPU_IRQ_ISR: STR R3, [SP, #-4]! ;Put R3 on the IRQ stack STR R2, [SP, #-4]! ;Put R2 on the IRQ stack STR R1, [SP, #-4]! ;Put R1 on the IRQ stack MOV R1, SP ;Save SP in R1 for future use ADD SP, SP, #12 ;Adjust IRQ stack pointer to remove the stacked data SUB R2, LR, #4 ;Adjust return address because CPU saves PC+4 into LR during interrupt MRS R3, SPSR ;Copy CPSR of interrupted task into R3 for future use MSR CPSR_c, #0xDF ;Switch to SYS mode with IRQ & FIQ disabled STR R2, [SP, #-4]! ;Put the return address onto the stack in the place of the return PC STR LR, [SP, #-4]! ;Put the R14_sys LR into R14 STR R12, [SP, #-4]! ;Put R12 on the stack STR R11, [SP, #-4]! ;Put R11 on the stack STR R10, [SP, #-4]! ;Put R10 on the stack STR R9, [SP, #-4]! ;Put R9 on the stack STR R8, [SP, #-4]! ;Put R8 on the stack STR R7, [SP, #-4]! ;Put R7 on the stack STR R6, [SP, #-4]! ;Put R6 on the stack STR R5, [SP, #-4]! ;Put R5 on the stack STR R4, [SP, #-4]! ;Put R4 on the stack LDR R4, [R1], #4 ;Get R1 of interrupted task (SP was pointing at it) into R4 LDR R5, [R1], #4 ;Get R2 of interrupted task into R5 LDR R6, [R1], #4 ;Get R3 of interrupted task into R6 STR R6, [SP, #-4]! ;Put R3 on the stack STR R5, [SP, #-4]! ;Put R2 on the stack STR R4, [SP, #-4]! ;Put R1 on the stack STR R0, [SP, #-4]! ;Put R0 on the stack STR R3, [SP, #-4]! ;Put SPSR of interrupted task into CPSR of stack LDR R0, ??OSIntNesting ;Put OSIntNesting address into R0 LDRB R1, [R0] ;Put value of OSIntNesting into R1 ADD R1, R1, #1 ;Increment OSIntNesting by 1 STRB R1, [R0] ;Put it back in the global location CMP R1, #1 ;Check if OSIntNesting==1 BNE OS_CPU_IRQ_ISR_1 ;Jump to OS_CPU_IRQ_ISR_1 if it is not LDR R4, ??OSTCBCur ;Get the current OS_TCBCur address in R4 LDR R5, [R4] ;Get the value of OS_TCBCur in R5 STR SP, [R5] ;Store the SP of the current task into the OS_TCB of the ISR OS_CPU_IRQ_ISR_1: MSR CPSR_c, #0xD1 ;Switch to IRQ mode with interrupts disabled BL OS_CPU_IRQ_ISR_Handler ;Call the code that will handle the ISR (written in C) MSR CPSR_c, #0x1F ;Switch to SYS mode with interrupts enabled BL OSIntExit ;Change this to 0xDF for disabled interrupts LDR R4, [SP], #4 ;Get the new task CPSR MSR CPSR_cxsf, R4 ;Put the value of CPSR back LDR R0, [SP], #4 ;Put R0 back (this was pdata) LDR R1, [SP], #4 ;Put R1 back LDR R2, [SP], #4 ;Put R2 back LDR R3, [SP], #4 ;Put R3 back LDR R4, [SP], #4 ;Put R4 back LDR R5, [SP], #4 ;Put R5 back LDR R6, [SP], #4 ;Put R6 back LDR R7, [SP], #4 ;Put R7 back LDR R8, [SP], #4 ;Put R8 back LDR R9, [SP], #4 ;Put R9 back LDR R10, [SP], #4 ;Put R10 back LDR R11, [SP], #4 ;Put R11 back LDR R12, [SP], #4 ;Put R12 back LDR LR, [SP], #4 ;Put R14=LR back LDR PC, [SP], #4 ;Put R13=PC back, this will start the instructions running again ;---------------------------------------------------------------------------- ; ;6) OS_CPU_FIQ_ISR ; NOTE: Right now it does exactly what OS_CPU_IRQ_ISR does. This will have to change ; This is the interrupt service routine written in assembly code. It is well described in ; AN-1011-PPT.pdf on pages 15-30, AN-1011.pdf on page 29, and the text MicroC-OSII on page 104-105 ; ; It does the following: ; 1) Pushes the working registers (R1-R3) onto the ISR stack because they will be used by the ISR ; 2) Adjusts them to account for offsets ; 3) Save the interrupted tasks registers to its stack ; 4) Increment OSNesting to tell mC/OS-II that we are starting an ISR ; Note: the text says we can do this by either ; a) entering OSIntEnter() ; b) incrementing OSIntNesting (it turns out this is faster than a) ; 5) Check to see if this leve is the first interrupt level ; If it is: immediately save the stack pointer into the current task OS_TC ; 6) Clear the interrupt source so as not to re-enter the ISR ; 7) Switch back to system mode and return to task level code ; 8) Call the uC/OS-II schedule to determine whether this or any other nested interrupt made ; a higher priority task ready to run ; 9) Restore all the registers ; ;---------------------------------------------------------------------------- SECTION `.text`:CODE:NOROOT(2) CODE32 OS_CPU_FIQ_ISR: STR R3, [SP, #-4]! ;Put R3 on the IRQ stack STR R2, [SP, #-4]! ;Put R2 on the IRQ stack STR R1, [SP, #-4]! ;Put R1 on the IRQ stack MOV R1, SP ;Save SP in R1 for future use ADD SP, SP, #12 ;Adjust IRQ stack pointer to remove the stacked data SUB R2, LR, #4 ;Adjust return address because CPU saves PC+4 into LR during interrupt MRS R3, SPSR ;Copy CPSR of interrupted task into R3 for future use MSR CPSR_cxsf, #0xDF ;Switch to SYS mode with IRQ & FIQ disabled STR R2, [SP, #-4]! ;Put the return address onto the stack in the place of the return PC STR LR, [SP, #-4]! ;Put the R14_sys LR into R14 STR R12, [SP, #-4]! ;Put R12 on the stack STR R11, [SP, #-4]! ;Put R11 on the stack STR R10, [SP, #-4]! ;Put R10 on the stack STR R9, [SP, #-4]! ;Put R9 on the stack STR R8, [SP, #-4]! ;Put R8 on the stack STR R7, [SP, #-4]! ;Put R7 on the stack STR R6, [SP, #-4]! ;Put R6 on the stack STR R5, [SP, #-4]! ;Put R5 on the stack STR R4, [SP, #-4]! ;Put R4 on the stack LDR R4, [R1], #4 ;Get R1 of interrupted task (SP was pointing at it) into R4 LDR R5, [R1], #4 ;Get R2 of interrupted task into R5 LDR R6, [R1], #4 ;Get R3 of interrupted task into R6 STR R6, [SP, #-4]! ;Put R3 on the stack STR R5, [SP, #-4]! ;Put R2 on the stack STR R4, [SP, #-4]! ;Put R1 on the stack STR R0, [SP, #-4]! ;Put R0 on the stack STR R3, [SP, #-4]! ;Put SPSR of interrupted task into CPSR of stack LDR R0, ??OSIntNesting ;Put OSIntNesting address into R0 LDRB R1, [R0] ;Put value of OSIntNesting into R1 ADD R1, R1, #1 ;Increment OSIntNesting by 1 STRB R1, [R0] ;Put it back in the global location CMP R1, #1 ;Check if OSIntNesting==1 BNE OS_CPU_FIQ_ISR_1 ;Jump to OS_CPU_IRQ_ISR_1 if it is not LDR R4, ??OSTCBCur ;Get the current OS_TCBCur address in R4 LDR R5, [R4] ;Get the value of OS_TCBCur in R5 STR SP, [R5] ;Store the SP of the current task into the OS_TCB of the ISR OS_CPU_FIQ_ISR_1: MSR CPSR_c, #0xD2 ;Switch to IRQ mode with interrupts disabled BL OS_CPU_FIQ_ISR_Handler ;Call the code that will handle the ISR (written in C) MSR CPSR_c, #0xDF ;Switch to SYS mode with interrupts disabled BL OSIntExit LDR R4, [SP], #4 ;Get the new task CPSR MSR CPSR_cxsf, R4 ;Put the value of CPSR back LDR R0, [SP], #4 ;Put R0 back (this was pdata) LDR R1, [SP], #4 ;Put R1 back LDR R2, [SP], #4 ;Put R2 back LDR R3, [SP], #4 ;Put R3 back LDR R4, [SP], #4 ;Put R4 back LDR R5, [SP], #4 ;Put R5 back LDR R6, [SP], #4 ;Put R6 back LDR R7, [SP], #4 ;Put R7 back LDR R8, [SP], #4 ;Put R8 back LDR R9, [SP], #4 ;Put R9 back LDR R10, [SP], #4 ;Put R10 back LDR R11, [SP], #4 ;Put R11 back LDR R12, [SP], #4 ;Put R12 back LDR LR, [SP], #4 ;Put R14=LR back LDR PC, [SP], #4 ;Put R13=PC back, this will start the instructions running again ;---------------------------------------------------------------------------- ; ;8) DISABLE_CACHE ; This function disables caching of data memory. We will most likely not ; use this. Rather, we will individually disable caching for pages of ; memory. But for right now it will serve for testing. ; ; For reference, see the PXA270 Developers Guide pg. 1219, Intel XScale ; Developers Guide pg. 87 and 83. ; ;---------------------------------------------------------------------------- ; SECTION `.text`:CODE:NOROOT(2) CODE32 DISABLE_CACHE: MCR P15, 0, R0, C7, C10, 4 ;Drain Write and Fill Buffer in the Cache MRC P15, 0, R0, C1, C0, 0 ;Get the current ARM Control Register in r0 AND R0, R0, #0xFFFFFFFB ;Disable cache by setting ARM Control Reg[2]=0 MCR P15, 0, R0, C1, C0, 0 ;Update the control register ;---------------------------------------------------------------------------- ; ;9) RETURN_MMU_TABLE_ADDR ; This function obtains the address of the MMU Section Table in memory. ; For the PXA270 running on top of LOLO, this happens to be at the address ; 0xA0048000 ; ; The address is returned in R0. To use this function in C, use the ; following syntax ; ; INT32U MMU_Table_Addr; ; MMU_Table_Addr = Return_MMU_Table_ADDR(); ; ;---------------------------------------------------------------------------- ; SECTION `.text`:CODE:NOROOT(2) CODE32 Return_MMU_Table_ADDR: MRC P15, 0, R0, C2, C0, 0 ;Get the value of the Translation Table Address BX LR ;---------------------------------------------------------------------------- ; ;10) UPDATE_MMU_TABLE ; This function updates the MMU Table so that caching is disabled for ; certain areas of memory. ; ; To do this, it obtains the original address for the MMU Section Table that is set ; by the LOLO firmware or program is booted up (0xA0048000). It copies all of the ; entries in this table to a new table at address MMU_SectionTable (this array ; is forced to address 0xA3F00000 because the base address for the translation ; table (Coprocessor Register 15, Cn=C2, Cm=0) should only have bits [31:14] ; written. So it has to be on a 64KB boundary, I believe. ; ; After the copy, it clears the cache the Translation Lookaside Buffer by ; invalidating all of the entries. Then it updates the Translation Table ; Address with MMU_SectionTable[0]. ; ;---------------------------------------------------------------------------- ; SECTION `.text`:CODE:NOROOT(2) CODE32 Update_MMU_Table: MRC P15, 0, R1, C2, C0, 0 ;Get the address of the current Translation Table in R1 LDR R2, =MMU_SectionTable ;Get the address of the new Translation Table in R2 MOV R3, #4096 ;Load 4096 to cover the full 4096 MegaBytes of Address Space MOV R4, #0 ;Load 0 for some reason MOV R6, #0xA3000000 ;Load starting address for non-cached RAM MOV R7, #0xA4000000 ;Load ending address for non-cached RAM mmu_loop: LDR R5, [R1] ;Put the current Translation Table element in R5 CMP R5, R6 ;Check if Table Address is below uncached region BLT cache_memory ;Keep cache enable/disable for this region CMP R5, R7 ;Check if Table Address is above uncached region BGE cache_memory ;Keep cache enable/disable for this region AND R5, R5, #0xFFFFFFF3 ;Disable cache for 0xA3000000-0xA4000000 cache_memory: STR R5, [R2] ;Copy this to the new Translation Table ADDS R1, R1, #4 ;Increment the current Translation Table address ADDS R2, R2, #4 ;Increment the new Translation Table address CMP R3, #0 ;See if loop is finished SUBS R3, R3, #1 ;If not, subtract 1 and jump back to mmu_loop BNE mmu_loop MOV R5, #0 ;Move a zero to MCR p15, 0, R5, C7, C7 ;Flush the D Cache MCR P15, 0, R5, C7, C10, 4 ;Drain Write and Fill Buffer in the Cache MCR P15, 0, R5, C8, C7 ;Invalidate the I and D TLBs LDR R0, =MMU_SectionTable ;Get the address of the new MMU Section Translation Table MCR P15, 0, R0, C2, C0, 0 ;Write the TTB so the CPU knows where the table is BX LR ;-------------------------------------------------------------------------------------------------- ;32 BIT ADDRESSES ;-------------------------------------------------------------------------------------------------- ??OSTCBCur: DC32 OSTCBCur ??OSTCBHighRdy: DC32 OSTCBHighRdy ??OSPrioCur: DC32 OSPrioCur ??OSPrioHighRdy: DC32 OSPrioHighRdy ??OSRunning: DC32 OSRunning ??OSIntNesting DC32 OSIntNesting END