-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
core: Common code for applications dfu-bootloader: Modified version of the DFU bootloader to work with the core linker: Useful linker scripts
- Loading branch information
Showing
13 changed files
with
1,683 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
#include <cstring> | ||
|
||
#include <libopencm3/stm32/rcc.h> | ||
#include <libopencm3/stm32/gpio.h> | ||
#include <libopencm3/stm32/usart.h> | ||
#include <libopencm3/cm3/cortex.h> | ||
#include <libopencm3/cm3/nvic.h> | ||
#include <libopencm3/cm3/scb.h> | ||
|
||
#include <core/types.h> | ||
#include <core/lib/mini_printf.h> | ||
|
||
#include "UART.h" | ||
|
||
constexpr char radix_digits[] = {'0', '1', '2', '3', '4', '5', | ||
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | ||
|
||
// MCU specific methods | ||
// ----------------------------------------- | ||
|
||
#ifdef STM32F1 | ||
_UART1 UART1; | ||
|
||
void _UART1::init(uint32_t bitrate) { | ||
rcc_periph_clock_enable(RCC_GPIOA); | ||
rcc_periph_clock_enable(RCC_AFIO); | ||
rcc_periph_clock_enable(RCC_USART1); | ||
|
||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, | ||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX); | ||
|
||
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, | ||
GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX); | ||
|
||
usart_set_baudrate(USART1, bitrate); | ||
usart_set_databits(USART1, 8); | ||
usart_set_parity(USART1, USART_PARITY_NONE); | ||
usart_set_stopbits(USART1, USART_CR2_STOPBITS_1); | ||
usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); | ||
usart_set_mode(USART1, USART_MODE_TX_RX); | ||
|
||
nvic_enable_irq(NVIC_USART1_IRQ); | ||
usart_enable_rx_interrupt(USART1); | ||
|
||
usart_enable(USART1); | ||
} | ||
|
||
extern "C" void usart1_isr(void) { | ||
|
||
// RX Interrupt | ||
if((USART_CR1(USART1) & USART_CR1_RXNEIE) | ||
&& usart_get_flag(USART1, USART_SR_RXNE)) { | ||
|
||
UART1.rx_push(usart_recv(USART1)); | ||
} | ||
|
||
// TX Interrupt | ||
if((USART_CR1(USART1) & USART_CR1_TXEIE) | ||
&& usart_get_flag(USART1, USART_SR_TXE)) { | ||
|
||
if(UART1.tx_has()) | ||
usart_send(USART1, UART1.tx_pop()); | ||
|
||
// Disable TX interrupt if no more data in queue | ||
if(!UART1.tx_has()) | ||
usart_disable_tx_interrupt(USART1); | ||
} | ||
} | ||
|
||
void _UART1::write(uint8_t data) { | ||
while(tx_len == tx_size); | ||
|
||
CM_ATOMIC_BLOCK() { | ||
uint8_t index = (tx_start + tx_len) % tx_size; | ||
tx_buffer[index] = data; | ||
|
||
tx_len++; | ||
|
||
if(!(USART_CR1(USART1) & USART_CR1_TXEIE)) | ||
usart_enable_tx_interrupt(USART1); | ||
} | ||
} | ||
|
||
// void _UART1::write(uint8_t *data, size_t count) { | ||
void _UART1::write(void *data, size_t count) { | ||
for(size_t i = 0; i < count; i++) | ||
write(((uint8_t *) data)[i]); | ||
} | ||
|
||
#else | ||
#error Please provide UART definitions for this MCU | ||
#endif | ||
|
||
// Methods used by ISRs | ||
// ----------------------------------------- | ||
|
||
void UART_VIRTUAL::rx_push(uint8_t data) { | ||
if(rx_len == rx_size) | ||
return; | ||
|
||
size_t index = (rx_start + rx_len) % rx_size; | ||
rx_buffer[index] = data; | ||
|
||
rx_len++; | ||
} | ||
|
||
uint8_t UART_VIRTUAL::tx_pop() { | ||
if(tx_len == 0) return 0; | ||
|
||
uint8_t data = tx_buffer[tx_start]; | ||
|
||
tx_start = (tx_start + 1) % tx_size; | ||
tx_len--; | ||
|
||
return data; | ||
} | ||
|
||
bool UART_VIRTUAL::tx_has() { | ||
return (tx_len > 0); | ||
} | ||
|
||
// Receive methods | ||
// ----------------------------------------- | ||
|
||
uint8_t UART_VIRTUAL::read() { | ||
uint8_t data; | ||
|
||
while(rx_len == 0); | ||
|
||
CM_ATOMIC_BLOCK() { | ||
data = rx_buffer[rx_start]; | ||
|
||
rx_start = (rx_start + 1) % rx_size; | ||
rx_len--; | ||
} | ||
|
||
return data; | ||
} | ||
|
||
size_t UART_VIRTUAL::available() { | ||
return rx_len; | ||
} | ||
|
||
uint8_t UART_VIRTUAL::peek() { | ||
uint8_t data; | ||
|
||
while(rx_len == 0); | ||
|
||
CM_ATOMIC_BLOCK() { | ||
data = rx_buffer[rx_start]; | ||
} | ||
|
||
return data; | ||
} | ||
|
||
// Transmit buffer methods | ||
// ----------------------------------------- | ||
|
||
size_t UART_VIRTUAL::tx_items() { | ||
return tx_len; | ||
} | ||
|
||
void UART_VIRTUAL::tx_flush() { | ||
while(tx_len != 0); | ||
} | ||
|
||
size_t UART_VIRTUAL::printf(const char *fmt, ...) { | ||
char printf_buffer[128]; | ||
|
||
va_list va; | ||
va_start(va, fmt); | ||
|
||
size_t len = mini_vsnprintf(printf_buffer, | ||
sizeof printf_buffer, fmt, va); | ||
|
||
va_end(va); | ||
|
||
write((uint8_t *) printf_buffer, len); | ||
|
||
return len; | ||
} | ||
|
||
// ----------------------------------------- | ||
|
||
void UART_VIRTUAL::write_word(uint16_t data) { | ||
data = __builtin_bswap16(data); | ||
write((uint8_t *) &data, 2); | ||
} | ||
|
||
void UART_VIRTUAL::write_dword(uint32_t data) { | ||
data = __builtin_bswap32(data); | ||
write((uint8_t *) &data, 4); | ||
} | ||
|
||
uint16_t UART_VIRTUAL::read_word() { | ||
return ((uint16_t) read() << 8) | read(); | ||
} | ||
|
||
uint32_t UART_VIRTUAL::read_dword() { | ||
return ((uint32_t) read() << 24) | ((uint32_t)read() << 16) | ||
| ((uint16_t) read() << 8) | read(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#ifndef UART_H | ||
#define UART_H | ||
|
||
#include <core/types.h> | ||
|
||
#define UART_TX_BUF_SIZE 128 | ||
#define UART_RX_BUF_SIZE 128 | ||
|
||
#define DEC 10 | ||
#define HEX 16 | ||
#define OCT 8 | ||
#define BIN 2 | ||
|
||
class UART_VIRTUAL { | ||
protected: | ||
static constexpr size_t tx_size = UART_TX_BUF_SIZE; | ||
static constexpr size_t rx_size = UART_RX_BUF_SIZE; | ||
|
||
uint8_t tx_buffer[tx_size]; | ||
uint8_t rx_buffer[rx_size]; | ||
|
||
volatile size_t rx_start = 0, tx_start = 0; | ||
volatile size_t rx_len = 0, tx_len = 0; | ||
|
||
public: | ||
/* Not really meant to be called by the user. | ||
* Public so that they can be called from ISRs. | ||
* Also, not async-safe. */ | ||
|
||
void rx_push(uint8_t data); | ||
uint8_t tx_pop(); | ||
bool tx_has(); | ||
|
||
public: | ||
bool initialized = false; | ||
|
||
virtual void init(uint32_t bitrate) = 0; | ||
|
||
virtual void write(uint8_t data) = 0; | ||
// virtual void write(uint8_t *data, size_t count) = 0; | ||
virtual void write(void *data, size_t count) = 0; | ||
uint8_t read(); | ||
|
||
size_t available(); | ||
uint8_t peek(); | ||
|
||
size_t tx_items(); | ||
void tx_flush(); | ||
|
||
size_t printf(const char *fmt, ...); | ||
|
||
void write_word(uint16_t data); | ||
void write_dword(uint32_t data); | ||
|
||
uint16_t read_word(); | ||
uint32_t read_dword(); | ||
}; | ||
|
||
#ifdef STM32F1 | ||
extern class _UART1 : public UART_VIRTUAL { | ||
public: | ||
void init(uint32_t bitrate); | ||
|
||
void write(uint8_t data); | ||
// void write(uint8_t *data, size_t count); | ||
void write(void *data, size_t count); | ||
} UART1; | ||
|
||
#else | ||
#error Please provide UART definitions for this MCU | ||
#endif | ||
|
||
#endif |
Oops, something went wrong.