static void lp_ticker_arm_cd(void) { TIMER_T * timer3_base = (TIMER_T *) NU_MODBASE(timer3_modinit.modname); // Reset 8-bit PSC counter, 24-bit up counter value and CNTEN bit // NUC472/M451: See TIMER_CTL_RSTCNT_Msk // M480 timer3_base->CNT = 0; while (timer3_base->CNT & TIMER_CNT_RSTACT_Msk); // One-shot mode, Clock = 1 KHz uint32_t clk_timer3 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); uint32_t prescale_timer3 = clk_timer3 / TMR3_CLK_PER_SEC - 1; MBED_ASSERT((prescale_timer3 != (uint32_t) -1) && prescale_timer3 <= 127); MBED_ASSERT((clk_timer3 % TMR3_CLK_PER_SEC) == 0); // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451/M480. In M451/M480, TIMER_CNT is updated continuously by default. timer3_base->CTL &= ~(TIMER_CTL_OPMODE_Msk | TIMER_CTL_PSC_Msk/* | TIMER_CTL_CNTDATEN_Msk*/); timer3_base->CTL |= TIMER_ONESHOT_MODE | prescale_timer3/* | TIMER_CTL_CNTDATEN_Msk*/; cd_minor_clks = cd_major_minor_clks; cd_minor_clks = NU_CLAMP(cd_minor_clks, TMR_CMP_MIN, TMR_CMP_MAX); timer3_base->CMP = cd_minor_clks; TIMER_EnableInt(timer3_base); TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); TIMER_Start(timer3_base); }
void us_ticker_init(void) { if (ticker_inited) { return; } ticker_inited = 1; // Reset IP SYS_ResetModule(TIMER_MODINIT.rsetidx); // Select IP clock source CLK_SetModuleClock(TIMER_MODINIT.clkidx, TIMER_MODINIT.clksrc, TIMER_MODINIT.clkdiv); // Enable IP clock CLK_EnableModuleClock(TIMER_MODINIT.clkidx); // Timer for normal counter uint32_t clk_timer = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname)); uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1; MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127); MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0); uint32_t cmp_timer = TMR_CMP_MAX; MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX); // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451. In M451, TIMER_CNT is updated continuously by default. ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/; ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CMP = cmp_timer; NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var); NVIC_EnableIRQ(TIMER_MODINIT.irq_n); TIMER_EnableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname)); TIMER_Start((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname)); }
static void tmr3_vec(void) { TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); TIMER_ClearWakeupFlag((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); cd_major_minor_ms -= cd_minor_ms; if (cd_major_minor_ms > 0) { lp_ticker_arm_cd(); } }
static void tmr3_vec(void) { TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); TIMER_ClearWakeupFlag((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); cd_major_minor_clks = (cd_major_minor_clks > cd_minor_clks) ? (cd_major_minor_clks - cd_minor_clks) : 0; if (cd_major_minor_clks == 0) { // NOTE: lp_ticker_set_interrupt() may get called in lp_ticker_irq_handler(); lp_ticker_irq_handler(); } else { lp_ticker_arm_cd(); } }
timestamp_t lp_ticker_read() { if (! lp_ticker_inited) { lp_ticker_init(); } TIMER_T * timer2_base = (TIMER_T *) NU_MODBASE(timer2_modinit.modname); do { uint64_t major_minor_clks; uint32_t minor_clks; // NOTE: As TIMER_CNT = TIMER_CMP and counter_major has increased by one, TIMER_CNT doesn't change to 0 for one tick time. // NOTE: As TIMER_CNT = TIMER_CMP or TIMER_CNT = 0, counter_major (ISR) may not sync with TIMER_CNT. So skip and fetch stable one at the cost of 1 clock delay on this read. do { core_util_critical_section_enter(); // NOTE: Order of reading minor_us/carry here is significant. minor_clks = TIMER_GetCounter(timer2_base); uint32_t carry = (timer2_base->INTSTS & TIMER_INTSTS_TIF_Msk) ? 1 : 0; // When TIMER_CNT approaches TIMER_CMP and will wrap soon, we may get carry but TIMER_CNT not wrapped. Handle carefully carry == 1 && TIMER_CNT is near TIMER_CMP. if (carry && minor_clks > (TMR2_CLK_PER_TMR2_INT / 2)) { major_minor_clks = (counter_major + 1) * TMR2_CLK_PER_TMR2_INT; } else { major_minor_clks = (counter_major + carry) * TMR2_CLK_PER_TMR2_INT + minor_clks; } core_util_critical_section_exit(); } while (minor_clks == 0 || minor_clks == TMR2_CLK_PER_TMR2_INT); // Add power-down compensation return ((uint64_t) major_minor_clks * US_PER_SEC / TMR2_CLK_PER_SEC / US_PER_TICK); } while (0); }
void lp_ticker_set_interrupt(timestamp_t timestamp) { uint32_t now = lp_ticker_read(); wakeup_tick = timestamp; TIMER_Stop((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); /** * FIXME: Scheduled alarm may go off incorrectly due to wrap around. * Conditions in which delta is negative: * 1. Wrap around * 2. Newly scheduled alarm is behind now */ //int delta = (timestamp > now) ? (timestamp - now) : (uint32_t) ((uint64_t) timestamp + 0xFFFFFFFFu - now); int delta = (int) (timestamp - now); if (delta > 0) { cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC; lp_ticker_arm_cd(); } else { cd_major_minor_clks = cd_minor_clks = 0; /** * This event was in the past. Set the interrupt as pending, but don't process it here. * This prevents a recurive loop under heavy load which can lead to a stack overflow. */ NVIC_SetPendingIRQ(timer3_modinit.irq_n); } }
void can_init(can_t *obj, PinName rd, PinName td) { uint32_t can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD); uint32_t can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD); obj->can = (CANName)pinmap_merge(can_td, can_rd); MBED_ASSERT((int)obj->can != NC); const struct nu_modinit_s *modinit = get_modinit(obj->can, can_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == obj->can); // Reset this module SYS_ResetModule(modinit->rsetidx); // Enable IP clock CLK_EnableModuleClock(modinit->clkidx); obj->index = 0; pinmap_pinout(td, PinMap_CAN_TD); pinmap_pinout(rd, PinMap_CAN_RD); /* For M453 mbed Board Transmitter Setting (RS Pin) */ GPIO_SetMode(PA, BIT0| BIT1, GPIO_MODE_OUTPUT); PA0 = 0x00; PA1 = 0x00; CAN_Open((CAN_T *)NU_MODBASE(obj->can), 500000, CAN_NORMAL_MODE); can_filter(obj, 0, 0, CANStandard, 0); }
static void tmr0_vec(void) { TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname)); // NOTE: us_ticker_set_interrupt() may get called in us_ticker_irq_handler(); us_ticker_irq_handler(); }
void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable) { CAN_T *can_base = (CAN_T *) NU_MODBASE(obj->can); CAN_EnterInitMode(can_base, ((enable != 0 )? CAN_CON_IE_Msk :0) ); switch (irq) { case IRQ_ERROR: case IRQ_BUS: case IRQ_PASSIVE: can_base->CON = can_base->CON |CAN_CON_EIE_Msk; can_base->CON = can_base->CON |CAN_CON_SIE_Msk; break; case IRQ_RX: case IRQ_TX: case IRQ_OVERRUN: case IRQ_WAKEUP: can_base->CON = can_base->CON |CAN_CON_SIE_Msk; break; default: break; } CAN_LeaveInitMode(can_base); NVIC_SetVector(CAN0_IRQn, (uint32_t)&CAN0_IRQHandler); NVIC_EnableIRQ(CAN0_IRQn); }
void us_ticker_set_interrupt(timestamp_t timestamp) { /* Clear any previously pending interrupts */ us_ticker_clear_interrupt(); NVIC_ClearPendingIRQ(TIMER_MODINIT.irq_n); /* In continuous mode, counter will be reset to zero with the following sequence: * 1. Stop counting * 2. Configure new CMP value * 3. Restart counting * * This behavior is not what we want. To fix it, we could configure new CMP value * without stopping counting first. */ TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname); /* NOTE: Because H/W timer requests min compare value, our implementation would have alarm delay of * (TMR_CMP_MIN - interval_clk) clocks when interval_clk is between [1, TMR_CMP_MIN). */ uint32_t cmp_timer = timestamp * NU_TMRCLK_PER_TICK; cmp_timer = NU_CLAMP(cmp_timer, TMR_CMP_MIN, TMR_CMP_MAX); timer_base->CMP = cmp_timer; /* We can call ticker_irq_handler now. */ NVIC_EnableIRQ(TIMER_MODINIT.irq_n); }
void can_irq_free(can_t *obj) { CAN_DisableInt((CAN_T *)NU_MODBASE(obj->can), (CAN_CON_IE_Msk|CAN_CON_SIE_Msk|CAN_CON_EIE_Msk)); can_irq_ids[obj->index] = 0; NVIC_DisableIRQ(CAN0_IRQn); }
uint32_t us_ticker_read() { if (! ticker_inited) { us_ticker_init(); } TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname); return (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK); }
void lp_ticker_set_interrupt(timestamp_t timestamp) { uint32_t delta = timestamp - lp_ticker_read(); wakeup_tick = timestamp; TIMER_Stop((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC; lp_ticker_arm_cd(); }
void us_ticker_init(void) { if (us_ticker_inited) { return; } counter_major = 0; cd_major_minor_us = 0; cd_minor_us = 0; us_ticker_inited = 1; // Reset IP SYS_ResetModule(timer0hires_modinit.rsetidx); SYS_ResetModule(timer1hires_modinit.rsetidx); // Select IP clock source CLK_SetModuleClock(timer0hires_modinit.clkidx, timer0hires_modinit.clksrc, timer0hires_modinit.clkdiv); CLK_SetModuleClock(timer1hires_modinit.clkidx, timer1hires_modinit.clksrc, timer1hires_modinit.clkdiv); // Enable IP clock CLK_EnableModuleClock(timer0hires_modinit.clkidx); CLK_EnableModuleClock(timer1hires_modinit.clkidx); // Timer for normal counter uint32_t clk_timer0 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname)); uint32_t prescale_timer0 = clk_timer0 / TMR0HIRES_CLK_PER_SEC - 1; MBED_ASSERT((prescale_timer0 != (uint32_t) -1) && prescale_timer0 <= 127); MBED_ASSERT((clk_timer0 % TMR0HIRES_CLK_PER_SEC) == 0); uint32_t cmp_timer0 = TMR0HIRES_CLK_PER_TMR0HIRES_INT; MBED_ASSERT(cmp_timer0 >= TMR_CMP_MIN && cmp_timer0 <= TMR_CMP_MAX); // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451. In M451, TIMER_CNT is updated continuously by default. ((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname))->CTL = TIMER_PERIODIC_MODE | prescale_timer0/* | TIMER_CTL_CNTDATEN_Msk*/; ((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname))->CMP = cmp_timer0; NVIC_SetVector(timer0hires_modinit.irq_n, (uint32_t) timer0hires_modinit.var); NVIC_SetVector(timer1hires_modinit.irq_n, (uint32_t) timer1hires_modinit.var); NVIC_EnableIRQ(timer0hires_modinit.irq_n); NVIC_EnableIRQ(timer1hires_modinit.irq_n); TIMER_EnableInt((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname)); TIMER_Start((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname)); }
static void lp_ticker_arm_cd(void) { TIMER_T * timer3_base = (TIMER_T *) NU_MODBASE(timer3_modinit.modname); // Reset 8-bit PSC counter, 24-bit up counter value and CNTEN bit timer3_base->CTL |= TIMER_CTL_RSTCNT_Msk; // One-shot mode, Clock = 1 KHz uint32_t clk_timer3 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); uint32_t prescale_timer3 = clk_timer3 / TMR3_CLK_FREQ - 1; MBED_ASSERT((prescale_timer3 != (uint32_t) -1) && prescale_timer3 <= 127); timer3_base->CTL &= ~(TIMER_CTL_OPMODE_Msk | TIMER_CTL_PSC_Msk | TIMER_CTL_CNTDATEN_Msk); timer3_base->CTL |= TIMER_ONESHOT_MODE | prescale_timer3 | TIMER_CTL_CNTDATEN_Msk; cd_minor_ms = cd_major_minor_ms; cd_minor_ms = NU_CLAMP(cd_minor_ms, TMR_CMP_MIN * MS_PER_TMR3_CLK, TMR_CMP_MAX * MS_PER_TMR3_CLK); timer3_base->CMP = cd_minor_ms / MS_PER_TMR3_CLK; TIMER_EnableInt(timer3_base); TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); TIMER_Start(timer3_base); }
void lp_ticker_set_interrupt(uint32_t now, uint32_t time) { wakeup_tick = time; TIMER_Stop((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); int delta = (time > now) ? (time - now) : (uint32_t) ((uint64_t) time + 0xFFFFFFFFu - now); // NOTE: If this event was in the past, arm an interrupt to be triggered immediately. cd_major_minor_ms = delta * MS_PER_TICK; lp_ticker_arm_cd(); }
static void tmr1_vec(void) { TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname)); cd_major_minor_us = (cd_major_minor_us > cd_minor_us) ? (cd_major_minor_us - cd_minor_us) : 0; if (cd_major_minor_us == 0) { // NOTE: us_ticker_set_interrupt() may get called in us_ticker_irq_handler(); us_ticker_irq_handler(); } else { us_ticker_arm_cd(); } }
int can_write(can_t *obj, CAN_Message msg, int cc) { STR_CANMSG_T CMsg; CMsg.IdType = (uint32_t)msg.format; CMsg.FrameType = (uint32_t)!msg.type; CMsg.Id = msg.id; CMsg.DLC = msg.len; memcpy((void *)&CMsg.Data[0],(const void *)&msg.data[0], (unsigned int)8); return CAN_Transmit((CAN_T *)NU_MODBASE(obj->can), cc, &CMsg); }
void us_ticker_init(void) { if (ticker_inited) { /* By HAL spec, ticker_init allows the ticker to keep counting and disables the * ticker interrupt. */ us_ticker_disable_interrupt(); return; } ticker_inited = 1; /* Reset module * * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure. */ SYS_ResetModule_S(TIMER_MODINIT.rsetidx); /* Select IP clock source * * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure. */ CLK_SetModuleClock_S(TIMER_MODINIT.clkidx, TIMER_MODINIT.clksrc, TIMER_MODINIT.clkdiv); /* Enable IP clock * * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure. */ CLK_EnableModuleClock_S(TIMER_MODINIT.clkidx); TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname); // Timer for normal counter uint32_t clk_timer = TIMER_GetModuleClock(timer_base); uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1; MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127); MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0); uint32_t cmp_timer = TMR_CMP_MAX; MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX); // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451/M480/M2351. In M451/M480/M2351, TIMER_CNT is updated continuously by default. timer_base->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/; timer_base->CMP = cmp_timer; NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var); NVIC_DisableIRQ(TIMER_MODINIT.irq_n); TIMER_EnableInt(timer_base); TIMER_Start(timer_base); /* Wait for timer to start counting and raise active flag */ while(! (timer_base->CTL & TIMER_CTL_ACTSTS_Msk)); }
int can_read(can_t *obj, CAN_Message *msg, int handle) { STR_CANMSG_T CMsg; if(!CAN_Receive((CAN_T *)NU_MODBASE(obj->can), handle, &CMsg)) return 0; msg->format = (CANFormat)CMsg.IdType; msg->type = (CANType)!CMsg.FrameType; msg->id = CMsg.Id; msg->len = CMsg.DLC; memcpy(&msg->data[0], &CMsg.Data[0], 8); return 1; }
static void us_ticker_arm_cd(void) { TIMER_T * timer1_base = (TIMER_T *) NU_MODBASE(timer1hires_modinit.modname); cd_minor_us = cd_major_minor_us; // Reset 8-bit PSC counter, 24-bit up counter value and CNTEN bit timer1_base->CTL |= TIMER_CTL_RSTCNT_Msk; // One-shot mode, Clock = 1 MHz uint32_t clk_timer1 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname)); uint32_t prescale_timer1 = clk_timer1 / TMR1HIRES_CLK_PER_SEC - 1; MBED_ASSERT((prescale_timer1 != (uint32_t) -1) && prescale_timer1 <= 127); MBED_ASSERT((clk_timer1 % TMR1HIRES_CLK_PER_SEC) == 0); // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451. In M451, TIMER_CNT is updated continuously by default. timer1_base->CTL &= ~(TIMER_CTL_OPMODE_Msk | TIMER_CTL_PSC_Msk/* | TIMER_CTL_CNTDATEN_Msk*/); timer1_base->CTL |= TIMER_ONESHOT_MODE | prescale_timer1/* | TIMER_CTL_CNTDATEN_Msk*/; uint32_t cmp_timer1 = cd_minor_us / US_PER_TMR1HIRES_CLK; cmp_timer1 = NU_CLAMP(cmp_timer1, TMR_CMP_MIN, TMR_CMP_MAX); timer1_base->CMP = cmp_timer1; TIMER_EnableInt(timer1_base); TIMER_Start(timer1_base); }
void lp_ticker_init(void) { if (lp_ticker_inited) { return; } lp_ticker_inited = 1; counter_major = 0; cd_major_minor_clks = 0; cd_minor_clks = 0; wakeup_tick = (uint32_t) -1; // Reset module SYS_ResetModule(timer2_modinit.rsetidx); SYS_ResetModule(timer3_modinit.rsetidx); // Select IP clock source CLK_SetModuleClock(timer2_modinit.clkidx, timer2_modinit.clksrc, timer2_modinit.clkdiv); CLK_SetModuleClock(timer3_modinit.clkidx, timer3_modinit.clksrc, timer3_modinit.clkdiv); // Enable IP clock CLK_EnableModuleClock(timer2_modinit.clkidx); CLK_EnableModuleClock(timer3_modinit.clkidx); // Configure clock uint32_t clk_timer2 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); uint32_t prescale_timer2 = clk_timer2 / TMR2_CLK_PER_SEC - 1; MBED_ASSERT((prescale_timer2 != (uint32_t) -1) && prescale_timer2 <= 127); MBED_ASSERT((clk_timer2 % TMR2_CLK_PER_SEC) == 0); uint32_t cmp_timer2 = TMR2_CLK_PER_TMR2_INT; MBED_ASSERT(cmp_timer2 >= TMR_CMP_MIN && cmp_timer2 <= TMR_CMP_MAX); // Continuous mode // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451/M480. In M451/M480, TIMER_CNT is updated continuously by default. ((TIMER_T *) NU_MODBASE(timer2_modinit.modname))->CTL = TIMER_PERIODIC_MODE | prescale_timer2/* | TIMER_CTL_CNTDATEN_Msk*/; ((TIMER_T *) NU_MODBASE(timer2_modinit.modname))->CMP = cmp_timer2; // Set vector NVIC_SetVector(timer2_modinit.irq_n, (uint32_t) timer2_modinit.var); NVIC_SetVector(timer3_modinit.irq_n, (uint32_t) timer3_modinit.var); NVIC_EnableIRQ(timer2_modinit.irq_n); NVIC_EnableIRQ(timer3_modinit.irq_n); TIMER_EnableInt((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); // NOTE: TIMER_Start() first and then lp_ticker_set_interrupt(); otherwise, we may get stuck in lp_ticker_read() because // timer is not running. // Start timer TIMER_Start((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); // Schedule wakeup to match semantics of lp_ticker_get_compare_match() lp_ticker_set_interrupt(wakeup_tick); }
void us_ticker_set_interrupt(timestamp_t timestamp) { TIMER_Stop((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname)); int delta = (int) (timestamp - us_ticker_read()); if (delta > 0) { cd_major_minor_us = delta * US_PER_TICK; us_ticker_arm_cd(); } else { cd_major_minor_us = cd_minor_us = 0; /** * This event was in the past. Set the interrupt as pending, but don't process it here. * This prevents a recurive loop under heavy load which can lead to a stack overflow. */ NVIC_SetPendingIRQ(timer1hires_modinit.irq_n); } }
static void can_irq(CANName name, int id) { CAN_T *can = (CAN_T *)NU_MODBASE(name); uint32_t u8IIDRstatus; u8IIDRstatus = can->IIDR; if(u8IIDRstatus == 0x00008000) { /* Check Status Interrupt Flag (Error status Int and Status change Int) */ /**************************/ /* Status Change interrupt*/ /**************************/ if(can->STATUS & CAN_STATUS_RXOK_Msk) { can->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ can0_irq_handler(can_irq_ids[id], IRQ_RX); } if(can->STATUS & CAN_STATUS_TXOK_Msk) { can->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ can0_irq_handler(can_irq_ids[id], IRQ_TX); } /**************************/ /* Error Status interrupt */ /**************************/ if(can->STATUS & CAN_STATUS_EWARN_Msk) { can0_irq_handler(can_irq_ids[id], IRQ_ERROR); } if(can->STATUS & CAN_STATUS_BOFF_Msk) { can0_irq_handler(can_irq_ids[id], IRQ_BUS); } } else if (u8IIDRstatus!=0) { can0_irq_handler(can_irq_ids[id], IRQ_OVERRUN); CAN_CLR_INT_PENDING_BIT(can, ((can->IIDR) -1)); /* Clear Interrupt Pending */ } else if(can->WU_STATUS == 1) { can->WU_STATUS = 0; /* Write '0' to clear */ can0_irq_handler(can_irq_ids[id], IRQ_WAKEUP); } }
void us_ticker_init(void) { if (ticker_inited) { /* By HAL spec, ticker_init allows the ticker to keep counting and disables the * ticker interrupt. */ us_ticker_disable_interrupt(); return; } ticker_inited = 1; // Reset IP SYS_ResetModule(TIMER_MODINIT.rsetidx); // Select IP clock source CLK_SetModuleClock(TIMER_MODINIT.clkidx, TIMER_MODINIT.clksrc, TIMER_MODINIT.clkdiv); // Enable IP clock CLK_EnableModuleClock(TIMER_MODINIT.clkidx); TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname); // Timer for normal counter uint32_t clk_timer = TIMER_GetModuleClock(timer_base); uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1; MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127); MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0); uint32_t cmp_timer = TMR_CMP_MAX; MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX); timer_base->CTL = TIMER_CONTINUOUS_MODE; timer_base->PRECNT = prescale_timer; timer_base->CMPR = cmp_timer; NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var); NVIC_DisableIRQ(TIMER_MODINIT.irq_n); TIMER_EnableInt(timer_base); TIMER_Start(timer_base); /* Wait for timer to start counting and raise active flag */ while(! (timer_base->CTL & TIMER_CTL_TMR_ACT_Msk)); }
int can_mode(can_t *obj, CanMode mode) { CAN_T *can_base = (CAN_T *) NU_MODBASE(obj->can); int success = 0; switch (mode) { case MODE_RESET: CAN_LeaveTestMode(can_base); success = 1; break; case MODE_NORMAL: CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk); success = 1; break; case MODE_SILENT: CAN_EnterTestMode(can_base, CAN_TEST_SILENT_Msk); success = 1; break; case MODE_TEST_LOCAL: case MODE_TEST_GLOBAL: CAN_EnterTestMode(can_base, CAN_TEST_LBACK_Msk); success = 1; break; case MODE_TEST_SILENT: CAN_EnterTestMode(can_base, CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); success = 1; break; default: success = 0; break; } return success; }
void lp_ticker_init(void) { if (lp_ticker_inited) { return; } lp_ticker_inited = 1; counter_major = 0; cd_major_minor_ms = 0; cd_minor_ms = 0; wakeup_tick = TMR_CMP_MAX * MS_PER_TMR2_CLK / MS_PER_TICK; // Reset module SYS_ResetModule(timer2_modinit.rsetidx); SYS_ResetModule(timer3_modinit.rsetidx); // Select IP clock source CLK_SetModuleClock(timer2_modinit.clkidx, timer2_modinit.clksrc, timer2_modinit.clkdiv); CLK_SetModuleClock(timer3_modinit.clkidx, timer3_modinit.clksrc, timer3_modinit.clkdiv); // Enable IP clock CLK_EnableModuleClock(timer2_modinit.clkidx); CLK_EnableModuleClock(timer3_modinit.clkidx); // Configure clock uint32_t clk_timer2 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); uint32_t prescale_timer2 = clk_timer2 / TMR2_CLK_FREQ - 1; MBED_ASSERT((prescale_timer2 != (uint32_t) -1) && prescale_timer2 <= 127); uint32_t cmp_timer2 = MS_PER_TMR2_INT / MS_PER_TMR2_CLK; MBED_ASSERT(cmp_timer2 >= TMR_CMP_MIN && cmp_timer2 <= TMR_CMP_MAX); // Continuous mode ((TIMER_T *) NU_MODBASE(timer2_modinit.modname))->CTL = TIMER_PERIODIC_MODE | prescale_timer2 | TIMER_CTL_CNTDATEN_Msk; ((TIMER_T *) NU_MODBASE(timer2_modinit.modname))->CMP = cmp_timer2; // Set vector NVIC_SetVector(timer2_modinit.irq_n, (uint32_t) timer2_modinit.var); NVIC_SetVector(timer3_modinit.irq_n, (uint32_t) timer3_modinit.var); NVIC_EnableIRQ(timer2_modinit.irq_n); NVIC_EnableIRQ(timer3_modinit.irq_n); TIMER_EnableInt((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); // Schedule wakeup to match semantics of lp_ticker_get_compare_match() lp_ticker_set_interrupt(lp_ticker_read(), wakeup_tick); // Start timer TIMER_Start((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); }
uint32_t lp_ticker_read() { if (! lp_ticker_inited) { lp_ticker_init(); } TIMER_T * timer2_base = (TIMER_T *) NU_MODBASE(timer2_modinit.modname); do { uint64_t major_minor_ms; uint32_t minor_ms; // NOTE: As TIMER_CNT = TIMER_CMP and counter_major has increased by one, TIMER_CNT doesn't change to 0 for one tick time. // NOTE: As TIMER_CNT = TIMER_CMP or TIMER_CNT = 0, counter_major (ISR) may not sync with TIMER_CNT. So skip and fetch stable one at the cost of 1 clock delay on this read. do { uint32_t _state = __get_PRIMASK(); __disable_irq(); // NOTE: Order of reading minor_us/carry here is significant. minor_ms = TIMER_GetCounter(timer2_base) * MS_PER_TMR2_CLK; uint32_t carry = (timer2_base->INTSTS & TIMER_INTSTS_TIF_Msk) ? 1 : 0; // When TIMER_CNT approaches TIMER_CMP and will wrap soon, we may get carry but TIMER_CNT not wrapped. Hanlde carefully carry == 1 && TIMER_CNT is near TIMER_CMP. if (carry && minor_ms > (MS_PER_TMR2_INT / 2)) { major_minor_ms = (counter_major + 1) * MS_PER_TMR2_INT; } else { major_minor_ms = (counter_major + carry) * MS_PER_TMR2_INT + minor_ms; } __set_PRIMASK(_state); } while (minor_ms == 0 || minor_ms == MS_PER_TMR2_INT); // Add power-down compensation return (major_minor_ms / MS_PER_TICK); } while (0); }
void us_ticker_clear_interrupt(void) { TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname)); }
static void tmr0_vec(void) { TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname)); counter_major ++; }