/**************************************************************************//** * * mss_hal_init * * @brief initialize mss HAL unit, shall do the following tasks: * - setup CPU frequency (if necessary) * - if @ref MSS_TASK_USE_TIMER set to TRUE, this function shall * setup timer interrupt which shall increment the timer counter * mss_timer_tick_cnt and call @ref mss_timer_tick() function * periodically * - if @ref MSS_PREEMPTIVE_SCHEDULING is set to TRUE, setup the * software interrupt or hardware interrupt which is used to call * mss_scheduler during preemption * * @param - * * @return - * * @remark the global interrupt shall not be enabled here * ******************************************************************************/ void mss_hal_init(void) { // check calibration data MSS_DEBUG_CHECK(CALBC1_8MHZ != 0xFF); MSS_DEBUG_CHECK(CALDCO_8MHZ != 0xFF); // set basic clock module+ BCSCTL1 = XT2OFF | CALBC1_8MHZ; DCOCTL = CALDCO_8MHZ; BCSCTL2 |= DIVS_3; // 1 MHz SMCLK BCSCTL3 = LFXT1S_2; // source VLOCLK as ACLK // wait until clock stabilizes do { IFG1 &= ~OFIFG; __delay_cycles(100); } while(IFG1 & OFIFG); #if (MSS_TASK_USE_TIMER == TRUE) // use watchdog timer to generate mss timer interrupt tick WDTCTL = WDT_MDLY_0_5; IE1 |= WDTIE; #endif #if (MSS_PREEMPTIVE_SCHEDULING == TRUE) // enable interrupt CACTL1 = CAIE; #endif /* (MSS_PREEMPTIVE_SCHEDULING == TRUE) */ }
/**************************************************************************//** * * mss_timer_get_state * * @brief get the state of a mss timer. will automatically reset the timer * state to MSS_TIMER_STATE_IDLE if the current state is * MSS_TIMER_STATE_EXPIRED_ONE_SHOT or * MSS_TIMER_STATE_RUNNING_PERIODIC if current state is * MSS_TIMER_STATE_EXPIRED_PERIODIC * * @param[in] hdl timer handle * * @return true if success, false if failed * ******************************************************************************/ mss_timer_state_t mss_timer_get_state(mss_timer_t hdl) { mss_int_flag_t int_flag; mss_timer_state_t state; // check timer handler MSS_DEBUG_CHECK(hdl != MSS_TIMER_INVALID_HDL); MSS_ENTER_CRITICAL_SECTION(int_flag); // return timer state state = hdl->state; if(state & TIMER_ALL_EXPIRED_MASK) { if(hdl->reload_tick == 0) { // set timer state as idle hdl->state = MSS_TIMER_STATE_IDLE; } else { // set timer state as idle hdl->state = MSS_TIMER_STATE_RUNNING_PERIODIC; } } MSS_LEAVE_CRITICAL_SECTION(int_flag); return (state); }
/**************************************************************************//** * * mss_timer_init * * @brief initialize mss timer module * * @param - * * @return - * ******************************************************************************/ void mss_timer_init(void) { uint8_t i; // initialize timer blocks for(i=0 ; i<MSS_MAX_NUM_OF_TIMER ; i++) { timer_tbl[i].task_id = MSS_INVALID_TASK_ID; timer_tbl[i].state = MSS_TIMER_STATE_IDLE; timer_tbl[i].expired_tick = 0; timer_tbl[i].reload_tick = 0; } // initialize linked list timer active_timer_llist = llist_create(); MSS_DEBUG_CHECK(active_timer_llist != LLIST_INVALID_HDL); }
/**************************************************************************//** * * mss_timer_stop * * @brief stop a running mss timer (timer state is reset back to * MSS_TIMER_STATE_IDLE) * * @param[in] hdl timer handle * * @return true if success, false if failed * ******************************************************************************/ void mss_timer_stop(mss_timer_t hdl) { mss_int_flag_t int_flag; // check timer handler MSS_DEBUG_CHECK(hdl != MSS_TIMER_INVALID_HDL); MSS_ENTER_CRITICAL_SECTION(int_flag); if(hdl->state & TIMER_ALL_RUNNING_MASK) { // search for the timer and remove it llist_remove(active_timer_llist, hdl); // set timer state as idle hdl->state = MSS_TIMER_STATE_IDLE; } MSS_LEAVE_CRITICAL_SECTION(int_flag); }
/**************************************************************************//** * * timer_start * * @brief start a mss timer * * @param[in] hdl timer handle * @param[in] tick number of timer ticks to run * (maximum value is ((sizeof(mss_timer_tick_t)/2)-1) ) * @param[in] reload number of ticks of reloading/periodic timer. 0 means * that it is a one shot timer (maximum value is * ((sizeof(mss_timer_tick_t)/2)-1) ) * * @return true if success, false if failed * ******************************************************************************/ static bool timer_start(mss_timer_t hdl, mss_timer_tick_t tick, mss_timer_tick_t reload) { bool ret = false; mss_int_flag_t int_flag; // check timer handler MSS_DEBUG_CHECK(hdl != MSS_TIMER_INVALID_HDL); if((!(tick & MSB_TMR_MASK)) && (tick > 0)) { // disable timer interrupt to enable re-setting the timer MSS_ENTER_CRITICAL_SECTION(int_flag); // set timer to active state and set timer counter hdl->expired_tick = mss_timer_tick_cnt + tick; hdl->reload_tick = reload; if(!(hdl->state & TIMER_ALL_RUNNING_MASK)) { // put the timer into the active timer linked list llist_add_first(active_timer_llist, hdl); } // set new state hdl->state = (reload > 0) ? MSS_TIMER_STATE_RUNNING_PERIODIC : MSS_TIMER_STATE_RUNNING_ONE_SHOT; // sort the active timer list llist_sort(active_timer_llist, timer_cmp); // return true ret = true; MSS_LEAVE_CRITICAL_SECTION(int_flag); } return ret; }