示例#1
0
/**
  * @brief  This function handles EXTI Lines 15 to 10 interrupts requests.
  * @param  None
  * @retval None
  */
void EXTI15_10_IRQHandler(void)
{
  if(EXTI_GetITStatus(TAMPER_BUTTON_EXTI_LINE) != RESET)
  {
    if(uwIndex == 0)
    {
      /* Configure the BASEPRI register to 0x40 (Preemption priority = 1).
         Only IRQ with higher preemption priority than 1 are permitted.
         This will mask TIM3 and TIM4 IRQ from generation. */
      __set_BASEPRI(0x40);
      uwIndex++;
    }
    else
    {
      /* Configure the BASEPRI register to 0x00 (Preemption priority = 0).
         When this BASEPRI register is set to 0, it has no effect on the current
         priority.
         TIM2, TIM3 and TIM4 generation is controlled by NVIC priority registers. */
      __set_BASEPRI(0x00);
      uwIndex = 0;
    }

    /* Clears the TAMPER Button EXTI line pending bit */
    EXTI_ClearITPendingBit(TAMPER_BUTTON_EXTI_LINE);
  }
}
示例#2
0
文件: nOSPort.c 项目: jimtremblay/nOS
void nOS_SwitchContext (void)
{
#if (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO > 0)
    nOS_StatusReg   sr = __get_BASEPRI();
#endif

    /* Request context switch */
    *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL;

    /* Leave critical section */
#if (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO > 0)
    __set_BASEPRI(0);
#else
    __enable_interrupt();
#endif
    __DSB();
    __ISB();

    __no_operation();

    /* Enter critical section */
#if (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO > 0)
    __set_BASEPRI(sr);
#else
    __disable_interrupt();
#endif
    __DSB();
    __ISB();
}
示例#3
0
文件: arch.c 项目: nqbit/lk
void arch_early_init(void)
{

    arch_disable_ints();

#if     (__CORTEX_M >= 0x03) || (CORTEX_SC >= 300)
    uint i;
    /* set the vector table base */
    SCB->VTOR = (uint32_t)&vectab;

#if ARM_CM_DYNAMIC_PRIORITY_SIZE
    /* number of priorities */
    for (i=0; i < 7; i++) {
        __set_BASEPRI(1 << i);
        if (__get_BASEPRI() != 0)
            break;
    }
    arm_cm_num_irq_pri_bits = 8 - i;
    arm_cm_irq_pri_mask = ~((1 << i) - 1) & 0xff;
#endif

    /* clear any pending interrupts and set all the vectors to medium priority */
    uint groups = (SCnSCB->ICTR & 0xf) + 1;
    for (i = 0; i < groups; i++) {
        NVIC->ICER[i] = 0xffffffff;
        NVIC->ICPR[i] = 0xffffffff;
        for (uint j = 0; j < 32; j++) {
            NVIC_SetPriority(i*32 + j, arm_cm_medium_priority());
        }
    }

    /* leave BASEPRI at 0 */
    __set_BASEPRI(0);

    /* set priority grouping to 0 */
    NVIC_SetPriorityGrouping(0);

    /* enable certain faults */
    SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_MEMFAULTENA_Msk);

    /* set the svc and pendsv priority level to pretty low */
#endif
    NVIC_SetPriority(SVCall_IRQn, arm_cm_lowest_priority());
    NVIC_SetPriority(PendSV_IRQn, arm_cm_lowest_priority());

    /* set systick and debugmonitor to medium priority */
    NVIC_SetPriority(SysTick_IRQn, arm_cm_medium_priority());

#if (__CORTEX_M >= 0x03)
    NVIC_SetPriority(DebugMonitor_IRQn, arm_cm_medium_priority());
#endif

#if ARM_WITH_CACHE
    arch_enable_cache(UCACHE);
#endif
}
示例#4
0
int HAL_disable_irq() {
    // We are blocking any interrupts with priorities >= 2, without
    // affecting SoftDevice interrupts which run with priorities 0 and 1.
    int st = __get_BASEPRI();
    __set_BASEPRI(APP_IRQ_PRIORITY_HIGHEST << (8 - __NVIC_PRIO_BITS));
    return st;
}
/* If FreeRTOS is not running, then we rely on RIT service to call this function,
 * otherwise we rely on FreeRTOS tick hook to provide system timer
 */
static void hl_periodic_service(void)
{
    sys_watchdog_feed();

    /* If FreeRTOS is running, user should use a dedicated task to call mesh service,
     * so we will not call it if freertos is running
     */
    if (taskSCHEDULER_RUNNING == xTaskGetSchedulerState()) {
        g_system_uptime_ms += MS_PER_TICK();

        /* We don't need RIT if FreeRTOS is running */
        if (sys_rit_running()) {
            sys_rit_disable();

            /* The timer value so far may be an odd number, and if MS_PER_TICK() is not 1
             * then we may increment it like 12, 22, 32, etc. so round this number once.
             */
            g_system_uptime_ms = (g_system_uptime_ms / 10) * 10;
        }
    }
    else {
        g_system_uptime_ms += g_time_per_rit_isr_ms;
        wireless_service();

        /**
         * Small hack to support interrupts if FreeRTOS is not running :
         * FreeRTOS API resets our base priority register, then all
         * interrupts higher priority than IP_SYSCALL will not get locked out.
         *   @see more notes at isr_priorities.h.  @see IP_SYSCALL
         */
        __set_BASEPRI(0);
    }
}
示例#6
0
/**
\brief Test case: TC_CoreFunc_BASEPRI
\details
- Check if __get_BASEPRI and __set_BASEPRI intrinsic can be used to manipulate BASEPRI.
- Check if __set_BASEPRI_MAX intrinsic can be used to manipulate BASEPRI.
*/
void TC_CoreFunc_BASEPRI(void) {
  uint32_t orig = __get_BASEPRI();

  uint32_t basepri = ~orig & 0x80U;
  __set_BASEPRI(basepri);
  uint32_t result = __get_BASEPRI();

  ASSERT_TRUE(result == basepri);

  __set_BASEPRI(orig);

  __set_BASEPRI_MAX(basepri);
  result = __get_BASEPRI();

  ASSERT_TRUE(result == basepri);
}
示例#7
0
文件: arch.c 项目: herhut-ggl/lk
void _arm_cm_set_irqpri(uint32_t pri)
{
	if (pri == 0) {
		__disable_irq(); // cpsid i
		__set_BASEPRI(0);
	} else if (pri >= 256) {
		__set_BASEPRI(0);
		__enable_irq();
	} else {
		uint32_t _pri = pri & arm_cm_irq_pri_mask;

		if (_pri == 0)
			__set_BASEPRI(1 << (8 - arm_cm_num_irq_pri_bits));
		else
			__set_BASEPRI(_pri);
		__enable_irq(); // cpsie i
	}
}
示例#8
0
文件: usb_lld.c 项目: DTFUHF/TauLabs
/**
 * @brief   Outgoing packets handler.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 *
 * @notapi
 */
static bool_t otg_txfifo_handler(USBDriver *usbp, usbep_t ep) {

  /* The TXFIFO is filled until there is space and data to be transmitted.*/
  while (TRUE) {
    uint32_t n;

    /* Transaction end condition.*/
    if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize)
      return TRUE;

    /* Number of bytes remaining in current transaction.*/
    n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt;
    if (n > usbp->epc[ep]->in_maxsize)
      n = usbp->epc[ep]->in_maxsize;

    /* Checks if in the TXFIFO there is enough space to accommodate the
       next packet.*/
    if (((usbp->otg->ie[ep].DTXFSTS & DTXFSTS_INEPTFSAV_MASK) * 4) < n)
      return FALSE;

#if STM32_USB_OTGFIFO_FILL_BASEPRI
    __set_BASEPRI(CORTEX_PRIORITY_MASK(STM32_USB_OTGFIFO_FILL_BASEPRI));
#endif
    /* Handles the two cases: linear buffer or queue.*/
    if (usbp->epc[ep]->in_state->txqueued) {
      /* Queue associated.*/
      otg_fifo_write_from_queue(usbp->otg->FIFO[ep],
                                usbp->epc[ep]->in_state->mode.queue.txqueue,
                                n);
    }
    else {
      /* Linear buffer associated.*/
      otg_fifo_write_from_buffer(usbp->otg->FIFO[ep],
                                 usbp->epc[ep]->in_state->mode.linear.txbuf,
                                 n);
      usbp->epc[ep]->in_state->mode.linear.txbuf += n;
    }
    usbp->epc[ep]->in_state->txcnt += n;
  }
#if STM32_USB_OTGFIFO_FILL_BASEPRI
  __set_BASEPRI(0);
#endif
}
示例#9
0
void nOS_SwitchContext (void)
{
    nOS_StatusReg   sr = __get_BASEPRI();

    /* Request context switch */
    *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL;

    /* Leave critical section */
    __set_BASEPRI(0);
    __DSB();
    __ISB();

    __no_operation();

    /* Enter critical section */
    __set_BASEPRI(sr);
    __DSB();
    __ISB();
}
示例#10
0
void lock_interrupts(void)
{
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
	__disable_irq();
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
	__set_BASEPRI(_EXC_IRQ_DEFAULT_PRIO);
#else
#error Unknown ARM architecture
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
}
示例#11
0
文件: main.c 项目: onelife/rt-thread
void board_init(void)
{
	/* Set the Vector Table base location at 0x08000000 */
	NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

    /* Set NVIC Preemption Priority Bits: 0 bit for pre-emption, 4 bits for
       subpriority */
    NVIC_SetPriorityGrouping(NVIC_PriorityGroup_0);

    /* Set Base Priority Mask Register */
    __set_BASEPRI(0x00UL);
}
void restoreInterruptMasking(const InterruptMask interruptMask)
{
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0

	__set_BASEPRI(interruptMask);

#else	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0

	__set_PRIMASK(interruptMask);

#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
}
InterruptMask disableInterruptMasking()
{
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0

	const auto interruptMask = __get_BASEPRI();
	__set_BASEPRI(0);
	return interruptMask;

#else	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0

	const auto interruptMask = __get_PRIMASK();
	__enable_irq();
	return interruptMask;

#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
}
示例#14
0
文件: board.c 项目: onelife/rt-thread
/***************************************************************************//**
 * @brief
 *   Configure the address of vector table
 *
 * @details
 *
 * @note
 *
 ******************************************************************************/
static void NVIC_Configuration(void)
{
#ifdef  VECT_TAB_RAM
	/* Set the Vector Table base location at 0x20000000 */
	NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  /* VECT_TAB_FLASH  */
	/* Set the Vector Table base location at 0x08003000 */
	NVIC_SetVectorTable(0x08000000, 0x0);
#endif

    /* Set NVIC Preemption Priority Bits: 0 bit for pre-emption, 4 bits for
       subpriority */
    NVIC_SetPriorityGrouping(NVIC_PriorityGroup_0);

    /* Set Base Priority Mask Register */
    __set_BASEPRI(BSP_BASE_PRI_DEFAULT);
}
示例#15
0
/***************************************************************************//**
 * @brief
 *   Configure the address of vector table
 *
 * @details
 *
 * @note
 *
 ******************************************************************************/
static void NVIC_Configuration(void)
{
#ifdef  VECT_TAB_RAM
	/* Set the vector table allocated at 0x20000000 */
	NVIC_SetVectorTable(RAM_MEM_BASE, 0x0);
#else  /* VECT_TAB_FLASH  */
	/* Set the vector table allocated at 0x00000000 */
	NVIC_SetVectorTable(FLASH_MEM_BASE, 0x0);
#endif

	/* Set NVIC Preemption Priority Bits: 0 bit for pre-emption, 4 bits for
	   subpriority */
	NVIC_SetPriorityGrouping(0x7UL);

	/* Set Base Priority Mask Register */
	__set_BASEPRI(EFM32_BASE_PRI_DEFAULT);
}
示例#16
0
文件: power.c 项目: lunt7/zephyr
/* Handle SOC specific activity after Low Power Mode Exit */
void _sys_soc_power_state_post_ops(enum power_states state)
{
	switch (state) {
	case SYS_POWER_STATE_CPU_LPS:
	case SYS_POWER_STATE_CPU_LPS_1:
		/* Enable interrupts */
		__set_BASEPRI(0);
		break;
#if defined(CONFIG_SYS_POWER_DEEP_SLEEP)
	case SYS_POWER_STATE_DEEP_SLEEP:
		break;
#endif
	default:
		/* Unsupported State */
		SYS_LOG_ERR("Unsupported State\n");
		break;
	}
}
InterruptMask enableInterruptMasking()
{
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0

	const auto interruptMask = __get_BASEPRI();
	constexpr auto basepriValue = CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI << (8 - __NVIC_PRIO_BITS);
	static_assert(basepriValue > 0 && basepriValue <= UINT8_MAX,
			"Invalid CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI value!");
	__set_BASEPRI(basepriValue);
	return interruptMask;

#else	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0

	const auto interruptMask = __get_PRIMASK();
	__disable_irq();
	return interruptMask;

#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
}
/* If FreeRTOS is not running, then we rely on rit service to call this function,
 * otherwise we rely on FreeRTOS tick hook to provide system timer
 */
static void hl_periodic_service(void)
{
    const uint32_t timer_ms = sys_get_uptime_ms();

    /* If FreeRTOS is running, user should use a dedicated task to call mesh service,
     * so we will not call it if freertos is running
     */
    if (taskSCHEDULER_RUNNING == xTaskGetSchedulerState()) {
        m_system_uptime_ms += MS_PER_TICK();

        /* We don't need RIT if FreeRTOS is running */
        if (sys_rit_running()) {
            sys_rit_disable();

            /* Round up uptime_ms because if ms per tick is 10, then we don't want to
             * increment this timer by 10 from an odd number because % 10 won't work.
             */
            m_system_uptime_ms = (m_system_uptime_ms / 10) * 10;
        }
    }
    else {
        m_system_uptime_ms += m_time_per_rit_isr_ms;
        wireless_service();

        /**
         * Small hack to support interrupts if FreeRTOS is not running :
         * FreeRTOS API resets our base priority register, then all
         * interrupts higher priority than IP_SYSCALL will not get locked out.
         *   @see more notes at isr_priorities.h.  @see IP_SYSCALL
         */
        __set_BASEPRI(0);
    }
	
	/**
     * Call SD timer function at 100Hz.
     * Feed the watchdog too while we're at it.
     */
    if (0 == (timer_ms % 10)) {
        sd_timerproc();
        sys_watchdog_feed();
    }
}
示例#19
0
/**
 * Initializes the minimal system including CPU Clock, UART, and Flash accelerator
 * Be careful of the order of the operations!!!
 */
void low_level_init(void)
{
    rtc_init();
    g_rtc_boot_time = rtc_gettime();

    /* Configure System Clock based on desired clock rate @ sys_config.h */
    sys_clock_configure();
    configure_flash_acceleration(sys_get_cpu_clock());

    /* Setup default interrupt priorities that will work with FreeRTOS */
    configure_interrupt_priorities();

    /* These methods shouldn't be needed but doing it anyway to be safe */
    NVIC_SetPriorityGrouping(0);
    __set_BASEPRI(0);
    __enable_fault_irq();
    __enable_irq();

    /* Setup UART with minimal I/O functions */
    uart0_init(SYS_CFG_UART0_BPS);
    sys_set_outchar_func(uart0_putchar);
    sys_set_inchar_func(uart0_getchar);

    /**
     * Turn off I/O buffering otherwise sometimes printf/scanf doesn't behave
     * correctly due to strange buffering and/or flushing effects.
     */
    setvbuf(stdout, 0, _IONBF, 0);
    setvbuf(stdin,  0, _IONBF, 0);

    /* Initialize newlib fopen() fread() calls support */
    syscalls_init();

    /* Enable the watchdog to allow us to recover in an event of system crash */
    sys_watchdog_enable();

    /* Uart and printf() are initialized, so print our boot-up message */
    print_boot_info();
}
示例#20
0
/* Note: On ARMv7-M the return_handler is executed in NP mode. */
void debug_deprivilege_and_return(void * debug_handler, void * return_handler,
                                  uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3)
{
    /* Source box: Get the current stack pointer. */
    /* Note: The source stack pointer is only used to assess the stack
     *       alignment and to read the xpsr. */
    uint32_t src_sp = context_validate_exc_sf(__get_PSP());

    /* Destination box: The debug box. */
    uint8_t dst_id = g_debug_box.box_id;

    /* Copy the xPSR from the source exception stack frame. */
    uint32_t xpsr = vmpu_unpriv_uint32_read((uint32_t) &((uint32_t *) src_sp)[7]);

    /* Destination box: Forge the destination stack frame. */
    /* Note: We manually have to set the 4 parameters on the destination stack,
     *       so we will set the API to have nargs=0. */
    uint32_t dst_sp = context_forge_exc_sf(src_sp, dst_id, (uint32_t) debug_handler, (uint32_t) return_handler, xpsr, 0);
    ((uint32_t *) dst_sp)[0] = a0;
    ((uint32_t *) dst_sp)[1] = a1;
    ((uint32_t *) dst_sp)[2] = a2;
    ((uint32_t *) dst_sp)[3] = a3;

    /* Suspend the OS. */
    g_priv_sys_hooks.priv_os_suspend();

    /* Stop all lower-than-SVC-priority interrupts. FIXME Enable debug box to
     * do things that require interrupts. One idea would be to provide an SVC
     * to re-enable interrupts that can only be called by the debug box during
     * debug handling. */
    __set_BASEPRI(__UVISOR_NVIC_MIN_PRIORITY << (8U - __NVIC_PRIO_BITS));

    context_switch_in(CONTEXT_SWITCH_FUNCTION_DEBUG, dst_id, src_sp, dst_sp);

    /* Upon execution return debug_handler will be executed. Upon return from
     * debug_handler, return_handler will be executed. */
    return;
}
示例#21
0
void HAL_enable_irq(int is) {
    __set_BASEPRI(is);
}
InterruptMask disableInterruptMasking()
{
	const auto interruptMask = __get_BASEPRI();
	__set_BASEPRI(0);
	return interruptMask;
}
/*-------------------------------------------------------------------------*
 * Function:  CPUDisableInterrupts
 *-------------------------------------------------------------------------*
 * Description:
 *      Disables all standard CPU interrupts (IRQ).
 *-------------------------------------------------------------------------*/
void CPUDisableInterrupts(void)
{
    __set_BASEPRI(16UL << (8 - 5));
}
示例#24
0
byte Synth::play() {
    static const byte sineQuadrant[128] = {
        129, 130, 132, 133, 135, 137, 138, 140, 141, 143, 144, 146, 147, 149, 150, 152,
        154, 155, 157, 158, 160, 161, 163, 164, 166, 167, 169, 170, 172, 173, 174, 176,
        177, 179, 180, 182, 183, 184, 186, 187, 189, 190, 191, 193, 194, 195, 197, 198,
        199, 200, 202, 203, 204, 206, 207, 208, 209, 210, 212, 213, 214, 215, 216, 217,
        218, 219, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 230, 231, 232, 233,
        234, 235, 236, 237, 237, 238, 239, 240, 240, 241, 242, 242, 243, 244, 244, 245,
        246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 252,
        253, 253, 253, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255
    };

    //ensure is off -------------------

    TIM_DeInit(TIM2);

    //some checks ---------------------

    if( ! warnings) {
        if(putFrame > theFrames && putFrame[-1].nPulses != 0) {
            warnings |= MISSING_END_FRAME_WARNING;
        }

        if(putFrame < &theFrames[2]) {
            warnings |= NO_FRAMES_TO_PLAY_WARNING;
        }
    }

    if(warnings) {
        return warnings; // don't attempt to play dodgy sequences
    }

    //start ---------------------------

    SynthFrame *playFrame;
    uint16_t pulsesRemaining;
    U32 amplitude;
    uint32_t phaseStep;
    U32 phase;

    playFrame = theFrames;

    pulsesRemaining = playFrame->nPulses;
    amplitude.w[0] = 0;
    amplitude.w[1] = playFrame->amplitude + 1;
    phase.u = 384UL << 16; // sine sample is at lowest point (zero) at start of fourth quadrant
    phaseStep = playFrame->phaseStep;

    // save interrupt state & turn off all but highest level user interrupts (level 0)
    // Could alternatively use PRIMASK

    uint32_t savedInterruptBasePriority = __get_BASEPRI();
    __set_BASEPRI(1 << (8 - __NVIC_PRIO_BITS));

    // initialise timer

    // We output on TIM2 channel 1 which uses PA0

    const int16_t TOP = 128;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    pinMode(A0, AF_OUTPUT_PUSHPULL);

    TIM_TimeBaseInitTypeDef timerInit;
    timerInit.TIM_Prescaler = 0; // no prescaling run clock at 72MHz. Sets TIM2_PSC register to 0
    timerInit.TIM_CounterMode = TIM_CounterMode_CenterAligned1; // count from 0 to Auto Reload Reg. Sets TIM2_CR1 CMS bits to 01
    timerInit.TIM_Period = TOP; // Counter re-zeroes at 128 (for period 256): 281,250 Hz. Sets TIM2_ARR to become 128 on update
    timerInit.TIM_ClockDivision = 0; // not really relevant
    TIM_TimeBaseInit(TIM2, &timerInit);

    TIM_OCInitTypeDef outputChannelInit;
    outputChannelInit.TIM_OCMode = TIM_OCMode_PWM2; // we want PWM, active when count is high (## how is this different from polarity?)
    outputChannelInit.TIM_OCPolarity = TIM_OCNPolarity_High; // Output is active (high) while counter is high (at (on up) or above TIM2_CCR1)
    outputChannelInit.TIM_OutputState = TIM_OutputState_Enable;
    outputChannelInit.TIM_Pulse = 0; //TOP - 0; // Set initial duty cycle. First pulse is 0% to start quietly. TIM2_CCR1 = 128
    TIM_OC1Init(TIM2, &outputChannelInit); // init output channel 1

    TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); // TIM2_CCR1 to be buffered so changes take effect at update event (counter reset)
    //TIM_ARRPreloadConfig(TIM2, ENABLE); // commented as we never change TIM2_ARR from now on

    // Note URS & UDIS bits in TIM2_CR1 by default allow update events to set TIM_IT_Update flag in TIM2_SR

    // start timer
    TIM_Cmd(TIM2, ENABLE);

    // ensure update flag is clear on entry
    TIM2->SR = (uint16_t) ~TIM_IT_Update;

    //loop ---------------------------

    while(true) {
        // We want to wait for the TIM_IT_Update bit in TIM2_SR to signal an update event
        // With up/down counting for centered PWM we get update events at both top and bottom
        // if its already set then we're late here so store a warning

        if(TIM2->SR & TIM_IT_Update) {
            warnings |= LATE_SAMPLE_PULSE_WARNING;
        }
        else {
            // wait for timer to set its update flag when counter next reaches top
            while((TIM2->SR & TIM_IT_Update) == 0) {
            }
        }
        // now clear the flag; TIM->SR are only cleared on write; they can't be set on write
        TIM2->SR = (uint16_t) ~TIM_IT_Update;

        if(TIM2->CR1 & TIM_CR1_DIR) { // only supply next sample when we're counting down (so update occurs at bottom)

            // One quarter period of sine wave is stored; symmetry is used to obtain other quadrant data
            byte p = phase.b[2];
            byte sample = sineQuadrant[p & 0x80 ? 255 - p : p]; // read table forwards or backwards
            if(phase.b[3] & 1) { // invert if in second half of wave period
                sample = 255 - sample;
            }

            // if amplitude not maximum (amplitude.w[1] == 256) then reduce sample
            if(amplitude.b[3] == 0) {
                sample = (sample * amplitude.b[2]) >> 8;
            }

            // set the output compare register which sets the number of clock cycles the output pin will be on for
            // TIM2_CCR1 is buffered so the actual change occurs at the *next* timer overflow

            // for TOP = 128, sample range 0..255 must be halved (period is doubled again by symmetry)

            TIM2->CCR1 = TOP - (sample >> 1);
        }
/*-------------------------------------------------------------------------*
 * Function:  CPUEnableInterrupts
 *-------------------------------------------------------------------------*
 * Description:
 *      Enables all standard CPU interrupts (IRQ).
 *-------------------------------------------------------------------------*/
void CPUEnableInterrupts(void)
{
    __set_BASEPRI(0UL);
}