Add support for UART1

This commit is contained in:
Samuel Sadok
2020-09-24 19:59:14 +02:00
parent e0c34a66a4
commit e7f046d518
9 changed files with 103 additions and 43 deletions
+1
View File
@@ -2,6 +2,7 @@
Please add a note of your changes below this heading if you make a Pull Request.
### Added
* [Mechanical brake support](docs/mechanical-brakes.md)
* Support for UART1 on GPIO3 and GPIO4. UART0 (on GPIO1/2) and UART1 can currently not be enabled at the same time.
### Changed
+12 -7
View File
@@ -21,7 +21,7 @@ Stm32SpiArbiter spi3_arbiter{&hspi3};
Stm32SpiArbiter& ext_spi_arbiter = spi3_arbiter;
UART_HandleTypeDef* uart0 = &huart4;
UART_HandleTypeDef* uart1 = nullptr; // TODO: this could be supported in ODrive v3.6 (or similar) using STM32's USART2
UART_HandleTypeDef* uart1 = &huart2; // TODO: this could be supported in ODrive v3.6 (or similar) using STM32's USART2
UART_HandleTypeDef* uart2 = nullptr;
Drv8301 m0_gate_driver{
@@ -219,14 +219,14 @@ std::array<GpioFunction, 3> alternate_functions[GPIO_COUNT] = {
#if HW_VERSION_MINOR >= 3
/* GPIO1: */ {{{ODrive::GPIO_MODE_UART0, GPIO_AF8_UART4}, {ODrive::GPIO_MODE_PWM0, GPIO_AF2_TIM5}}},
/* GPIO2: */ {{{ODrive::GPIO_MODE_UART0, GPIO_AF8_UART4}, {ODrive::GPIO_MODE_PWM0, GPIO_AF2_TIM5}}},
/* GPIO3: */ {{{ODrive::GPIO_MODE_PWM0, GPIO_AF2_TIM5}}},
/* GPIO3: */ {{{ODrive::GPIO_MODE_UART1, GPIO_AF7_USART2}, {ODrive::GPIO_MODE_PWM0, GPIO_AF2_TIM5}}},
#else
/* GPIO1: */ {{}},
/* GPIO2: */ {{}},
/* GPIO3: */ {{}},
#endif
/* GPIO4: */ {{{ODrive::GPIO_MODE_PWM0, GPIO_AF2_TIM5}}},
/* GPIO4: */ {{{ODrive::GPIO_MODE_UART1, GPIO_AF7_USART2}, {ODrive::GPIO_MODE_PWM0, GPIO_AF2_TIM5}}},
/* GPIO5: */ {{}},
/* GPIO6: */ {{}},
/* GPIO7: */ {{}},
@@ -273,13 +273,18 @@ bool board_init() {
MX_SPI3_Init();
MX_ADC3_Init();
MX_TIM2_Init();
MX_UART4_Init();
MX_TIM5_Init();
MX_TIM13_Init();
HAL_UART_DeInit(uart0);
uart0->Init.BaudRate = odrv.config_.uart0_baudrate;
HAL_UART_Init(uart0);
if (odrv.config_.enable_uart0) {
uart0->Init.BaudRate = odrv.config_.uart0_baudrate;
MX_UART4_Init();
}
if (odrv.config_.enable_uart1) {
uart1->Init.BaudRate = odrv.config_.uart1_baudrate;
MX_USART2_UART_Init();
}
if (odrv.config_.enable_i2c0) {
// Set up the direction GPIO as input
+8 -1
View File
@@ -41,8 +41,15 @@ size_t oscilloscope_pos = 0;
void init_communication(void) {
printf("hi!\r\n");
// Dual UART operation not supported yet
if (odrv.config_.enable_uart0 && odrv.config_.enable_uart1) {
odrv.misconfigured_ = true;
}
if (odrv.config_.enable_uart0 && uart0) {
start_uart_server();
start_uart_server(uart0);
} else if (odrv.config_.enable_uart1 && uart1) {
start_uart_server(uart1);
}
start_usb_server();
+4 -3
View File
@@ -22,8 +22,7 @@ static uint32_t dma_last_rcv_idx;
// static thread_local uint32_t deadline_ms = 0;
osThreadId uart_thread = 0;
extern UART_HandleTypeDef* uart0;
static UART_HandleTypeDef* huart_ = uart0; // defined in board.cpp.
static UART_HandleTypeDef* huart_ = nullptr;
const uint32_t stack_size_uart_thread = 4096; // Bytes
@@ -102,7 +101,9 @@ static void uart_server_thread(void * ctx) {
}
// TODO: allow multiple UART server instances
void start_uart_server() {
void start_uart_server(UART_HandleTypeDef* huart) {
huart_ = huart;
// DMA is set up to receive in a circular buffer forever.
// We dont use interrupts to fetch the data, instead we periodically read
// data out of the circular buffer into a parse buffer, controlled by a state machine
+2 -1
View File
@@ -9,11 +9,12 @@ extern "C" {
#endif
#include <cmsis_os.h>
#include "usart.h"
extern osThreadId uart_thread;
extern const uint32_t stack_size_uart_thread;
void start_uart_server(void);
void start_uart_server(UART_HandleTypeDef* huart);
void uart_poll(void);
#ifdef __cplusplus
+19 -4
View File
@@ -99,13 +99,24 @@ interfaces:
enable_uart0:
type: bool
doc: Enables/disables UART0. You also need to set the corresponding GPIOs to GPIO_MODE_UART0. Changing this requires a reboot.
enable_uart1: {type: bool, doc: Not supported on ODrive v3.x.}
brief: Enables/disables UART0.
doc: |
You also need to set the corresponding GPIOs to GPIO_MODE_UART0.
Refer to [interfaces](interfaces.md) to see which pins support UART0.
Changing this requires a reboot.
enable_uart0:
type: bool
brief: Enables/disables UART1.
doc: |
You also need to set the corresponding GPIOs to GPIO_MODE_UART1.
Refer to [interfaces](interfaces.md) to see which pins support UART1.
Changing this requires a reboot.
enable_uart2: {type: bool, doc: Not supported on ODrive v3.x.}
uart0_baudrate:
type: uint32
unit: baud/s
brief: Defines the baudrate used on the UART interface.
doc: |
Defines the baudrate used on the UART interface.
Some baudrates will have a small timing error due to hardware limitations.
Here's an (incomplete) list of baudrates for ODrive v3.x:
@@ -127,7 +138,11 @@ interfaces:
For more information refer to Section 30.3.4 and Table 142 (the column with f_PCLK = 42 MHz) in the
[STM datasheet](https://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf).
uart1_baudrate: {type: uint32, doc: Not supported on ODrive v3.x.}
uart1_baudrate:
type: uint32
unit: baud/s
brief: Defines the baudrate used on the UART interface.
doc: See `uart0_baudrate` for details.
uart2_baudrate: {type: uint32, doc: Not supported on ODrive v3.x.}
enable_can0:
type: bool
+20 -19
View File
@@ -18,25 +18,25 @@ The ODrive can be controlled over various ports and protocols. If you're comfort
## Pinout
| # | Label | `GPIO_MODE_DIGITAL` | `GPIO_MODE_ANALOG_IN` | `GPIO_MODE_UART0` | `GPIO_MODE_PWM0` | `GPIO_MODE_CAN0` | `GPIO_MODE_I2C0` | `GPIO_MODE_ENC0` | `GPIO_MODE_ENC1` | `GPIO_MODE_MECH_BRAKE` |
|----|---------------|------------------------|-----------------------|-------------------|------------------|------------------|------------------|------------------|------------------|------------------------|
| 0 | _not a pin_ | | | | | | | | | |
| 1 | GPIO1 (+) | general purpose | analog input | **UART0.TX** | PWM0.0 | | | | | mechanical brake |
| 2 | GPIO2 (+) | general purpose | analog input | **UART0.RX** | PWM0.1 | | | | | mechanical brake |
| 3 | GPIO3 | general purpose | **analog input** | | PWM0.2 | | | | | mechanical brake |
| 4 | GPIO4 | general purpose | **analog input** | | PWM0.3 | | | | | mechanical brake |
| 5 | GPIO5 | general purpose | **analog input** (*) | | | | | | | mechanical brake |
| 6 | GPIO6 (*) (+) | **general purpose** | | | | | | | | mechanical brake |
| 7 | GPIO7 (*) (+) | **general purpose** | | | | | | | | mechanical brake |
| 8 | GPIO8 (*) (+) | **general purpose** | | | | | | | | mechanical brake |
| 9 | M0.A | general purpose | | | | | | **ENC0.A** | | |
| 10 | M0.B | general purpose | | | | | | **ENC0.B** | | |
| 11 | M0.Z | **general purpose** | | | | | | | | |
| 12 | M1.A | general purpose | | | | | I2C.SCL | | **ENC1.A** | |
| 13 | M1.B | general purpose | | | | | I2C.SDA | | **ENC1.B** | |
| 14 | M1.Z | **general purpose** | | | | | | | | |
| 15 | _not exposed_ | general purpose | | | | **CAN0.RX** | I2C.SCL | | | |
| 16 | _not exposed_ | general purpose | | | | **CAN0.TX** | I2C.SDA | | | |
| # | Label | `GPIO_MODE_DIGITAL` | `GPIO_MODE_ANALOG_IN` | `GPIO_MODE_UART0` | `GPIO_MODE_UART1` | `GPIO_MODE_PWM0` | `GPIO_MODE_CAN0` | `GPIO_MODE_I2C0` | `GPIO_MODE_ENC0` | `GPIO_MODE_ENC1` | `GPIO_MODE_MECH_BRAKE` |
|----|---------------|------------------------|-----------------------|-------------------|-------------------|------------------|------------------|------------------|------------------|------------------|------------------------|
| 0 | _not a pin_ | | | | | | | | | | |
| 1 | GPIO1 (+) | general purpose | analog input | **UART0.TX** | | PWM0.0 | | | | | mechanical brake |
| 2 | GPIO2 (+) | general purpose | analog input | **UART0.RX** | | PWM0.1 | | | | | mechanical brake |
| 3 | GPIO3 | general purpose | **analog input** | | **UART1.TX** | PWM0.2 | | | | | mechanical brake |
| 4 | GPIO4 | general purpose | **analog input** | | **UART1.RX** | PWM0.3 | | | | | mechanical brake |
| 5 | GPIO5 | general purpose | **analog input** (*) | | | | | | | | mechanical brake |
| 6 | GPIO6 (*) (+) | **general purpose** | | | | | | | | | mechanical brake |
| 7 | GPIO7 (*) (+) | **general purpose** | | | | | | | | | mechanical brake |
| 8 | GPIO8 (*) (+) | **general purpose** | | | | | | | | | mechanical brake |
| 9 | M0.A | general purpose | | | | | | | **ENC0.A** | | |
| 10 | M0.B | general purpose | | | | | | | **ENC0.B** | | |
| 11 | M0.Z | **general purpose** | | | | | | | | | |
| 12 | M1.A | general purpose | | | | | | I2C.SCL | | **ENC1.A** | |
| 13 | M1.B | general purpose | | | | | | I2C.SDA | | **ENC1.B** | |
| 14 | M1.Z | **general purpose** | | | | | | | | | |
| 15 | _not exposed_ | general purpose | | | | | **CAN0.RX** | I2C.SCL | | | |
| 16 | _not exposed_ | general purpose | | | | | **CAN0.TX** | I2C.SDA | | | |
(*) ODrive v3.5 and later <br>
@@ -50,6 +50,7 @@ Notes:
* Digital mode is a general purpose mode that can be used for these functions: step, dir, enable, encoder index, hall effect encoder, SPI encoder nCS.
* You must also connect GND between ODrive and your other board.
* ODrive v3.3 and onward have 5V tolerant GPIO pins.
* Simultaneous operation of UART0 and UART1 is currently not supported.
## Native Protocol
+6 -1
View File
@@ -21,14 +21,17 @@ Most information in this file can be reproduced by running `dump_interrupts(odrv
| 13 | DMA1_Stream2_IRQn | 5 |
| 15 | DMA1_Stream4_IRQn | 5 |
| 16 | DMA1_Stream5_IRQn | 5 |
| 17 | DMA1_Stream6_IRQn | 5 |
| 18 | ADC_IRQn | 5 |
| 19 | CAN1_TX_IRQn | 6 |
| 20 | CAN1_RX0_IRQn | 6 |
| 21 | CAN1_RX1_IRQn | 6 |
| 22 | CAN1_SCE_IRQn | 6 |
| 25 | TIM1_UP_TIM10_IRQn | 0 |
| 38 | USART2_IRQn | 5 |
| 44 | TIM8_UP_TIM13_IRQn | 0 |
| 45 | TIM8_TRG_COM_TIM14_IRQn | 0 |
| 47 | DMA1_Stream7_IRQn | 5 |
| 50 | TIM5_IRQn | 5 |
| 51 | SPI3_IRQn | 5 |
| 52 | UART4_IRQn | 5 |
@@ -44,6 +47,8 @@ Most information in this file can be reproduced by running `dump_interrupts(odrv
| DMA1_Stream0 | 1 | 0 (SPI3_RX) | SPI |
| DMA1_Stream2 | 0 | 4 (UART4_RX) | UART0 |
| DMA1_Stream4 | 0 | 4 (UART4_TX) | UART0 |
| DMA1_Stream5 | 1 | 0 (SPI3_TX) | SPI |
| DMA1_Stream5 | 0 | 4 (USART2_RX) | UART1 |
| DMA1_Stream6 | 0 | 4 (USART2_TX) | UART1 |
| DMA1_Stream7 | 1 | 0 (SPI3_TX) | SPI |
| DMA2_Stream0 | 0 | 0 (ADC1) | freerunning ADC |
+31 -7
View File
@@ -41,16 +41,40 @@ class TestUartAscii():
'rx': (odrive.gpio1, True),
'tx': (odrive.gpio2, False)
}, SerialPortComponent))
yield (odrive, ports)
yield (odrive, 0, ports)
def run_test(self, odrive: ODriveComponent, port: SerialPortComponent, logger: Logger):
logger.debug('Enabling UART...')
# Enable the line below to manually test UART1. For this you need
# to manually move to the wires go to GPIO1/2 to GPIO3/4. The ones
# that normally go to GPIO3/4 have a low pass filter.
#yield (odrive, 1, ports)
def run_test(self, odrive: ODriveComponent, uart_num: int, port: SerialPortComponent, logger: Logger):
logger.debug('Enabling UART {}...'.format(uart_num))
# GPIOs might be in use by something other than UART and some components
# might be configured so that they would fail in the later test.
odrive.erase_config_and_reboot()
odrive.handle.config.enable_uart0 = True
odrive.handle.config.gpio1_mode = GPIO_MODE_UART0
odrive.handle.config.gpio2_mode = GPIO_MODE_UART0
odrive.disable_mappings()
odrive.handle.config.enable_uart0 = False
odrive.handle.config.uart0_baudrate = 115200
odrive.handle.config.enable_uart1 = False
odrive.handle.config.uart1_baudrate = 115200
odrive.handle.config.enable_uart2 = False
odrive.handle.config.uart2_baudrate = 115200
if uart_num == 0:
odrive.handle.config.enable_uart0 = True
odrive.handle.config.gpio1_mode = GPIO_MODE_UART0
odrive.handle.config.gpio2_mode = GPIO_MODE_UART0
odrive.handle.config.gpio3_mode = GPIO_MODE_ANALOG_IN
odrive.handle.config.gpio4_mode = GPIO_MODE_ANALOG_IN
else:
odrive.handle.config.enable_uart1 = True
odrive.handle.config.gpio1_mode = GPIO_MODE_ANALOG_IN
odrive.handle.config.gpio2_mode = GPIO_MODE_ANALOG_IN
odrive.handle.config.gpio3_mode = GPIO_MODE_UART1
odrive.handle.config.gpio4_mode = GPIO_MODE_UART1
odrive.save_config_and_reboot()
with port.open(115200) as ser:
# reset port to known state