FreeRTOS & PIC24EP & Correct interrupt handling - interrupt

I've been using FreeRTOS for a while now on my project and I have to say I love it.
Tough i'm facing a bug which is killing me.
My code contains a large amount of code, about 80 files and use several microchip stack and run about 10 tasks.
The problem is that about 2-3 times a day, the chip will go into an address error interrupt and I haven't really been able to find out what was the source of the problem.
I believe that this error occur at the moment of an interrupt because I've been able to reduce the occurrence of the crash be using DMA transfer in one UART which reduce the interruption by a factor of 80.
I've been reading a lot of example and and forum thread about it, but it seem to always have different approach about how to handle interrupt, whether use or not the taskYield, specifically on the PIC24EP.
An other point is the interrupt nesting. It is currently enabled and I haven't tested disabled. I've seen some thread about it without really an answer whether it should be kept enable or not.
This is the way I'm currently handling my DMA interrupt. I use a queue instead of a semaphore for previous code compatibility bot it does the same job.
void attribute((interrupt, auto_psv)) _DMA1Interrupt(void)
{
char val = 55;
IFS0bits.DMA1IF = 0; // Clear the DMA1 Interrupt Flag
xQueueSendFromISR( RS485_Queue, &val, NULL );
}
Some example from the RTOS library shows no task yield after the interrupt.
Shall I add the yield into each interrupt ?
void attribute((interrupt, auto_psv)) _DMA1Interrupt(void)
{
char val = 55;
portBASE_TYPE xTaskWoken;
IFS0bits.DMA1IF = 0; // Clear the DMA1 Interrupt Flag
xQueueSendFromISR( RS485_Queue, &val, &xTaskWoken);
if( xTaskWoken )
taskYIELD();
}
Shall I disable Nested interrupt ?
Shall I add more stack space in my tasks ?
I'm not a specialist of processor stack and the way RTOS works at the stack level.
If two interrupt happens at the same time then the current running task would need bigger stack size ? Might my problem be related of having two interrupt (or more) at the same time and having nested interrupt use more task space than it is actually defined ?
Thanks!
Edit:
Problem solved, and seem actually I'm not the only one to have gone into that problem as unfortunately it doesn't seem to appear on the documentation or the code example but only in some webpage of freertos that needs to be dug up.
The interrupt using FreeRTOS Kernel should not have a priority higher than the configKERNEL_INTERRUPT_PRIORITY which has default value of 1, while interrupt on microchip have default value of 3. This means using interrupt at their default priority level will lead to sporadic trap error.

Related

How to get data from an interrupt into a task-based system?

I am preparing for an embedded systems interview and was given this question as one of the questions to prepare with.
From my research, I learned that interrupts are called by a piece of hardware when there is an important issue that the OS should take care of and because of this data cannot be returned by an interrupt.
However, I didn't find any definitive information about how interrupts work with a task-based system. Is this a trick question about interrupts or is there a method to get data from them?
It is true that an interrupt cannot "return" data to a caller, because there is no caller. Interrupts are triggered by asynchronous events independent of normal program flow.
However it is possible for an interrupt pass data to a thread/task context (or even other interrupts) via shared memory or inter-process communication (IPC) such as a message queue, pipe or mailbox. Such data exchange must be non-blocking. So for example, if a message queue is full, the ISR may not wait on the queue to become available - it must baulk and discard the data.
interrupts are called [...] when there is an important issue that the OS should take care of [...]
It is not about "importance" it is about timliness, determinusm, meeting real-time deadlines, and dealing with data before buffers or FIFOs are overrun for example. There need not even be an OS, ant interrupts are generally application specific and not an issue for the OS at all.
I didn't find any definitive information about how interrupts work with a task-based system.
Perhaps you need to hone your research technique (or Google Fu). https://www.google.com/search?q=rtos+interrupt+communication
It's not a trick question. The problem is the same whether you have a "task-based system" (RTOS) or not:
Interrupts will happen at random times, relative to your main program. I.e. you could be calculating something like a = b + c and the interrupt could happen at a time where b is loaded into a register, but before c is.
Interrupts execute in a different context from your main program. Depending on the architecture, you could have a separate stack, for example.
Given the above, the interrupt service routines cannot take any parameters and cannot return any values. The way to pass data in and out of an ISR is to use shared memory (e.g. a global variable).
There are several ways to get data from interrupt:
Using queue or similar approach (implement in freeRTOS). NOTE: there is special API for ISR.
Using global variable. For this way you need to care about consistency of data because interrupt can happen anytime.
...

Is this a safe way to disable interrupts on PIC24?

I am working on a project that uses a Microchip PIC24FJ256GA702. For several days I have been looking for an intermittent bug with some UART code. It uses an interrupt service routine (ISR) to transmit a buffer named char txBuff[] and its length int txLen.
In the main (i.e. not ISR) code I occasionally access the buffer to add bytes or to see how many bytes are left to transmit. To ensure the main code sees a clean copy of the buffer it has a critical section in the form:
Disable interrupts
Read and write 'txBuff' and its length 'txLen'
Enable interrupt
There are several ways to disable an ISR on this PIC. Including: Use the DISI instruction, or clear the GIE bit, or alter interrupt priority levels.
But I have chosen to clear the interrupt to enable bit of the specific interrupt bit in IECx. In this case, it is IEC1bits.U2TXIE because I am using UART2. I do this because it is easy, it does not disable unrelated interrupts, and it has always worked well in my other projects. So in C, the critical section is:
IEC1bits.U2TXIE = 0;
copyOfTxLen = txLen;
...
IEC1bits.U2TXIE = 1;
And the disassembly listing starts:
BCLR 0x9B, #7 // disable interrupt
MOV txLen, W1 // read txLen
...
The problem: I am now fairly certain that the ISR occasionally gets called during read txLen such that copyOfTxLen ends up being the value of txLen before the ISR was called, but the remainder of the critical section sees variables in the state they are after the ISR is called.
The question: Is my code faulty? If so how can the fault be avoided?
Some background:
UART is running at a high speed (250 kBaud) with a PIC24 clock of 8 MHz, a byte every 160 instructions, so the ISR is quite busy and this I think increases the chances of hitting a race condition compared to my previous projects.
I see dsPIC33/PIC24 Family Reference Manual / Interrupts, section 2.3.1 Note 2 says "There is one cycle delay between clearing the GIE bit and the interrupts being disabled." Now this refers to GIE, not U2TXIE and I am not sure whether it would cause a problem like I am seeing because the MOV instruction is a 2 cycle instruction. But nevertheless, it looks like a cunning way to trap unwary programmers.
If I try to debug it or add any debug code the already very intermittent problem goes away (feels like a race condition). I don't want to just add some NOPs without knowing exactly why I should because race conditions always bite you back unless you actually fix them.
The code in the question is faulty.
To fix it, wrap expressions intended to disable interrupts such as IEC1bits.U2TXIE = 0 in a macro like this:
__write_to_IEC(IEC1bits.U2TXIE = 0);
XC16 compiler release notes says:
__write_to_IEC(X) - a macro that wraps the expression X with an appropriate number of nop instructions to ensure that the write to the IEC register has taken effect before the program executes. For example, __write_to_IEC(IEC0bits.T1IE = 0); will not progress until the device has disabled the interrupt enable bit for T1 (Timer1).
In p24FJ256GA702.h that is provided with the XC16 compiler, the macro is defined:
#define __write_to_IEC(X) \
( (void)(X), \
__builtin_nop() \
)
So despite not being mentioned anywhere in the PIC24FJ256GA705 FAMILY datasheet or in the separate Interrupts document, it seems clear that a single NOP is required here on this PIC.
Update: I find exactly the same issue on the dsPIC33EP256MU806 (dsPIC33E family) which requires two NOP instructions.

How to best convert legacy polling embedded firmware architecture into an event driven one?

I've got a family of embedded products running a typical main-loop based firmware with 150+k lines of code. A load of complex timing critical features is realized by a combination of hardware interrupt handlers, timer polling and protothreads (think co-routines). Actually protothreads are polling well and "only" are syntactic sugar to mimic pseudo-parallel scheduling of multiple threads (endless loops). I add bugfixes and extensions to the firmware all the time. There are about 30k devices of about 7 slightly different hardware types and versions out in the field.
For a new product-family member I need to integrate an external FreeRTOS-based project on the new product only while all older products need to get further features and improvements.
In order to not have to port the whole complex legacy firmware to FreeRTOS with all the risk of breaking perfectly fine products I plan to let the old firmware run inside a FreeRTOS task. On the older products the firmware shall still not run without FreeRTOS. Inside the FreeRTOS task the legacy firmware would consume all available processor time because its underlying implementation scheme is polling based. Due to the fact that its using prothreads (timer and hardware polling based behind the scenes) and polls on a free-running processor counter register I hope that I can convert the polling into a event driven behavior.
Here are two examples:
// first example: do something every 100 ms
if (GET_TICK_COUNT() - start > MS(100))
{
start = GET_TICK_COUNT();
// do something every 100 ms
}
// second example: wait for hardware event
setup_hardware();
PT_WAIT_UNTIL(hardware_ready(), pt);
// hardware is ready, do something else
So I got the impression that I can convert these 2 programming patterns (e.g. through macro magic and FreeRTOS functionality) into an underlying event based scheme.
So now my question: has anybody done such a thing already? Are there patterns and or best practices to follow?
[Update]
Thanks for the detailed responses. Let me comment some details: My need is to combine a "multithreading-simulation based legacy firmware (using coo-routines implementation protothreads)" and a FreeRTOS based project being composed of a couple of interacting FreeRTOS tasks. The idea is to let the complete old firmware run in its own RTOS task besides the other new tasks. I'm aware of RTOS principles and patterns (pre-emption, ressource sharing, blocking operations, signals, semaphores, mutexes, mailboxes, task priorities and so forth). I've planed to base the interaction of old and new parts exactly on these mechanisms. What I'm asking for is 1) Ideas how to convert the legacy firmware (150k+ LOC) in a semi-automated way so that the busy-waiting / polling schemes I presented above are using either the new mechanisms when run inside the RTOS tasks or just work the old way when build and run as the current main-loop-kind of firmware. A complete rewrite / full port of the legacy code is no option. 2) More ideas how to teach the old firmware implementation that is used to have full CPU resources on its hands to behave nicely inside its new prison of a RTOS task and not just consume all CPU cycles available (when given the highest priority) or producing new large Real Time Latencies when run not at the highest RTOS priority.
I guess here is nobody who already has done such a very special tas. So I just have to do the hard work and solve all the described issues one after another.
In an RTOS you create and run tasks. If you are not running more than one task, then there is little advantage in using an RTOS.
I don't use FreeRTOS (but have done), but the following applies to any RTOS, and is pseudo-code rather then FreeRTOS API specific - many details such as task priorities and stack allocation are deliberately missing.
First in most simple RTOS, including FreeRTOS, main() is used for hardware initialisation, task creation, and scheduler start:
int main( void )
{
// Necessary h/w & kernel initialisation
initHardware() ;
initKernel() ;
// Create tasks
createTask( task1 ) ;
createTask( task2 ) ;
// Start scheduling
schedulerStart() ;
// schedulerStart should not normally return
return 0 ;
}
Now let us assume that your first example is implemented in task1. A typical RTOS will have both timer and delay functions. The simplest to use is a delay, and this is suitable when the periodic processing is guaranteed to take less than one OS tick period:
void task1()
{
// do something every 100 ms
for(;;)
{
delay( 100 ) ; // assuming 1ms tick period
// something
...
}
}
If the something takes more than 1ms in this case, it will not be executed every 100ms, but 100ms plus the something execution time, which may itself be variable or non-deterministic leading to undesirable timing jitter. In that case you should use a timer:
void task1()
{
// do something every 100 ms
TIMER timer = createTimer( 100 ) ; // assuming 1ms tick period
for(;;)
{
timerWait() ;
// something
...
}
}
That way something can take up to 100ms and will still be executed accurately and deterministically every 100ms.
Now to your second example; that is a little more complex. If nothing useful can happen until the hardware is initialised, then you may as well use your existing pattern in main() before starting the scheduler. However as a generalisation, waiting for something in a different context (task or interrupt) to occur is done using a synchronisation primitive such as a semaphore or task event flag (not all RTOS have task event flags). So in a simple case in main() you might create a semaphore:
createSemaphore( hardware_ready ) ;
Then in the context performing the process that must complete:
// Init hardware
...
// Tell waiting task hardware ready
semaphoreGive( hardware_ready ) ;
Then in some task that will wait for the hardware to be ready:
void task2()
{
// wait for hardware ready
semaphoreTake( hardware_ready ) ;
// do something else
for(;;)
{
// This loop must block is any lower-priority task
// will run. Equal priority tasks may run is round-robin
// scheduling is implemented.
...
}
}
You are facing two big gotchas...
Since the old code is implemented using protothreads (coroutines), there is never any asynchronous resource contention between them. If you split these into FreeRTOS tasks, there there will be preemptive scheduling task switches; these switches may occur at places where the protothreads were not expecting, leaving data or other resources in an inconsistent state.
If you convert any of your protothreads' PT_WAIT calls into real waits in FreeRTOS, the call will really block. But the protothreads assume that other protothreads continue while they're blocked.
So, #1 implies you cannot just convert protothreads to tasks, and #2 implies you must convert protothreads to tasks (if you use FreeRTOS blocking primitives, like xEventGroupWaitBits().
The most straightforward approach will be to put all your protothreads in one task, and continue polling within that task.

ATtiny85: how to respond simultaneously to pin and timer interrupts

I've recently been playing around with the ATtiny85 as a means of prototyping some simple electronics in a very small package. I'm having a spot of trouble with this since the language used for many of its functions is very different (and a lot less intuitive!) than that found in a standard Arduino sketch. I'm having some difficulty finding a decent reference for the hardware-specific functions too.
Primarily, what I'd like to do is listen for both a pin change and a timer at the same time. A change of state in the pin will reset the timer, but at the same time the code needs to respond to the timer itself if it ends before the pin's state changes.
Now, from the tutorials I've managed to find it seems that both pin change and timer interrupts are funnelled through the same function - ISR(). What I'd like to know is:
Is it possible to have both a pin and a timer interrupt going at the same time?
Assuming they both call the same function, how do you tell them apart?
ISR() is not a function, it's a construct (macro) that is used to generate the stub for an ISR as well as inject the ISR into the vector table. The vector name passed to the macro determines which interrupt it services.
ISR(INT0_vect)
{
// Handle external interrupt 0 (PB2)
...
};
ISR(TIM0_OVF_vect)
{
// Handle timer 0 overflow
...
};
According to the datasheet ATtiny85 doesn't have the same interrupt vector for PCINT0 and TIMER1 COMPA/OVF/COMPB, so you can define different ISR handlers for each one of them.
If you're using the same handler for more interrupts, it might be impossible to differentiate between them, as interrupt flags are usually cleared by hardware on ISR vector execution.
As an addition to the accepted answer:
Is it possible to have both a pin and a timer interrupt going at the same time?
The interrupt can occur at exactly the same time on the hardware level and the corresponding interrupt flags would be set accordingly. The flags indicate that the ISR for the respective interrupt should be executed. But the actual ISRs are (more or less obviously) not executed at the same time / in parallel. Which ISR is executed first (in case multiple interrupts are pending) depends on the interrupt priority, which is specified in the interrupt vector table from the data sheet.

Which Cortex-M3 interrupts can I use for general purpose work?

I'd have some code that needs to be run as the result of a particular interrupt going off.
I don't want to execute it in the context of the interrupt itself but I also don't want it to execute in thread mode.
I would like to run it at a priority that's lower than the high level interrupt that precipitated its running but also a priority that higher than thread level (and some other interrupts as well).
I think I need to use one of the other interrupt handlers.
Which ones are the best to use and what the best way to invoke them?
At the moment I'm planning on just using the interrupt handlers for some peripherals that I'm not using and invoking them by setting bits directly through the NVIC but I was hoping there's a better, more official way.
Thanks,
ARM Cortex supports a very special kind of exception called PendSV. It seems that you could use this exception exactly to do your work. Virtually all preemptive RTOSes for ARM Cortex use PendSV to implement the context switch.
To make it work, you need to prioritize PendSV low (write 0xFF to the PRI_14 register in the NVIC). You should also prioritize all IRQs above the PendSV (write lower numbers in the respective priority registers in the NVIC). When you are ready to process the whole message, trigger the PendSV from the high-priority ISR:
*((uint32_t volatile *)0xE000ED04) = 0x10000000; // trigger PendSV
The ARM Cortex CPU will then finish your ISR and all other ISRs that possibly were preempted by it, and eventually it will tail-chain to the PendSV exception. This is where your code for parsing the message should be.
Please note that PendSV could be preempted by other ISRs. This is all fine, but you need to obviously remember to protect all shared resources by a critical section of code (briefly disabling and enabling interrupts). In ARM Cortex, you disable interrupts by executing __asm("cpsid i") and you enable interrupts by __asm("cpsie i"). (Most C compilers provide built-in intrinsic functions or macros for this purpose.)
Are you using an RTOS? Generally this type of thing would be handled by having a high priority thread that gets signaled to do some work by the interrupt.
If you're not using an RTOS, you only have a few tasks, and the work being kicked off by the interrupt isn't too resource intensive, it might be simplest having your high priority work done in the context of the interrupt handler. If those conditions don't hold, then implementing what you're talking about would be the start of a basic multitasking OS itself. That can be an interesting project in its own right, but if you're looking to just get work done, you might want to consider a simple RTOS.
Since you mentioned some specifics about the work you're doing, here's an overview of how I've handled a similar problem in the past:
For handling received data over a UART one method that I've used when dealing with a simpler system that doesn't have full support for tasking (ie., the tasks are round-robined i na simple while loop) is to have a shared queue for data that's received from the UART. When a UART interrupt fires, the data is read from the UART's RDR (Receive Data Register) and placed in the queue. The trick to deal with this in such a way that the queue pointers aren't corrupted is to carefully make the queue pointers volatile, and make certain that only the interrupt handler modifies the tail pointer and that only the 'foreground' task that's reading data off the queue modified the head pointer. A high-level overview:
producer (the UART interrupt handler):
read queue.head and queue.tail into locals;
increment the local tail pointer (not the actual queue.tail pointer). Wrap it to the start of the queue buffer if you've incremented past the end of the queue's buffer.
compare local.tail and local.head - if they're equal, the queue is full, and you'll have to do whatever error handing is appropriate.
otherwise you can write the new data to where local.tail points
only now can you set queue.tail == local.tail
return from the interrupt (or handle other UART related tasks, if appropriate, like reading from a transmit queue)
consumer (the foreground 'task')
read queue.head and queue.tail into locals;
if local.head == local.tail the queue is empty; return to let the next task do some work
read the byte pointed to by local.head
increment local.head and wrap it if necessary;
set queue.head = local.head
goto step 1
Make sure that queue.head and queue.tail are volatile (or write these bits in assembly) to make sure there are no sequencing issues.
Now just make sure that your UART received data queue is large enough that it'll hold all the bytes that could be received before the foreground task gets a chance to run. The foreground task needs to pull the data off the queue into it's own buffers to build up the messages to give to the 'message processor' task.
What you are asking for is pretty straightforward on the Cortex-M3. You need to enable the STIR register so you can trigger the low priority ISR with software. When the high-priority ISR gets done with the critical stuff, it just triggers the low priority interrupt and exits. The NVIC will then tail-chain to the low-priority handler, if there is nothing more important going on.
The "more official way" or rather the conventional method is to use a priority based preemptive multi-tasking scheduler and the 'deferred interrupt handler' pattern.
Check your processor documentation. Some processors will interrupt if you write the bit that you normally have to clear inside the interrupt. I am presently using a SiLabs c8051F344 and in the spec sheet section 9.3.1:
"Software can simulate an interrupt by setting any interrupt-pending flag to logic 1. If interrupts are enabled for the flag, an interrupt request will be generated and the CPU will vector to the ISR address associated with the interrupt-pending flag."