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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /**
  23. * SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
  24. */
  25. #ifdef __SAMD51__
  26. #include "../../inc/MarlinConfig.h"
  27. #include <Adafruit_ZeroDMA.h>
  28. #include <wiring_private.h>
  29. #ifdef ADAFRUIT_GRAND_CENTRAL_M4
  30. #if USING_HW_SERIALUSB
  31. DefaultSerial1 MSerial0(false, Serial);
  32. #endif
  33. #if USING_HW_SERIAL0
  34. DefaultSerial2 MSerial1(false, Serial1);
  35. #endif
  36. #if USING_HW_SERIAL1
  37. DefaultSerial3 MSerial2(false, Serial2);
  38. #endif
  39. #if USING_HW_SERIAL2
  40. DefaultSerial4 MSerial3(false, Serial3);
  41. #endif
  42. #if USING_HW_SERIAL3
  43. DefaultSerial5 MSerial4(false, Serial4);
  44. #endif
  45. #endif
  46. #define GET_TEMP_0_ADC() TERN(HAS_TEMP_ADC_0, PIN_TO_ADC(TEMP_0_PIN), -1)
  47. #define GET_TEMP_1_ADC() TERN(HAS_TEMP_ADC_1, PIN_TO_ADC(TEMP_1_PIN), -1)
  48. #define GET_TEMP_2_ADC() TERN(HAS_TEMP_ADC_2, PIN_TO_ADC(TEMP_2_PIN), -1)
  49. #define GET_TEMP_3_ADC() TERN(HAS_TEMP_ADC_3, PIN_TO_ADC(TEMP_3_PIN), -1)
  50. #define GET_TEMP_4_ADC() TERN(HAS_TEMP_ADC_4, PIN_TO_ADC(TEMP_4_PIN), -1)
  51. #define GET_TEMP_5_ADC() TERN(HAS_TEMP_ADC_5, PIN_TO_ADC(TEMP_5_PIN), -1)
  52. #define GET_TEMP_6_ADC() TERN(HAS_TEMP_ADC_6, PIN_TO_ADC(TEMP_6_PIN), -1)
  53. #define GET_TEMP_7_ADC() TERN(HAS_TEMP_ADC_7, PIN_TO_ADC(TEMP_7_PIN), -1)
  54. #define GET_BED_ADC() TERN(HAS_TEMP_ADC_BED, PIN_TO_ADC(TEMP_BED_PIN), -1)
  55. #define GET_CHAMBER_ADC() TERN(HAS_TEMP_ADC_CHAMBER, PIN_TO_ADC(TEMP_CHAMBER_PIN), -1)
  56. #define GET_PROBE_ADC() TERN(HAS_TEMP_ADC_PROBE, PIN_TO_ADC(TEMP_PROBE_PIN), -1)
  57. #define GET_COOLER_ADC() TERN(HAS_TEMP_ADC_COOLER, PIN_TO_ADC(TEMP_COOLER_PIN), -1)
  58. #define GET_BOARD_ADC() TERN(HAS_TEMP_ADC_BOARD, PIN_TO_ADC(TEMP_BOARD_PIN), -1)
  59. #define GET_FILAMENT_WIDTH_ADC() TERN(FILAMENT_WIDTH_SENSOR, PIN_TO_ADC(FILWIDTH_PIN), -1)
  60. #define GET_BUTTONS_ADC() TERN(HAS_ADC_BUTTONS, PIN_TO_ADC(ADC_KEYPAD_PIN), -1)
  61. #define GET_JOY_ADC_X() TERN(HAS_JOY_ADC_X, PIN_TO_ADC(JOY_X_PIN), -1)
  62. #define GET_JOY_ADC_Y() TERN(HAS_JOY_ADC_Y, PIN_TO_ADC(JOY_Y_PIN), -1)
  63. #define GET_JOY_ADC_Z() TERN(HAS_JOY_ADC_Z, PIN_TO_ADC(JOY_Z_PIN), -1)
  64. #define IS_ADC_REQUIRED(n) ( \
  65. GET_TEMP_0_ADC() == n || GET_TEMP_1_ADC() == n || GET_TEMP_2_ADC() == n || GET_TEMP_3_ADC() == n \
  66. || GET_TEMP_4_ADC() == n || GET_TEMP_5_ADC() == n || GET_TEMP_6_ADC() == n || GET_TEMP_7_ADC() == n \
  67. || GET_BED_ADC() == n \
  68. || GET_CHAMBER_ADC() == n \
  69. || GET_PROBE_ADC() == n \
  70. || GET_COOLER_ADC() == n \
  71. || GET_BOARD_ADC() == n \
  72. || GET_FILAMENT_WIDTH_ADC() == n \
  73. || GET_BUTTONS_ADC() == n \
  74. || GET_JOY_ADC_X() == n || GET_JOY_ADC_Y() == n || GET_JOY_ADC_Z() == n \
  75. )
  76. #if IS_ADC_REQUIRED(0)
  77. #define ADC0_IS_REQUIRED 1
  78. #define FIRST_ADC 0
  79. #else
  80. #define FIRST_ADC 1
  81. #endif
  82. #if IS_ADC_REQUIRED(1)
  83. #define ADC1_IS_REQUIRED 1
  84. #define LAST_ADC 1
  85. #else
  86. #define LAST_ADC 0
  87. #endif
  88. #if ADC0_IS_REQUIRED || ADC1_IS_REQUIRED
  89. #define ADC_IS_REQUIRED 1
  90. #define DMA_IS_REQUIRED 1
  91. #endif
  92. enum ADCIndex {
  93. #if GET_TEMP_0_ADC() == 0
  94. TEMP_0,
  95. #endif
  96. #if GET_TEMP_1_ADC() == 0
  97. TEMP_1,
  98. #endif
  99. #if GET_TEMP_2_ADC() == 0
  100. TEMP_2,
  101. #endif
  102. #if GET_TEMP_3_ADC() == 0
  103. TEMP_3,
  104. #endif
  105. #if GET_TEMP_4_ADC() == 0
  106. TEMP_4,
  107. #endif
  108. #if GET_TEMP_5_ADC() == 0
  109. TEMP_5,
  110. #endif
  111. #if GET_TEMP_6_ADC() == 0
  112. TEMP_6,
  113. #endif
  114. #if GET_TEMP_7_ADC() == 0
  115. TEMP_7,
  116. #endif
  117. #if GET_BED_ADC() == 0
  118. TEMP_BED,
  119. #endif
  120. #if GET_CHAMBER_ADC() == 0
  121. TEMP_CHAMBER,
  122. #endif
  123. #if GET_PROBE_ADC() == 0
  124. TEMP_PROBE,
  125. #endif
  126. #if GET_COOLER_ADC() == 0
  127. TEMP_COOLER,
  128. #endif
  129. #if GET_BOARD_ADC() == 0
  130. TEMP_BOARD,
  131. #endif
  132. #if GET_FILAMENT_WIDTH_ADC() == 0
  133. FILWIDTH,
  134. #endif
  135. #if GET_BUTTONS_ADC() == 0
  136. ADC_KEY,
  137. #endif
  138. #if GET_JOY_ADC_X() == 0
  139. JOY_X,
  140. #endif
  141. #if GET_JOY_ADC_Y() == 0
  142. JOY_Y,
  143. #endif
  144. #if GET_JOY_ADC_Z() == 0
  145. JOY_Z,
  146. #endif
  147. #if GET_TEMP_0_ADC() == 1
  148. TEMP_0,
  149. #endif
  150. #if GET_TEMP_1_ADC() == 1
  151. TEMP_1,
  152. #endif
  153. #if GET_TEMP_2_ADC() == 1
  154. TEMP_2,
  155. #endif
  156. #if GET_TEMP_3_ADC() == 1
  157. TEMP_3,
  158. #endif
  159. #if GET_TEMP_4_ADC() == 1
  160. TEMP_4,
  161. #endif
  162. #if GET_TEMP_5_ADC() == 1
  163. TEMP_5,
  164. #endif
  165. #if GET_TEMP_6_ADC() == 1
  166. TEMP_6,
  167. #endif
  168. #if GET_TEMP_7_ADC() == 1
  169. TEMP_7,
  170. #endif
  171. #if GET_BED_ADC() == 1
  172. TEMP_BED,
  173. #endif
  174. #if GET_CHAMBER_ADC() == 1
  175. TEMP_CHAMBER,
  176. #endif
  177. #if GET_PROBE_ADC() == 1
  178. TEMP_PROBE,
  179. #endif
  180. #if GET_COOLER_ADC() == 1
  181. TEMP_COOLER,
  182. #endif
  183. #if GET_BOARD_ADC() == 1
  184. TEMP_BOARD,
  185. #endif
  186. #if GET_FILAMENT_WIDTH_ADC() == 1
  187. FILWIDTH,
  188. #endif
  189. #if GET_BUTTONS_ADC() == 1
  190. ADC_KEY,
  191. #endif
  192. #if GET_JOY_ADC_X() == 1
  193. JOY_X,
  194. #endif
  195. #if GET_JOY_ADC_Y() == 1
  196. JOY_Y,
  197. #endif
  198. #if GET_JOY_ADC_Z() == 1
  199. JOY_Z,
  200. #endif
  201. ADC_COUNT
  202. };
  203. #if ENABLED(USE_WATCHDOG)
  204. #define WDT_TIMEOUT_REG TERN(WATCHDOG_DURATION_8S, WDT_CONFIG_PER_CYC8192, WDT_CONFIG_PER_CYC4096) // 4 or 8 second timeout
  205. void MarlinHAL::watchdog_init() {
  206. // The low-power oscillator used by the WDT runs at 32,768 Hz with
  207. // a 1:32 prescale, thus 1024 Hz, though probably not super precise.
  208. // Setup WDT clocks
  209. MCLK->APBAMASK.bit.OSC32KCTRL_ = true;
  210. MCLK->APBAMASK.bit.WDT_ = true;
  211. OSC32KCTRL->OSCULP32K.bit.EN1K = true; // Enable out 1K (this is what WDT uses)
  212. WDT->CTRLA.bit.ENABLE = false; // Disable watchdog for config
  213. SYNC(WDT->SYNCBUSY.bit.ENABLE);
  214. WDT->INTENCLR.reg = WDT_INTENCLR_EW; // Disable early warning interrupt
  215. WDT->CONFIG.reg = WDT_TIMEOUT_REG; // Set a 4s or 8s period for chip reset
  216. hal.watchdog_refresh();
  217. WDT->CTRLA.reg = WDT_CTRLA_ENABLE; // Start watchdog now in normal mode
  218. SYNC(WDT->SYNCBUSY.bit.ENABLE);
  219. }
  220. // Reset watchdog. MUST be called at least every 4 seconds after the
  221. // first watchdog_init or SAMD will go into emergency procedures.
  222. void MarlinHAL::watchdog_refresh() {
  223. SYNC(WDT->SYNCBUSY.bit.CLEAR); // Test first if previous is 'ongoing' to save time waiting for command execution
  224. WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY;
  225. }
  226. #endif
  227. // ------------------------
  228. // Types
  229. // ------------------------
  230. #if DMA_IS_REQUIRED
  231. // Struct must be 32 bits aligned because of DMA accesses but fields needs to be 8 bits packed
  232. typedef struct __attribute__((aligned(4), packed)) {
  233. ADC_INPUTCTRL_Type INPUTCTRL;
  234. } HAL_DMA_DAC_Registers; // DMA transferred registers
  235. #endif
  236. // ------------------------
  237. // Private Variables
  238. // ------------------------
  239. #if ADC_IS_REQUIRED
  240. // Pins used by ADC inputs. Order must be ADC0 inputs first then ADC1
  241. static constexpr uint8_t adc_pins[ADC_COUNT] = {
  242. // ADC0 pins
  243. #if GET_TEMP_0_ADC() == 0
  244. TEMP_0_PIN,
  245. #endif
  246. #if GET_TEMP_1_ADC() == 0
  247. TEMP_1_PIN,
  248. #endif
  249. #if GET_TEMP_2_ADC() == 0
  250. TEMP_2_PIN,
  251. #endif
  252. #if GET_TEMP_3_ADC() == 0
  253. TEMP_3_PIN,
  254. #endif
  255. #if GET_TEMP_4_ADC() == 0
  256. TEMP_4_PIN,
  257. #endif
  258. #if GET_TEMP_5_ADC() == 0
  259. TEMP_5_PIN,
  260. #endif
  261. #if GET_TEMP_6_ADC() == 0
  262. TEMP_6_PIN,
  263. #endif
  264. #if GET_TEMP_7_ADC() == 0
  265. TEMP_7_PIN,
  266. #endif
  267. #if GET_BED_ADC() == 0
  268. TEMP_BED_PIN,
  269. #endif
  270. #if GET_CHAMBER_ADC() == 0
  271. TEMP_CHAMBER_PIN,
  272. #endif
  273. #if GET_PROBE_ADC() == 0
  274. TEMP_PROBE_PIN,
  275. #endif
  276. #if GET_COOLER_ADC() == 0
  277. TEMP_COOLER_PIN,
  278. #endif
  279. #if GET_BOARD_ADC() == 0
  280. TEMP_BOARD_PIN,
  281. #endif
  282. #if GET_FILAMENT_WIDTH_ADC() == 0
  283. FILWIDTH_PIN,
  284. #endif
  285. #if GET_BUTTONS_ADC() == 0
  286. ADC_KEYPAD_PIN,
  287. #endif
  288. #if GET_JOY_ADC_X() == 0
  289. JOY_X_PIN,
  290. #endif
  291. #if GET_JOY_ADC_Y() == 0
  292. JOY_Y_PIN,
  293. #endif
  294. #if GET_JOY_ADC_Z() == 0
  295. JOY_Z_PIN,
  296. #endif
  297. // ADC1 pins
  298. #if GET_TEMP_0_ADC() == 1
  299. TEMP_0_PIN,
  300. #endif
  301. #if GET_TEMP_1_ADC() == 1
  302. TEMP_1_PIN,
  303. #endif
  304. #if GET_TEMP_2_ADC() == 1
  305. TEMP_2_PIN,
  306. #endif
  307. #if GET_TEMP_3_ADC() == 1
  308. TEMP_3_PIN,
  309. #endif
  310. #if GET_TEMP_4_ADC() == 1
  311. TEMP_4_PIN,
  312. #endif
  313. #if GET_TEMP_5_ADC() == 1
  314. TEMP_5_PIN,
  315. #endif
  316. #if GET_TEMP_6_ADC() == 1
  317. TEMP_6_PIN,
  318. #endif
  319. #if GET_TEMP_7_ADC() == 1
  320. TEMP_7_PIN,
  321. #endif
  322. #if GET_BED_ADC() == 1
  323. TEMP_BED_PIN,
  324. #endif
  325. #if GET_CHAMBER_ADC() == 1
  326. TEMP_CHAMBER_PIN,
  327. #endif
  328. #if GET_PROBE_ADC() == 1
  329. TEMP_PROBE_PIN,
  330. #endif
  331. #if GET_COOLER_ADC() == 1
  332. TEMP_COOLER_PIN,
  333. #endif
  334. #if GET_BOARD_ADC() == 1
  335. TEMP_BOARD_PIN,
  336. #endif
  337. #if GET_FILAMENT_WIDTH_ADC() == 1
  338. FILWIDTH_PIN,
  339. #endif
  340. #if GET_BUTTONS_ADC() == 1
  341. ADC_KEYPAD_PIN,
  342. #endif
  343. #if GET_JOY_ADC_X() == 1
  344. JOY_X_PIN,
  345. #endif
  346. #if GET_JOY_ADC_Y() == 1
  347. JOY_Y_PIN,
  348. #endif
  349. #if GET_JOY_ADC_Z() == 1
  350. JOY_Z_PIN,
  351. #endif
  352. };
  353. static uint16_t adc_results[ADC_COUNT];
  354. #if ADC0_IS_REQUIRED
  355. Adafruit_ZeroDMA adc0DMAProgram, adc0DMARead;
  356. static constexpr HAL_DMA_DAC_Registers adc0_dma_regs_list[ADC_COUNT] = {
  357. #if GET_TEMP_0_ADC() == 0
  358. { PIN_TO_INPUTCTRL(TEMP_0_PIN) },
  359. #endif
  360. #if GET_TEMP_1_ADC() == 0
  361. { PIN_TO_INPUTCTRL(TEMP_1_PIN) },
  362. #endif
  363. #if GET_TEMP_2_ADC() == 0
  364. { PIN_TO_INPUTCTRL(TEMP_2_PIN) },
  365. #endif
  366. #if GET_TEMP_3_ADC() == 0
  367. { PIN_TO_INPUTCTRL(TEMP_3_PIN) },
  368. #endif
  369. #if GET_TEMP_4_ADC() == 0
  370. { PIN_TO_INPUTCTRL(TEMP_4_PIN) },
  371. #endif
  372. #if GET_TEMP_5_ADC() == 0
  373. { PIN_TO_INPUTCTRL(TEMP_5_PIN) },
  374. #endif
  375. #if GET_TEMP_6_ADC() == 0
  376. { PIN_TO_INPUTCTRL(TEMP_6_PIN) },
  377. #endif
  378. #if GET_TEMP_7_ADC() == 0
  379. { PIN_TO_INPUTCTRL(TEMP_7_PIN) },
  380. #endif
  381. #if GET_BED_ADC() == 0
  382. { PIN_TO_INPUTCTRL(TEMP_BED_PIN) },
  383. #endif
  384. #if GET_CHAMBER_ADC() == 0
  385. { PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
  386. #endif
  387. #if GET_PROBE_ADC() == 0
  388. { PIN_TO_INPUTCTRL(TEMP_PROBE_PIN) },
  389. #endif
  390. #if GET_COOLER_ADC() == 0
  391. { PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
  392. #endif
  393. #if GET_BOARD_ADC() == 0
  394. { PIN_TO_INPUTCTRL(TEMP_BOARD_PIN) },
  395. #endif
  396. #if GET_FILAMENT_WIDTH_ADC() == 0
  397. { PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
  398. #endif
  399. #if GET_BUTTONS_ADC() == 0
  400. { PIN_TO_INPUTCTRL(ADC_KEYPAD_PIN) },
  401. #endif
  402. #if GET_JOY_ADC_X() == 0
  403. { PIN_TO_INPUTCTRL(JOY_X_PIN) },
  404. #endif
  405. #if GET_JOY_ADC_Y() == 0
  406. { PIN_TO_INPUTCTRL(JOY_Y_PIN) },
  407. #endif
  408. #if GET_JOY_ADC_Z() == 0
  409. { PIN_TO_INPUTCTRL(JOY_Z_PIN) },
  410. #endif
  411. };
  412. #define ADC0_AINCOUNT COUNT(adc0_dma_regs_list)
  413. #endif // ADC0_IS_REQUIRED
  414. #if ADC1_IS_REQUIRED
  415. Adafruit_ZeroDMA adc1DMAProgram, adc1DMARead;
  416. static constexpr HAL_DMA_DAC_Registers adc1_dma_regs_list[ADC_COUNT] = {
  417. #if GET_TEMP_0_ADC() == 1
  418. { PIN_TO_INPUTCTRL(TEMP_0_PIN) },
  419. #endif
  420. #if GET_TEMP_1_ADC() == 1
  421. { PIN_TO_INPUTCTRL(TEMP_1_PIN) },
  422. #endif
  423. #if GET_TEMP_2_ADC() == 1
  424. { PIN_TO_INPUTCTRL(TEMP_2_PIN) },
  425. #endif
  426. #if GET_TEMP_3_ADC() == 1
  427. { PIN_TO_INPUTCTRL(TEMP_3_PIN) },
  428. #endif
  429. #if GET_TEMP_4_ADC() == 1
  430. { PIN_TO_INPUTCTRL(TEMP_4_PIN) },
  431. #endif
  432. #if GET_TEMP_5_ADC() == 1
  433. { PIN_TO_INPUTCTRL(TEMP_5_PIN) },
  434. #endif
  435. #if GET_TEMP_6_ADC() == 1
  436. { PIN_TO_INPUTCTRL(TEMP_6_PIN) },
  437. #endif
  438. #if GET_TEMP_7_ADC() == 1
  439. { PIN_TO_INPUTCTRL(TEMP_7_PIN) },
  440. #endif
  441. #if GET_BED_ADC() == 1
  442. { PIN_TO_INPUTCTRL(TEMP_BED_PIN) },
  443. #endif
  444. #if GET_CHAMBER_ADC() == 1
  445. { PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
  446. #endif
  447. #if GET_PROBE_ADC() == 1
  448. { PIN_TO_INPUTCTRL(TEMP_PROBE_PIN) },
  449. #endif
  450. #if GET_COOLER_ADC() == 1
  451. { PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
  452. #endif
  453. #if GET_BOARD_ADC() == 1
  454. { PIN_TO_INPUTCTRL(TEMP_BOARD_PIN) },
  455. #endif
  456. #if GET_FILAMENT_WIDTH_ADC() == 1
  457. { PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
  458. #endif
  459. #if GET_BUTTONS_ADC() == 1
  460. { PIN_TO_INPUTCTRL(ADC_KEYPAD_PIN) },
  461. #endif
  462. #if GET_JOY_ADC_X() == 1
  463. { PIN_TO_INPUTCTRL(JOY_X_PIN) },
  464. #endif
  465. #if GET_JOY_ADC_Y() == 1
  466. { PIN_TO_INPUTCTRL(JOY_Y_PIN) },
  467. #endif
  468. #if GET_JOY_ADC_Z() == 1
  469. { PIN_TO_INPUTCTRL(JOY_Z_PIN) },
  470. #endif
  471. };
  472. #define ADC1_AINCOUNT COUNT(adc1_dma_regs_list)
  473. #endif // ADC1_IS_REQUIRED
  474. #endif // ADC_IS_REQUIRED
  475. // ------------------------
  476. // Private functions
  477. // ------------------------
  478. void MarlinHAL::dma_init() {
  479. #if DMA_IS_REQUIRED
  480. DmacDescriptor *descriptor;
  481. #if ADC0_IS_REQUIRED
  482. adc0DMAProgram.setTrigger(ADC0_DMAC_ID_SEQ);
  483. adc0DMAProgram.setAction(DMA_TRIGGER_ACTON_BEAT);
  484. adc0DMAProgram.loop(true);
  485. if (adc0DMAProgram.allocate() == DMA_STATUS_OK) {
  486. descriptor = adc0DMAProgram.addDescriptor(
  487. (void *)adc0_dma_regs_list, // SRC
  488. (void *)&ADC0->DSEQDATA.reg, // DEST
  489. sizeof(adc0_dma_regs_list) / 4, // CNT
  490. DMA_BEAT_SIZE_WORD,
  491. true, // SRCINC
  492. false, // DSTINC
  493. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  494. DMA_STEPSEL_SRC // STEPSEL
  495. );
  496. if (descriptor)
  497. descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
  498. adc0DMAProgram.startJob();
  499. }
  500. adc0DMARead.setTrigger(ADC0_DMAC_ID_RESRDY);
  501. adc0DMARead.setAction(DMA_TRIGGER_ACTON_BEAT);
  502. adc0DMARead.loop(true);
  503. if (adc0DMARead.allocate() == DMA_STATUS_OK) {
  504. adc0DMARead.addDescriptor(
  505. (void *)&ADC0->RESULT.reg, // SRC
  506. &adc_results, // DEST
  507. ADC0_AINCOUNT, // CNT
  508. DMA_BEAT_SIZE_HWORD,
  509. false, // SRCINC
  510. true, // DSTINC
  511. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  512. DMA_STEPSEL_DST // STEPSEL
  513. );
  514. adc0DMARead.startJob();
  515. }
  516. #endif
  517. #if ADC1_IS_REQUIRED
  518. adc1DMAProgram.setTrigger(ADC1_DMAC_ID_SEQ);
  519. adc1DMAProgram.setAction(DMA_TRIGGER_ACTON_BEAT);
  520. adc1DMAProgram.loop(true);
  521. if (adc1DMAProgram.allocate() == DMA_STATUS_OK) {
  522. descriptor = adc1DMAProgram.addDescriptor(
  523. (void *)adc1_dma_regs_list, // SRC
  524. (void *)&ADC1->DSEQDATA.reg, // DEST
  525. sizeof(adc1_dma_regs_list) / 4, // CNT
  526. DMA_BEAT_SIZE_WORD,
  527. true, // SRCINC
  528. false, // DSTINC
  529. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  530. DMA_STEPSEL_SRC // STEPSEL
  531. );
  532. if (descriptor)
  533. descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
  534. adc1DMAProgram.startJob();
  535. }
  536. adc1DMARead.setTrigger(ADC1_DMAC_ID_RESRDY);
  537. adc1DMARead.setAction(DMA_TRIGGER_ACTON_BEAT);
  538. adc1DMARead.loop(true);
  539. if (adc1DMARead.allocate() == DMA_STATUS_OK) {
  540. adc1DMARead.addDescriptor(
  541. (void *)&ADC1->RESULT.reg, // SRC
  542. &adc_results[ADC0_AINCOUNT], // DEST
  543. ADC1_AINCOUNT, // CNT
  544. DMA_BEAT_SIZE_HWORD,
  545. false, // SRCINC
  546. true, // DSTINC
  547. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  548. DMA_STEPSEL_DST // STEPSEL
  549. );
  550. adc1DMARead.startJob();
  551. }
  552. #endif
  553. DMAC->PRICTRL0.bit.RRLVLEN0 = true; // Activate round robin for DMA channels required by ADCs
  554. #endif // DMA_IS_REQUIRED
  555. }
  556. // ------------------------
  557. // Public functions
  558. // ------------------------
  559. // HAL initialization task
  560. void MarlinHAL::init() {
  561. TERN_(DMA_IS_REQUIRED, dma_init());
  562. #if ENABLED(SDSUPPORT)
  563. #if HAS_SD_DETECT && SD_CONNECTION_IS(ONBOARD)
  564. SET_INPUT_PULLUP(SD_DETECT_PIN);
  565. #endif
  566. OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
  567. #endif
  568. }
  569. #pragma push_macro("WDT")
  570. #undef WDT // Required to be able to use '.bit.WDT'. Compiler wrongly replace struct field with WDT define
  571. uint8_t MarlinHAL::get_reset_source() {
  572. RSTC_RCAUSE_Type resetCause;
  573. resetCause.reg = REG_RSTC_RCAUSE;
  574. if (resetCause.bit.POR) return RST_POWER_ON;
  575. else if (resetCause.bit.EXT) return RST_EXTERNAL;
  576. else if (resetCause.bit.BODCORE || resetCause.bit.BODVDD) return RST_BROWN_OUT;
  577. else if (resetCause.bit.WDT) return RST_WATCHDOG;
  578. else if (resetCause.bit.SYST || resetCause.bit.NVM) return RST_SOFTWARE;
  579. else if (resetCause.bit.BACKUP) return RST_BACKUP;
  580. return 0;
  581. }
  582. #pragma pop_macro("WDT")
  583. void MarlinHAL::reboot() { NVIC_SystemReset(); }
  584. extern "C" {
  585. void * _sbrk(int incr);
  586. extern unsigned int __bss_end__; // end of bss section
  587. }
  588. // Return free memory between end of heap (or end bss) and whatever is current
  589. int freeMemory() {
  590. int free_memory, heap_end = (int)_sbrk(0);
  591. return (int)&free_memory - (heap_end ?: (int)&__bss_end__);
  592. }
  593. // ------------------------
  594. // ADC
  595. // ------------------------
  596. uint16_t MarlinHAL::adc_result;
  597. void MarlinHAL::adc_init() {
  598. #if ADC_IS_REQUIRED
  599. memset(adc_results, 0xFF, sizeof(adc_results)); // Fill result with invalid values
  600. LOOP_L_N(pi, COUNT(adc_pins))
  601. pinPeripheral(adc_pins[pi], PIO_ANALOG);
  602. LOOP_S_LE_N(ai, FIRST_ADC, LAST_ADC) {
  603. Adc* adc = ((Adc*[])ADC_INSTS)[ai];
  604. // ADC clock setup
  605. GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN = false;
  606. SYNC(GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN);
  607. GCLK->PCHCTRL[ADC0_GCLK_ID + ai].reg = GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN; // 48MHz startup code programmed
  608. SYNC(!GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN);
  609. adc->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV32_Val; // 1.5MHZ adc clock
  610. // ADC setup
  611. // Preloaded data (fixed for all ADC instances hence not loaded by DMA)
  612. adc->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val; // VRefA pin
  613. SYNC(adc->SYNCBUSY.bit.REFCTRL);
  614. adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val; // ... ADC_CTRLB_RESSEL_16BIT_Val
  615. SYNC(adc->SYNCBUSY.bit.CTRLB);
  616. adc->SAMPCTRL.bit.SAMPLEN = (6 - 1); // Sampling clocks
  617. //adc->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_16 | ADC_AVGCTRL_ADJRES(4); // 16 Accumulated conversions and shift 4 to get oversampled 12 bits result
  618. //SYNC(adc->SYNCBUSY.bit.AVGCTRL);
  619. // Registers loaded by DMA
  620. adc->DSEQCTRL.bit.INPUTCTRL = true;
  621. adc->DSEQCTRL.bit.AUTOSTART = true; // Start conversion after DMA sequence
  622. adc->CTRLA.bit.ENABLE = true; // Enable ADC
  623. SYNC(adc->SYNCBUSY.bit.ENABLE);
  624. }
  625. #endif // ADC_IS_REQUIRED
  626. }
  627. void MarlinHAL::adc_start(const pin_t pin) {
  628. #if ADC_IS_REQUIRED
  629. LOOP_L_N(pi, COUNT(adc_pins))
  630. if (pin == adc_pins[pi]) { adc_result = adc_results[pi]; return; }
  631. #endif
  632. adc_result = 0xFFFF;
  633. }
  634. #endif // __SAMD51__