diff --git a/arm/isr.s b/arm/isr.s index d857e35..de29bd6 100644 --- a/arm/isr.s +++ b/arm/isr.s @@ -1,27 +1,37 @@ +/* + ARMv7-M Architecture Reference Manual: B1.5 exception model + + Exception entry: + 1) the hardware saves eight 32-bit words to the stack (non FPU context*): + xPSR, ReturnAddress(R15), LR(R14), R12, R3, R2, R1, R0 + * non-FPU => CONTROL[2].FPCA = 0 + 2) EXC_RETURN code (0xFFFFFF??) is loaded into LR (indicates return mode, stack register, saved stack frame type) + + Exception return when EXC_RETURN is loaded into PC via (LDM/POP, LDR PC or BX), e.g. BX LR: + 1) Restores registers from the saved stack frame + 2) Resumes execution at return address (unless Preempted or Tail-chaining) + + Global enable/disable interrupts instructions (priviledged more only): + CPSID i ; Disable interrupts and configurable fault handlers (set PRIMASK) + CPSID f ; Disable interrupts and all fault handlers (set FAULTMASK) + CPSIE i ; Enable interrupts and configurable fault handlers (clear PRIMASK) + CPSIE f ; Enable interrupts and fault handlers (clear FAULTMASK) + */ + .thumb_func nullhandler: - push {lr} - push {r1} ldr r1, =#48 SEMIT r1 mrs r1, ipsr add r1, #48 @ +"0" SEMIT r1 - - pop {r1} - pop {pc} + bx lr .thumb_func faulthandler: - push {lr} - push {r1} - ldr r1, =#70 @ F SEMIT r1 mrs r1, ipsr adds r1, #48 @ +"0" SEMIT r1 - pop {r1} - pop {pc} - -.ltorg + bx lr diff --git a/arm/mcu/ra4m1/dict_mcu.inc b/arm/mcu/ra4m1/dict_mcu.inc index 21b869e..ab433dd 100644 --- a/arm/mcu/ra4m1/dict_mcu.inc +++ b/arm/mcu/ra4m1/dict_mcu.inc @@ -9,3 +9,6 @@ .include "words/at-usart.s" .include "words/dwt.s" + +.include "words/agt.s" +.include "words/icu.s" diff --git a/arm/mcu/ra4m1/isr.s b/arm/mcu/ra4m1/isr.s deleted file mode 100644 index 9186c7e..0000000 --- a/arm/mcu/ra4m1/isr.s +++ /dev/null @@ -1,3 +0,0 @@ -# fall back to nullhandler -.include "arm/isr.s" - diff --git a/arm/mcu/ra4m1/readme.md b/arm/mcu/ra4m1/readme.md index 52fb38e..1b5eb65 100644 --- a/arm/mcu/ra4m1/readme.md +++ b/arm/mcu/ra4m1/readme.md @@ -95,6 +95,7 @@ Note that the only tools needed for this process are AmForth running on the targ ## UNO R4 WIFI * https://docs.arduino.cc/hardware/uno-r4-wifi/ +* https://www.renesas.com/en/products/ra4m1 * https://docs.freenove.com/projects/fnk0096/en/latest/ * https://github.com/arduino/ArduinoCore-renesas * https://www.shumatech.com/web/products/bossa diff --git a/arm/mcu/ra4m1/vectors.s b/arm/mcu/ra4m1/vectors.s index d0a394c..c04c2ed 100644 --- a/arm/mcu/ra4m1/vectors.s +++ b/arm/mcu/ra4m1/vectors.s @@ -4,16 +4,10 @@ IRQ_VECTORS: /* RA4M1 User Manual 13.3.1 Interrupt Vector Table - - 13.2.6 ICU Event Link Setting Register n (IELSRn) - Address: 0x40006300 + 4n : - * IELS[7:0] - ICU Event Link Select ; 0 = disabled, otherwise Event Table 13.4. - * IR[16] - Interrupt Status Flag ; write 0 to clear request - * DTCE[24] - DTC Activation Enable ; activates DTC instead of NVIC - + ARM_ICTR.INTLINESNUM=0 => 32 interrupts */ -.word 0 @ 16: ICU.IELSR0 +.word led_handler @ 16: ICU.IELSR0 = AGT0 .word 0 @ 17: ICU.IELSR1 .word 0 @ 18: ICU.IELSR2 .word 0 @ 19: ICU.IELSR3 diff --git a/arm/mcu/ra4m1/words/agt.s b/arm/mcu/ra4m1/words/agt.s new file mode 100644 index 0000000..18e9200 --- /dev/null +++ b/arm/mcu/ra4m1/words/agt.s @@ -0,0 +1,92 @@ +/* + Use AGT0 timer as an interrupt source. + */ + +/* + RA4M1 Group: User Manual: 23. Low Power Asynchronous General Purpose Timer (AGT) + */ +.equ RA4_AGT0_AGT, 0x40084000 /* AGT0 Counter Register [15:0] R/W */ +.equ RA4_AGT1_AGT, 0x40084100 /* AGT1 Counter Register [15:0] R/W */ +.equ RA4_AGT0_AGTCMA, 0x40084002 /* AGT0 Compare Match A Register [15:0] R/W */ +.equ RA4_AGT1_AGTCMA, 0x40084102 /* AGT1 Compare Match A Register [15:0] R/W */ +.equ RA4_AGT0_AGTCMB, 0x40084004 /* AGT0 Compare Match B Register [15:0] R/W */ +.equ RA4_AGT1_AGTCMB, 0x40084104 /* AGT1 Compare Match B Register [15:0] R/W */ +.equ RA4_AGT0_AGTCR, 0x40084008 /* AGT0 Control Register */ +.equ RA4_AGT1_AGTCR, 0x40084108 /* AGT1 Control Register */ +/* + [0] TSTART Count Start R/W + [1] TCSTF Count Status Flag R + [2] TSTOP Count Forced Stop W=1 + [4] TEDGF Active Edge Judgement Flag R/(W) + [5] TUNDF Undeflow Flag R/(W) + [6] TCMAF Compare Match A Flag R/(W) + [7] TCMBF Compare Match B Flag R/(W) + (W) - only 0 can be written to clear the flag + */ + .equ RA4_AGT0_AGTMR1, 0x40084009 /* AGT0 Mode Register 1 */ + .equ RA4_AGT1_AGTMR1, 0x40084109 /* AGT1 Mode Register 1 */ + /* + [2:0] TMOD Operating mode R/W 000=Timer, 001=Pulse output, 010=Event Counter, 011=Pulse Width Msr, 100=Pulse Period Msr + [3] TEDGPL Edge Polarity R/W + [6:4] TCK Count Source 000=PCKLB, 001=PCKLB/8, 011=PCKLB/2, 100=AGTLCLK, 101=AGT0 underflow, 110=AGTSCLK + */ +.equ RA4_AGT0_AGTMR2, 0x4008400A /* AGT0 Mode Register 2 */ +.equ RA4_AGT1_AGTMR2, 0x4008410A /* AGT1 Mode Register 2 */ +/* + [2:0] CKS AGTLCLK/AGTSCLK divisor R/W n => 1/2^n + [7] LPM Low Power Mode R/W 0=normal, 1=low power + + AGTLCLK is generated by LOCO, AGTSCLCK is not available on UNO R4 (no SOSC) + */ +.equ RA4_AGTO_AGTIOC, 0x4008400C /* AGT0 I/O Control Register */ +.equ RA4_AGT1_AGTIOC, 0x4008410C /* AGT1 I/O Control Register */ +.equ RA4_AGTO_AGTISR, 0x4008400D /* AGT0 Event Pin Select Register */ +.equ RA4_AGT1_AGTISR, 0x4008410D /* AGT1 Event Pin Select Register */ +.equ RA4_AGTO_AGTCMSR, 0x4008400E /* AGT0 Compare Match Function Select Register */ +.equ RA4_AGT1_AGTCMSR, 0x4008410E /* AGT1 Compare Match Function Select Register */ +.equ RA4_AGTO_AGTIOSEL, 0x4008400F /* AGT0 Pin Select Register */ +.equ RA4_AGT1_AGTIOSEL, 0x4008410F /* AGT1 Pin Select Register */ + +.equ INT_AGT0, 0 @ AGT0 interrupt number + +CODEWORD "agt0.init", AGT0_INIT /* ( u -- ) initialize AGT0 as millisecond counter to generate interrupt every u ms */ + @ enable interrupt in NVIC + ldr r0, =ARM_NVIC_ISER + mov r1, 1< ~ 1ms tick + strb r1, [r0] + ldr r0, =RA4_AGT0_AGT + strb TOS, [r0] @ set interrupt period to u1 milliseconds + loadtos + NEXT +END AGT0_INIT + +CODEWORD "agt0.start", AGT0_START /* ( -- ) start the interrupt timer */ + ldr r0, =RA4_AGT0_AGTCR + mov r1, #1 @ TSTART = 1 + str r1, [r0] + NEXT +END AGT0_START + +CODEWORD "agt0.stop", AGT0_STOP /* ( -- ) stop the interrupt timer */ + ldr r0, =RA4_AGT0_AGTCR + mov r1, #1 @ TSTART = 0 + str r1, [r0] + NEXT +END AGT0_STOP + +.thumb_func +led_handler: /* flip the LED state, assume LED is initialized as per led.s */ + ldr r0, =RA4_P102PFS + ldrb r1, [r0] @ read PODR bit + eor r1, #1 @ flip PODR bit + strb r1, [r0] + bx lr diff --git a/arm/mcu/ra4m1/words/icu.s b/arm/mcu/ra4m1/words/icu.s new file mode 100644 index 0000000..7676ee3 --- /dev/null +++ b/arm/mcu/ra4m1/words/icu.s @@ -0,0 +1,17 @@ +/* + RA4M1 Group: User Manual: 13. Interrupt Controller Unit (ICU) + * peripheral function interrupts: 174 sources + * external pin interrupts: 15 sources IRQ0-12,14,15 + * NVIC: 32 sources + * NMI, Oscillation stop, WDT, IWDT, Voltage Monitor 1/2, VBATT + * SRAM parity/ECC, BUS slave/master error, Stack pointer Monitor + * Low Power mode return + */ + +.equ RA4_ICU_IELSR, 0x40006300 /* ICU Event Link Setting Register n (IELSRn) = IELSR + 4n */ +/* + 13.2.6 ICU Event Link Setting Register n (IELSRn) + * IELS[7:0] - ICU Event Link Selec R/W; 0 = disabled, otherwise see 13.3.2 Event Table + * IR[16] - Interrupt Status Flag R/(W); write 0 to clear request + * DTCE[24] - DTC Activation Enable R/W; activates DTC instead of NVIC +*/ \ No newline at end of file diff --git a/arm/system.s b/arm/system.s index c443d16..b85a25b 100644 --- a/arm/system.s +++ b/arm/system.s @@ -1,6 +1,7 @@ -/* ARMv7M System Memory Region 0xE0000000-0xFFFFFFFF - Ref: ARMv7-M Architecture Reference Manual */ - +/* + ARMv7M System Memory Region 0xE0000000-0xFFFFFFFF + Ref: ARMv7-M Architecture Reference Manual +*/ /* B3.2.2 System control and ID registers (System Control Space SCS) */ .equ ARM_CPUID, 0xE000ED00 /* CPUID Base Register */ .equ ARM_ICSR, 0xE000ED04 /* Interrupt Control Register */ @@ -12,7 +13,7 @@ .equ ARM_SHPR2, 0xE000ED1C /* System Handler Priority Register */ .equ ARM_SHPR3, 0xE000ED20 /* System Handler Priority Register */ .equ ARM_SHCSR, 0xE000ED24 /* System Handler Control and State Register */ -.equ ARM_CFSR, 0xE000ED28 /* Configurable Fault Status Register */ +.equ ARM_CFSR, 0xE000ED28 /* Configurable Fault Status Register (UFSAR, BFSR, MMFSR) */ .equ ARM_HFSR, 0xE000ED2C /* HardFault Status Register */ .equ ARM_DFSR, 0xE000ED30 /* Debug Fault Status Register */ .equ ARM_MMFAR, 0xE000ED34 /* MemManage Fault Address Register */ @@ -33,3 +34,18 @@ .equ ARM_NVIC_IABR, 0xE000E300 /* Interrupt Active Bit Registers (0-15), bit per interrupt */ .equ ARM_NVIC_IPR, 0xE000E400 /* Interrupt Priority Registers (0-123), byte per interrupt */ +CODEWORD "int+", INTPLUS /* ( -- ) enable interrupts */ + cpsie i + NEXT +END INTPLUS + +CODEWORD "int-", INTMINUS /* ( -- ) disable interrupts */ + cpsid i + NEXT +END INTPLUS + +CODEWORD "int?", INTQ /* ( -- f ) f == interrupts enabled */ + savetos + mrs TOS, PRIMASK + NEXT +END INTQ