FreeRTOS Error with High Speed ​​UART Interrupt in PIC24H

I have already used FreeRTOSfor some embedded projects for some years, and so far it has worked perfectly. Currently, I am faced with a difficult problem related to using high-speed interrupt in FreeRTOSporting to PIC24H, I hope you all can help me, although this problem. thanks in advance

I created a small demo project for easy testing:

Two tasks:

// Task 1

if (xTaskCreate(RTOSTask_1, (signed char) "[T1]", configMINIMAL_STACK_SIZE2, NULL, tskIDLE_PRIORITY + 1, &hTask1) == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
{
  LREP("\r\nCannot create Task 1.");   
  Display_Error(1000);
}

// Task 2

if (xTaskCreate(RTOSTask_2, (signed char) "[T2]", configMINIMAL_STACK_SIZE2, NULL, tskIDLE_PRIORITY + 2, &hTask2) == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
{
  LREP("\r\nCannot create Task 2."); 
  Display_Error(1000);  
}

Accomplishment of tasks:

void RTOSTask_1(void* pvParameter)
{ 
  while(1)
  {

    if (xSemaphoreTake(hTask1Semaphore, portMAX_DELAY) == pdTRUE)
    { 
      putchar1('1');
    } 
  }
}

void RTOSTask_2(void* pvParameter)
{
  while(1)
  {
    if (xSemaphoreTake(hTask2Semaphore, portMAX_DELAY) == pdTRUE)
    { 
       putchar1('2');
    } 

   }
}

To perform on two tasks to be performed, I use one Timerand one UARTto give them Semaphores:

void attribute((interrupt, auto_psv)) _T2Interrupt (void)
{ 
  _T2IF = 0;
  static signed portBASE_TYPE xTaskWoken = pdFALSE;
  xSemaphoreGiveFromISR(hTask1Semaphore, &xTaskWoken );

  if( xTaskWoken != pdFALSE )
  {
    taskYIELD();
  }
}

void attribute((interrupt, auto_psv)) _U1TXInterrupt()
{

  _U1TXIF = 0;
  putchar1('E');
} 

void attribute((interrupt, auto_psv)) _U1RXInterrupt()
{

  _U1RXIF = 0;
  if(U1STAbits.URXDA == 1)
  {
    uint8 u8Recv = U1RXREG;
  }

  static signed portBASE_TYPE xTaskWoken;

  xTaskWoken = pdFALSE;

  xSemaphoreGiveFromISR(hTask2Semaphore, &xTaskWoken);


  if( xTaskWoken != pdFALSE )
  {
    taskYIELD();
  }
}

My timer interrupts every 100 seconds, UART runs at 24,400 bps.

, :

_AddressError

_StackError

, . , , (ISR). , SAVE_CONTEXT() RESTORE_CONTEXT(). PIC24 .

, , .

!


, . , PIC24H , UART RX, TX, .

ISR :

void (( , auto_psv))

:

__ U1RXInterrupt:       ; CPU

    PUSH    SR          
PUSH    W0
PUSH    W1          
PUSH.D  W2
PUSH.D  W4
PUSH.D  W6
PUSH.D  W8
PUSH.D  W10
PUSH.D  W12
PUSH    W14
PUSH    RCOUNT
PUSH    TBLPAG
PUSH    CORCON
PUSH    PSVPAG

    ; Call my ISR
    call _UART1_RxISRHandler        

    ; Pop out CPU registers
POP PSVPAG
POP CORCON
POP TBLPAG
POP RCOUNT                  
POP W14
POP.D   W12
POP.D   W10
POP.D   W8
POP.D   W6
POP.D   W4
POP.D   W2
POP.D   W0
POP SR


retfie      

UART1_RxISRHandler - ISR. TX, .

, 1 ( 1-5 ). 1-2 . , , - . , - .

- , , .

+4
3

.

uart?

RTOS, FreeRTOSConfig.h, 1, PIC 3.

, .

SAVE_CONTEXT() RESTORE_CONTEXT() PIC, , , _FASTISR .

+1

. LPC1769. mcu.

mainQUEUE_LENGTH (1)

, . , ,

#include "FreeRTOS.h"
#include "task.h"
#include "queue.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 bit of port 0 that the LPCXpresso LPC13xx LED is connected. */
#define mainLED_BIT                         ( 22 )

/* The rate at which data is sent to the queue, specified in milliseconds. */
#define mainQUEUE_SEND_FREQUENCY_MS         ( 500 / portTICK_RATE_MS )

/* The number of items the queue can hold.  This is 1 as the receive task
will remove items as they are added, meaning the send task should always find
the queue empty. */
#define mainQUEUE_LENGTH                    ( 1 )

/*
 * The tasks as described in the accompanying PDF application note.
 */
static void prvQueueReceiveTask( void *pvParameters );
static void prvQueueSendTask( void *pvParameters );

/*
 * Simple function to toggle the LED on the LPCXpresso LPC17xx board.
 */
static void prvToggleLED( void );

/* The queue used by both tasks. */
static xQueueHandle xQueue = NULL;

/*-----------------------------------------------------------*/

int main(void)
{
    /* Initialise P0_22 for the LED. */
    LPC_PINCON->PINSEL1 &= ( ~( 3 << 12 ) );
    LPC_GPIO0->FIODIR |= ( 1 << mainLED_BIT );

    /* Create the queue. */
    xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );

    if( xQueue != NULL )
    {
        /* Start the two tasks as described in the accompanying application
        note. */
        xTaskCreate( prvQueueReceiveTask, ( signed char * ) "Rx", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_RECEIVE_TASK_PRIORITY, NULL );
        xTaskCreate( prvQueueSendTask, ( signed char * ) "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );

        /* Start the tasks running. */
        vTaskStartScheduler();
    }

    /* If all is well we will never reach here as the scheduler will now be
    running.  If we do reach here then it is likely that there was insufficient
    heap available for the idle task to be created. */
    for( ;; );
}
/*-----------------------------------------------------------*/

static void prvQueueSendTask( void *pvParameters )
{
portTickType xNextWakeTime;
const unsigned long ulValueToSend = 100UL;

    /* Initialise xNextWakeTime - this only needs to be done once. */
    xNextWakeTime = xTaskGetTickCount();

    for( ;; )
    {
        /* Place this task in the blocked state until it is time to run again.
        The block state is specified in ticks, the constant used converts ticks
        to ms.  While in the blocked state this task will not consume any CPU
        time. */
        vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );

        /* Send to the queue - causing the queue receive task to flash its LED.
        0 is used as the block time so the sending operation will not block -
        it shouldn't need to block as the queue should always be empty at this
        point in the code. */
        xQueueSend( xQueue, &ulValueToSend, 0 );
    }
}
/*-----------------------------------------------------------*/

static void prvQueueReceiveTask( void *pvParameters )
{
unsigned long ulReceivedValue;

    for( ;; )
    {
        /* Wait until something arrives in the queue - this task will block
        indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
        FreeRTOSConfig.h. */
        xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );

        /*  To get here something must have been received from the queue, but
        is it the expected value?  If it is, toggle the LED. */
        if( ulReceivedValue == 100UL )
        {
            prvToggleLED();
        }
    }
}
/*-----------------------------------------------------------*/

static void prvToggleLED( void )
{
unsigned long ulLEDState;

    /* Obtain the current P0 state. */
    ulLEDState = LPC_GPIO0->FIOPIN;

    /* Turn the LED off if it was on, and on if it was off. */
    LPC_GPIO0->FIOCLR = ulLEDState & ( 1 << mainLED_BIT );
    LPC_GPIO0->FIOSET = ( ( ~ulLEDState ) & ( 1 << mainLED_BIT ) );
}
0

. ?

FreeRTOS FreeRTOS (AFAIK, ), , .

, , .

, , IDLE ( , ). , :

// in FreeRTOSConfig.h
#define configCHECK_FOR_STACK_OVERFLOW 1

=== somewhere in your code ===
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
    // Embed assembler code to put your processor into debughalt state.
    // I'm not familiar with PIC24 asm, but
    //
    // - http://www.microchip.com/forums/tm.aspx?m=434136
    //
    // may help.
    MACRO_TO_DEBUG_HALT();
}
0

All Articles