Closed robzed closed 1 year ago
Thanks for catching this! Just tested it and byte-access indeed does not work for these registers.
I have come up with and tested the following code, and it appears to work (but who knows if zeptoforth will stop working once I add it and actually build rather than just exercising things from the REPL):
begin-module interrupt-internal
\ Create an address for a priority index
: NVIC_IPR_IP_addr ( u -- addr ) 3 bic NVIC_IPR_Base + ;
\ Create a bitshift for a priority index
: NVIC_IPR_IP_shift ( u -- bitshift ) 3 and 3 lshift ;
commit-flash
\ Create a mask for a priority index
: NVIC_IPR_IP_mask ( u -- mask ) NVIC_IPR_IP_shift $FF swap lshift ;
end-module> import
commit-flash
\ Set NVIC interrupt priority register field
: NVIC_IPR_IP! ( priority u -- )
dup NVIC_IPR_IP_addr dup >r @ over NVIC_IPR_IP_mask bic
swap NVIC_IPR_IP_shift rot $FF and swap lshift or r> !
;
\ Get NVIC interrupt priority register field
: NVIC_IPR_IP@ ( u -- priority )
dup NVIC_IPR_IP_addr @ over NVIC_IPR_IP_mask and
swap NVIC_IPR_IP_shift rshift
;
TEST RESULTS
zeptoforth_full-1.1.0.2.uf2 Built for rp2040, version 1.1.0.2, on Sun Sep 17 08:40:41 PM CDT 2023
#include irq_info.fth
irq_priorities
: set_priority ( irq level0-3 -- )
6 lshift swap NVIC_IPR_IP!
;
irq_priorities
0 0 set_priority
1 1 set_priority
2 2 set_priority
3 3 set_priority
4 3 set_priority
5 2 set_priority
6 1 set_priority
7 0 set_priority
8 3 set_priority
#9 2 set_priority
#10 1 set_priority
#11 0 set_priority
irq_priorities
#12 3 set_priority
#13 1 set_priority
#14 2 set_priority
#15 2 set_priority
#16 1 set_priority
#17 2 set_priority
#18 3 set_priority
#19 0 set_priority
#20 1 set_priority
irq_priorities
0 NVIC_IPR_IP@ u.
interrupt import
$c0804000 NVIC_IPR_Base !
0 NVIC_IPR_IP@ u.
1 NVIC_IPR_IP@ u.
2 NVIC_IPR_IP@ u.
3 NVIC_IPR_IP@ u.
irq_priorities
interrupt import ok
decimal ok
: .HEX ( n cnt -- ) HEX <# 0 DO # LOOP #> TYPE DECIMAL ; ok
: .B 0 2 .HEX ; ok
: .H 0 4 .HEX ; ok
: .L 0 8 .HEX ; ok
: irq_priorities ok
cr ." 0=high, 3=low" cr ok
." mem man fault " SHPR1_PRI_4@ 6 rshift . cr ok
." bus fault " SHPR1_PRI_5@ 6 rshift . cr ok
." usage fault " SHPR1_PRI_6@ 6 rshift . cr ok
." SVCall " SHPR2_PRI_11@ 6 rshift . cr ok
." PendSV " SHPR3_PRI_14@ 6 rshift . cr ok
." systick " SHPR3_PRI_15@ 6 rshift . cr ok
32 0 do ok
I ." IRQ" . I NVIC_IPR_IP@ 6 rshift . 3 spaces ok
I 3 and 3 = IF cr THEN ok
loop ok
." Summary" cr ok
NVIC_IPR_Base ok
8 0 do ok
." IRQ" I 4 * 3 + . I 4 * . space dup @ .L 4 + cr ok
loop drop ok
; ok
: .bitpos ( data -- ) ok
32 0 do ok
dup 1 rshift swap 1 and if ." 1" else ." _" then ok
loop ok
drop ok
; ok
: irq_status ok
cr ." " #10 0 do SPACE SPACE loop #22 0 do I #10 / 1+ . loop ok
cr ." " #32 0 do I #10 MOD . loop ok
cr ." pending" NVIC_ISPR_Base @ .bitpos ok
cr ." enabled" NVIC_ISER_Base @ .bitpos ok
cr ." NMI proc0 " $40004000 @ .L ok
cr ." NMI proc1 " $40004004 @ .L ok
cr ok
cr ." 1=Low Level, 2=High Level, 4=Edge Low, 8=Edge High" ok
cr ." INTR07-00 " $400140f0 @ .L \ .bitpos8 ok
cr ." INTR15-08 " $400140f4 @ .L \ .bitpos8 ok
cr ." INTR23-16 " $400140f8 @ .L \ .bitpos8 ok
cr ." INTR31-24 " $400140fc @ .L \ .bitpos8 ok
cr ." INTE07-00 " $40014100 @ .L \ .bitpos8 ok
cr ." INTE15-08 " $40014104 @ .L \ .bitpos8 ok
cr ." INTE23-16 " $40014108 @ .L \ .bitpos8 ok
cr ." INTE31-24 " $4001410c @ .L \ .bitpos8 ok
cr ." INTS07-00 " $40014120 @ .L \ .bitpos8 ok
cr ." INTS15-08 " $40014124 @ .L \ .bitpos8 ok
cr ." INTS23-16 " $40014128 @ .L \ .bitpos8 ok
cr ." INTS31-24 " $4001412c @ .L \ .bitpos8 ok
cr ok
; ok
: irq_source ok
cr ." 0 TIMER_IRQ_0 6 XIP_IRQ 12 DMA_IRQ_1 18 SPI0_IRQ 24 I2C1_IRQ" ok
cr ." 1 TIMER_IRQ_1 7 PIO0_IRQ_0 13 IO_IRQ_BANK0 19 SPI1_IRQ 25 RTC_IRQ" ok
cr ." 2 TIMER_IRQ_2 8 PIO0_IRQ_1 14 IO_IRQ_QSPI 20 UART0_IRQ" ok
cr ." 3 TIMER_IRQ_3 9 PIO1_IRQ_0 15 SIO_IRQ_PROC0 21 UART1_IRQ" ok
cr ." 4 PWM_IRQ_WRAP 10 PIO1_IRQ_1 16 SIO_IRQ_PROC1 22 ADC_IRQ_FIFO" ok
cr ." 5 USBCTRL_IRQ 11 DMA_IRQ_0 17 CLOCKS_IRQ 23 I2C0_IRQ" ok
cr ok
; ok
irq_priorities
0=high, 3=low
mem man fault 0
bus fault 0
usage fault 0
SVCall 0
PendSV 3
systick 1
IRQ0 0 IRQ1 0 IRQ2 0 IRQ3 0
IRQ4 0 IRQ5 0 IRQ6 0 IRQ7 0
IRQ8 0 IRQ9 0 IRQ10 0 IRQ11 0
IRQ12 0 IRQ13 0 IRQ14 0 IRQ15 0
IRQ16 0 IRQ17 0 IRQ18 0 IRQ19 0
IRQ20 0 IRQ21 0 IRQ22 0 IRQ23 0
IRQ24 0 IRQ25 0 IRQ26 0 IRQ27 0
IRQ28 0 IRQ29 0 IRQ30 0 IRQ31 0
Summary
IRQ3 0 00000000
IRQ7 4 00000000
IRQ11 8 00000000
IRQ15 12 00000000
IRQ19 16 00000000
IRQ23 20 00000000
IRQ27 24 00000000
IRQ31 28 00000000
ok
: set_priority ( irq level0-3 -- ) ok
6 lshift swap NVIC_IPR_IP! ok
; ok
irq_priorities
0=high, 3=low
mem man fault 0
bus fault 0
usage fault 0
SVCall 0
PendSV 3
systick 1
IRQ0 0 IRQ1 0 IRQ2 0 IRQ3 0
IRQ4 0 IRQ5 0 IRQ6 0 IRQ7 0
IRQ8 0 IRQ9 0 IRQ10 0 IRQ11 0
IRQ12 0 IRQ13 0 IRQ14 0 IRQ15 0
IRQ16 0 IRQ17 0 IRQ18 0 IRQ19 0
IRQ20 0 IRQ21 0 IRQ22 0 IRQ23 0
IRQ24 0 IRQ25 0 IRQ26 0 IRQ27 0
IRQ28 0 IRQ29 0 IRQ30 0 IRQ31 0
Summary
IRQ3 0 00000000
IRQ7 4 00000000
IRQ11 8 00000000
IRQ15 12 00000000
IRQ19 16 00000000
IRQ23 20 00000000
IRQ27 24 00000000
IRQ31 28 00000000
ok
0 0 set_priority ok
1 1 set_priority ok
2 2 set_priority ok
3 3 set_priority ok
4 3 set_priority ok
5 2 set_priority ok
6 1 set_priority ok
7 0 set_priority ok
8 3 set_priority ok
#9 2 set_priority ok
#10 1 set_priority ok
#11 0 set_priority ok
irq_priorities
0=high, 3=low
mem man fault 0
bus fault 0
usage fault 0
SVCall 0
PendSV 3
systick 1
IRQ0 0 IRQ1 1 IRQ2 2 IRQ3 3
IRQ4 3 IRQ5 2 IRQ6 1 IRQ7 0
IRQ8 3 IRQ9 2 IRQ10 1 IRQ11 0
IRQ12 0 IRQ13 0 IRQ14 0 IRQ15 0
IRQ16 0 IRQ17 0 IRQ18 0 IRQ19 0
IRQ20 0 IRQ21 0 IRQ22 0 IRQ23 0
IRQ24 0 IRQ25 0 IRQ26 0 IRQ27 0
IRQ28 0 IRQ29 0 IRQ30 0 IRQ31 0
Summary
IRQ3 0 C0804000
IRQ7 4 004080C0
IRQ11 8 004080C0
IRQ15 12 00000000
IRQ19 16 00000000
IRQ23 20 00000000
IRQ27 24 00000000
IRQ31 28 00000000
ok
#12 3 set_priority ok
#13 1 set_priority ok
#14 2 set_priority ok
#15 2 set_priority ok
#16 1 set_priority ok
#17 2 set_priority ok
#18 3 set_priority ok
#19 0 set_priority ok
#20 1 set_priority ok
irq_priorities
0=high, 3=low
mem man fault 0
bus fault 0
usage fault 0
SVCall 0
PendSV 3
systick 1
IRQ0 0 IRQ1 1 IRQ2 2 IRQ3 3
IRQ4 3 IRQ5 2 IRQ6 1 IRQ7 0
IRQ8 3 IRQ9 2 IRQ10 1 IRQ11 0
IRQ12 3 IRQ13 1 IRQ14 2 IRQ15 2
IRQ16 1 IRQ17 2 IRQ18 3 IRQ19 0
IRQ20 1 IRQ21 0 IRQ22 0 IRQ23 0
IRQ24 0 IRQ25 0 IRQ26 0 IRQ27 0
IRQ28 0 IRQ29 0 IRQ30 0 IRQ31 0
Summary
IRQ3 0 C0804000
IRQ7 4 004080C0
IRQ11 8 004080C0
IRQ15 12 808040C0
IRQ19 16 00C08040
IRQ23 20 00000040
IRQ27 24 00000000
IRQ31 28 00000000
ok
0 NVIC_IPR_IP@ u. 0 ok
interrupt import ok
$c0804000 NVIC_IPR_Base ! ok
0 NVIC_IPR_IP@ u. 0 ok
1 NVIC_IPR_IP@ u. 64 ok
2 NVIC_IPR_IP@ u. 128 ok
3 NVIC_IPR_IP@ u. 192 ok
irq_priorities
0=high, 3=low
mem man fault 0
bus fault 0
usage fault 0
SVCall 0
PendSV 3
systick 1
IRQ0 0 IRQ1 1 IRQ2 2 IRQ3 3
IRQ4 3 IRQ5 2 IRQ6 1 IRQ7 0
IRQ8 3 IRQ9 2 IRQ10 1 IRQ11 0
IRQ12 3 IRQ13 1 IRQ14 2 IRQ15 2
IRQ16 1 IRQ17 2 IRQ18 3 IRQ19 0
IRQ20 1 IRQ21 0 IRQ22 0 IRQ23 0
IRQ24 0 IRQ25 0 IRQ26 0 IRQ27 0
IRQ28 0 IRQ29 0 IRQ30 0 IRQ31 0
Summary
IRQ3 0 C0804000
IRQ7 4 004080C0
IRQ11 8 004080C0
IRQ15 12 808040C0
IRQ19 16 00C08040
IRQ23 20 00000040
IRQ27 24 00000000
IRQ31 28 00000000
ok
Test results show that the NVIC_IPR_IP! and NVIC_IPR_IP@ perform as expected with no unexpected results.
Happy to close.
I have problems setting the interrupt priority registers.
RP2040 Datasheet says:
Note the last line.
I suspect using c! and c@ will be problematic.
This might do the job, although it's rather 'baroque' and overly complex for a Forth word... Perhaps there is a simpler method, or at least a way of refactoring it into a set of smaller words?