Advertisement
Guest User

serial_lld.c

a guest
Mar 23rd, 2017
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.56 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. IDLE,
  103. RECEIVE_INIT,
  104. RECEIVE,
  105. TRANSMIT_INIT,
  106. TRANSMIT
  107. } sds_state_t;
  108.  
  109. /**
  110. * @brief Driver default configuration.
  111. */
  112. static const SerialConfig default_config = {
  113. UBRR(SERIAL_DEFAULT_BITRATE),
  114. USART_CHAR_SIZE_8,
  115. 96,
  116. (1 << CS21)
  117. };
  118.  
  119. /**
  120. * @brief SDS Timer clock control value
  121. */
  122. static uint8_t sds_rx_tccr2b_div;
  123.  
  124. /**
  125. * @brief SDS UART bits per character
  126. */
  127. static uint8_t sds_bits_per_char;
  128.  
  129. /**
  130. * @brief SDS state
  131. */
  132. static volatile sds_state_t sds_state = 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. /* Timer 2 CTC mode.*/
  313. TCCR2A |= 1 << WGM21;
  314. TCCR2A &= ~((1 << WGM22) | (1 << WGM20));
  315. /* Save the timer clock input.*/
  316. sds_rx_tccr2b_div = config->sc_tccr2b_div;
  317. /* Default to be 8 bit.*/
  318. switch (config->sc_bits_per_char) {
  319. default:
  320. sds_bits_per_char = 8;
  321. }
  322. /* Timer 2 Top.*/
  323. OCR2A = config->sc_ocr2a;
  324. /* Timer 2 output compare A interrupt.*/
  325. TIMSK2 |= 1 << OCIE2A;
  326. usartS_start_timer();
  327. #endif
  328. }
  329.  
  330. void usartS_enable_rx(void) {
  331. EIMSK |= 1<<0;
  332. }
  333.  
  334. void usartS_disable_rx(void) {
  335. EIMSK &= ~(1<<0);
  336. }
  337.  
  338. /**
  339. * @brief USART0 de-initialization.
  340. */
  341. static void usartS_deinit(void) {
  342. usartS_stop_timer();
  343. usartS_disable_rx();
  344. TIMSK2 &= ~(1 << OCIE2A);
  345. }
  346.  
  347. #endif
  348.  
  349. /*===========================================================================*/
  350. /* Driver interrupt handlers. */
  351. /*===========================================================================*/
  352.  
  353. #if AVR_SERIAL_USE_USART0 || defined(__DOXYGEN__)
  354. /**
  355. * @brief USART0 RX interrupt handler.
  356. *
  357. * @isr
  358. */
  359. OSAL_IRQ_HANDLER(AVR_SD1_RX_VECT) {
  360. uint8_t sra;
  361.  
  362. OSAL_IRQ_PROLOGUE();
  363.  
  364. sra = UCSR0A;
  365. if (sra & ((1 << DOR0) | (1 << UPE0) | (1 << FE0)))
  366. set_error(sra, &SD1);
  367. osalSysLockFromISR();
  368. sdIncomingDataI(&SD1, UDR0);
  369. osalSysUnlockFromISR();
  370.  
  371. OSAL_IRQ_EPILOGUE();
  372. }
  373.  
  374. /**
  375. * @brief USART0 TX interrupt handler.
  376. *
  377. * @isr
  378. */
  379. OSAL_IRQ_HANDLER(AVR_SD1_TX_VECT) {
  380. msg_t b;
  381.  
  382. OSAL_IRQ_PROLOGUE();
  383. osalSysLockFromISR();
  384. b = sdRequestDataI(&SD1);
  385. osalSysUnlockFromISR();
  386. if (b < Q_OK)
  387. UCSR0B &= ~(1 << UDRIE0);
  388. else
  389. UDR0 = b;
  390.  
  391. OSAL_IRQ_EPILOGUE();
  392. }
  393. #endif /* AVR_SERIAL_USE_USART0 */
  394.  
  395. #if AVR_SERIAL_USE_USART1 || defined(__DOXYGEN__)
  396. /**
  397. * @brief USART1 RX interrupt handler.
  398. *
  399. * @isr
  400. */
  401. OSAL_IRQ_HANDLER(AVR_SD2_RX_VECT) {
  402. uint8_t sra;
  403.  
  404. OSAL_IRQ_PROLOGUE();
  405.  
  406. sra = UCSR1A;
  407. if (sra & ((1 << DOR1) | (1 << UPE1) | (1 << FE1)))
  408. set_error(sra, &SD2);
  409. osalSysLockFromISR();
  410. sdIncomingDataI(&SD2, UDR1);
  411. osalSysUnlockFromISR();
  412.  
  413. OSAL_IRQ_EPILOGUE();
  414. }
  415.  
  416. /**
  417. * @brief USART1 TX interrupt handler.
  418. *
  419. * @isr
  420. */
  421. OSAL_IRQ_HANDLER(AVR_SD2_TX_VECT) {
  422. msg_t b;
  423.  
  424. OSAL_IRQ_PROLOGUE();
  425.  
  426. osalSysLockFromISR();
  427. b = sdRequestDataI(&SD2);
  428. osalSysUnlockFromISR();
  429. if (b < Q_OK)
  430. UCSR1B &= ~(1 << UDRIE1);
  431. else
  432. UDR1 = b;
  433.  
  434. OSAL_IRQ_EPILOGUE();
  435. }
  436. #endif /* AVR_SERIAL_USE_USART1 */
  437.  
  438. #if AVR_SERIAL_USE_USARTS || defined(__DOXYGEN__)
  439.  
  440. /**
  441. * @brief PCINT interrupt handler
  442. *
  443. * @details This handler changes state by sensing the START bit. Otherwise do nothing
  444. *
  445. * @isr
  446. */
  447. OSAL_IRQ_HANDLER(AVR_SDS_RX_VECT) {
  448. OSAL_IRQ_PROLOGUE();
  449. switch (sds_state) {
  450. case IDLE:
  451. sds_state = RECEIVE_INIT;
  452. usartS_stop_timer();
  453. usartS_start_timer_half();
  454. break;
  455. case RECEIVE_INIT:
  456. case RECEIVE:
  457. /* Do nothing.*/
  458. break;
  459. case TRANSMIT_INIT:
  460. case TRANSMIT:
  461. /* Do nothing.*/
  462. break;
  463. }
  464. OSAL_IRQ_EPILOGUE();
  465. }
  466.  
  467. /**
  468. * @brief TIMER2 Comparator A interrupt
  469. *
  470. * @details Receives data if state is in RECEIVE
  471. *
  472. * @isr
  473. */
  474. OSAL_IRQ_HANDLER(TIMER2_COMPA_vect) {
  475. static int8_t i;
  476. /* Data byte.*/
  477. static int8_t byte;
  478.  
  479. OSAL_IRQ_PROLOGUE();
  480. switch (sds_state) {
  481. case IDLE:
  482. osalSysLockFromISR();
  483. byte = sdRequestDataI(&SDS);
  484. osalSysUnlockFromISR();
  485. if (byte >= Q_OK)
  486. sds_state = TRANSMIT_INIT;
  487. /* Do Nothing.*/
  488. break;
  489. case RECEIVE_INIT:
  490. i = 0;
  491. byte = 0;
  492. sds_state = RECEIVE;
  493. break; /* Break for the initial half period.*/
  494. case RECEIVE:
  495. if (i < sds_bits_per_char) {
  496. byte |= palReadPad(AVR_SDS_RX_PORT, AVR_SDS_RX_PIN) << i;
  497. ++i;
  498. }
  499. else {
  500. /* If last bit is STOP, then assume info is correct. Otherwise, treat as garbage*/
  501. if (palReadPad(AVR_SDS_RX_PORT, AVR_SDS_RX_PIN)) {
  502. osalSysLockFromISR();
  503. sdIncomingDataI(&SDS, byte);
  504. osalSysUnlockFromISR();
  505. }
  506. sds_state = IDLE;
  507. i = 0;
  508. byte = 0;
  509. }
  510. break;
  511. case TRANSMIT_INIT:
  512. /* Transmit must not be interrupted.*/
  513. usartS_disable_rx();
  514. sds_state = TRANSMIT;
  515. i = -1;
  516. /* No break here or timing will be wrong.*/
  517. case TRANSMIT: {
  518. uint8_t bit;
  519. /* START.*/
  520. if (i == -1) {
  521. bit = 0;
  522. }
  523. /* STOP.*/
  524. else if (i == sds_bits_per_char) {
  525. bit = 1;
  526. sds_state = IDLE;
  527. /* Re-enable receive at the end of a transmit.*/
  528. usartS_enable_rx();
  529. }
  530. /* Data.*/
  531. else {
  532. bit = (byte & (1 << i)) != 0;
  533. }
  534. palWritePad(AVR_SDS_TX_PORT, AVR_SDS_TX_PIN, bit);
  535. ++i;
  536. break;
  537. }
  538. }
  539. OSAL_IRQ_EPILOGUE();
  540. }
  541.  
  542. #endif
  543.  
  544.  
  545. /*===========================================================================*/
  546. /* Driver exported functions. */
  547. /*===========================================================================*/
  548.  
  549. /**
  550. * @brief Low level serial driver initialization.
  551. *
  552. * @notapi
  553. */
  554. void sd_lld_init(void) {
  555.  
  556. #if AVR_SERIAL_USE_USART0
  557. sdObjectInit(&SD1, NULL, notify1);
  558. #endif
  559. #if AVR_SERIAL_USE_USART1
  560. sdObjectInit(&SD2, NULL, notify2);
  561. #endif
  562. #if AVR_SERIAL_USE_USARTS
  563. sdObjectInit(&SDS, NULL, NULL);
  564. #endif
  565. }
  566.  
  567. /**
  568. * @brief Low level serial driver configuration and (re)start.
  569. *
  570. * @param[in] sdp pointer to a @p SerialDriver object
  571. * @param[in] config the architecture-dependent serial driver configuration.
  572. * If this parameter is set to @p NULL then a default
  573. * configuration is used.
  574. *
  575. * @notapi
  576. */
  577. void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
  578.  
  579. if (config == NULL)
  580. config = &default_config;
  581.  
  582. #if AVR_SERIAL_USE_USART0
  583. if (&SD1 == sdp) {
  584. usart0_init(config);
  585. return;
  586. }
  587. #endif
  588. #if AVR_SERIAL_USE_USART1
  589. if (&SD2 == sdp) {
  590. usart1_init(config);
  591. return;
  592. }
  593. #endif
  594. #if AVR_SERIAL_USE_USARTS
  595. if (&SDS == sdp) {
  596. usartS_init(config);
  597. return;
  598. }
  599. #endif
  600. }
  601.  
  602. /**
  603. * @brief Low level serial driver stop.
  604. * @details De-initializes the USART, stops the associated clock, resets the
  605. * interrupt vector.
  606. *
  607. * @param[in] sdp pointer to a @p SerialDriver object
  608. *
  609. * @notapi
  610. */
  611. void sd_lld_stop(SerialDriver *sdp) {
  612.  
  613. #if AVR_SERIAL_USE_USART0
  614. if (&SD1 == sdp)
  615. usart0_deinit();
  616. #endif
  617. #if AVR_SERIAL_USE_USART1
  618. if (&SD2 == sdp)
  619. usart1_deinit();
  620. #endif
  621. #if AVR_SERIAL_USE_USARTS
  622. if (&SDS == sdp) {
  623. usartS_deinit();
  624. }
  625. #endif
  626. }
  627.  
  628. #endif /* HAL_USE_SERIAL */
  629.  
  630. /** @} */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement