-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PoC: Add LED toggling interrupt example
Add example firmware for demoing interrupts on Tkey hardware.
- Loading branch information
Showing
5 changed files
with
221 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Uses ../.clang-format | ||
FMTFILES=main.c | ||
.PHONY: fmt | ||
fmt: | ||
clang-format --dry-run --ferror-limit=0 $(FMTFILES) | ||
clang-format --verbose -i $(FMTFILES) | ||
.PHONY: checkfmt | ||
checkfmt: | ||
clang-format --dry-run --ferror-limit=0 --Werror $(FMTFILES) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// This is free and unencumbered software released into the public domain. | ||
// | ||
// Anyone is free to copy, modify, publish, use, compile, sell, or | ||
// distribute this software, either in source code form or as a compiled | ||
// binary, for any purpose, commercial or non-commercial, and by any | ||
// means. | ||
|
||
#define regnum_q0 0 | ||
#define regnum_q1 1 | ||
#define regnum_q2 2 | ||
#define regnum_q3 3 | ||
|
||
#define regnum_x0 0 | ||
#define regnum_x1 1 | ||
#define regnum_x2 2 | ||
#define regnum_x3 3 | ||
#define regnum_x4 4 | ||
#define regnum_x5 5 | ||
#define regnum_x6 6 | ||
#define regnum_x7 7 | ||
#define regnum_x8 8 | ||
#define regnum_x9 9 | ||
#define regnum_x10 10 | ||
#define regnum_x11 11 | ||
#define regnum_x12 12 | ||
#define regnum_x13 13 | ||
#define regnum_x14 14 | ||
#define regnum_x15 15 | ||
#define regnum_x16 16 | ||
#define regnum_x17 17 | ||
#define regnum_x18 18 | ||
#define regnum_x19 19 | ||
#define regnum_x20 20 | ||
#define regnum_x21 21 | ||
#define regnum_x22 22 | ||
#define regnum_x23 23 | ||
#define regnum_x24 24 | ||
#define regnum_x25 25 | ||
#define regnum_x26 26 | ||
#define regnum_x27 27 | ||
#define regnum_x28 28 | ||
#define regnum_x29 29 | ||
#define regnum_x30 30 | ||
#define regnum_x31 31 | ||
|
||
#define regnum_zero 0 | ||
#define regnum_ra 1 | ||
#define regnum_sp 2 | ||
#define regnum_gp 3 | ||
#define regnum_tp 4 | ||
#define regnum_t0 5 | ||
#define regnum_t1 6 | ||
#define regnum_t2 7 | ||
#define regnum_s0 8 | ||
#define regnum_s1 9 | ||
#define regnum_a0 10 | ||
#define regnum_a1 11 | ||
#define regnum_a2 12 | ||
#define regnum_a3 13 | ||
#define regnum_a4 14 | ||
#define regnum_a5 15 | ||
#define regnum_a6 16 | ||
#define regnum_a7 17 | ||
#define regnum_s2 18 | ||
#define regnum_s3 19 | ||
#define regnum_s4 20 | ||
#define regnum_s5 21 | ||
#define regnum_s6 22 | ||
#define regnum_s7 23 | ||
#define regnum_s8 24 | ||
#define regnum_s9 25 | ||
#define regnum_s10 26 | ||
#define regnum_s11 27 | ||
#define regnum_t3 28 | ||
#define regnum_t4 29 | ||
#define regnum_t5 30 | ||
#define regnum_t6 31 | ||
|
||
// x8 is s0 and also fp | ||
#define regnum_fp 8 | ||
|
||
#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \ | ||
.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0)) | ||
|
||
#define picorv32_getq_insn(_rd, _qs) \ | ||
r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011) | ||
|
||
#define picorv32_setq_insn(_qd, _rs) \ | ||
r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011) | ||
|
||
#define picorv32_retirq_insn() \ | ||
r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011) | ||
|
||
#define picorv32_maskirq_insn(_rd, _rs) \ | ||
r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011) | ||
|
||
#define picorv32_waitirq_insn(_rd) \ | ||
r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011) | ||
|
||
#define picorv32_timer_insn(_rd, _rs) \ | ||
r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Copyright (C) 2022, 2023 - Tillitis AB | ||
* SPDX-License-Identifier: GPL-2.0-only | ||
*/ | ||
|
||
int main(void) | ||
{ | ||
while (1) { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* Copyright (C) 2022, 2023 - Tillitis AB | ||
* SPDX-License-Identifier: GPL-2.0-only | ||
*/ | ||
|
||
// Triggers both interrupts, one after the other, in an endless loop. The | ||
// interrupt handler updates the LED color depending on which interrupt | ||
// was triggered. | ||
// The LED color will alterate between blue and green. | ||
// | ||
// | IRQ number | Color | | ||
// |------------|-------| | ||
// | 30 | Blue | | ||
// | 31 | Green | | ||
// | Unexpected | Red | | ||
// | ||
|
||
#include "custom_ops.S" // PicoRV32 custom instructions | ||
|
||
.section ".text.init" | ||
.globl _start | ||
_start: | ||
j init | ||
|
||
|
||
.=0x10 // IRQ handler at fixed address 0x10 | ||
irq_handler: | ||
// PicoRV32 stores the IRQ bitmask in x4. | ||
// If bit 31 is 1: IRQ31 was triggered. | ||
// If bit 30 is 1: IRQ30 was triggered. | ||
irq30_check: | ||
li t4, (1 << 30) | ||
bne x4, t4, irq31_check | ||
call led_blue | ||
call delay | ||
j irq_source_check_done | ||
irq31_check: | ||
li t4, (1 << 31) | ||
bne x4, t4, unexpected_irq | ||
call led_green | ||
call delay | ||
j irq_source_check_done | ||
unexpected_irq: | ||
call led_red | ||
call delay | ||
irq_source_check_done: | ||
picorv32_retirq_insn() // Return from interrupt | ||
|
||
|
||
init: | ||
li t0, 0x3fffffff // IRQ31 & IRQ30 mask | ||
picorv32_maskirq_insn(zero, t0) // Enable IRQs | ||
|
||
irq_trigger_loop: | ||
li t0, 0xe0000000 // IRQ31 trigger address | ||
sw zero, 0(t0) // Raise IRQ by writing to interrupt trigger address. | ||
// Writing any data triggers an interrupt. | ||
|
||
li t0, 0xe1000000 // IRQ30 trigger address | ||
sw zero, 0(t0) // Raise IRQ by writing to interrupt trigger address. | ||
// Writing any data triggers an interrupt. | ||
j irq_trigger_loop | ||
|
||
led_red: | ||
li t2, 0xff000024 | ||
li t3, (1 << 2) | ||
sw t3, 0(t2) | ||
ret | ||
|
||
led_green: | ||
li t2, 0xff000024 | ||
li t3, (1 << 1) | ||
sw t3, 0(t2) | ||
ret | ||
|
||
led_blue: | ||
li t2, 0xff000024 | ||
li t3, (1 << 0) | ||
sw t3, 0(t2) | ||
ret | ||
|
||
delay: | ||
li t5, 0x100000 | ||
delay_dec: | ||
addi t5, t5, -1 | ||
bne t5, zero, delay_dec | ||
ret | ||
|
||
.align 4 // Padding to please makehex.py which requires even 4-byte file | ||
// sizes. | ||
|