From 2433c9572c4d41907b903860d717e2b25a117b21 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 1 Dec 2021 16:14:37 -0800 Subject: [PATCH 1/2] Add full pin mux info and use it for I2C All I2C peripherals should be usable now. This also adds pin in-use tracking and resetting. Part of #5629 --- ports/broadcom/Makefile | 1 + ports/broadcom/broadcom_peripherals_config.h | 34 ++++++ ports/broadcom/common-hal/busio/I2C.c | 56 +++++++--- .../broadcom/common-hal/microcontroller/Pin.c | 101 ++++++------------ .../broadcom/common-hal/microcontroller/Pin.h | 69 +----------- .../common-hal/microcontroller/__init__.c | 2 + ports/broadcom/peripherals | 2 +- 7 files changed, 111 insertions(+), 154 deletions(-) create mode 100644 ports/broadcom/broadcom_peripherals_config.h diff --git a/ports/broadcom/Makefile b/ports/broadcom/Makefile index a5a3f744b7f1..16b44f75019c 100644 --- a/ports/broadcom/Makefile +++ b/ports/broadcom/Makefile @@ -63,6 +63,7 @@ SRC_C += bindings/videocore/__init__.c \ lib/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c \ peripherals/broadcom/caches.c \ peripherals/broadcom/gen/interrupt_handlers.c \ + peripherals/broadcom/gen/pins.c \ peripherals/broadcom/gpio.c \ peripherals/broadcom/interrupts.c \ peripherals/broadcom/mmu.c \ diff --git a/ports/broadcom/broadcom_peripherals_config.h b/ports/broadcom/broadcom_peripherals_config.h new file mode 100644 index 000000000000..e31b3f635c8a --- /dev/null +++ b/ports/broadcom/broadcom_peripherals_config.h @@ -0,0 +1,34 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "py/obj.h" + +extern const mp_obj_type_t mcu_pin_type; + +#define PIN_PREFIX_VALUES { &mcu_pin_type }, +#define PIN_PREFIX_FIELDS mp_obj_base_t base; diff --git a/ports/broadcom/common-hal/busio/I2C.c b/ports/broadcom/common-hal/busio/I2C.c index 608b1ded15ec..7301e6314b4d 100644 --- a/ports/broadcom/common-hal/busio/I2C.c +++ b/ports/broadcom/common-hal/busio/I2C.c @@ -35,35 +35,63 @@ #include "peripherals/broadcom/cpu.h" #include "peripherals/broadcom/vcmailbox.h" -#define NUM_I2C (2) +#if BCM_VERSION == 2711 +#define NUM_I2C (8) +STATIC BSC0_Type *i2c[NUM_I2C] = {BSC0, BSC1, NULL, BSC3, BSC4, BSC5, BSC6, NULL}; +#else +#define NUM_I2C (3) +STATIC BSC0_Type *i2c[NUM_I2C] = {BSC0, BSC1, NULL}; +#endif STATIC bool never_reset_i2c[NUM_I2C]; -STATIC bool in_use_i2c[NUM_I2C]; -STATIC BSC0_Type *i2c[2] = {BSC0, BSC1}; +STATIC bool i2c_in_use[NUM_I2C]; void reset_i2c(void) { + // BSC2 is dedicated to the first HDMI output. + never_reset_i2c[2] = true; + i2c_in_use[2] = true; + #if BCM_VERSION == 2711 + // BSC7 is dedicated to the second HDMI output. + never_reset_i2c[7] = true; + i2c_in_use[7] = true; + #endif for (size_t i = 0; i < 2; i++) { if (never_reset_i2c[i]) { continue; } - in_use_i2c[i] = false; + i2c_in_use[i] = false; + i2c[i]->C_b.I2CEN = false; + COMPLETE_MEMORY_READS; } } void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { size_t instance_index = NUM_I2C; - if ((scl == &pin_GPIO1 || scl == &pin_GPIO29 || scl == &pin_GPIO45) && - (sda == &pin_GPIO0 || sda == &pin_GPIO28 || sda == &pin_GPIO44)) { - instance_index = 0; - } else if ((scl == &pin_GPIO44 || scl == &pin_GPIO3) && - (sda == &pin_GPIO43 || sda == &pin_GPIO2)) { - instance_index = 1; + uint8_t scl_alt = 0; + uint8_t sda_alt = 0; + for (scl_alt = 0; scl_alt < 6; scl_alt++) { + if (scl->functions[scl_alt].type != PIN_FUNCTION_I2C || + i2c_in_use[scl->functions[scl_alt].index]) { + continue; + } + for (sda_alt = 0; sda_alt < 6; sda_alt++) { + if (sda->functions[sda_alt].type != PIN_FUNCTION_I2C || + scl->functions[scl_alt].index != sda->functions[sda_alt].index || + sda->functions[sda_alt].function != I2C_FUNCTION_SDA) { + continue; + } + instance_index = scl->functions[scl_alt].index; + break; + } + if (instance_index != NUM_I2C) { + break; + } } if (instance_index == NUM_I2C) { mp_raise_ValueError(translate("Invalid pins")); } - in_use_i2c[instance_index] = true; + i2c_in_use[instance_index] = true; self->index = instance_index; self->peripheral = i2c[self->index]; self->sda_pin = sda; @@ -73,8 +101,8 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, uint16_t clock_divider = source_clock / frequency; self->peripheral->DIV_b.CDIV = clock_divider; - gpio_set_function(sda->number, GPIO_GPFSEL0_FSEL2_SDA1); - gpio_set_function(scl->number, GPIO_GPFSEL0_FSEL3_SCL1); + gpio_set_function(sda->number, FSEL_VALUES[sda_alt]); + gpio_set_function(scl->number, FSEL_VALUES[scl_alt]); } bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { @@ -86,6 +114,7 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { return; } never_reset_i2c[self->index] = false; + i2c_in_use[self->index] = false; common_hal_reset_pin(self->sda_pin); common_hal_reset_pin(self->scl_pin); @@ -95,7 +124,6 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { uint8_t result = common_hal_busio_i2c_write(self, addr, NULL, 0, true); - // mp_printf(&mp_plat_print, "result %d %d\n", addr, result); return result == 0; } diff --git a/ports/broadcom/common-hal/microcontroller/Pin.c b/ports/broadcom/common-hal/microcontroller/Pin.c index 3c802a5727bc..d1e5627bcd58 100644 --- a/ports/broadcom/common-hal/microcontroller/Pin.c +++ b/ports/broadcom/common-hal/microcontroller/Pin.c @@ -28,14 +28,41 @@ #include "peripherals/broadcom/gpio.h" +STATIC bool pin_in_use[BCM_PIN_COUNT]; +STATIC bool never_reset_pin[BCM_PIN_COUNT]; + void reset_all_pins(void) { + for (size_t i = 0; i < BCM_PIN_COUNT; i++) { + if (never_reset_pin[i]) { + continue; + } + reset_pin_number(i); + } } void never_reset_pin_number(uint8_t pin_number) { + never_reset_pin[pin_number] = true; } void reset_pin_number(uint8_t pin_number) { - gpio_set_function(pin_number, 0); + gpio_set_function(pin_number, GPIO_FUNCTION_INPUT); + pin_in_use[pin_number] = false; + never_reset_pin[pin_number] = false; + // Set the pull to match the datasheet. + BP_PULL_Enum pull = BP_PULL_NONE; + if (pin_number < 9 || + (33 < pin_number && pin_number < 37) || + pin_number > 45) { + pull = BP_PULL_UP; + } else if (pin_number != 28 && + pin_number != 29 && + pin_number != 44 && + pin_number != 45) { + // Most pins are pulled low so we only exclude the four pins that aren't + // pulled at all. + pull = BP_PULL_DOWN; + } + gpio_set_pull(pin_number, pull); } void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) { @@ -47,11 +74,11 @@ void common_hal_reset_pin(const mcu_pin_obj_t *pin) { } void claim_pin(const mcu_pin_obj_t *pin) { - // Nothing to do because all changes will set the GPIO settings. + pin_in_use[pin->number] = true; } bool pin_number_is_free(uint8_t pin_number) { - return true; + return !pin_in_use[pin_number]; } bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) { @@ -69,71 +96,3 @@ void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) { void common_hal_mcu_pin_reset_number(uint8_t pin_no) { reset_pin_number(pin_no); } - -#define PIN(num) \ - const mcu_pin_obj_t pin_GPIO##num = { \ - { &mcu_pin_type }, \ - .number = num \ - }; - -PIN(0) -PIN(1) -PIN(2) -PIN(3) -PIN(4) -PIN(5) -PIN(6) -PIN(7) -PIN(8) -PIN(9) -PIN(10) -PIN(11) -PIN(12) -PIN(13) -PIN(14) -PIN(15) -PIN(16) -PIN(17) -PIN(18) -PIN(19) -PIN(20) -PIN(21) -PIN(22) -PIN(23) -PIN(24) -PIN(25) -PIN(26) -PIN(27) -PIN(28) -PIN(29) - -PIN(30) -PIN(31) -PIN(32) -PIN(33) -PIN(34) -PIN(35) -PIN(36) -PIN(37) -PIN(38) -PIN(39) - -PIN(40) -PIN(41) -PIN(42) -PIN(43) -PIN(44) -PIN(45) -PIN(46) -PIN(47) -PIN(48) -PIN(49) - -PIN(50) -PIN(51) -PIN(52) -PIN(53) -PIN(54) -PIN(55) -PIN(56) -PIN(57) diff --git a/ports/broadcom/common-hal/microcontroller/Pin.h b/ports/broadcom/common-hal/microcontroller/Pin.h index 9c9b28f1e692..d234657ddab7 100644 --- a/ports/broadcom/common-hal/microcontroller/Pin.h +++ b/ports/broadcom/common-hal/microcontroller/Pin.h @@ -32,74 +32,7 @@ #include -typedef struct { - mp_obj_base_t base; - uint8_t number; -} mcu_pin_obj_t; - -extern const mcu_pin_obj_t pin_GPIO0; -extern const mcu_pin_obj_t pin_GPIO1; -extern const mcu_pin_obj_t pin_GPIO2; -extern const mcu_pin_obj_t pin_GPIO3; -extern const mcu_pin_obj_t pin_GPIO4; -extern const mcu_pin_obj_t pin_GPIO5; -extern const mcu_pin_obj_t pin_GPIO6; -extern const mcu_pin_obj_t pin_GPIO7; -extern const mcu_pin_obj_t pin_GPIO8; -extern const mcu_pin_obj_t pin_GPIO9; - -extern const mcu_pin_obj_t pin_GPIO10; -extern const mcu_pin_obj_t pin_GPIO11; -extern const mcu_pin_obj_t pin_GPIO12; -extern const mcu_pin_obj_t pin_GPIO13; -extern const mcu_pin_obj_t pin_GPIO14; -extern const mcu_pin_obj_t pin_GPIO15; -extern const mcu_pin_obj_t pin_GPIO16; -extern const mcu_pin_obj_t pin_GPIO17; -extern const mcu_pin_obj_t pin_GPIO18; -extern const mcu_pin_obj_t pin_GPIO19; - -extern const mcu_pin_obj_t pin_GPIO20; -extern const mcu_pin_obj_t pin_GPIO21; -extern const mcu_pin_obj_t pin_GPIO22; -extern const mcu_pin_obj_t pin_GPIO23; -extern const mcu_pin_obj_t pin_GPIO24; -extern const mcu_pin_obj_t pin_GPIO25; -extern const mcu_pin_obj_t pin_GPIO26; -extern const mcu_pin_obj_t pin_GPIO27; -extern const mcu_pin_obj_t pin_GPIO28; -extern const mcu_pin_obj_t pin_GPIO29; - -extern const mcu_pin_obj_t pin_GPIO30; -extern const mcu_pin_obj_t pin_GPIO31; -extern const mcu_pin_obj_t pin_GPIO32; -extern const mcu_pin_obj_t pin_GPIO33; -extern const mcu_pin_obj_t pin_GPIO34; -extern const mcu_pin_obj_t pin_GPIO35; -extern const mcu_pin_obj_t pin_GPIO36; -extern const mcu_pin_obj_t pin_GPIO37; -extern const mcu_pin_obj_t pin_GPIO38; -extern const mcu_pin_obj_t pin_GPIO39; - -extern const mcu_pin_obj_t pin_GPIO40; -extern const mcu_pin_obj_t pin_GPIO41; -extern const mcu_pin_obj_t pin_GPIO42; -extern const mcu_pin_obj_t pin_GPIO43; -extern const mcu_pin_obj_t pin_GPIO44; -extern const mcu_pin_obj_t pin_GPIO45; -extern const mcu_pin_obj_t pin_GPIO46; -extern const mcu_pin_obj_t pin_GPIO47; -extern const mcu_pin_obj_t pin_GPIO48; -extern const mcu_pin_obj_t pin_GPIO49; - -extern const mcu_pin_obj_t pin_GPIO50; -extern const mcu_pin_obj_t pin_GPIO51; -extern const mcu_pin_obj_t pin_GPIO52; -extern const mcu_pin_obj_t pin_GPIO53; -extern const mcu_pin_obj_t pin_GPIO54; -extern const mcu_pin_obj_t pin_GPIO55; -extern const mcu_pin_obj_t pin_GPIO56; -extern const mcu_pin_obj_t pin_GPIO57; +#include "peripherals/broadcom/pins.h" void reset_all_pins(void); // reset_pin_number takes the pin number instead of the pointer so that objects don't diff --git a/ports/broadcom/common-hal/microcontroller/__init__.c b/ports/broadcom/common-hal/microcontroller/__init__.c index 02ce04724c63..e6f7b9c73725 100644 --- a/ports/broadcom/common-hal/microcontroller/__init__.c +++ b/ports/broadcom/common-hal/microcontroller/__init__.c @@ -187,9 +187,11 @@ const mp_rom_map_elem_t mcu_pin_global_dict_table[TOTAL_GPIO_COUNT] = { PIN(51) PIN(52) PIN(53) + #if BCM_VERSION == 2711 PIN(54) PIN(55) PIN(56) PIN(57) + #endif }; MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table); diff --git a/ports/broadcom/peripherals b/ports/broadcom/peripherals index 8057af2d614c..2e7b56bbe941 160000 --- a/ports/broadcom/peripherals +++ b/ports/broadcom/peripherals @@ -1 +1 @@ -Subproject commit 8057af2d614c27a1e103d5f4300428f341da6bcb +Subproject commit 2e7b56bbe941311e54fba66f0b32336bfea4388d From 8adb0ecd334fe67d266bf119d420a2ecf6b372af Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 2 Dec 2021 10:28:26 -0800 Subject: [PATCH 2/2] Fix loop bounds --- ports/broadcom/common-hal/busio/I2C.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/broadcom/common-hal/busio/I2C.c b/ports/broadcom/common-hal/busio/I2C.c index 7301e6314b4d..9726f394d2de 100644 --- a/ports/broadcom/common-hal/busio/I2C.c +++ b/ports/broadcom/common-hal/busio/I2C.c @@ -55,7 +55,7 @@ void reset_i2c(void) { never_reset_i2c[7] = true; i2c_in_use[7] = true; #endif - for (size_t i = 0; i < 2; i++) { + for (size_t i = 0; i < NUM_I2C; i++) { if (never_reset_i2c[i]) { continue; }