diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index 2a9608bae75..6fb2f1d67df 100644 --- a/atmel-samd/Makefile +++ b/atmel-samd/Makefile @@ -135,7 +135,9 @@ ifeq ($(DEBUG), 1) # -DMICROPY_DEBUG_MODULES may also be added to an -flto build, if you wish. CFLAGS += -Os -ggdb -DNDEBUG -DENABLE_MICRO_TRACE_BUFFER -DMICROPY_DEBUG_MODULES else -CFLAGS += -Os -DNDEBUG -flto +# -finline-limit can shrink the image size. -finline-limit=80 or so is similar to not having it on. +# There is no simple default value, though. +CFLAGS += -Os -DNDEBUG -flto -finline-limit=57 endif ifneq ($(FROZEN_DIR),) @@ -248,6 +250,7 @@ SRC_COMMON_HAL = \ digitalio/DigitalInOut.c \ microcontroller/__init__.c \ microcontroller/Pin.c \ + microcontroller/Processor.c \ neopixel_write/__init__.c \ nvm/__init__.c \ nvm/ByteArray.c \ diff --git a/atmel-samd/common-hal/microcontroller/Processor.c b/atmel-samd/common-hal/microcontroller/Processor.c new file mode 100644 index 00000000000..a1d5e8c1272 --- /dev/null +++ b/atmel-samd/common-hal/microcontroller/Processor.c @@ -0,0 +1,235 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Dan Halbert 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. + */ + +/* + * Includes code from ASF sample code adc_temp.h and adc_temp.c, + * and so includes this license: + * + * Copyright (C) 2015 Atmel Corporation. All rights reserved. + * + * License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "common-hal/microcontroller/Processor.h" + +// Don't reorder these includes because they are dependencies of adc_feature.h. +// They should really be included by adc_feature.h. +#include +#include "asf/sam0/drivers/system/clock/gclk.h" +#include "asf/sam0/utils/cmsis/samd21/include/component/adc.h" + +#include "asf/sam0/drivers/adc/adc_sam_d_r/adc_feature.h" +#include "asf/sam0/drivers/adc/adc.h" + +#define ADC_TEMP_SAMPLE_LENGTH 4 +#define INT1V_VALUE_FLOAT 1.0 +#define INT1V_DIVIDER_1000 1000.0 +#define ADC_12BIT_FULL_SCALE_VALUE_FLOAT 4095.0 + +typedef struct nvm_calibration_data_t { + float tempR; // Production Room temperature + float tempH; // Production Hot temperature + float INT1VR; // Room temp 2's complement of the internal 1V reference value + float INT1VH; // Hot temp 2's complement of the internal 1V reference value + uint16_t ADCR; // Production Room temperature ADC value + uint16_t ADCH; // Production Hot temperature ADC value + float VADCR; // Room temperature ADC voltage + float VADCH; // Hot temperature ADC voltage +} nvm_calibration_data_t; + + +// Decimal to fraction conversion. (adapted from ASF sample). +STATIC float convert_dec_to_frac(uint8_t val) { + float float_val = (float)val; + if (val < 10) { + return (float_val/10.0); + } else if (val < 100) { + return (float_val/100.0); + } else { + return (float_val/1000.0); + } +} + +STATIC void configure_adc_temp(struct adc_module *adc_instance) { + struct adc_config config_adc; + adc_get_config_defaults(&config_adc); + + // The parameters chosen here are from the temperature example in: + // http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf + // That note also recommends in general: + // "Discard the first conversion result whenever there is a change + // in ADC configuration like voltage reference / ADC channel change." + + config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV16; + config_adc.reference = ADC_REFERENCE_INT1V; + config_adc.positive_input = ADC_POSITIVE_INPUT_TEMP; + config_adc.negative_input = ADC_NEGATIVE_INPUT_GND; + config_adc.sample_length = ADC_TEMP_SAMPLE_LENGTH; + + adc_init(adc_instance, ADC, &config_adc); + + // Oversample and decimate. A higher samplenum produces a more stable result. + ADC->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(2) | ADC_AVGCTRL_SAMPLENUM_4; + //ADC->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(4) | ADC_AVGCTRL_SAMPLENUM_16; +} + +// Extract the production calibration data information from NVM (adapted from ASF sample). +// +STATIC void load_calibration_data(nvm_calibration_data_t *cal) { + volatile uint32_t val1; /* Temperature Log Row Content first 32 bits */ + volatile uint32_t val2; /* Temperature Log Row Content another 32 bits */ + uint8_t room_temp_val_int; /* Integer part of room temperature in °C */ + uint8_t room_temp_val_dec; /* Decimal part of room temperature in °C */ + uint8_t hot_temp_val_int; /* Integer part of hot temperature in °C */ + uint8_t hot_temp_val_dec; /* Decimal part of hot temperature in °C */ + int8_t room_int1v_val; /* internal 1V reference drift at room temperature */ + int8_t hot_int1v_val; /* internal 1V reference drift at hot temperature*/ + + uint32_t *temp_log_row_ptr = (uint32_t *)NVMCTRL_TEMP_LOG; + + val1 = *temp_log_row_ptr; + temp_log_row_ptr++; + val2 = *temp_log_row_ptr; + + room_temp_val_int = (uint8_t)((val1 & NVMCTRL_FUSES_ROOM_TEMP_VAL_INT_Msk) >> NVMCTRL_FUSES_ROOM_TEMP_VAL_INT_Pos); + room_temp_val_dec = (uint8_t)((val1 & NVMCTRL_FUSES_ROOM_TEMP_VAL_DEC_Msk) >> NVMCTRL_FUSES_ROOM_TEMP_VAL_DEC_Pos); + + hot_temp_val_int = (uint8_t)((val1 & NVMCTRL_FUSES_HOT_TEMP_VAL_INT_Msk) >> NVMCTRL_FUSES_HOT_TEMP_VAL_INT_Pos); + hot_temp_val_dec = (uint8_t)((val1 & NVMCTRL_FUSES_HOT_TEMP_VAL_DEC_Msk) >> NVMCTRL_FUSES_HOT_TEMP_VAL_DEC_Pos); + + room_int1v_val = (int8_t)((val1 & NVMCTRL_FUSES_ROOM_INT1V_VAL_Msk) >> NVMCTRL_FUSES_ROOM_INT1V_VAL_Pos); + hot_int1v_val = (int8_t)((val2 & NVMCTRL_FUSES_HOT_INT1V_VAL_Msk) >> NVMCTRL_FUSES_HOT_INT1V_VAL_Pos); + + cal->ADCR = (uint16_t)((val2 & NVMCTRL_FUSES_ROOM_ADC_VAL_Msk) >> NVMCTRL_FUSES_ROOM_ADC_VAL_Pos); + + cal->ADCH = (uint16_t)((val2 & NVMCTRL_FUSES_HOT_ADC_VAL_Msk) >> NVMCTRL_FUSES_HOT_ADC_VAL_Pos); + + cal->tempR = room_temp_val_int + convert_dec_to_frac(room_temp_val_dec); + cal->tempH = hot_temp_val_int + convert_dec_to_frac(hot_temp_val_dec); + + cal->INT1VR = 1 - ((float)room_int1v_val/INT1V_DIVIDER_1000); + cal->INT1VH = 1 - ((float)hot_int1v_val/INT1V_DIVIDER_1000); + + cal->VADCR = ((float)cal->ADCR * cal->INT1VR)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT; + cal->VADCH = ((float)cal->ADCH * cal->INT1VH)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT; +} + +/* + * Calculate fine temperature using Equation1 and Equation + * 1b as mentioned in data sheet section "Temperature Sensor Characteristics" + * of Electrical Characteristics. (adapted from ASF sample code). + */ +STATIC float calculate_temperature(uint16_t raw_code, nvm_calibration_data_t *cal) +{ + float VADC; /* Voltage calculation using ADC result for Coarse Temp calculation */ + float VADCM; /* Voltage calculation using ADC result for Fine Temp calculation. */ + float INT1VM; /* Voltage calculation for reality INT1V value during the ADC conversion */ + + VADC = ((float)raw_code * INT1V_VALUE_FLOAT)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT; + + // Hopefully compiler will remove common subepxressions here. + + /* Coarse Temp Calculation by assume INT1V=1V for this ADC conversion */ + float coarse_temp = cal->tempR + (((cal->tempH - cal->tempR)/(cal->VADCH - cal->VADCR)) * (VADC - cal->VADCR)); + + /* Calculation to find the real INT1V value during the ADC conversion */ + INT1VM = cal->INT1VR + (((cal->INT1VH - cal->INT1VR) * (coarse_temp - cal->tempR))/(cal->tempH - cal->tempR)); + + VADCM = ((float)raw_code * INT1VM)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT; + + /* Fine Temp Calculation by replace INT1V=1V by INT1V = INT1Vm for ADC conversion */ + float fine_temp = cal->tempR + (((cal->tempH - cal->tempR)/(cal->VADCH - cal->VADCR)) * (VADCM - cal->VADCR)); + + return fine_temp; +} + + +// External interface. +// +float common_hal_mcu_processor_get_temperature(void) { + struct adc_module adc_instance_struct; + + system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_TEMPSENSE); + configure_adc_temp(&adc_instance_struct); + nvm_calibration_data_t nvm_calibration_data; + load_calibration_data(&nvm_calibration_data); + + adc_enable(&adc_instance_struct); + + uint16_t data; + enum status_code status; + + // Read twice and discard first result, as recommended in section 14 of + // http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf + // "Discard the first conversion result whenever there is a change in ADC configuration + // like voltage reference / ADC channel change" + // Empirical observation shows the first reading is quite different than subsequent ones. + + adc_start_conversion(&adc_instance_struct); + do { + status = adc_read(&adc_instance_struct, &data); + } while (status == STATUS_BUSY); + + adc_start_conversion(&adc_instance_struct); + do { + status = adc_read(&adc_instance_struct, &data); + } while (status == STATUS_BUSY); + + return calculate_temperature(data, &nvm_calibration_data); +} + + +uint32_t common_hal_mcu_processor_get_frequency(void) { + return system_cpu_clock_get_hz(); +} diff --git a/atmel-samd/common-hal/microcontroller/Processor.h b/atmel-samd/common-hal/microcontroller/Processor.h new file mode 100644 index 00000000000..81f92bb0f6c --- /dev/null +++ b/atmel-samd/common-hal/microcontroller/Processor.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Dan Halbert 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. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H +#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + // Stores no state currently. +} mcu_processor_obj_t; + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H diff --git a/atmel-samd/common-hal/microcontroller/__init__.c b/atmel-samd/common-hal/microcontroller/__init__.c index 2b9cc8bfcd6..84cea008b8d 100644 --- a/atmel-samd/common-hal/microcontroller/__init__.c +++ b/atmel-samd/common-hal/microcontroller/__init__.c @@ -30,6 +30,7 @@ #include "samd21_pins.h" #include "shared-bindings/nvm/ByteArray.h" +#include "shared-bindings/microcontroller/Processor.h" void common_hal_mcu_delay_us(uint32_t delay) { mp_hal_delay_us(delay); @@ -50,8 +51,17 @@ void common_hal_mcu_enable_interrupts(void) { cpu_irq_restore(irq_flags); } +// The singleton microcontroller.Processor object, bound to microcontroller.cpu +// It currently only has properties, and no state. +mcu_processor_obj_t common_hal_mcu_processor_obj = { + .base = { + .type = &mcu_processor_type, + }, +}; + // NVM is only available on Express boards for now. #if CIRCUITPY_INTERNAL_NVM_SIZE > 0 +// The singleton nvm.ByteArray object. nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { .base = { .type = &nvm_bytearray_type, diff --git a/atmel-samd/common-hal/nvm/__init__.c b/atmel-samd/common-hal/nvm/__init__.c index 1b702a1584d..f0792430f01 100644 --- a/atmel-samd/common-hal/nvm/__init__.c +++ b/atmel-samd/common-hal/nvm/__init__.c @@ -1 +1,27 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 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. + */ + // No nvm module functions. diff --git a/esp8266/Makefile b/esp8266/Makefile index 5c32160ccb8..3daff9c62e5 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -101,6 +101,7 @@ SRC_C = \ SRC_COMMON_HAL = \ microcontroller/__init__.c \ microcontroller/Pin.c \ + microcontroller/Processor.c \ analogio/__init__.c \ analogio/AnalogIn.c \ analogio/AnalogOut.c \ diff --git a/esp8266/common-hal/microcontroller/Processor.c b/esp8266/common-hal/microcontroller/Processor.c new file mode 100644 index 00000000000..fb0a3d50ac2 --- /dev/null +++ b/esp8266/common-hal/microcontroller/Processor.c @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Dan Halbert 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 "common-hal/microcontroller/Processor.h" + +#include + +#include "esp_mphal.h" + + +float common_hal_mcu_processor_get_temperature(void) { + return NAN; +} + +uint32_t common_hal_mcu_processor_get_frequency(void) { + return mp_hal_get_cpu_freq(); +} diff --git a/esp8266/common-hal/microcontroller/Processor.h b/esp8266/common-hal/microcontroller/Processor.h new file mode 100644 index 00000000000..8fc59c2cb10 --- /dev/null +++ b/esp8266/common-hal/microcontroller/Processor.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Dan Halbert 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. + */ + +#ifndef MICROPY_INCLUDED_ESP8266_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H +#define MICROPY_INCLUDED_ESP8266_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + // Stores no state currently. +} mcu_processor_obj_t; + +#endif // MICROPY_INCLUDED_ESP8266_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H diff --git a/esp8266/common-hal/microcontroller/__init__.c b/esp8266/common-hal/microcontroller/__init__.c index 4fb5eee6329..6aef23761c8 100644 --- a/esp8266/common-hal/microcontroller/__init__.c +++ b/esp8266/common-hal/microcontroller/__init__.c @@ -25,8 +25,10 @@ */ #include "common-hal/microcontroller/Pin.h" -#include "common-hal/microcontroller/Pin.h" +#include "common-hal/microcontroller/Processor.h" + #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Processor.h" #include "eagle_soc.h" #include "ets_alt_task.h" @@ -52,6 +54,14 @@ void common_hal_mcu_enable_interrupts() { enable_irq(saved_interrupt_state & ~(1 << ETS_LOOP_ITER_BIT)); } +// The singleton microcontroller.Processor object, returned by microcontroller.cpu +// It currently only has properties, and no state. +mcu_processor_obj_t common_hal_mcu_processor_obj = { + .base = { + .type = &mcu_processor_type, + }, +}; + // This macro is used to simplify pin definition in boards//pins.c #define PIN(p_name, p_gpio_number, p_gpio_function, p_peripheral) \ const mcu_pin_obj_t pin_## p_name = { \ diff --git a/esp8266/esp_mphal.c b/esp8266/esp_mphal.c index effed04dda6..748c90292ff 100644 --- a/esp8266/esp_mphal.c +++ b/esp8266/esp_mphal.c @@ -55,6 +55,10 @@ void mp_hal_delay_us(uint32_t us) { } } +uint32_t mp_hal_get_cpu_freq(void) { + return system_get_cpu_freq() * 1000000; +} + int mp_hal_stdin_rx_chr(void) { for (;;) { int c = ringbuf_get(&input_buf); diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index 0939910dcf5..ee23ff05535 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -147,7 +147,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_uart___exit___obj, 4, 4, busio_ //| .. method:: read(nbytes=None) //| //| Read characters. If ``nbytes`` is specified then read at most that many -//| bytes. Otherwise, read everything that has been buffered. +//| bytes. Otherwise, read everything that arrives until the connection +//| times out. Providing the number of bytes expected is highly recommended +//| because it will be faster. //| //| :return: Data read //| :rtype: bytes or None diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst index ab92fd57c43..49b6ce5bc3a 100644 --- a/shared-bindings/index.rst +++ b/shared-bindings/index.rst @@ -12,13 +12,28 @@ limited. For example, a microcontroller without analog features will not have Support Matrix --------------- -=============== ========== ========= =========== ======= ======= =========== ================= =============== ================ ======= ========= ======== ========= ======== ========= ======= ========= -Port `analogio` `audioio` `bitbangio` `board` `busio` `digitalio` `microcontroller` `multiterminal` `neopixel_write` `os` `pulseio` `random` `storage` `time` `touchio` `uheap` `usb_hid` -=============== ========== ========= =========== ======= ======= =========== ================= =============== ================ ======= ========= ======== ========= ======== ========= ======= ========= -SAMD21 **Yes** No No **Yes** **Yes** **Yes** **Yes** No **Yes** **Yes** No **Yes** **Yes** **Yes** **Yes** Debug **Yes** -SAMD21 Express **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** No **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** Debug **Yes** -ESP8266 **Yes** No **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** No **Yes** **Yes** **Yes** No Debug No -=============== ========== ========= =========== ======= ======= =========== ================= =============== ================ ======= ========= ======== ========= ======== ========= ======= ========= +================= ======= ============== ======= +Module / Port SAMD21 SAMD21 Express ESP8266 +================= ======= ============== ======= +`analogio` **Yes** **Yes** **Yes** +`audioio` No **Yes** No +`bitbangio` No **Yes** **Yes** +`board` **Yes** **Yes** **Yes** +`busio` **Yes** **Yes** **Yes** +`digitalio` **Yes** **Yes** **Yes** +`microcontroller` **Yes** **Yes** **Yes** +`multiterminal` No No **Yes** +`neopixel_write` **Yes** **Yes** **Yes** +`nvm` No **Yes** No +`os` **Yes** **Yes** **Yes** +`pulseio` No **Yes** No +`random` **Yes** **Yes** **Yes** +`storage` **Yes** **Yes** **Yes** +`time` **Yes** **Yes** **Yes** +`touchio` **Yes** **Yes** No +`uheap` Debug Debug Debug +`usb_hid` **Yes** **Yes** No +================= ======= ============== ======= Modules --------- diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c new file mode 100644 index 00000000000..0e843bd31d4 --- /dev/null +++ b/shared-bindings/microcontroller/Processor.c @@ -0,0 +1,107 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Dan Halbert 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 "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Processor.h" + +#include +#include + +#include "py/objproperty.h" + +#include "py/objproperty.h" +#include "py/runtime.h" + +//| .. currentmodule:: microcontroller +//| +//| :class:`Processor` --- Microcontroller CPU information and control +//| -------------------------------------------------------- +//| +//| Get information about the microcontroller CPU and control it. +//| +//| Usage:: +//| +//| import microcontroller +//| print(microcontroller.cpu.frequency) +//| print(microcontroller.cpu.temperature) +//| + +//| .. class:: Processor() +//| +//| You cannot create an instance of `microcontroller.Processor`. +//| Use `microcontroller.cpu` to access the sole instance available. +//| + +//| .. attribute:: frequency +//| +//| Return the CPU operating frequency as an int, in Hz. +//| +STATIC mp_obj_t mcu_processor_get_frequency(mp_obj_t self) { + return mp_obj_new_int_from_uint(common_hal_mcu_processor_get_frequency()); +} + +MP_DEFINE_CONST_FUN_OBJ_1(mcu_processor_get_frequency_obj, mcu_processor_get_frequency); + +const mp_obj_property_t mcu_processor_frequency_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&mcu_processor_get_frequency_obj, // getter + (mp_obj_t)&mp_const_none_obj, // no setter + (mp_obj_t)&mp_const_none_obj, // no deleter + }, +}; + +//| .. attribute:: temperature +//| +//| Return the on-chip temperature, in Celsius, as a float. +//| If the temperature is not available, return `None`. +//| +STATIC mp_obj_t mcu_processor_get_temperature(mp_obj_t self) { + float temperature = common_hal_mcu_processor_get_temperature(); + return isnan(temperature) ? mp_const_none : mp_obj_new_float(temperature); +} + +MP_DEFINE_CONST_FUN_OBJ_1(mcu_processor_get_temperature_obj, mcu_processor_get_temperature); + +const mp_obj_property_t mcu_processor_temperature_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&mcu_processor_get_temperature_obj, // getter + (mp_obj_t)&mp_const_none_obj, // no setter + (mp_obj_t)&mp_const_none_obj, // no deleter + }, +}; + +STATIC const mp_rom_map_elem_t mcu_processor_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&mcu_processor_frequency_obj) }, + { MP_ROM_QSTR(MP_QSTR_temperature), MP_ROM_PTR(&mcu_processor_temperature_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mcu_processor_locals_dict, mcu_processor_locals_dict_table); + +const mp_obj_type_t mcu_processor_type = { + { &mp_type_type }, + .name = MP_QSTR_Processor, + .locals_dict = (mp_obj_t)&mcu_processor_locals_dict, +}; diff --git a/shared-bindings/microcontroller/Processor.h b/shared-bindings/microcontroller/Processor.h new file mode 100644 index 00000000000..a79dea47894 --- /dev/null +++ b/shared-bindings/microcontroller/Processor.h @@ -0,0 +1,39 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 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. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PROCESSOR_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PROCESSOR_H + +#include "py/obj.h" + +#include "common-hal/microcontroller/Processor.h" + +const mp_obj_type_t mcu_processor_type; + +uint32_t common_hal_mcu_processor_get_frequency(void); +float common_hal_mcu_processor_get_temperature(void); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PROCESSOR_H diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c index 56d363eed0f..0546ebf30f9 100644 --- a/shared-bindings/microcontroller/__init__.c +++ b/shared-bindings/microcontroller/__init__.c @@ -32,13 +32,17 @@ #include "py/obj.h" #include "py/runtime.h" +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/microcontroller/Processor.h" + #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" -#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Processor.h" + #include "py/runtime.h" -//| :mod:`microcontroller` --- Pin references and core functionality +//| :mod:`microcontroller` --- Pin references and cpu functionality //| ================================================================ //| //| .. module:: microcontroller @@ -56,6 +60,12 @@ //| Pin //| +//| .. attribute:: cpu +//| +//| CPU information and control, such as temperature and clock frequency. +//| This object is the sole instance of `microcontroller.Processor`. +//| + //| .. method:: delay_us(delay) //| //| Dedicated delay method used for very short delays. DO NOT do long delays @@ -92,8 +102,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_enable_interrupts_obj, mcu_enable_interrupt //| .. attribute:: nvm //| -//| Available non-volatile memory. Its a `nvm.ByteArray` when available or -//| ``None`` otherwise. +//| Available non-volatile memory. +//| This object is the sole instance of `nvm.ByteArray` when available or ``None`` otherwise. //| //| :mod:`microcontroller.pin` --- Microcontroller pin names @@ -112,16 +122,19 @@ const mp_obj_module_t mcu_pin_module = { STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_microcontroller) }, + { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&common_hal_mcu_processor_obj) }, { MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_interrupts), MP_ROM_PTR(&mcu_disable_interrupts_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) }, #if CIRCUITPY_INTERNAL_NVM_SIZE > 0 - { MP_ROM_QSTR(MP_QSTR_nvm), &common_hal_mcu_nvm_obj }, + { MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&common_hal_mcu_nvm_obj) }, #else - { MP_ROM_QSTR(MP_QSTR_nvm), &mp_const_none_obj }, + { MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&mp_const_none_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&mcu_pin_type) }, { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&mcu_pin_module) }, + { MP_ROM_QSTR(MP_QSTR_Processor), MP_ROM_PTR(&mcu_processor_type) }, + }; STATIC MP_DEFINE_CONST_DICT(mcu_module_globals, mcu_module_globals_table); diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h index 9bad926cd3d..d43db4bf456 100644 --- a/shared-bindings/microcontroller/__init__.h +++ b/shared-bindings/microcontroller/__init__.h @@ -1,3 +1,4 @@ + /* * This file is part of the MicroPython project, http://micropython.org/ * @@ -30,6 +31,8 @@ #include "py/mpconfig.h" #include "py/obj.h" +#include "common-hal/microcontroller/Processor.h" + extern void common_hal_mcu_delay_us(uint32_t); extern void common_hal_mcu_disable_interrupts(void); @@ -37,6 +40,9 @@ extern void common_hal_mcu_enable_interrupts(void); extern const mp_obj_dict_t mcu_pin_globals; +extern const mcu_processor_obj_t common_hal_mcu_processor_obj; + + #if CIRCUITPY_INTERNAL_NVM_SIZE > 0 #include "common-hal/nvm/ByteArray.h" diff --git a/shared-bindings/nvm/ByteArray.c b/shared-bindings/nvm/ByteArray.c index 0ba511a7799..361d03c55df 100644 --- a/shared-bindings/nvm/ByteArray.c +++ b/shared-bindings/nvm/ByteArray.c @@ -46,12 +46,8 @@ //| .. class:: ByteArray() //| -//| Not currently dynamically supported. Access one through `microcontroller.nvm`. +//| Not currently dynamically supported. Access the sole instance through `microcontroller.nvm`. //| -STATIC mp_obj_t nvm_bytearray_make_new(const mp_obj_type_t *type, - mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { - return mp_const_none; -} //| .. method:: __len__() //| @@ -151,7 +147,6 @@ STATIC mp_obj_t nvm_bytearray_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj const mp_obj_type_t nvm_bytearray_type = { { &mp_type_type }, .name = MP_QSTR_ByteArray, - .make_new = nvm_bytearray_make_new, .subscr = nvm_bytearray_subscr, .unary_op = nvm_bytearray_unary_op, .print = NULL,