Subversion Repositories libSerial

Rev

Rev 7 | Rev 9 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * serial.c
  3.  *
  4.  *  Created on: 4 Jan 2016
  5.  *      Author: Mike
  6.  *
  7.  *      This (ab)uses the STMCubeMX HAL declarations to implement a generic STM32F1xx
  8.  *      USART driver layer
  9.  */
  10.  
  11. #include "libSerial/serial.h"
  12.  
  13. /* workspaces for the USARTS being used */
  14. #if defined SERIAL_UART1
  15. usart_ctl uc1;
  16. #endif
  17. #if defined SERIAL_UART2
  18. usart_ctl uc2;
  19. #endif
  20. #if defined SERIAL_UART3
  21. usart_ctl uc3;
  22. #endif
  23. #if defined SERIAL_UART4
  24. usart_ctl uc4;
  25. #endif
  26. #if defined SERIAL_UART5
  27. usart_ctl uc5;
  28. #endif
  29.  
  30. /* returns the number of characters received by the Rx USART */
  31. uint16_t
  32. SerialCharsReceived(usart_ctl *instance)
  33. {
  34.   uint16_t result = 0; // assume no characters received yet
  35.   __HAL_UART_DISABLE_IT(instance->Handle, UART_IT_RXNE);
  36.  
  37.   if (instance->rx_usart_buffer_full)
  38.   { // buffer is full...
  39.     result = RX_USART_BUFF_SIZ;
  40.   }
  41.   else if (instance->rx_usart_in_Ptr >= instance->rx_usart_out_Ptr)
  42.   { // buffer has not wrapped...
  43.     result = instance->rx_usart_in_Ptr - instance->rx_usart_out_Ptr;
  44.   }
  45.   else
  46.   { // buffer has possibly wrapped...
  47.     result = RX_USART_BUFF_SIZ - instance->rx_usart_out_Ptr + instance->rx_usart_in_Ptr;
  48.   }
  49.   __HAL_UART_ENABLE_IT(instance->Handle, UART_IT_RXNE);
  50.  
  51.   return result;
  52. }
  53.  
  54. uint16_t SerialTransmitSpace(usart_ctl *instance)
  55. {
  56.   return TX_USART_BUFF_SIZ - instance->tx_usart_count;
  57. }
  58.  
  59. inline uint8_t
  60. PollSerial(usart_ctl *instance)
  61. {
  62.   uint8_t rc;
  63.  
  64.   __HAL_UART_DISABLE_IT(instance->Handle, UART_IT_RXNE);
  65.   rc = (instance->rx_usart_buffer_full || (instance->rx_usart_in_Ptr != instance->rx_usart_out_Ptr));
  66.   __HAL_UART_ENABLE_IT(instance->Handle, UART_IT_RXNE);
  67.  
  68.   return rc;
  69. }
  70.  
  71. /***!
  72.  * @brief return the next character in the Serial input buffer
  73.  * This function will wait until a character arrives.
  74.  */
  75. inline uint8_t
  76. GetCharSerial(usart_ctl *instance)
  77. {
  78.   uint8_t c;
  79.   __HAL_UART_DISABLE_IT(instance->Handle, UART_IT_RXNE);
  80.   while (!instance->rx_usart_buffer_full && (instance->rx_usart_in_Ptr == instance->rx_usart_out_Ptr))
  81.   {
  82.     __HAL_UART_ENABLE_IT(instance->Handle, UART_IT_RXNE);
  83.     __WFI(); /* wait for something */
  84.     __HAL_UART_DISABLE_IT(instance->Handle, UART_IT_RXNE);
  85.   }
  86.  
  87.   c = instance->rx_usart_buff[instance->rx_usart_out_Ptr];
  88.   instance->rx_usart_buffer_full = 0; /* removed character */
  89.   instance->rx_usart_out_Ptr++;
  90.   if (instance->rx_usart_out_Ptr >= RX_USART_BUFF_SIZ)
  91.   {
  92.     instance->rx_usart_out_Ptr = 0;
  93.   }
  94.   __HAL_UART_ENABLE_IT(instance->Handle, UART_IT_RXNE);
  95.   return c;
  96. }
  97.  
  98. /*
  99.  * \brief
  100.  * void EnableSerialRxInterrupt(void) - this function is used from the interrupt handler and the main scheduler loop
  101.  * to enable the serial rx interrupt after resetting the serial rx buffer...
  102.  */
  103. inline void
  104. EnableSerialRxInterrupt(usart_ctl *instance)
  105. {
  106.   /* cheat here - this is a macro and I have the same Instance member as the HAL handle, with the same meaning */
  107.   __HAL_UART_ENABLE_IT(instance->Handle, UART_IT_RXNE);
  108. }
  109.  
  110. /****!
  111.  * @brief send a character to the serial USART via placing it in the serial buffer
  112.  *
  113.  */
  114.  
  115. static void
  116. PutCharSerialFIFO(usart_ctl *instance, uint8_t c)
  117. {
  118.   __HAL_UART_DISABLE_IT(instance->Handle, UART_IT_TXE);
  119.  
  120.   instance->tx_usart_buff[instance->tx_usart_in_Ptr++] = c;
  121.   instance->tx_usart_count += 1;
  122.   if (instance->tx_usart_in_Ptr >= TX_USART_BUFF_SIZ)
  123.   {
  124.     instance->tx_usart_in_Ptr = 0;
  125.   }
  126.   /* Handle overrun by losing oldest characters */
  127.   if (instance->tx_usart_in_Ptr == instance->tx_usart_out_Ptr)
  128.   {
  129.     instance->tx_usart_out_Ptr++;
  130.     if (instance->tx_usart_out_Ptr >= TX_USART_BUFF_SIZ)
  131.     {
  132.       instance->tx_usart_out_Ptr = 0;
  133.     }
  134.   }
  135.  
  136.   instance->tx_usart_running = 1;
  137.   __HAL_UART_ENABLE_IT(instance->Handle, UART_IT_TXE);
  138. }
  139.  
  140. void UART_IRQHandler(usart_ctl *instance)
  141. {
  142.  
  143.   __disable_irq();
  144.   uint32_t rxStatus; // status from USART receiver
  145.  
  146.   rxStatus = instance->Handle->Instance->SR; // read the status bits - this resets all the hardware signalling flags
  147.  
  148.   if ((rxStatus & USART_SR_LBD))
  149.     __HAL_UART_CLEAR_FLAG(instance->Handle, USART_SR_LBD);
  150.  
  151.   if ((rxStatus & USART_SR_RXNE) != RESET)
  152.   {
  153.     // no error has occurred...
  154.     uint8_t rxChar = (uint8_t)(instance->Handle->Instance->DR & 0xff); // read the bottom 8-bits only
  155.  
  156.     if (!instance->rx_usart_buffer_full)
  157.     {
  158.       instance->rx_usart_buff[instance->rx_usart_in_Ptr++] = rxChar;
  159.  
  160.       if (instance->rx_usart_in_Ptr >= RX_USART_BUFF_SIZ)
  161.       {
  162.         instance->rx_usart_in_Ptr = 0;
  163.       }
  164.       if (instance->rx_usart_in_Ptr == instance->rx_usart_out_Ptr)
  165.       {
  166.         instance->rx_usart_buffer_full = 1; /* buffer overrun */
  167.       }
  168.     }
  169.   }
  170.   /* check for transmitter interrupt : this code is used */
  171.   if ((rxStatus & USART_SR_TXE) != RESET)
  172.   {
  173.  
  174.     /* Only enable the transmitter when baud detect has completed or check expired.
  175.      * and the software is ready for it to be enabled as programming mode is wanting
  176.      * to receive a response and that can get blocked if we're streaming a lot of debug messages*/
  177.     if (instance->tx_usart_in_Ptr != instance->tx_usart_out_Ptr)
  178.     {
  179.  
  180.       instance->Handle->Instance->DR =
  181.           instance->tx_usart_buff[instance->tx_usart_out_Ptr++];
  182.       if (instance->tx_usart_count != 0)
  183.         instance->tx_usart_count -= 1;
  184.  
  185.       if (instance->tx_usart_out_Ptr >= TX_USART_BUFF_SIZ)
  186.       {
  187.         instance->tx_usart_out_Ptr = 0;
  188.       }
  189.     }
  190.     if (instance->tx_usart_count == 0)
  191.     {
  192.       __HAL_UART_DISABLE_IT(instance->Handle, UART_IT_TXE);
  193.       instance->tx_usart_running = 0;
  194.     }
  195.   }
  196.   __enable_irq();
  197. }
  198.  
  199. void PutCharSerial(usart_ctl *instance, uint8_t c)
  200. {
  201.   // Put character in Crayon/Pen interface
  202.   PutCharSerialFIFO(instance, c);
  203. }
  204.  
  205. /*
  206.  * \brief
  207.  * ResetTxBuffer(void) - resets the serial transmitter buffer
  208.  */
  209. void ResetTxBuffer(usart_ctl *instance)
  210. {
  211.  
  212.   instance->tx_usart_out_Ptr = 0;
  213.   instance->tx_usart_running = 0;
  214.   instance->tx_usart_in_Ptr = 0; /* setup in pointer last to drop any chars come in */
  215.   instance->tx_usart_count = 0;
  216. }
  217.  
  218. /*
  219.  * \brief
  220.  * void ResetRxBuffer(void) - resets the serial receiver buffer
  221.  */
  222. void ResetRxBuffer(usart_ctl *instance)
  223. {
  224.  
  225.   instance->rx_usart_out_Ptr = 0;
  226.   instance->rx_usart_buffer_full = 0;
  227.   instance->rx_usart_in_Ptr = 0; /* setup in pointer last to drop any chars come in */
  228. }
  229.  
  230. /***!
  231.  * @brief Flush Serial input and output buffers
  232.  */
  233. void FlushSerial(usart_ctl *instance)
  234. {
  235.   ResetRxBuffer(instance);
  236.   ResetTxBuffer(instance);
  237. }
  238.  
  239. /***!
  240.  * @brief check if tx buffer is empty...
  241.  */
  242. uint8_t
  243. TxBufferEmpty(usart_ctl *instance)
  244. {
  245.   return (0 == instance->tx_usart_count);
  246. }
  247.  
  248. /***!
  249.  * @brief wait for transmission to finish
  250.  */
  251.  
  252. void TxWaitEmpty(usart_ctl *instance)
  253. {
  254.   while (instance->tx_usart_count ||
  255.          (instance->Handle->Instance->SR & USART_SR_TC) != RESET)
  256.   {
  257.   };
  258. }
  259.  
  260. /****
  261.  * @brief Initialise control structure
  262.  */
  263. void init_usart_ctl(usart_ctl *instance, UART_HandleTypeDef *handle)
  264. {
  265.  
  266.   instance->Handle = handle;
  267.  
  268.   /* cheat here - this is a macro and I have the same Instance member as the HAL handle, with the same meaning */
  269.   __HAL_UART_DISABLE_IT(instance->Handle, UART_IT_TXE);
  270.   __HAL_UART_DISABLE_IT(instance->Handle, UART_IT_RXNE);
  271.  
  272.   instance->tx_usart_in_Ptr = 0;
  273.   instance->tx_usart_out_Ptr = 0;
  274.   instance->tx_usart_running = 0;
  275.   instance->tx_usart_count = 0;
  276.  
  277.   instance->rx_usart_in_Ptr = 0;
  278.   instance->rx_usart_out_Ptr = 0;
  279.   instance->rx_usart_buffer_full = 0;
  280. }
  281.  
  282. void setBaud(usart_ctl *ctl, uint32_t baud)
  283. {
  284.   ctl->Handle->Init.BaudRate = baud;
  285.   __disable_irq();
  286.   HAL_UART_Init(ctl->Handle);
  287.   __enable_irq();
  288. }
  289.  
  290.  
  291.  
  292. void sendString(usart_ctl *ctl, char const * string , int length)
  293. {
  294.   for (int i = 0; i < length; i++)
  295.     PutCharSerial(ctl, string[i]);
  296. }
  297.  
  298. /////////////////////////////////////////////////////////
  299. /// Moved from generated code  to avoid crappy HAL handler
  300. #if defined SERIAL_UART1
  301. void USART1_IRQHandler(void)
  302. {
  303.   UART_IRQHandler(&uc1);
  304. }
  305. #endif
  306. #if defined SERIAL_UART2
  307. void USART2_IRQHandler(void)
  308. {
  309.   UART_IRQHandler(&uc2);
  310. }
  311. #endif
  312. #if defined SERIAL_UART3
  313. void USART3_IRQHandler(void)
  314. {
  315.   UART_IRQHandler(&uc3);
  316. }
  317. #endif
  318. #if defined SERIAL_UART4
  319. void UART4_IRQHandler(void)
  320. {
  321.   UART_IRQHandler(&uc4);
  322. }
  323. #endif
  324. #if defined SERIAL_UART5
  325. void UART5_IRQHandler(void)
  326. {
  327.   UART_IRQHandler(&uc5);
  328. }
  329. #endif
  330.