/**************************************************************************** * 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); } }
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]); } }
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); } }
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; }
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]); }
// asynchronous API void spi_master_transfer(spi_t *obj, void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t handler, uint32_t event, DMAUsage hint) { // TODO: DMA usage is currently ignored (void) hint; // check which use-case we have bool use_tx = (tx != NULL && tx_length > 0); bool use_rx = (rx != NULL && rx_length > 0); // don't do anything, if the buffers aren't valid if (!use_tx && !use_rx) return; SPI_HandleTypeDef *handle = &SpiHandle[obj->spi.module]; bool is16bit = (handle->Init.DataSize == SPI_DATASIZE_16BIT); // copy the buffers to the SPI object obj->tx_buff.buffer = tx; obj->tx_buff.length = tx_length; obj->tx_buff.pos = 0; obj->tx_buff.width = is16bit ? 16 : 8; obj->rx_buff.buffer = rx; obj->rx_buff.length = rx_length; obj->rx_buff.pos = 0; obj->rx_buff.width = obj->tx_buff.width; obj->spi.event = event; DEBUG_PRINTF("SPI%u: Transfer: %u, %u\n", obj->spi.module+1, tx_length, rx_length); // register the thunking handler IRQn_Type irq_n = SpiIRQs[obj->spi.module]; vIRQ_SetVector(irq_n, handler); // enable the right hal transfer if (use_tx && use_rx) { // transfer with the min(tx, rx), then later either transmit _or_ receive the remainder size_t size = (tx_length < rx_length)? tx_length : rx_length; spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TXRX, tx, rx, size); } else if (use_tx) { spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TX, tx, NULL, tx_length); } else if (use_rx) { spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_RX, NULL, rx, rx_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); } }