#pragma section @@CODE ROM_CODE #pragma nop #pragma ei #pragma di #pragma sfr /****************************************************************************** タスクシステム? なるほど、iTRONにはコンフィギュレータがあるはずだ。 →作りました ctr_mcu_config.rb 参照。 task_config.hが作成されます。 *****************************************************************************/ #include "renge_defs.h" #include "renge_task_intval.h" #include "renge_task_immediate.h" #include "..\WDT.h" #include "..\config.h" //****************************************************************************** bit renge_flg_interval; bit renge_task_interval_run_force; u8 system_time; extern const task_info tasks[]; #include "..\bsr_system.h" extern system_status_ system_status; //****************************************************************************** static void renge_task_immed_init(); static void renge_task_immed_del(); /****************************************************************************** 初期化。 ・タスクシステムの動的部分の初期化 ・インターバルタイマ *****************************************************************************/ void renge_init(){ renge_task_immed_init(); /* イベントタイマのセットなど 今回はRTCを流用しているのでコメントアウト #define renge_tick 19xxxxxxx [ms] renge_interval_init(); → RTC_init(); */ } /****************************************************************************** システムチックを進める *****************************************************************************/ /* void renge_interval(){ // RTCがやってくれる →__interrupt void int_rtc_int(); } */ /****************************************************************************** コンパイル時に決まっている、インターバル起動のタスク そのうち、逐次起動と混ぜるかもしれない。 *****************************************************************************/ err renge_task_interval_run(){ task_info *current_task; // インターバル起動 if( renge_flg_interval == 1 ){ renge_flg_interval = 0; for( current_task = &tasks[0]; current_task != &tasks[TSK_LAST]; current_task += 1 ) { current_task -> task(); } } return( ERR_SUCCESS ); } /***************************************************************************** ■逐一起動タスク■ ●task_immed を返す関数。 ●システムtick、何らかの割り込み(I2C通信完了など)で スリープから復帰したタイミングで実行されます。 ■返値 ERR_FINISED タスクを削除     それ以外 次のタイミングでまた実行 *****************************************************************************/ #define IMMED_RSV_TASKS_NUM 10 task_immed tasks_immed[ IMMED_RSV_TASKS_NUM ]; // タスクへのポインタの配列 u8 task_immed_index = 0; /************************************** **************************************/ void renge_task_immed_init(){ /* グローバルなメモリはスタートアップルーチンで0に初期化される u8 i; for( i = 0; i < IMMED_RSV_TASKS_NUM; i++ ){ tasks_immed[ i ] = (void *)0; } task_immed_index = 0; */ } /************************************** **************************************/ err renge_task_immed_add( task_immed new_task ){ static u8 lock = 0; DI(); if( lock != 0 ){ while(1){ NOP(); } } lock = 1; // 末尾の連続した空き領域の先頭でかつ、 // 重複登録を避ける { u8 i; u8 place; for( i = place = 0; i < IMMED_RSV_TASKS_NUM; i += 1 ) { if( tasks_immed[ i ] != ( void * )0 ) { place = i+1; } if( tasks_immed[ i ] == new_task ) // 重複登録 { // while(1){ NOP(); // アサートで止めたい // } lock = 0; EI(); return( ERR_ERR ); } } if( place < IMMED_RSV_TASKS_NUM ) { tasks_immed[ place ] = new_task; } else { // タスク登録しすぎ(無いはず // while(1){ NOP(); // アサートで止めたい // } lock = 0; EI(); return( ERR_ERR ); } } lock = 0; EI(); return( ERR_SUCCESS ); } /************************************** **************************************/ static void renge_task_immed_del(){ u8 i,j; // リスト前詰め i = 0; j = 1; for( ; j < IMMED_RSV_TASKS_NUM; j++) { if( tasks_immed[ i ] == (void *)0 ) { if( tasks_immed[ j ] != (void *)0 ) { tasks_immed[ i ] = tasks_immed[ j ]; tasks_immed[ j ] = (void *)0; i += 1; } } else { i += 1; } } } /************************************** **************************************/ err renge_task_immed_run(){ u8 task_id; u8 i; do{ i = 0; for( task_id = 0; task_id < IMMED_RSV_TASKS_NUM; task_id += 1 ){ if( tasks_immed[ task_id ] != 0 ){ if( tasks_immed[ task_id ]() == ERR_FINISED ){ tasks_immed[ task_id ] = (void*)0; } } } DI(); renge_task_immed_del(); EI(); // さらに登録されたり、再度実行の場合 // todo エラー繰り返しまくりだと困る for( task_id = 0; task_id < IMMED_RSV_TASKS_NUM; task_id += 1 ){ if( tasks_immed[ task_id ] != 0 ){ i += 1; } } }while( i != 0 ); #if 0 for( task_id = 0; task_id < IMMED_RSV_TASKS_NUM; task_id += 1 ){ if( tasks_immed[ task_id ] == 0 ){ break; } if( tasks_immed[ task_id ]() == ERR_FINISED ){ DI(); renge_task_immed_del( task_id ); EI(); } } // 整合性チェック { u8 j; u8 k = 0; for( j = 0; j < ( IMMED_RSV_TASKS_NUM -1); j += 1 ){ if( tasks_immed[ j ] != 0 ){ k += 1; } } if( k != task_immed_index ){ while(1){ NOP(); } } } #endif return( ERR_SUCCESS ); } /****************************************************************************** 単位は ms NOPを回すだけ、指定時間CPUを *占有します* 。 割り込みとか入るとその分遅れます。 少し誤差あります。 *****************************************************************************/ void wait_ms( u8 ms ){ u16 fine; WDT_Restart(); // まだ適当です! while( ms != 0 ){ ms--; #ifdef _OVERCLOCK_ fine = 860; #else fine = 430; #endif while( fine != 0 ){ fine -= 1; } } }