From ae30a1e5aa198bdeee7dce04194b027ff4e3d65a Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Sat, 14 Sep 2019 12:40:24 -0700 Subject: Refine _bleio This PR refines the _bleio API. It was originally motivated by the addition of a new CircuitPython service that enables reading and modifying files on the device. Moving the BLE lifecycle outside of the VM motivated a number of changes to remove heap allocations in some APIs. It also motivated unifying connection initiation to the Adapter class rather than the Central and Peripheral classes which have been removed. Adapter now handles the GAP portion of BLE including advertising, which has moved but is largely unchanged, and scanning, which has been enhanced to return an iterator of filtered results. Once a connection is created (either by us (aka Central) or a remote device (aka Peripheral)) it is represented by a new Connection class. This class knows the current connection state and can discover and instantiate remote Services along with their Characteristics and Descriptors. Relates to #586 --- shared-module/_bleio/ScanEntry.c | 43 +++++++++++- shared-module/_bleio/ScanEntry.h | 7 +- shared-module/_bleio/ScanResults.c | 138 +++++++++++++++++++++++++++++++++++++ shared-module/_bleio/ScanResults.h | 64 +++++++++++++++++ 4 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 shared-module/_bleio/ScanResults.c create mode 100644 shared-module/_bleio/ScanResults.h (limited to 'shared-module') diff --git a/shared-module/_bleio/ScanEntry.c b/shared-module/_bleio/ScanEntry.c index 8dfa17f31..785209c4a 100644 --- a/shared-module/_bleio/ScanEntry.c +++ b/shared-module/_bleio/ScanEntry.c @@ -37,9 +37,50 @@ mp_obj_t common_hal_bleio_scanentry_get_address(bleio_scanentry_obj_t *self) { } mp_obj_t common_hal_bleio_scanentry_get_advertisement_bytes(bleio_scanentry_obj_t *self) { - return self->data; + return MP_OBJ_FROM_PTR(self->data); } mp_int_t common_hal_bleio_scanentry_get_rssi(bleio_scanentry_obj_t *self) { return self->rssi; } + +bool common_hal_bleio_scanentry_get_connectable(bleio_scanentry_obj_t *self) { + return self->connectable; +} + +bool common_hal_bleio_scanentry_get_scan_response(bleio_scanentry_obj_t *self) { + return self->scan_response; +} + +bool bleio_scanentry_data_matches(const uint8_t* data, size_t len, const uint8_t* prefixes, size_t prefixes_length, bool any) { + if (prefixes_length == 0) { + return true; + } + size_t i = 0; + while(i < prefixes_length) { + uint8_t prefix_length = prefixes[i]; + i += 1; + size_t j = 0; + while (j < len) { + uint8_t structure_length = data[j]; + j += 1; + if (structure_length == 0) { + break; + } + if (structure_length >= prefix_length && memcmp(data + j, prefixes + i, prefix_length) == 0) { + if (any) { + return true; + } + } else if (!any) { + return false; + } + j += structure_length; + } + i += prefix_length; + } + return !any; +} + +bool common_hal_bleio_scanentry_matches(bleio_scanentry_obj_t *self, const uint8_t* prefixes, size_t prefixes_len, bool all) { + return bleio_scanentry_data_matches(self->data->data, self->data->len, prefixes, prefixes_len, !all); +} diff --git a/shared-module/_bleio/ScanEntry.h b/shared-module/_bleio/ScanEntry.h index 1e798d78f..94361a397 100644 --- a/shared-module/_bleio/ScanEntry.h +++ b/shared-module/_bleio/ScanEntry.h @@ -29,14 +29,19 @@ #define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H #include "py/obj.h" +#include "py/objstr.h" #include "shared-bindings/_bleio/Address.h" typedef struct { mp_obj_base_t base; bool connectable; + bool scan_response; int8_t rssi; bleio_address_obj_t *address; - mp_obj_t data; + mp_obj_str_t *data; + uint64_t time_received; } bleio_scanentry_obj_t; +bool bleio_scanentry_data_matches(const uint8_t* data, size_t len, const uint8_t* prefixes, size_t prefix_length, bool any); + #endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H diff --git a/shared-module/_bleio/ScanResults.c b/shared-module/_bleio/ScanResults.c new file mode 100644 index 000000000..9f23a836c --- /dev/null +++ b/shared-module/_bleio/ScanResults.c @@ -0,0 +1,138 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2017 Glenn Ruben Bakke + * + * 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 + +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/ScanEntry.h" +#include "shared-bindings/_bleio/ScanResults.h" + +bleio_scanresults_obj_t* shared_module_bleio_new_scanresults(size_t buffer_size, uint8_t* prefixes, size_t prefixes_len, mp_int_t minimum_rssi) { + bleio_scanresults_obj_t* self = m_new_obj(bleio_scanresults_obj_t); + self->base.type = &bleio_scanresults_type; + ringbuf_alloc(&self->buf, buffer_size, false); + self->prefixes = prefixes; + self->prefix_length = prefixes_len; + self->minimum_rssi = minimum_rssi; + return self; +} + +mp_obj_t common_hal_bleio_scanresults_next(bleio_scanresults_obj_t *self) { + while (ringbuf_count(&self->buf) == 0 && !self->done && !mp_exception_pending()) { + RUN_BACKGROUND_TASKS; + } + if (ringbuf_count(&self->buf) == 0 || mp_exception_pending()) { + return mp_const_none; + } + + // Create a ScanEntry out of the data on the buffer. + uint8_t type = ringbuf_get(&self->buf); + bool connectable = (type & (1 << 0)) != 0; + bool scan_response = (type & (1 << 1)) != 0; + uint64_t ticks_ms; + ringbuf_get_n(&self->buf, (uint8_t*) &ticks_ms, sizeof(ticks_ms)); + uint8_t rssi = ringbuf_get(&self->buf); + uint8_t peer_addr[NUM_BLEIO_ADDRESS_BYTES]; + ringbuf_get_n(&self->buf, peer_addr, sizeof(peer_addr)); + uint8_t addr_type = ringbuf_get(&self->buf); + uint16_t len; + ringbuf_get_n(&self->buf, (uint8_t*) &len, sizeof(len)); + + mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_bytes_of_zeros(len)); + ringbuf_get_n(&self->buf, (uint8_t*) o->data, len); + + bleio_scanentry_obj_t *entry = m_new_obj(bleio_scanentry_obj_t); + entry->base.type = &bleio_scanentry_type; + entry->rssi = rssi; + + bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t); + address->base.type = &bleio_address_type; + common_hal_bleio_address_construct(MP_OBJ_TO_PTR(address), peer_addr, addr_type); + entry->address = address; + + entry->data = o; + entry->time_received = ticks_ms; + entry->connectable = connectable; + entry->scan_response = scan_response; + + return MP_OBJ_FROM_PTR(entry); +} + + +void shared_module_bleio_scanresults_append(bleio_scanresults_obj_t* self, + uint64_t ticks_ms, + bool connectable, + bool scan_response, + int8_t rssi, + uint8_t *peer_addr, + uint8_t addr_type, + uint8_t *data, + uint16_t len) { + int32_t packet_size = sizeof(uint8_t) + sizeof(ticks_ms) + sizeof(rssi) + NUM_BLEIO_ADDRESS_BYTES + + sizeof(addr_type) + sizeof(len) + len; + int32_t empty_space = self->buf.size - ringbuf_count(&self->buf); + if (packet_size >= empty_space) { + // We can't fit the packet so skip it. + return; + } + // Filter the packet. + if (rssi < self->minimum_rssi) { + return; + } + + // If any prefixes are provided, then only include packets that include at least one of them. + if (!bleio_scanentry_data_matches(data, len, self->prefixes, self->prefix_length, true)) { + return; + } + uint8_t type = 0; + if (connectable) { + type |= 1 << 0; + } + if (scan_response) { + type |= 1 << 1; + } + + // Add the packet to the buffer. + ringbuf_put(&self->buf, type); + ringbuf_put_n(&self->buf, (uint8_t*) &ticks_ms, sizeof(ticks_ms)); + ringbuf_put(&self->buf, rssi); + ringbuf_put_n(&self->buf, peer_addr, NUM_BLEIO_ADDRESS_BYTES); + ringbuf_put(&self->buf, addr_type); + ringbuf_put_n(&self->buf, (uint8_t*) &len, sizeof(len)); + ringbuf_put_n(&self->buf, data, len); +} + +bool shared_module_bleio_scanresults_get_done(bleio_scanresults_obj_t* self) { + return self->done; +} + +void shared_module_bleio_scanresults_set_done(bleio_scanresults_obj_t* self, bool done) { + self->done = done; + self->common_hal_data = NULL; +} diff --git a/shared-module/_bleio/ScanResults.h b/shared-module/_bleio/ScanResults.h new file mode 100644 index 000000000..8912357a9 --- /dev/null +++ b/shared-module/_bleio/ScanResults.h @@ -0,0 +1,64 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * 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_MODULE_BLEIO_SCANRESULTS_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANRESULTS_H + +#include + +#include "py/obj.h" +#include "py/ringbuf.h" + +typedef struct { + mp_obj_base_t base; + // Pointers that needs to live until the scan is done. + void* common_hal_data; + ringbuf_t buf; + // Prefixes is a length encoded array of prefixes. + uint8_t* prefixes; + size_t prefix_length; + mp_int_t minimum_rssi; + bool active; + bool done; +} bleio_scanresults_obj_t; + +bleio_scanresults_obj_t* shared_module_bleio_new_scanresults(size_t buffer_size, uint8_t* prefixes, size_t prefixes_len, mp_int_t minimum_rssi); + +bool shared_module_bleio_scanresults_get_done(bleio_scanresults_obj_t* self); +void shared_module_bleio_scanresults_set_done(bleio_scanresults_obj_t* self, bool done); + +void shared_module_bleio_scanresults_append(bleio_scanresults_obj_t* self, + uint64_t ticks_ms, + bool connectable, + bool scan_result, + int8_t rssi, + uint8_t *peer_addr, + uint8_t addr_type, + uint8_t* data, + uint16_t len); + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANRESULTS_H -- cgit v1.2.3 From ece8352126e34c5437080e9343f469f2f5e1bfe9 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 22 Oct 2019 17:24:04 -0700 Subject: Fix build by removing unused vars --- shared-module/_bleio/ScanResults.c | 5 +++-- supervisor/shared/bluetooth.c | 19 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'shared-module') diff --git a/shared-module/_bleio/ScanResults.c b/shared-module/_bleio/ScanResults.c index 9f23a836c..7ea0c165f 100644 --- a/shared-module/_bleio/ScanResults.c +++ b/shared-module/_bleio/ScanResults.c @@ -28,6 +28,7 @@ #include +#include "lib/utils/interrupt_char.h" #include "py/objstr.h" #include "py/runtime.h" #include "shared-bindings/_bleio/ScanEntry.h" @@ -44,10 +45,10 @@ bleio_scanresults_obj_t* shared_module_bleio_new_scanresults(size_t buffer_size, } mp_obj_t common_hal_bleio_scanresults_next(bleio_scanresults_obj_t *self) { - while (ringbuf_count(&self->buf) == 0 && !self->done && !mp_exception_pending()) { + while (ringbuf_count(&self->buf) == 0 && !self->done && !mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; } - if (ringbuf_count(&self->buf) == 0 || mp_exception_pending()) { + if (ringbuf_count(&self->buf) == 0 || mp_hal_is_interrupted()) { return mp_const_none; } diff --git a/supervisor/shared/bluetooth.c b/supervisor/shared/bluetooth.c index 64f3b55eb..02258de74 100644 --- a/supervisor/shared/bluetooth.c +++ b/supervisor/shared/bluetooth.c @@ -87,7 +87,7 @@ void supervisor_start_bluetooth(void) { characteristic_list.items = characteristic_list_items; mp_seq_clear(characteristic_list.items, 0, characteristic_list.alloc, sizeof(*characteristic_list.items)); - const uint32_t err_code = _common_hal_bleio_service_construct(&supervisor_ble_service, &supervisor_ble_service_uuid, false /* is secondary */, &characteristic_list); + _common_hal_bleio_service_construct(&supervisor_ble_service, &supervisor_ble_service_uuid, false /* is secondary */, &characteristic_list); // File length supervisor_ble_version_uuid.base.type = &bleio_uuid_type; @@ -186,7 +186,7 @@ void open_current_file(void) { path[length] = '\0'; FATFS *fs = &((fs_user_mount_t *) MP_STATE_VM(vfs_mount_table)->obj)->fatfs; - FRESULT result = f_open(fs, &active_file, (char*) path, FA_READ | FA_WRITE); + f_open(fs, &active_file, (char*) path, FA_READ | FA_WRITE); update_file_length(); } @@ -246,7 +246,6 @@ void supervisor_bluetooth_background(void) { //uint32_t data_shift_length = fileLength - offset - remove_length; int32_t data_shift = insert_length - remove_length; uint32_t new_length = file_length + data_shift; - FRESULT result; // TODO: Make these loops smarter to read and write on sector boundaries. if (data_shift < 0) { @@ -254,32 +253,32 @@ void supervisor_bluetooth_background(void) { uint8_t data; UINT actual; f_lseek(&active_file, shift_offset - data_shift); - result = f_read(&active_file, &data, 1, &actual); + f_read(&active_file, &data, 1, &actual); f_lseek(&active_file, shift_offset); - result = f_write(&active_file, &data, 1, &actual); + f_write(&active_file, &data, 1, &actual); } f_truncate(&active_file); } else if (data_shift > 0) { - result = f_lseek(&active_file, file_length); + f_lseek(&active_file, file_length); // Fill end with 0xff so we don't need to erase. uint8_t data = 0xff; for (size_t i = 0; i < (size_t) data_shift; i++) { UINT actual; - result = f_write(&active_file, &data, 1, &actual); + f_write(&active_file, &data, 1, &actual); } for (uint32_t shift_offset = new_length - 1; shift_offset >= offset + insert_length ; shift_offset--) { UINT actual; f_lseek(&active_file, shift_offset - data_shift); - result = f_read(&active_file, &data, 1, &actual); + f_read(&active_file, &data, 1, &actual); f_lseek(&active_file, shift_offset); - result = f_write(&active_file, &data, 1, &actual); + f_write(&active_file, &data, 1, &actual); } } f_lseek(&active_file, offset); uint8_t* data = (uint8_t *) (current_command + 4); UINT written; - result = f_write(&active_file, data, insert_length, &written); + f_write(&active_file, data, insert_length, &written); f_sync(&active_file); // Notify the new file length. update_file_length(); -- cgit v1.2.3 From d0044c74b626cee32077789697f1bf73bae96fe7 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 26 Oct 2019 16:06:02 -0400 Subject: bitbangio.SPI was not setting direction of output pins --- shared-module/bitbangio/SPI.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'shared-module') diff --git a/shared-module/bitbangio/SPI.c b/shared-module/bitbangio/SPI.c index 6d3a28523..d02adf34f 100644 --- a/shared-module/bitbangio/SPI.c +++ b/shared-module/bitbangio/SPI.c @@ -43,6 +43,8 @@ void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, if (result != DIGITALINOUT_OK) { mp_raise_ValueError(translate("Clock pin init failed.")); } + common_hal_digitalio_digitalinout_switch_to_output(&self->clock, self->polarity == 1, DRIVE_MODE_PUSH_PULL); + if (mosi != mp_const_none) { result = common_hal_digitalio_digitalinout_construct(&self->mosi, mosi); if (result != DIGITALINOUT_OK) { @@ -50,8 +52,11 @@ void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, mp_raise_ValueError(translate("MOSI pin init failed.")); } self->has_mosi = true; + common_hal_digitalio_digitalinout_switch_to_output(&self->mosi, false, DRIVE_MODE_PUSH_PULL); } + if (miso != mp_const_none) { + // Starts out as input by default, no need to change. result = common_hal_digitalio_digitalinout_construct(&self->miso, miso); if (result != DIGITALINOUT_OK) { common_hal_digitalio_digitalinout_deinit(&self->clock); -- cgit v1.2.3 From 39b38256fd2159680d0f01f73de6cad26597909c Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Fri, 8 Nov 2019 12:35:35 -0800 Subject: Fixed I2CDisplay reset issue --- shared-module/displayio/I2CDisplay.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'shared-module') diff --git a/shared-module/displayio/I2CDisplay.c b/shared-module/displayio/I2CDisplay.c index d9452dc50..0307410d1 100644 --- a/shared-module/displayio/I2CDisplay.c +++ b/shared-module/displayio/I2CDisplay.c @@ -42,12 +42,22 @@ void common_hal_displayio_i2cdisplay_construct(displayio_i2cdisplay_obj_t* self, busio_i2c_obj_t* i2c, uint16_t device_address, const mcu_pin_obj_t* reset) { + // Reset the display before probing + self->reset.base.type = &mp_type_NoneType; + if (reset != NULL) { + self->reset.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&self->reset, reset); + common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL); + never_reset_pin_number(reset->number); + common_hal_displayio_i2cdisplay_reset(self); + } + // Probe the bus to see if a device acknowledges the given address. if (!common_hal_busio_i2c_probe(i2c, device_address)) { mp_raise_ValueError_varg(translate("Unable to find I2C Display at %x"), device_address); } - // Write to the device and return 0 on success or an appropriate error code from mperrno.h + // Write to the device and return 0 on success or an appropriate error code from mperrno.h self->bus = i2c; common_hal_busio_i2c_never_reset(self->bus); // Our object is statically allocated off the heap so make sure the bus object lives to the end @@ -55,15 +65,6 @@ void common_hal_displayio_i2cdisplay_construct(displayio_i2cdisplay_obj_t* self, gc_never_free(self->bus); self->address = device_address; - - self->reset.base.type = &mp_type_NoneType; - if (reset != NULL) { - self->reset.base.type = &digitalio_digitalinout_type; - common_hal_digitalio_digitalinout_construct(&self->reset, reset); - common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL); - never_reset_pin_number(reset->number); - common_hal_displayio_i2cdisplay_reset(self); - } } void common_hal_displayio_i2cdisplay_deinit(displayio_i2cdisplay_obj_t* self) { -- cgit v1.2.3 From de5691acf5060d6e2182da4c84095a007f6da606 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Fri, 15 Nov 2019 12:47:00 -0500 Subject: Add never_reset and reset to pin common hal, adjust files --- ports/atmel-samd/common-hal/microcontroller/Pin.c | 8 ++++++++ ports/nrf/common-hal/microcontroller/Pin.c | 8 ++++++++ ports/stm32f4/common-hal/microcontroller/Pin.c | 8 ++++++++ shared-bindings/microcontroller/Pin.h | 2 ++ shared-module/displayio/Display.c | 2 +- shared-module/displayio/EPaperDisplay.c | 2 +- shared-module/displayio/FourWire.c | 13 +++++++------ shared-module/displayio/I2CDisplay.c | 5 +++-- supervisor/shared/rgb_led_status.c | 8 ++++---- 9 files changed, 42 insertions(+), 14 deletions(-) (limited to 'shared-module') diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.c b/ports/atmel-samd/common-hal/microcontroller/Pin.c index 6f3cbc759..9719ea5b1 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.c +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.c @@ -158,6 +158,14 @@ void reset_pin_number(uint8_t pin_number) { #endif } +void common_hal_never_reset_pin(const mcu_pin_obj_t* pin) { + never_reset_pin_number(pin->number); +} + +void common_hal_reset_pin(const mcu_pin_obj_t* pin) { + reset_pin_number(pin->number); +} + void claim_pin(const mcu_pin_obj_t* pin) { #ifdef MICROPY_HW_NEOPIXEL if (pin == MICROPY_HW_NEOPIXEL) { diff --git a/ports/nrf/common-hal/microcontroller/Pin.c b/ports/nrf/common-hal/microcontroller/Pin.c index ce55317e5..b7931a2e1 100644 --- a/ports/nrf/common-hal/microcontroller/Pin.c +++ b/ports/nrf/common-hal/microcontroller/Pin.c @@ -125,6 +125,14 @@ void never_reset_pin_number(uint8_t pin_number) { never_reset_pins[nrf_pin_port(pin_number)] |= 1 << nrf_relative_pin_number(pin_number); } +void common_hal_never_reset_pin(const mcu_pin_obj_t* pin) { + never_reset_pin_number(pin->number); +} + +void common_hal_reset_pin(const mcu_pin_obj_t* pin) { + reset_pin_number(pin->number); +} + void claim_pin(const mcu_pin_obj_t* pin) { // Set bit in claimed_pins bitmask. claimed_pins[nrf_pin_port(pin->number)] |= 1 << nrf_relative_pin_number(pin->number); diff --git a/ports/stm32f4/common-hal/microcontroller/Pin.c b/ports/stm32f4/common-hal/microcontroller/Pin.c index 5761d7fb1..7e737e21b 100644 --- a/ports/stm32f4/common-hal/microcontroller/Pin.c +++ b/ports/stm32f4/common-hal/microcontroller/Pin.c @@ -72,6 +72,14 @@ void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number) { never_reset_pins[pin_port] |= 1<port, pin->number); +} + +void common_hal_reset_pin(const mcu_pin_obj_t* pin) { + reset_pin_number(pin->port, pin->number); +} + void claim_pin(const mcu_pin_obj_t* pin) { // Set bit in claimed_pins bitmask. claimed_pins[pin->port] |= 1<number; diff --git a/shared-bindings/microcontroller/Pin.h b/shared-bindings/microcontroller/Pin.h index ed831b258..2d15dd5c5 100644 --- a/shared-bindings/microcontroller/Pin.h +++ b/shared-bindings/microcontroller/Pin.h @@ -37,5 +37,7 @@ void assert_pin(mp_obj_t obj, bool none_ok); void assert_pin_free(const mcu_pin_obj_t* pin); bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin); +void common_hal_never_reset_pin(const mcu_pin_obj_t* pin); +void common_hal_reset_pin(const mcu_pin_obj_t* pin); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PIN_H diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c index 06b81f2f8..862d2cf59 100644 --- a/shared-module/displayio/Display.c +++ b/shared-module/displayio/Display.c @@ -113,7 +113,7 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self, if (result != PWMOUT_OK) { self->backlight_inout.base.type = &digitalio_digitalinout_type; common_hal_digitalio_digitalinout_construct(&self->backlight_inout, backlight_pin); - never_reset_pin_number(backlight_pin->number); + common_hal_never_reset_pin(backlight_pin); } else { self->backlight_pwm.base.type = &pulseio_pwmout_type; common_hal_pulseio_pwmout_never_reset(&self->backlight_pwm); diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index efbd9f3dd..df1d5162b 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -82,7 +82,7 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* if (busy_pin != NULL) { self->busy.base.type = &digitalio_digitalinout_type; common_hal_digitalio_digitalinout_construct(&self->busy, busy_pin); - never_reset_pin_number(busy_pin->number); + common_hal_never_reset_pin(busy_pin); } // Clear the color memory if it isn't in use. diff --git a/shared-module/displayio/FourWire.c b/shared-module/displayio/FourWire.c index fcc4c1a20..92d4507dd 100644 --- a/shared-module/displayio/FourWire.c +++ b/shared-module/displayio/FourWire.c @@ -31,6 +31,7 @@ #include "py/gc.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/time/__init__.h" #include "shared-module/displayio/display_core.h" @@ -61,12 +62,12 @@ void common_hal_displayio_fourwire_construct(displayio_fourwire_obj_t* self, self->reset.base.type = &digitalio_digitalinout_type; common_hal_digitalio_digitalinout_construct(&self->reset, reset); common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL); - never_reset_pin_number(reset->number); + common_hal_never_reset_pin(reset); common_hal_displayio_fourwire_reset(self); } - never_reset_pin_number(command->number); - never_reset_pin_number(chip_select->number); + common_hal_never_reset_pin(command); + common_hal_never_reset_pin(chip_select); } void common_hal_displayio_fourwire_deinit(displayio_fourwire_obj_t* self) { @@ -74,9 +75,9 @@ void common_hal_displayio_fourwire_deinit(displayio_fourwire_obj_t* self) { common_hal_busio_spi_deinit(self->bus); } - reset_pin_number(self->command.pin->number); - reset_pin_number(self->chip_select.pin->number); - reset_pin_number(self->reset.pin->number); + common_hal_reset_pin(self->command.pin); + common_hal_reset_pin(self->chip_select.pin); + common_hal_reset_pin(self->reset.pin); } bool common_hal_displayio_fourwire_reset(mp_obj_t obj) { diff --git a/shared-module/displayio/I2CDisplay.c b/shared-module/displayio/I2CDisplay.c index 0307410d1..280476f19 100644 --- a/shared-module/displayio/I2CDisplay.c +++ b/shared-module/displayio/I2CDisplay.c @@ -33,6 +33,7 @@ #include "py/runtime.h" #include "shared-bindings/busio/I2C.h" #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/time/__init__.h" #include "shared-module/displayio/display_core.h" @@ -48,7 +49,7 @@ void common_hal_displayio_i2cdisplay_construct(displayio_i2cdisplay_obj_t* self, self->reset.base.type = &digitalio_digitalinout_type; common_hal_digitalio_digitalinout_construct(&self->reset, reset); common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL); - never_reset_pin_number(reset->number); + common_hal_never_reset_pin(reset); common_hal_displayio_i2cdisplay_reset(self); } @@ -72,7 +73,7 @@ void common_hal_displayio_i2cdisplay_deinit(displayio_i2cdisplay_obj_t* self) { common_hal_busio_i2c_deinit(self->bus); } - reset_pin_number(self->reset.pin->number); + common_hal_reset_pin(self->reset.pin); } bool common_hal_displayio_i2cdisplay_reset(mp_obj_t obj) { diff --git a/supervisor/shared/rgb_led_status.c b/supervisor/shared/rgb_led_status.c index 05df4c628..90c78fbbe 100644 --- a/supervisor/shared/rgb_led_status.c +++ b/supervisor/shared/rgb_led_status.c @@ -117,7 +117,7 @@ void rgb_led_status_init() { mp_const_none); #else if (!common_hal_busio_spi_deinited(&status_apa102)) { - // This may call us recursively if reset_pin_number() is called, + // This may call us recursively if common_hal_reset_pin() is called, // The rgb_led_status_init_in_progress guard will prevent further recursion. common_hal_busio_spi_deinit(&status_apa102); } @@ -181,11 +181,11 @@ void rgb_led_status_init() { void reset_status_led() { #ifdef MICROPY_HW_NEOPIXEL - reset_pin_number(MICROPY_HW_NEOPIXEL->number); + common_hal_reset_pin(MICROPY_HW_NEOPIXEL); #endif #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) - reset_pin_number(MICROPY_HW_APA102_MOSI->number); - reset_pin_number(MICROPY_HW_APA102_SCK->number); + common_hal_reset_pin(MICROPY_HW_APA102_MOSI); + common_hal_reset_pin(MICROPY_HW_APA102_SCK); #endif #if defined(CP_RGB_STATUS_LED) // TODO: Support sharing status LED with user. -- cgit v1.2.3 From 7f744a2369a5036cadfa05575da1704f709c98bb Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 18 Nov 2019 08:22:41 -0600 Subject: Supervisor: move most of systick to the supervisor This code is shared by most parts, except where not all the #ifdefs inside the tick function were present in all ports. This mostly would have broken gamepad tick support on non-samd ports. The "ms32" and "ms64" variants of the tick functions are introduced because there is no 64-bit atomic read. Disabling interrupts avoids a low probability bug where milliseconds could be off by ~49.5 days once every ~49.5 days (2^32 ms). Avoiding disabling interrupts when only the low 32 bits are needed is a minor optimization. Testing performed: on metro m4 express, USB still works and time.monotonic_ns() still counts up --- drivers/wiznet5k/internet/dns/dns.c | 4 +- ports/atmel-samd/background.c | 5 +- ports/atmel-samd/common-hal/busio/UART.c | 13 ++-- ports/atmel-samd/common-hal/time/__init__.c | 4 +- ports/atmel-samd/mphalport.c | 6 +- ports/atmel-samd/mphalport.h | 6 +- ports/atmel-samd/tick.c | 36 ++-------- ports/atmel-samd/tick.h | 2 - ports/cxd56/common-hal/time/__init__.c | 4 +- ports/cxd56/mphalport.c | 6 +- ports/cxd56/mphalport.h | 2 - ports/cxd56/tick.c | 15 +---- ports/cxd56/tick.h | 2 - ports/nrf/common-hal/_bleio/Adapter.c | 3 +- ports/nrf/common-hal/_bleio/CharacteristicBuffer.c | 5 +- ports/nrf/common-hal/busio/UART.c | 12 ++-- ports/nrf/common-hal/time/__init__.c | 2 +- ports/nrf/mphalport.c | 5 +- ports/nrf/mphalport.h | 5 +- ports/nrf/tick.c | 33 +++------- ports/nrf/tick.h | 2 - ports/stm32f4/common-hal/time/__init__.c | 2 +- ports/stm32f4/mphalport.c | 6 +- ports/stm32f4/mphalport.h | 4 +- ports/stm32f4/tick.c | 32 +++------ ports/stm32f4/tick.h | 2 - py/circuitpy_mpconfig.h | 1 + shared-module/displayio/Display.c | 11 ++-- shared-module/displayio/EPaperDisplay.c | 5 +- shared-module/displayio/display_core.c | 5 +- shared-module/network/__init__.c | 4 +- shared-module/usb_hid/Device.c | 5 +- supervisor/shared/rgb_led_status.c | 9 +-- supervisor/shared/safe_mode.c | 5 +- supervisor/shared/tick.c | 76 ++++++++++++++++++++++ supervisor/shared/tick.h | 37 +++++++++++ supervisor/supervisor.mk | 1 + 37 files changed, 214 insertions(+), 163 deletions(-) create mode 100644 supervisor/shared/tick.c create mode 100644 supervisor/shared/tick.h (limited to 'shared-module') diff --git a/drivers/wiznet5k/internet/dns/dns.c b/drivers/wiznet5k/internet/dns/dns.c index daf4db123..8b9e96670 100644 --- a/drivers/wiznet5k/internet/dns/dns.c +++ b/drivers/wiznet5k/internet/dns/dns.c @@ -52,7 +52,7 @@ #include #include -#include "tick.h" +#include "supervisor/shared/tick.h" //#include "Ethernet/socket.h" //#include "Internet/DNS/dns.h" @@ -125,7 +125,7 @@ uint16_t DNS_MSGID; // DNS message ID uint32_t HAL_GetTick(void) { - return ticks_ms; + return supervisor_ticks_ms32(); } uint32_t hal_sys_tick; diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c index 386ba0715..3b698768b 100644 --- a/ports/atmel-samd/background.c +++ b/ports/atmel-samd/background.c @@ -28,6 +28,7 @@ #include "audio_dma.h" #include "tick.h" #include "supervisor/filesystem.h" +#include "supervisor/shared/tick.h" #include "supervisor/usb.h" #include "py/runtime.h" @@ -71,9 +72,9 @@ void run_background_tasks(void) { running_background_tasks = false; assert_heap_ok(); - last_finished_tick = ticks_ms; + last_finished_tick = supervisor_ticks_ms64(); } bool background_tasks_ok(void) { - return ticks_ms - last_finished_tick < 1000; + return supervisor_ticks_ms64() - last_finished_tick < 1000; } diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 2505e894a..42493a6b6 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -34,8 +34,7 @@ #include "py/runtime.h" #include "py/stream.h" #include "supervisor/shared/translate.h" - -#include "tick.h" +#include "supervisor/shared/tick.h" #include "hpl_sercom_config.h" #include "peripheral_clk_config.h" @@ -272,10 +271,10 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t usart_async_get_io_descriptor(usart_desc_p, &io); size_t total_read = 0; - uint64_t start_ticks = ticks_ms; + uint64_t start_ticks = supervisor_ticks_ms64(); // Busy-wait until timeout or until we've read enough chars. - while (ticks_ms - start_ticks <= self->timeout_ms) { + while (supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) { // Read as many chars as we can right now, up to len. size_t num_read = io_read(io, data, len); @@ -289,7 +288,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t } if (num_read > 0) { // Reset the timeout on every character read. - start_ticks = ticks_ms; + start_ticks = supervisor_ticks_ms64(); } RUN_BACKGROUND_TASKS; // Allow user to break out of a timeout with a KeyboardInterrupt. @@ -330,9 +329,9 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, // Wait until write is complete or timeout. bool done = false; - uint64_t start_ticks = ticks_ms; + uint64_t start_ticks = supervisor_ticks_ms64(); // Busy-wait for timeout. - while (ticks_ms - start_ticks < self->timeout_ms) { + while (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) { if (usart_async_is_tx_empty(usart_desc_p)) { done = true; break; diff --git a/ports/atmel-samd/common-hal/time/__init__.c b/ports/atmel-samd/common-hal/time/__init__.c index 0d60adef2..2d82b3d1a 100644 --- a/ports/atmel-samd/common-hal/time/__init__.c +++ b/ports/atmel-samd/common-hal/time/__init__.c @@ -28,10 +28,10 @@ #include "shared-bindings/time/__init__.h" -#include "tick.h" +#include "supervisor/shared/tick.h" inline uint64_t common_hal_time_monotonic() { - return ticks_ms; + return supervisor_ticks_ms64(); } void common_hal_time_delay_ms(uint32_t delay) { diff --git a/ports/atmel-samd/mphalport.c b/ports/atmel-samd/mphalport.c index 957bf6073..96433d729 100644 --- a/ports/atmel-samd/mphalport.c +++ b/ports/atmel-samd/mphalport.c @@ -45,12 +45,12 @@ #include "mpconfigboard.h" #include "mphalport.h" #include "reset.h" -#include "tick.h" +#include "supervisor/shared/tick.h" extern uint32_t common_hal_mcu_processor_get_frequency(void); void mp_hal_delay_ms(mp_uint_t delay) { - uint64_t start_tick = ticks_ms; + uint64_t start_tick = supervisor_ticks_ms64(); uint64_t duration = 0; while (duration < delay) { RUN_BACKGROUND_TASKS; @@ -59,7 +59,7 @@ void mp_hal_delay_ms(mp_uint_t delay) { MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) { break; } - duration = (ticks_ms - start_tick); + duration = (supervisor_ticks_ms64() - start_tick); // TODO(tannewt): Go to sleep for a little while while we wait. } } diff --git a/ports/atmel-samd/mphalport.h b/ports/atmel-samd/mphalport.h index 64269b201..8a762e258 100644 --- a/ports/atmel-samd/mphalport.h +++ b/ports/atmel-samd/mphalport.h @@ -31,11 +31,11 @@ #include "lib/oofatfs/ff.h" -// Global millisecond tick count (driven by SysTick interrupt). -extern volatile uint64_t ticks_ms; +#include "supervisor/shared/tick.h" +// Global millisecond tick count (driven by SysTick interrupt). static inline mp_uint_t mp_hal_ticks_ms(void) { - return ticks_ms; + return supervisor_ticks_ms32(); } // Number of bytes in receive buffer volatile uint8_t usb_rx_count; diff --git a/ports/atmel-samd/tick.c b/ports/atmel-samd/tick.c index 4d7bb9dca..f996440ae 100644 --- a/ports/atmel-samd/tick.c +++ b/ports/atmel-samd/tick.c @@ -28,47 +28,21 @@ #include "peripheral_clk_config.h" -#include "supervisor/shared/autoreload.h" -#include "supervisor/filesystem.h" +#include "supervisor/shared/tick.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Processor.h" -#if CIRCUITPY_GAMEPAD -#include "shared-module/gamepad/__init__.h" -#endif - -#if CIRCUITPY_GAMEPADSHIFT -#include "shared-module/gamepadshift/__init__.h" -#endif -// Global millisecond tick count -volatile uint64_t ticks_ms = 0; - void SysTick_Handler(void) { // SysTick interrupt handler called when the SysTick timer reaches zero // (every millisecond). common_hal_mcu_disable_interrupts(); - ticks_ms += 1; // Read the control register to reset the COUNTFLAG. (void) SysTick->CTRL; common_hal_mcu_enable_interrupts(); -#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0 - filesystem_tick(); -#endif -#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS - autoreload_tick(); -#endif -#ifdef CIRCUITPY_GAMEPAD_TICKS - if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) { - #if CIRCUITPY_GAMEPAD - gamepad_tick(); - #endif - #if CIRCUITPY_GAMEPADSHIFT - gamepadshift_tick(); - #endif - } -#endif + // Do things common to all ports when the tick occurs + supervisor_tick(); } void tick_init() { @@ -115,7 +89,7 @@ void current_tick(uint64_t* ms, uint32_t* us_until_ms) { uint32_t tick_status = SysTick->CTRL; uint32_t current_us = SysTick->VAL; uint32_t tick_status2 = SysTick->CTRL; - uint64_t current_ms = ticks_ms; + uint64_t current_ms = supervisor_ticks_ms64(); // The second clause ensures our value actually rolled over. Its possible it hit zero between // the VAL read and CTRL read. if ((tick_status & SysTick_CTRL_COUNTFLAG_Msk) != 0 || @@ -129,5 +103,5 @@ void current_tick(uint64_t* ms, uint32_t* us_until_ms) { void wait_until(uint64_t ms, uint32_t us_until_ms) { uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000; - while (ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {} + while (supervisor_ticks_ms64() <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {} } diff --git a/ports/atmel-samd/tick.h b/ports/atmel-samd/tick.h index c8c8d739a..334352df2 100644 --- a/ports/atmel-samd/tick.h +++ b/ports/atmel-samd/tick.h @@ -28,8 +28,6 @@ #include "py/mpconfig.h" -extern volatile uint64_t ticks_ms; - extern struct timer_descriptor ms_timer; void tick_init(void); diff --git a/ports/cxd56/common-hal/time/__init__.c b/ports/cxd56/common-hal/time/__init__.c index 8f7326b62..6f5eedd41 100644 --- a/ports/cxd56/common-hal/time/__init__.c +++ b/ports/cxd56/common-hal/time/__init__.c @@ -26,10 +26,10 @@ #include "py/mphal.h" -#include "tick.h" +#include "supervisor/shared/tick.h" uint64_t common_hal_time_monotonic(void) { - return ticks_ms; + return supervisor_ticks_ms64(); } void common_hal_time_delay_ms(uint32_t delay) { diff --git a/ports/cxd56/mphalport.c b/ports/cxd56/mphalport.c index 79d93f975..1305706ca 100644 --- a/ports/cxd56/mphalport.c +++ b/ports/cxd56/mphalport.c @@ -31,7 +31,7 @@ #include "py/mpstate.h" -#include "tick.h" +#include "supervisor/shared/tick.h" #define DELAY_CORRECTION (700) #define DELAY_INTERVAL (50) @@ -57,7 +57,7 @@ mp_uint_t mp_hal_ticks_cpu(void) { } void mp_hal_delay_ms(mp_uint_t delay) { - uint64_t start_tick = ticks_ms; + uint64_t start_tick = supervisor_ticks_ms64(); uint64_t duration = 0; while (duration < delay) { #ifdef MICROPY_VM_HOOK_LOOP @@ -68,7 +68,7 @@ void mp_hal_delay_ms(mp_uint_t delay) { MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) { break; } - duration = (ticks_ms - start_tick); + duration = (supervisor_ticks_ms64() - start_tick); // TODO(tannewt): Go to sleep for a little while while we wait. } } diff --git a/ports/cxd56/mphalport.h b/ports/cxd56/mphalport.h index 25bca97ad..a2be10b8d 100644 --- a/ports/cxd56/mphalport.h +++ b/ports/cxd56/mphalport.h @@ -31,6 +31,4 @@ #include "lib/utils/interrupt_char.h" -extern volatile uint64_t ticks_ms; - #endif // MICROPY_INCLUDED_CXD56_MPHALPORT_H diff --git a/ports/cxd56/tick.c b/ports/cxd56/tick.c index 6529db790..671b82b74 100644 --- a/ports/cxd56/tick.c +++ b/ports/cxd56/tick.c @@ -27,19 +27,10 @@ #include "tick.h" #include "supervisor/shared/autoreload.h" -#include "supervisor/filesystem.h" - -// Global millisecond tick count -volatile uint64_t ticks_ms = 0; +#include "supervisor/shared/tick.h" void board_timerhook(void) { - ticks_ms += 1; - -#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0 - filesystem_tick(); -#endif -#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS - autoreload_tick(); -#endif + // Do things common to all ports when the tick occurs + supervisor_tick(); } diff --git a/ports/cxd56/tick.h b/ports/cxd56/tick.h index a0d9ee526..d641d9cd4 100644 --- a/ports/cxd56/tick.h +++ b/ports/cxd56/tick.h @@ -29,6 +29,4 @@ #include "py/mpconfig.h" -extern volatile uint64_t ticks_ms; - #endif // MICROPY_INCLUDED_CXD56_TICK_H diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 295a42d63..c3b8dcebe 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -40,6 +40,7 @@ #include "py/objstr.h" #include "py/runtime.h" #include "supervisor/shared/safe_mode.h" +#include "supervisor/shared/tick.h" #include "supervisor/usb.h" #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Adapter.h" @@ -353,7 +354,7 @@ STATIC bool scan_on_ble_evt(ble_evt_t *ble_evt, void *scan_results_in) { ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report; shared_module_bleio_scanresults_append(scan_results, - ticks_ms, + supervisor_ticks_ms64(), report->type.connectable, report->type.scan_response, report->rssi, diff --git a/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c index 5f280e121..9f9b453de 100644 --- a/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c @@ -39,6 +39,7 @@ #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Connection.h" +#include "supervisor/shared/tick.h" #include "common-hal/_bleio/CharacteristicBuffer.h" STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) { @@ -100,10 +101,10 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe } int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) { - uint64_t start_ticks = ticks_ms; + uint64_t start_ticks = supervisor_ticks_ms64(); // Wait for all bytes received or timeout - while ( (ringbuf_count(&self->ringbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) { + while ( (ringbuf_count(&self->ringbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) { RUN_BACKGROUND_TASKS; // Allow user to break out of a timeout with a KeyboardInterrupt. if ( mp_hal_is_interrupted() ) { diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index 54a66ddbe..982b8efa9 100644 --- a/ports/nrf/common-hal/busio/UART.c +++ b/ports/nrf/common-hal/busio/UART.c @@ -231,10 +231,10 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t } size_t rx_bytes = 0; - uint64_t start_ticks = ticks_ms; + uint64_t start_ticks = supervisor_ticks_ms64(); // Wait for all bytes received or timeout - while ( (ringbuf_count(&self->rbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) { + while ( (ringbuf_count(&self->rbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) { RUN_BACKGROUND_TASKS; // Allow user to break out of a timeout with a KeyboardInterrupt. if ( mp_hal_is_interrupted() ) { @@ -265,15 +265,15 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, if ( len == 0 ) return 0; - uint64_t start_ticks = ticks_ms; + uint64_t start_ticks = supervisor_ticks_ms64(); // Wait for on-going transfer to complete - while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) { + while ( nrfx_uarte_tx_in_progress(self->uarte) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) { RUN_BACKGROUND_TASKS; } // Time up - if ( !(ticks_ms - start_ticks < self->timeout_ms) ) { + if ( !(supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } @@ -290,7 +290,7 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, _VERIFY_ERR(*errcode); (*errcode) = 0; - while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) { + while ( nrfx_uarte_tx_in_progress(self->uarte) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) { RUN_BACKGROUND_TASKS; } diff --git a/ports/nrf/common-hal/time/__init__.c b/ports/nrf/common-hal/time/__init__.c index e3cb481ef..976f519db 100644 --- a/ports/nrf/common-hal/time/__init__.c +++ b/ports/nrf/common-hal/time/__init__.c @@ -29,7 +29,7 @@ #include "tick.h" uint64_t common_hal_time_monotonic(void) { - return ticks_ms; + return supervisor_ticks_ms64(); } void common_hal_time_delay_ms(uint32_t delay) { diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index bcd9fb114..3885d5a82 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -31,12 +31,13 @@ #include "py/mphal.h" #include "py/mpstate.h" #include "py/gc.h" +#include "supervisor/shared/tick.h" /*------------------------------------------------------------------*/ /* delay *------------------------------------------------------------------*/ void mp_hal_delay_ms(mp_uint_t delay) { - uint64_t start_tick = ticks_ms; + uint64_t start_tick = supervisor_ticks_ms64(); uint64_t duration = 0; while (duration < delay) { RUN_BACKGROUND_TASKS; @@ -45,7 +46,7 @@ void mp_hal_delay_ms(mp_uint_t delay) { MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) { break; } - duration = (ticks_ms - start_tick); + duration = (supervisor_ticks_ms64() - start_tick); // TODO(tannewt): Go to sleep for a little while while we wait. } } diff --git a/ports/nrf/mphalport.h b/ports/nrf/mphalport.h index a1929a4ac..8bb351401 100644 --- a/ports/nrf/mphalport.h +++ b/ports/nrf/mphalport.h @@ -33,12 +33,11 @@ #include "lib/utils/interrupt_char.h" #include "nrfx_uarte.h" #include "py/mpconfig.h" +#include "supervisor/shared/tick.h" extern nrfx_uarte_t serial_instance; -extern volatile uint64_t ticks_ms; - -#define mp_hal_ticks_ms() ((mp_uint_t) ticks_ms) +#define mp_hal_ticks_ms() ((mp_uint_t) supervisor_ticks_ms32()) #define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t) (us)) bool mp_hal_stdin_any(void); diff --git a/ports/nrf/tick.c b/ports/nrf/tick.c index 6d8fd13e0..ac825a7f1 100644 --- a/ports/nrf/tick.c +++ b/ports/nrf/tick.c @@ -26,31 +26,14 @@ #include "tick.h" -#include "supervisor/shared/autoreload.h" -#include "supervisor/filesystem.h" +#include "supervisor/shared/tick.h" #include "shared-module/gamepad/__init__.h" #include "shared-bindings/microcontroller/Processor.h" #include "nrf.h" -// Global millisecond tick count -volatile uint64_t ticks_ms = 0; - void SysTick_Handler(void) { - // SysTick interrupt handler called when the SysTick timer reaches zero - // (every millisecond). - ticks_ms += 1; - -#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0 - filesystem_tick(); -#endif -#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS - autoreload_tick(); -#endif -#ifdef CIRCUITPY_GAMEPAD_TICKS - if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) { - gamepad_tick(); - } -#endif + // Do things common to all ports when the tick occurs + supervisor_tick(); } void tick_init() { @@ -61,11 +44,11 @@ void tick_init() { void tick_delay(uint32_t us) { uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000; uint32_t us_between_ticks = SysTick->VAL / ticks_per_us; - uint64_t start_ms = ticks_ms; + uint64_t start_ms = supervisor_ticks_ms64(); while (us > 1000) { - while (ticks_ms == start_ms) {} + while (supervisor_ticks_ms64() == start_ms) {} us -= us_between_ticks; - start_ms = ticks_ms; + start_ms = supervisor_ticks_ms64(); us_between_ticks = 1000; } while (SysTick->VAL > ((us_between_ticks - us) * ticks_per_us)) {} @@ -74,11 +57,11 @@ void tick_delay(uint32_t us) { // us counts down! void current_tick(uint64_t* ms, uint32_t* us_until_ms) { uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000; - *ms = ticks_ms; + *ms = supervisor_ticks_ms64(); *us_until_ms = SysTick->VAL / ticks_per_us; } void wait_until(uint64_t ms, uint32_t us_until_ms) { uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000; - while(ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {} + while(supervisor_ticks_ms64() <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {} } diff --git a/ports/nrf/tick.h b/ports/nrf/tick.h index 838e9fbea..d638ad025 100644 --- a/ports/nrf/tick.h +++ b/ports/nrf/tick.h @@ -30,8 +30,6 @@ #include -extern volatile uint64_t ticks_ms; - extern struct timer_descriptor ms_timer; void tick_init(void); diff --git a/ports/stm32f4/common-hal/time/__init__.c b/ports/stm32f4/common-hal/time/__init__.c index e3cb481ef..976f519db 100644 --- a/ports/stm32f4/common-hal/time/__init__.c +++ b/ports/stm32f4/common-hal/time/__init__.c @@ -29,7 +29,7 @@ #include "tick.h" uint64_t common_hal_time_monotonic(void) { - return ticks_ms; + return supervisor_ticks_ms64(); } void common_hal_time_delay_ms(uint32_t delay) { diff --git a/ports/stm32f4/mphalport.c b/ports/stm32f4/mphalport.c index ea864e7ce..f78e9c750 100644 --- a/ports/stm32f4/mphalport.c +++ b/ports/stm32f4/mphalport.c @@ -31,11 +31,13 @@ #include "py/mpstate.h" #include "py/gc.h" +#include "supervisor/shared/tick.h" + /*------------------------------------------------------------------*/ /* delay *------------------------------------------------------------------*/ void mp_hal_delay_ms(mp_uint_t delay) { - uint64_t start_tick = ticks_ms; + uint64_t start_tick = supervisor_ticks_ms64(); uint64_t duration = 0; while (duration < delay) { #ifdef MICROPY_VM_HOOK_LOOP @@ -46,7 +48,7 @@ void mp_hal_delay_ms(mp_uint_t delay) { MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) { break; } - duration = (ticks_ms - start_tick); + duration = (supervisor_ticks_ms64() - start_tick); // TODO(tannewt): Go to sleep for a little while while we wait. } } diff --git a/ports/stm32f4/mphalport.h b/ports/stm32f4/mphalport.h index d184138f7..df2f0ca65 100644 --- a/ports/stm32f4/mphalport.h +++ b/ports/stm32f4/mphalport.h @@ -32,10 +32,10 @@ #include "lib/utils/interrupt_char.h" #include "py/mpconfig.h" +#include "supervisor/shared/tick.h" -extern volatile uint64_t ticks_ms; -#define mp_hal_ticks_ms() ((mp_uint_t) ticks_ms) +#define mp_hal_ticks_ms() ((mp_uint_t) supervisor_ticks_ms32()) //#define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t) (us)) bool mp_hal_stdin_any(void); diff --git a/ports/stm32f4/tick.c b/ports/stm32f4/tick.c index 688f71dbd..f4adf183a 100644 --- a/ports/stm32f4/tick.c +++ b/ports/stm32f4/tick.c @@ -26,37 +26,23 @@ #include "tick.h" -#include "supervisor/shared/autoreload.h" #include "supervisor/filesystem.h" -#include "shared-module/gamepad/__init__.h" +#include "supervisor/shared/tick.h" #include "shared-bindings/microcontroller/Processor.h" #include "stm32f4xx.h" -// Global millisecond tick count -volatile uint64_t ticks_ms = 0; - void SysTick_Handler(void) { // SysTick interrupt handler called when the SysTick timer reaches zero // (every millisecond). - ticks_ms += 1; -#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0 - filesystem_tick(); -#endif -#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS - autoreload_tick(); -#endif -#ifdef CIRCUITPY_GAMEPAD_TICKS - if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) { - gamepad_tick(); - } -#endif + // Do things common to all ports when the tick occurs + supervisor_tick(); } uint32_t HAL_GetTick(void) //override ST HAL { - return (uint32_t)ticks_ms; + return (uint32_t)supervisor_ticks_ms32(); } void tick_init() { @@ -72,11 +58,11 @@ void tick_init() { void tick_delay(uint32_t us) { uint32_t ticks_per_us = SystemCoreClock / 1000 / 1000; uint32_t us_between_ticks = SysTick->VAL / ticks_per_us; - uint64_t start_ms = ticks_ms; + uint64_t start_ms = supervisor_ticks_ms64(); while (us > 1000) { - while (ticks_ms == start_ms) {} + while (supervisor_ticks_ms64() == start_ms) {} us -= us_between_ticks; - start_ms = ticks_ms; + start_ms = supervisor_ticks_ms64(); us_between_ticks = 1000; } while (SysTick->VAL > ((us_between_ticks - us) * ticks_per_us)) {} @@ -85,11 +71,11 @@ void tick_delay(uint32_t us) { // us counts down! void current_tick(uint64_t* ms, uint32_t* us_until_ms) { uint32_t ticks_per_us = SystemCoreClock / 1000 / 1000; - *ms = ticks_ms; + *ms = supervisor_ticks_ms32(); *us_until_ms = SysTick->VAL / ticks_per_us; } void wait_until(uint64_t ms, uint32_t us_until_ms) { uint32_t ticks_per_us = SystemCoreClock / 1000 / 1000; - while(ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {} + while(supervisor_ticks_ms64() <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {} } diff --git a/ports/stm32f4/tick.h b/ports/stm32f4/tick.h index e4772fa2c..999acc7a3 100644 --- a/ports/stm32f4/tick.h +++ b/ports/stm32f4/tick.h @@ -30,8 +30,6 @@ #include -extern volatile uint64_t ticks_ms; - extern struct timer_descriptor ms_timer; void tick_init(void); diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 61d324291..7853e4de9 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -32,6 +32,7 @@ #define __INCLUDED_MPCONFIG_CIRCUITPY_H #include +#include // This is CircuitPython. #define CIRCUITPY 1 diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c index 862d2cf59..11db0f8ff 100644 --- a/shared-module/displayio/Display.c +++ b/shared-module/displayio/Display.c @@ -35,6 +35,7 @@ #include "shared-module/displayio/__init__.h" #include "shared-module/displayio/display_core.h" #include "supervisor/shared/display.h" +#include "supervisor/shared/tick.h" #include "supervisor/usb.h" #include @@ -313,7 +314,7 @@ uint16_t common_hal_displayio_display_get_rotation(displayio_display_obj_t* self bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame) { if (!self->auto_refresh && !self->first_manual_refresh) { - uint64_t current_time = ticks_ms; + uint64_t current_time = supervisor_ticks_ms64(); uint32_t current_ms_since_real_refresh = current_time - self->core.last_refresh; // Test to see if the real frame time is below our minimum. if (current_ms_since_real_refresh > maximum_ms_per_real_frame) { @@ -327,7 +328,7 @@ bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_ } uint32_t remaining_time = target_ms_per_frame - (current_ms_since_real_refresh % target_ms_per_frame); // We're ahead of the game so wait until we align with the frame rate. - while (ticks_ms - self->last_refresh_call < remaining_time) { + while (supervisor_ticks_ms64() - self->last_refresh_call < remaining_time) { RUN_BACKGROUND_TASKS; } } @@ -350,20 +351,20 @@ STATIC void _update_backlight(displayio_display_obj_t* self) { if (!self->auto_brightness || self->updating_backlight) { return; } - if (ticks_ms - self->last_backlight_refresh < 100) { + if (supervisor_ticks_ms64() - self->last_backlight_refresh < 100) { return; } // TODO(tannewt): Fade the backlight based on it's existing value and a target value. The target // should account for ambient light when possible. common_hal_displayio_display_set_brightness(self, 1.0); - self->last_backlight_refresh = ticks_ms; + self->last_backlight_refresh = supervisor_ticks_ms64(); } void displayio_display_background(displayio_display_obj_t* self) { _update_backlight(self); - if (self->auto_refresh && (ticks_ms - self->core.last_refresh) > self->native_ms_per_frame) { + if (self->auto_refresh && (supervisor_ticks_ms64() - self->core.last_refresh) > self->native_ms_per_frame) { _refresh_display(self); } } diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index df1d5162b..ad2559a83 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -35,6 +35,7 @@ #include "shared-bindings/time/__init__.h" #include "shared-module/displayio/__init__.h" #include "supervisor/shared/display.h" +#include "supervisor/shared/tick.h" #include "supervisor/usb.h" #include @@ -175,7 +176,7 @@ uint32_t common_hal_displayio_epaperdisplay_get_time_to_refresh(displayio_epaper return 0; } // Refresh at seconds per frame rate. - uint32_t elapsed_time = ticks_ms - self->core.last_refresh; + uint32_t elapsed_time = supervisor_ticks_ms64() - self->core.last_refresh; if (elapsed_time > self->milliseconds_per_frame) { return 0; } @@ -339,7 +340,7 @@ void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self) { bool busy = common_hal_digitalio_digitalinout_get_value(&self->busy); refresh_done = busy != self->busy_state; } else { - refresh_done = ticks_ms - self->core.last_refresh > self->refresh_time; + refresh_done = supervisor_ticks_ms64() - self->core.last_refresh > self->refresh_time; } if (refresh_done) { self->refreshing = false; diff --git a/shared-module/displayio/display_core.c b/shared-module/displayio/display_core.c index a73ea81d1..658daa8d6 100644 --- a/shared-module/displayio/display_core.c +++ b/shared-module/displayio/display_core.c @@ -35,6 +35,7 @@ #include "shared-bindings/time/__init__.h" #include "shared-module/displayio/__init__.h" #include "supervisor/shared/display.h" +#include "supervisor/shared/tick.h" #include #include @@ -281,7 +282,7 @@ void displayio_display_core_set_region_to_update(displayio_display_core_t* self, } void displayio_display_core_start_refresh(displayio_display_core_t* self) { - self->last_refresh = ticks_ms; + self->last_refresh = supervisor_ticks_ms64(); } void displayio_display_core_finish_refresh(displayio_display_core_t* self) { @@ -289,7 +290,7 @@ void displayio_display_core_finish_refresh(displayio_display_core_t* self) { displayio_group_finish_refresh(self->current_group); } self->full_refresh = false; - self->last_refresh = ticks_ms; + self->last_refresh = supervisor_ticks_ms64(); } void release_display_core(displayio_display_core_t* self) { diff --git a/shared-module/network/__init__.c b/shared-module/network/__init__.c index 96648b260..925e9a2a3 100644 --- a/shared-module/network/__init__.c +++ b/shared-module/network/__init__.c @@ -31,6 +31,8 @@ #include "py/mphal.h" #include "py/mperrno.h" +#include "supervisor/shared/tick.h" + #include "shared-bindings/random/__init__.h" #include "shared-module/network/__init__.h" @@ -53,7 +55,7 @@ void network_module_deinit(void) { void network_module_background(void) { static uint32_t next_tick = 0; - uint32_t this_tick = ticks_ms; + uint32_t this_tick = supervisor_ticks_ms32(); if (this_tick < next_tick) return; next_tick = this_tick + 1000; diff --git a/shared-module/usb_hid/Device.c b/shared-module/usb_hid/Device.c index bed7d163f..8744f2ed3 100644 --- a/shared-module/usb_hid/Device.c +++ b/shared-module/usb_hid/Device.c @@ -30,6 +30,7 @@ #include "shared-bindings/usb_hid/Device.h" #include "shared-module/usb_hid/Device.h" #include "supervisor/shared/translate.h" +#include "supervisor/shared/tick.h" #include "tusb.h" uint8_t common_hal_usb_hid_device_get_usage_page(usb_hid_device_obj_t *self) { @@ -46,8 +47,8 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t* } // Wait until interface is ready, timeout = 2 seconds - uint64_t end_ticks = ticks_ms + 2000; - while ( (ticks_ms < end_ticks) && !tud_hid_ready() ) { + uint64_t end_ticks = supervisor_ticks_ms64() + 2000; + while ( (supervisor_ticks_ms64() < end_ticks) && !tud_hid_ready() ) { RUN_BACKGROUND_TASKS; } diff --git a/supervisor/shared/rgb_led_status.c b/supervisor/shared/rgb_led_status.c index 940cbf1f2..f751a7ffd 100644 --- a/supervisor/shared/rgb_led_status.c +++ b/supervisor/shared/rgb_led_status.c @@ -27,6 +27,7 @@ #include "mphalport.h" #include "shared-bindings/microcontroller/Pin.h" #include "rgb_led_status.h" +#include "supervisor/shared/tick.h" #ifdef MICROPY_HW_NEOPIXEL uint8_t rgb_status_brightness = 63; @@ -360,7 +361,7 @@ void prep_rgb_status_animation(const pyexec_result_t* result, rgb_status_animation_t* status) { #if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED)) new_status_color(ALL_DONE); - status->pattern_start = ticks_ms; + status->pattern_start = supervisor_ticks_ms32(); status->safe_mode = safe_mode; status->found_main = found_main; status->total_exception_cycle = 0; @@ -405,11 +406,11 @@ void prep_rgb_status_animation(const pyexec_result_t* result, void tick_rgb_status_animation(rgb_status_animation_t* status) { #if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED)) - uint32_t tick_diff = ticks_ms - status->pattern_start; + uint32_t tick_diff = supervisor_ticks_ms32() - status->pattern_start; if (status->ok) { // All is good. Ramp ALL_DONE up and down. if (tick_diff > ALL_GOOD_CYCLE_MS) { - status->pattern_start = ticks_ms; + status->pattern_start = supervisor_ticks_ms32(); tick_diff = 0; } @@ -424,7 +425,7 @@ void tick_rgb_status_animation(rgb_status_animation_t* status) { } } else { if (tick_diff > status->total_exception_cycle) { - status->pattern_start = ticks_ms; + status->pattern_start = supervisor_ticks_ms32(); tick_diff = 0; } // First flash the file color. diff --git a/supervisor/shared/safe_mode.c b/supervisor/shared/safe_mode.c index d8d3ab379..363181da0 100644 --- a/supervisor/shared/safe_mode.c +++ b/supervisor/shared/safe_mode.c @@ -34,6 +34,7 @@ #include "supervisor/shared/rgb_led_colors.h" #include "supervisor/shared/rgb_led_status.h" #include "supervisor/shared/translate.h" +#include "supervisor/shared/tick.h" #define SAFE_MODE_DATA_GUARD 0xad0000af #define SAFE_MODE_DATA_GUARD_MASK 0xff0000ff @@ -59,14 +60,14 @@ safe_mode_t wait_for_safe_mode_reset(void) { common_hal_digitalio_digitalinout_construct(&status_led, MICROPY_HW_LED_STATUS); common_hal_digitalio_digitalinout_switch_to_output(&status_led, true, DRIVE_MODE_PUSH_PULL); #endif - uint64_t start_ticks = ticks_ms; + uint64_t start_ticks = supervisor_ticks_ms64(); uint64_t diff = 0; while (diff < 700) { #ifdef MICROPY_HW_LED_STATUS // Blink on for 100, off for 100, on for 100, off for 100 and on for 200 common_hal_digitalio_digitalinout_set_value(&status_led, diff > 100 && diff / 100 != 2 && diff / 100 != 4); #endif - diff = ticks_ms - start_ticks; + diff = supervisor_ticks_ms64() - start_ticks; } #ifdef MICROPY_HW_LED_STATUS common_hal_digitalio_digitalinout_deinit(&status_led); diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c new file mode 100644 index 000000000..d4a6ac5d7 --- /dev/null +++ b/supervisor/shared/tick.c @@ -0,0 +1,76 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jeff Epler 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 "supervisor/shared/tick.h" +#include "supervisor/filesystem.h" +#include "supervisor/shared/autoreload.h" + +static volatile uint64_t ticks_ms; + +#if CIRCUITPY_GAMEPAD +#include "shared-module/gamepad/__init__.h" +#endif + +#if CIRCUITPY_GAMEPADSHIFT +#include "shared-module/gamepadshift/__init__.h" +#endif + +#include "shared-bindings/microcontroller/__init__.h" + +void supervisor_tick(void) { + + ticks_ms ++; + + +#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0 + filesystem_tick(); +#endif +#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS + autoreload_tick(); +#endif +#ifdef CIRCUITPY_GAMEPAD_TICKS + if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) { + #if CIRCUITPY_GAMEPAD + gamepad_tick(); + #endif + #if CIRCUITPY_GAMEPADSHIFT + gamepadshift_tick(); + #endif + } +#endif +} + +uint64_t supervisor_ticks_ms64() { + uint64_t result; + common_hal_mcu_disable_interrupts(); + result = ticks_ms; + common_hal_mcu_enable_interrupts(); + return result; +} + +uint32_t supervisor_ticks_ms32() { + return ticks_ms; +} diff --git a/supervisor/shared/tick.h b/supervisor/shared/tick.h new file mode 100644 index 000000000..3defeb108 --- /dev/null +++ b/supervisor/shared/tick.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jeff Epler 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 __INCLUDED_SUPERVISOR_TICK_H +#define __INCLUDED_SUPERVISOR_TICK_H + +#include +#include + +extern void supervisor_tick(void); +extern uint32_t supervisor_ticks_ms32(void); +extern uint64_t supervisor_ticks_ms64(void); + +#endif diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index b2e4eb1dc..5e997ee78 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -10,6 +10,7 @@ SRC_SUPERVISOR = \ supervisor/shared/safe_mode.c \ supervisor/shared/stack.c \ supervisor/shared/status_leds.c \ + supervisor/shared/tick.c \ supervisor/shared/translate.c ifndef $(NO_USB) -- cgit v1.2.3 From d32dc814d3f0d3e845e54a043467f37a5908f5f0 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 26 Nov 2019 12:48:36 -0800 Subject: Fix ePaper so it works after a GC. We weren't correctly collecting the start and stop sequences. As a result, the GC would free the space and allocate other info there. Thanks to JacobT on Discord for the bug report! --- shared-module/displayio/EPaperDisplay.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'shared-module') diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index df1d5162b..252b39eb7 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -26,6 +26,7 @@ #include "shared-bindings/displayio/EPaperDisplay.h" +#include "py/gc.h" #include "py/runtime.h" #include "shared-bindings/displayio/ColorConverter.h" #include "shared-bindings/displayio/FourWire.h" @@ -298,7 +299,7 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c } bool common_hal_displayio_epaperdisplay_refresh(displayio_epaperdisplay_obj_t* self) { - + if (self->refreshing && self->busy.base.type == &digitalio_digitalinout_type) { if (common_hal_digitalio_digitalinout_get_value(&self->busy) != self->busy_state) { self->refreshing = false; @@ -365,6 +366,8 @@ void release_epaperdisplay(displayio_epaperdisplay_obj_t* self) { void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t* self) { displayio_display_core_collect_ptrs(&self->core); + gc_collect_ptr(self->start_sequence); + gc_collect_ptr(self->stop_sequence); } bool maybe_refresh_epaperdisplay(void) { -- cgit v1.2.3 From b32a9192df04c6fb36027b2b9b3e0e3a3548005a Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 27 Nov 2019 12:52:11 -0500 Subject: make UART.write be blocking on SAMD; add timeout property --- ports/atmel-samd/common-hal/busio/UART.c | 36 ++++++------ ports/cxd56/common-hal/busio/UART.c | 12 +++- ports/cxd56/common-hal/busio/UART.h | 2 +- ports/nrf/common-hal/busio/UART.c | 24 ++++---- ports/stm32f4/common-hal/busio/UART.c | 98 ++++++++++++++++++-------------- shared-bindings/board/__init__.c | 6 ++ shared-bindings/busio/UART.c | 46 +++++++++++++-- shared-bindings/busio/UART.h | 3 +- shared-module/board/__init__.c | 2 +- 9 files changed, 144 insertions(+), 85 deletions(-) (limited to 'shared-module') diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 2505e894a..d869f70ff 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -323,29 +323,23 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, struct io_descriptor *io; usart_async_get_io_descriptor(usart_desc_p, &io); + // Start writing characters. This is non-blocking and will + // return immediately after setting up the write. if (io_write(io, data, len) < 0) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } - // Wait until write is complete or timeout. - bool done = false; - uint64_t start_ticks = ticks_ms; - // Busy-wait for timeout. - while (ticks_ms - start_ticks < self->timeout_ms) { - if (usart_async_is_tx_empty(usart_desc_p)) { - done = true; + // Busy-wait until all characters transmitted. + struct usart_async_status async_status; + while (true) { + usart_async_get_status(usart_desc_p, &async_status); + if (async_status.txcnt >= len) { break; } RUN_BACKGROUND_TASKS; } - if (!done) { - *errcode = MP_EAGAIN; - return MP_STREAM_ERROR; - } - - // All the characters got written. return len; } @@ -368,6 +362,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat self->baudrate = baudrate; } +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return (mp_float_t) (self->timeout_ms / 1000.0f); +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + self->timeout_ms = timeout * 1000; +} + uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { // This assignment is only here because the usart_async routines take a *const argument. struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; @@ -383,12 +385,14 @@ void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) { } +// True if there are no characters still to be written. bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { if (self->tx_pin == NO_PIN) { return false; } // This assignment is only here because the usart_async routines take a *const argument. - const struct _usart_async_device * const usart_device_p = - (struct _usart_async_device * const) &self->usart_desc.device; - return _usart_async_is_byte_sent(usart_device_p); + struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; + struct usart_async_status async_status; + usart_async_get_status(usart_desc_p, &async_status); + return !(async_status.flags & USART_ASYNC_STATUS_BUSY); } diff --git a/ports/cxd56/common-hal/busio/UART.c b/ports/cxd56/common-hal/busio/UART.c index 4a1376f19..6ae2403c1 100644 --- a/ports/cxd56/common-hal/busio/UART.c +++ b/ports/cxd56/common-hal/busio/UART.c @@ -102,7 +102,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, self->tx_pin = tx; self->rx_pin = rx; self->baudrate = baudrate; - self->timeout = timeout; + self->timeout_us = timeout * 1000000; } void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { @@ -135,7 +135,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t FD_SET(busio_uart_dev[self->number].fd, &rfds); tv.tv_sec = 0; - tv.tv_usec = self->timeout * 1000; + tv.tv_usec = self->timeout_us; retval = select(busio_uart_dev[self->number].fd + 1, &rfds, NULL, NULL, &tv); @@ -172,6 +172,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat ioctl(busio_uart_dev[self->number].fd, TCFLSH, (long unsigned int)NULL); } +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return (mp_float_t) (self->timeout / 1000000.0f); +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + self->timeout_us = timeout * 1000000; +} + uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { int count = 0; diff --git a/ports/cxd56/common-hal/busio/UART.h b/ports/cxd56/common-hal/busio/UART.h index e1d816149..a69c47056 100644 --- a/ports/cxd56/common-hal/busio/UART.h +++ b/ports/cxd56/common-hal/busio/UART.h @@ -37,7 +37,7 @@ typedef struct { const mcu_pin_obj_t *tx_pin; const mcu_pin_obj_t *rx_pin; uint32_t baudrate; - uint32_t timeout; + uint32_t timeout_us; } busio_uart_obj_t; void busio_uart_reset(void); diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index 54a66ddbe..a0ae8af00 100644 --- a/ports/nrf/common-hal/busio/UART.c +++ b/ports/nrf/common-hal/busio/UART.c @@ -265,19 +265,6 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, if ( len == 0 ) return 0; - uint64_t start_ticks = ticks_ms; - - // Wait for on-going transfer to complete - while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) { - RUN_BACKGROUND_TASKS; - } - - // Time up - if ( !(ticks_ms - start_ticks < self->timeout_ms) ) { - *errcode = MP_EAGAIN; - return MP_STREAM_ERROR; - } - // EasyDMA can only access SRAM uint8_t * tx_buf = (uint8_t*) data; if ( !nrfx_is_in_ram(data) ) { @@ -290,7 +277,8 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, _VERIFY_ERR(*errcode); (*errcode) = 0; - while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) { + // Wait for write to complete. + while ( nrfx_uarte_tx_in_progress(self->uarte) ) { RUN_BACKGROUND_TASKS; } @@ -310,6 +298,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat nrf_uarte_baudrate_set(self->uarte->p_reg, get_nrf_baud(baudrate)); } +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return (mp_float_t) (self->timeout_ms / 1000.0f); +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + self->timeout_ms = timeout * 1000; +} + uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { return ringbuf_count(&self->rbuf); } diff --git a/ports/stm32f4/common-hal/busio/UART.c b/ports/stm32f4/common-hal/busio/UART.c index c4ab237cd..f0e0cc9eb 100644 --- a/ports/stm32f4/common-hal/busio/UART.c +++ b/ports/stm32f4/common-hal/busio/UART.c @@ -36,7 +36,7 @@ #include "supervisor/shared/translate.h" #include "tick.h" -#include "stm32f4xx_hal.h" +#include "stm32f4xx_hal.h" #define ALL_UARTS 0xFFFF @@ -55,7 +55,7 @@ void uart_reset(void) { uart_clock_disable(ALL_UARTS); } -STATIC USART_TypeDef * assign_uart_or_throw(busio_uart_obj_t* self, bool pin_eval, +STATIC USART_TypeDef * assign_uart_or_throw(busio_uart_obj_t* self, bool pin_eval, int uart_index, bool uart_taken) { if (pin_eval) { //assign a root pointer pointer for IRQ @@ -82,7 +82,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, uint8_t rx_len = sizeof(mcu_uart_rx_list)/sizeof(*mcu_uart_rx_list); bool uart_taken = false; uint8_t uart_index = 0; //origin 0 corrected - + //Can have both pins, or either if ((tx != mp_const_none) && (rx != mp_const_none)) { //normal find loop if both pins exist @@ -90,7 +90,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, if (mcu_uart_tx_list[i].pin == tx) { //rx for (uint j = 0; j < rx_len; j++) { - if (mcu_uart_rx_list[j].pin == rx + if (mcu_uart_rx_list[j].pin == rx && mcu_uart_rx_list[j].uart_index == mcu_uart_tx_list[i].uart_index) { //keep looking if the UART is taken, edge case if (reserved_uart[mcu_uart_tx_list[i].uart_index - 1]) { @@ -106,7 +106,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, } } uart_index = self->tx->uart_index - 1; - USARTx = assign_uart_or_throw(self, (self->tx != NULL && self->rx != NULL), + USARTx = assign_uart_or_throw(self, (self->tx != NULL && self->rx != NULL), uart_index, uart_taken); } else if (tx == mp_const_none) { //If there is no tx, run only rx @@ -123,7 +123,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, } } uart_index = self->rx->uart_index - 1; - USARTx = assign_uart_or_throw(self, (self->rx != NULL), + USARTx = assign_uart_or_throw(self, (self->rx != NULL), uart_index, uart_taken); } else if (rx == mp_const_none) { //If there is no rx, run only tx @@ -140,7 +140,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, } } uart_index = self->tx->uart_index - 1; - USARTx = assign_uart_or_throw(self, (self->tx != NULL), + USARTx = assign_uart_or_throw(self, (self->tx != NULL), uart_index, uart_taken); } else { //both pins cannot be empty @@ -173,7 +173,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = self->rx->altfn_index; + GPIO_InitStruct.Alternate = self->rx->altfn_index; HAL_GPIO_Init(pin_port(rx->port), &GPIO_InitStruct); } @@ -186,7 +186,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, self->handle.Init.BaudRate = baudrate; self->handle.Init.WordLength = (bits == 9) ? UART_WORDLENGTH_9B : UART_WORDLENGTH_8B; self->handle.Init.StopBits = (stop > 1) ? UART_STOPBITS_2 : UART_STOPBITS_1; - self->handle.Init.Parity = (parity == PARITY_ODD) ? UART_PARITY_ODD : + self->handle.Init.Parity = (parity == PARITY_ODD) ? UART_PARITY_ODD : (parity == PARITY_EVEN) ? UART_PARITY_EVEN : UART_PARITY_NONE; self->handle.Init.Mode = (self->tx != NULL && self->rx != NULL) ? UART_MODE_TX_RX : @@ -234,7 +234,7 @@ bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { if (common_hal_busio_uart_deinited(self)) return; - + reset_pin_number(self->tx->pin->port,self->tx->pin->number); reset_pin_number(self->rx->pin->port,self->rx->pin->number); self->tx = mp_const_none; @@ -279,7 +279,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t *errcode = EAGAIN; return MP_STREAM_ERROR; } - return rx_bytes; + return rx_bytes; } // Write characters. @@ -290,13 +290,15 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, bool write_err = false; //write error shouldn't disable interrupts HAL_NVIC_DisableIRQ(self->irq); - if (HAL_UART_Transmit(&self->handle, (uint8_t*)data, len, self->timeout_ms) != HAL_OK) { + if (HAL_UART_Transmit(&self->handle, (uint8_t*)data, len, HAL_MAX_DELAY) != HAL_OK) { write_err = true; } HAL_UART_Receive_IT(&self->handle, &self->rx_char, 1); HAL_NVIC_EnableIRQ(self->irq); - if (write_err) mp_raise_ValueError(translate("UART write error")); + if (write_err) { + mp_raise_ValueError(translate("UART write error")); + } return len; } @@ -312,7 +314,7 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *handle) } ringbuf_put_n(&context->rbuf, &context->rx_char, 1); errflag = HAL_UART_Receive_IT(handle, &context->rx_char, 1); - + return; } } @@ -360,6 +362,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat self->baudrate = baudrate; } +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return (mp_float_t) (self->timeout_ms / 1000.0f); +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + self->timeout_ms = timeout * 1000; +} + uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { return ringbuf_count(&self->rbuf); } @@ -414,71 +424,71 @@ STATIC void uart_clock_enable(uint16_t mask) { if (mask & (1 << 0)) { __HAL_RCC_USART1_FORCE_RESET(); __HAL_RCC_USART1_RELEASE_RESET(); - __HAL_RCC_USART1_CLK_ENABLE(); + __HAL_RCC_USART1_CLK_ENABLE(); } #endif #ifdef USART2 if (mask & (1 << 1)) { __HAL_RCC_USART2_FORCE_RESET(); __HAL_RCC_USART2_RELEASE_RESET(); - __HAL_RCC_USART2_CLK_ENABLE(); + __HAL_RCC_USART2_CLK_ENABLE(); } #endif #ifdef USART3 if (mask & (1 << 2)) { __HAL_RCC_USART3_FORCE_RESET(); __HAL_RCC_USART3_RELEASE_RESET(); - __HAL_RCC_USART3_CLK_ENABLE(); + __HAL_RCC_USART3_CLK_ENABLE(); } #endif #ifdef UART4 if (mask & (1 << 3)) { __HAL_RCC_UART4_FORCE_RESET(); __HAL_RCC_UART4_RELEASE_RESET(); - __HAL_RCC_UART4_CLK_ENABLE(); + __HAL_RCC_UART4_CLK_ENABLE(); } #endif #ifdef UART5 if (mask & (1 << 4)) { __HAL_RCC_UART5_FORCE_RESET(); __HAL_RCC_UART5_RELEASE_RESET(); - __HAL_RCC_UART5_CLK_ENABLE(); + __HAL_RCC_UART5_CLK_ENABLE(); } #endif #ifdef USART6 if (mask & (1 << 5)) { __HAL_RCC_USART6_FORCE_RESET(); __HAL_RCC_USART6_RELEASE_RESET(); - __HAL_RCC_USART6_CLK_ENABLE(); - } + __HAL_RCC_USART6_CLK_ENABLE(); + } #endif #ifdef UART7 if (mask & (1 << 6)) { __HAL_RCC_UART7_FORCE_RESET(); __HAL_RCC_UART7_RELEASE_RESET(); - __HAL_RCC_UART7_CLK_ENABLE(); - } + __HAL_RCC_UART7_CLK_ENABLE(); + } #endif #ifdef UART8 if (mask & (1 << 7)) { __HAL_RCC_UART8_FORCE_RESET(); __HAL_RCC_UART8_RELEASE_RESET(); - __HAL_RCC_UART8_CLK_ENABLE(); - } + __HAL_RCC_UART8_CLK_ENABLE(); + } #endif #ifdef UART9 if (mask & (1 << 8)) { __HAL_RCC_UART9_FORCE_RESET(); __HAL_RCC_UART9_RELEASE_RESET(); - __HAL_RCC_UART9_CLK_ENABLE(); - } + __HAL_RCC_UART9_CLK_ENABLE(); + } #endif #ifdef UART10 if (mask & (1 << 9)) { __HAL_RCC_UART10_FORCE_RESET(); __HAL_RCC_UART10_RELEASE_RESET(); - __HAL_RCC_UART10_CLK_ENABLE(); - } + __HAL_RCC_UART10_CLK_ENABLE(); + } #endif } @@ -487,71 +497,71 @@ STATIC void uart_clock_disable(uint16_t mask) { if (mask & (1 << 0)) { __HAL_RCC_USART1_FORCE_RESET(); __HAL_RCC_USART1_RELEASE_RESET(); - __HAL_RCC_USART1_CLK_DISABLE(); + __HAL_RCC_USART1_CLK_DISABLE(); } #endif #ifdef USART2 if (mask & (1 << 1)) { __HAL_RCC_USART2_FORCE_RESET(); __HAL_RCC_USART2_RELEASE_RESET(); - __HAL_RCC_USART2_CLK_DISABLE(); + __HAL_RCC_USART2_CLK_DISABLE(); } #endif #ifdef USART3 if (mask & (1 << 2)) { __HAL_RCC_USART3_FORCE_RESET(); __HAL_RCC_USART3_RELEASE_RESET(); - __HAL_RCC_USART3_CLK_DISABLE(); + __HAL_RCC_USART3_CLK_DISABLE(); } #endif #ifdef UART4 if (mask & (1 << 3)) { __HAL_RCC_UART4_FORCE_RESET(); __HAL_RCC_UART4_RELEASE_RESET(); - __HAL_RCC_UART4_CLK_DISABLE(); + __HAL_RCC_UART4_CLK_DISABLE(); } #endif #ifdef UART5 if (mask & (1 << 4)) { __HAL_RCC_UART5_FORCE_RESET(); __HAL_RCC_UART5_RELEASE_RESET(); - __HAL_RCC_UART5_CLK_DISABLE(); + __HAL_RCC_UART5_CLK_DISABLE(); } #endif #ifdef USART6 if (mask & (1 << 5)) { __HAL_RCC_USART6_FORCE_RESET(); __HAL_RCC_USART6_RELEASE_RESET(); - __HAL_RCC_USART6_CLK_DISABLE(); - } + __HAL_RCC_USART6_CLK_DISABLE(); + } #endif #ifdef UART7 if (mask & (1 << 6)) { __HAL_RCC_UART7_FORCE_RESET(); __HAL_RCC_UART7_RELEASE_RESET(); - __HAL_RCC_UART7_CLK_DISABLE(); - } + __HAL_RCC_UART7_CLK_DISABLE(); + } #endif #ifdef UART8 if (mask & (1 << 7)) { __HAL_RCC_UART8_FORCE_RESET(); __HAL_RCC_UART8_RELEASE_RESET(); - __HAL_RCC_UART8_CLK_DISABLE(); - } + __HAL_RCC_UART8_CLK_DISABLE(); + } #endif #ifdef UART9 if (mask & (1 << 8)) { __HAL_RCC_UART9_FORCE_RESET(); __HAL_RCC_UART9_RELEASE_RESET(); - __HAL_RCC_UART9_CLK_DISABLE(); - } + __HAL_RCC_UART9_CLK_DISABLE(); + } #endif #ifdef UART10 if (mask & (1 << 9)) { __HAL_RCC_UART10_FORCE_RESET(); __HAL_RCC_UART10_RELEASE_RESET(); - __HAL_RCC_UART10_CLK_DISABLE(); - } + __HAL_RCC_UART10_CLK_DISABLE(); + } #endif } diff --git a/shared-bindings/board/__init__.c b/shared-bindings/board/__init__.c index 47e2d64bc..3dda59fb8 100644 --- a/shared-bindings/board/__init__.c +++ b/shared-bindings/board/__init__.c @@ -93,6 +93,12 @@ MP_DEFINE_CONST_FUN_OBJ_0(board_spi_obj, board_spi); //| //| Returns the `busio.UART` object for the board designated TX and RX pins. It is a singleton. //| +//| The object created uses the default parameter values for `busio.UART`. If you need to set +//| parameters that are not changeable after creation, such as ``receiver_buffer_size``, +//| do not use `board.UART()`; instead create a `busio.UART` object explicitly with the +//| desired parameters. +//| +//| #if BOARD_UART mp_obj_t board_uart(void) { mp_obj_t singleton = common_hal_board_get_uart(); diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index c7eef8c43..9606c77e9 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -57,7 +57,7 @@ //| :param int bits: the number of bits per byte, 7, 8 or 9. //| :param Parity parity: the parity used for error checking. //| :param int stop: the number of stop bits, 1 or 2. -//| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters. Raises ``ValueError`` if timeout >100 seconds. +//| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters when reading. Raises ``ValueError`` if timeout >100 seconds. //| :param int receiver_buffer_size: the character length of the read buffer (0 to disable). (When a character is 9 bits the buffer will be 2 * receiver_buffer_size bytes.) //| //| *New in CircuitPython 4.0:* ``timeout`` has incompatibly changed units from milliseconds to seconds. @@ -69,6 +69,12 @@ typedef struct { extern const busio_uart_parity_obj_t busio_uart_parity_even_obj; extern const busio_uart_parity_obj_t busio_uart_parity_odd_obj; +STATIC void validate_timeout(mp_float_t timeout) { + if (timeout < (mp_float_t) 0.0f || timeout > (mp_float_t) 100.0f) { + mp_raise_ValueError(translate("timeout must be 0.0-100.0 (units are now seconds, not msecs)")); + } +} + STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // Always initially allocate the UART object within the long-lived heap. // This is needed to avoid crashes with certain UART implementations which @@ -116,9 +122,7 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co } mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); - if (timeout > (mp_float_t)100.0) { - mp_raise_ValueError(translate("timeout >100 (units are now seconds, not msecs)")); - } + validate_timeout(timeout); common_hal_busio_uart_construct(self, tx, rx, args[ARG_baudrate].u_int, bits, parity, stop, timeout, @@ -286,6 +290,35 @@ const mp_obj_property_t busio_uart_in_waiting_obj = { (mp_obj_t)&mp_const_none_obj}, }; +//| .. attribute:: timeout +//| +//| The current timeout, in seconds (float). +//| +STATIC mp_obj_t busio_uart_obj_get_timeout(mp_obj_t self_in) { + busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_float(common_hal_busio_uart_get_timeout(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_get_timeout_obj, busio_uart_obj_get_timeout); + +STATIC mp_obj_t busio_uart_obj_set_timeout(mp_obj_t self_in, mp_obj_t timeout) { + busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + mp_float_t timeout_float = mp_obj_get_float(timeout); + validate_timeout(timeout_float); + common_hal_busio_uart_set_timeout(self, timeout_float); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(busio_uart_set_timeout_obj, busio_uart_obj_set_timeout); + + +const mp_obj_property_t busio_uart_timeout_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&busio_uart_get_timeout_obj, + (mp_obj_t)&busio_uart_set_timeout_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + //| .. method:: reset_input_buffer() //| //| Discard any unread characters in the input buffer. @@ -355,8 +388,9 @@ STATIC const mp_rom_map_elem_t busio_uart_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&busio_uart_reset_input_buffer_obj) }, // Properties - { MP_ROM_QSTR(MP_QSTR_baudrate), MP_ROM_PTR(&busio_uart_baudrate_obj) }, - { MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&busio_uart_in_waiting_obj) }, + { MP_ROM_QSTR(MP_QSTR_baudrate), MP_ROM_PTR(&busio_uart_baudrate_obj) }, + { MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&busio_uart_in_waiting_obj) }, + { MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&busio_uart_timeout_obj) }, // Nested Enum-like Classes. { MP_ROM_QSTR(MP_QSTR_Parity), MP_ROM_PTR(&busio_uart_parity_type) }, diff --git a/shared-bindings/busio/UART.h b/shared-bindings/busio/UART.h index 776a996be..cfd2c800c 100644 --- a/shared-bindings/busio/UART.h +++ b/shared-bindings/busio/UART.h @@ -57,7 +57,8 @@ extern size_t common_hal_busio_uart_write(busio_uart_obj_t *self, extern uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self); extern void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate); - +extern mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self); +extern void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout); extern uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self); extern void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self); diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index dd07d7190..914bc4313 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -101,7 +101,7 @@ mp_obj_t common_hal_board_create_uart(void) { const mcu_pin_obj_t* rx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RX); const mcu_pin_obj_t* tx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_TX); - common_hal_busio_uart_construct(self, tx, rx, 9600, 8, PARITY_NONE, 1, 1000, 64); + common_hal_busio_uart_construct(self, tx, rx, 9600, 8, PARITY_NONE, 1, 1.0f, 64); MP_STATE_VM(shared_uart_bus) = MP_OBJ_FROM_PTR(self); return MP_STATE_VM(shared_uart_bus); } -- cgit v1.2.3