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.

HardwareSerial.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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. #ifdef TARGET_LPC1768
  23. #include "../../inc/MarlinConfig.h"
  24. #include "HardwareSerial.h"
  25. HardwareSerial Serial = HardwareSerial(LPC_UART0);
  26. HardwareSerial Serial1 = HardwareSerial((LPC_UART_TypeDef *) LPC_UART1);
  27. HardwareSerial Serial2 = HardwareSerial(LPC_UART2);
  28. HardwareSerial Serial3 = HardwareSerial(LPC_UART3);
  29. void HardwareSerial::begin(uint32_t baudrate) {
  30. UART_CFG_Type UARTConfigStruct;
  31. PINSEL_CFG_Type PinCfg;
  32. UART_FIFO_CFG_Type FIFOConfig;
  33. if (UARTx == LPC_UART0) {
  34. /*
  35. * Initialize UART0 pin connect
  36. */
  37. PinCfg.Funcnum = 1;
  38. PinCfg.OpenDrain = 0;
  39. PinCfg.Pinmode = 0;
  40. PinCfg.Pinnum = 2;
  41. PinCfg.Portnum = 0;
  42. PINSEL_ConfigPin(&PinCfg);
  43. PinCfg.Pinnum = 3;
  44. PINSEL_ConfigPin(&PinCfg);
  45. }
  46. else if ((LPC_UART1_TypeDef *) UARTx == LPC_UART1) {
  47. /*
  48. * Initialize UART1 pin connect
  49. */
  50. PinCfg.Funcnum = 1;
  51. PinCfg.OpenDrain = 0;
  52. PinCfg.Pinmode = 0;
  53. PinCfg.Pinnum = 15;
  54. PinCfg.Portnum = 0;
  55. PINSEL_ConfigPin(&PinCfg);
  56. PinCfg.Pinnum = 16;
  57. PINSEL_ConfigPin(&PinCfg);
  58. }
  59. else if (UARTx == LPC_UART2) {
  60. /*
  61. * Initialize UART2 pin connect
  62. */
  63. PinCfg.Funcnum = 1;
  64. PinCfg.OpenDrain = 0;
  65. PinCfg.Pinmode = 0;
  66. PinCfg.Pinnum = 10;
  67. PinCfg.Portnum = 0;
  68. PINSEL_ConfigPin(&PinCfg);
  69. PinCfg.Pinnum = 11;
  70. PINSEL_ConfigPin(&PinCfg);
  71. }
  72. else if (UARTx == LPC_UART3) {
  73. /*
  74. * Initialize UART2 pin connect
  75. */
  76. PinCfg.Funcnum = 1;
  77. PinCfg.OpenDrain = 0;
  78. PinCfg.Pinmode = 0;
  79. PinCfg.Pinnum = 0;
  80. PinCfg.Portnum = 0;
  81. PINSEL_ConfigPin(&PinCfg);
  82. PinCfg.Pinnum = 1;
  83. PINSEL_ConfigPin(&PinCfg);
  84. }
  85. /* Initialize UART Configuration parameter structure to default state:
  86. * Baudrate = 9600bps
  87. * 8 data bit
  88. * 1 Stop bit
  89. * None parity
  90. */
  91. UART_ConfigStructInit(&UARTConfigStruct);
  92. // Re-configure baudrate
  93. UARTConfigStruct.Baud_rate = baudrate;
  94. // Initialize eripheral with given to corresponding parameter
  95. UART_Init(UARTx, &UARTConfigStruct);
  96. // Enable and reset the TX and RX FIFOs
  97. UART_FIFOConfigStructInit(&FIFOConfig);
  98. UART_FIFOConfig(UARTx, &FIFOConfig);
  99. // Enable UART Transmit
  100. UART_TxCmd(UARTx, ENABLE);
  101. // Configure Interrupts
  102. UART_IntConfig(UARTx, UART_INTCFG_RBR, ENABLE);
  103. UART_IntConfig(UARTx, UART_INTCFG_RLS, ENABLE);
  104. if (UARTx == LPC_UART0)
  105. NVIC_EnableIRQ(UART0_IRQn);
  106. else if ((LPC_UART1_TypeDef *) UARTx == LPC_UART1)
  107. NVIC_EnableIRQ(UART1_IRQn);
  108. else if (UARTx == LPC_UART2)
  109. NVIC_EnableIRQ(UART2_IRQn);
  110. else if (UARTx == LPC_UART3)
  111. NVIC_EnableIRQ(UART3_IRQn);
  112. RxQueueWritePos = RxQueueReadPos = 0;
  113. #if TX_BUFFER_SIZE > 0
  114. TxQueueWritePos = TxQueueReadPos = 0;
  115. #endif
  116. }
  117. int HardwareSerial::peek() {
  118. int byte = -1;
  119. /* Temporarily lock out UART receive interrupts during this read so the UART receive
  120. interrupt won't cause problems with the index values */
  121. UART_IntConfig(UARTx, UART_INTCFG_RBR, DISABLE);
  122. if (RxQueueReadPos != RxQueueWritePos)
  123. byte = RxBuffer[RxQueueReadPos];
  124. /* Re-enable UART interrupts */
  125. UART_IntConfig(UARTx, UART_INTCFG_RBR, ENABLE);
  126. return byte;
  127. }
  128. int HardwareSerial::read() {
  129. int byte = -1;
  130. /* Temporarily lock out UART receive interrupts during this read so the UART receive
  131. interrupt won't cause problems with the index values */
  132. UART_IntConfig(UARTx, UART_INTCFG_RBR, DISABLE);
  133. if (RxQueueReadPos != RxQueueWritePos) {
  134. byte = RxBuffer[RxQueueReadPos];
  135. RxQueueReadPos = (RxQueueReadPos + 1) % RX_BUFFER_SIZE;
  136. }
  137. /* Re-enable UART interrupts */
  138. UART_IntConfig(UARTx, UART_INTCFG_RBR, ENABLE);
  139. return byte;
  140. }
  141. size_t HardwareSerial::write(uint8_t send) {
  142. #if TX_BUFFER_SIZE > 0
  143. size_t bytes = 0;
  144. uint32_t fifolvl = 0;
  145. /* If the Tx Buffer is full, wait for space to clear */
  146. if ((TxQueueWritePos+1) % TX_BUFFER_SIZE == TxQueueReadPos) flushTX();
  147. /* Temporarily lock out UART transmit interrupts during this read so the UART transmit interrupt won't
  148. cause problems with the index values */
  149. UART_IntConfig(UARTx, UART_INTCFG_THRE, DISABLE);
  150. /* LPC17xx.h incorrectly defines FIFOLVL as a uint8_t, when it's actually a 32-bit register */
  151. if ((LPC_UART1_TypeDef *) UARTx == LPC_UART1)
  152. fifolvl = *(reinterpret_cast<volatile uint32_t *>(&((LPC_UART1_TypeDef *) UARTx)->FIFOLVL));
  153. else
  154. fifolvl = *(reinterpret_cast<volatile uint32_t *>(&UARTx->FIFOLVL));
  155. /* If the queue is empty and there's space in the FIFO, immediately send the byte */
  156. if (TxQueueWritePos == TxQueueReadPos && fifolvl < UART_TX_FIFO_SIZE) {
  157. bytes = UART_Send(UARTx, &send, 1, BLOCKING);
  158. }
  159. /* Otherwiise, write the byte to the transmit buffer */
  160. else if ((TxQueueWritePos+1) % TX_BUFFER_SIZE != TxQueueReadPos) {
  161. TxBuffer[TxQueueWritePos] = send;
  162. TxQueueWritePos = (TxQueueWritePos+1) % TX_BUFFER_SIZE;
  163. bytes++;
  164. }
  165. /* Re-enable the TX Interrupt */
  166. UART_IntConfig(UARTx, UART_INTCFG_THRE, ENABLE);
  167. return bytes;
  168. #else
  169. return UART_Send(UARTx, &send, 1, BLOCKING);
  170. #endif
  171. }
  172. #if TX_BUFFER_SIZE > 0
  173. void HardwareSerial::flushTX() {
  174. /* Wait for the tx buffer and FIFO to drain */
  175. while (TxQueueWritePos != TxQueueReadPos && UART_CheckBusy(UARTx) == SET);
  176. }
  177. #endif
  178. int HardwareSerial::available() {
  179. return (RxQueueWritePos + RX_BUFFER_SIZE - RxQueueReadPos) % RX_BUFFER_SIZE;
  180. }
  181. void HardwareSerial::flush() {
  182. RxQueueWritePos = 0;
  183. RxQueueReadPos = 0;
  184. }
  185. void HardwareSerial::printf(const char *format, ...) {
  186. char RxBuffer[256];
  187. va_list vArgs;
  188. va_start(vArgs, format);
  189. int length = vsnprintf(RxBuffer, 256, format, vArgs);
  190. va_end(vArgs);
  191. if (length > 0 && length < 256) {
  192. for (int i = 0; i < length; ++i)
  193. write(RxBuffer[i]);
  194. }
  195. }
  196. void HardwareSerial::IRQHandler() {
  197. uint32_t IIRValue;
  198. uint8_t LSRValue, byte;
  199. IIRValue = UART_GetIntId(UARTx);
  200. IIRValue &= UART_IIR_INTID_MASK; /* check bit 1~3, interrupt identification */
  201. if ( IIRValue == UART_IIR_INTID_RLS ) /* Receive Line Status */
  202. {
  203. LSRValue = UART_GetLineStatus(UARTx);
  204. /* Receive Line Status */
  205. if ( LSRValue & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_RXFE|UART_LSR_BI) )
  206. {
  207. /* There are errors or break interrupt */
  208. /* Read LSR will clear the interrupt */
  209. Status = LSRValue;
  210. byte = UART_ReceiveByte(UARTx); /* Dummy read on RX to clear
  211. interrupt, then bail out */
  212. return;
  213. }
  214. }
  215. if ( IIRValue == UART_IIR_INTID_RDA ) /* Receive Data Available */
  216. {
  217. /* Clear the FIFO */
  218. while ( UART_Receive(UARTx, &byte, 1, NONE_BLOCKING) ) {
  219. if ((RxQueueWritePos+1) % RX_BUFFER_SIZE != RxQueueReadPos)
  220. {
  221. RxBuffer[RxQueueWritePos] = byte;
  222. RxQueueWritePos = (RxQueueWritePos+1) % RX_BUFFER_SIZE;
  223. }
  224. else
  225. break;
  226. }
  227. }
  228. else if ( IIRValue == UART_IIR_INTID_CTI ) /* Character timeout indicator */
  229. {
  230. /* Character Time-out indicator */
  231. Status |= 0x100; /* Bit 9 as the CTI error */
  232. }
  233. #if TX_BUFFER_SIZE > 0
  234. if (IIRValue == UART_IIR_INTID_THRE) {
  235. /* Disable THRE interrupt */
  236. UART_IntConfig(UARTx, UART_INTCFG_THRE, DISABLE);
  237. /* Wait for FIFO buffer empty */
  238. while (UART_CheckBusy(UARTx) == SET);
  239. /* Transfer up to UART_TX_FIFO_SIZE bytes of data */
  240. for (int i = 0; i < UART_TX_FIFO_SIZE && TxQueueWritePos != TxQueueReadPos; i++) {
  241. /* Move a piece of data into the transmit FIFO */
  242. if (UART_Send(UARTx, &TxBuffer[TxQueueReadPos], 1, NONE_BLOCKING))
  243. TxQueueReadPos = (TxQueueReadPos+1) % TX_BUFFER_SIZE;
  244. else
  245. break;
  246. }
  247. /* If there is no more data to send, disable the transmit interrupt - else enable it or keep it enabled */
  248. if (TxQueueWritePos == TxQueueReadPos)
  249. UART_IntConfig(UARTx, UART_INTCFG_THRE, DISABLE);
  250. else
  251. UART_IntConfig(UARTx, UART_INTCFG_THRE, ENABLE);
  252. }
  253. #endif
  254. }
  255. #ifdef __cplusplus
  256. extern "C" {
  257. #endif
  258. /*****************************************************************************
  259. ** Function name: UART0_IRQHandler
  260. **
  261. ** Descriptions: UART0 interrupt handler
  262. **
  263. ** parameters: None
  264. ** Returned value: None
  265. **
  266. *****************************************************************************/
  267. void UART0_IRQHandler (void)
  268. {
  269. Serial.IRQHandler();
  270. }
  271. /*****************************************************************************
  272. ** Function name: UART1_IRQHandler
  273. **
  274. ** Descriptions: UART1 interrupt handler
  275. **
  276. ** parameters: None
  277. ** Returned value: None
  278. **
  279. *****************************************************************************/
  280. void UART1_IRQHandler (void)
  281. {
  282. Serial1.IRQHandler();
  283. }
  284. /*****************************************************************************
  285. ** Function name: UART2_IRQHandler
  286. **
  287. ** Descriptions: UART2 interrupt handler
  288. **
  289. ** parameters: None
  290. ** Returned value: None
  291. **
  292. *****************************************************************************/
  293. void UART2_IRQHandler (void)
  294. {
  295. Serial2.IRQHandler();
  296. }
  297. /*****************************************************************************
  298. ** Function name: UART3_IRQHandler
  299. **
  300. ** Descriptions: UART3 interrupt handler
  301. **
  302. ** parameters: None
  303. ** Returned value: None
  304. **
  305. *****************************************************************************/
  306. void UART3_IRQHandler (void)
  307. {
  308. Serial3.IRQHandler();
  309. }
  310. #ifdef __cplusplus
  311. }
  312. #endif
  313. #endif // TARGET_LPC1768