The Board keep restarting while comment out one of the task

I have defined three tasks, below are the code of these tasks: ~~~ static void vThread1( void pvParameters ) { //vTaskSetApplicationTaskTag( NULL, ( void * ) 1 ); for(;;){ vTaskDelay( 10000 ); LED_1_LAT=0; while(U1STAbits.TRMT==0); UART1_sent((uchar)”Thread1 Runningrnrrr”,18); } } static void vThread2( void pvParameters ) { //vTaskSetApplicationTaskTag( NULL, ( void * ) 2 ); for(;;){ vTaskDelay( 10000 ); LED_1_LAT=1; while(U1STAbits.TRMT==0); UART1_sent((uchar)”Thread2 Runningrnrrr”,18); } } static void vIdle( void *pvParameters ) { //vTaskSetApplicationTaskTag( NULL, ( void * ) 1 ); for(;;){ Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop(); } } ~~~ Then create above three tasks by below code: ~~~ xTaskCreate( vThread1, “Thread1”, mainCHECK_TAKS_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); xTaskCreate( vThread2, “Thread2”, mainCHECK_TAKS_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); xTaskCreate( vIdle, “IdleThread”, mainCHECK_TAKS_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); ~~~ up to now, the program works well, the serial port keep out put “Thread1 Running” &”Thread2 Running” as I have expected. When I read through the FreeRTOS manual “Mastering the FreeRTOS™Real Time Kernel”, I chapter 3.8, it’s mentioned the FreeRTOS itself will create a Idle task, so I comment out the Idle task create by me, below is the only part I have modified: //xTaskCreate( vIdle, "IdleThread", mainCHECK_TAKS_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); the program supposed to work well by then, but the truth is after comment out this statement, the board keeps restarting. Really have no ideal why this happen, appreciate anyone can help me on this.

The Board keep restarting while comment out one of the task

Your vIdle() task should have no real effect here. How is UART1_sent() implemented? Does it include some mutual exclusion to prevent a context switch to the other task half way through a string being sent?

The Board keep restarting while comment out one of the task

Thank you for your reply Sir. The UART1sent do use UART interrupt for sending&receiving data, but I don’t believe it will affect context switching. because context switch are using Timer1 to trigger switch. Below are my code, BTW my chip is dsPIC33EV256GM106 from Microchip. ~~~ volatile uchar *UART1TXDATA; volatile uint UART1TXLEN; uchar UART1TXBUFF[UART1TXBUFFSIZE]; volatile uchar UART1RXBUFF[UART1RXBUFFSIZE]; volatile uchar UART1RXMEM; volatile bool UART1RETURN; void init_UART1(void)// initalize the UART1 {
U1MODEbits.STSEL = 0; // 1-Stop bit U1MODEbits.PDSEL = 0; // No Parity, 8-Data bits U1MODEbits.ABAUD = 0; // Auto-Baud disabled U1MODEbits.BRGH = 0; // Standard-Speed mode U1BRG = BRGVAL; // Baud Rate setting for 115200
U1STAbits.UTXISEL0 = 0; // bit <15,13>=0b10 Interrupt when the last bit is shifted into TSR, and as a result, the TX FIFO is empty
U1STAbits.UTXISEL1 = 1;
IEC0bits.U1TXIE = 1; // Enable UART TX interrupt
U1MODEbits.UARTEN = 1; // Enable UART
U1STAbits.UTXEN = 1; // Enable UART TX

U1STAbits.URXISEL=0b00; //Interrupt is set when any character is received
IEC0bits.U1RXIE=1;  // Enable UART RX interrupt

UART1_RX_MEM=0;
UART1_RETURN=false;
} void attribute((interrupt, autopsv)) _U1TXInterrupt(void) { IFS0bits.U1TXIF = 0; // Clear TX Interrupt flag while(U1STAbits.UTXBF==0 && UART1TXLEN>0) { U1TXREG = *UART1TXDATA++; UART1TX_LEN–; } } void attribute((interrupt, autopsv)) _U1RXInterrupt(void) { IFS0bits.U1RXIF = 0; // Clear TX Interrupt flag UART1RXBUFF[UART1RXMEM]=U1RXREG; U1TXREG=UART1RXBUFF[UART1RXMEM]; if(UART1RXBUFF[UART1RXMEM]==’r’) { UART1RETURN=true; U1TXREG=’n’; } UART1RXMEM++; if(UART1RXMEM>=UART1RXBUFFSIZE) UART1RXMEM-=UART1RXBUFFSIZE; } bool UART1sent(uchar data[], uint length) { if(U1STAbits.TRMT) { UART1TXDATA=data; U1TXREG = *UART1TXDATA++; UART1TX_LEN=length-1; return true; } return false;
} ~~~

The Board keep restarting while comment out one of the task

Sir The U1TXREG is a transmit register, once the data placed to this register, the UART moule will automatic shift the data out. and after the last bit of data shifted out, the UART module will trigger a interrupt to call the void attribute((interrupt, autopsv)) _U1TXInterrupt(void); So, basically, the UART1sent(uchar data[], uint length), just triggle the first byte of data to sent, and the remaining data will be send out by the interrupt.

The Board keep restarting while comment out one of the task

Consider what will happen one task starts to send a string, half the string has been transmitted, then a context switch occurs to the other task, and that task starts to send a string before the original string has been transmitted completely. Take a look through the mutual exclusion chapters in the book. http://www.freertos.org/Documentation/RTOS_book.html

The Board keep restarting while comment out one of the task

Actually the statement :while(U1STAbits.TRMT==0); is to prevent this from happen. if the “TRMT” bit is clear, that means the UART is occupied, task will wait it to set then start the string sending. Anyway, I will read the book through to see whether I can find some clue. Thanks again Sir!

The Board keep restarting while comment out one of the task

Actually the statement :while(U1STAbits.TRMT==0); is to prevent this from happen. if the “TRMT” bit is clear, that means the UART is
Maybe that will work, but I suspect you have a race condition there.

The Board keep restarting while comment out one of the task

Hello Sir, This problem still un-resolved, but I have dig in the source code, and one thing I noticed is the vPortYield function in portasm_dsPIC.s file did not switching the value in Program Counter (PC) register while switch tasks. Below is the code: ~~~ _vPortYield:
    PUSH    SR                      /* Save the SR used by the task.... */
    PUSH    W0                      /* ....then disable interrupts. */
    MOV     #32, W0
    MOV     W0, SR
    PUSH    W1                      /* Save registers to the stack. */
    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    ACCAL
    PUSH    ACCAH
    PUSH    ACCAU
    PUSH    ACCBL
    PUSH    ACCBH
    PUSH    ACCBU
    PUSH    DCOUNT
    PUSH    DOSTARTL
    PUSH    DOSTARTH
    PUSH    DOENDL
    PUSH    DOENDH


    PUSH    CORCON
    #ifdef  __HAS_EDS__
        PUSH    DSRPAG
        PUSH    DSWPAG
    #else
        PUSH    PSVPAG
    #endif /* __HAS_EDS__ */
    MOV     _uxCriticalNesting, W0      /* Save the critical nesting counter for the task. */
    PUSH    W0
    MOV     _pxCurrentTCB, W0           /* Save the new top of stack into the TCB. */
    MOV     W15, [W0]

    call    _vTaskSwitchContext

    MOV     _pxCurrentTCB, W0           /* Restore the stack pointer for the task. */
    MOV     [W0], W15
    POP     W0                          /* Restore the critical nesting counter for the task. */
    MOV     W0, _uxCriticalNesting
    #ifdef __HAS_EDS__
        POP     DSWPAG
        POP     DSRPAG
    #else
        POP     PSVPAG
    #endif /* __HAS_EDS__ */
    POP     CORCON
    POP     DOENDH
    POP     DOENDL
    POP     DOSTARTH
    POP     DOSTARTL
    POP     DCOUNT
    POP     ACCBU
    POP     ACCBH
    POP     ACCBL
    POP     ACCAU
    POP     ACCAH
    POP     ACCAL
    POP     TBLPAG
    POP     RCOUNT                      /* Restore the registers from the stack. */
    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

    return

    .end
~~~ even there is a function vTaskSwitchContext(viod) , but this function didn’t switching the PC, what it did is to find the highest priority task, and return the point of task’s TCB. Do you think this is the reason cause the error? BTW, I have put and error trap in my code, and it proved the board restart is caused by Address Error, That is to say the error is caused by wrong PC. Below is my error trap: ~~~ void attribute((interrupt, noautopsv)) _AddressError(void) { asm volatile(“nop”); // use volatile keyword to avoid the instruction being optimized away } ~~~

The Board keep restarting while comment out one of the task

I’m not sure I understand. The vTaskSwitchContex() function will work the same each time – why do you think its behaviour on just one call would be the problem?

The Board keep restarting while comment out one of the task

Hello Sir, What I mean is in the overall switching procedure there is no place operated the PC, I’m not focus on the function vTaskSwitchContex() .

The Board keep restarting while comment out one of the task

I just finished another experiment. I have disable all the user defined interrupt, and comment out the UART1sent function, just left a simple LED control instruction as shown below, the result still the same. ~~~ static void vThread1( void *pvParameters ) { //vTaskSetApplicationTaskTag( NULL, ( void * ) 1 ); for(;;){ vTaskDelay( 5000 ); LED1LAT=0; //while(U1STAbits.TRMT==0); //UART1sent((uchar*)”Thread1 Runningrnrrr”,18); } } ~~~ one of my finding is, once the FreeRTOS called the system default idle task prvIdleTask(), this error will happen. If I create the user defined idle task, and use the idle task to occupy all the idle time, the error never appear.

The Board keep restarting while comment out one of the task

What is configMINIMALSTACKSIZE set to? That sets the size of the stack used by the idle task.

The Board keep restarting while comment out one of the task

The configMINIMALSTACKSIZE is 105, I believe it’s large enough to store all the registers.

The Board keep restarting while comment out one of the task

My Chip have 16kByte RAM, Below are the configuration: ~~~

define configUSE_PREEMPTION 1

define configUSEIDLEHOOK 1

define configUSETICKHOOK 0

define configTICKRATEHZ ( ( TickType_t ) 1000 )

define configCPUCLOCKHZ ( ( unsigned long ) 64000000 ) /* Fosc / 2 */

define configMAX_PRIORITIES ( 4 )

define configMINIMALSTACKSIZE ( 105 )

define configTOTALHEAPSIZE ( ( size_t ) 5120 )

define configMAXTASKNAME_LEN ( 4 )

define configUSETRACEFACILITY 0

define configUSE16BIT_TICKS 1

define configIDLESHOULDYIELD 1

/* Co-routine definitions. */

define configUSECOROUTINES 1

define configMAXCOROUTINE_PRIORITIES ( 2 )

/* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */

define INCLUDE_vTaskPrioritySet 1

define INCLUDE_uxTaskPriorityGet 0

define INCLUDE_vTaskDelete 0

define INCLUDE_vTaskCleanUpResources 0

define INCLUDE_vTaskSuspend 1

define INCLUDE_vTaskDelayUntil 1

define INCLUDE_vTaskDelay 1

define configKERNELINTERRUPTPRIORITY 0x01

endif /* FREERTOSCONFIGH */

~~~

The Board keep restarting while comment out one of the task

The demo in the FreeRTOS download has this set to 115. Did you try increasing it?

The Board keep restarting while comment out one of the task

After set it to 205, still the same.

The Board keep restarting while comment out one of the task

Hello Sir, When I comment out the vCoRoutineSchedule from the code, the program goes well, I believe what cause the error is the the Co-Routine, any comment on that? void vApplicationIdleHook( void ) { /* Schedule the co-routines from within the idle task hook. */ //vCoRoutineSchedule(); }

The Board keep restarting while comment out one of the task

Hmm. If only you had mentioned you were actually calling something from the idle hook then that would have been found much earlier.

The Board keep restarting while comment out one of the task

I’m sorry Sir, I have focus on the PC value for long time until reach this point. But this calling is from the example port, I haven’t made any change. I’m curious what is the Co-Routine doing? If I remove it from the project, what will happen?

The Board keep restarting while comment out one of the task

Are you using the CoRoutines in FreeRTOS (I don’t as they have a somewhat clunky interface and seam intended for very resource limited processors)? One big requirement of the idle hook is that you can’t put anything that might block there, I am not sure that vCoRoutineSchedule meets that requirement, do the coroutines say to put it there?

The Board keep restarting while comment out one of the task

I suspect the issue was commenting out the code from the demo that was creating the co-routines, but leaving the code in the idle task that was trying to schedule them.

The Board keep restarting while comment out one of the task

Hi Richard, I’m not trying to use CoRoutines. I just trying to modify a FreeRTOS example port to my own project. The example port already used the CoRoutines. Actually I’m trying remove it from my project, but I don’t know what is the inpact if remove it directly.

The Board keep restarting while comment out one of the task

Sir, while this issue happens, I haven’t comment any of the code from sample port yet.

The Board keep restarting while comment out one of the task

If you don’t have co-routines being created you must comment out the vCoRoutineSchedule(), or if that is the only thing the idle task hook is doing, set configUSEIDLEHOOK to 0 in FreeRTOSConfig.h.

The Board keep restarting while comment out one of the task

Noted with thanks, Finally this problem resolved.