Improvements to Olieman's MODI2C library. Supports calls from IRQ.
Dependents: FreeIMU FreeIMU_external_magnetometer FreeIMU
Fork of MODI2C by
Revision 5:fa0cca8e28b6, committed 2018-03-28
- Comitter:
- tyftyftyf
- Date:
- Wed Mar 28 21:48:20 2018 +0000
- Parent:
- 4:52d01d39ab28
- Commit message:
- wip
Changed in this revision
MODI2C_IRQ.cpp | Show annotated file Show diff for this revision Revisions of this file |
diff -r 52d01d39ab28 -r fa0cca8e28b6 MODI2C_IRQ.cpp --- a/MODI2C_IRQ.cpp Sun Feb 09 14:05:04 2014 +0000 +++ b/MODI2C_IRQ.cpp Wed Mar 28 21:48:20 2018 +0000 @@ -144,27 +144,33 @@ Buffer = &Buffer2; } - //Start user interrupt + // Start user interrupt Buffer->curr->caller->runUserIRQ((I2CData*)Buffer->curr); - + // Free allocated data Buffer->pool.free((I2CData*)Buffer->curr); + // Don't attempt to call startBuffer if another + // thread is about to call it if (Buffer->crit_flag) return; - + + // See if there is any other data to be written osEvent evt = Buffer->queue.get(0); if (evt.status == osEventMessage){ Buffer->curr = (I2CData*)evt.value.p; startBuffer(I2CMODULE); } else{ + // Set curr to NULL to indicate no data being written now Buffer->curr = NULL; _clearISR(I2CMODULE); } } -//Returns true if succeeded, false if buffer is full +// Returns true if succeeded, false if buffer is full bool MODI2C::addBuffer(I2CData *Data, LPC_I2C_TypeDef *I2CMODULE) { - + // check if we are in an interrupt now + // __get_IPSR returns 0 when in Thread Mode, + // return value > 15 when in interrupt int interrupt = __get_IPSR(); I2CBuffer *Buffer; @@ -174,37 +180,49 @@ Buffer = &Buffer2; } + // Hack to update status if(Data->status == NULL) { Data->status = &defaultStatus; - wait_us(1); //I blame the compiler that this is needed + wait_us(1); // I blame the compiler that this is needed } *(Data->status) = 0; + // Attempt to enqueue data to be written if (Buffer->queue.put(Data, 0)!=osOK){ - if (interrupt!=0) - return false; //no waiting in ISR + if (interrupt != 0) + return false; // no waiting in ISR, and buffer is full. + // no choice but to exit, return false for failure else + // wait for buffer to be available (should rarely happen!!) + // an interrupt will free Buffer when other write finishes while (Buffer->queue.put(Data, 0)!=osOK); } - if (interrupt!=0){ + // Check for critical section in if in interrupt + if (interrupt != 0){ if (Buffer->crit_flag_isr) return true; - }else Buffer->crit_flag_isr = true; + } else Buffer->crit_flag_isr = true; + // If no active writing if (Buffer->curr == NULL){ - if (interrupt==0) Buffer->crit_flag = true; + // If we are not in an interrupt, we want to prevent + // bufferHandler interrupt code from messing with Buffer. + if (interrupt == 0) Buffer->crit_flag = true; + + // Get new data to be written osEvent evt = Buffer->queue.get(0); if (evt.status == osEventMessage){ Buffer->curr = (volatile I2CData*)(evt.value.p); - if (interrupt==0) Buffer->crit_flag_isr = false; - if (interrupt==0) Buffer->crit_flag = false; - startBuffer(I2CMODULE); - }else{ - if (interrupt==0) Buffer->crit_flag_isr = false; - if (interrupt==0) Buffer->crit_flag = false; + if (interrupt == 0) Buffer->crit_flag_isr = false; + if (interrupt == 0) Buffer->crit_flag = false; + startBuffer(I2CMODULE); // start transfer + } else { // No data + // "Leave" critical section + if (interrupt == 0) Buffer->crit_flag_isr = false; + if (interrupt == 0) Buffer->crit_flag = false; } - }else{ - if (interrupt==0) Buffer->crit_flag_isr = false; + } else { + if (interrupt == 0) Buffer->crit_flag_isr = false; }