我正在学习freeRTOS,需要在PIC32平台(cerebot Mx7ck)上为其编写软件中断ISR处理程序。我已经查看了文档,但并没有找到帮助。请有经验的人士提供帮助。
您是否正在寻找软件定时器中断或类似于SPI/I2C/UART的内容?我有一些示例。我不知道我所拥有的是否完全符合FreeRTOS的要求,但它可以工作。 以下是uart.c和isr.S文件中的UART ISR。
void vU5InterruptHandler( void );
void __attribute__( (interrupt(ipl0), vector(_UART_5_VECTOR))) vU5InterruptWrapper( void );
void vU5InterruptHandler( void )
{
/* Declared static to minimize stack use. */
static char cChar;
static portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
/* Are any Rx interrupts pending? */
if( IFS2bits.U5RXIF == 1)
{
//while( U5STAbits.URXDA )
//{
/*
** Retrieve the received character and place it in the
** queue of received characters.
*/
cChar = U5RXREG;
if(cChar != '\n')
{
xQueueSendFromISR( gps_event_queue, &cChar, &xHigherPriorityTaskWoken );
}
//}
IFS2CLR = _IFS2_U5RXIF_MASK;
}
/* Are any Tx interrupts pending? */
if( IFS2bits.U5TXIF == 1 )
{
IFS2CLR = _IFS2_U5TXIF_MASK;
}
/* If sending or receiving necessitates a context switch, then switch now. */
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
/* isr.S */
.extern vU5InterruptHandler
.global vU5InterruptWrapper
.ent vU5InterruptWrapper
vU5InterruptWrapper:
portSAVE_CONTEXT
jal vU5InterruptHandler
nop
portRESTORE_CONTEXT
.end vU5InterruptWrapper
/* sW timer */
TimerHandle_t xSysMonTimer = NULL;
xSysMonTimer = xTimerCreate("SysMonTimer",( 500 / portTICK_PERIOD_MS),pdFALSE,0,Sys_Mon_Callback);
if( xSysMonTimer == NULL )
{
/* The timer was not created. */
}
else
{
/* Start the timer. No block time is specified, and even if one was
it would be ignored because the RTOS scheduler has not yet been
started. */
if( xTimerStart( xSysMonTimer, 0 ) != pdPASS )
{
/* The timer could not be set into the Active state. */
}
}
void Sys_Mon_Callback( TimerHandle_t pxTimer )
{
if( xTimerReset( xSysMonTimer, 10 ) != pdPASS )
{
/* The reset command was not executed successfully. Take appropriate
action here. */
}
}
如果需要演示源代码,您可以参考FreeRTOS/Demo/并选择适合您项目的代码。
软件中断的示例代码:(main_blinky.c)
/* Standard includes. */
#include <stdio.h>
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
/* Priorities at which the tasks are created. */
#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* The rate at which data is sent to the queue. The times are converted from
milliseconds to ticks using the pdMS_TO_TICKS() macro. */
#define mainTASK_SEND_FREQUENCY_MS pdMS_TO_TICKS( 200UL )
#define mainTIMER_SEND_FREQUENCY_MS pdMS_TO_TICKS( 2000UL )
/* The number of items the queue can hold at once. */
#define mainQUEUE_LENGTH ( 2 )
/* The values sent to the queue receive task from the queue send task and the
queue send software timer respectively. */
#define mainVALUE_SENT_FROM_TASK ( 100UL )
#define mainVALUE_SENT_FROM_TIMER ( 200UL )
/*-----------------------------------------------------------*/
/*
* The tasks as described in the comments at the top of this file.
*/
static void prvQueueReceiveTask( void *pvParameters );
static void prvQueueSendTask( void *pvParameters );
/*
* The callback function executed when the software timer expires.
*/
static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle );
/*-----------------------------------------------------------*/
/* The queue used by both tasks. */
static QueueHandle_t xQueue = NULL;
/* A software timer that is started from the tick hook. */
static TimerHandle_t xTimer = NULL;
/*-----------------------------------------------------------*/
/*** SEE THE COMMENTS AT THE TOP OF THIS FILE ***/
void main_blinky( void )
{
const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS;
printf( "Blinky Demo\n" );
esp32_init(9600);
esp32_create_tasks();
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
if( xQueue != NULL )
{
/* Start the two tasks as described in the comments at the top of this
file. */
xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
"Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this simple case. */
mainQUEUE_RECEIVE_TASK_PRIORITY,/* The priority assigned to the task. */
NULL ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
/* Create the software timer, but don't start it yet. */
xTimer = xTimerCreate( "Timer", /* The text name assigned to the software timer - for debug only as it is not used by the kernel. */
xTimerPeriod, /* The period of the software timer in ticks. */
pdTRUE, /* xAutoReload is set to pdTRUE, so he timers will auto-reload themselves when they expire. */
NULL, /* The timer's ID is not used. */
prvQueueSendTimerCallback );/* The function executed when the timer expires. */
/* Start the tasks and timer running. */
xTimerStart( xTimer, 0 );
vTaskStartScheduler();
}
/* If all is well, the scheduler will now be running, and the following
line will never be reached. If the following line does execute, then
there was insufficient FreeRTOS heap memory available for the idle and/or
timer tasks to be created. See the memory management section on the
FreeRTOS web site for more details. */
for( ;; );
}
/*-----------------------------------------------------------*/
static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle )
{
const uint32_t ulValueToSend = mainVALUE_SENT_FROM_TIMER;
/* This is the software timer callback function. The software timer has a
period of two seconds and is reset each time a key is pressed. This
callback function will execute if the timer expires, which will only happen
if a key is not pressed for two seconds. */
/* Avoid compiler warnings resulting from the unused parameter. */
( void ) xTimerHandle;
/* Send to the queue - causing the queue receive task to unblock and
write out a message. This function is called from the timer/daemon task, so
must not block. Hence the block time is set to 0. */
xQueueSend( xQueue, &ulValueToSend, 0U );
}
/*-----------------------------------------------------------*/
static void prvQueueReceiveTask( void *pvParameters )
{
uint32_t ulReceivedValue;
/* Prevent the compiler warning about the unused parameter. */
( void ) pvParameters;
for( ;; )
{
/* Wait until something arrives in the queue - this task will block
indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
FreeRTOSConfig.h. It will not use any CPU time while it is in the
Blocked state. */
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
/* To get here something must have been received from the queue, but
is it an expected value? Normally calling printf() from a task is not
a good idea. Here there is lots of stack space and only one task is
using console IO so it is ok. However, note the comments at the top of
this file about the risks of making Windows system calls (such as
console output) from a FreeRTOS task. */
if( ulReceivedValue == mainVALUE_SENT_FROM_TIMER )
{
printf( "Message received from software timer\r\n" );
}
else
{
printf( "Unexpected message\r\n" );
}
}
}