Subversion Repositories libSerial

Rev

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