interrupt_handling Interrupt Handling in NetBurner Applications
interrupt_overview Overview
An interrupt is a hardware or software signal that temporarily suspends normal program execution to handle a time-critical event. When an interrupt occurs, the processor:
- Saves the current execution context
- Executes the Interrupt Service Routine (ISR)
- Restores the context and resumes normal execution
Normal Program Flow Interrupt Flow
───────────────── ──────────────
Instruction A Instruction A
| |
v v
Instruction B ┌──────────────────┐
| │ Interrupt Signal │
v └──────────────────┘
Instruction C |
| v
v ┌─────────────────┐
Instruction D │ Save Context │
└─────────────────┘
|
v
┌─────────────────┐
│ Execute ISR │
└─────────────────┘
|
v
┌─────────────────┐
│ Restore Context │
└─────────────────┘
|
v
Instruction B
|
v
Instruction C
|
v
Instruction D
interrupt_sources Common Interrupt Sources
NetBurner devices handle interrupts from various sources:
- Hardware Timers - Periodic or one-shot timing events
- Serial Ports - UART data reception/transmission
- Ethernet Controllers - Network packet events
- GPIO Pins - External hardware signals
- Software Traps - Programmatically triggered interrupts
interrupt_platform_variations Platform Variations
Interrupt handling implementation varies by processor architecture:
| Platform | Complexity | Key Characteristics |
| ARM (Cortex-M7) | Simple | Direct function calls, minimal setup |
| ColdFire (MCF5441x) | Complex | Requires entry/exit macros, controller setup |
NetBurner provides abstraction layers to simplify interrupt configuration across all platforms.
core_interrupt_functions Core Interrupt Functions
The following functions work across all NetBurner platforms and provide a consistent interface for interrupt management.
interrupt_header_requirements Header Requirements
#include <pins.h>
#include <system.h>
interrupt_function_overview Function Overview
Interrupt Configuration Workflow
────────────────────────────────
┌─────────────────────────────────┐
│ 1. Configure Pin as Interrupt │
│ SetPinIrq(pin, pol, func) │
└─────────────────────────────────┘
|
v
┌─────────────────────────────────┐
│ 2. Enable the Interrupt │
│ EnableIrq(pin) │
└─────────────────────────────────┘
|
v
┌─────────────────────────────────┐
│ Interrupt Active - ISR Called │
└─────────────────────────────────┘
|
v
┌─────────────────────────────────┐
│ 3. Disable When Finished │
│ DisableIrq(pin) │
└─────────────────────────────────┘
interrupt_setpinirq SetPinIrq() - Configure Interrupt Pin
Function Signature:**
bool SetPinIrq(
PinIO pin,
int polarity, PinIrq_t func);
GPIO Pin Class.
Definition coldfire/cpu/MCF5441X/include/cpu_pins.h:15
Parameters:**
| Parameter | Type | Description |
pin | PinIO | Pin object to configure as interrupt source |
polarity | int | Trigger condition (see polarity table below) |
func | PinIrq_t | Function pointer to the ISR |
Polarity Values:**
Signal Polarity Configuration
─────────────────────────────
Value │ Trigger Type │ Signal Diagram
────────┼────────────────────────┼─────────────────────
2 │ High Level │ ────┐
│ │ └──────
────────┼────────────────────────┼─────────────────────
1 │ Rising Edge (Pos) │ ┌─────
│ │ ────┘
────────┼────────────────────────┼─────────────────────
0 │ Any Edge (Both) │ ┌───── ────┐
│ │ ────┘ or └──
────────┼────────────────────────┼─────────────────────
-1 │ Falling Edge (Neg) │ ────┐
│ │ └─────
────────┼────────────────────────┼─────────────────────
-2 │ Low Level │ ┌──────
│ │ ────┘
Returns:** true if configuration successful, false otherwise.
Example:**
void MyButtonISR() {
printf("Button pressed!\r\n");
}
buttonPin.function(PINMODE_GPIO);
SetPinIrq(buttonPin, -1, MyButtonISR);
interrupt_enableirq EnableIrq() - Activate Interrupt
Function Signature:**
void EnableIrq(
PinIO pin);
Enables interrupt processing for the specified pin.
Example:**
interrupt_disableirq DisableIrq() - Deactivate Interrupt
Function Signature:**
void DisableIrq(
PinIO pin);
Disables interrupt processing for the specified pin.
Example:**
isr_restrictions ISR Restrictions
isr_critical_constraints Critical Constraints
The code within an ISR executes in an interrupt context, which has strict limitations. The following operations are PROHIBITED in an ISR:
ISR Execution Context
─────────────────────
User Application Interrupt Context
──────────────── ─────────────────
┌──────────────┐ ┌──────────────┐
│ │ │ │
│ Full RTOS │ │ Limited │
│ Services │ <───────X────> │ Services │
│ Available │ Cannot │ Available │
│ │ Call │ │
└──────────────┘ └──────────────┘
Can use: Can use:
- OSxxPend - OSxxPendNoWait only
- malloc/free - Direct hardware access
- printf/
write - OSxxPost
- All I/O - Simple variables
int write(int fd, const char *buf, int nbytes)
Write data to the stream associated with a file descriptor (fd). Can be used to write data to stdio,...
isr_prohibited_rtos Prohibited RTOS Functions
All blocking/waiting functions are forbidden:**
OSMboxPend()
OSSemPend()
OSQPend()
OSCritEnter()
OSChangePrio()
OSTaskDelete()
OSLock()
OSUnlock()
OSTaskCreate()
OSTimeDly()
Allowed RTOS operations (non-blocking only):**
OSMboxPendNoWait()
OSSemPendNoWait()
OSQPendNoWait()
OSMboxPost()
OSSemPost()
OSQPost()
isr_prohibited_io Prohibited I/O Functions
All I/O operations that may block are forbidden:**
printf()
fprintf()
printf()
scanf()
gets()
puts()
int fdprintf(int fd, const char *format,...)
Print formatted output to a file descriptor.
int read(int fd, char *buf, int nbytes)
Read data from a file descriptor (fd).
int writeall(int fd, const char *buf, int nbytes=0)
Write the specified number of bytes to a file descriptor. Will block until all bytes are sent,...
isr_prohibited_memory Prohibited Memory Functions
Dynamic memory operations are forbidden:**
malloc()
free()
new
delete
isr_recommended_pattern Recommended ISR Pattern
volatile bool eventFlag = false;
volatile uint32_t eventData = 0;
void MyISR() {
eventData = ReadHardwareRegister();
eventFlag = true;
OSSemPost(&processingTask);
}
void ProcessingTask(void* pd) {
while (1) {
OSSemPend(&processingTask, 0);
if (eventFlag) {
eventFlag = false;
ProcessEvent(eventData);
printf("Event processed: %lu\r\n", eventData);
}
}
}
platform_specific_implementations Platform-Specific Implementations
Different processor architectures require different interrupt setup procedures.
Platform Interrupt Architecture
────────────────────────────────
NetBurner Platforms
|
┌───────────┴───────────┐
| |
v v
ARM Based ColdFire Based
───────── ──────────────
| |
| |
v v
┌─────────┐ ┌──────────┐
│ SAME70 │ │ MCF5441x │
└─────────┘ └──────────┘
| |
v v
Simple Config Complex Config
- Direct ISR - INTERRUPT macro
- Port priority - SetIntc() setup
-
PinIO based - Vector tables
same70_platforms SAME70 Platforms (MODM7AE70 and SBE70LC)
same70_architecture Architecture Overview
The SAME70 (Cortex-M7) features:
- Any GPIO pin can be used as an interrupt source
- Port-based priority - all pins on same port share priority
- 7 Priority Levels - 1 (highest) to 7 (lowest)
SAME70 Interrupt Structure
──────────────────────────
Physical Pins Port IRQ Controller
───────────── ───────────────────
┌──────┐ ┌─────────────────┐
│ PA0 │───┐ │ │
│ PA1 │───┤ │ PIOA IRQ │
│ PA2 │───┤──────────────>│ Priority: X │
│ ... │ │ │ │
│ PA31 │───┘ └─────────────────┘
└──────┘ |
v
┌──────┐ ┌─────────────────┐
│ PB0 │───┐ │ │
│ PB1 │───┤ │ PIOB IRQ │
│ PB2 │───┤──────────────>│ Priority: Y │
│ ... │ │ │ │
│ PB31 │───┘ └─────────────────┘
└──────┘ |
v
┌──────┐ ┌─────────────────┐
│ PC0 │───┐ │ │
│ PC1 │───┤ │ PIOC IRQ │
│ PC2 │───┤──────────────>│ Priority: Z │
│ ... │ │ │ │
│ PC31 │───┘ └─────────────────┘
└──────┘
same70_port_priority Port Priority Configuration
SetPortIrqPriority() - By PinIO Object
Function Signature:**
bool SetPortIrqPriority(
PinIO pin,
int priority);
Parameters:**
| Parameter | Type | Description |
pin | PinIO | Any pin on the target port |
priority | int | Priority level: 1 (highest) to 7 (lowest) |
Important:** Setting priority for any pin affects the entire port.
Returns:** true if successful, false otherwise.
Example:**
SetPortIrqPriority(myPin, 3);
SetPortIrqPriority() - By Port Number
Function Signature:**
bool SetPortIrqPriority(int portNum, int priority);
Parameters:**
| Parameter | Type | Description |
portNum | int | Port number: PIOA=0, PIOB=1, PIOC=2, PIOD=3, PIOE=4 |
priority | int | Priority level: 1 (highest) to 7 (lowest) |
Example:**
SetPortIrqPriority(1, 3);
same70_port_mapping Port Priority Mapping
SAME70 Port Assignments
───────────────────────
Port Number │ Port Name │ Example Usage
─────────────┼─────────────┼──────────────────────
0 │ PIOA │ High priority sensors
1 │ PIOB │ Medium priority inputs
2 │ PIOC │ Communication signals
3 │ PIOD │ General I/O
4 │ PIOE │ Low priority monitoring
same70_workflow Configuration Workflow
Critical:** Always set port priority before configuring pin interrupts.
SAME70 Interrupt Setup Sequence
────────────────────────────────
Step 1 Step 2 Step 3
────── ────── ──────
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Set Port │ │ Configure Pin │ │ Enable │
│ Priority │ ───> │ Interrupt │ ───> │ Interrupt │
│ │ │ │ │ │
│ SetPortIrqPri() │ │ SetPinIrq() │ │ EnableIrq() │
└─────────────────┘ └─────────────────┘ └─────────────────┘
same70_example Complete SAME70 Example
#include <pins.h>
#include <system.h>
#include <nbrtos.h>
void SensorISR() {
OSSemPost(&sensorEvent);
}
void ConfigureSensorInterrupt() {
sensorPin.function(PINMODE_GPIO);
SetPortIrqPriority(1, 2);
SetPinIrq(sensorPin, 1, SensorISR);
EnableIrq(sensorPin);
printf("Sensor interrupt configured on pin 42\r\n");
}
mcf5441x_platforms MCF5441x Platforms (MOD54415, MOD54417, NANO54415 and SB800EX)
mcf5441x_architecture Architecture Overview
The MCF5441x (ColdFire) processor requires more complex setup:
- INTERRUPT() macro - Handles ISR entry/exit code
- SetIntc() function - Configures interrupt controller hardware
- 7 Priority Levels - 1 to 7, with 7 being highest (unmaskable)
ColdFire Interrupt Flow
───────────────────────
Interrupt Source Interrupt Controller ISR Processing
──────────────── ──────────────────── ──────────────
┌──────────┐ ┌─────────────────┐ ┌───────────┐
│ UART 0 │ │ │ │ │
│ Vector:26│──┐ │ Controller 0 │ │ MACRO │
└──────────┘ │ │ │ │ Handles │
├───────────────> Vector Table │───────────>│ Entry/ │
┌──────────┐ │ │ │ │ Exit │
│ Timer 2 │ │ │ Priority: 1-7 │ │ Code │
│ Vector:15│──┘ │ │ │ │
└──────────┘ └─────────────────┘ └───────────┘
|
v
┌───────────┐
│ User ISR │
│ Function │
└───────────┘
mcf5441x_interrupt_macro INTERRUPT() Macro
The INTERRUPT() macro simplifies ISR implementation by handling:
- Saving processor registers
- Setting status register
- RTOS notification
- Restoring registers on exit
Header Requirements
#include <nbrtos.h>
#include <cfinter.h>
Macro Syntax
INTERRUPT(FunctionName, SR_Value)
{
}
Parameters
| Parameter | Description |
FunctionName | ISR function name (used with SetIntc()) |
SR_Value | Status Register value - controls interrupt masking |
Status Register Values
The Status Register (SR) controls which interrupts can preempt the current ISR:
ColdFire Status Register Interrupt Masking
──────────────────────────────────────────
SR Value │ Mask Level │ Allows Interrupts At Level │ Blocks
──────────┼──────────────┼──────────────────────────────┼─────────────
0x2000 │ 0 │ All (1-7) │ None
0x2100 │ 1 │ 2 and above │ Level 1
0x2200 │ 2 │ 3 and above │ Levels 1-2
0x2300 │ 3 │ 4 and above │ Levels 1-3
0x2400 │ 4 │ 5 and above │ Levels 1-4
0x2500 │ 5 │ 6 and above │ Levels 1-5
0x2600 │ 6 │ 7 only │ Levels 1-6
0x2700 │ 7 │ None (masks all maskable) │ All < 7
Note: Level 7 interrupts are unmaskable - they always execute
Bit 29 is supervisor bit (always set = 0x2000 base)
Interrupt Priority Hierarchy
Interrupt Priority Levels
─────────────────────────
Level 7 ─────────── Highest (Unmaskable)
^ Critical system events
| Can interrupt anything
|
Level 6 ─────────── Very High Priority
^ Time-critical operations
|
Level 5 ─────────── High Priority
^ Important peripherals
|
Level 4 ─────────── Medium-High Priority
^ Communication interfaces
|
Level 3 ─────────── Medium Priority
^ General peripherals
|
Level 2 ─────────── Low-Medium Priority
^ Non-critical I/O
|
Level 1 ─────────── Low Priority
^ Background tasks
|
Level 0 ─────────── Disabled
Level 7 Warning
CRITICAL:** Level 7 interrupts are unmaskable and can interrupt themselves!
Level 7 Interrupt Danger
────────────────────────
┌─────────────────┐
│ Level 7 ISR │
│ Executing │
└────────┬────────┘
|
| Another Level 7
| interrupt occurs
v
┌─────────────────┐ <─── DANGER!
│ Level 7 ISR │ Stack corruption
│ Re-enters! │ Register collision
└─────────────────┘ Data corruption
Mitigation Strategy:**
INTERRUPT(CriticalISR, 0x2700)
{
ClearInterruptFlag();
volatile uint32_t data = ReadHardwareRegister();
criticalEventFlag = true;
}
mcf5441x_setintc SetIntc() Function
Configures the interrupt controller to route hardware interrupts to ISR functions.
Function Declaration
Important:** SetIntc() is defined in platform HAL files and must be declared as extern:
extern void SetIntc(int intcnum, long func, int vector, int level);
Location:** \nburn\platform\MOD5441x\hal.cpp
Parameters
| Parameter | Type | Description |
intcnum | int | Interrupt controller number (0 or 1 for MCF5441x) |
func | long | Pointer to ISR function (from INTERRUPT macro) |
vector | int | Interrupt vector number (0-255, device-specific) |
level | int | Interrupt priority level (0=disabled, 1-7) |
Vector Numbers
The MCF5441x has 256 exception vectors:
- 0-63: Core exceptions (reserved)
- 64-255: Peripheral interrupt sources (192 device-specific vectors)
Common MCF5441x Interrupt Sources
─────────────────────────────────
Source │ Vector │ Typical Use
─────────────┼──────────┼────────────────────────
UART 0 │ 26 │ Serial communication
UART 1 │ 27 │ Serial communication
PIT Timer 2 │ 15 │ Periodic timer
1-Wire │ 63 │ 1-Wire bus interface
Ethernet │ varies │ Network events
Reference:** See Chapter 17, Table 17.2.9.1 in NXP MCF5441x Reference Manual
Interrupt Controller Selection
MCF5441x Interrupt Controllers
──────────────────────────────
Controller 0 (intcnum = 0) Controller 1 (intcnum = 1)
────────────────────── ──────────────────────
├─ UART 0 (Vector 26) ├─ Additional peripherals
├─ PIT Timers ├─ Extended I/O
├─ Ethernet ├─ Communication interfaces
├─ 1-Wire (Vector 63) └─ Platform-specific devices
└─ Core peripherals
mcf5441x_example Complete MCF5441x Example: 1-Wire Interface
#include <nbrtos.h>
#include <cfinter.h>
#include <sim5441x.h>
extern void SetIntc(int intc, long func, int vector, int level);
volatile enum { OK, BUSY, ERROR } ow_state = OK;
void OWMasterIsr()
{
uint8_t status = sim1.ow.sr;
sim1.ow.sr = status;
if (status & OW_SR_RBF) {
ow_state = OK;
}
}
INTERRUPT(ow_master_int_routine, 0x2600)
{
OWMasterIsr();
}
void OWInit()
{
sim1.ow.cr = 0;
sim1.ow.div = 0x7C;
sim1.ow.cmd = 0;
sim1.ow.ier = OW_IER_ERBF;
SetIntc(0, (long)&ow_master_int_routine, 63, 3);
ow_state = OK;
printf("1-Wire interrupt configured: Vector 63, Level 3\r\n");
}
void UserMain(void *pd)
{
OWInit();
while (1) {
}
}
#define TICKS_PER_SECOND
System clock ticks per second.
Definition constants.h:49
void init()
System initialization. Ideally called at the beginning of all applications, since the easiest Recover...
mcf5441x_workflow MCF5441x Configuration Workflow
ColdFire Interrupt Setup Process
────────────────────────────────
Step 1: Implement ISR Logic
┌─────────────────────────────┐
│ void MyIsr() { │
│
│ } │
└─────────────────────────────┘
|
v
Step 2: Wrap with INTERRUPT Macro
┌─────────────────────────────┐
│ INTERRUPT(my_isr, 0x2500) { │
│ MyIsr(); │
│ } │
└─────────────────────────────┘
|
v
Step 3: Configure Hardware
┌─────────────────────────────┐
│
│ peripheral.control = ...; │
│ peripheral.enable = ...; │
└─────────────────────────────┘
|
v
Step 4: Configure Controller
┌─────────────────────────────┐
│ SetIntc(0, │
│ (long)&my_isr, │
│ vector_num, │
│ priority_level); │
└─────────────────────────────┘
|
v
Step 5: Interrupt Active
┌─────────────────────────────┐
│ ISR Called on Events │
└─────────────────────────────┘
mcf5441x_best_practices Best Practices for MCF5441x
- Always use INTERRUPT() macro - Never write bare ISR functions
- Match SR value to needs - Don't block higher priority interrupts unnecessarily
- Initialize hardware first - Set up peripheral registers before SetIntc()
- Use correct vector numbers - Consult reference manual for device-specific vectors
- Avoid Level 7 unless critical - Use lower levels when possible
somrt1061_platform SOMRT1061 Platform
somrt1061_overview Overview
The SOMRT1061 platform uses the i.MX RT1061 processor (ARM Cortex-M7). Interrupt configuration follows the standard NetBurner approach with some platform-specific considerations.
i.MX RT1061 Interrupt Architecture
──────────────────────────────────
GPIO Pins NVIC Controller ISR
───────── ─────────────── ───
┌──────────────┐ ┌─────────────┐ ┌───────────┐
│ GPIO1[0:31] │───────────────>│ │ │ │
├──────────────┤ │ Priority │─────────>│ Direct │
│ GPIO2[0:31] │───────────────>│ Settings │ │ Function │
├──────────────┤ │ │ │ Call │
│ GPIO3[0:31] │───────────────>│ IRQ Enable │ │ │
├──────────────┤ │ │ └───────────┘
│ GPIO4[0:31] │───────────────>│ Vector │
├──────────────┤ │ Routing │
│ GPIO5[0:31] │───────────────>│ │
└──────────────┘ └─────────────┘
somrt1061_configuration Configuration Approach
The SOMRT1061 uses the standard NetBurner interrupt functions:
#include <pins.h>
#include <system.h>
void MyRT1061ISR() {
}
void ConfigureInterrupt() {
myPin.function(PINMODE_GPIO);
SetPinIrq(myPin, 1, MyRT1061ISR);
EnableIrq(myPin);
}
somrt1061_notes Platform-Specific Notes
- No port-based priority - Each GPIO can have individual priority
- Direct ISR calls - No INTERRUPT() macro needed
- Fast interrupt response - Cortex-M7 architecture provides low latency
- Standard PinIO support - All GPIO pins accessible via PinIO objects
somrt1061_example SOMRT1061 Example
#include <init.h>
#include <nbrtos.h>
#include <pins.h>
#include <system.h>
const char *AppName = "RT1061 Interrupt Example";
OS_SEM buttonSem;
void ButtonPressISR() {
OSSemPost(&buttonSem);
}
void ButtonTask(void *pd) {
while (1) {
OSSemPend(&buttonSem, 0);
printf("Button pressed at %lu seconds\r\n", Secs);
}
}
void UserMain(void *pd) {
OSSemInit(&buttonSem, 0);
buttonPin.function(PINMODE_GPIO);
SetPinIrq(buttonPin, -1, ButtonPressISR);
EnableIrq(buttonPin);
OSTaskCreate(ButtonTask,
NULL,
(void *)&ButtonTaskStack[USER_TASK_STK_SIZE],
(void *)ButtonTaskStack,
printf("%s: Interrupt configured on pin 23\r\n", AppName);
while (1) {
}
}
#define MAIN_PRIO
Recommend UserMain priority.
Definition constants.h:130
interrupt_summary Summary and Best Practices
interrupt_cross_platform Cross-Platform Compatibility
For maximum portability across NetBurner platforms:
SetPinIrq(pin, polarity, isr_func);
EnableIrq(pin);
DisableIrq(pin);
interrupt_platform_selection Platform Selection Guide
Choose Your Approach Based on Platform
──────────────────────────────────────
Platform │ Complexity │ Key Functions
─────────────────┼──────────────┼────────────────────────────
SAME70 │ Simple │ SetPinIrq()
(MODM7AE70) │ │ SetPortIrqPriority()
│ │ EnableIrq() / DisableIrq()
─────────────────┼──────────────┼────────────────────────────
MCF5441x │ Complex │ INTERRUPT() macro
(MOD54415, etc) │ │ SetIntc()
│ │ Manual register setup
─────────────────┼──────────────┼────────────────────────────
SOMRT1061 │ Simple │ SetPinIrq()
(i.MX RT1061) │ │ EnableIrq() / DisableIrq()
interrupt_general_best_practices General Best Practices
- Keep ISRs short - Minimal processing, set flags, post semaphores
- Use volatile for shared variables - Prevent compiler optimization issues
- Never block in ISRs - No waiting, no delays, no blocking I/O
- Signal tasks for processing - Use semaphores/mailboxes to defer work
- Test interrupt rates - Ensure ISR completes before next interrupt
- Document vector/priority choices - Make interrupt configuration clear
- Initialize hardware before interrupts - Configure peripherals, then enable IRQ
interrupt_debugging Debugging Interrupts
Interrupt Debugging Checklist
─────────────────────────────
┌─────────────────────────────────────┐
│ 1. Is ISR being called? │ <─── Add toggle/LED
│ > Add debug indicator │
└─────────────────────────────────────┘
|
v
┌─────────────────────────────────────┐
│ 2. Is interrupt enabled? │ <─── Verify EnableIrq()
│ > Check enable status │
└─────────────────────────────────────┘
|
v
┌─────────────────────────────────────┐
│ 3. Is priority correct? │ <─── Check for blocking
│ > Verify vs other interrupts │
└─────────────────────────────────────┘
|
v
┌─────────────────────────────────────┐
│ 4. Is hardware generating signal? │ <─── Check with scope
│ > Verify with oscilloscope │
└─────────────────────────────────────┘
|
v
┌─────────────────────────────────────┐
│ 5. Is ISR corrupting data? │ <─── Check for prohibited
│ > Review ISR restrictions │ function calls
└─────────────────────────────────────┘
interrupt_error_prevention Error Prevention
void BadISR() {
printf("Interrupt!\r\n");
}
void GoodISR() {
interruptFlag = true;
OSSemPost(&processSem);
}
interrupt_resources Additional Resources
For more detailed information:
- Platform Hardware Manuals:
\nburn\docs\nxp\
- ColdFire Interrupt Header:
\nburn\arch\coldfire\include\cfinter.h
- NetBurner API Documentation: SDK API reference
- Example Projects: NetBurner SDK examples directory