|
- /*
- * Code to TX/RX RS-485 frames.
- *
- */
-
- #include <stdbool.h>
- #include <sysinit.h>
-
- #include <stm32f103xb.h>
- #include <stm32f1xx_hal.h>
- #include <stm32f1xx_hal_cortex.h>
- #include <stm32f1xx_hal_dma.h>
- #include <stm32f1xx_hal_rcc.h>
- #include <stm32f1xx_hal_gpio.h>
- #include <stm32f1xx_hal_uart.h>
-
- #include <rs485frame.h>
-
- const char *rs485err = NULL;
-
- static uint8_t rxbuf[1024];
- static txdone_fn_t txdone;
- static rxdone_fn_t rxdone;
- static txdone_fn_t errcb;
-
- static int doingrx = 0;
- static int doingtx = 0;
-
- static UART_HandleTypeDef rs485uart;
-
- /*
- * Notes:
- HAL_UARTEx_RxEventCallback rx evnts
- * HAL_UART_TxCpltCallback tx_it completed
- * HAL_UART_RxCpltCallback rx_it completed
- * HAL_UART_ErrorCallback for errors
- */
-
- void
- USART3_IRQHandler(void)
- {
-
- HAL_UART_IRQHandler(&rs485uart);
- }
-
- void
- rs485_register(txdone_fn_t txf, rxdone_fn_t rxf, txdone_fn_t errf)
- {
-
- txdone = txf;
- rxdone = rxf;
- errcb = errf;
- }
-
- static void
- settx(bool tx)
- {
- GPIO_PinState s;
-
- if (tx)
- s = GPIO_PIN_SET;
- else
- s = GPIO_PIN_RESET;
-
- HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, s);
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, s);
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, s);
- }
-
- void
- rs485_starttx(uint8_t *pkt, size_t len)
- {
-
- /* XXX - make sure not tx'ing */
- /* XXX - make sure line is idle */
- if (doingrx) {
- HAL_UART_AbortReceive_IT(&rs485uart);
- }
-
- settx(true);
-
- HAL_UART_Transmit_IT(&rs485uart, pkt, len);
- }
-
- void
- HAL_UART_ErrorCallback(UART_HandleTypeDef *phuart)
- {
-
- settx(false);
- doingtx = 0;
- doingrx = 0;
- errcb();
- }
-
- void
- HAL_UART_TxCpltCallback(UART_HandleTypeDef *phuart)
- {
-
- if (phuart != &rs485uart || txdone == NULL)
- return;
-
- settx(false);
- doingtx = 0;
-
- txdone();
- }
-
- void
- HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
- {
- if (huart != &rs485uart || rxdone == NULL)
- return;
-
- doingrx = 0;
-
- rxdone(rxbuf, Size);
- }
-
- /*
- * Called when the buffer has been completed, i.e. it likely
- * overflowed.
- */
- void
- HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
-
- if (huart != &rs485uart || rxdone == NULL)
- return;
-
- doingrx = 0;
- rxdone(NULL, 0);
- }
-
- /* USE_HAL_UART_REGISTER_CALLBACKS defaults to 0, so use this */
- void
- HAL_UART_MspInit(UART_HandleTypeDef *huart)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
-
- /* UM1850 § 38.1.2 Page 550 */
-
- /* 2.a */
- __HAL_RCC_USART3_FORCE_RESET( );
- __HAL_RCC_USART3_RELEASE_RESET( );
- __HAL_RCC_USART3_CLK_ENABLE();
-
- /* 2.b */
- __HAL_RCC_GPIOB_CLK_ENABLE();
- /* TX pin */
- GPIO_InitStruct = (GPIO_InitTypeDef){
- .Pin = GPIO_PIN_10,
- .Mode = GPIO_MODE_AF_PP,
- .Pull = GPIO_NOPULL,
- .Speed = GPIO_SPEED_FREQ_LOW,
- };
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- /* RX pin */
- GPIO_InitStruct = (GPIO_InitTypeDef){
- .Pin = GPIO_PIN_11,
- .Mode = GPIO_MODE_AF_INPUT,
- .Pull = GPIO_NOPULL,
- .Speed = GPIO_SPEED_FREQ_LOW,
- };
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-
- /* 2.c */
- HAL_NVIC_SetPriority(USART3_IRQn, 1, 0);
- HAL_NVIC_EnableIRQ(USART3_IRQn);
-
- /* 2.d */
- /* DMA unused */
- }
-
- const char *
- statustostr(HAL_StatusTypeDef r)
- {
-
- switch (r) {
- case HAL_OK:
- return "ok";
- case HAL_ERROR:
- return "error";
- case HAL_BUSY:
- return "busy";
- default:
- return "unknown";
- }
- }
-
- int
- rs485_startrx()
- {
- HAL_StatusTypeDef r;
-
- if (doingtx) {
- rs485err = "doingtx";
- return 0;
- }
-
- r = HAL_UARTEx_ReceiveToIdle_IT(&rs485uart, rxbuf, sizeof rxbuf);
- if (r == HAL_BUSY) {
- HAL_UART_AbortReceive_IT(&rs485uart);
- r = HAL_UARTEx_ReceiveToIdle_IT(&rs485uart, rxbuf, sizeof rxbuf);
- }
-
- rs485err = statustostr(r);
-
- return r == HAL_OK;
- }
-
- static void
- rs485frame_init(const void *v)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
-
- /* setup DE/RE */
- GPIO_InitStruct = (GPIO_InitTypeDef){
- .Pin = GPIO_PIN_0|GPIO_PIN_1,
- .Mode = GPIO_MODE_OUTPUT_OD,
- .Pull = GPIO_NOPULL,
- .Speed = GPIO_SPEED_FREQ_LOW, /* 2 MHz */
- };
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-
- /* switch to RX */
- settx(false);
-
- /* UM1850 § 38.1.2 Page 550 */
- /* 3 */
- rs485uart = (UART_HandleTypeDef){
- .Init.BaudRate = 230400,
- .Init.WordLength = UART_WORDLENGTH_8B,
- .Init.StopBits = UART_STOPBITS_1,
- .Init.Parity = UART_PARITY_NONE,
- .Init.HwFlowCtl = UART_HWCONTROL_NONE,
- .Init.Mode = UART_MODE_TX_RX,
- .Instance = USART3,
- };
-
- /* 4 */
- HAL_UART_Init(&rs485uart);
- }
- SYSINIT(rs485frame_init, SI_SUB_STANDARD, SI_ORDER_FIRST, rs485frame_init, NULL);
|