Subversion Repositories EngineBay2

Rev

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