Advertisement
Guest User

serial_lld.c

a guest
Mar 30th, 2017
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.72 KB | None | 0 0
  1. /*
  2.     ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
  3.  
  4.     Licensed under the Apache License, Version 2.0 (the "License");
  5.     you may not use this file except in compliance with the License.
  6.     You may obtain a copy of the License at
  7.  
  8.         http://www.apache.org/licenses/LICENSE-2.0
  9.  
  10.     Unless required by applicable law or agreed to in writing, software
  11.     distributed under the License is distributed on an "AS IS" BASIS,
  12.     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.     See the License for the specific language governing permissions and
  14.     limitations under the License.
  15. */
  16.  
  17. /**
  18.  * @file    AVR/serial_lld.c
  19.  * @brief   AVR low level serial driver code.
  20.  *
  21.  * @addtogroup SERIAL
  22.  * @{
  23.  */
  24.  
  25. #include "hal.h"
  26.  
  27. #if HAL_USE_SERIAL || defined(__DOXYGEN__)
  28.  
  29. /*===========================================================================*/
  30. /* Driver exported variables.                                                */
  31. /*===========================================================================*/
  32.  
  33. /**
  34.  * @brief   USART0 serial driver identifier.
  35.  * @note    The name does not follow the convention used in the other ports
  36.  *          (COMn) because a name conflict with the AVR headers.
  37.  */
  38. #if AVR_SERIAL_USE_USART0 || defined(__DOXYGEN__)
  39. SerialDriver SD1;
  40.  
  41. /* USARTs are not consistently named across the AVR range */
  42. #ifdef USART0_RX_vect
  43. #define AVR_SD1_RX_VECT USART0_RX_vect
  44. #define AVR_SD1_TX_VECT USART0_UDRE_vect
  45. #elif defined(USART_RX_vect)
  46. #define AVR_SD1_RX_VECT USART_RX_vect
  47. #define AVR_SD1_TX_VECT USART_UDRE_vect
  48. #else
  49. #error "Cannot find USART to use for SD1"
  50. #endif
  51. #endif /* AVR_SERIAL_USE_USART0 */
  52.  
  53. /**
  54.  * @brief   USART1 serial driver identifier.
  55.  * @note    The name does not follow the convention used in the other ports
  56.  *          (COMn) because a name conflict with the AVR headers.
  57.  */
  58. #if AVR_SERIAL_USE_USART1 || defined(__DOXYGEN__)
  59. SerialDriver SD2;
  60.  
  61. /* Check if USART1 exists for this MCU */
  62. #ifdef USART1_RX_vect
  63. #define AVR_SD2_RX_VECT USART1_RX_vect
  64. #define AVR_SD2_TX_VECT USART1_UDRE_vect
  65. #else
  66. #error "Cannot find USART to use for SD2"
  67. #endif
  68. #endif /* AVR_SERIAL_USE_USART1 */
  69.  
  70. /**
  71.  * @brief   Software serial driver identifier
  72.  */
  73. #if AVR_SERIAL_USE_USARTS || defined(__DOXYGEN__)
  74. SerialDriver SDS;
  75. #if !defined AVR_GPT_USE_TIM2
  76. #error "Software serial requires AVR_GPT_USE_TIM2"
  77. #endif
  78. /* Uses INT0*/
  79. #if AVR_SDS_USE_INT0
  80. #define AVR_SDS_RX_PORT IOPORT4
  81. #define AVR_SDS_RX_PIN 2
  82. #define AVR_SDS_RX_VECT PCINT0_vect
  83. #define AVR_SDS_RX_TCCR2B_CLK_MASK 0b00000111
  84. #endif
  85. /* By default, uses PB1 as TX.*/
  86. #if !defined(AVR_SDS_TX_PORT)
  87. #define AVR_SDS_TX_PORT IOPORT4
  88. #endif
  89. #if !defined(AVR_SDS_TX_PIN)
  90. #define AVR_SDS_TX_PIN 3
  91. #endif
  92. #endif
  93.  
  94. /*===========================================================================*/
  95. /* Driver local variables and types.                                         */
  96. /*===========================================================================*/
  97.  
  98. /**
  99.  * @brief SDS state machine
  100.  */
  101. typedef enum {
  102.   SDS_RX_IDLE,
  103.   SDS_RX_WAIT,
  104.   SDS_RX_SAMPLE
  105. } sds_rx_state_t;
  106.  
  107. typedef enum {
  108.   SDS_TX_IDLE,
  109.   SDS_TX_TRANSMIT,
  110.   SDS_TX_WAIT
  111. } sds_tx_state_t;
  112.  
  113. /**
  114.  * @brief   Driver default configuration.
  115.  */
  116. static const SerialConfig default_config = {
  117.     UBRR(SERIAL_DEFAULT_BITRATE),
  118.     USART_CHAR_SIZE_8,
  119.     96,
  120.     (1 << CS21)};
  121.  
  122. /**
  123.  * @brief SDS Timer clock control value
  124.  */
  125. static uint8_t sds_rx_tccr2b_div;
  126.  
  127. /**
  128.  * @brief SDS UART bits per character
  129.  */
  130. static uint8_t sds_bits_per_char;
  131.  
  132. static volatile sds_rx_state_t sds_rx_state = SDS_RX_IDLE;
  133.  
  134. /*===========================================================================*/
  135. /* Driver local functions.                                                   */
  136. /*===========================================================================*/
  137.  
  138. static void set_error(uint8_t sra, SerialDriver *sdp) {
  139.   eventflags_t sts = 0;
  140.   uint8_t dor = 0;
  141.   uint8_t upe = 0;
  142.   uint8_t fe = 0;
  143.  
  144. #if AVR_SERIAL_USE_USART0
  145.   if (&SD1 == sdp) {
  146.     dor = (1 << DOR0);
  147.     upe = (1 << UPE0);
  148.     fe = (1 << FE0);
  149.   }
  150. #endif
  151.  
  152. #if AVR_SERIAL_USE_USART1
  153.   if (&SD2 == sdp) {
  154.     dor = (1 << DOR1);
  155.     upe = (1 << UPE1);
  156.     fe = (1 << FE1);
  157.   }
  158. #endif
  159.  
  160.   if (sra & dor)
  161.     sts |= SD_OVERRUN_ERROR;
  162.   if (sra & upe)
  163.     sts |= SD_PARITY_ERROR;
  164.   if (sra & fe)
  165.     sts |= SD_FRAMING_ERROR;
  166.   osalSysLockFromISR();
  167.   chnAddFlagsI(sdp, sts);
  168.   osalSysUnlockFromISR();
  169. }
  170.  
  171. #if AVR_SERIAL_USE_USART0 || defined(__DOXYGEN__)
  172. static void notify1(io_queue_t *qp) {
  173.  
  174.   (void)qp;
  175.   UCSR0B |= (1 << UDRIE0);
  176. }
  177.  
  178. /**
  179.  * @brief   USART0 initialization.
  180.  *
  181.  * @param[in] config    the architecture-dependent serial driver configuration
  182.  */
  183. static void usart0_init(const SerialConfig *config) {
  184.  
  185.   UBRR0L = config->sc_brr;
  186.   UBRR0H = config->sc_brr >> 8;
  187.   UCSR0A = 0;
  188.   UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
  189.   switch (config->sc_bits_per_char) {
  190.   case USART_CHAR_SIZE_5:
  191.     UCSR0C = 0;
  192.     break;
  193.   case USART_CHAR_SIZE_6:
  194.     UCSR0C = (1 << UCSZ00);
  195.     break;
  196.   case USART_CHAR_SIZE_7:
  197.     UCSR0C = (1 << UCSZ01);
  198.     break;
  199.   case USART_CHAR_SIZE_9:
  200.     UCSR0B |= (1 << UCSZ02);
  201.     UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);
  202.     break;
  203.   case USART_CHAR_SIZE_8:
  204.   default:
  205.     UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);
  206.   }
  207. }
  208.  
  209. /**
  210.  * @brief   USART0 de-initialization.
  211.  */
  212. static void usart0_deinit(void) {
  213.  
  214.   UCSR0A = 0;
  215.   UCSR0B = 0;
  216.   UCSR0C = 0;
  217. }
  218. #endif
  219.  
  220. #if AVR_SERIAL_USE_USART1 || defined(__DOXYGEN__)
  221. static void notify2(io_queue_t *qp) {
  222.  
  223.   (void)qp;
  224.   UCSR1B |= (1 << UDRIE1);
  225. }
  226.  
  227. /**
  228.  * @brief   USART1 initialization.
  229.  *
  230.  * @param[in] config    the architecture-dependent serial driver configuration
  231.  */
  232. static void usart1_init(const SerialConfig *config) {
  233.  
  234.   UBRR1L = config->sc_brr;
  235.   UBRR1H = config->sc_brr >> 8;
  236.   UCSR1A = 0;
  237.   UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1);
  238.   switch (config->sc_bits_per_char) {
  239.   case USART_CHAR_SIZE_5:
  240.     UCSR1C = 0;
  241.     break;
  242.   case USART_CHAR_SIZE_6:
  243.     UCSR1C = (1 << UCSZ10);
  244.     break;
  245.   case USART_CHAR_SIZE_7:
  246.     UCSR1C = (1 << UCSZ11);
  247.     break;
  248.   case USART_CHAR_SIZE_9:
  249.     UCSR1B |= (1 << UCSZ12);
  250.     UCSR1C = (1 << UCSZ10) | (1 << UCSZ11);
  251.     break;
  252.   case USART_CHAR_SIZE_8:
  253.   default:
  254.     UCSR1C = (1 << UCSZ10) | (1 << UCSZ11);
  255.   }
  256. }
  257.  
  258. /**
  259.  * @brief   USART1 de-initialization.
  260.  */
  261. static void usart1_deinit(void) {
  262.  
  263.   UCSR1A = 0;
  264.   UCSR1B = 0;
  265.   UCSR1C = 0;
  266. }
  267. #endif
  268.  
  269. #if AVR_SERIAL_USE_USARTS || defined(__DOXYGEN__)
  270.  
  271. // /**
  272. //  * @brief Generates a single half period. Used in receiving
  273. //  */
  274. // void usartS_start_timer_half(void) {
  275. //   /* Resets counter to half length.*/
  276. //   TCNT2 = OCR2A / 2;
  277. //   /* Start timer.*/
  278. //   TCCR2B &= ~AVR_SDS_RX_TCCR2B_CLK_MASK; /* Clear CLK section.*/
  279. //   TCCR2B |= sds_rx_tccr2b_div;           /* Set CLK setting.*/
  280. // }
  281.  
  282. void usartS_start_timer(void) {
  283.   /* Reset counter.*/
  284.   TCNT2 = 0;
  285.   /* Start timer.*/
  286.   TCCR2B &= ~AVR_SDS_RX_TCCR2B_CLK_MASK; /* Clear CLK section.*/
  287.   TCCR2B |= sds_rx_tccr2b_div;           /* Set CLK setting.*/
  288. }
  289.  
  290. void usartS_stop_timer(void) {
  291.   TCCR2B &= ~AVR_SDS_RX_TCCR2B_CLK_MASK;
  292. }
  293.  
  294. void usartS_reset_timer(void) {
  295.   usartS_stop_timer();
  296.   usartS_start_timer();
  297. }
  298.  
  299. /**
  300.  * @brief   USARTS initialization.
  301.  *
  302.  * @param[in] config    the architecture-dependent serial driver configuration
  303.  */
  304. static void usartS_init(const SerialConfig *config) {
  305.   /* Sets appropriate I/O mode.*/
  306.   palSetPadMode(AVR_SDS_RX_PORT, AVR_SDS_RX_PIN, PAL_MODE_INPUT);
  307.   palSetPadMode(AVR_SDS_TX_PORT, AVR_SDS_TX_PIN, PAL_MODE_OUTPUT_PUSHPULL);
  308. #if defined AVR_SDS_USE_INT0
  309.   /* Falling edge of INT0 triggers interrupt.*/
  310.   EICRA |= (1 << ISC01);
  311.   EICRA &= ~(1 << ISC00);
  312.   EIMSK |= 1 << 0;
  313.  
  314. #endif
  315.   /* Timer 2 CTC mode.*/
  316.   TCCR2A |= 1 << WGM21;
  317.   TCCR2A &= ~((1 << WGM22) | (1 << WGM20));
  318.   /* Save the timer clock input.*/
  319.   sds_rx_tccr2b_div = config->sc_tccr2b_div;
  320.   /* Default to be 8 bit.*/
  321.   switch (config->sc_bits_per_char) {
  322.   default:
  323.     sds_bits_per_char = 8;
  324.   }
  325.  
  326.   /* Timer 2 Top.*/
  327.   OCR2A = config->sc_ocr2a;
  328.   /* Timer 2 output compare A interrupt.*/
  329.   TIMSK2 |= 1 << OCIE2A;
  330.   usartS_start_timer();
  331. }
  332.  
  333. /**
  334. * @brief   USART0 de-initialization.
  335. */
  336. static void usartS_deinit(void) {
  337.   usartS_stop_timer();
  338.   TIMSK2 &= ~(1 << OCIE2A);
  339.   EIMSK &= ~(1 << 0);
  340. }
  341.  
  342. #endif
  343.  
  344. /*===========================================================================*/
  345. /* Driver interrupt handlers.                                                */
  346. /*===========================================================================*/
  347.  
  348. #if AVR_SERIAL_USE_USART0 || defined(__DOXYGEN__)
  349. /**
  350.  * @brief   USART0 RX interrupt handler.
  351.  *
  352.  * @isr
  353.  */
  354. OSAL_IRQ_HANDLER(AVR_SD1_RX_VECT) {
  355.   uint8_t sra;
  356.  
  357.   OSAL_IRQ_PROLOGUE();
  358.  
  359.   sra = UCSR0A;
  360.   if (sra & ((1 << DOR0) | (1 << UPE0) | (1 << FE0)))
  361.     set_error(sra, &SD1);
  362.   osalSysLockFromISR();
  363.   sdIncomingDataI(&SD1, UDR0);
  364.   osalSysUnlockFromISR();
  365.  
  366.   OSAL_IRQ_EPILOGUE();
  367. }
  368.  
  369. /**
  370.  * @brief   USART0 TX interrupt handler.
  371.  *
  372.  * @isr
  373.  */
  374. OSAL_IRQ_HANDLER(AVR_SD1_TX_VECT) {
  375.   msg_t b;
  376.  
  377.   OSAL_IRQ_PROLOGUE();
  378.   osalSysLockFromISR();
  379.   b = sdRequestDataI(&SD1);
  380.   osalSysUnlockFromISR();
  381.   if (b < Q_OK)
  382.     UCSR0B &= ~(1 << UDRIE0);
  383.   else
  384.     UDR0 = b;
  385.  
  386.   OSAL_IRQ_EPILOGUE();
  387. }
  388. #endif /* AVR_SERIAL_USE_USART0 */
  389.  
  390. #if AVR_SERIAL_USE_USART1 || defined(__DOXYGEN__)
  391. /**
  392.  * @brief   USART1 RX interrupt handler.
  393.  *
  394.  * @isr
  395.  */
  396. OSAL_IRQ_HANDLER(AVR_SD2_RX_VECT) {
  397.   uint8_t sra;
  398.  
  399.   OSAL_IRQ_PROLOGUE();
  400.  
  401.   sra = UCSR1A;
  402.   if (sra & ((1 << DOR1) | (1 << UPE1) | (1 << FE1)))
  403.     set_error(sra, &SD2);
  404.   osalSysLockFromISR();
  405.   sdIncomingDataI(&SD2, UDR1);
  406.   osalSysUnlockFromISR();
  407.  
  408.   OSAL_IRQ_EPILOGUE();
  409. }
  410.  
  411. /**
  412.  * @brief   USART1 TX interrupt handler.
  413.  *
  414.  * @isr
  415.  */
  416. OSAL_IRQ_HANDLER(AVR_SD2_TX_VECT) {
  417.   msg_t b;
  418.  
  419.   OSAL_IRQ_PROLOGUE();
  420.  
  421.   osalSysLockFromISR();
  422.   b = sdRequestDataI(&SD2);
  423.   osalSysUnlockFromISR();
  424.   if (b < Q_OK)
  425.     UCSR1B &= ~(1 << UDRIE1);
  426.   else
  427.     UDR1 = b;
  428.  
  429.   OSAL_IRQ_EPILOGUE();
  430. }
  431. #endif /* AVR_SERIAL_USE_USART1 */
  432.  
  433. #if AVR_SERIAL_USE_USARTS || defined(__DOXYGEN__)
  434.  
  435. /**
  436.  * @brief PCINT interrupt handler
  437.  *
  438.  * @details This handler changes state by sensing the START bit. Otherwise do nothing
  439.  *
  440.  * @isr
  441.  */
  442. OSAL_IRQ_HANDLER(AVR_SDS_RX_VECT) {
  443.   OSAL_IRQ_PROLOGUE();
  444.   chSysDisable();
  445.   switch (sds_rx_state) {
  446.   case SDS_RX_IDLE:
  447.     sds_rx_state = SDS_RX_WAIT;
  448.     break;
  449.   default:
  450.     break;
  451.   }
  452.   chSysEnable();
  453.   OSAL_IRQ_EPILOGUE();
  454. }
  455.  
  456. /**
  457.  * @brief TIMER2 Comparator A interrupt
  458.  *
  459.  * @details VERY IMPORTANT: Timer is triggered twice per data bit, so 4800 BAUD
  460.  * serial requires 9600Hz clock.
  461.  *
  462.  * @isr
  463.  */
  464. OSAL_IRQ_HANDLER(TIMER2_COMPA_vect) {
  465.   /* Data byte.*/
  466.  
  467.   OSAL_IRQ_PROLOGUE();
  468.   {
  469.     static int8_t rx_i;
  470.     static int8_t rx_byte;
  471.     /* RX state machine.*/
  472.     switch (sds_rx_state) {
  473.     case SDS_RX_IDLE:
  474.       rx_i = 0;
  475.       rx_byte = 0;
  476.       /* Do Nothing.*/
  477.       break;
  478.     case SDS_RX_WAIT: /* Waits a clock before sampling*/
  479.       // byte = 0;
  480.       sds_rx_state = SDS_RX_SAMPLE;
  481.       break;
  482.     case SDS_RX_SAMPLE:
  483.       if (rx_i < sds_bits_per_char) {
  484.         rx_byte |= palReadPad(AVR_SDS_RX_PORT, AVR_SDS_RX_PIN) << rx_i;
  485.       } else {
  486.         /* If last bit is STOP, then assume info is correct. Otherwise, treat as garbage*/
  487.         if (palReadPad(AVR_SDS_RX_PORT, AVR_SDS_RX_PIN)) {
  488.           osalSysLockFromISR();
  489.           sdIncomingDataI(&SDS, rx_byte);
  490.           osalSysUnlockFromISR();
  491.         }
  492.         rx_byte = 0;
  493.       }
  494.       if (rx_i < sds_bits_per_char) {
  495.         sds_rx_state = SDS_RX_SAMPLE;
  496.       } else {
  497.         sds_rx_state = SDS_RX_IDLE;
  498.       }
  499.       ++rx_i;
  500.       break;
  501.     }
  502.   }
  503.   /* TX state machine.*/
  504.   {
  505.     static sds_tx_state_t tx_state = SDS_TX_IDLE;
  506.     static int8_t tx_byte;
  507.     static int8_t tx_i;
  508.     switch (tx_state) {
  509.     case SDS_TX_IDLE:
  510.       tx_i = -1;
  511.       osalSysLockFromISR();
  512.       tx_byte = sdRequestDataI(&SDS);
  513.       osalSysUnlockFromISR();
  514.       if (tx_byte >= Q_OK) {
  515.         tx_state = SDS_TX_TRANSMIT;
  516.       }
  517.       break;
  518.     case SDS_TX_TRANSMIT: {
  519.       uint8_t bit;
  520.       /* START.*/
  521.       if (tx_i == -1) {
  522.         bit = 0;
  523.       }
  524.       /* STOP.*/
  525.       else if (tx_i == sds_bits_per_char) {
  526.         bit = 1;
  527.       }
  528.       /* Data.*/
  529.       else {
  530.         bit = (tx_byte & (1 << tx_i)) != 0;
  531.       }
  532.       palWritePad(AVR_SDS_TX_PORT, AVR_SDS_TX_PIN, bit);
  533.       tx_state = SDS_TX_WAIT;
  534.       break;
  535.     }
  536.     case SDS_TX_WAIT:
  537.       if (tx_i == sds_bits_per_char) {
  538.         tx_state = SDS_TX_IDLE;
  539.       } else {
  540.         tx_state = SDS_TX_TRANSMIT;
  541.       }
  542.       ++tx_i;
  543.       break;
  544.     }
  545.   }
  546.   OSAL_IRQ_EPILOGUE();
  547. }
  548.  
  549. #endif
  550.  
  551. /*===========================================================================*/
  552. /* Driver exported functions.                                                */
  553. /*===========================================================================*/
  554.  
  555. /**
  556.  * @brief   Low level serial driver initialization.
  557.  *
  558.  * @notapi
  559.  */
  560. void sd_lld_init(void) {
  561.  
  562. #if AVR_SERIAL_USE_USART0
  563.   sdObjectInit(&SD1, NULL, notify1);
  564. #endif
  565. #if AVR_SERIAL_USE_USART1
  566.   sdObjectInit(&SD2, NULL, notify2);
  567. #endif
  568. #if AVR_SERIAL_USE_USARTS
  569.   sdObjectInit(&SDS, NULL, NULL);
  570. #endif
  571. }
  572.  
  573. /**
  574.  * @brief   Low level serial driver configuration and (re)start.
  575.  *
  576.  * @param[in] sdp       pointer to a @p SerialDriver object
  577.  * @param[in] config    the architecture-dependent serial driver configuration.
  578.  *                      If this parameter is set to @p NULL then a default
  579.  *                      configuration is used.
  580.  *
  581.  * @notapi
  582.  */
  583. void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
  584.  
  585.   if (config == NULL)
  586.     config = &default_config;
  587.  
  588. #if AVR_SERIAL_USE_USART0
  589.   if (&SD1 == sdp) {
  590.     usart0_init(config);
  591.     return;
  592.   }
  593. #endif
  594. #if AVR_SERIAL_USE_USART1
  595.   if (&SD2 == sdp) {
  596.     usart1_init(config);
  597.     return;
  598.   }
  599. #endif
  600. #if AVR_SERIAL_USE_USARTS
  601.   if (&SDS == sdp) {
  602.     usartS_init(config);
  603.     return;
  604.   }
  605. #endif
  606. }
  607.  
  608. /**
  609.  * @brief   Low level serial driver stop.
  610.  * @details De-initializes the USART, stops the associated clock, resets the
  611.  *          interrupt vector.
  612.  *
  613.  * @param[in] sdp       pointer to a @p SerialDriver object
  614.  *
  615.  * @notapi
  616.  */
  617. void sd_lld_stop(SerialDriver *sdp) {
  618.  
  619. #if AVR_SERIAL_USE_USART0
  620.   if (&SD1 == sdp)
  621.     usart0_deinit();
  622. #endif
  623. #if AVR_SERIAL_USE_USART1
  624.   if (&SD2 == sdp)
  625.     usart1_deinit();
  626. #endif
  627. #if AVR_SERIAL_USE_USARTS
  628.   if (&SDS == sdp) {
  629.     usartS_deinit();
  630.   }
  631. #endif
  632. }
  633.  
  634. #endif /* HAL_USE_SERIAL */
  635.  
  636. /** @} */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement