diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 0ec038a586..d6ed0707a9 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -239,6 +239,8 @@ SRC_C = \ timers.c \ usb.c \ usb_mass_storage.c \ + bindings/samd/__init__.c \ + bindings/samd/Clock.c \ boards/$(BOARD)/board.c \ boards/$(BOARD)/pins.c \ lib/oofatfs/ff.c \ diff --git a/ports/atmel-samd/README.rst b/ports/atmel-samd/README.rst index d475e3816d..0c1026644d 100644 --- a/ports/atmel-samd/README.rst +++ b/ports/atmel-samd/README.rst @@ -231,3 +231,9 @@ Mass storage All boards will also show up as a mass storage device. Make sure to eject it before resetting or disconnecting the board. + +Port Specific modules +--------------------- + +.. toctree:: + bindings/samd/__init__ diff --git a/ports/atmel-samd/bindings/samd/Clock.c b/ports/atmel-samd/bindings/samd/Clock.c new file mode 100644 index 0000000000..81e8fb1cec --- /dev/null +++ b/ports/atmel-samd/bindings/samd/Clock.c @@ -0,0 +1,174 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Noralf Trønnes + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "clocks.h" +#include "bindings/samd/Clock.h" + +#include "py/obj.h" +#include "py/objproperty.h" +#include "py/runtime.h" + +//| .. currentmodule:: samd +//| +//| :class:`Clock` --- Clock reference +//| ------------------------------------------ +//| +//| Identifies a clock on the microcontroller. +//| +//| .. class:: Clock +//| +//| Identifies a clock on the microcontroller. They are fixed by the +//| hardware so they cannot be constructed on demand. Instead, use +//| `samd.clock` to reference the desired clock. +//| + +STATIC void samd_clock_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "%q.%q.%s(", MP_QSTR_samd, MP_QSTR_clock, self->name); + if (clock_get_enabled(self->type, self->index)) { + mp_printf(print, "frequency=%u", clock_get_frequency(self->type, self->index)); + uint32_t calibration = clock_get_calibration(self->type, self->index); + if (calibration) { + mp_printf(print, ", calibration=%u", calibration); + } + } + mp_printf(print, ")"); +} + +//| .. attribute:: enabled +//| +//| Is the clock enabled? (read-only) +//| +STATIC mp_obj_t samd_clock_get_enabled(mp_obj_t self_in) { + samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(clock_get_enabled(self->type, self->index)); +} + +MP_DEFINE_CONST_FUN_OBJ_1(samd_clock_get_enabled_obj, samd_clock_get_enabled); + +const mp_obj_property_t samd_clock_enabled_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&samd_clock_get_enabled_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj, + }, +}; + +//| .. attribute:: parent +//| +//| Clock parent. (read-only) +//| +STATIC mp_obj_t samd_clock_get_parent(mp_obj_t self_in) { + samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint8_t p_type, p_index; + if (!clock_get_parent(self->type, self->index, &p_type, &p_index)) + return mp_const_none; + + const mp_map_t* samd_map = &samd_clock_globals.map; + for (uint8_t i = 0; i < samd_map->alloc; i++) { + samd_clock_obj_t *iter = samd_map->table[i].value; + if (iter->type == p_type && iter->index == p_index) + return iter; + } + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_1(samd_clock_get_parent_obj, samd_clock_get_parent); + +const mp_obj_property_t samd_clock_parent_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&samd_clock_get_parent_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj, + }, +}; + +//| .. attribute:: frequency +//| +//| Clock frequency. (read-only) +//| +STATIC mp_obj_t samd_clock_get_frequency(mp_obj_t self_in) { + samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int_from_uint(clock_get_frequency(self->type, self->index)); +} + +MP_DEFINE_CONST_FUN_OBJ_1(samd_clock_get_frequency_obj, samd_clock_get_frequency); + +const mp_obj_property_t samd_clock_frequency_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&samd_clock_get_frequency_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj, + }, +}; + +//| .. attribute:: calibration +//| +//| Clock calibration. Not all clocks can be calibrated. +//| +STATIC mp_obj_t samd_clock_get_calibration(mp_obj_t self_in) { + samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int_from_uint(clock_get_calibration(self->type, self->index)); +} + +MP_DEFINE_CONST_FUN_OBJ_1(samd_clock_get_calibration_obj, samd_clock_get_calibration); + +STATIC mp_obj_t samd_clock_set_calibration(mp_obj_t self_in, mp_obj_t calibration) { + samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in); + int ret = clock_set_calibration(self->type, self->index, mp_obj_get_int(calibration)); + if (ret == -2) + mp_raise_AttributeError("calibration is read only"); + if (ret == -1) + mp_raise_ValueError("calibration is out of range"); + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_2(samd_clock_set_calibration_obj, samd_clock_set_calibration); + +const mp_obj_property_t samd_clock_calibration_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&samd_clock_get_calibration_obj, + (mp_obj_t)&samd_clock_set_calibration_obj, + (mp_obj_t)&mp_const_none_obj, + }, +}; + +STATIC const mp_rom_map_elem_t samd_clock_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&samd_clock_enabled_obj) }, + { MP_ROM_QSTR(MP_QSTR_parent), MP_ROM_PTR(&samd_clock_parent_obj) }, + { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&samd_clock_frequency_obj) }, + { MP_ROM_QSTR(MP_QSTR_calibration), MP_ROM_PTR(&samd_clock_calibration_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(samd_clock_locals_dict, samd_clock_locals_dict_table); + +const mp_obj_type_t samd_clock_type = { + { &mp_type_type }, + .name = MP_QSTR_Clock, + .print = samd_clock_print, + .locals_dict = (mp_obj_t)&samd_clock_locals_dict, +}; diff --git a/ports/atmel-samd/bindings/samd/Clock.h b/ports/atmel-samd/bindings/samd/Clock.h new file mode 100644 index 0000000000..0d13ae2533 --- /dev/null +++ b/ports/atmel-samd/bindings/samd/Clock.h @@ -0,0 +1,77 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Noralf Trønnes + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BINDINGS_SAMD_CLOCK_H +#define MICROPY_INCLUDED_ATMEL_SAMD_BINDINGS_SAMD_CLOCK_H + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + const char *name; + uint8_t type; + uint8_t index; +} samd_clock_obj_t; + +#define CLOCK(_name, _type, _index) \ +const samd_clock_obj_t clock_ ## _name = { \ + { &samd_clock_type }, \ + .name = #_name, \ + .type = _type, \ + .index = _index, \ +} + +#define CLOCK_SOURCE(_name) \ +const samd_clock_obj_t clock_ ## _name = { \ + { &samd_clock_type }, \ + .name = #_name, \ + .type = 0, \ + .index = GCLK_SOURCE_ ## _name, \ +} + +#define CLOCK_GCLK(_name) \ +const samd_clock_obj_t clock_ ## _name = { \ + { &samd_clock_type }, \ + .name = #_name, \ + .type = 1, \ + .index = _name ## _GCLK_ID, \ +} + +#define CLOCK_GCLK_(_name, _extra) \ +const samd_clock_obj_t clock_ ## _name ## _ ## _extra = { \ + { &samd_clock_type }, \ + .name = #_name "_" #_extra, \ + .type = 1, \ + .index = _name ## _GCLK_ID_ ## _extra, \ +} + +#define CLOCK_ENTRY(_name) { MP_ROM_QSTR(MP_QSTR_ ## _name), MP_ROM_PTR(&clock_ ## _name) } +#define CLOCK_ENTRY_(_name, _extra) { MP_ROM_QSTR(MP_QSTR_ ## _name ## _ ## _extra), MP_ROM_PTR(&clock_ ## _name ## _ ## _extra) } + +extern const mp_obj_type_t samd_clock_type; +extern const mp_obj_dict_t samd_clock_globals; + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_BINDINGS_SAMD_CLOCK_H diff --git a/ports/atmel-samd/bindings/samd/__init__.c b/ports/atmel-samd/bindings/samd/__init__.c new file mode 100644 index 0000000000..55a10001d2 --- /dev/null +++ b/ports/atmel-samd/bindings/samd/__init__.c @@ -0,0 +1,72 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Noralf Trønnes + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/obj.h" +#include "py/runtime.h" + +#include "bindings/samd/Clock.h" + +//| :mod:`samd` --- SAMD implementation settings +//| ================================================= +//| +//| .. module:: samd +//| :synopsis: SAMD implementation settings +//| :platform: SAMD21 +//| +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| Clock +//| + +//| :mod:`samd.clock` --- samd clock names +//| -------------------------------------------------------- +//| +//| .. module:: samd.clock +//| :synopsis: samd clock names +//| :platform: SAMD21 +//| +//| References to clocks as named by the microcontroller +//| +const mp_obj_module_t samd_clock_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&samd_clock_globals, +}; + +STATIC const mp_rom_map_elem_t samd_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_samd) }, + { MP_ROM_QSTR(MP_QSTR_clock), MP_ROM_PTR(&samd_clock_module) }, +}; + +STATIC MP_DEFINE_CONST_DICT(samd_module_globals, samd_module_globals_table); + +const mp_obj_module_t samd_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&samd_module_globals, +}; diff --git a/ports/atmel-samd/clocks.h b/ports/atmel-samd/clocks.h index 6a61e49c7f..6b7cfedce0 100644 --- a/ports/atmel-samd/clocks.h +++ b/ports/atmel-samd/clocks.h @@ -64,4 +64,10 @@ static inline bool board_has_crystal(void) { void clock_init(void); +bool clock_get_enabled(uint8_t type, uint8_t index); +bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index); +uint32_t clock_get_frequency(uint8_t type, uint8_t index); +uint32_t clock_get_calibration(uint8_t type, uint8_t index); +int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val); + #endif // MICROPY_INCLUDED_ATMEL_SAMD_CLOCKS_H diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 5ac06944ad..e6c3a201fe 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -167,6 +167,7 @@ extern const struct _mp_obj_module_t math_module; extern const struct _mp_obj_module_t os_module; extern const struct _mp_obj_module_t random_module; extern const struct _mp_obj_module_t rtc_module; +extern const struct _mp_obj_module_t samd_module; extern const struct _mp_obj_module_t storage_module; extern const struct _mp_obj_module_t struct_module; extern const struct _mp_obj_module_t time_module; @@ -236,6 +237,7 @@ extern const struct _mp_obj_module_t usb_hid_module; { MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_rtc), (mp_obj_t)&rtc_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_samd),(mp_obj_t)&samd_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&struct_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_supervisor), (mp_obj_t)&supervisor_module }, \ diff --git a/ports/atmel-samd/samd21_clocks.c b/ports/atmel-samd/samd21_clocks.c index 4fc039a588..0fc4d63e50 100644 --- a/ports/atmel-samd/samd21_clocks.c +++ b/ports/atmel-samd/samd21_clocks.c @@ -28,6 +28,7 @@ #include "hpl_gclk_config.h" +#include "bindings/samd/Clock.h" #include "shared-bindings/microcontroller/__init__.h" #include "py/runtime.h" @@ -135,3 +136,290 @@ void clock_init(void) else enable_clock_generator(2, GCLK_GENCTRL_SRC_OSC32K_Val, 32); } + +static bool clk_enabled(uint8_t clk) { + common_hal_mcu_disable_interrupts(); + *((uint8_t*) &GCLK->CLKCTRL.reg) = clk; + while (GCLK->STATUS.bit.SYNCBUSY == 1) {} + bool enabled = GCLK->CLKCTRL.bit.CLKEN; + common_hal_mcu_enable_interrupts(); + return enabled; +} + +static uint8_t clk_get_generator(uint8_t clk) { + common_hal_mcu_disable_interrupts(); + *((uint8_t*) &GCLK->CLKCTRL.reg) = clk; + while (GCLK->STATUS.bit.SYNCBUSY == 1) {} + uint8_t gen = GCLK->CLKCTRL.bit.GEN; + common_hal_mcu_enable_interrupts(); + return gen; +} + +static uint8_t generator_get_source(uint8_t gen) { + common_hal_mcu_disable_interrupts(); + *((uint8_t*) &GCLK->GENCTRL.reg) = gen; + while (GCLK->STATUS.bit.SYNCBUSY == 1) {} + uint8_t src = GCLK->GENCTRL.bit.SRC; + common_hal_mcu_enable_interrupts(); + return src; +} + +static bool osc_enabled(uint8_t index) { + switch (index) { + case GCLK_SOURCE_XOSC: + return SYSCTRL->XOSC.bit.ENABLE; + // TODO: GCLK_SOURCE_GCLKIN + // TODO: GCLK_SOURCE_GCLKGEN1 + case GCLK_SOURCE_OSCULP32K: + return true; + case GCLK_SOURCE_OSC32K: + return SYSCTRL->OSC32K.bit.ENABLE; + case GCLK_SOURCE_XOSC32K: + return SYSCTRL->XOSC32K.bit.ENABLE; + case GCLK_SOURCE_OSC8M: + return SYSCTRL->OSC8M.bit.ENABLE; + case GCLK_SOURCE_DFLL48M: + return SYSCTRL->DFLLCTRL.bit.ENABLE; + case GCLK_SOURCE_DPLL96M: + return SYSCTRL->DPLLCTRLA.bit.ENABLE; + }; + return false; +} + +static uint32_t osc_get_frequency(uint8_t index) { + switch (index) { + case GCLK_SOURCE_XOSC: + return 0; // unknown 0.4-32MHz + // TODO: GCLK_SOURCE_GCLKIN + // TODO: GCLK_SOURCE_GCLKGEN1 + case GCLK_SOURCE_OSCULP32K: + case GCLK_SOURCE_OSC32K: + case GCLK_SOURCE_XOSC32K: + return 32768; + case GCLK_SOURCE_OSC8M: + return 8000000; + case GCLK_SOURCE_DFLL48M: + return 48000000; + case GCLK_SOURCE_DPLL96M: + return 96000000; + } + return 0; +} + +bool clock_get_enabled(uint8_t type, uint8_t index) { + if (type == 0) + return osc_enabled(index); + if (type == 1) + return clk_enabled(index); + if (type == 2) + return SysTick->CTRL & SysTick_CTRL_ENABLE_Msk; + return false; +} + +bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index) { + if (type == 1 && index <= 0x24 && clk_enabled(index)) { + *p_type = 0; + *p_index = generator_get_source(clk_get_generator(index)); + return true; + } + if (type == 2 && index == 0) { + *p_type = 0; + *p_index = generator_get_source(0); + return true; + } + return false; +} + +uint32_t clock_get_frequency(uint8_t type, uint8_t index) { + if (type == 0) { + return osc_get_frequency(index); + } + if (type == 1) { + if (!clk_enabled(index)) + return 0; + + uint8_t gen = clk_get_generator(index); + + common_hal_mcu_disable_interrupts(); + *((uint8_t*) &GCLK->GENCTRL.reg) = gen; + *((uint8_t*) &GCLK->GENDIV.reg) = gen; + while (GCLK->STATUS.bit.SYNCBUSY == 1) {} + + uint8_t src = GCLK->GENCTRL.bit.SRC; + uint32_t div; + if (GCLK->GENCTRL.bit.DIVSEL) { + div = 1 << (GCLK->GENDIV.bit.DIV + 1); + } else { + div = GCLK->GENDIV.bit.DIV; + if (!div) + div = 1; + } + common_hal_mcu_enable_interrupts(); + + return osc_get_frequency(src) / div; + } + if (type == 2 && index == 0) { + return clock_get_frequency(0, generator_get_source(0)) / SysTick->LOAD; + } + return 0; +} + +uint32_t clock_get_calibration(uint8_t type, uint8_t index) { + if (type == 0) { + switch (index) { + case GCLK_SOURCE_OSCULP32K: + return SYSCTRL->OSCULP32K.bit.CALIB; + case GCLK_SOURCE_OSC32K: + return SYSCTRL->OSC32K.bit.CALIB; + case GCLK_SOURCE_OSC8M: + return SYSCTRL->OSC8M.bit.CALIB; + }; + } + if (type == 2 && index == 0) { + return SysTick->LOAD + 1; + } + return 0; +} + +int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) { + if (type == 0) { + switch (index) { + case GCLK_SOURCE_OSCULP32K: + if (val > 0x1f) + return -1; + SYSCTRL->OSCULP32K.bit.CALIB = val; + return 0; + case GCLK_SOURCE_OSC32K: + if (val > 0x7f) + return -1; + SYSCTRL->OSC32K.bit.CALIB = val; + return 0; + case GCLK_SOURCE_OSC8M: + if (val > 0xfff) + return -1; + SYSCTRL->OSC8M.bit.CALIB = val; + return 0; + }; + } + if (type == 2 && index == 0) { + if (val < 0x1000 || val > 0x1000000) + return -1; + SysTick->LOAD = val - 1; + return 0; + } + return -2; // calibration is read only +} + +#ifdef SAMD21_EXPOSE_ALL_CLOCKS +CLOCK_SOURCE(XOSC); +CLOCK_SOURCE(GCLKIN); +CLOCK_SOURCE(GCLKGEN1); +CLOCK_SOURCE(OSCULP32K); +#endif +CLOCK_SOURCE(OSC32K); +CLOCK_SOURCE(XOSC32K); +#ifdef SAMD21_EXPOSE_ALL_CLOCKS +CLOCK_SOURCE(OSC8M); +CLOCK_SOURCE(DFLL48M); +CLOCK_SOURCE(DPLL96M); + +CLOCK_GCLK_(SYSCTRL, DFLL48); +CLOCK_GCLK_(SYSCTRL, FDPLL); +CLOCK_GCLK_(SYSCTRL, FDPLL32K); +CLOCK_GCLK(WDT); +#endif +CLOCK_GCLK(RTC); +#ifdef SAMD21_EXPOSE_ALL_CLOCKS +CLOCK_GCLK(EIC); +CLOCK_GCLK(USB); +CLOCK_GCLK_(EVSYS, 0); +CLOCK_GCLK_(EVSYS, 1); +CLOCK_GCLK_(EVSYS, 2); +CLOCK_GCLK_(EVSYS, 3); +CLOCK_GCLK_(EVSYS, 4); +CLOCK_GCLK_(EVSYS, 5); +CLOCK_GCLK_(EVSYS, 6); +CLOCK_GCLK_(EVSYS, 7); +CLOCK_GCLK_(EVSYS, 8); +CLOCK_GCLK_(EVSYS, 9); +CLOCK_GCLK_(EVSYS, 10); +CLOCK_GCLK_(EVSYS, 11); +CLOCK(SERCOMx_SLOW, 1, 19); +CLOCK_GCLK_(SERCOM0, CORE); +CLOCK_GCLK_(SERCOM1, CORE); +CLOCK_GCLK_(SERCOM2, CORE); +CLOCK_GCLK_(SERCOM3, CORE); +CLOCK_GCLK_(SERCOM4, CORE); +CLOCK_GCLK_(SERCOM5, CORE); +CLOCK(TCC0_TCC1, 1, 26); +CLOCK(TCC2_TCC3, 1, 27); +CLOCK(TC4_TC5, 1, 28); +CLOCK(TC6_TC7, 1, 29); +CLOCK_GCLK(ADC); +CLOCK_GCLK_(AC, DIG); +CLOCK_GCLK_(AC, ANA); +CLOCK_GCLK(DAC); +CLOCK_GCLK(PTC); +CLOCK_GCLK_(I2S, 0); +CLOCK_GCLK_(I2S, 1); + +CLOCK(SYSTICK, 2, 0); +#endif + +STATIC const mp_rom_map_elem_t samd_clock_global_dict_table[] = { +#ifdef SAMD21_EXPOSE_ALL_CLOCKS + CLOCK_ENTRY(XOSC), + CLOCK_ENTRY(GCLKIN), + CLOCK_ENTRY(GCLKGEN1), + CLOCK_ENTRY(OSCULP32K), +#endif + CLOCK_ENTRY(OSC32K), + CLOCK_ENTRY(XOSC32K), +#ifdef SAMD21_EXPOSE_ALL_CLOCKS + CLOCK_ENTRY(OSC8M), + CLOCK_ENTRY(DFLL48M), + CLOCK_ENTRY(DPLL96M), + CLOCK_ENTRY_(SYSCTRL, DFLL48), + CLOCK_ENTRY_(SYSCTRL, FDPLL), + CLOCK_ENTRY_(SYSCTRL, FDPLL32K), + CLOCK_ENTRY(WDT), +#endif + CLOCK_ENTRY(RTC), +#ifdef SAMD21_EXPOSE_ALL_CLOCKS + CLOCK_ENTRY(EIC), + CLOCK_ENTRY(USB), + CLOCK_ENTRY_(EVSYS, 0), + CLOCK_ENTRY_(EVSYS, 1), + CLOCK_ENTRY_(EVSYS, 2), + CLOCK_ENTRY_(EVSYS, 3), + CLOCK_ENTRY_(EVSYS, 4), + CLOCK_ENTRY_(EVSYS, 5), + CLOCK_ENTRY_(EVSYS, 6), + CLOCK_ENTRY_(EVSYS, 7), + CLOCK_ENTRY_(EVSYS, 8), + CLOCK_ENTRY_(EVSYS, 9), + CLOCK_ENTRY_(EVSYS, 10), + CLOCK_ENTRY_(EVSYS, 11), + CLOCK_ENTRY(SERCOMx_SLOW), + CLOCK_ENTRY_(SERCOM0, CORE), + CLOCK_ENTRY_(SERCOM1, CORE), + CLOCK_ENTRY_(SERCOM2, CORE), + CLOCK_ENTRY_(SERCOM3, CORE), + CLOCK_ENTRY_(SERCOM4, CORE), + CLOCK_ENTRY_(SERCOM5, CORE), + CLOCK_ENTRY(TCC0_TCC1), + CLOCK_ENTRY(TCC2_TCC3), + CLOCK_ENTRY(TC4_TC5), + CLOCK_ENTRY(TC6_TC7), + CLOCK_ENTRY(ADC), + CLOCK_ENTRY_(AC, DIG), + CLOCK_ENTRY_(AC, ANA), + CLOCK_ENTRY(DAC), + CLOCK_ENTRY(PTC), + CLOCK_ENTRY_(I2S, 0), + CLOCK_ENTRY_(I2S, 1), + + CLOCK_ENTRY(SYSTICK), +#endif +}; +MP_DEFINE_CONST_DICT(samd_clock_globals, samd_clock_global_dict_table); diff --git a/ports/atmel-samd/samd51_clocks.c b/ports/atmel-samd/samd51_clocks.c index 72f3de871e..cc3dd7917a 100644 --- a/ports/atmel-samd/samd51_clocks.c +++ b/ports/atmel-samd/samd51_clocks.c @@ -60,3 +60,27 @@ void disable_clock_generator(uint8_t gclk) { GCLK->GENCTRL[gclk].reg = 0; while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {} } + +bool clock_get_enabled(uint8_t type, uint8_t index) { + return false; +} + +bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index) { + return false; +} + +uint32_t clock_get_frequency(uint8_t type, uint8_t index) { + return 0; +} + +uint32_t clock_get_calibration(uint8_t type, uint8_t index) { + return 0; +} + +int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) { + return -2; +} + +STATIC const mp_rom_map_elem_t samd_clock_global_dict_table[] = { +}; +MP_DEFINE_CONST_DICT(samd_clock_globals, samd_clock_global_dict_table);