Thank you for your replay!
I’m using port for PIC32MZ, partly
My main is from demo:
/* Kernel includes. */
#include "common.h"
#include "runtime/mips_lib.h"
#include "periphery/eic.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
unsigned char indi;
unsigned char indi;
/* The rate at which data is sent to the queue, specified in milliseconds. */
#define mainQUEUE_SEND_FREQUENCY_MS ( 10 )
/* 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 ( 16 )
/* Priorities at which the tasks are created. */
#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
//-----------------------------------------------------------
// The tasks as described in the accompanying PDF application note.
static void CheckTask( void *pvParameters );
static void FillTask( void *pvParameters );
///-----------------------------------------------------------
// The queue used by both tasks.
static xQueueHandle xQueue = NULL;
// One array position is used for each task created by this demo. The
//variables in this array are set and cleared by the trace macros within
//FreeRTOS, and displayed on the logic analyzer window within the Keil IDE -
//the result of which being that the logic analyzer shows which task is
//running when.
unsigned long ulTaskNumber[ 3 ];
uint8_t data[16];
//-----------------------------------------------------------
int main()
{
BaseType_t xReturned1;
BaseType_t xReturned2;
SystemInit();
// stop dc Cause Register
__asm__ __volatile ("nop");
__asm__ __volatile ("mfc0 $26, $13, 0" );
__asm__ __volatile ("lui $27, 0x0800");
__asm__ __volatile ("or $26, $26, $27");
__asm__ __volatile ("mtc0 $26, $13, 0");
__asm__ __volatile ("nop");
indi = 0xAA ;
SetLeds(indi) ; // indi(GPIO)
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );
if( xQueue != NULL )
{
xReturned1 = xTaskCreate( CheckTask, ( signed char * ) "CheckTask", configMINIMAL_STACK_SIZE, NULL, ( tskIDLE_PRIORITY + 2 ), NULL ); // tskIDLE_PRIORITY + 2 , NULL );
xReturned2 = xTaskCreate( FillTask, ( signed char * ) "FillTask", configMINIMAL_STACK_SIZE, NULL, ( tskIDLE_PRIORITY + 2 ), NULL ); //tskIDLE_PRIORITY + 1 , NULL );
if(( xReturned1 == pdPASS ) && (xReturned2 == pdPASS))
{
indi = 0xFF ;
SetLeds(indi) ; // indi(GPIO)
}
vTaskStartScheduler();
}
///OutString("WARNING! This point in main must not be reached!\n");
// 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( ;; );
}
/*-----------------------------------------------------------*/
///
void vApplicationTickHook( void )
{
for( ;; ){
__asm__ ("nop");
}
}
/*-----------------------------------------------------------*/
static void FillTask( void *pvParameters )
{
portTickType xNextWakeTime;
const unsigned long ulValueToSend = 8;
for(int i = 0; i < 16; i++)
data[i] = i + 5;
// Initialise xNextWakeTime - this only needs to be done once.
for(;;)
{
// Send to the queue - causing the queue receive task to unblock and
//print out a message. 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.
if( xQueueSend( xQueue, &ulValueToSend, 0 ) != pdPASS )
{
indi = 0xF0 ;
SetLeds(indi) ; // indi(GPIO)
}
}
}
/*-----------------------------------------------------------*/
static void CheckTask( void *pvParameters )
{
unsigned long ulReceivedValue;
// Wait until something arrives in the queue - this task will block
//indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
//FreeRTOSConfig.h.
for(;;){
//To get here something must have been received from the queue, but
//is it the expected value? If it is, print out a pass message, if no,
//print out a fail message.
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
if( ulReceivedValue == 8 )
{
for(int i = 0;i < 16;i++)
if(data[i] != i + 5){
indi = 0x0F ;
SetLeds(indi) ; // indi(GPIO)
}
}
}
}
////
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
( void ) pcTaskName;
( void ) pxTask;
/* Run time task stack overflow checking is performed if
configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook function is
called if a task stack overflow is detected. Note the system/interrupt
stack is not checked. */
taskDISABLE_INTERRUPTS();
for( ;; );
}
////
/*-----------------------------------------------------------*/
///
void vApplicationMallocFailedHook( void )
{
taskDISABLE_INTERRUPTS();
for( ;; );
}
void vAssertCalled( const char *pcFile, unsigned long ulLine )
{
volatile char *pcFileName;
volatile unsigned long ulLineNumber;
/* Prevent things that are useful to view in the debugger from being
optimised away. */
pcFileName = ( char * ) pcFile;
( void ) pcFileName;
ulLineNumber = ulLine;
/* Set ulLineNumber to 0 in the debugger to break out of this loop and
return to the line that triggered the assert. */
while( ulLineNumber != 0 )
{
__asm volatile( "NOP" );
__asm volatile( "NOP" );
__asm volatile( "NOP" );
__asm volatile( "NOP" );
__asm volatile( "NOP" );
}
}
///
initialization of stack:
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
/* Ensure 8 byte alignment is maintained when leaving this function. */
pxTopOfStack--;
pxTopOfStack--;
*pxTopOfStack = (StackType_t) 0xDEADBEEF;
pxTopOfStack--;
*pxTopOfStack = (StackType_t) 0x12345678; // Word to which the stack pointer will be left pointing after context restore.
pxTopOfStack--;
*pxTopOfStack = (StackType_t) mips_getcr(); //_CP0_GET_CAUSE();
pxTopOfStack--;
*pxTopOfStack = (StackType_t) portINITIAL_SR;// CP0_STATUS
pxTopOfStack--;
*pxTopOfStack = (StackType_t) pxCode; //CP0_EPC
pxTopOfStack--;
*pxTopOfStack = (StackType_t) portTASK_RETURN_ADDRESS; //ra
pxTopOfStack -= 15;
*pxTopOfStack = (StackType_t) pvParameters; // Parameters to pass in.
pxTopOfStack -= 15;
*pxTopOfStack = (StackType_t) pdFALSE; //by default disable FPU context save on parts with FPU
return pxTopOfStack;
}
Start of scheduler:
BaseType_t xPortStartScheduler( void )
{
extern void vPortStartFirstTask( void );
extern void *pxCurrentTCB;
#if ( configCHECK_FOR_STACK_OVERFLOW > 2 )
{
/* Fill the ISR stack to make it easy to asses how much is being used. */
memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) );
}
#endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */
/* Kick off the highest priority task that has been created so far.
Its stack location is loaded into uxSavedTaskStackPointer. */
uxSavedTaskStackPointer = *( UBaseType_t * ) pxCurrentTCB;
mips_eic0_setmask(9);
//mips32_bissr(SR_IE);
__asm__ __volatile ("mfc0 $26, $12, 0");
__asm__ __volatile ("lui $27, 0x0000");
__asm__ __volatile ("ori $27, $27, 0x0001");
__asm__ __volatile ("or $26, $27");
__asm__ __volatile ("mtc0 $26, $12, 0");
__asm__ __volatile ("nop");
mips_setcount(0);
mips_setcompare(0x3000);
/* Start Counting */
// mips_biscr(CR_DC);
__asm__ __volatile ("mfc0 $26, $13, 0");
__asm__ __volatile ("lui $27, 0x0800");
__asm__ __volatile ("ori $27, $27, 0x0000");
__asm__ __volatile ("nor $27, $0, $27");
__asm__ __volatile ("and $26, $26, $27");
__asm__ __volatile ("mtc0 $26, $13, 0");
__asm__ __volatile ("nop");
__asm__ __volatile ("ehb");
vPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. */
prvTaskExitError();
return pdFALSE;
}
I’m using software interrupt to yeild
void vPortIncrementTick( void )
{
if( xTaskIncrementTick() != pdFALSE )
{
/* Pend a context switch. */
portYIELD();
}
}
where
#define portYIELD() \
{ \
mips_eic0_seticureq(2); \
}
void mips_eic0_seticureq (const uint32_t val)
{
*(volatile uint32_t* const)(EIC_IRQ_EN) = val;
}
For system tick(PortTick) I use coprocessor timer(in compare mode):
.set noat
.ent vPortTickInterruptHandler
.global vPortTickInterruptHandler
vPortTickInterruptHandler:
di
ehb
#rdpgpr sp, sp
#rdpgpr gp, gp
mtc0 zero, C0_COUNT
ehb
mfc0 a0, C0_CAUSE
li a1, (1 << 27)
or a0, a0, a1
mtc0 a0, C0_CAUSE
ehb
jal vPortIncrementTick
nop
nop
ei
ehb
eret
nop
nop
nop
.end vPortTickInterruptHandler
First task:
.ent vPortStartFirstTask
vPortStartFirstTask:
// Simply restore the context of the highest priority task that has been created so far.
portRESTORE_CONTEXT
nop
.end vPortStartFirstTask
portRESTORE_CONTEXT:
.macro portRESTORE_CONTEXT
la s6, uxInterruptNesting
lw s6, (s6)
addiu s6, s6, -1
bne s6, zero, 1f
nop
la s6, uxSavedTaskStackPointer
lw s5, (s6)
1:
// Restore the context.
// s6 is loaded as it was used as a scratch register and therefore saved as part of the interrupt context.
lw s7, 48(s5)
lw s6, 44(s5)
lw v0, 52(s5)
lw v1, 56(s5)
lw a0, 60(s5)
lw a1, 64(s5)
lw a2, 68(s5)
lw a3, 72(s5)
lw t0, 76(s5)
lw t1, 80(s5)
lw t2, 84(s5)
lw t3, 88(s5)
lw t4, 92(s5)
lw t5, 96(s5)
lw t6, 100(s5)
lw t7, 104(s5)
lw t8, 108(s5)
lw t9, 112(s5)
lw s8, 116(s5)
lw ra, 120(s5)
// Protect access to the k registers, and others.
di
ehb
// Decrement the nesting count.
la k0, uxInterruptNesting
lw k1, (k0)
addiu k1, k1, -1
sw k1, 0(k0)
// Restore the frame when there is no hardware FP support.
lw k0, portSTATUS_STACK_LOCATION(s5)
lw k1, portEPC_STACK_LOCATION(s5)
// Leave the stack in its original state. First load sp from s5, then restore s5 from the stack.
add sp, zero, s5
lw s5, 40(sp)
addiu sp, sp, portCONTEXT_SIZE
mtc0 k0, C0_STATUS
mtc0 k1, C0_EPC
ei
ehb
eret
nop
.endm
I suppose what scheduler is not run and can not run but I don’t understand the reason