diff --git a/CHANGELOG.md b/CHANGELOG.md index ea1c76d9..a8504f12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,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) * Added periodic sending of encoder position on CAN +* Support for UART1 on GPIO3 and GPIO4. UART0 (on GPIO1/2) and UART1 can currently not be enabled at the same time. ### Changed * Modified encoder offset calibration to work correctly when calib_scan_distance is not a multiple of 4pi diff --git a/Firmware/Board/v3/Inc/board.h b/Firmware/Board/v3/Inc/board.h index 931286d5..4d83f9af 100644 --- a/Firmware/Board/v3/Inc/board.h +++ b/Firmware/Board/v3/Inc/board.h @@ -43,8 +43,8 @@ #define DEFAULT_GPIO_MODES \ ODriveIntf::GPIO_MODE_DIGITAL, \ - ODriveIntf::GPIO_MODE_UART0, \ - ODriveIntf::GPIO_MODE_UART0, \ + ODriveIntf::GPIO_MODE_UART_A, \ + ODriveIntf::GPIO_MODE_UART_A, \ ODriveIntf::GPIO_MODE_ANALOG_IN, \ ODriveIntf::GPIO_MODE_ANALOG_IN, \ ODriveIntf::GPIO_MODE_ANALOG_IN, \ @@ -57,8 +57,8 @@ ODriveIntf::GPIO_MODE_ENC1, \ ODriveIntf::GPIO_MODE_ENC1, \ ODriveIntf::GPIO_MODE_DIGITAL_PULL_DOWN, \ - ODriveIntf::GPIO_MODE_CAN0, \ - ODriveIntf::GPIO_MODE_CAN0, + ODriveIntf::GPIO_MODE_CAN_A, \ + ODriveIntf::GPIO_MODE_CAN_A, #define TIM_TIME_BASE TIM14 @@ -89,9 +89,9 @@ extern USBD_HandleTypeDef& usb_dev_handle; extern Stm32SpiArbiter& ext_spi_arbiter; -extern UART_HandleTypeDef* uart0; -extern UART_HandleTypeDef* uart1; -extern UART_HandleTypeDef* uart2; +extern UART_HandleTypeDef* uart_a; +extern UART_HandleTypeDef* uart_b; +extern UART_HandleTypeDef* uart_c; extern PwmInput pwm0_input; #endif diff --git a/Firmware/Board/v3/Inc/stm32f4xx_it.h b/Firmware/Board/v3/Inc/stm32f4xx_it.h index 784a3333..3bdb143f 100644 --- a/Firmware/Board/v3/Inc/stm32f4xx_it.h +++ b/Firmware/Board/v3/Inc/stm32f4xx_it.h @@ -58,11 +58,14 @@ void DMA1_Stream0_IRQHandler(void); void DMA1_Stream2_IRQHandler(void); void DMA1_Stream4_IRQHandler(void); void DMA1_Stream5_IRQHandler(void); +void DMA1_Stream6_IRQHandler(void); +void DMA1_Stream7_IRQHandler(void); void ADC_IRQHandler(void); void CAN1_TX_IRQHandler(void); void CAN1_RX0_IRQHandler(void); void CAN1_RX1_IRQHandler(void); void CAN1_SCE_IRQHandler(void); +void USART2_IRQHandler(void); void TIM8_TRG_COM_TIM14_IRQHandler(void); void TIM5_IRQHandler(void); void SPI3_IRQHandler(void); diff --git a/Firmware/Board/v3/Inc/usart.h b/Firmware/Board/v3/Inc/usart.h index c987f7f2..ff3d48b8 100644 --- a/Firmware/Board/v3/Inc/usart.h +++ b/Firmware/Board/v3/Inc/usart.h @@ -62,6 +62,7 @@ /* USER CODE END Includes */ extern UART_HandleTypeDef huart4; +extern UART_HandleTypeDef huart2; /* USER CODE BEGIN Private defines */ @@ -70,6 +71,7 @@ extern UART_HandleTypeDef huart4; extern void _Error_Handler(char *, int); void MX_UART4_Init(void); +void MX_USART2_UART_Init(void); /* USER CODE BEGIN Prototypes */ diff --git a/Firmware/Board/v3/Src/dma.c b/Firmware/Board/v3/Src/dma.c index 813c735a..969827c7 100644 --- a/Firmware/Board/v3/Src/dma.c +++ b/Firmware/Board/v3/Src/dma.c @@ -83,6 +83,12 @@ void MX_DMA_Init(void) /* DMA1_Stream5_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); + /* DMA1_Stream6_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn); + /* DMA1_Stream7_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Stream7_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn); /* DMA2_Stream0_IRQn interrupt configuration */ // Dear STM, no we _don't_ want to fire an interrupt for this DMA // (it's not possible to deselect this in CubeMX) diff --git a/Firmware/Board/v3/Src/spi.c b/Firmware/Board/v3/Src/spi.c index a3a3311e..42aae784 100644 --- a/Firmware/Board/v3/Src/spi.c +++ b/Firmware/Board/v3/Src/spi.c @@ -110,7 +110,7 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) /* SPI3 DMA Init */ /* SPI3_TX Init */ - hdma_spi3_tx.Instance = DMA1_Stream5; + hdma_spi3_tx.Instance = DMA1_Stream7; hdma_spi3_tx.Init.Channel = DMA_CHANNEL_0; hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; diff --git a/Firmware/Board/v3/Src/stm32f4xx_it.c b/Firmware/Board/v3/Src/stm32f4xx_it.c index ec80da19..175a4380 100644 --- a/Firmware/Board/v3/Src/stm32f4xx_it.c +++ b/Firmware/Board/v3/Src/stm32f4xx_it.c @@ -54,7 +54,10 @@ extern TIM_HandleTypeDef htim5; extern TIM_HandleTypeDef htim8; extern DMA_HandleTypeDef hdma_uart4_rx; extern DMA_HandleTypeDef hdma_uart4_tx; +extern DMA_HandleTypeDef hdma_usart2_rx; +extern DMA_HandleTypeDef hdma_usart2_tx; extern UART_HandleTypeDef huart4; +extern UART_HandleTypeDef huart2; extern TIM_HandleTypeDef htim14; @@ -251,12 +254,40 @@ void DMA1_Stream5_IRQHandler(void) /* USER CODE BEGIN DMA1_Stream5_IRQn 0 */ COUNT_IRQ(DMA1_Stream5_IRQn); /* USER CODE END DMA1_Stream5_IRQn 0 */ - HAL_DMA_IRQHandler(&hdma_spi3_tx); + HAL_DMA_IRQHandler(&hdma_usart2_rx); /* USER CODE BEGIN DMA1_Stream5_IRQn 1 */ /* USER CODE END DMA1_Stream5_IRQn 1 */ } +/** +* @brief This function handles DMA1 stream6 global interrupt. +*/ +void DMA1_Stream6_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Stream6_IRQn 0 */ + COUNT_IRQ(DMA1_Stream6_IRQn); + /* USER CODE END DMA1_Stream6_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_usart2_tx); + /* USER CODE BEGIN DMA1_Stream6_IRQn 1 */ + + /* USER CODE END DMA1_Stream6_IRQn 1 */ +} + +/** +* @brief This function handles DMA1 stream7 global interrupt. +*/ +void DMA1_Stream7_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Stream7_IRQn 0 */ + COUNT_IRQ(DMA1_Stream7_IRQn); + /* USER CODE END DMA1_Stream7_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_spi3_tx); + /* USER CODE BEGIN DMA1_Stream7_IRQn 1 */ + + /* USER CODE END DMA1_Stream7_IRQn 1 */ +} + /** * @brief This function handles CAN1 TX interrupts. */ @@ -313,6 +344,20 @@ void CAN1_SCE_IRQHandler(void) /* USER CODE END CAN1_SCE_IRQn 1 */ } +/** + * @brief This function handles USART2 global interrupt. + */ +void USART2_IRQHandler(void) +{ + /* USER CODE BEGIN USART2_IRQn 0 */ + + /* USER CODE END USART2_IRQn 0 */ + HAL_UART_IRQHandler(&huart2); + /* USER CODE BEGIN USART2_IRQn 1 */ + + /* USER CODE END USART2_IRQn 1 */ +} + /** * @brief This function handles TIM8 trigger and commutation interrupts and TIM14 global interrupt. */ diff --git a/Firmware/Board/v3/Src/usart.c b/Firmware/Board/v3/Src/usart.c index 93bac536..b2c8e461 100644 --- a/Firmware/Board/v3/Src/usart.c +++ b/Firmware/Board/v3/Src/usart.c @@ -58,15 +58,18 @@ /* USER CODE END 0 */ UART_HandleTypeDef huart4; +UART_HandleTypeDef huart2; DMA_HandleTypeDef hdma_uart4_rx; DMA_HandleTypeDef hdma_uart4_tx; +DMA_HandleTypeDef hdma_usart2_rx; +DMA_HandleTypeDef hdma_usart2_tx; /* UART4 init function */ void MX_UART4_Init(void) { huart4.Instance = UART4; - huart4.Init.BaudRate = 115200; // Provisionally this can be changed to 921600 for faster transfers, the low power Arduinos will not keep up. + //huart4.Init.BaudRate = 115200; // Provisionally this can be changed to 921600 for faster transfers, the low power Arduinos will not keep up. huart4.Init.WordLength = UART_WORDLENGTH_8B; huart4.Init.StopBits = UART_STOPBITS_1; huart4.Init.Parity = UART_PARITY_NONE; @@ -78,6 +81,25 @@ void MX_UART4_Init(void) _Error_Handler(__FILE__, __LINE__); } +} +/* USART2 init function */ + +void MX_USART2_UART_Init(void) +{ + + huart2.Instance = USART2; + //huart2.Init.BaudRate = 115200; + huart2.Init.WordLength = UART_WORDLENGTH_8B; + huart2.Init.StopBits = UART_STOPBITS_1; + huart2.Init.Parity = UART_PARITY_NONE; + huart2.Init.Mode = UART_MODE_TX_RX; + huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart2.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart2) != HAL_OK) + { + Error_Handler(); + } + } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) @@ -135,6 +157,58 @@ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) /* USER CODE END UART4_MspInit 1 */ } + else if(uartHandle->Instance==USART2) + { + /* USER CODE BEGIN USART2_MspInit 0 */ + + /* USER CODE END USART2_MspInit 0 */ + /* USART2 clock enable */ + __HAL_RCC_USART2_CLK_ENABLE(); + + /* USART2 DMA Init */ + /* USART2_RX Init */ + hdma_usart2_rx.Instance = DMA1_Stream5; + hdma_usart2_rx.Init.Channel = DMA_CHANNEL_4; + hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_usart2_rx.Init.Mode = DMA_CIRCULAR; + hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx); + + /* USART2_TX Init */ + hdma_usart2_tx.Instance = DMA1_Stream6; + hdma_usart2_tx.Init.Channel = DMA_CHANNEL_4; + hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_usart2_tx.Init.Mode = DMA_NORMAL; + hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_usart2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&hdma_usart2_tx) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart2_tx); + + /* USART2 interrupt Init */ + HAL_NVIC_SetPriority(USART2_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(USART2_IRQn); + /* USER CODE BEGIN USART2_MspInit 1 */ + + /* USER CODE END USART2_MspInit 1 */ + } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) @@ -147,12 +221,6 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) /* USER CODE END UART4_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART4_CLK_DISABLE(); - - /**UART4 GPIO Configuration - PA0-WKUP ------> UART4_TX - PA1 ------> UART4_RX - */ - HAL_GPIO_DeInit(GPIOA, GPIO_1_Pin|GPIO_2_Pin); /* UART4 DMA DeInit */ HAL_DMA_DeInit(uartHandle->hdmarx); @@ -164,6 +232,24 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) /* USER CODE END UART4_MspDeInit 1 */ } + else if(uartHandle->Instance==USART2) + { + /* USER CODE BEGIN USART2_MspDeInit 0 */ + + /* USER CODE END USART2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART2_CLK_DISABLE(); + + /* UART4 DMA DeInit */ + HAL_DMA_DeInit(uartHandle->hdmarx); + HAL_DMA_DeInit(uartHandle->hdmatx); + + /* USART2 interrupt Deinit */ + HAL_NVIC_DisableIRQ(USART2_IRQn); + /* USER CODE BEGIN USART2_MspDeInit 1 */ + + /* USER CODE END USART2_MspDeInit 1 */ + } } /* USER CODE BEGIN 1 */ diff --git a/Firmware/Board/v3/board.cpp b/Firmware/Board/v3/board.cpp index 716329cf..679aa633 100644 --- a/Firmware/Board/v3/board.cpp +++ b/Firmware/Board/v3/board.cpp @@ -20,9 +20,9 @@ extern "C" void SystemClock_Config(void); // defined in main.c generated by Cube 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* uart2 = nullptr; +UART_HandleTypeDef* uart_a = &huart4; +UART_HandleTypeDef* uart_b = &huart2; // TODO: this could be supported in ODrive v3.6 (or similar) using STM32's USART2 +UART_HandleTypeDef* uart_c = nullptr; Drv8301 m0_gate_driver{ &spi3_arbiter, @@ -218,16 +218,16 @@ std::array alternate_functions[GPIO_COUNT] = { /* GPIO0 (inexistent): */ {{}}, #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}}}, + /* GPIO1: */ {{{ODrive::GPIO_MODE_UART_A, GPIO_AF8_UART4}, {ODrive::GPIO_MODE_PWM, GPIO_AF2_TIM5}}}, + /* GPIO2: */ {{{ODrive::GPIO_MODE_UART_A, GPIO_AF8_UART4}, {ODrive::GPIO_MODE_PWM, GPIO_AF2_TIM5}}}, + /* GPIO3: */ {{{ODrive::GPIO_MODE_UART_B, GPIO_AF7_USART2}, {ODrive::GPIO_MODE_PWM, GPIO_AF2_TIM5}}}, #else /* GPIO1: */ {{}}, /* GPIO2: */ {{}}, /* GPIO3: */ {{}}, #endif - /* GPIO4: */ {{{ODrive::GPIO_MODE_PWM0, GPIO_AF2_TIM5}}}, + /* GPIO4: */ {{{ODrive::GPIO_MODE_UART_B, GPIO_AF7_USART2}, {ODrive::GPIO_MODE_PWM, GPIO_AF2_TIM5}}}, /* GPIO5: */ {{}}, /* GPIO6: */ {{}}, /* GPIO7: */ {{}}, @@ -235,11 +235,11 @@ std::array alternate_functions[GPIO_COUNT] = { /* ENC0_A: */ {{{ODrive::GPIO_MODE_ENC0, GPIO_AF2_TIM3}}}, /* ENC0_B: */ {{{ODrive::GPIO_MODE_ENC0, GPIO_AF2_TIM3}}}, /* ENC0_Z: */ {{}}, - /* ENC1_A: */ {{{ODrive::GPIO_MODE_I2C0, GPIO_AF4_I2C1}, {ODrive::GPIO_MODE_ENC1, GPIO_AF2_TIM4}}}, - /* ENC1_B: */ {{{ODrive::GPIO_MODE_I2C0, GPIO_AF4_I2C1}, {ODrive::GPIO_MODE_ENC1, GPIO_AF2_TIM4}}}, + /* ENC1_A: */ {{{ODrive::GPIO_MODE_I2C_A, GPIO_AF4_I2C1}, {ODrive::GPIO_MODE_ENC1, GPIO_AF2_TIM4}}}, + /* ENC1_B: */ {{{ODrive::GPIO_MODE_I2C_A, GPIO_AF4_I2C1}, {ODrive::GPIO_MODE_ENC1, GPIO_AF2_TIM4}}}, /* ENC1_Z: */ {{}}, - /* CAN_R: */ {{{ODrive::GPIO_MODE_CAN0, GPIO_AF9_CAN1}, {ODrive::GPIO_MODE_I2C0, GPIO_AF4_I2C1}}}, - /* CAN_D: */ {{{ODrive::GPIO_MODE_CAN0, GPIO_AF9_CAN1}, {ODrive::GPIO_MODE_I2C0, GPIO_AF4_I2C1}}}, + /* CAN_R: */ {{{ODrive::GPIO_MODE_CAN_A, GPIO_AF9_CAN1}, {ODrive::GPIO_MODE_I2C_A, GPIO_AF4_I2C1}}}, + /* CAN_D: */ {{{ODrive::GPIO_MODE_CAN_A, GPIO_AF9_CAN1}, {ODrive::GPIO_MODE_I2C_A, GPIO_AF4_I2C1}}}, }; #if HW_VERSION_MINOR <= 2 @@ -274,15 +274,20 @@ 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_uart_a) { + uart_a->Init.BaudRate = odrv.config_.uart_a_baudrate; + MX_UART4_Init(); + } - if (odrv.config_.enable_i2c0) { + if (odrv.config_.enable_uart_b) { + uart_b->Init.BaudRate = odrv.config_.uart_b_baudrate; + MX_USART2_UART_Init(); + } + + if (odrv.config_.enable_i2c_a) { // Set up the direction GPIO as input get_gpio(3).config(GPIO_MODE_INPUT, GPIO_PULLUP); get_gpio(4).config(GPIO_MODE_INPUT, GPIO_PULLUP); @@ -296,11 +301,11 @@ bool board_init() { MX_I2C1_Init(i2c_stats_.addr); } - if (odrv.config_.enable_can0) { + if (odrv.config_.enable_can_a) { // The CAN initialization will (and must) init its own GPIOs before the // GPIO modes are initialized. Therefore we ensure that the later GPIO // mode initialization won't override the CAN mode. - if (odrv.config_.gpio_modes[15] != ODriveIntf::GPIO_MODE_CAN0 || odrv.config_.gpio_modes[16] != ODriveIntf::GPIO_MODE_CAN0) { + if (odrv.config_.gpio_modes[15] != ODriveIntf::GPIO_MODE_CAN_A || odrv.config_.gpio_modes[16] != ODriveIntf::GPIO_MODE_CAN_A) { odrv.misconfigured_ = true; } else { MX_CAN1_Init(); diff --git a/Firmware/MotorControl/main.cpp b/Firmware/MotorControl/main.cpp index 301fe1c4..9e647e49 100644 --- a/Firmware/MotorControl/main.cpp +++ b/Firmware/MotorControl/main.cpp @@ -398,9 +398,9 @@ extern "C" int main(void) { } odrv.misconfigured_ = odrv.misconfigured_ - || (odrv.config_.enable_uart0 && !uart0) - || (odrv.config_.enable_uart1 && !uart1) - || (odrv.config_.enable_uart2 && !uart2); + || (odrv.config_.enable_uart_a && !uart_a) + || (odrv.config_.enable_uart_b && !uart_b) + || (odrv.config_.enable_uart_c && !uart_c); // Init board-specific peripherals if (!board_init()) { @@ -458,49 +458,49 @@ extern "C" int main(void) { GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; } break; - case ODriveIntf::GPIO_MODE_UART0: { + case ODriveIntf::GPIO_MODE_UART_A: { GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = (i == 0) ? GPIO_PULLDOWN : GPIO_PULLUP; // this is probably swapped but imitates old behavior GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - if (!odrv.config_.enable_uart0) { + if (!odrv.config_.enable_uart_a) { odrv.misconfigured_ = true; } } break; - case ODriveIntf::GPIO_MODE_UART1: { + case ODriveIntf::GPIO_MODE_UART_B: { GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = (i == 0) ? GPIO_PULLDOWN : GPIO_PULLUP; // this is probably swapped but imitates old behavior GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - if (!odrv.config_.enable_uart1) { + if (!odrv.config_.enable_uart_b) { odrv.misconfigured_ = true; } } break; - case ODriveIntf::GPIO_MODE_UART2: { + case ODriveIntf::GPIO_MODE_UART_C: { GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = (i == 0) ? GPIO_PULLDOWN : GPIO_PULLUP; // this is probably swapped but imitates old behavior GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - if (!odrv.config_.enable_uart2) { + if (!odrv.config_.enable_uart_c) { odrv.misconfigured_ = true; } } break; - case ODriveIntf::GPIO_MODE_CAN0: { + case ODriveIntf::GPIO_MODE_CAN_A: { GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - if (!odrv.config_.enable_can0) { + if (!odrv.config_.enable_can_a) { odrv.misconfigured_ = true; } } break; - case ODriveIntf::GPIO_MODE_I2C0: { + case ODriveIntf::GPIO_MODE_I2C_A: { GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - if (!odrv.config_.enable_i2c0) { + if (!odrv.config_.enable_i2c_a) { odrv.misconfigured_ = true; } } break; - //case ODriveIntf::GPIO_MODE_SPI0: { // TODO + //case ODriveIntf::GPIO_MODE_SPI_A: { // TODO //} break; - case ODriveIntf::GPIO_MODE_PWM0: { + case ODriveIntf::GPIO_MODE_PWM: { GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; diff --git a/Firmware/MotorControl/odrive_main.h b/Firmware/MotorControl/odrive_main.h index 4291bbfa..f59a7e2b 100644 --- a/Firmware/MotorControl/odrive_main.h +++ b/Firmware/MotorControl/odrive_main.h @@ -61,14 +61,14 @@ struct BoardConfig_t { DEFAULT_GPIO_MODES }; - bool enable_uart0 = true; - bool enable_uart1 = false; - bool enable_uart2 = false; - uint32_t uart0_baudrate = 115200; - uint32_t uart1_baudrate = 115200; - uint32_t uart2_baudrate = 115200; - bool enable_can0 = true; - bool enable_i2c0 = false; + bool enable_uart_a = true; + bool enable_uart_b = false; + bool enable_uart_c = false; + uint32_t uart_a_baudrate = 115200; + uint32_t uart_b_baudrate = 115200; + uint32_t uart_c_baudrate = 115200; + bool enable_can_a = true; + bool enable_i2c_a = false; bool enable_ascii_protocol_on_usb = true; float max_regen_current = 0.0f; float brake_resistance = DEFAULT_BRAKE_RESISTANCE; diff --git a/Firmware/communication/communication.cpp b/Firmware/communication/communication.cpp index 7845fd6f..20680987 100644 --- a/Firmware/communication/communication.cpp +++ b/Firmware/communication/communication.cpp @@ -41,17 +41,24 @@ size_t oscilloscope_pos = 0; void init_communication(void) { printf("hi!\r\n"); - if (odrv.config_.enable_uart0 && uart0) { - start_uart_server(); + // Dual UART operation not supported yet + if (odrv.config_.enable_uart_a && odrv.config_.enable_uart_b) { + odrv.misconfigured_ = true; + } + + if (odrv.config_.enable_uart_a && uart_a) { + start_uart_server(uart_a); + } else if (odrv.config_.enable_uart_b && uart_b) { + start_uart_server(uart_b); } start_usb_server(); - if (odrv.config_.enable_i2c0) { + if (odrv.config_.enable_i2c_a) { start_i2c_server(); } - if (odrv.config_.enable_can0) { + if (odrv.config_.enable_can_a) { odCAN->start_can_server(); } } diff --git a/Firmware/communication/interface_uart.cpp b/Firmware/communication/interface_uart.cpp index 6450eb50..c0775df5 100644 --- a/Firmware/communication/interface_uart.cpp +++ b/Firmware/communication/interface_uart.cpp @@ -19,8 +19,7 @@ static uint8_t dma_rx_buffer[UART_RX_BUFFER_SIZE]; static uint32_t dma_last_rcv_idx; 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 @@ -97,7 +96,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 diff --git a/Firmware/communication/interface_uart.h b/Firmware/communication/interface_uart.h index a7df55bd..83b70e66 100644 --- a/Firmware/communication/interface_uart.h +++ b/Firmware/communication/interface_uart.h @@ -9,11 +9,12 @@ extern "C" { #endif #include +#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 diff --git a/Firmware/fibre/tools/interface_generator.py b/Firmware/fibre/tools/interface_generator.py index 2dcf9c83..6c4390bc 100644 --- a/Firmware/fibre/tools/interface_generator.py +++ b/Firmware/fibre/tools/interface_generator.py @@ -91,6 +91,8 @@ properties: additionalProperties: false """)) +# TODO: detect duplicate keys in yaml dictionaries + # Source: https://stackoverflow.com/a/53647080/3621512 class SafeLineLoader(yaml.SafeLoader): pass diff --git a/Firmware/odrive-interface.yaml b/Firmware/odrive-interface.yaml index dec37590..f6d5ad4e 100644 --- a/Firmware/odrive-interface.yaml +++ b/Firmware/odrive-interface.yaml @@ -98,15 +98,26 @@ interfaces: gpio15_mode: {type: GpioMode, doc: Mode of GPIO15 (changes take effect after reboot), c_name: 'gpio_modes[15]'} gpio16_mode: {type: GpioMode, doc: Mode of GPIO16 (changes take effect after reboot), c_name: 'gpio_modes[16]'} - enable_uart0: + enable_uart_a: 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.} - enable_uart2: {type: bool, doc: Not supported on ODrive v3.x.} - uart0_baudrate: - type: uint32 + brief: Enables/disables UART_A. + doc: | + You also need to set the corresponding GPIOs to GPIO_MODE_UART_A. + Refer to [interfaces](interfaces.md) to see which pins support UART_A. + Changing this requires a reboot. + enable_uart_b: + type: bool + brief: Enables/disables UART_B. + doc: | + You also need to set the corresponding GPIOs to GPIO_MODE_UART_B. + Refer to [interfaces](interfaces.md) to see which pins support UART_B. + Changing this requires a reboot. + enable_uart_c: {type: bool, doc: Not supported on ODrive v3.x.} + uart_a_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: @@ -128,17 +139,21 @@ 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.} - uart2_baudrate: {type: uint32, doc: Not supported on ODrive v3.x.} - enable_can0: + uart_b_baudrate: + type: uint32 + unit: baud/s + brief: Defines the baudrate used on the UART interface. + doc: See `uart_a_baudrate` for details. + uart_c_baudrate: {type: uint32, doc: Not supported on ODrive v3.x.} + enable_can_a: type: bool doc: | Enables CAN. Changing this setting requires a reboot. - enable_i2c0: + enable_i2c_a: type: bool doc: | Enables I2C. The I2C pins on ODrive v3.x are in conflict with CAN. - This setting has no effect if `enable_can0` is also true. + This setting has no effect if `enable_can_a` is also true. This setting has no effect on ODrive v3.2 or earlier. Changing this setting requires a reboot. enable_ascii_protocol_on_usb: bool @@ -202,10 +217,10 @@ interfaces: brief: Max current the power supply can sink. doc: You most likely want a non-positive value here. Set to -INFINITY to disable. - gpio1_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[0]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM0`.} - gpio2_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[1]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM0`.} - gpio3_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[2]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM0`.} - gpio4_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[3]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM0`.} + gpio1_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[0]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM`.} + gpio2_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[1]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM`.} + gpio3_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[2]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM`.} + gpio4_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[3]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM`.} gpio3_analog_mapping: {type: Endpoint, c_name: 'analog_mappings[3]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_ANALOG_IN`.} gpio4_analog_mapping: {type: Endpoint, c_name: 'analog_mappings[4]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_ANALOG_IN`.} user_config_loaded: readonly uint32 @@ -220,10 +235,10 @@ interfaces: Possible causes: - A GPIO was set to a mode that it doesn't support - A GPIO was set to a mode for which the corresponding feature was - not enabled. Example: `GPIO_MODE_UART0` was used without enabling - `config.enable_uart0`. + not enabled. Example: `GPIO_MODE_UART_A` was used without enabling + `config.enable_uart_a`. - A feature was enabled which is not supported on this hardware. - Example: `config.enable_uart2` set to true on ODrive v3.x. + Example: `config.enable_uart_c` set to true on ODrive v3.x. - A GPIO was used as an interrupt input for two internal components or two GPIOs that are mutually exclusive in their interrupt capability were both used as interrupt input. @@ -983,15 +998,15 @@ valuetypes: doc: | The pin can be used for one or more of these functions: Sin/cos encoders, analog input, `get_adc_voltage`. - Uart0: {doc: See `config.enable_uart0`.} - Uart1: {doc: This mode is not supported on ODrive v3.x.} - Uart2: {doc: This mode is not supported on ODrive v3.x.} - Can0: {doc: See `config.enable_can0`.} - I2c0: {doc: See `config.enable_i2c0`.} - Spi0: {doc: Note that the SPI pins on ODrive v3.x are hardwired so they - cannot be configured through software. Consequently, even though SPI0 + UartA: {doc: See `config.enable_uart_a`.} + UartB: {doc: This mode is not supported on ODrive v3.x.} + UartC: {doc: This mode is not supported on ODrive v3.x.} + CanA: {doc: See `config.enable_can_a`.} + I2cA: {doc: See `config.enable_i2c_a`.} + SpiA: {doc: Note that the SPI pins on ODrive v3.x are hardwired so they + cannot be configured through software. Consequently, even though SPI_A is exposed, this mode is of no use on ODrive v3.x.} - Pwm0: {doc: See `config.gpio0_pwm_mapping`.} + Pwm: {doc: See `config.gpio0_pwm_mapping`.} Enc0: {doc: The pin is used by quadrature encoder 0.} Enc1: {doc: The pin is used by quadrature encoder 1.} Enc2: {doc: This mode is not supported on ODrive v3.x.} diff --git a/docs/pinout.md b/docs/pinout.md index 84401b3f..bc30bbdc 100644 --- a/docs/pinout.md +++ b/docs/pinout.md @@ -1,24 +1,24 @@ # 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_UART_A` | `GPIO_MODE_UART_B` | `GPIO_MODE_PWM` | `GPIO_MODE_CAN_A` | `GPIO_MODE_I2C_A` | `GPIO_MODE_ENC0` | `GPIO_MODE_ENC1` | `GPIO_MODE_MECH_BRAKE` | +|----|---------------|------------------------|-----------------------|--------------------|--------------------|-----------------|------------------|-------------------|------------------|------------------|------------------------| +| 0 | _not a pin_ | | | | | | | | | | | +| 1 | GPIO1 (+) | general purpose | analog input | **UART_A.TX** | | PWM0.0 | | | | | mechanical brake | +| 2 | GPIO2 (+) | general purpose | analog input | **UART_A.RX** | | PWM0.1 | | | | | mechanical brake | +| 3 | GPIO3 | general purpose | **analog input** | | **UART_B.TX** | PWM0.2 | | | | | mechanical brake | +| 4 | GPIO4 | general purpose | **analog input** | | **UART_B.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 | | | | | **CAN_A.RX** | I2C.SCL | | | | +| 16 | _not exposed_ | general purpose | | | | | **CAN_A.TX** | I2C.SDA | | | | (*) ODrive v3.5 and later
@@ -28,7 +28,8 @@ Notes: * Changes to the pin configuration only take effect after `odrv0.save_configuration()` and `odrv0.reboot()` * Bold font marks the default configuration. * If a GPIO is set to an unsupported mode it will be left uninitialized. -* When setting a GPIO to a special purpose mode (e.g. `GPIO_MODE_UART0`) you must also enable the corresponding feature (e.g. `.config.enable_uart`). +* When setting a GPIO to a special purpose mode (e.g. `GPIO_MODE_UART_A`) you must also enable the corresponding feature (e.g. `.config.enable_uart_a`). * 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 UART_A and UART_B is currently not supported. diff --git a/docs/rc-pwm.md b/docs/rc-pwm.md index b18ea494..184c2ce8 100644 --- a/docs/rc-pwm.md +++ b/docs/rc-pwm.md @@ -7,7 +7,7 @@ Any of the numerical parameters that are writable from the ODrive Tool can be ho 2. If you want to control your ODrive with the PWM input without using anything else to activate the ODrive, you can configure the ODrive such that axis 0 automatically goes operational at startup. See [here](commands.md#startup-procedure) for more information. 3. In ODrive Tool, configure the PWM input mapping ``` - odrv0.config.gpio4_mode = GPIO_MODE_PWM0 + odrv0.config.gpio4_mode = GPIO_MODE_PWM odrv0.config.gpio4_pwm_mapping.min = -2 odrv0.config.gpio4_pwm_mapping.max = 2 odrv0.config.gpio4_pwm_mapping.endpoint = odrv0.axis0.controller._remote_attributes['input_pos'] diff --git a/docs/resources.md b/docs/resources.md index 2d6fcb8f..ead55eca 100644 --- a/docs/resources.md +++ b/docs/resources.md @@ -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 | @@ -41,9 +44,11 @@ Most information in this file can be reproduced by running `dump_interrupts(odrv | Name | Prio | Channel | High Level Func | |--------------|------|----------------------------------|-----------------| -| 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_Stream0 | 1 | 0 (SPI3_RX) | SPI_A | +| DMA1_Stream2 | 0 | 4 (UART4_RX) | UART_A | +| DMA1_Stream4 | 0 | 4 (UART4_TX) | UART_A | +| DMA1_Stream5 | 0 | 4 (USART2_RX) | UART_B | +| DMA1_Stream6 | 0 | 4 (USART2_TX) | UART_B | +| DMA1_Stream7 | 1 | 0 (SPI3_TX) | SPI_A | | DMA2_Stream0 | 0 | 0 (ADC1) | freerunning ADC | diff --git a/docs/uart.md b/docs/uart.md index b72069ca..a1e16849 100644 --- a/docs/uart.md +++ b/docs/uart.md @@ -1,6 +1,6 @@ # UART Interface -The ODrive's UART0 interface is enabled by default with a baudrate of 115200 on the pins as shown in [Pinout](pinout). +The ODrive's UART_A interface is enabled by default with a baudrate of 115200 on the pins as shown in [Pinout](pinout). To use UART connect it like this: @@ -10,4 +10,16 @@ To use UART connect it like this: The logic level of the ODrive is 3.3V. The GPIOs are 5V tolerant. -You can use `odrv0.config.uart0_baudrate` to change the baudrate and `odrv0.config.enable_uart0` to disable/reenable UART0. Currently the UART port runs both the [Native Protocol](native-protocol) and the [ASCII Protocol](ascii-protocol) at the same time. +You can use `odrv0.config.uart_a_baudrate` to change the baudrate and `odrv0.config.enable_uart_a` to disable/reenable UART_A. Currently the UART port runs both the [Native Protocol](native-protocol) and the [ASCII Protocol](ascii-protocol) at the same time. + +### How to use UART on GPIO3/4 + +If you need GPIO1/2 for some function other than UART you can disable UART_A and instead use UART_B on GPIO3/4. Here's how you do it: + + odrv0.config.enable_uart_a = False + odrv0.config.gpio1_mode = GPIO_MODE_DIGITAL + odrv0.config.gpio2_mode = GPIO_MODE_DIGITAL + odrv0.config.enable_uart_b = True + odrv0.config.gpio3_mode = GPIO_MODE_UART_B + odrv0.config.gpio4_mode = GPIO_MODE_UART_B + odrv0.reboot() diff --git a/tools/odrive/enums.py b/tools/odrive/enums.py index 0957576a..751c49ed 100644 --- a/tools/odrive/enums.py +++ b/tools/odrive/enums.py @@ -8,13 +8,13 @@ GPIO_MODE_DIGITAL = 0 GPIO_MODE_DIGITAL_PULL_UP = 1 GPIO_MODE_DIGITAL_PULL_DOWN = 2 GPIO_MODE_ANALOG_IN = 3 -GPIO_MODE_UART0 = 4 -GPIO_MODE_UART1 = 5 -GPIO_MODE_UART2 = 6 -GPIO_MODE_CAN0 = 7 -GPIO_MODE_I2C0 = 8 -GPIO_MODE_SPI0 = 9 -GPIO_MODE_PWM0 = 10 +GPIO_MODE_UART_A = 4 +GPIO_MODE_UART_B = 5 +GPIO_MODE_UART_C = 6 +GPIO_MODE_CAN_A = 7 +GPIO_MODE_I2C_A = 8 +GPIO_MODE_SPI_A = 9 +GPIO_MODE_PWM = 10 GPIO_MODE_ENC0 = 11 GPIO_MODE_ENC1 = 12 GPIO_MODE_ENC2 = 13 diff --git a/tools/odrive/tests/can_test.py b/tools/odrive/tests/can_test.py index e9956e9a..2da69490 100644 --- a/tools/odrive/tests/can_test.py +++ b/tools/odrive/tests/can_test.py @@ -109,9 +109,9 @@ class TestSimpleCAN(): def run_test(self, odrive: ODriveComponent, canbus: CanInterfaceComponent, node_id: int, extended_id: bool, logger: Logger): odrive.disable_mappings() - odrive.handle.config.gpio15_mode = GPIO_MODE_CAN0 - odrive.handle.config.gpio16_mode = GPIO_MODE_CAN0 - odrive.handle.config.enable_can0 = True + odrive.handle.config.gpio15_mode = GPIO_MODE_CAN_A + odrive.handle.config.gpio16_mode = GPIO_MODE_CAN_A + odrive.handle.config.enable_can_a = True odrive.save_config_and_reboot() axis = odrive.handle.axis0 diff --git a/tools/odrive/tests/integration_test.py b/tools/odrive/tests/integration_test.py index da9464e9..b59b77d7 100644 --- a/tools/odrive/tests/integration_test.py +++ b/tools/odrive/tests/integration_test.py @@ -145,9 +145,9 @@ class TestSimpleCANClosedLoop(): # make sure no gpio input is overwriting our values odrive.disable_mappings() - odrive.handle.config.gpio15_mode = GPIO_MODE_CAN0 - odrive.handle.config.gpio16_mode = GPIO_MODE_CAN0 - odrive.handle.config.enable_can0 = True + odrive.handle.config.gpio15_mode = GPIO_MODE_CAN_A + odrive.handle.config.gpio16_mode = GPIO_MODE_CAN_A + odrive.handle.config.enable_can_a = True odrive.save_config_and_reboot() with self.prepare(odrive, canbus, axis_ctx, motor_ctx, enc_ctx, node_id, extended_id, logger): diff --git a/tools/odrive/tests/pwm_input_test.py b/tools/odrive/tests/pwm_input_test.py index 82586638..a79d8aac 100644 --- a/tools/odrive/tests/pwm_input_test.py +++ b/tools/odrive/tests/pwm_input_test.py @@ -70,7 +70,7 @@ class TestPwmInput(): odrive.handle.config.gpio4_pwm_mapping ][odrive_gpio_num - 1] - setattr(odrive.handle.config, 'gpio' + str(odrive_gpio_num) + '_mode', GPIO_MODE_PWM0) + setattr(odrive.handle.config, 'gpio' + str(odrive_gpio_num) + '_mode', GPIO_MODE_PWM) pwm_mapping.endpoint = odrive.handle.axis0.controller._remote_attributes['input_pos'] pwm_mapping.min = min_val pwm_mapping.max = max_val diff --git a/tools/odrive/tests/uart_ascii_test.py b/tools/odrive/tests/uart_ascii_test.py index 962f3797..52a1c64e 100644 --- a/tools/odrive/tests/uart_ascii_test.py +++ b/tools/odrive/tests/uart_ascii_test.py @@ -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 UART_B. 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_uart_a = False + odrive.handle.config.uart_a_baudrate = 115200 + odrive.handle.config.enable_uart_b = False + odrive.handle.config.uart_b_baudrate = 115200 + odrive.handle.config.enable_uart_c = False + odrive.handle.config.uart_c_baudrate = 115200 + + if uart_num == 0: + odrive.handle.config.enable_uart_a = True + odrive.handle.config.gpio1_mode = GPIO_MODE_UART_A + odrive.handle.config.gpio2_mode = GPIO_MODE_UART_A + odrive.handle.config.gpio3_mode = GPIO_MODE_ANALOG_IN + odrive.handle.config.gpio4_mode = GPIO_MODE_ANALOG_IN + else: + odrive.handle.config.enable_uart_b = 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_UART_B + odrive.handle.config.gpio4_mode = GPIO_MODE_UART_B + + odrive.save_config_and_reboot() with port.open(115200) as ser: # reset port to known state @@ -163,11 +187,11 @@ class TestUartBaudrate(): yield (odrive, ports) def run_test(self, odrive: ODriveComponent, port: SerialPortComponent, logger: Logger): - 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.enable_uart_a = True + odrive.handle.config.gpio1_mode = GPIO_MODE_UART_A + odrive.handle.config.gpio2_mode = GPIO_MODE_UART_A - odrive.handle.config.uart0_baudrate = 9600 + odrive.handle.config.uart_a_baudrate = 9600 odrive.save_config_and_reboot() # Control test: talk to the ODrive with the wrong baudrate @@ -187,7 +211,7 @@ class TestUartBaudrate(): response = float(ser.readline().strip()) test_assert_eq(response, odrive.handle.vbus_voltage, accuracy=0.1) - odrive.handle.config.uart0_baudrate = 115200 + odrive.handle.config.uart_a_baudrate = 115200 odrive.save_config_and_reboot() @@ -205,9 +229,9 @@ class TestUartBurnIn(): yield (odrive, ports) def run_test(self, odrive: ODriveComponent, port: SerialPortComponent, logger: Logger): - 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.enable_uart_a = True + odrive.handle.config.gpio1_mode = GPIO_MODE_UART_A + odrive.handle.config.gpio2_mode = GPIO_MODE_UART_A with port.open(115200) as ser: with open('/dev/random', 'rb') as rand: @@ -262,9 +286,9 @@ class TestUartNoise(): noise_enable.write(False) time.sleep(0.1) - 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.enable_uart_a = True + odrive.handle.config.gpio1_mode = GPIO_MODE_UART_A + odrive.handle.config.gpio2_mode = GPIO_MODE_UART_A with port.open(115200) as ser: # reset port to known state