/****************************************************************************
* void spi_enable_interrupt(spi_t *obj, uint32_t handler, uint8_t enable)
*
* This will enable the interrupt in NVIC for the associated USART RX channel
*
*   * obj: pointer to spi object
*   * handler: pointer to interrupt handler for this channel
*   * enable: Whether to enable (true) or disable (false) the interrupt
*
****************************************************************************/
void spi_enable_interrupt(spi_t *obj, uint32_t handler, uint8_t enable)
{
    IRQn_Type IRQvector;

    switch ((uint32_t)obj->spi.spi) {
#ifdef USART0
        case USART_0:
            IRQvector = USART0_RX_IRQn;
            break;
#endif
#ifdef USART1
        case USART_1:
            IRQvector = USART1_RX_IRQn;
            break;
#endif
#ifdef USART2
        case USART_2:
            IRQvector = USART2_RX_IRQn;
            break;
#endif
        default:
            error("Undefined SPI peripheral");
            return;
    }

    if (enable == true) {
        vIRQ_SetVector(IRQvector, handler);
        USART_IntEnable(obj->spi.spi, USART_IEN_RXDATAV);
        vIRQ_EnableIRQ(IRQvector);
    } else {
        vIRQ_SetVector(IRQvector, handler);
        USART_IntDisable(obj->spi.spi, USART_IEN_RXDATAV);
        vIRQ_DisableIRQ(IRQvector);
    }
}
void lp_ticker_init(void) {
    if (!lp_ticker_inited) {
        lp_ticker_inited = 1;
        __TIM2_CLK_ENABLE();
        __TIM2_FORCE_RESET();
        __TIM2_RELEASE_RESET();

        // Update the SystemCoreClock variable
        SystemCoreClockUpdate();

        // Configure time base
        TimMasterHandle.Instance = TIM2;
        TimMasterHandle.Init.Period            = 0xFFFFFFFF;
        TimMasterHandle.Init.Prescaler         = (uint32_t)(SystemCoreClock / 1000000000) - 1; // 1 ms tick
        TimMasterHandle.Init.ClockDivision     = 0;
        TimMasterHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
        TimMasterHandle.Init.RepetitionCounter = 0;
        HAL_TIM_OC_Init(&TimMasterHandle);

        vIRQ_SetVector(TIM2_IRQn, (uint32_t)lp_handler);
        vIRQ_EnableIRQ(TIM2_IRQn);

        HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_1);
    }
}
示例#3
0
static void spi_enable_vector_interrupt(spi_t *obj, uint32_t handler, uint8_t enable)
{
    IRQn_Type spi_irq[] = SPI_IRQS;
    if (enable) {
        vIRQ_SetVector(spi_irq[obj->spi.instance], handler);
        vIRQ_EnableIRQ(spi_irq[obj->spi.instance]);
    } else {
        vIRQ_SetVector(spi_irq[obj->spi.instance], handler);
        vIRQ_DisableIRQ(spi_irq[obj->spi.instance]);
    }
}
int serial_tx_asynch(serial_t *obj, void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint)
{
    // TODO: DMA usage is currently ignored
    (void) hint;

    bool use_tx = (tx != NULL && tx_length > 0);
    IRQn_Type irq_n = UartIRQs[obj->serial.module];

    if (!use_tx || !irq_n)
        return 0;

    obj->tx_buff.buffer = tx;
    obj->tx_buff.length = tx_length;
    obj->tx_buff.pos    = 0;
    obj->tx_buff.width  = tx_width;

    obj->serial.event   = (obj->serial.event & ~SERIAL_EVENT_TX_MASK) | (event & SERIAL_EVENT_TX_MASK);

    // register the thunking handler
    vIRQ_SetVector(irq_n, handler);
    vIRQ_EnableIRQ(irq_n);

    UART_HandleTypeDef *handle = &UartHandle[obj->serial.module];
    // HAL_StatusTypeDef rc = HAL_UART_Transmit_IT(handle, tx, tx_length);

    // manually implemented HAL_UART_Transmit_IT for tighter control of what it does
    handle->pTxBuffPtr = tx;
    handle->TxXferSize = tx_length;
    handle->TxXferCount = tx_length;

    if(handle->State == HAL_UART_STATE_BUSY_RX) {
        handle->State = HAL_UART_STATE_BUSY_TX_RX;
    } else {
        handle->State = HAL_UART_STATE_BUSY_TX;
    }

    // if the TX register is empty, directly input the first transmit byte
    if (__HAL_UART_GET_FLAG(handle, UART_FLAG_TXE)) {
        handle->Instance->DR = *handle->pTxBuffPtr++;
        handle->TxXferCount--;
    }
    // chose either the tx reg empty or if last byte wait directly for tx complete
    if (handle->TxXferCount != 0) {
        handle->Instance->CR1 |= USART_CR1_TXEIE;
    } else {
        handle->Instance->CR1 |= USART_CR1_TCIE;
    }

    DEBUG_PRINTF("UART%u: Tx: 0=(%u, %u) %x\n", obj->serial.module+1, tx_length, tx_width, HAL_UART_GetState(handle));

    return tx_length;
}
示例#5
0
void lp_ticker_init(void) {
    if (lp_ticker_inited) {
        return;
    }
    lp_ticker_inited = 1;

    // RTC might be configured already, don't reset it
    RTC_HAL_SetSupervisorAccessCmd(RTC_BASE, true);
    if (!RTC_HAL_IsCounterEnabled(RTC_BASE)) {
        // select RTC for OSC32KSEL
        CLOCK_HAL_SetSource(SIM_BASE, kClockOsc32kSel, 2);
        // configure RTC
        SIM_HAL_EnableRtcClock(SIM_BASE, 0U);
        RTC_HAL_Init(RTC_BASE);
        RTC_HAL_Enable(RTC_BASE);
        for (volatile uint32_t wait_count = 0; wait_count < 1000000; wait_count++);
        RTC_HAL_SetAlarmIntCmd(RTC_BASE, false);
        RTC_HAL_SetSecsIntCmd(RTC_BASE, false);
        RTC_HAL_SetAlarmReg(RTC_BASE, 0);
        RTC_HAL_EnableCounter(RTC_BASE, true);
    }
    vIRQ_ClearPendingIRQ(RTC_IRQn);
    vIRQ_SetVector(RTC_IRQn, (uint32_t)rct_isr);
    vIRQ_EnableIRQ(RTC_IRQn);

    // configure LPTMR
    CLOCK_SYS_EnableLptimerClock(0);
    LPTMR0_CSR = 0x00;
    LPTMR0_PSR = 0x00;
    LPTMR0_CMR = 0x00;
    LPTMR_HAL_SetTimerModeMode(LPTMR0_BASE, kLptmrTimerModeTimeCounter);
    LPTMR0_PSR |= LPTMR_PSR_PCS(0x2) | LPTMR_PSR_PBYP_MASK;
    LPTMR_HAL_SetIntCmd(LPTMR0_BASE, 1);
    LPTMR_HAL_SetFreeRunningCmd(LPTMR0_BASE, 0);
    IRQn_Type timer_irq[] = LPTMR_IRQS;
    vIRQ_SetVector(timer_irq[0], (uint32_t)lptmr_isr);
    vIRQ_EnableIRQ(timer_irq[0]);
}
示例#6
0
/// @returns the number of bytes transferred, or `0` if nothing transferred
static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer_type, void *tx, void *rx, size_t length)
{
    if (transfer_type != SPI_TRANSFER_TYPE_TX) DEBUG_PRINTF("SPI%u: Start: %u, %u\n", obj->spi.module+1, transfer_type, length);
    SPI_HandleTypeDef *handle = &SpiHandle[obj->spi.module];
    obj->spi.transfer_type = transfer_type;

    bool is16bit = (handle->Init.DataSize == SPI_DATASIZE_16BIT);
    // the HAL expects number of transfers instead of number of bytes
    // so for 16 bit transfer width the count needs to be halved
    size_t words;
    if (is16bit) words = length / 2;
    else         words = length;

    // enable the interrupt
    IRQn_Type irq_n = SpiIRQs[obj->spi.module];
    vIRQ_EnableIRQ(irq_n);

    // enable the right hal transfer
    static uint16_t sink;
    int rc = 0;
    switch(transfer_type) {
        case SPI_TRANSFER_TYPE_TXRX:
            rc = HAL_SPI_TransmitReceive_IT(handle, (uint8_t*)tx, (uint8_t*)rx, words);
            break;
        case SPI_TRANSFER_TYPE_TX:
            // TODO: we do not use `HAL_SPI_Transmit_IT`, since it has some unknown bug
            // and makes the HAL keep some state and then that fails successive transfers
            // rc = HAL_SPI_Transmit_IT(handle, (uint8_t*)tx, words);
            rc = HAL_SPI_TransmitReceive_IT(handle, (uint8_t*)tx, (uint8_t*)&sink, 1);
            length = is16bit ? 2 : 1;
            break;
        case SPI_TRANSFER_TYPE_RX:
            // the receive function also "transmits" the receive buffer so in order
            // to guarantee that 0xff is on the line, we explicitly memset it here
            memset(rx, SPI_FILL_WORD, length);
            rc = HAL_SPI_Receive_IT(handle, (uint8_t*)rx, words);
            break;
        default:
            length = 0;
    }

    if (rc) {
        DEBUG_PRINTF("SPI%u: RC=%u\n", obj->spi.module+1, rc);
        length = 0;
    }

    return length;
}
void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint)
{
    // TODO: DMA usage is currently ignored
    (void) hint;

    bool use_rx = (rx != NULL && rx_length > 0);
    IRQn_Type irq_n = UartIRQs[obj->serial.module];

    if (!use_rx || !irq_n)
        return;

    obj->rx_buff.buffer = rx;
    obj->rx_buff.length = rx_length;
    obj->rx_buff.pos    = 0;
    obj->rx_buff.width  = rx_width;

    obj->serial.event      = (obj->serial.event & ~SERIAL_EVENT_RX_MASK) | (event & SERIAL_EVENT_RX_MASK);
    obj->serial.char_match = char_match;

    UART_HandleTypeDef *handle = &UartHandle[obj->serial.module];
    // register the thunking handler
    vIRQ_SetVector(irq_n, handler);
    vIRQ_EnableIRQ(irq_n);

    // HAL_StatusTypeDef rc = HAL_UART_Receive_IT(handle, rx, rx_length);

    handle->pRxBuffPtr = rx;
    handle->RxXferSize = rx_length;
    handle->RxXferCount = rx_length;

    if(handle->State == HAL_UART_STATE_BUSY_TX) {
        handle->State = HAL_UART_STATE_BUSY_TX_RX;
    } else {
        handle->State = HAL_UART_STATE_BUSY_RX;
    }

    __HAL_UART_CLEAR_PEFLAG(handle);
    handle->Instance->CR1 |= USART_CR1_RXNEIE | USART_CR1_PEIE;
    handle->Instance->CR3 |= USART_CR3_EIE;

    DEBUG_PRINTF("UART%u: Rx: 0=(%u, %u, %u) %x\n", obj->serial.module+1, rx_length, rx_width, char_match, HAL_UART_GetState(handle));
}
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
{
    UART_HandleTypeDef *handle = &UartHandle[obj->serial.module];
    IRQn_Type irq_n = UartIRQs[obj->serial.module];
    uint32_t vector = uart_irq_vectors[obj->serial.module];

    if (!irq_n || !vector)
        return;

    if (enable) {

        if (irq == RxIrq) {
            __HAL_UART_ENABLE_IT(handle, UART_IT_RXNE);
        } else { // TxIrq
            __HAL_UART_ENABLE_IT(handle, UART_IT_TC);
        }

        vIRQ_SetVector(irq_n, vector);
        vIRQ_EnableIRQ(irq_n);

    } else { // disable

        int all_disabled = 0;

        if (irq == RxIrq) {
            __HAL_UART_DISABLE_IT(handle, UART_IT_RXNE);
            // Check if TxIrq is disabled too
            if ((handle->Instance->CR1 & USART_CR1_TXEIE) == 0) all_disabled = 1;
        } else { // TxIrq
            __HAL_UART_DISABLE_IT(handle, UART_IT_TXE);
            // Check if RxIrq is disabled too
            if ((handle->Instance->CR1 & USART_CR1_RXNEIE) == 0) all_disabled = 1;
        }

        if (all_disabled) vIRQ_DisableIRQ(irq_n);

    }
}