My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MarlinSerial_Due.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /**
  23. * MarlinSerial_Due.cpp - Hardware serial library for Arduino DUE
  24. * Copyright (c) 2017 Eduardo José Tagle. All right reserved
  25. * Based on MarlinSerial for AVR, copyright (c) 2006 Nicholas Zambetti. All right reserved.
  26. */
  27. #ifdef ARDUINO_ARCH_SAM
  28. #include "../../inc/MarlinConfig.h"
  29. #include "MarlinSerial_Due.h"
  30. #include "InterruptVectors_Due.h"
  31. #include "../../Marlin.h"
  32. // If not using the USB port as serial port
  33. #if SERIAL_PORT >= 0
  34. // Based on selected port, use the proper configuration
  35. #if SERIAL_PORT == 0
  36. #define HWUART UART
  37. #define HWUART_IRQ UART_IRQn
  38. #define HWUART_IRQ_ID ID_UART
  39. #elif SERIAL_PORT == 1
  40. #define HWUART ((Uart*)USART0)
  41. #define HWUART_IRQ USART0_IRQn
  42. #define HWUART_IRQ_ID ID_USART0
  43. #elif SERIAL_PORT == 2
  44. #define HWUART ((Uart*)USART1)
  45. #define HWUART_IRQ USART1_IRQn
  46. #define HWUART_IRQ_ID ID_USART1
  47. #elif SERIAL_PORT == 3
  48. #define HWUART ((Uart*)USART2)
  49. #define HWUART_IRQ USART2_IRQn
  50. #define HWUART_IRQ_ID ID_USART2
  51. #elif SERIAL_PORT == 4
  52. #define HWUART ((Uart*)USART3)
  53. #define HWUART_IRQ USART3_IRQn
  54. #define HWUART_IRQ_ID ID_USART3
  55. #endif
  56. struct ring_buffer_r {
  57. unsigned char buffer[RX_BUFFER_SIZE];
  58. volatile ring_buffer_pos_t head, tail;
  59. };
  60. #if TX_BUFFER_SIZE > 0
  61. struct ring_buffer_t {
  62. unsigned char buffer[TX_BUFFER_SIZE];
  63. volatile uint8_t head, tail;
  64. };
  65. #endif
  66. ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
  67. #if TX_BUFFER_SIZE > 0
  68. ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
  69. #endif
  70. static bool _written;
  71. #if ENABLED(SERIAL_XON_XOFF)
  72. constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
  73. XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
  74. // XON / XOFF character definitions
  75. constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
  76. uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
  77. // Validate that RX buffer size is at least 4096 bytes- According to several experiments, on
  78. // the original Arduino Due that uses a ATmega16U2 as USB to serial bridge, due to the introduced
  79. // latencies, at least 2959 bytes of RX buffering (when transmitting at 250kbits/s) are required
  80. // to avoid overflows.
  81. #if RX_BUFFER_SIZE < 4096
  82. #error Arduino DUE requires at least 4096 bytes of RX buffer to avoid buffer overflows when using XON/XOFF handshake
  83. #endif
  84. #endif
  85. #if ENABLED(SERIAL_STATS_DROPPED_RX)
  86. uint8_t rx_dropped_bytes = 0;
  87. #endif
  88. #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
  89. uint8_t rx_buffer_overruns = 0;
  90. #endif
  91. #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
  92. uint8_t rx_framing_errors = 0;
  93. #endif
  94. #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
  95. ring_buffer_pos_t rx_max_enqueued = 0;
  96. #endif
  97. // A SW memory barrier, to ensure GCC does not overoptimize loops
  98. #define sw_barrier() asm volatile("": : :"memory");
  99. #if ENABLED(EMERGENCY_PARSER)
  100. #include "../../feature/emergency_parser.h"
  101. #endif
  102. // (called with RX interrupts disabled)
  103. FORCE_INLINE void store_rxd_char() {
  104. #if ENABLED(EMERGENCY_PARSER)
  105. static EmergencyParser::State emergency_state; // = EP_RESET
  106. #endif
  107. // Get the tail - Nothing can alter its value while we are at this ISR
  108. const ring_buffer_pos_t t = rx_buffer.tail;
  109. // Get the head pointer
  110. ring_buffer_pos_t h = rx_buffer.head;
  111. // Get the next element
  112. ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
  113. // Read the character from the USART
  114. uint8_t c = HWUART->UART_RHR;
  115. #if ENABLED(EMERGENCY_PARSER)
  116. emergency_parser.update(emergency_state, c);
  117. #endif
  118. // If the character is to be stored at the index just before the tail
  119. // (such that the head would advance to the current tail), the RX FIFO is
  120. // full, so don't write the character or advance the head.
  121. if (i != t) {
  122. rx_buffer.buffer[h] = c;
  123. h = i;
  124. }
  125. #if ENABLED(SERIAL_STATS_DROPPED_RX)
  126. else if (!++rx_dropped_bytes) --rx_dropped_bytes;
  127. #endif
  128. #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
  129. const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
  130. // Calculate count of bytes stored into the RX buffer
  131. // Keep track of the maximum count of enqueued bytes
  132. NOLESS(rx_max_enqueued, rx_count);
  133. #endif
  134. #if ENABLED(SERIAL_XON_XOFF)
  135. // If the last char that was sent was an XON
  136. if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
  137. // Bytes stored into the RX buffer
  138. const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
  139. // If over 12.5% of RX buffer capacity, send XOFF before running out of
  140. // RX buffer space .. 325 bytes @ 250kbits/s needed to let the host react
  141. // and stop sending bytes. This translates to 13mS propagation time.
  142. if (rx_count >= (RX_BUFFER_SIZE) / 8) {
  143. // At this point, definitely no TX interrupt was executing, since the TX isr can't be preempted.
  144. // Don't enable the TX interrupt here as a means to trigger the XOFF char, because if it happens
  145. // to be in the middle of trying to disable the RX interrupt in the main program, eventually the
  146. // enabling of the TX interrupt could be undone. The ONLY reliable thing this can do to ensure
  147. // the sending of the XOFF char is to send it HERE AND NOW.
  148. // About to send the XOFF char
  149. xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
  150. // Wait until the TX register becomes empty and send it - Here there could be a problem
  151. // - While waiting for the TX register to empty, the RX register could receive a new
  152. // character. This must also handle that situation!
  153. uint32_t status;
  154. while (!((status = HWUART->UART_SR) & UART_SR_TXRDY)) {
  155. if (status & UART_SR_RXRDY) {
  156. // We received a char while waiting for the TX buffer to be empty - Receive and process it!
  157. i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
  158. // Read the character from the USART
  159. c = HWUART->UART_RHR;
  160. #if ENABLED(EMERGENCY_PARSER)
  161. emergency_parser.update(emergency_state, c);
  162. #endif
  163. // If the character is to be stored at the index just before the tail
  164. // (such that the head would advance to the current tail), the FIFO is
  165. // full, so don't write the character or advance the head.
  166. if (i != t) {
  167. rx_buffer.buffer[h] = c;
  168. h = i;
  169. }
  170. #if ENABLED(SERIAL_STATS_DROPPED_RX)
  171. else if (!++rx_dropped_bytes) --rx_dropped_bytes;
  172. #endif
  173. }
  174. sw_barrier();
  175. }
  176. HWUART->UART_THR = XOFF_CHAR;
  177. // At this point there could be a race condition between the write() function
  178. // and this sending of the XOFF char. This interrupt could happen between the
  179. // wait to be empty TX buffer loop and the actual write of the character. Since
  180. // the TX buffer is full because it's sending the XOFF char, the only way to be
  181. // sure the write() function will succeed is to wait for the XOFF char to be
  182. // completely sent. Since an extra character could be received during the wait
  183. // it must also be handled!
  184. while (!((status = HWUART->UART_SR) & UART_SR_TXRDY)) {
  185. if (status & UART_SR_RXRDY) {
  186. // A char arrived while waiting for the TX buffer to be empty - Receive and process it!
  187. i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
  188. // Read the character from the USART
  189. c = HWUART->UART_RHR;
  190. #if ENABLED(EMERGENCY_PARSER)
  191. emergency_parser.update(emergency_state, c);
  192. #endif
  193. // If the character is to be stored at the index just before the tail
  194. // (such that the head would advance to the current tail), the FIFO is
  195. // full, so don't write the character or advance the head.
  196. if (i != t) {
  197. rx_buffer.buffer[h] = c;
  198. h = i;
  199. }
  200. #if ENABLED(SERIAL_STATS_DROPPED_RX)
  201. else if (!++rx_dropped_bytes) --rx_dropped_bytes;
  202. #endif
  203. }
  204. sw_barrier();
  205. }
  206. // At this point everything is ready. The write() function won't
  207. // have any issues writing to the UART TX register if it needs to!
  208. }
  209. }
  210. #endif // SERIAL_XON_XOFF
  211. // Store the new head value
  212. rx_buffer.head = h;
  213. }
  214. #if TX_BUFFER_SIZE > 0
  215. FORCE_INLINE void _tx_thr_empty_irq(void) {
  216. // Read positions
  217. uint8_t t = tx_buffer.tail;
  218. const uint8_t h = tx_buffer.head;
  219. #if ENABLED(SERIAL_XON_XOFF)
  220. // If an XON char is pending to be sent, do it now
  221. if (xon_xoff_state == XON_CHAR) {
  222. // Send the character
  223. HWUART->UART_THR = XON_CHAR;
  224. // Remember we sent it.
  225. xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
  226. // If nothing else to transmit, just disable TX interrupts.
  227. if (h == t) HWUART->UART_IDR = UART_IDR_TXRDY;
  228. return;
  229. }
  230. #endif
  231. // If nothing to transmit, just disable TX interrupts. This could
  232. // happen as the result of the non atomicity of the disabling of RX
  233. // interrupts that could end reenabling TX interrupts as a side effect.
  234. if (h == t) {
  235. HWUART->UART_IDR = UART_IDR_TXRDY;
  236. return;
  237. }
  238. // There is something to TX, Send the next byte
  239. const uint8_t c = tx_buffer.buffer[t];
  240. t = (t + 1) & (TX_BUFFER_SIZE - 1);
  241. HWUART->UART_THR = c;
  242. tx_buffer.tail = t;
  243. // Disable interrupts if there is nothing to transmit following this byte
  244. if (h == t) HWUART->UART_IDR = UART_IDR_TXRDY;
  245. }
  246. #endif // TX_BUFFER_SIZE > 0
  247. static void UART_ISR(void) {
  248. const uint32_t status = HWUART->UART_SR;
  249. // Data received?
  250. if (status & UART_SR_RXRDY) store_rxd_char();
  251. #if TX_BUFFER_SIZE > 0
  252. // Something to send, and TX interrupts are enabled (meaning something to send)?
  253. if ((status & UART_SR_TXRDY) && (HWUART->UART_IMR & UART_IMR_TXRDY)) _tx_thr_empty_irq();
  254. #endif
  255. // Acknowledge errors
  256. if ((status & UART_SR_OVRE) || (status & UART_SR_FRAME)) {
  257. #if ENABLED(SERIAL_STATS_DROPPED_RX)
  258. if (status & UART_SR_OVRE && !++rx_dropped_bytes) --rx_dropped_bytes;
  259. #endif
  260. #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
  261. if (status & UART_SR_OVRE && !++rx_buffer_overruns) --rx_buffer_overruns;
  262. #endif
  263. #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
  264. if (status & UART_SR_FRAME && !++rx_framing_errors) --rx_framing_errors;
  265. #endif
  266. // TODO: error reporting outside ISR
  267. HWUART->UART_CR = UART_CR_RSTSTA;
  268. }
  269. }
  270. // Public Methods
  271. void MarlinSerial::begin(const long baud_setting) {
  272. // Disable UART interrupt in NVIC
  273. NVIC_DisableIRQ( HWUART_IRQ );
  274. // We NEED memory barriers to ensure Interrupts are actually disabled!
  275. // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
  276. __DSB();
  277. __ISB();
  278. // Disable clock
  279. pmc_disable_periph_clk( HWUART_IRQ_ID );
  280. // Configure PMC
  281. pmc_enable_periph_clk( HWUART_IRQ_ID );
  282. // Disable PDC channel
  283. HWUART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
  284. // Reset and disable receiver and transmitter
  285. HWUART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
  286. // Configure mode: 8bit, No parity, 1 bit stop
  287. HWUART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
  288. // Configure baudrate (asynchronous, no oversampling)
  289. HWUART->UART_BRGR = (SystemCoreClock / (baud_setting << 4));
  290. // Configure interrupts
  291. HWUART->UART_IDR = 0xFFFFFFFF;
  292. HWUART->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME;
  293. // Install interrupt handler
  294. install_isr(HWUART_IRQ, UART_ISR);
  295. // Configure priority. We need a very high priority to avoid losing characters
  296. // and we need to be able to preempt the Stepper ISR and everything else!
  297. // (this could probably be fixed by using DMA with the Serial port)
  298. NVIC_SetPriority(HWUART_IRQ, 1);
  299. // Enable UART interrupt in NVIC
  300. NVIC_EnableIRQ(HWUART_IRQ);
  301. // Enable receiver and transmitter
  302. HWUART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
  303. #if TX_BUFFER_SIZE > 0
  304. _written = false;
  305. #endif
  306. }
  307. void MarlinSerial::end() {
  308. // Disable UART interrupt in NVIC
  309. NVIC_DisableIRQ( HWUART_IRQ );
  310. // We NEED memory barriers to ensure Interrupts are actually disabled!
  311. // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
  312. __DSB();
  313. __ISB();
  314. pmc_disable_periph_clk( HWUART_IRQ_ID );
  315. }
  316. int MarlinSerial::peek(void) {
  317. const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
  318. return v;
  319. }
  320. int MarlinSerial::read(void) {
  321. const ring_buffer_pos_t h = rx_buffer.head;
  322. ring_buffer_pos_t t = rx_buffer.tail;
  323. if (h == t) return -1;
  324. int v = rx_buffer.buffer[t];
  325. t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
  326. // Advance tail
  327. rx_buffer.tail = t;
  328. #if ENABLED(SERIAL_XON_XOFF)
  329. // If the XOFF char was sent, or about to be sent...
  330. if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
  331. // Get count of bytes in the RX buffer
  332. const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
  333. // When below 10% of RX buffer capacity, send XON before running out of RX buffer bytes
  334. if (rx_count < (RX_BUFFER_SIZE) / 10) {
  335. #if TX_BUFFER_SIZE > 0
  336. // Signal we want an XON character to be sent.
  337. xon_xoff_state = XON_CHAR;
  338. // Enable TX isr.
  339. HWUART->UART_IER = UART_IER_TXRDY;
  340. #else
  341. // If not using TX interrupts, we must send the XON char now
  342. xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
  343. while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
  344. HWUART->UART_THR = XON_CHAR;
  345. #endif
  346. }
  347. }
  348. #endif
  349. return v;
  350. }
  351. ring_buffer_pos_t MarlinSerial::available(void) {
  352. const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
  353. return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
  354. }
  355. void MarlinSerial::flush(void) {
  356. rx_buffer.tail = rx_buffer.head;
  357. #if ENABLED(SERIAL_XON_XOFF)
  358. if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
  359. #if TX_BUFFER_SIZE > 0
  360. // Signal we want an XON character to be sent.
  361. xon_xoff_state = XON_CHAR;
  362. // Enable TX isr.
  363. HWUART->UART_IER = UART_IER_TXRDY;
  364. #else
  365. // If not using TX interrupts, we must send the XON char now
  366. xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
  367. while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
  368. HWUART->UART_THR = XON_CHAR;
  369. #endif
  370. }
  371. #endif
  372. }
  373. #if TX_BUFFER_SIZE > 0
  374. void MarlinSerial::write(const uint8_t c) {
  375. _written = true;
  376. // If the TX interrupts are disabled and the data register
  377. // is empty, just write the byte to the data register and
  378. // be done. This shortcut helps significantly improve the
  379. // effective datarate at high (>500kbit/s) bitrates, where
  380. // interrupt overhead becomes a slowdown.
  381. // Yes, there is a race condition between the sending of the
  382. // XOFF char at the RX isr, but it is properly handled there
  383. if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
  384. HWUART->UART_THR = c;
  385. return;
  386. }
  387. const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
  388. // If global interrupts are disabled (as the result of being called from an ISR)...
  389. if (!ISRS_ENABLED()) {
  390. // Make room by polling if it is possible to transmit, and do so!
  391. while (i == tx_buffer.tail) {
  392. // If we can transmit another byte, do it.
  393. if (HWUART->UART_SR & UART_SR_TXRDY) _tx_thr_empty_irq();
  394. // Make sure compiler rereads tx_buffer.tail
  395. sw_barrier();
  396. }
  397. }
  398. else {
  399. // Interrupts are enabled, just wait until there is space
  400. while (i == tx_buffer.tail) sw_barrier();
  401. }
  402. // Store new char. head is always safe to move
  403. tx_buffer.buffer[tx_buffer.head] = c;
  404. tx_buffer.head = i;
  405. // Enable TX isr - Non atomic, but it will eventually enable TX isr
  406. HWUART->UART_IER = UART_IER_TXRDY;
  407. }
  408. void MarlinSerial::flushTX(void) {
  409. // TX
  410. // If we have never written a byte, no need to flush. This special
  411. // case is needed since there is no way to force the TXC (transmit
  412. // complete) bit to 1 during initialization
  413. if (!_written) return;
  414. // If global interrupts are disabled (as the result of being called from an ISR)...
  415. if (!ISRS_ENABLED()) {
  416. // Wait until everything was transmitted - We must do polling, as interrupts are disabled
  417. while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {
  418. // If there is more space, send an extra character
  419. if (HWUART->UART_SR & UART_SR_TXRDY) _tx_thr_empty_irq();
  420. sw_barrier();
  421. }
  422. }
  423. else {
  424. // Wait until everything was transmitted
  425. while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) sw_barrier();
  426. }
  427. // At this point nothing is queued anymore (DRIE is disabled) and
  428. // the hardware finished transmission (TXC is set).
  429. }
  430. #else // TX_BUFFER_SIZE == 0
  431. void MarlinSerial::write(const uint8_t c) {
  432. _written = true;
  433. while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
  434. HWUART->UART_THR = c;
  435. }
  436. void MarlinSerial::flushTX(void) {
  437. // TX
  438. // No bytes written, no need to flush. This special case is needed since there's
  439. // no way to force the TXC (transmit complete) bit to 1 during initialization.
  440. if (!_written) return;
  441. // Wait until everything was transmitted
  442. while (!(HWUART->UART_SR & UART_SR_TXEMPTY)) sw_barrier();
  443. // At this point nothing is queued anymore (DRIE is disabled) and
  444. // the hardware finished transmission (TXC is set).
  445. }
  446. #endif // TX_BUFFER_SIZE == 0
  447. /**
  448. * Imports from print.h
  449. */
  450. void MarlinSerial::print(char c, int base) {
  451. print((long)c, base);
  452. }
  453. void MarlinSerial::print(unsigned char b, int base) {
  454. print((unsigned long)b, base);
  455. }
  456. void MarlinSerial::print(int n, int base) {
  457. print((long)n, base);
  458. }
  459. void MarlinSerial::print(unsigned int n, int base) {
  460. print((unsigned long)n, base);
  461. }
  462. void MarlinSerial::print(long n, int base) {
  463. if (base == 0) write(n);
  464. else if (base == 10) {
  465. if (n < 0) { print('-'); n = -n; }
  466. printNumber(n, 10);
  467. }
  468. else
  469. printNumber(n, base);
  470. }
  471. void MarlinSerial::print(unsigned long n, int base) {
  472. if (base == 0) write(n);
  473. else printNumber(n, base);
  474. }
  475. void MarlinSerial::print(double n, int digits) {
  476. printFloat(n, digits);
  477. }
  478. void MarlinSerial::println(void) {
  479. print('\r');
  480. print('\n');
  481. }
  482. void MarlinSerial::println(const String& s) {
  483. print(s);
  484. println();
  485. }
  486. void MarlinSerial::println(const char c[]) {
  487. print(c);
  488. println();
  489. }
  490. void MarlinSerial::println(char c, int base) {
  491. print(c, base);
  492. println();
  493. }
  494. void MarlinSerial::println(unsigned char b, int base) {
  495. print(b, base);
  496. println();
  497. }
  498. void MarlinSerial::println(int n, int base) {
  499. print(n, base);
  500. println();
  501. }
  502. void MarlinSerial::println(unsigned int n, int base) {
  503. print(n, base);
  504. println();
  505. }
  506. void MarlinSerial::println(long n, int base) {
  507. print(n, base);
  508. println();
  509. }
  510. void MarlinSerial::println(unsigned long n, int base) {
  511. print(n, base);
  512. println();
  513. }
  514. void MarlinSerial::println(double n, int digits) {
  515. print(n, digits);
  516. println();
  517. }
  518. // Private Methods
  519. void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
  520. if (n) {
  521. unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
  522. int8_t i = 0;
  523. while (n) {
  524. buf[i++] = n % base;
  525. n /= base;
  526. }
  527. while (i--)
  528. print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
  529. }
  530. else
  531. print('0');
  532. }
  533. void MarlinSerial::printFloat(double number, uint8_t digits) {
  534. // Handle negative numbers
  535. if (number < 0.0) {
  536. print('-');
  537. number = -number;
  538. }
  539. // Round correctly so that print(1.999, 2) prints as "2.00"
  540. double rounding = 0.5;
  541. for (uint8_t i = 0; i < digits; ++i) rounding *= 0.1;
  542. number += rounding;
  543. // Extract the integer part of the number and print it
  544. unsigned long int_part = (unsigned long)number;
  545. double remainder = number - (double)int_part;
  546. print(int_part);
  547. // Print the decimal point, but only if there are digits beyond
  548. if (digits) {
  549. print('.');
  550. // Extract digits from the remainder one at a time
  551. while (digits--) {
  552. remainder *= 10.0;
  553. int toPrint = int(remainder);
  554. print(toPrint);
  555. remainder -= toPrint;
  556. }
  557. }
  558. }
  559. // Preinstantiate
  560. MarlinSerial customizedSerial;
  561. #endif
  562. #endif // ARDUINO_ARCH_SAM