PIC24 TNkernel. Трюки типа мысли в слух.
Макросы для инициализации системного таймера, ну и других таймеров тоже.
#define XTAL 16000
#define OS_TIME_PER_TICK 10 //mS
#define TMR_TIC_TIME(TMR_PRESCALER) (double)(2./XTAL*(1<<(2*TMR_PRESCALER+\
2*(TMR_PRESCALER+1)/3))) // mSec
#define TMR2_PRESCALER 1
#define TMR4_PRESCALER 3
int main(void){
//....
T2CONbits.TCKPS = TMR2_PRESCALER;
PR2 = (WORD)(OS_TIME_PER_TICK/TMR_TIC_TIME(TMR2_PRESCALER));
Использование сервисов РТОС и пользовательского прерывания.
Пришло на ум следующее.
Из пользовательского прерывания активируем системное прерывание(векторов то лишних много) в котором и вызываем сервис РТОС.
За что мне нравится ПИК24 vs 16&18 так это за возможность определения векторов прерываний в модуле задачи. Следовательно глобальные переменные как бы не используются. static в модуле ведь это не глобально :-)
adc.c
void TN_TASK TaskADC (void *par){
t_ADCMsg *pMsgAdc;
tn_queue_create(MSG_ADC_P, MsgBuffADC, SINGLE_MSG_ADC);
loop {
tn_queue_receive(MSG_ADC_P, (void**)&pMsgAdc, TN_WAIT_INFINITE);
...
}
}
static BYTE rgbData[sizeof(t_AdcElpOut)];
static t_ADCMsg ADCMsg={0, (t_AdcElpOut*)rgbData};
void ISR _T4Interrupt(void){
static BYTE bPhase, bData, bCRC;
IFS1bits.T4IF = 0;
switch(bPhase){
case ADCPhaseStart:{
...
}
...
case ADCPhaseDone:{
_MI2C1IF=1; // send message(MSG_ADC_P, (void*)&ADCMsg) in
_MI2C1IE=1; // tn_sys_interrupt(_MI2C1Interrupt)
...
}
}
}
tn_sys_interrupt(_MI2C1Interrupt){
tn_queue_isend_polling(MSG_ADC_P, (void*)&ADCMsg);
_MI2C1IE=0;
}