Software Interrupts for task acitvation: Use vectors of unused peripherals possible?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hello,

I want to set up a set of periodical tasks without using a complete RTOS.
For this purpose I want to use the SysTick to generate one high priority Interrupt every 1ms. Within this SysTick_Handler() I want to start tasks by triggering some SW-Interrupts (lower priority). Because the XMC45xx has only two (SVCall, PendSV) Interrupts for this purpose I want to use the Interrupt vectors of unused peripherals. The peripheral itself (e.g. DSD0) is held in reset state (PRSET0.DSDRS=1) and the Interrupt vectors are used by CMSIS Functions (NVIC_SetPendingIRQ, NVIC_EnableIRQ).
Is there anything I have to consider further? If it works it would be a nice and simple solution for providing cooperative or preemptive or mixed task scheduling...

Thanks a lot for your ideas/comments.

Best regards,

Mario

This is a sample code, and it seems to work pretty good when I look at the LED1/2 signals on the scope:


void SysTick_Handler( void )
{
uint32_t port1_status = PORT1->OUT;
PORT1->OMR = 0x00030000; // reset LED1/LED2

static uint8_t cnt = 0;
cnt++;
switch (cnt )
{
case 10: // start Task 1 (low prio)
NVIC_SetPendingIRQ(DSD0_M_0_IRQn);
break;
case 11: // start Task 2 (high prio) -> this will interrupt Task 1. Task1 will be finished after Task2 is finished...
NVIC_SetPendingIRQ(DSD0_M_1_IRQn);
break;
case 15: // start Task 2 (high prio) -> Task2 is still active -> wait until Task2 calls return from interrupt
NVIC_SetPendingIRQ(DSD0_M_1_IRQn);
default:
break;
case 100: // start Task 2 (high prio) -> Task2 is started
NVIC_SetPendingIRQ(DSD0_M_1_IRQn);
break;
case 101: // start Task 1 (low prio) -> Task2 is still running -> Task1 has to wait until Task2 is finished
NVIC_SetPendingIRQ(DSD0_M_0_IRQn);
break;
}

if ( port1_status & 0x01 )
{
PORT1->OMR = 0x00000001; // set LED2
}

if ( port1_status & 0x02 )
{
PORT1->OMR = 0x00000002; // set LED1
}
}

// Task1 (low prio)
void DSD0_0_IRQHandler( void )
{
PORT1->OMR = 0x0000002; // set LED1
for (uint32_t i=0 ; i<60000 ; i++ )
{
// approx 25ms @ 24MHz
}
PORT1->OMR = 0x00020000; // reset LED1
}

// Task2 (high prio)
void DSD0_1_IRQHandler( void )
{
PORT1->OMR = 0x0000001; // set LED2
for (uint32_t i=0 ; i<10000 ; i++ )
{
// approx 4,2ms @ 24MHz
}
PORT1->OMR = 0x00010000; // reset LED2
}

sint32_t main(void)
{
if ( SysTick_Config(SystemCoreClock/1000) != 0 ) // CMSIS init SysTick to generate Interrupt every 1ms
{
// Error handling...
}
NVIC_SetPriority (SysTick_IRQn, 0);
NVIC_SetPriority (DSD0_M_0_IRQn, 2);
NVIC_SetPriority (DSD0_M_1_IRQn, 1);
NVIC_EnableIRQ(DSD0_M_0_IRQn);
NVIC_EnableIRQ(DSD0_M_1_IRQn);
while(1)
{

}
return 0;
}
0 Likes
2 Replies
User6412
Level 4
Level 4
Why additional interrupts? The 1 ms high priority interrupt on my oppinion is enought. There you can trigger some software flags for any low priority tasks. This software flags can be checked and erased in the main loop, where the free microcontroller time is spended.
0 Likes
Not applicable
Hi Dmitry,

thanks for your reply. Handling tasks with flags in the main loop would have the disadvantage that no preemptive scheduling (one task interrupts another) is possible or in each task must be special calls to the scheduler to handle task interruption... This makes the code more complex...
With the Interrupt method you can specify which task interrupts another by setting the priority. So cooperative and preemptive scheduling is possible without SW-overhead.

Best regards,

Mario
0 Likes