Skip to content

Commit d2af6fa

Browse files
Note IRQ potential race condition
1 parent bdef111 commit d2af6fa

File tree

1 file changed

+7
-10
lines changed

1 file changed

+7
-10
lines changed

cores/esp8266/core_esp8266_i2s.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ typedef struct slc_queue_item {
5353
volatile uint32_t owner : 1; // DMA can change this value
5454
uint32_t * buf_ptr;
5555
struct slc_queue_item * next_link_ptr;
56-
// This is my own way of tracking item ID
57-
volatile uint32_t myid;
5856
} slc_queue_item_t;
5957

6058
typedef struct i2s_state {
@@ -158,13 +156,16 @@ static void ICACHE_RAM_ATTR i2s_slc_queue_append_item(i2s_state_t *ch, uint32_t
158156
}
159157

160158
// This routine is called as soon as the DMA routine has something to tell us. All we
161-
// handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose
159+
// handle here is the *_EOF_INT status, which indicate the DMA has finished a buffer whose
162160
// descriptor has the 'EOF' field set to 1.
163161
void ICACHE_RAM_ATTR i2s_slc_isr(void) {
162+
ETS_SLC_INTR_DISABLE();
163+
// TODO - Seems like there's a chance of missed IRQ notification because the clear happens at least 1 cycle
164+
// after the status read. Not sure if there's a HW way to prevernt this, even atomic SWAP
165+
// won't help since these are 2 separate addresses. Ugh!
164166
uint32_t slc_intr_status = SLCIS;
165167
SLCIC = 0xFFFFFFFF;
166168
if (slc_intr_status & SLCIRXEOF) {
167-
ETS_SLC_INTR_DISABLE();
168169
tx_irqs++;
169170
slc_queue_item_t *finished_item = (slc_queue_item_t *)SLCRXEDA;
170171
memset((void *)finished_item->buf_ptr, 0x00, SLC_BUF_LEN * 4);//zero the buffer so it is mute in case of underflow
@@ -175,20 +176,17 @@ void ICACHE_RAM_ATTR i2s_slc_isr(void) {
175176
if (tx->callback) {
176177
tx->callback();
177178
}
178-
ETS_SLC_INTR_ENABLE();
179179
}
180180
if (slc_intr_status & SLCITXEOF) {
181-
ETS_SLC_INTR_DISABLE();
182181
rx_irqs++;
183182
slc_queue_item_t *finished_item = (slc_queue_item_t *)SLCTXEDA;
184183
finished_item->owner = 1; // Or else RX just stops
185-
finished_item->myid++;
186184
i2s_slc_queue_append_item(rx, finished_item->buf_ptr);
187185
if (rx->callback) {
188186
rx->callback();
189187
}
190-
ETS_SLC_INTR_ENABLE();
191188
}
189+
ETS_SLC_INTR_ENABLE();
192190
}
193191

194192
void i2s_set_callback(void (*callback) (void)){
@@ -213,14 +211,13 @@ static void _alloc_channel(i2s_state_t *ch) {
213211
ch->slc_items[x].blocksize = SLC_BUF_LEN * 4;
214212
ch->slc_items[x].buf_ptr = (uint32_t*)&ch->slc_buf_pntr[x][0];
215213
ch->slc_items[x].next_link_ptr = (x<(SLC_BUF_CNT-1))?(&ch->slc_items[x+1]):(&ch->slc_items[0]);
216-
ch->slc_items[x].myid = 0;
217214
}
218215
}
219216
#if 0
220217
void dumprx()
221218
{
222219
for (int i=0; i<SLC_BUF_CNT; i++) {
223-
printf("%d: %d %d %d %d %d %d %p %p\n", i, rx->slc_items[i].myid, rx->slc_items[i].owner, rx->slc_items[i].eof, rx->slc_items[i].sub_sof, rx->slc_items[i].datalen, rx->slc_items[i].blocksize,
220+
printf("%d: %d %d %d %d %d %d %p %p\n", i, 0, rx->slc_items[i].owner, rx->slc_items[i].eof, rx->slc_items[i].sub_sof, rx->slc_items[i].datalen, rx->slc_items[i].blocksize,
224221
rx->slc_items[i].buf_ptr, rx->slc_items[i].next_link_ptr);
225222
}
226223
}

0 commit comments

Comments
 (0)