2 #include <twr_scheduler.h>
4 #include <twr_system.h>
8 #define _TWR_SPI_EVENT_CLEAR 0
10 static const uint32_t _twr_spi_speed_table[8] =
22 static const uint32_t _twr_spi_mode_table[4] =
34 void (*event_handler)(
twr_spi_event_t event,
void *_twr_spi_event_param);
37 bool pending_event_done;
39 bool manual_cs_control;
54 .address_peripheral = (
void *)&SPI2->DR,
58 static uint8_t _twr_spi_transfer_byte(uint8_t value);
62 static void _twr_spi_task();
67 if(_twr_spi.initilized ==
true)
72 _twr_spi.initilized =
true;
75 RCC->IOPENR |= RCC_IOPENR_GPIOBEN;
81 GPIOB->PUPDR |= GPIO_PUPDR_PUPD14_1;
84 GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEED12 | GPIO_OSPEEDER_OSPEED13 | GPIO_OSPEEDER_OSPEED14 | GPIO_OSPEEDER_OSPEED15;
87 GPIOB->MODER &= ~(GPIO_MODER_MODE12_1 | GPIO_MODER_MODE13_0 | GPIO_MODER_MODE14_0 | GPIO_MODER_MODE15_0);
90 GPIOB->BSRR = GPIO_BSRR_BS_12;
93 RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
99 SPI2->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR;
108 SPI2->CR1 |= SPI_CR1_SPE;
124 _twr_spi.speed = speed;
127 SPI2->CR1 &= ~SPI_CR1_SPE;
131 cr1 &= ~(SPI_CR1_BR_Msk | SPI_CR1_SPE);
132 cr1 |= _twr_spi_speed_table[speed];
138 SPI2->CR1 |= SPI_CR1_SPE;
143 _twr_spi.cs_delay = cs_delay;
145 _twr_spi.delay = delay;
147 _twr_spi.cs_quit = cs_quit;
152 return _twr_spi.speed;
160 _twr_spi.mode = mode;
163 SPI2->CR1 &= ~SPI_CR1_SPE;
167 cr1 &= ~(SPI_CR1_CPHA_Msk | SPI_CR1_CPOL_Msk | SPI_CR1_SPE);
168 cr1 |= _twr_spi_mode_table[mode];
174 SPI2->CR1 |= SPI_CR1_SPE;
179 return _twr_spi.mode;
184 _twr_spi.manual_cs_control = manual_cs_control;
189 return (!_twr_spi.in_progress) && (_twr_spi.pending_event_done == _TWR_SPI_EVENT_CLEAR);
195 if (_twr_spi.in_progress ==
true)
202 _twr_spi.in_progress =
true;
205 twr_system_pll_enable();
208 if (!_twr_spi.manual_cs_control)
210 GPIOB->BSRR = GPIO_BSRR_BR_12;
213 if (_twr_spi.cs_delay > 0)
222 for (
size_t i = 0; i < length; i++)
225 *((uint8_t *) destination + i) = _twr_spi_transfer_byte(0);
228 else if (destination == NULL)
230 for (
size_t i = 0; i < length; i++)
233 _twr_spi_transfer_byte(*((uint8_t *) source + i));
238 for (
size_t i = 0; i < length; i++)
241 *((uint8_t *) destination + i) = _twr_spi_transfer_byte(*((uint8_t *) source + i));
245 if (_twr_spi.cs_quit > 0)
253 if (!_twr_spi.manual_cs_control)
255 GPIOB->BSRR = GPIO_BSRR_BS_12;
259 twr_system_pll_disable();
262 _twr_spi.in_progress =
false;
270 if((_twr_spi.in_progress ==
true) || (_twr_spi.pending_event_done != _TWR_SPI_EVENT_CLEAR))
277 _twr_spi.event_handler = event_handler;
278 _twr_spi.event_param = event_param;
281 twr_system_pll_enable();
284 if ((source != NULL) && (destination == NULL))
289 GPIOB->BSRR = GPIO_BSRR_BR_12;
292 _twr_spi.in_progress =
true;
295 SPI2->CR1 &= ~SPI_CR1_SPE;
298 SPI2->CR2 |= SPI_CR2_TXDMAEN;
301 SPI2->CR1 |= SPI_CR1_SPE;
305 _twr_spi_dma_config.
length = length;
312 else if ((source == NULL) && (destination != NULL))
317 twr_system_pll_disable();
325 twr_system_pll_disable();
331 static uint8_t _twr_spi_transfer_byte(uint8_t value)
334 while ((SPI2->SR & SPI_SR_TXE) == 0)
343 while ((SPI2->SR & SPI_SR_RXNE) == 0)
351 if (_twr_spi.delay > 0)
369 _twr_spi.in_progress =
false;
370 _twr_spi.pending_event_done =
true;
372 GPIOB->BSRR = GPIO_BSRR_BS_12;
383 static void _twr_spi_task()
386 if (_twr_spi.event_handler != NULL)
392 twr_system_pll_disable();
395 _twr_spi.pending_event_done =
false;
void twr_dma_channel_config(twr_dma_channel_t channel, twr_dma_channel_config_t *config)
Configure DMA channel.
void twr_dma_channel_run(twr_dma_channel_t channel)
Start DMA channel.
void twr_dma_set_event_handler(twr_dma_channel_t channel, void(*event_handler)(twr_dma_channel_t, twr_dma_event_t, void *), void *event_param)
Set callback function.
twr_dma_event_t
DMA channel event.
void twr_dma_init(void)
Initialize DMA.
twr_dma_channel_t
DMA channels.
@ TWR_DMA_REQUEST_2
DMA request 2.
@ TWR_DMA_EVENT_DONE
DMA channel event done.
@ TWR_DMA_EVENT_ERROR
DMA channel event error.
@ TWR_DMA_SIZE_1
DMA channel data size 1B.
@ TWR_DMA_DIRECTION_TO_PERIPHERAL
DMA channel direction from RAM to peripheral.
@ TWR_DMA_PRIORITY_HIGH
DMA channel priority is high.
@ TWR_DMA_CHANNEL_5
DMA channel 5, used for SPI.
@ TWR_DMA_MODE_STANDARD
DMA channel mode standard.
size_t twr_scheduler_task_id_t
Task ID assigned by scheduler.
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
twr_spi_speed_t
SPI communication speed.
bool twr_spi_is_ready(void)
Check if is ready for transfer.
bool twr_spi_async_transfer(const void *source, void *destination, size_t length, void(*event_handler)(twr_spi_event_t event, void *event_param), void(*event_param))
Execute async SPI transfer.
twr_spi_speed_t twr_spi_get_speed(void)
Get SPI communication speed.
twr_spi_mode_t
SPI mode of operation.
void twr_spi_set_manual_cs_control(bool manual_cs_control)
Enable manual control of CS pin.
bool twr_spi_transfer(const void *source, void *destination, size_t length)
Execute SPI transfer.
void twr_spi_set_speed(twr_spi_speed_t speed)
Set SPI communication speed.
void twr_spi_set_mode(twr_spi_mode_t mode)
Set SPI mode of operation.
twr_spi_mode_t twr_spi_get_mode(void)
Get SPI mode of operation.
void twr_spi_init(twr_spi_speed_t speed, twr_spi_mode_t mode)
Initialize SPI channel.
void twr_spi_set_timing(uint16_t cs_delay, uint16_t delay, uint16_t cs_quit)
Set SPI timing.
twr_spi_event_t
SPI event.
@ TWR_SPI_SPEED_16_MHZ
SPI communication speed is 16 MHz.
@ TWR_SPI_SPEED_125_KHZ
SPI communication speed is 125 kHz.
@ TWR_SPI_SPEED_8_MHZ
SPI communication speed is 8 MHz.
@ TWR_SPI_SPEED_250_KHZ
SPI communication speed is 250 kHz.
@ TWR_SPI_SPEED_500_KHZ
SPI communication speed is 500 kHz.
@ TWR_SPI_SPEED_4_MHZ
SPI communication speed is 4 MHz.
@ TWR_SPI_SPEED_2_MHZ
SPI communication speed is 2 MHz.
@ TWR_SPI_SPEED_1_MHZ
SPI communication speed is 1 MHz.
@ TWR_SPI_MODE_2
SPI mode of operation is 2 (CPOL = 1, CPHA = 0)
@ TWR_SPI_MODE_1
SPI mode of operation is 1 (CPOL = 0, CPHA = 1)
@ TWR_SPI_MODE_0
SPI mode of operation is 0 (CPOL = 0, CPHA = 0)
@ TWR_SPI_MODE_3
SPI mode of operation is 3 (CPOL = 1, CPHA = 1)
@ TWR_SPI_EVENT_DONE
SPI event is completed.
#define TWR_TICK_INFINITY
Maximum timestamp value.
void twr_timer_init(void)
Initialize timer.
void twr_timer_delay(uint16_t microseconds)
Relative delay.
void twr_timer_stop(void)
Stop timer.
void twr_timer_start(void)
Start timer.
DMA channel configuration.
twr_dma_request_t request
DMA channel request.
size_t length
DMA channel data length.
void * address_memory
RAM memory address.