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.

HAL.cpp 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /**
  2. * Marlin 3D Printer Firmware
  3. *
  4. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  5. * SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. #ifdef __SAMD51__
  22. #include "../../inc/MarlinConfig.h"
  23. #include <Adafruit_ZeroDMA.h>
  24. #include <wiring_private.h>
  25. // ------------------------
  26. // Local defines
  27. // ------------------------
  28. #define GET_TEMP_0_ADC() TERN(HAS_TEMP_ADC_0, PIN_TO_ADC(TEMP_0_PIN), -1)
  29. #define GET_TEMP_1_ADC() TERN(HAS_TEMP_ADC_1, PIN_TO_ADC(TEMP_1_PIN), -1)
  30. #define GET_TEMP_2_ADC() TERN(HAS_TEMP_ADC_2, PIN_TO_ADC(TEMP_2_PIN), -1)
  31. #define GET_TEMP_3_ADC() TERN(HAS_TEMP_ADC_3, PIN_TO_ADC(TEMP_3_PIN), -1)
  32. #define GET_TEMP_4_ADC() TERN(HAS_TEMP_ADC_4, PIN_TO_ADC(TEMP_4_PIN), -1)
  33. #define GET_TEMP_5_ADC() TERN(HAS_TEMP_ADC_5, PIN_TO_ADC(TEMP_5_PIN), -1)
  34. #define GET_TEMP_6_ADC() TERN(HAS_TEMP_ADC_6, PIN_TO_ADC(TEMP_6_PIN), -1)
  35. #define GET_TEMP_7_ADC() TERN(HAS_TEMP_ADC_7, PIN_TO_ADC(TEMP_7_PIN), -1)
  36. #define GET_PROBE_ADC() TERN(HAS_TEMP_PROBE, PIN_TO_ADC(TEMP_PROBE_PIN), -1)
  37. #define GET_BED_ADC() TERN(HAS_TEMP_ADC_BED, PIN_TO_ADC(TEMP_BED_PIN), -1)
  38. #define GET_CHAMBER_ADC() TERN(HAS_TEMP_ADC_CHAMBER, PIN_TO_ADC(TEMP_CHAMBER_PIN), -1)
  39. #define GET_FILAMENT_WIDTH_ADC() TERN(FILAMENT_WIDTH_SENSOR, PIN_TO_ADC(FILWIDTH_PIN), -1)
  40. #define GET_BUTTONS_ADC() TERN(HAS_ADC_BUTTONS, PIN_TO_ADC(ADC_KEYPAD_PIN), -1)
  41. #define IS_ADC_REQUIRED(n) ( \
  42. GET_TEMP_0_ADC() == n || GET_TEMP_1_ADC() == n || GET_TEMP_2_ADC() == n || GET_TEMP_3_ADC() == n \
  43. || GET_TEMP_4_ADC() == n || GET_TEMP_5_ADC() == n || GET_TEMP_6_ADC() == n || GET_TEMP_7_ADC() == n \
  44. || GET_PROBE_ADC() == n \
  45. || GET_BED_ADC() == n \
  46. || GET_CHAMBER_ADC() == n \
  47. || GET_FILAMENT_WIDTH_ADC() == n \
  48. || GET_BUTTONS_ADC() == n \
  49. )
  50. #if IS_ADC_REQUIRED(0)
  51. #define ADC0_IS_REQUIRED 1
  52. #define FIRST_ADC 0
  53. #else
  54. #define FIRST_ADC 1
  55. #endif
  56. #if IS_ADC_REQUIRED(1)
  57. #define ADC1_IS_REQUIRED 1
  58. #define LAST_ADC 1
  59. #else
  60. #define LAST_ADC 0
  61. #endif
  62. #if ADC0_IS_REQUIRED || ADC1_IS_REQUIRED
  63. #define ADC_IS_REQUIRED 1
  64. #define DMA_IS_REQUIRED 1
  65. #endif
  66. // ------------------------
  67. // Types
  68. // ------------------------
  69. #if DMA_IS_REQUIRED
  70. // Struct must be 32 bits aligned because of DMA accesses but fields needs to be 8 bits packed
  71. typedef struct __attribute__((aligned(4), packed)) {
  72. ADC_INPUTCTRL_Type INPUTCTRL;
  73. } HAL_DMA_DAC_Registers; // DMA transfered registers
  74. #endif
  75. // ------------------------
  76. // Private Variables
  77. // ------------------------
  78. uint16_t HAL_adc_result;
  79. #if ADC_IS_REQUIRED
  80. // Pins used by ADC inputs. Order must be ADC0 inputs first then ADC1
  81. const uint8_t adc_pins[] = {
  82. // ADC0 pins
  83. #if GET_TEMP_0_ADC() == 0
  84. TEMP_0_PIN,
  85. #endif
  86. #if GET_TEMP_1_ADC() == 0
  87. TEMP_1_PIN,
  88. #endif
  89. #if GET_TEMP_2_ADC() == 0
  90. TEMP_2_PIN,
  91. #endif
  92. #if GET_TEMP_3_ADC() == 0
  93. TEMP_3_PIN,
  94. #endif
  95. #if GET_TEMP_4_ADC() == 0
  96. TEMP_4_PIN,
  97. #endif
  98. #if GET_TEMP_5_ADC() == 0
  99. TEMP_5_PIN,
  100. #endif
  101. #if GET_TEMP_6_ADC() == 0
  102. TEMP_6_PIN,
  103. #endif
  104. #if GET_TEMP_7_ADC() == 0
  105. TEMP_7_PIN,
  106. #endif
  107. #if GET_PROBE_ADC() == 0
  108. TEMP_PROBE_PIN,
  109. #endif
  110. #if GET_BED_ADC() == 0
  111. TEMP_BED_PIN,
  112. #endif
  113. #if GET_CHAMBER_ADC() == 0
  114. TEMP_CHAMBER_PIN,
  115. #endif
  116. #if GET_FILAMENT_WIDTH_ADC() == 0
  117. FILWIDTH_PIN,
  118. #endif
  119. #if GET_BUTTONS_ADC() == 0
  120. ADC_KEYPAD_PIN,
  121. #endif
  122. // ADC1 pins
  123. #if GET_TEMP_0_ADC() == 1
  124. TEMP_0_PIN,
  125. #endif
  126. #if GET_TEMP_1_ADC() == 1
  127. TEMP_1_PIN,
  128. #endif
  129. #if GET_TEMP_2_ADC() == 1
  130. TEMP_2_PIN,
  131. #endif
  132. #if GET_TEMP_3_ADC() == 1
  133. TEMP_3_PIN,
  134. #endif
  135. #if GET_TEMP_4_ADC() == 1
  136. TEMP_4_PIN,
  137. #endif
  138. #if GET_TEMP_5_ADC() == 1
  139. TEMP_5_PIN,
  140. #endif
  141. #if GET_TEMP_6_ADC() == 1
  142. TEMP_6_PIN,
  143. #endif
  144. #if GET_TEMP_7_ADC() == 1
  145. TEMP_7_PIN,
  146. #endif
  147. #if GET_PROBE_ADC() == 1
  148. TEMP_PROBE_PIN,
  149. #endif
  150. #if GET_BED_ADC() == 1
  151. TEMP_BED_PIN,
  152. #endif
  153. #if GET_CHAMBER_ADC() == 1
  154. TEMP_CHAMBER_PIN,
  155. #endif
  156. #if GET_FILAMENT_WIDTH_ADC() == 1
  157. FILWIDTH_PIN,
  158. #endif
  159. #if GET_BUTTONS_ADC() == 1
  160. ADC_KEYPAD_PIN,
  161. #endif
  162. };
  163. uint16_t HAL_adc_results[COUNT(adc_pins)];
  164. #if ADC0_IS_REQUIRED
  165. Adafruit_ZeroDMA adc0DMAProgram,
  166. adc0DMARead;
  167. const HAL_DMA_DAC_Registers adc0_dma_regs_list[] = {
  168. #if GET_TEMP_0_ADC() == 0
  169. { PIN_TO_INPUTCTRL(TEMP_0_PIN) },
  170. #endif
  171. #if GET_TEMP_1_ADC() == 0
  172. { PIN_TO_INPUTCTRL(TEMP_1_PIN) },
  173. #endif
  174. #if GET_TEMP_2_ADC() == 0
  175. { PIN_TO_INPUTCTRL(TEMP_2_PIN) },
  176. #endif
  177. #if GET_TEMP_3_ADC() == 0
  178. { PIN_TO_INPUTCTRL(TEMP_3_PIN) },
  179. #endif
  180. #if GET_TEMP_4_ADC() == 0
  181. { PIN_TO_INPUTCTRL(TEMP_4_PIN) },
  182. #endif
  183. #if GET_TEMP_5_ADC() == 0
  184. { PIN_TO_INPUTCTRL(TEMP_5_PIN) },
  185. #endif
  186. #if GET_TEMP_6_ADC() == 0
  187. { PIN_TO_INPUTCTRL(TEMP_6_PIN) },
  188. #endif
  189. #if GET_TEMP_7_ADC() == 0
  190. { PIN_TO_INPUTCTRL(TEMP_7_PIN) },
  191. #endif
  192. #if GET_PROBE_ADC() == 0
  193. { PIN_TO_INPUTCTRL(TEMP_PROBE_PIN) },
  194. #endif
  195. #if GET_BED_ADC() == 0
  196. { PIN_TO_INPUTCTRL(TEMP_BED_PIN) },
  197. #endif
  198. #if GET_CHAMBER_ADC() == 0
  199. { PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
  200. #endif
  201. #if GET_FILAMENT_WIDTH_ADC() == 0
  202. { PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
  203. #endif
  204. #if GET_BUTTONS_ADC() == 0
  205. { PIN_TO_INPUTCTRL(ADC_KEYPAD_PIN) },
  206. #endif
  207. };
  208. #define ADC0_AINCOUNT COUNT(adc0_dma_regs_list)
  209. #endif // ADC0_IS_REQUIRED
  210. #if ADC1_IS_REQUIRED
  211. Adafruit_ZeroDMA adc1DMAProgram,
  212. adc1DMARead;
  213. const HAL_DMA_DAC_Registers adc1_dma_regs_list[] = {
  214. #if GET_TEMP_0_ADC() == 1
  215. { PIN_TO_INPUTCTRL(TEMP_0_PIN) },
  216. #endif
  217. #if GET_TEMP_1_ADC() == 1
  218. { PIN_TO_INPUTCTRL(TEMP_1_PIN) },
  219. #endif
  220. #if GET_TEMP_2_ADC() == 1
  221. { PIN_TO_INPUTCTRL(TEMP_2_PIN) },
  222. #endif
  223. #if GET_TEMP_3_ADC() == 1
  224. { PIN_TO_INPUTCTRL(TEMP_3_PIN) },
  225. #endif
  226. #if GET_TEMP_4_ADC() == 1
  227. { PIN_TO_INPUTCTRL(TEMP_4_PIN) },
  228. #endif
  229. #if GET_TEMP_5_ADC() == 1
  230. { PIN_TO_INPUTCTRL(TEMP_5_PIN) },
  231. #endif
  232. #if GET_TEMP_6_ADC() == 1
  233. { PIN_TO_INPUTCTRL(TEMP_6_PIN) },
  234. #endif
  235. #if GET_TEMP_7_ADC() == 1
  236. { PIN_TO_INPUTCTRL(TEMP_7_PIN) },
  237. #endif
  238. #if GET_PROBE_ADC() == 1
  239. { PIN_TO_INPUTCTRL(TEMP_PROBE_PIN) },
  240. #endif
  241. #if GET_BED_ADC() == 1
  242. { PIN_TO_INPUTCTRL(TEMP_BED_PIN) },
  243. #endif
  244. #if GET_CHAMBER_ADC() == 1
  245. { PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
  246. #endif
  247. #if GET_FILAMENT_WIDTH_ADC() == 1
  248. { PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
  249. #endif
  250. #if GET_BUTTONS_ADC() == 1
  251. { PIN_TO_INPUTCTRL(ADC_KEYPAD_PIN) },
  252. #endif
  253. };
  254. #define ADC1_AINCOUNT COUNT(adc1_dma_regs_list)
  255. #endif // ADC1_IS_REQUIRED
  256. #endif // ADC_IS_REQUIRED
  257. // ------------------------
  258. // Private functions
  259. // ------------------------
  260. #if DMA_IS_REQUIRED
  261. void dma_init() {
  262. DmacDescriptor *descriptor;
  263. #if ADC0_IS_REQUIRED
  264. adc0DMAProgram.setTrigger(ADC0_DMAC_ID_SEQ);
  265. adc0DMAProgram.setAction(DMA_TRIGGER_ACTON_BEAT);
  266. adc0DMAProgram.loop(true);
  267. if (adc0DMAProgram.allocate() == DMA_STATUS_OK) {
  268. descriptor = adc0DMAProgram.addDescriptor(
  269. (void *)adc0_dma_regs_list, // SRC
  270. (void *)&ADC0->DSEQDATA.reg, // DEST
  271. sizeof(adc0_dma_regs_list) / 4, // CNT
  272. DMA_BEAT_SIZE_WORD,
  273. true, // SRCINC
  274. false, // DSTINC
  275. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  276. DMA_STEPSEL_SRC // STEPSEL
  277. );
  278. if (descriptor != nullptr)
  279. descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
  280. adc0DMAProgram.startJob();
  281. }
  282. adc0DMARead.setTrigger(ADC0_DMAC_ID_RESRDY);
  283. adc0DMARead.setAction(DMA_TRIGGER_ACTON_BEAT);
  284. adc0DMARead.loop(true);
  285. if (adc0DMARead.allocate() == DMA_STATUS_OK) {
  286. adc0DMARead.addDescriptor(
  287. (void *)&ADC0->RESULT.reg, // SRC
  288. &HAL_adc_results, // DEST
  289. ADC0_AINCOUNT, // CNT
  290. DMA_BEAT_SIZE_HWORD,
  291. false, // SRCINC
  292. true, // DSTINC
  293. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  294. DMA_STEPSEL_DST // STEPSEL
  295. );
  296. adc0DMARead.startJob();
  297. }
  298. #endif
  299. #if ADC1_IS_REQUIRED
  300. adc1DMAProgram.setTrigger(ADC1_DMAC_ID_SEQ);
  301. adc1DMAProgram.setAction(DMA_TRIGGER_ACTON_BEAT);
  302. adc1DMAProgram.loop(true);
  303. if (adc1DMAProgram.allocate() == DMA_STATUS_OK) {
  304. descriptor = adc1DMAProgram.addDescriptor(
  305. (void *)adc1_dma_regs_list, // SRC
  306. (void *)&ADC1->DSEQDATA.reg, // DEST
  307. sizeof(adc1_dma_regs_list) / 4, // CNT
  308. DMA_BEAT_SIZE_WORD,
  309. true, // SRCINC
  310. false, // DSTINC
  311. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  312. DMA_STEPSEL_SRC // STEPSEL
  313. );
  314. if (descriptor != nullptr)
  315. descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
  316. adc1DMAProgram.startJob();
  317. }
  318. adc1DMARead.setTrigger(ADC1_DMAC_ID_RESRDY);
  319. adc1DMARead.setAction(DMA_TRIGGER_ACTON_BEAT);
  320. adc1DMARead.loop(true);
  321. if (adc1DMARead.allocate() == DMA_STATUS_OK) {
  322. adc1DMARead.addDescriptor(
  323. (void *)&ADC1->RESULT.reg, // SRC
  324. &HAL_adc_results[ADC0_AINCOUNT], // DEST
  325. ADC1_AINCOUNT, // CNT
  326. DMA_BEAT_SIZE_HWORD,
  327. false, // SRCINC
  328. true, // DSTINC
  329. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  330. DMA_STEPSEL_DST // STEPSEL
  331. );
  332. adc1DMARead.startJob();
  333. }
  334. #endif
  335. DMAC->PRICTRL0.bit.RRLVLEN0 = true; // Activate round robin for DMA channels required by ADCs
  336. }
  337. #endif // DMA_IS_REQUIRED
  338. // ------------------------
  339. // Public functions
  340. // ------------------------
  341. // HAL initialization task
  342. void HAL_init() {
  343. TERN_(DMA_IS_REQUIRED, dma_init());
  344. #if ENABLED(SDSUPPORT)
  345. #if SD_CONNECTION_IS(ONBOARD) && PIN_EXISTS(SD_DETECT)
  346. SET_INPUT_PULLUP(SD_DETECT_PIN);
  347. #endif
  348. OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
  349. #endif
  350. }
  351. // HAL idle task
  352. /*
  353. void HAL_idletask() {
  354. }
  355. */
  356. void HAL_clear_reset_source() { }
  357. #pragma push_macro("WDT")
  358. #undef WDT // Required to be able to use '.bit.WDT'. Compiler wrongly replace struct field with WDT define
  359. uint8_t HAL_get_reset_source() {
  360. RSTC_RCAUSE_Type resetCause;
  361. resetCause.reg = REG_RSTC_RCAUSE;
  362. if (resetCause.bit.POR) return RST_POWER_ON;
  363. else if (resetCause.bit.EXT) return RST_EXTERNAL;
  364. else if (resetCause.bit.BODCORE || resetCause.bit.BODVDD) return RST_BROWN_OUT;
  365. else if (resetCause.bit.WDT) return RST_WATCHDOG;
  366. else if (resetCause.bit.SYST || resetCause.bit.NVM) return RST_SOFTWARE;
  367. else if (resetCause.bit.BACKUP) return RST_BACKUP;
  368. return 0;
  369. }
  370. #pragma pop_macro("WDT")
  371. extern "C" {
  372. void * _sbrk(int incr);
  373. extern unsigned int __bss_end__; // end of bss section
  374. }
  375. // Return free memory between end of heap (or end bss) and whatever is current
  376. int freeMemory() {
  377. int free_memory, heap_end = (int)_sbrk(0);
  378. return (int)&free_memory - (heap_end ?: (int)&__bss_end__);
  379. }
  380. // ------------------------
  381. // ADC
  382. // ------------------------
  383. void HAL_adc_init() {
  384. #if ADC_IS_REQUIRED
  385. memset(HAL_adc_results, 0xFF, sizeof(HAL_adc_results)); // Fill result with invalid values
  386. LOOP_L_N(pi, COUNT(adc_pins))
  387. pinPeripheral(adc_pins[pi], PIO_ANALOG);
  388. LOOP_S_LE_N(ai, FIRST_ADC, LAST_ADC) {
  389. Adc* adc = ((Adc*[])ADC_INSTS)[ai];
  390. // ADC clock setup
  391. GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN = false;
  392. SYNC(GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN);
  393. GCLK->PCHCTRL[ADC0_GCLK_ID + ai].reg = GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN; // 48MHz startup code programmed
  394. SYNC(!GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN);
  395. adc->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV32_Val; // 1.5MHZ adc clock
  396. // ADC setup
  397. // Preloaded data (fixed for all ADC instances hence not loaded by DMA)
  398. adc->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val; // VRefA pin
  399. SYNC(adc->SYNCBUSY.bit.REFCTRL);
  400. adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val; // ... ADC_CTRLB_RESSEL_16BIT_Val
  401. SYNC(adc->SYNCBUSY.bit.CTRLB);
  402. adc->SAMPCTRL.bit.SAMPLEN = (6 - 1); // Sampling clocks
  403. //adc->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_16 | ADC_AVGCTRL_ADJRES(4); // 16 Accumulated conversions and shift 4 to get oversampled 12 bits result
  404. //SYNC(adc->SYNCBUSY.bit.AVGCTRL);
  405. // Registers loaded by DMA
  406. adc->DSEQCTRL.bit.INPUTCTRL = true;
  407. adc->DSEQCTRL.bit.AUTOSTART = true; // Start conversion after DMA sequence
  408. adc->CTRLA.bit.ENABLE = true; // Enable ADC
  409. SYNC(adc->SYNCBUSY.bit.ENABLE);
  410. }
  411. #endif // ADC_IS_REQUIRED
  412. }
  413. void HAL_adc_start_conversion(const uint8_t adc_pin) {
  414. #if ADC_IS_REQUIRED
  415. LOOP_L_N(pi, COUNT(adc_pins)) {
  416. if (adc_pin == adc_pins[pi]) {
  417. HAL_adc_result = HAL_adc_results[pi];
  418. return;
  419. }
  420. }
  421. #endif
  422. HAL_adc_result = 0xFFFF;
  423. }
  424. #endif // __SAMD51__