My Marlin configs for Fabrikator Mini and CTC i3 Pro B
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

HAL.cpp 20KB

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