Thank you for your replay!
Maybe could you help me a little in my current porting problem then, please?
I have got problem in switching of 2 tasks
After when scheduler staterd fill task started and then check task and its all, anothet switchin doesnt occure however fill trander data per queue in cycle, so check has to be also in cycle as its in pending receive
Thats my main:
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "iolib.h"
int var1_addr;// = 0x1503FF00;
int var2_addr;// = 0x1503FF01;
int var3_addr;// = 0x1503FF03;
var1_addr = 0xFFFFFFFFB503FF00;//0x07FFFF00;//0x1503FF00;
var2_addr = 0xFFFFFFFFB503FF08;//0x07FFFF08;//0x1503FF01;
var3_addr = 0xFFFFFFFFB503FF0B;//0x07FFFF0B;
/* The rate at which data is sent to the queue, specified in milliseconds. */
#define mainQUEUE_SEND_FREQUENCY_MS ( 10 )
#define IOP1_BASE 0xffffffffB610FF50
/* 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 )
static void CheckTask( void *pvParameters );
static void FillTask( void *pvParameters );
static void taskA( void* );
static void taskB( void* );
///-----------------------------------------------------------
// The queue used by both tasks.
static xQueueHandle xQueue = NULL;
unsigned long ulTaskNumber[ 3 ];
uint8_t data[16];
//-----------------------------------------------------------
void main(void)
{
*((volatile uint16_t* const)(IOP1_BASE )) = 0x0000;
*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA55;
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );
if( xQueue != NULL )
{
xTaskCreate( CheckTask, ( signed char * ) "CheckTask", configMINIMAL_STACK_SIZE, NULL, ( tskIDLE_PRIORITY + 2 ), NULL ); // tskIDLE_PRIORITY + 2 , NULL );
xTaskCreate( FillTask, ( signed char * ) "FillTask", configMINIMAL_STACK_SIZE, NULL, ( tskIDLE_PRIORITY + 2 ), NULL ); //tskIDLE_PRIORITY + 1 , NULL );
*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA50;
vTaskStartScheduler();
}
for( ;; );
}
/*-----------------------------------------------------------*/
void vApplicationTickHook( void )
{
for( ;; ){
asm("nop");
}
}
/*-----------------------------------------------------------*/
static void FillTask( void *pvParameters )
{
portTickType xNextWakeTime;
const unsigned long ulValueToSend = 8;
*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA54;
for(int i = 0; i < 16; i++)
data[i] = i + 5;
for( ;;)
{
*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA54;
if( xQueueSend( xQueue, &ulValueToSend, 0 ) != pdPASS )
*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA01;
else
*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA03;
*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA00;
}
}
/*-----------------------------------------------------------*/
static void CheckTask( void *pvParameters )
{
unsigned long ulReceivedValue;
for(;;){
xQueueReceive( xQueue, &ulReceivedValue, 1000);///;portMAX_DELAY );
if( ulReceivedValue == 8 )
{*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0x55AA;
for(int i = 0;i < 16;i++)
if(data[i] != i + 5){
}
}
}
/*-----------------------------------------------------------*/
///
void vAssertCalled( const char *pcFileName, unsigned long ulLine )
{
asm("di");
*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA56;
*((volatile uint64_t* const)(var3_addr)) = 0x0000FFFF0000AA56;
for (;;);
}
And thas my hardware ticktimer handler
_CP0_TIM_VEC4_handler:
// Cause_DC = 1
mfc0 a0, C0_CAUSE
li a1, ~(1 << 27)
and a0, a0, a1
mtc0 a0, C0_CAUSE
ehb
di
ehb
ld sp, xISRStackTop
// LA sp, __stack
LA gp, _gp
/*.macro portSAVE_CONTEXT*/
// Make room for the context. First save the current status so it can be
//manipulated, and the cause and EPC registers so their original values are
//captured.
ADDU sp, sp, -CTX_SIZE
REG_S k1, CTX_K1(sp)
// k1 is used as the frame pointer.
ADDU k1, zero, sp
// Save the context into the space just created.
/*.macro _gpctx_save*/
/*ld sp, xISRStackTop*/
/* Save general registers. */
/* $27/k1 must be saved prior to using this macro. */
.irp num,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 \
20,21,22,23,24,25,26,28,29,30,31
REG_S $\num, CTX_REG(\num) (k1)
.endr
PTR_S $0, CTX_LINK(k1) /* Clear the link field. */
mfhi $9
REG_S $9, CTX_HI0(k1)
mflo $10
REG_S $10, CTX_LO0(k1)
/* Save CP0 registers. */
PTR_MFC0 $31, C0_EPC
ehb
/* mfc0 $10, C0_STATUS */
/* ehb */
REG_S $31, CTX_EPC(k1)
ehb
/* sw $10, CTX_STATUS(k1) */
.endm
// Save the stack pointer.
LA s6, uxSavedTaskStackPointer
REG_S k1, (s6)
REG_L k1, CTX_K1(sp)
/*.endm*/
jal vPortIncrementTick
nop
nop
/*.macro portRESTORE_CONTEXT*/
LA s6, uxSavedTaskStackPointer
REG_L k0, (s6)
// Restore the context.
/*.macro _gpctx_load*/
REG_L $9, CTX_HI0(k0)
REG_L $10, CTX_LO0(k0)
mthi $9
mtlo $10
/* Restore the general registers. */
.irp num,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, \
20,21,22,23,24,25
REG_L $\num, CTX_REG(\num) (k0)
.endr
/* Restore CP0 registers, kernel registers and stack with
interrupts disabled. */
/* di */
/* lw k1, CTX_STATUS(k0) */
/* mtc0 k1, C0_STATUS */
REG_L k1, CTX_EPC(k0)
PTR_MTC0 k1, C0_EPC
REG_L $27, CTX_REG(27) (k0)
REG_L $28, CTX_REG(28) (k0)
REG_L $29, CTX_REG(29) (k0)
REG_L $30, CTX_REG(30) (k0)
REG_L $31, CTX_REG(31) (k0)
/* Finally restore k0/$26. */
REG_L $26, CTX_REG(26)(k0)
/*.endm*/
LA sp, uxSavedTaskStackPointer
REG_L sp, (sp)
ADDU sp, sp, CTX_SIZE
/*.endm*/
// Count = 0
mtc0 zero, C0_COUNT
ehb
mfc0 a0, C0_CAUSE
li a1, (1 << 27)
or a0, a0, a1
mtc0 a0, C0_CAUSE
ehb
ei
ehb
eret
.end _CP0_TIM_VEC4_handler
And thats my software interrupt handler to yield
SW_VEC1_handler:
#mfc0 a0, C0_CAUSE
di
ehb
ld sp, xISRStackTop
LA gp, _gp
/*portYIELD_SAVE*/
// Make room for the context. First save the current status so it can be
//manipulated.
daddiu sp, sp, -CTX_SIZE
REG_S k1, CTX_K1(sp)
// k0cd is used as the frame pointer.
move k1, sp
// Save the context into the space just created.
/*_gpctx_save*/
.irp num,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 \
20,21,22,23,24,25,27,28,29,30,31
rdpgpr k1, $\num
REG_S k1, CTX_REG(\num) (k0)
.endr
rdpgpr k1, $26
nop
nop
REG_S k1, CTX_REG(26) (k0)
mfhi k1
REG_S k1, CTX_HI0(k0)
mflo k1
REG_S k1, CTX_LO0(k0)
/* Save CP0 registers. */
PTR_MFC0 k1, C0_EPC
REG_S k1, CTX_EPC(k0)
// Save the stack pointer to the task.
LA s7, pxCurrentTCB
REG_L s7, (s7)
REG_S k1, (s7)
jal vTaskSwitchContext
nop
nop
/*portYIELD_RESTORE*/
// Set the context restore register from the TCB.
LA s0, pxCurrentTCB
REG_L s0, (s0)
REG_L k0, (s0)
// The _gpctx_load restore code just wholesale copies the
// status register from the context back to the register loosing
// any changes that may have occured, 'status' is really global state
// You dont enable interrupts on one thread and not another...
// So we just copy the current status value into the saved value
// so nothing changes on the restore
//
/***/
mfc0 k1, C0_STATUS
sw k1, CTX_STATUS(k0)
/***/
/*_gpctx_load*/
REG_L $9, CTX_HI0(k0)
REG_L $10, CTX_LO0(k0)
mthi $9
mtlo $10
/* Restore the general registers. */
.irp num,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, \
20,21,22,23,24,25
REG_L $\num, CTX_REG(\num) (k0)
.endr
/* Restore CP0 registers, kernel registers and stack with
interrupts disabled. */
/* di */
/* lw k1, CTX_STATUS(k0) */
/* mtc0 k1, C0_STATUS */
REG_L k1, CTX_EPC(k0)
PTR_MTC0 k1, C0_EPC
REG_L $27, CTX_REG(27) (k0)
REG_L $28, CTX_REG(28) (k0)
REG_L $29, CTX_REG(29) (k0)
REG_L $30, CTX_REG(30) (k0)
REG_L $31, CTX_REG(31) (k0)
/* Finally restore k0/$26. */
REG_L $26, CTX_REG(26)(k0)
// Restore the stack pointer from the TCB.
LA sp, pxCurrentTCB
REG_L sp, (sp)
REG_L sp, (sp)
// Remove stack frame.
daddiu sp, sp, CTX_SIZE
ei
ehb
eret
.end _SW_VEC1_handler
And I see that I have two consecutive triggers of software interrupt, - one that I do after increment tick and additional from FreeRTOS in portYIELD_WITHIN_API() of xQueueReceive when I stopped in fill task
Please help !