This repository has been archived on 2024-05-28. You can view files and clone it, but cannot push or open issues or pull requests.
2023-11-14 16:25:09 -05:00

155 lines
5.3 KiB
C++
Executable File

#ifndef STM32U5XX_HAL_SPI_HPP
#define STM32U5XX_HAL_SPI_HPP
#include "global_variable.h"
#include "stdint.h"
#include "stdlib.h"
#include "stm32u575xx.h"
#include "stm32u5xx.h"
#include "queue.hpp"
#include "reg_spi.h"
typedef struct {
} spi_s; ///< @brief spi instance for driver
__UNUSED static inline void rcc_enable_spi(SPI_TypeDef *spi) {
if (spi == SPI1) SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN);
else if (spi == SPI2)
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN);
else if (spi == SPI3)
SET_BIT(RCC->APB3ENR, RCC_APB3ENR_SPI3EN);
}
__UNUSED static inline void nvic_enable_spi_irq(SPI_TypeDef *spi) {
if (spi == SPI1) NVIC_EnableIRQ(SPI1_IRQn);
else if (spi == SPI2)
NVIC_EnableIRQ(SPI2_IRQn);
else if (spi == SPI3)
NVIC_EnableIRQ(SPI3_IRQn);
}
typedef struct {
REG_SPI_MBR master_baud_rate; ///< @brief master baud rate prescaler
REG_SPI_CPHA clock_phase; ///< @brief clock phase
REG_SPI_CPOL clock_polarity; ///< @brief clock polarity
REG_SPI_FIRST_BIT first_bit; ///< @brief first bit select
REG_SPI_SS_MANAGEMENT slave_man; ///< @brief slave select management
REG_SPI_MASTER mode; ///< @brief spi mode
REG_SPI_SSI_STATE slave_select_pin; ///< @brief slave select pin
ll_state_e af_control; ///< @brief alternate function control
/// @brief alternate function control
} spi_init_options_s; ///< @brief spi options for initialization of spi
//
//const spi_init_options_s spi_default_option = {
// .master_baud_rate = SPI_MBR_DIV256,
// .clock_phase = SPI_CPHA_FIRST,
// .clock_polarity = SPI_CPOL_LOW,
// .first_bit = SPI_FIRST_BIT_MSB,
// .slave_man = SPI_SS_MANAGER_SOFTWARE,
// .slave_select_pin = SPI_SSI_HIGH,
// .mode = SPI_MASTER,
// .af_control = LL_ENABLE,
//};
extern const spi_init_options_s spi_default_option; // the default spi options for initialization
extern spi_s *spi1_p; // spi1 instance
class Spi {
private:
SPI_TypeDef *spi; ///< @brief spi instance
queue20u8 tx_queue; ///< @brief queue for data to send
queue20u8 rx_queue; ///< @brief queue for data to receive
public:
Spi() = default;
void setup() {}
/// @brief initialize spi
/// @param[in] spi spi to initialize
/// @param[in] queue_size size of the tx_queue and rx_queue
/// @return status of the operation
hal_status_e spi_init(int queue_size, spi_init_options_s options){
// initialize the queue
hal_status_e status;
// set clock to 100k hz
// use hsi16 clock
RCC->CCIPR1 |= 2 << RCC_CCIPR1_SPI1SEL_Pos;
// 16 Mhz / 160 -> 0.1Mhz = 100kHz
options.master_baud_rate = SPI_MBR_DIV256; // clock = 16M/256 < 100Khz
// enable clock for spi
rcc_enable_spi(spi);
nvic_enable_spi_irq(spi);
reg_spi_set_af_control(spi, options.af_control);
reg_spi_set_slave_select(spi, options.slave_man);
reg_spi_set_slave_select_pin(spi, options.slave_select_pin);
reg_spi_set_master(spi, options.mode);
reg_spi_set_master_baud_rate(spi, options.master_baud_rate);
reg_spi_set_data_size(spi, 8);
reg_spi_set_clock_phase(spi, options.clock_phase);
reg_spi_set_clock_polarity(spi, options.clock_polarity);
reg_spi_set_first_bit(spi, options.first_bit);
reg_spi_set_peripheral_enable(spi, LL_ENABLE);
// todo: get MODF status, if MODF is set, return error
return HAL_OK;
}
/// @brief send data to spi
/// @param[in] spi spi to send data
/// @param[in] send_ptr pointer to data to send. when this function return,
/// the data can be free
/// @param[in] size size of data to send
/// @return status of the operation
hal_status_e spi_send( uint8_t *send_ptr, uint32_t size){
// enable tx and rx intterupt
spi->CR1 |= SPI_CR1_CSTART;
tx_queue.push_block(send_ptr, size);
// spi->spi->CR2 = 1;
reg_spi_set_rx_interrupt(spi, LL_ENABLE);
reg_spi_set_tx_interrupt(spi, LL_ENABLE);
// reg_spi_set_peripheral_enable(spi->spi, LL_ENABLE);
// spi->spi->CR1 |= SPI_CR1_CSTART | SPI_CR1_SPE;
// return ret;
return HAL_OK;
}
/// @brief read data from spi
/// @param[in] spi spi to read data
/// @param[out] read_ptr the space to store the data
/// @param[in,out] size size of data to read. return the actual size of data.
/// @return status of the operation
hal_status_e spi_read(uint8_t *read_ptr, uint32_t *size){
return rx_queue.pop_block(read_ptr, *size);
}
void spi_irq_handler() {
uint32_t sr = spi->SR;
// handle the error
if (sr & SPI_SR_OVR) {
// clear the error
spi->SR &= ~SPI_SR_OVR;
}
// handle the rx queue
if (sr & SPI_SR_RXP) {
if (rx_queue.push(spi->RXDR) != HAL_OK) {
// error
}
}
if (sr & SPI_SR_TXP) {
uint8_t data;
if (tx_queue.pop(&data) == HAL_OK){
*(uint8_t *) &(spi->TXDR) = data;
// spi->spi->TXDR = data;
} else
reg_spi_set_tx_interrupt(spi, LL_DISABLE);
}
};
};
#endif // STM32U5XX_HAL_SPI_HPP