简体   繁体   English

freeRTOS 中的软件中断

[英]Software interrupt in freeRTOS

I am learning freeRTOS.我正在学习 freeRTOS。 I need to write software interrupt ISR handler in freeRTOS for PIC32 platform (cerebot Mx7ck).我需要在 PIC32 平台(cerebot Mx7ck)的 freeRTOS 中编写软件中断 ISR 处理程序。 I went through the documentation but no help.我浏览了文档,但没有帮助。 Please somebody help.请有人帮忙。

Are you looking for Software timer interrupts or something like SPI/I2C/UART?您是在寻找软件定时器中断还是 SPI/I2C/UART 之类的东西? I have some examples of all.我有一些例子。 I don't know if what I have is exactly to what FreeRTOS would want, but it works.我不知道我所拥有的是否正是 FreeRTOS 想要的,但它确实有效。 Below is the UART ISR in uart.c and my isr.S files.下面是 uart.c 中的 UART ISR 和我的 isr.S 文件。

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. */
    }
}

For Demo source code you can refer to FreeRTOS/Demo/ and get the suitable one for your project对于 Demo 源代码,您可以参考FreeRTOS/Demo/并获得适合您项目的代码

Example code of software interrupt: (main_blinky.c)软件中断示例代码:(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" );
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM