@@ -16,79 +16,62 @@ use esp32_hal::serial::{config::Config, NoRx, NoTx, Serial};
16
16
use esp32_hal:: target;
17
17
use esp32_hal:: Core :: PRO ;
18
18
19
- static TX : spin:: Mutex < Option < esp32_hal:: serial:: Tx < target:: UART0 > > > = spin:: Mutex :: new ( None ) ;
19
+ // !!! Cannot use CriticalSectionSpinLockMutex here, because an NMI is fires from within a locked
20
+ // section which leads to a deadlock in the NMI interrupt handler. This is not a problem in this
21
+ // case as this is a single threaded example. !!!
22
+ static TX : xtensa_lx6:: mutex:: CriticalSectionMutex < Option < esp32_hal:: serial:: Tx < esp32:: UART0 > > > =
23
+ xtensa_lx6:: mutex:: CriticalSectionMutex :: new ( None ) ;
24
+
25
+ fn locked_print ( str : & str ) {
26
+ ( & TX ) . lock ( |tx| {
27
+ let tx = tx. as_mut ( ) . unwrap ( ) ;
28
+
29
+ writeln ! (
30
+ tx,
31
+ " {}, Level: {}" ,
32
+ str ,
33
+ xtensa_lx6:: interrupt:: get_level( )
34
+ )
35
+ . unwrap ( ) ;
36
+ } ) ;
37
+ }
20
38
21
39
#[ interrupt]
22
40
fn FROM_CPU_INTR0 ( ) {
23
- writeln ! (
24
- TX . lock( ) . as_mut( ) . unwrap( ) ,
25
- " FROM_CPU_INTR0, level: {}" ,
26
- xtensa_lx6:: interrupt:: get_level( )
27
- )
28
- . unwrap ( ) ;
41
+ locked_print ( "FROM_CPU_INTR0" ) ;
29
42
clear_software_interrupt ( Interrupt :: FROM_CPU_INTR0 ) . unwrap ( ) ;
30
43
}
31
44
32
45
#[ interrupt]
33
46
fn FROM_CPU_INTR1 ( ) {
34
- writeln ! (
35
- TX . lock( ) . as_mut( ) . unwrap( ) ,
36
- " Start FROM_CPU_INTR1, level: {}" ,
37
- xtensa_lx6:: interrupt:: get_level( )
38
- )
39
- . unwrap ( ) ;
47
+ locked_print ( "Start FROM_CPU_INTR1" ) ;
40
48
interrupt:: set_software_interrupt ( Interrupt :: FROM_CPU_INTR0 ) . unwrap ( ) ;
41
49
interrupt:: set_software_interrupt ( Interrupt :: FROM_CPU_INTR2 ) . unwrap ( ) ;
42
- writeln ! (
43
- TX . lock( ) . as_mut( ) . unwrap( ) ,
44
- " End FROM_CPU_INTR1, level: {}" ,
45
- xtensa_lx6:: interrupt:: get_level( )
46
- )
47
- . unwrap ( ) ;
50
+ locked_print ( "End FROM_CPU_INTR1" ) ;
48
51
clear_software_interrupt ( Interrupt :: FROM_CPU_INTR1 ) . unwrap ( ) ;
49
52
}
50
53
51
54
#[ interrupt]
52
55
fn FROM_CPU_INTR2 ( ) {
53
- writeln ! (
54
- TX . lock( ) . as_mut( ) . unwrap( ) ,
55
- " FROM_CPU_INTR2, level: {}" ,
56
- xtensa_lx6:: interrupt:: get_level( )
57
- )
58
- . unwrap ( ) ;
56
+ locked_print ( "FROM_CPU_INTR2" ) ;
59
57
clear_software_interrupt ( Interrupt :: FROM_CPU_INTR2 ) . unwrap ( ) ;
60
58
}
61
59
62
60
#[ interrupt]
63
61
fn FROM_CPU_INTR3 ( ) {
64
- writeln ! (
65
- TX . lock( ) . as_mut( ) . unwrap( ) ,
66
- " FROM_CPU_INTR3, level: {}" ,
67
- xtensa_lx6:: interrupt:: get_level( )
68
- )
69
- . unwrap ( ) ;
62
+ locked_print ( "FROM_CPU_INTR3" ) ;
70
63
clear_software_interrupt ( Interrupt :: FROM_CPU_INTR3 ) . unwrap ( ) ;
71
64
}
72
65
73
66
#[ interrupt( INTERNAL_SOFTWARE_LEVEL_3_INTR ) ]
74
67
fn software_level_3 ( ) {
75
- writeln ! (
76
- TX . lock( ) . as_mut( ) . unwrap( ) ,
77
- " INTERNAL_SOFTWARE_LEVEL_3_INTR, level: {}" ,
78
- xtensa_lx6:: interrupt:: get_level( )
79
- )
80
- . unwrap ( ) ;
68
+ locked_print ( "INTERNAL_SOFTWARE_LEVEL_3_INTR" ) ;
81
69
clear_software_interrupt ( Interrupt :: FROM_CPU_INTR3 ) . unwrap ( ) ;
82
70
}
83
71
84
72
#[ interrupt( INTERNAL_SOFTWARE_LEVEL_1_INTR ) ]
85
73
fn random_name ( ) {
86
- writeln ! (
87
- TX . lock( ) . as_mut( ) . unwrap( ) ,
88
- " INTERNAL_SOFTWARE_LEVEL_1_INTR, level: {}" ,
89
- xtensa_lx6:: interrupt:: get_level( )
90
- )
91
- . unwrap ( ) ;
74
+ locked_print ( "INTERNAL_SOFTWARE_LEVEL_1_INTR" ) ;
92
75
clear_software_interrupt ( Interrupt :: FROM_CPU_INTR3 ) . unwrap ( ) ;
93
76
}
94
77
@@ -98,13 +81,10 @@ fn other_exception(
98
81
cause : xtensa_lx6_rt:: exception:: ExceptionCause ,
99
82
frame : xtensa_lx6_rt:: exception:: Context ,
100
83
) {
101
- writeln ! (
102
- TX . lock( ) . as_mut( ) . unwrap( ) ,
103
- "Exception {:?}, {:08x?}" ,
104
- cause,
105
- frame
106
- )
107
- . unwrap ( ) ;
84
+ ( & TX ) . lock ( |tx| {
85
+ let tx = tx. as_mut ( ) . unwrap ( ) ;
86
+ writeln ! ( tx, "Exception {:?}, {:08x?}" , cause, frame) . unwrap ( ) ;
87
+ } ) ;
108
88
loop { }
109
89
}
110
90
@@ -156,7 +136,7 @@ fn main() -> ! {
156
136
writeln ! ( uart0, "\n \n Reboot!\n " , ) . unwrap ( ) ;
157
137
158
138
let ( tx, _) = uart0. split ( ) ;
159
- * TX . lock ( ) = Some ( tx) ;
139
+ ( & TX ) . lock ( |tx_locked| * tx_locked = Some ( tx) ) ;
160
140
161
141
interrupt:: enable_with_priority ( PRO , Interrupt :: FROM_CPU_INTR0 , InterruptLevel ( 2 ) ) . unwrap ( ) ;
162
142
interrupt:: enable_with_priority ( PRO , Interrupt :: FROM_CPU_INTR1 , InterruptLevel ( 4 ) ) . unwrap ( ) ;
@@ -167,32 +147,40 @@ fn main() -> ! {
167
147
168
148
// Trigger various software interrupts, because done in an interrupt free section will
169
149
// actually trigger at the end in order of priority
170
- interrupt:: free ( |_| {
171
- writeln ! ( TX . lock( ) . as_mut( ) . unwrap( ) , "Start Trigger Interrupts" , ) . unwrap ( ) ;
150
+ ( & TX ) . lock ( |tx| {
151
+ let tx = tx. as_mut ( ) . unwrap ( ) ;
152
+
153
+ writeln ! ( tx, "Start Trigger Interrupts" , ) . unwrap ( ) ;
172
154
interrupt:: set_software_interrupt ( Interrupt :: FROM_CPU_INTR0 ) . unwrap ( ) ;
173
155
interrupt:: set_software_interrupt ( Interrupt :: FROM_CPU_INTR1 ) . unwrap ( ) ;
174
156
interrupt:: set_software_interrupt ( Interrupt :: FROM_CPU_INTR2 ) . unwrap ( ) ;
175
157
// this one will trigger immediately as level 7 is Non-Maskable Intterupt (NMI)
176
158
interrupt:: set_software_interrupt ( Interrupt :: FROM_CPU_INTR3 ) . unwrap ( ) ;
177
159
interrupt:: set_software_interrupt ( Interrupt :: INTERNAL_SOFTWARE_LEVEL_1_INTR ) . unwrap ( ) ;
178
160
interrupt:: set_software_interrupt ( Interrupt :: INTERNAL_SOFTWARE_LEVEL_3_INTR ) . unwrap ( ) ;
179
- writeln ! ( TX . lock ( ) . as_mut ( ) . unwrap ( ) , "End Trigger Interrupts" , ) . unwrap ( ) ;
161
+ writeln ! ( tx , "End Trigger Interrupts" , ) . unwrap ( ) ;
180
162
} ) ;
181
163
182
164
// Trigger outside of interrupt free section, triggers immediately
183
- writeln ! ( TX . lock( ) . as_mut( ) . unwrap( ) , "Start Trigger Interrupt" , ) . unwrap ( ) ;
165
+ ( & TX ) . lock ( |tx| {
166
+ let tx = tx. as_mut ( ) . unwrap ( ) ;
167
+ writeln ! ( tx, "Start Trigger Interrupt" , ) . unwrap ( ) ;
168
+ } ) ;
184
169
interrupt:: set_software_interrupt ( Interrupt :: FROM_CPU_INTR0 ) . unwrap ( ) ;
185
170
interrupt:: set_software_interrupt ( Interrupt :: FROM_CPU_INTR1 ) . unwrap ( ) ;
186
171
interrupt:: set_software_interrupt ( Interrupt :: FROM_CPU_INTR2 ) . unwrap ( ) ;
187
172
// this one will trigger immediately as level 7 is Non-Maskable Intterupt (NMI)
188
173
interrupt:: set_software_interrupt ( Interrupt :: FROM_CPU_INTR3 ) . unwrap ( ) ;
189
174
interrupt:: set_software_interrupt ( Interrupt :: INTERNAL_SOFTWARE_LEVEL_1_INTR ) . unwrap ( ) ;
190
175
interrupt:: set_software_interrupt ( Interrupt :: INTERNAL_SOFTWARE_LEVEL_3_INTR ) . unwrap ( ) ;
191
- writeln ! ( TX . lock( ) . as_mut( ) . unwrap( ) , "End Trigger Interrupt" , ) . unwrap ( ) ;
192
176
193
- // Trigger a LoadStoreError due to unaligned access in the IRAM
177
+ ( & TX ) . lock ( |tx| {
178
+ let tx = tx. as_mut ( ) . unwrap ( ) ;
179
+ writeln ! ( tx, "End Trigger Interrupt" , ) . unwrap ( ) ;
180
+ writeln ! ( tx, "\n Trigger exception:" , ) . unwrap ( ) ;
181
+ } ) ;
194
182
195
- writeln ! ( TX . lock ( ) . as_mut ( ) . unwrap ( ) , " \n Trigger exception:" , ) . unwrap ( ) ;
183
+ // Trigger a LoadStoreError due to unaligned access in the IRAM
196
184
197
185
#[ link_section = ".rwtext" ]
198
186
static mut IRAM : [ u8 ; 12 ] = [ 0 ; 12 ] ;
@@ -203,8 +191,10 @@ fn main() -> ! {
203
191
204
192
loop {
205
193
sleep ( 1 . s ( ) ) ;
206
- interrupt:: free ( |_| {
207
- writeln ! ( TX . lock( ) . as_mut( ) . unwrap( ) , "Wait for watchdog reset" ) . unwrap ( )
194
+ ( & TX ) . lock ( |tx| {
195
+ let tx = tx. as_mut ( ) . unwrap ( ) ;
196
+
197
+ writeln ! ( tx, "Wait for watchdog reset" ) . unwrap ( )
208
198
} ) ;
209
199
}
210
200
}
0 commit comments