xSemaphoreTake within an ISR

Processor SAMG55 Dev System: Atmel Studio with ASF version of FreeRTOS (version 8.0.1) I am using xSemaphoreTake ( semaphorescreated using xSemaphoreCreateMutex()). These work perfectly except… One particular semaphore protects TWI communications so that, under circumstances where one process has TWI in work and an interrupt is triggerd which also uses TWI, the ISR will not clobber the TWI interface. However, xSemaphoreTake() says that it can’t be called from within an ISR. How can I protect TWI in this case?

xSemaphoreTake within an ISR

As a rule of thumb, no FreeRTOS API functions that don’t end if “FromISR” can be called from an ISR. In this case there is an xSemaphoreTakeFromISR() function – however recent versions of FreeRTOS do not allow mutex semaphores to be used from interrupts. There are a couple of reasons for that, the first is an interrupt cannot block on a semaphore (or anything else for that matter) so if the mutex is not available then it has to just fail gracefully. The second is that mutexes have a priority inheritance mechanism whereby the mutex is associated with the priority of the task that holds it, and that breaks down when it is used from an interrupt as interrupts to not have a task priority. A complete TWI operation is going to be way too long to perform in an interrupt anyway. Normally it is preferable to just use interrupts to manage TWI events. For example, when one transaction is complete use the TWI end interrupt to see if there is another transaction pending – and if there is start that transaction ideally using DMA. If there are no further transactions pending then the TWI operation can just be ended until such time a new transaction is ready.

xSemaphoreTake within an ISR

Richard, thank you. The interrupt being fired is from a peripheral (ADC), signaling that the data is ready to read. Therefore I must service it or lose the data. Investigating this further, I discover that hacking within an ISR may be unnecessary as there’s a FreeRTOS TWI driver. So I added the driver (through Atmel ASF) and it wouldn’t compile. Offered two complaints on freertostwimaster.h, both referring me back to the Freertos Version 8 compatibility chart. I never expected this in a file that’s part of the version 8 code. So I replaced portTickType and xSemaphoreHandle with their Version 8 equivalents, and it compiles. FreeRTOS please note. Onward now to replace my atmel asf TWI driver with the FreeRTOS driver. Hopefully this will fix it?

xSemaphoreTake within an ISR

The interrupt being fired is from a peripheral (ADC), signaling that the data is ready to read. Therefore I must service it or lose the data.
That doesn’t mean you have to read all the data in the interrupt though. Either just start the read operation in the interrupt and let interrupts or DMA complete the read – or somehow signal a task (direct to task notifications are the best method, but not available in the older versions you are using) to unblock the task so the task performs the read.

xSemaphoreTake within an ISR

Richard, I can get to your idea, but for the moment have another issue. After initializing:
bool InitTWI(void) { freertosperipheraloptionst driveroptions = { NULL, 0, 0x0e, TWII2CMASTER, (WAITTXCOMPLETE | WAITRXCOMPLETE) };
flexcom_enable(BOARD_FLEXCOM_TWI);
flexcom_set_opmode(BOARD_FLEXCOM_TWI, FLEXCOM_TWI);
freertos_twi=freertos_twi_master_init(BOARD_BASE_TWI, &driver_options);
if (freertos_twi == NULL)
{
    puts("-E-tTWI master initialization failed.r");
    return(false);
}
twi_set_speed(freertos_twi,TWI_SPEED,F_CPU);
return(true);
}
I then make a write call:
nSuccessCode=freertostwiwritepacket(BOARDBASETWI, &packettx,TWIWRITEPACKET_WAIT);
And here I get an exception fault. Within freertostwiwrite_packet(): the exception is triggered at:
freertosoptionallywaittransfercompletion(…
And that’s within freertostwimaster.c in the freertostwiwritepacketasync() function. I didn’t call async.. so not sure how we got there… Any ideas?

xSemaphoreTake within an ISR

#define freertostwiwritepacket(ptwi, ppacket, blocktimeticks) freertostwiwritepacketasync((ptwi), (ppacket), (blocktime_ticks), (NULL)) is defined in freertostwimaster.h! So, if we’re not supposed to use async, why the dickens is it defined in? This is nuts 🙂

xSemaphoreTake within an ISR

So, if we’re not supposed to use async, why the dickens is it defined in?
Not sure I understand the statement about not supposed to use async. (should also point out that you are looking at very old code from the ASF rather than latest code from the FreeRTOS download)

xSemaphoreTake within an ISR

you are looking at very old code from the ASF rather than latest code from the FreeRTOS download
I’m using what has been published by Atmel/Microchip/whoever. Hmmm… well that’s likely the issue. If they have not updated it, and it’s broken (apparently so) then I’ll get on their ass and see what gives. Thanks for your help!