int ki_wait (struct k_t *sem, int timeout) { DI (); if (0 < sem->cnt1) { sem->cnt1--; // Salute to Dijkstra k_sem_unclip (sem->nr); return (1); // ok: 1 bq we are not suspended } if (timeout < 0) // no luck, dont want to wait so bye bye { return (-2); } // from here we want to wait pRun->cnt2 = timeout; // 0 == wait forever if (timeout) { // so we can be removed if timeout occurs pRun->cnt3 = (int) sem; // nasty keep ref to semaphore in task stomach } sem->cnt1--; // Salute to Dijkstra k_sem_unclip (sem->nr); enQ (sem, deQ (pRun)); ki_task_shift (); // back again - have semaphore received signal or timeout ? pRun->cnt3 = 0; // reset ref to timer semaphore return ((char) (pRun->cnt2)); // 0: ok , -1: timeout }
int k_set_prio (char prio) { int i; if (!k_running) { return (-2); } DI (); if ((prio <= 0) || (DMY_PRIO <= prio)) // not legal value my friend { EI (); return (-1); } i = pRun->prio; pRun->prio = prio; prio_enQ (pAQ, deQ (pRun)); ki_task_shift (); EI (); return (i); }
int k_wait (struct k_t *sem, int timeout) { // copy of ki_wait just with EI()'s before leaving DI (); if (0 < sem->cnt1) { // lucky that we do not need to wait ? sem->cnt1--; // Salute to Dijkstra EI (); return (0); } if (timeout == -1) { // no luck, dont want to wait so bye EI (); return (-2); } // from here we have to wait pRun->cnt2 = timeout; // if 0 then wait forever if (timeout) pRun->cnt3 = (int) sem; // nasty keep ref to semaphore, // so we can be removed if timeout occurs sem->cnt1--; // Salute to Dijkstra enQ (sem, deQ (pRun)); ki_task_shift (); // call enables interrupt on return EI (); return (char) (pRun->cnt2); // 0: ok, -1: timeout }
int k_mut_ceil_enter (struct k_t *sem, int timeout) { int retval; DI (); // if ceiling_prio < 0 then its a normal wait call if (sem->ceiling_prio < 0) { retval = ki_wait (sem, timeout); // could call k_wait but just extra fct call EI (); return retval; } if (pRun->prio < sem->ceiling_prio) { // I have higher priority than ceiling :-( EI (); return CEILINGFAIL; } // now we play imm ceiling protocol sem->saved_prio = pRun->prio; // do im ceiling pRun->prio = sem->ceiling_prio; // dont need to reinsert in AQ bq ceil prio is higher or equal to mine and Im already in front of AQ prio_enQ (pAQ, deQ (pRun)); // resinsert me in AQ acc to nwe(old) priority retval = ki_wait (sem, timeout); // coming back interrupt is still disabled ! // chk if we did get semaphore if (retval < 0) { // NOPE we did not pRun->prio = sem->saved_prio; // reset to my old priority prio_enQ (pAQ, deQ (pRun)); // reinsert me in AQ acc to nwe(old) priority ki_task_shift (); // bq maybe started task has higher prio than me } EI (); return retval; // 0(has waited),1(straight through) : ok, -1: timeout }
int ki_wait (struct k_t *sem, int timeout) { // used by msg system DI (); if (0 < sem->cnt1) { // lucky that we do not need to wait ? sem->cnt1--; // Salute to Dijkstra return (0); } if (timeout == -1) { // no luck, dont want to wait so bye bye return (-2); } // from here we want to wait pRun->cnt2 = timeout; // if 0 then wait forever if (timeout) pRun->cnt3 = (int) sem; // nasty keep ref to semaphor // so we can be removed if timeout occurs sem->cnt1--; // Salute to Dijkstra enQ (sem, deQ (pRun)); ki_task_shift (); // call enables NOT interrupt on return return ((char) (pRun->cnt2)); // 0: ok, -1: timeout }
void k_release (void) { // let next run DI (); ki_task_shift (); EI (); }
void k_round_robbin (void) { // reinsert running task in activeQ if round robbin is selected DI (); prio_enQ (pAQ, deQ (pRun)); ki_task_shift (); EI (); }
int k_signal (struct k_t *sem) { int res; DI (); res = ki_signal (sem); if (res == 0) ki_task_shift (); EI (); return (res); }
char k_send (struct k_msg_t *pB, void *el) { char res; DI (); res = ki_send (pB, el); if (res == 0) // if new task in AQ == someone was waiting for msg { // if 1 then nobody was waiting so no neeed for task shift ki_task_shift (); } EI (); return (res); }
int k_prio_wait (struct k_t *sem, int timeout, char prio) { int retval; return -666; // no rdy for use // copy of ki_wait just with EI()'s before leaving DI (); if (0 < sem->cnt1) { // lucky that we do not need to wait ? sem->cnt1--; // Salute to Dijkstra // set prio pRun->prio = prio; // no need bq we are alrdy in front prio_enQ (pAQ, deQ (pRun)); EI (); return (0); } if (timeout == -1) { // no luck, dont want to wait so bye EI (); return (-2); } // from here we have to wait pRun->cnt2 = timeout; // if 0 then wait forever if (timeout) { pRun->cnt3 = (int) sem; // nasty keep ref to semaphore, } // so we can be removed if timeout occurs sem->cnt1--; // Salute to Dijkstra enQ (sem, deQ (pRun)); ki_task_shift (); // call enables interrupt on return pRun->cnt3 = 0; // reset ref to timer semaphore retval = pRun->cnt2; if (retval == 0) { // set prio pRun->prio = prio; // no need prio_enQ (pAQ, deQ (pRun)); } EI (); return retval; // 0: ok, -1: timeout }
char k_send (struct k_msg_t *pB, void *el) { char res; DI (); res = ki_send (pB, el); if (res == 0) ki_task_shift (); EI (); return (res); }
int k_signal (struct k_t *sem) { int res; DI (); res = ki_signal (sem); // 1: ok no task to AQ, 0: ok task to AQ if (res == 0) { ki_task_shift (); // bq maybe started task has higher prio than me } EI (); return (res); }
char k_send (struct k_msg_t *pB, void *el) { char res; DI (); res = ki_send (pB, el); if (res == 0) { // if new task in AQ == someone was waiting for msg ki_task_shift (); } EI (); return (res); }
int k_prio_signal (struct k_t *sem, char prio) { int res; DI (); res = ki_signal (sem); // set prio pRun->prio = prio; prio_enQ (pAQ, deQ (pRun)); ki_task_shift (); EI (); return (res); }
char k_mutex_leave (struct k_t *sem) { volatile char res; DI (); pRun->prio = (char) (pRun->maxv); // back to org prio prio_enQ (pAQ, deQ (pRun)); // chg pos in AQ acc to prio res = ki_signal (sem); if (res == 0) ki_task_shift (); EI (); return (res); }
int k_stop (int exitVal) { // DANGEROUS - handle with care - no isr timer control etc etc // I WILL NEVER USE IT DI (); // silencio if (!k_running) { EI (); return -1; } pmain_el->cnt1 = exitVal; // transfer in pocket //NASTY // stop tick timer isr TIMSKx &= ~(1 << TOIEx); stopp = 1; // back to main AQ.next = pmain_el; // we will be the next BRUTAL WAY TO DO IT NASTY ki_task_shift (); while (1); // you will never come here }
int k_set_prio (char prio) { if (!k_running) return (-1); DI (); if ((prio <= 0) || (DMY_PRIO <= prio)) { // not legal value my friend EI (); return (-2); } pRun->prio = prio; prio_enQ (pAQ, deQ (pRun)); ki_task_shift (); EI (); return (0); }
int k_mut_ceil_leave (struct k_t *sem) { int res; DI (); if (sem->ceiling_prio < 0) { // just std signal return k_signal (sem); } res = ki_signal (sem); // 1: ok no task to AQ, 0: ok task to AQ // coming back interrupt is still disabled ! pRun->prio = sem->saved_prio; // reset to my old priority prio_enQ (pAQ, deQ (pRun)); // resinsert me in AQ acc to nwe(old) priority ki_task_shift (); // bq maybe started task has higher prio than me EI (); return (res); }
//------------------------------------------------------------------------------------------- int k_start (int tm) { if (k_err_cnt) return -k_err_cnt; // will not start if errors during initialization DI (); // silencio #if defined(__AVR_ATmega32U4__) // 32u4 have no intern/extern clock source register #else ASSR &= ~(1 << AS2); // Select clock source: internal I/O clock 32u4 does not have this facility #endif if (0 < tm) { TIFR2 = 0x00; TCCR2B = 0x00; // silencio from this timer TCCR2A &= ~((1 << WGM21) | (1 << WGM20)); // Configure timer2 in normal mode (pure counting, no PWM etc.) TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); // Set prescaler to CPU clock divided by 1024 See p162 i atmega328 TIMSK2 &= ~(1 << OCIE2A); // Disable Compare Match A interrupt enable (only want overflow) TIMSK2 = 0x01; //HACK ? ... TCCR2A = 0x00; // normal /* for your and my own memory * We need to calculate a proper value to load the timer counter. * The following loads the value 131 into the Timer 2 counter register * The math behind this is: * (CPU frequency) / (prescaler value) = 16000000/1024= 15625 Hz ~= 64us. * 100Hz = 10msec * 10000usec / 64us = 156.25 * MAX(uint8) + 1 - 156 = 100; * JDN * 100 Hz ~ 100 * tm in msec -> * cnt = tm*1000/64 * ex: 10 msec: 10000/64 =156 * * some timer reg values: * 1msec: 240 5msec: 178 10msec: 100 15msec: 22 */ tcnt2 = 240; // 1 msec as basic heart beat // lets set divider for timer ISR if (tm <= 0) fakecnt = fakecnt_preset = 10; // 10 msec else fakecnt = fakecnt_preset = tm; TCNT2 = tcnt2; // Finally load end enable the timer TIMSK2 |= (1 << TOIE2); } pRun = &main_el; // just for ki_task_shift k_running = 1; DI (); ki_task_shift (); // bye bye from here EI (); while (1); // you will never come here return (0); // ok you will never come here hmmmm }
int k_start (int tm) { /* TCCRxB 48,88,168,328, 1280,2560 timer 0 and 2 has same prescaler config: 8 bit: 0 0 0 No clock source (Timer/Counter stopped). 0 0 1 clk T2S /(No prescaling) 0 1 0 clk T2S /8 (From prescaler) 2000000 intr/sec at 1 downcount 0 1 1 clk T2S /32 (From prescaler) 500000 intr/sec ... 1 0 0 clk T2S /64 (From prescaler) 250000 1 0 1 clk T2S /128 (From prescaler) 125000 1 1 0 clk T 2 S /256 (From prescaler) 62500 1 1 1 clk T 2 S /1024 (From prescaler) 15625 eq 15.625 count down for 1 millisec so 255 counts ~= 80.32 milli sec timer timer 1(328+megas), 3,4,5(megas only) 1280, 2560,2561 has same prescaler config : FOR 16 bits ! prescaler in cs2 cs1 cs0 0 0 0 none 0 0 1 /1 == none 0 1 0 /8 2000000 intr/sec 0 1 1 /64 250000 intr/sec 1 0 0 /256 62500 intr/sec 1 0 1 /1024 15625 intr/sec 16MHz Arduino -> 16000000/1024 = 15625 intr/second at one count 16MHz Arduino -> 16000000/256 = 62500 ticks/second -------------------------/64 = 250000 ticks/second ! NB 16 bit counter so values >= 65535 is not working ************************************************************************************* */ // will not start if errors during initialization if (k_err_cnt) { return -k_err_cnt; } // boundary check if (tm <= 0) { return -555; } else { k_tick_size = fakecnt = tm; fakecnt_preset = 0; // on duty for every interrupt } DI (); // silencio // outdated ? JDN NASTY #if defined(__AVR_ATmega32U4__) // 32u4 have no intern/extern clock source register #else // should be default ASSR &= ~(1 << AS2); // Select clock source: internal I/O clock 32u4 does not have this facility #endif #if (KRNLTMR !=0) TCCRxA = 0; TCCRxB = PRESCALE; // atm328s 2560,... if (F_CPU == 16000000L) { tcntValue = COUNTMAX - DIVV; } else { tcntValue = COUNTMAX - DIVV8; // 8 Mhz wwe assume } TCNTx = tcntValue; // let us start the show TIMSKx |= (1 << TOIEx); // enable interrupt #endif DI (); pRun = pmain_el; // just for ki_task_shift k_running = 1; ki_task_shift (); // bye bye from here EI (); // this while loop bq main are dummy while (!stopp) { } return (pmain_el->cnt1); // haps from pocket from kstop }