Implement a secure ICS protocol targeting LoRa Node151 microcontroller for controlling irrigation.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

264 lines
4.6 KiB

  1. /*
  2. * Code to TX/RX RS-485 frames.
  3. *
  4. */
  5. #include <stdbool.h>
  6. #include <sysinit.h>
  7. #include <stm32f103xb.h>
  8. #include <stm32f1xx_hal.h>
  9. #include <stm32f1xx_hal_cortex.h>
  10. #include <stm32f1xx_hal_dma.h>
  11. #include <stm32f1xx_hal_rcc.h>
  12. #include <stm32f1xx_hal_gpio.h>
  13. #include <stm32f1xx_hal_uart.h>
  14. #include <rs485frame.h>
  15. const char *rs485err = NULL;
  16. static uint8_t rxbuf[128];
  17. static txdone_fn_t txdone;
  18. static rxdone_fn_t rxdone;
  19. static txdone_fn_t errcb;
  20. static int doingrx = 0;
  21. static int doingtx = 0;
  22. static UART_HandleTypeDef rs485uart;
  23. /*
  24. * Notes:
  25. HAL_UARTEx_RxEventCallback rx evnts
  26. * HAL_UART_TxCpltCallback tx_it completed
  27. * HAL_UART_RxCpltCallback rx_it completed
  28. * HAL_UART_ErrorCallback for errors
  29. */
  30. void
  31. USART3_IRQHandler(void)
  32. {
  33. HAL_UART_IRQHandler(&rs485uart);
  34. }
  35. void
  36. rs485_register(txdone_fn_t txf, rxdone_fn_t rxf, txdone_fn_t errf)
  37. {
  38. txdone = txf;
  39. rxdone = rxf;
  40. errcb = errf;
  41. }
  42. static void
  43. settx(bool tx)
  44. {
  45. GPIO_PinState s;
  46. if (tx)
  47. s = GPIO_PIN_SET;
  48. else
  49. s = GPIO_PIN_RESET;
  50. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, s); /* XXX - led */
  51. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, s);
  52. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, s);
  53. }
  54. void
  55. rs485_starttx(uint8_t *pkt, size_t len)
  56. {
  57. /* XXX - make sure not actively rx'ing */
  58. /* XXX - make sure line is idle */
  59. if (rs485uart.RxState == HAL_UART_STATE_BUSY_RX) {
  60. while (rs485uart.RxXferCount != sizeof rxbuf) {
  61. }
  62. }
  63. #if 0
  64. /* XXX - as it's full duplex, this shouldn't be needed */
  65. /* This appears to corrupt state and break things */
  66. if (doingrx) {
  67. HAL_UART_AbortReceive_IT(&rs485uart);
  68. }
  69. #endif
  70. settx(true);
  71. HAL_UART_Transmit_IT(&rs485uart, pkt, len);
  72. }
  73. void
  74. HAL_UART_ErrorCallback(UART_HandleTypeDef *phuart)
  75. {
  76. settx(false);
  77. doingtx = 0;
  78. doingrx = 0;
  79. errcb();
  80. }
  81. void
  82. HAL_UART_TxCpltCallback(UART_HandleTypeDef *phuart)
  83. {
  84. if (phuart != &rs485uart || txdone == NULL)
  85. return;
  86. for (int x = 0; x < 1000000; x++);
  87. settx(false);
  88. doingtx = 0;
  89. txdone();
  90. }
  91. void
  92. HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
  93. {
  94. if (huart != &rs485uart || rxdone == NULL)
  95. return;
  96. doingrx = 0;
  97. rxdone(rxbuf, Size);
  98. }
  99. /*
  100. * Called when the buffer has been completed, i.e. it likely
  101. * overflowed.
  102. */
  103. void
  104. HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  105. {
  106. if (huart != &rs485uart || rxdone == NULL)
  107. return;
  108. doingrx = 0;
  109. rxdone(NULL, 0);
  110. }
  111. /* USE_HAL_UART_REGISTER_CALLBACKS defaults to 0, so use this */
  112. void
  113. HAL_UART_MspInit(UART_HandleTypeDef *huart)
  114. {
  115. GPIO_InitTypeDef GPIO_InitStruct;
  116. /* UM1850 § 38.1.2 Page 550 */
  117. /* 2.a */
  118. __HAL_RCC_USART3_FORCE_RESET();
  119. __HAL_RCC_USART3_RELEASE_RESET();
  120. __HAL_RCC_USART3_CLK_ENABLE();
  121. /* 2.b */
  122. __HAL_RCC_GPIOB_CLK_ENABLE();
  123. /* TX pin */
  124. GPIO_InitStruct = (GPIO_InitTypeDef){
  125. .Pin = GPIO_PIN_10,
  126. .Mode = GPIO_MODE_AF_PP,
  127. .Pull = GPIO_NOPULL,
  128. .Speed = GPIO_SPEED_FREQ_LOW,
  129. };
  130. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  131. /* RX pin */
  132. GPIO_InitStruct = (GPIO_InitTypeDef){
  133. .Pin = GPIO_PIN_11,
  134. .Mode = GPIO_MODE_AF_INPUT,
  135. .Pull = GPIO_NOPULL,
  136. .Speed = GPIO_SPEED_FREQ_LOW,
  137. };
  138. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  139. /* 2.c */
  140. HAL_NVIC_SetPriority(USART3_IRQn, 1, 0);
  141. HAL_NVIC_EnableIRQ(USART3_IRQn);
  142. /* 2.d */
  143. /* DMA unused */
  144. }
  145. const char *
  146. statustostr(HAL_StatusTypeDef r)
  147. {
  148. switch (r) {
  149. case HAL_OK:
  150. return "ok";
  151. case HAL_ERROR:
  152. return "error";
  153. case HAL_BUSY:
  154. return "busy";
  155. default:
  156. return "unknown";
  157. }
  158. }
  159. int
  160. rs485_startrx()
  161. {
  162. HAL_StatusTypeDef r;
  163. if (doingtx) {
  164. rs485err = "doingtx";
  165. return 0;
  166. }
  167. doingrx = 1;
  168. r = HAL_UARTEx_ReceiveToIdle_IT(&rs485uart, rxbuf, sizeof rxbuf);
  169. if (r == HAL_BUSY) {
  170. rs485err = "already";
  171. return 1;
  172. #if 0
  173. /* This appears to corrupt state and break things */
  174. HAL_UART_AbortReceive_IT(&rs485uart);
  175. r = HAL_UARTEx_ReceiveToIdle_IT(&rs485uart, rxbuf, sizeof rxbuf);
  176. #endif
  177. }
  178. rs485err = statustostr(r);
  179. return r == HAL_OK;
  180. }
  181. static void
  182. rs485frame_init(void)
  183. {
  184. GPIO_InitTypeDef GPIO_InitStruct;
  185. __HAL_RCC_GPIOB_CLK_ENABLE();
  186. /* setup DE/RE */
  187. GPIO_InitStruct = (GPIO_InitTypeDef){
  188. .Pin = GPIO_PIN_0|GPIO_PIN_1,
  189. .Mode = GPIO_MODE_OUTPUT_PP,
  190. .Pull = GPIO_NOPULL,
  191. .Speed = GPIO_SPEED_FREQ_LOW, /* 2 MHz */
  192. };
  193. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  194. /* switch to RX */
  195. settx(false);
  196. /* UM1850 § 38.1.2 Page 550 */
  197. /* 3 */
  198. rs485uart = (UART_HandleTypeDef){
  199. .Init.BaudRate = 230400,
  200. .Init.WordLength = UART_WORDLENGTH_8B,
  201. .Init.StopBits = UART_STOPBITS_1,
  202. .Init.Parity = UART_PARITY_NONE,
  203. .Init.HwFlowCtl = UART_HWCONTROL_NONE,
  204. .Init.Mode = UART_MODE_TX_RX,
  205. .Instance = USART3,
  206. };
  207. /* 4 */
  208. HAL_UART_Init(&rs485uart);
  209. }
  210. SYSINIT_VF(rs485frame_init, SI_SUB_STANDARD, SI_ORDER_FIRST, rs485frame_init);