From 2a0b8576439b0cfefff909135dba424a2a179275 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 29 Jun 2018 16:01:46 -0400 Subject: [PATCH] implement mp_hal_delay_us() to not need interrupts, and use it --- ports/atmel-samd/mphalport.c | 9 +++----- ports/atmel-samd/mphalport.h | 2 -- ports/esp8266/Makefile | 1 - .../nrf/common-hal/microcontroller/__init__.c | 3 ++- ports/nrf/mphalport.c | 14 ------------ ports/nrf/mphalport.h | 2 -- shared-module/bitbangio/OneWire.c | 22 +++++++++---------- 7 files changed, 15 insertions(+), 38 deletions(-) diff --git a/ports/atmel-samd/mphalport.c b/ports/atmel-samd/mphalport.c index 7bb423a3e6..a4eca1c748 100644 --- a/ports/atmel-samd/mphalport.c +++ b/ports/atmel-samd/mphalport.c @@ -99,10 +99,7 @@ void mp_hal_delay_ms(mp_uint_t delay) { } } -void mp_hal_delay_us(mp_uint_t delay) { - tick_delay(delay); -} - +// Use mp_hal_delay_us() for timing of less than 1ms. // Do a simple timing loop to wait for a certain number of microseconds. // Can be used when interrupts are disabled, which makes tick_delay() unreliable. // @@ -115,8 +112,8 @@ void mp_hal_delay_us(mp_uint_t delay) { #define DELAY_LOOP_ITERATIONS_PER_US ( (30U*120000000U) / common_hal_mcu_processor_get_frequency()) #endif -void mp_hal_delay_us_loop(uint32_t us) { - for (uint32_t i = us*DELAY_LOOP_ITERATIONS_PER_US; i > 0; i--) { +void mp_hal_delay_us(mp_uint_t delay) { + for (uint32_t i = delay*DELAY_LOOP_ITERATIONS_PER_US; i > 0; i--) { asm volatile("nop"); } } diff --git a/ports/atmel-samd/mphalport.h b/ports/atmel-samd/mphalport.h index 31d34c8c39..3bc824d4e9 100644 --- a/ports/atmel-samd/mphalport.h +++ b/ports/atmel-samd/mphalport.h @@ -50,6 +50,4 @@ void mp_hal_set_interrupt_char(int c); void mp_hal_disable_all_interrupts(void); void mp_hal_enable_all_interrupts(void); -void mp_hal_delay_us_loop(uint32_t us); - #endif // MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 02b75eadd5..8fabd3412a 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -92,7 +92,6 @@ SRC_C = \ machine_hspi.c \ modesp.c \ modnetwork.c \ - mphalport.c \ ets_alt_task.c \ fatfs_port.c \ posix_helpers.c \ diff --git a/ports/nrf/common-hal/microcontroller/__init__.c b/ports/nrf/common-hal/microcontroller/__init__.c index e26acff1b4..4399e7708c 100644 --- a/ports/nrf/common-hal/microcontroller/__init__.c +++ b/ports/nrf/common-hal/microcontroller/__init__.c @@ -33,6 +33,8 @@ #include "shared-bindings/microcontroller/Processor.h" // TODO porting common_hal_mcu +// This routine should work even when interrupts are disabled. Used by OneWire +// for precise timing. void common_hal_mcu_delay_us(uint32_t delay) { // os_delay_us(delay); } @@ -58,4 +60,3 @@ const mcu_processor_obj_t common_hal_mcu_processor_obj = { .type = &mcu_processor_type, }, }; - diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 014d410ecf..d0447f06c3 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -85,17 +85,3 @@ void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } - -// Do a simple timing loop to wait for a certain number of microseconds. -// Can be used when interrupts are disabled, which makes tick_delay() unreliable. -// -// Testing done at 48 MHz on SAMD21 and 120 MHz on SAMD51 (cache on). -// TODO: Test on NRF. For now, use SAMD51 calibration, even though nRF52 runs slower. -// Fraction should compensate. -#define DELAY_LOOP_ITERATIONS_PER_US ( (30U*120000000U) / common_hal_mcu_processor_get_frequency()) - -void mp_hal_delay_us_loop(uint32_t us) { - for (uint32_t i = us*DELAY_LOOP_ITERATIONS_PER_US; i > 0; i--) { - asm volatile("nop"); - } -} diff --git a/ports/nrf/mphalport.h b/ports/nrf/mphalport.h index 79e1d2d58e..a872477370 100644 --- a/ports/nrf/mphalport.h +++ b/ports/nrf/mphalport.h @@ -52,7 +52,6 @@ static inline uint32_t hal_tick_fake(void) { extern const unsigned char mp_hal_status_to_errno_table[4]; - NORETURN void mp_hal_raise(HAL_StatusTypeDef status); void mp_hal_set_interrupt_char(int c); // -1 to disable @@ -70,7 +69,6 @@ bool mp_hal_stdin_any(void); #define mp_hal_pin_od_high(p) mp_hal_pin_high(p) #define mp_hal_pin_open_drain(p) hal_gpio_cfg_pin(p->port, p->pin, HAL_GPIO_MODE_INPUT, HAL_GPIO_PULL_DISABLED) -void mp_hal_delay_us_loop(uint32_t us); // TODO: empty implementation for now. Used by machine_spi.c:69 #define mp_hal_delay_us_fast(p) diff --git a/shared-module/bitbangio/OneWire.c b/shared-module/bitbangio/OneWire.c index b226b9d784..f5f4790876 100644 --- a/shared-module/bitbangio/OneWire.c +++ b/shared-module/bitbangio/OneWire.c @@ -24,8 +24,6 @@ * THE SOFTWARE. */ -#include "mphalport.h" - #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/bitbangio/OneWire.h" #include "shared-bindings/microcontroller/__init__.h" @@ -51,17 +49,17 @@ void shared_module_bitbangio_onewire_deinit(bitbangio_onewire_obj_t* self) { common_hal_digitalio_digitalinout_deinit(&self->pin); } -// We can't use common_hal_mcu_delay_us() here because it needs interrupts to be accurate -// due to SysTick rollover checking, done by an interrupt. +// We use common_hal_mcu_delay_us(). It should not be dependent on interrupts +// to do accurate timekeeping, since we disable interrupts during the delays below. bool shared_module_bitbangio_onewire_reset(bitbangio_onewire_obj_t* self) { common_hal_mcu_disable_interrupts(); common_hal_digitalio_digitalinout_switch_to_output(&self->pin, false, DRIVE_MODE_OPEN_DRAIN); - mp_hal_delay_us_loop(480); + common_hal_mcu_delay_us(480); common_hal_digitalio_digitalinout_switch_to_input(&self->pin, PULL_NONE); - mp_hal_delay_us_loop(70); + common_hal_mcu_delay_us(70); bool value = common_hal_digitalio_digitalinout_get_value(&self->pin); - mp_hal_delay_us_loop(410); + common_hal_mcu_delay_us(410); common_hal_mcu_enable_interrupts(); return value; } @@ -69,14 +67,14 @@ bool shared_module_bitbangio_onewire_reset(bitbangio_onewire_obj_t* self) { bool shared_module_bitbangio_onewire_read_bit(bitbangio_onewire_obj_t* self) { common_hal_mcu_disable_interrupts(); common_hal_digitalio_digitalinout_switch_to_output(&self->pin, false, DRIVE_MODE_OPEN_DRAIN); - mp_hal_delay_us_loop(6); + common_hal_mcu_delay_us(6); common_hal_digitalio_digitalinout_switch_to_input(&self->pin, PULL_NONE); // TODO(tannewt): Test with more devices and maybe make the delays // configurable. This should be 9 by the datasheet but all bits read as 1 // then. - mp_hal_delay_us_loop(6); + common_hal_mcu_delay_us(6); bool value = common_hal_digitalio_digitalinout_get_value(&self->pin); - mp_hal_delay_us_loop(55); + common_hal_mcu_delay_us(55); common_hal_mcu_enable_interrupts(); return value; } @@ -85,8 +83,8 @@ void shared_module_bitbangio_onewire_write_bit(bitbangio_onewire_obj_t* self, bool bit) { common_hal_mcu_disable_interrupts(); common_hal_digitalio_digitalinout_switch_to_output(&self->pin, false, DRIVE_MODE_OPEN_DRAIN); - mp_hal_delay_us_loop(bit? 6 : 60); + common_hal_mcu_delay_us(bit? 6 : 60); common_hal_digitalio_digitalinout_switch_to_input(&self->pin, PULL_NONE); - mp_hal_delay_us_loop(bit? 64 : 10); + common_hal_mcu_delay_us(bit? 64 : 10); common_hal_mcu_enable_interrupts(); }