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 9.2KB

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