Subversion Repositories libSerial

Rev

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