tl;dr: see the next post
Right while you’re all asleep, I’m going to start systematically working through this…
Test will be an output from Dr. Octature (i.e. self oscillating filter sine wave) into trigger 1.
The contents of script 1 will vary.
I’ll test for a crash by removing the trigger, replugging the keyboard, and seeing if the front panel button works.
09:51am
Clean checkout of b1817b6.
With an empty script 1, crash after a few minutes.
With TR.P 1 in script 1, either a crash or stuck trigger out.
10:11am
Clean checkout of b1817b6. Plus change to init_teletype.c as follows (make the trigger interrupts use APP_TC_IRQ_PRIORITY):
gpio_enable_pin_interrupt( A07, GPIO_RISING_EDGE);
// PA00-A07
- INTC_register_interrupt( &irq_port0_line0, AVR32_GPIO_IRQ_0, UI_IRQ_PRIORITY);
+ INTC_register_interrupt( &irq_port0_line0, AVR32_GPIO_IRQ_0, APP_TC_IRQ_PRIORITY);
// PA08 - PA15
- INTC_register_interrupt( &irq_port0_line1, AVR32_GPIO_IRQ_0 + (AVR32_PIN_PA08 / 8), UI_IRQ_PRIORITY);
+ INTC_register_interrupt( &irq_port0_line1, AVR32_GPIO_IRQ_0 + (AVR32_PIN_PA08 / 8), APP_TC_IRQ_PRIORITY);
// PB08 - PB15
// INTC_register_interrupt( &irq_port1_line1, AVR32_GPIO_IRQ_0 + (AVR32_PIN_PB08 / 8), UI_IRQ_PRIORITY);
With TR.P 1 in script 1, no crashes until you do something with the keyboard. And even then typing text works fine, but up or down arrow, or tab crashes immediately. Is it the keyboard or is it the screen drawing? Is it possible that we’re deadlocking on APP_TC_IRQ_PRIORITY somehow?
10:17am
Retesting clean checkout of b1817b6.
Can use the keyboard without causing an immediate crash.
10:27am
Clean b18117b6 with the following change (re-enable GPIO interrupt after event is posted).
diff --git a/src/init_teletype.c b/src/init_teletype.c
index 1dca206..2f762c3 100644
--- a/src/init_teletype.c
+++ b/src/init_teletype.c
@@ -77,10 +77,10 @@ __attribute__((__interrupt__))
static void irq_port0_line0(void) {
for(int i=0;i<8;i++) {
if(gpio_get_pin_interrupt_flag(i)) {
- gpio_clear_pin_interrupt_flag(i);
// print_dbg("\r\n # A00");
event_t e = { .type = kEventTrigger, .data = i };
event_post(&e);
+ gpio_clear_pin_interrupt_flag(i);
}
}
}
@@ -89,10 +89,10 @@ static void irq_port0_line0(void) {
__attribute__((__interrupt__))
static void irq_port0_line1(void) {
if(gpio_get_pin_interrupt_flag(NMI)) {
- gpio_clear_pin_interrupt_flag(NMI);
// print_dbg("\r\n ### NMI ### ");
event_t e = { .type = kEventFront, .data = gpio_get_pin_value(NMI) };
event_post(&e);
+ gpio_clear_pin_interrupt_flag(NMI);
}
}
Wow, makes a big difference to responsiveness. Some keyboard input get’s through. Sometimes the screen redraws don’t always complete, is that code re-entrant safe?
With TR.P 1 in script 1, trigger output still gets stuck. Haven’t seen any crashes yet though. Regardless I think this change is worth keeping.
10:37am
As 10.27am, but also commenting out all the IRQ masking in events.c
diff --git a/src/events.c b/src/events.c
index 34bff5a..1b2c241 100644
--- a/src/events.c
+++ b/src/events.c
@@ -52,7 +52,7 @@
// Returns non-zero if an event was available
u8 event_next( event_t *e ) {
u8 status;
- cpu_irq_disable_level(APP_TC_IRQ_PRIORITY);
+ //cpu_irq_disable_level(APP_TC_IRQ_PRIORITY);
// if pointers are equal, the queue is empty... don't allow idx's to wrap!
if ( getIdx != putIdx ) {
@@ -66,7 +66,7 @@ u8 event_next( event_t *e ) {
status = false;
}
- cpu_irq_enable_level(APP_TC_IRQ_PRIORITY);
+ //cpu_irq_enable_level(APP_TC_IRQ_PRIORITY);
return status;
}
@@ -79,7 +79,7 @@ u8 event_post( event_t *e ) {
// print_dbg("\r\n posting event, type: ");
// print_dbg_ulong(e->type);
- cpu_irq_disable_level(APP_TC_IRQ_PRIORITY);
+ //cpu_irq_disable_level(APP_TC_IRQ_PRIORITY);
// increment write idx, posbily wrapping
saveIndex = putIdx;
@@ -93,7 +93,7 @@ u8 event_post( event_t *e ) {
putIdx = saveIndex;
}
- cpu_irq_enable_level(APP_TC_IRQ_PRIORITY);
+ //cpu_irq_enable_level(APP_TC_IRQ_PRIORITY);
if (!status)
print_dbg("\r\n event queue full!");
No crashes. Feels dirty. System responsiveness is impressive though.
10:44am
Combination of 10.27am and 10.11am, but not 10.37am.
e.g. trigger inputs at APP_TC_IRQ_PRIORITY and re-enabling GPIO interrupt after event is posted.
Instant lockup as soon as trigger occurs.
11:10am
As 10.27am, but with aggressive interrupt masking:
diff --git a/src/events.c b/src/events.c
index 34bff5a..3901f12 100644
--- a/src/events.c
+++ b/src/events.c
@@ -52,8 +52,9 @@
// Returns non-zero if an event was available
u8 event_next( event_t *e ) {
u8 status;
- cpu_irq_disable_level(APP_TC_IRQ_PRIORITY);
-
+
+ irqflags_t flags = cpu_irq_save();
+
// if pointers are equal, the queue is empty... don't allow idx's to wrap!
if ( getIdx != putIdx ) {
INCR_EVENT_INDEX( getIdx );
@@ -66,7 +67,8 @@ u8 event_next( event_t *e ) {
status = false;
}
- cpu_irq_enable_level(APP_TC_IRQ_PRIORITY);
+ cpu_irq_restore(flags);
+
return status;
}
@@ -79,8 +81,8 @@ u8 event_post( event_t *e ) {
// print_dbg("\r\n posting event, type: ");
// print_dbg_ulong(e->type);
- cpu_irq_disable_level(APP_TC_IRQ_PRIORITY);
-
+ irqflags_t flags = cpu_irq_save();
+
// increment write idx, posbily wrapping
saveIndex = putIdx;
INCR_EVENT_INDEX( putIdx );
@@ -93,7 +95,7 @@ u8 event_post( event_t *e ) {
putIdx = saveIndex;
}
- cpu_irq_enable_level(APP_TC_IRQ_PRIORITY);
+ cpu_irq_restore(flags);
if (!status)
print_dbg("\r\n event queue full!");
Bomb proof again.
cpu_irq_save implicitly disables all interrupts.
FYI @zebra cpu_irq_save is used in a few places in the ASF, e.g. in sysclk, osc, twi, and usbb_host as well as pdca.
11:15am
Have tested the 11:10am code with also changing the GPIO interrupts to APP_TC_IRQ_PRIORITY (see 10.11am).
Everything is still rock solid (c.f. 10.44am)
Conclusions coming up…
11:40am
Once more for luck, so 11:10am code, plus less aggressive IRQ masking.
But saving and restoring mask status
diff --git a/src/events.c b/src/events.c
index 34bff5a..b7777cb 100644
--- a/src/events.c
+++ b/src/events.c
@@ -52,8 +52,13 @@
// Returns non-zero if an event was available
u8 event_next( event_t *e ) {
u8 status;
- cpu_irq_disable_level(APP_TC_IRQ_PRIORITY);
-
+
+ bool app_tc = cpu_irq_level_is_enabled(APP_TC_IRQ_PRIORITY);
+ bool ui = cpu_irq_level_is_enabled(UI_IRQ_PRIORITY);
+
+ if (app_tc) cpu_irq_disable_level(APP_TC_IRQ_PRIORITY);
+ if (ui) cpu_irq_disable_level(UI_IRQ_PRIORITY);
+
// if pointers are equal, the queue is empty... don't allow idx's to wrap!
if ( getIdx != putIdx ) {
INCR_EVENT_INDEX( getIdx );
@@ -66,7 +71,9 @@ u8 event_next( event_t *e ) {
status = false;
}
- cpu_irq_enable_level(APP_TC_IRQ_PRIORITY);
+ if (app_tc) cpu_irq_enable_level(APP_TC_IRQ_PRIORITY);
+ if (ui) cpu_irq_enable_level(UI_IRQ_PRIORITY);
+
return status;
}
@@ -79,8 +86,12 @@ u8 event_post( event_t *e ) {
// print_dbg("\r\n posting event, type: ");
// print_dbg_ulong(e->type);
- cpu_irq_disable_level(APP_TC_IRQ_PRIORITY);
-
+ bool app_tc = cpu_irq_level_is_enabled(APP_TC_IRQ_PRIORITY);
+ bool ui = cpu_irq_level_is_enabled(UI_IRQ_PRIORITY);
+
+ if (app_tc) cpu_irq_disable_level(APP_TC_IRQ_PRIORITY);
+ if (ui) cpu_irq_disable_level(UI_IRQ_PRIORITY);
+
// increment write idx, posbily wrapping
saveIndex = putIdx;
INCR_EVENT_INDEX( putIdx );
@@ -93,7 +104,8 @@ u8 event_post( event_t *e ) {
putIdx = saveIndex;
}
- cpu_irq_enable_level(APP_TC_IRQ_PRIORITY);
+ if (app_tc) cpu_irq_enable_level(APP_TC_IRQ_PRIORITY);
+ if (ui) cpu_irq_enable_level(UI_IRQ_PRIORITY);
if (!status)
print_dbg("\r\n event queue full!");
Rock solid