2 #include <twr_scheduler.h>
4 #include <twr_system.h>
18 bool async_write_in_progress;
19 bool async_read_in_progress;
39 static uint32_t _twr_uart_brr_t[] =
49 static void _twr_uart_async_write_task(
void *param);
50 static void _twr_uart_async_read_task(
void *param);
51 static void _twr_uart_2_dma_read_task(
void *param);
56 memset(&_twr_uart[channel], 0,
sizeof(_twr_uart[channel]));
73 RCC->APB1ENR |= RCC_APB1ENR_USART4EN;
79 USART4->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UESM;
82 USART4->CR3 = USART_CR3_UCESM | USART_CR3_OVRDIS | USART_CR3_ONEBIT;
85 USART4->BRR = _twr_uart_brr_t[baudrate];
87 NVIC_EnableIRQ(USART4_5_IRQn);
89 _twr_uart[channel].usart = USART4;
109 RCC->CCIPR |= RCC_CCIPR_LPUART1SEL_1;
110 RCC->CCIPR &= ~RCC_CCIPR_LPUART1SEL_0;
113 RCC->APB1ENR |= RCC_APB1ENR_LPUART1EN;
119 LPUART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UESM;
122 LPUART1->CR3 = USART_CR3_OVRDIS | USART_CR3_ONEBIT;
125 LPUART1->BRR = 426667;
127 NVIC_EnableIRQ(LPUART1_IRQn);
129 _twr_uart[channel].usart = LPUART1;
138 RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
144 USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UESM;
147 USART2->CR3 = USART_CR3_UCESM | USART_CR3_OVRDIS | USART_CR3_ONEBIT;
150 USART2->BRR = _twr_uart_brr_t[baudrate];
152 NVIC_EnableIRQ(USART2_IRQn);
154 _twr_uart[channel].usart = USART2;
172 RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
178 USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UESM;
181 USART1->CR3 = USART_CR3_UCESM | USART_CR3_OVRDIS | USART_CR3_ONEBIT;
184 USART1->BRR = _twr_uart_brr_t[baudrate];
186 NVIC_EnableIRQ(USART1_IRQn);
188 _twr_uart[channel].usart = USART1;
199 _twr_uart[channel].usart->ICR |= USART_ICR_CMCF | USART_ICR_IDLECF | USART_ICR_FECF;
202 _twr_uart[channel].usart->CR2 &= ~USART_CR2_STOP_Msk;
203 _twr_uart[channel].usart->CR2 |= ((uint32_t) setting & 0x03) << USART_CR2_STOP_Pos;
206 _twr_uart[channel].usart->CR1 &= ~(USART_CR1_PCE_Msk | USART_CR1_PS_Msk);
207 _twr_uart[channel].usart->CR1 |= (((uint32_t) setting >> 2) & 0x03) << USART_CR1_PS_Pos;
210 _twr_uart[channel].usart->CR1 &= ~(USART_CR1_M1_Msk | USART_CR1_M0_Msk);
212 uint32_t word_length = setting >> 4;
214 if ((setting & 0x0c) != 0)
219 if (word_length == 0x07)
223 _twr_uart[channel].usart->CR1 |= 1 << USART_CR1_M1_Pos;
225 else if (word_length == 0x09)
227 _twr_uart[channel].usart->CR1 |= 1 << USART_CR1_M0_Pos;
231 _twr_uart[channel].usart->CR1 |= USART_CR1_UE;
233 _twr_uart[channel].initialized =
true;
242 _twr_uart[channel].usart->CR1 &= ~USART_CR1_UE_Msk;
244 if (_twr_uart[channel].async_write_task_id != 0) {
252 NVIC_DisableIRQ(USART4_5_IRQn);
255 RCC->APB1ENR &= ~RCC_APB1ENR_USART4EN;
267 if (_twr_uart[channel].usart == LPUART1)
269 NVIC_DisableIRQ(LPUART1_IRQn);
272 RCC->APB1ENR &= ~RCC_APB1ENR_LPUART1EN;
276 NVIC_DisableIRQ(USART2_IRQn);
279 RCC->APB1ENR &= ~RCC_APB1ENR_USART2EN;
292 NVIC_DisableIRQ(USART1_IRQn);
295 RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN_Msk;
311 _twr_uart[channel].initialized =
false;
316 if (!_twr_uart[channel].initialized || _twr_uart[channel].async_write_in_progress)
321 USART_TypeDef *usart = _twr_uart[channel].usart;
323 size_t bytes_written = 0;
325 if (_twr_uart[channel].usart == LPUART1)
327 twr_system_hsi16_enable();
329 twr_system_pll_enable();
332 while (bytes_written != length)
335 while ((usart->ISR & USART_ISR_TXE) == 0)
341 usart->TDR = *((uint8_t *) buffer + bytes_written++);
345 while ((usart->ISR & USART_ISR_TC) == 0)
350 if (_twr_uart[channel].usart == LPUART1)
352 twr_system_hsi16_disable();
356 twr_system_pll_disable();
359 return bytes_written;
364 if (!_twr_uart[channel].initialized)
369 USART_TypeDef *usart = _twr_uart[channel].usart;
371 size_t bytes_read = 0;
373 if (_twr_uart[channel].usart != LPUART1)
375 twr_system_pll_enable();
380 while (bytes_read != length)
389 if ((usart->ISR & USART_ISR_RXNE) == 0)
395 *((uint8_t *) buffer + bytes_read++) = usart->RDR;
398 if (_twr_uart[channel].usart != LPUART1)
400 twr_system_pll_disable();
408 _twr_uart[channel].event_handler = event_handler;
409 _twr_uart[channel].event_param = event_param;
414 _twr_uart[channel].write_fifo = write_fifo;
415 _twr_uart[channel].read_fifo = read_fifo;
420 if (!_twr_uart[channel].initialized || _twr_uart[channel].write_fifo == NULL)
425 size_t bytes_written = 0;
427 for (
size_t i = 0; i < length; i += 16)
429 bytes_written +=
twr_fifo_write(_twr_uart[channel].write_fifo, (uint8_t *)buffer + i, length - i > 16 ? 16 : length - i);
432 if (bytes_written != 0)
434 if (!_twr_uart[channel].async_write_in_progress)
438 if (_twr_uart[channel].usart == LPUART1)
440 twr_system_hsi16_enable();
444 twr_system_pll_enable();
455 _twr_uart[channel].usart->CR1 |= USART_CR1_TXEIE;
459 _twr_uart[channel].async_write_in_progress =
true;
462 return bytes_written;
467 if (!_twr_uart[channel].initialized || _twr_uart[channel].read_fifo == NULL || _twr_uart[channel].async_read_in_progress)
472 _twr_uart[channel].async_timeout = timeout;
474 _twr_uart[channel].async_read_task_id =
twr_scheduler_register(_twr_uart_async_read_task, (
void *) channel, _twr_uart[channel].async_timeout);
483 .length = _twr_uart[channel].read_fifo->
size,
485 .address_memory = _twr_uart[channel].read_fifo->
buffer,
486 .address_peripheral = (
void *) &_twr_uart[channel].usart->RDR,
498 _twr_uart[channel].usart->CR3 |= USART_CR3_DMAR;
507 _twr_uart[channel].usart->CR1 |= USART_CR1_RXNEIE;
511 if (_twr_uart[channel].usart != LPUART1)
513 twr_system_pll_enable();
516 _twr_uart[channel].async_read_in_progress =
true;
523 if (!_twr_uart[channel].initialized || !_twr_uart[channel].async_read_in_progress)
528 _twr_uart[channel].async_read_in_progress =
false;
538 _twr_uart[channel].usart->CR3 &= ~USART_CR3_DMAR_Msk;
546 _twr_uart[channel].usart->CR1 &= ~USART_CR1_RXNEIE_Msk;
551 if (_twr_uart[channel].usart != LPUART1)
553 twr_system_pll_disable();
563 if (!_twr_uart[channel].initialized || !_twr_uart[channel].async_read_in_progress)
568 size_t bytes_read =
twr_fifo_read(_twr_uart[channel].read_fifo, buffer, length);
573 static void _twr_uart_async_write_task(
void *param)
578 uart->async_write_in_progress =
false;
582 if (uart->usart == LPUART1)
584 twr_system_hsi16_disable();
588 twr_system_pll_disable();
591 if (uart->event_handler != NULL)
597 static void _twr_uart_async_read_task(
void *param)
604 if (uart->event_handler != NULL)
617 static void _twr_uart_2_dma_read_task(
void *param)
625 if (_twr_uart_2_dma.length != length)
627 uart->read_fifo->
head = uart->read_fifo->
size - length;
629 _twr_uart_2_dma.length = length;
639 USART_TypeDef *usart = _twr_uart[channel].usart;
641 if ((usart->CR1 & USART_CR1_RXNEIE) != 0 && (usart->ISR & USART_ISR_RXNE) != 0)
646 character = usart->RDR;
654 if ((usart->CR1 & USART_CR1_TXEIE) != 0 && (usart->ISR & USART_ISR_TXE) != 0)
662 usart->TDR = character;
667 usart->CR1 &= ~USART_CR1_TXEIE;
670 usart->CR1 |= USART_CR1_TCIE;
675 if ((usart->CR1 & USART_CR1_TCIE) != 0 && (usart->ISR & USART_ISR_TC) != 0)
678 usart->CR1 &= ~USART_CR1_TCIE;
684 void AES_RNG_LPUART1_IRQHandler(
void)
689 void USART1_IRQHandler(
void)
694 void USART2_IRQHandler(
void)
699 void USART4_5_IRQHandler(
void)
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_init(void)
Initialize DMA.
void twr_dma_channel_stop(twr_dma_channel_t channel)
Stop DMA channel.
@ TWR_DMA_REQUEST_3
DMA request 3.
@ TWR_DMA_SIZE_1
DMA channel data size 1B.
@ TWR_DMA_DIRECTION_TO_RAM
DMA channel direction from peripheral to RAM.
@ TWR_DMA_PRIORITY_HIGH
DMA channel priority is high.
@ TWR_DMA_CHANNEL_3
DMA channel 3.
@ TWR_DMA_MODE_CIRCULAR
DMA channel mode circular.
size_t twr_fifo_irq_read(twr_fifo_t *fifo, void *buffer, size_t length)
Read data from FIFO from interrupt.
size_t twr_fifo_write(twr_fifo_t *fifo, const void *buffer, size_t length)
Write data to FIFO.
bool twr_fifo_is_empty(twr_fifo_t *fifo)
Is empty.
size_t twr_fifo_irq_write(twr_fifo_t *fifo, const void *buffer, size_t length)
Write data to FIFO from interrupt.
size_t twr_fifo_read(twr_fifo_t *fifo, void *buffer, size_t length)
Read data from FIFO.
void twr_gpio_set_pull(twr_gpio_channel_t channel, twr_gpio_pull_t pull)
Set pull-up/pull-down configuration for GPIO channel.
void twr_gpio_init(twr_gpio_channel_t channel)
Initialize GPIO channel.
void twr_gpio_set_mode(twr_gpio_channel_t channel, twr_gpio_mode_t mode)
Set mode of operation for GPIO channel.
@ TWR_GPIO_MODE_ALTERNATE_6
GPIO channel operates in alternate mode AF6.
@ TWR_GPIO_MODE_ALTERNATE_4
GPIO channel operates in alternate mode AF4.
@ TWR_GPIO_MODE_ANALOG
GPIO channel operates in analog mode.
@ TWR_GPIO_P11
GPIO channel P11, TXD2.
@ TWR_GPIO_P1
GPIO channel P1, A1, RXD0.
@ TWR_GPIO_P3
GPIO channel P3, A3, RXD1.
@ TWR_GPIO_P10
GPIO channel P10, RXD2.
@ TWR_GPIO_P2
GPIO channel P2, A2, TXD1.
@ TWR_GPIO_P0
GPIO channel P0, A0, TXD0.
@ TWR_GPIO_PULL_NONE
GPIO channel has no pull-up/pull-down.
@ TWR_GPIO_PULL_UP
GPIO channel has pull-up.
void twr_irq_disable(void)
Disable interrupt requests globally (call can be nested)
void twr_irq_enable(void)
Enable interrupt requests globally (call can be nested)
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
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.
void twr_scheduler_plan_current_now(void)
Schedule current 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.
#define TWR_TICK_INFINITY
Maximum timestamp value.
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
uint64_t twr_tick_t
Timestamp data type.
twr_uart_channel_t
UART channels.
void twr_uart_init(twr_uart_channel_t channel, twr_uart_baudrate_t baudrate, twr_uart_setting_t setting)
Initialize UART channel.
size_t twr_uart_async_write(twr_uart_channel_t channel, const void *buffer, size_t length)
Add data to be transmited in async mode.
void twr_uart_set_async_fifo(twr_uart_channel_t channel, twr_fifo_t *write_fifo, twr_fifo_t *read_fifo)
Set buffers for async transfers.
size_t twr_uart_write(twr_uart_channel_t channel, const void *buffer, size_t length)
Write data to UART channel (blocking call)
bool twr_uart_async_read_start(twr_uart_channel_t channel, twr_tick_t timeout)
Start async reading.
twr_uart_event_t
Callback events.
twr_uart_baudrate_t
UART baudrate.
void twr_uart_set_event_handler(twr_uart_channel_t channel, void(*event_handler)(twr_uart_channel_t, twr_uart_event_t, void *), void *event_param)
Set callback function.
bool twr_uart_async_read_cancel(twr_uart_channel_t channel)
Cancel async reading.
size_t twr_uart_async_read(twr_uart_channel_t channel, void *buffer, size_t length)
Get data that has been received in async mode.
size_t twr_uart_read(twr_uart_channel_t channel, void *buffer, size_t length, twr_tick_t timeout)
Read data from UART channel (blocking call)
void twr_uart_deinit(twr_uart_channel_t channel)
Deinitialize UART channel.
twr_uart_setting_t
UART setting.
@ TWR_UART_UART1
UART channel UART1.
@ TWR_UART_UART2
UART channel UART2.
@ TWR_UART_UART0
UART channel UART0.
@ TWR_UART_EVENT_ASYNC_READ_DATA
Event is reading done.
@ TWR_UART_EVENT_ASYNC_READ_TIMEOUT
Event is timeout.
@ TWR_UART_EVENT_ASYNC_WRITE_DONE
Event is writting done.
@ TWR_UART_BAUDRATE_38400
UART baudrat 38400 bps.
@ TWR_UART_BAUDRATE_921600
UART baudrat 921600 bps.
@ TWR_UART_BAUDRATE_57600
UART baudrat 57600 bps.
@ TWR_UART_BAUDRATE_115200
UART baudrat 115200 bps.
@ TWR_UART_BAUDRATE_19200
UART baudrat 19200 bps.
@ TWR_UART_BAUDRATE_9600
UART baudrat 9600 bps.
DMA channel configuration.
twr_dma_request_t request
DMA channel request.
Structure of FIFO instance.
void * buffer
Pointer to buffer where FIFO holds data.
size_t head
Position of FIFO's head.
size_t size
Size of buffer where FIFO holds data.