mirror of
https://github.com/licsber/micropython.git
synced 2024-09-20 00:50:24 +08:00
rp2/modrp2: Disable other core, shorten delay to 8us in bootsel_button.
This function seems to work fine in multi-core applications now. The delay is now in units of microseconds instead of depending on the clock speed, and is adjustable by board configuration headers. Also added documentation.
This commit is contained in:
parent
673957b643
commit
f80d040c03
@ -66,6 +66,17 @@ For running PIO programs, see :class:`rp2.StateMachine`.
|
|||||||
>>> rp2.asm_pio_encode("set(0, 1)", 0)
|
>>> rp2.asm_pio_encode("set(0, 1)", 0)
|
||||||
57345
|
57345
|
||||||
|
|
||||||
|
.. function:: bootsel_button()
|
||||||
|
|
||||||
|
Temporarily turns the QSPI_SS pin into an input and reads its value,
|
||||||
|
returning 1 for low and 0 for high.
|
||||||
|
On a typical RP2040 board with a BOOTSEL button, a return value of 1
|
||||||
|
indicates that the button is pressed.
|
||||||
|
|
||||||
|
Since this function temporarily disables access to the external flash
|
||||||
|
memory, it also temporarily disables interrupts and the other core to
|
||||||
|
prevent them from trying to execute code from flash.
|
||||||
|
|
||||||
.. class:: PIOASMError
|
.. class:: PIOASMError
|
||||||
|
|
||||||
This exception is raised from `asm_pio()` or `asm_pio_encode()` if there is
|
This exception is raised from `asm_pio()` or `asm_pio_encode()` if there is
|
||||||
|
@ -41,49 +41,43 @@
|
|||||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_country_obj);
|
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_country_obj);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Picoboard has a button attached to the flash CS pin, which the bootrom
|
// Improved version of
|
||||||
// checks, and jumps straight to the USB bootcode if the button is pressed
|
|
||||||
// (pulling flash CS low). We can check this pin in by jumping to some code in
|
|
||||||
// SRAM (so that the XIP interface is not required), floating the flash CS
|
|
||||||
// pin, and observing whether it is pulled low.
|
|
||||||
//
|
|
||||||
// This doesn't work if others are trying to access flash at the same time,
|
|
||||||
// e.g. XIP streamer, or the other core.
|
|
||||||
// https://github.com/raspberrypi/pico-examples/blob/master/picoboard/button/button.c
|
// https://github.com/raspberrypi/pico-examples/blob/master/picoboard/button/button.c
|
||||||
|
STATIC bool __no_inline_not_in_flash_func(bootsel_button)(void) {
|
||||||
bool __no_inline_not_in_flash_func(get_bootsel_button)() {
|
|
||||||
const uint CS_PIN_INDEX = 1;
|
const uint CS_PIN_INDEX = 1;
|
||||||
|
|
||||||
// Must disable interrupts, as interrupt handlers may be in flash, and we
|
// Disable interrupts and the other core since they might be
|
||||||
// are about to temporarily disable flash access!
|
// executing code from flash and we are about to temporarily
|
||||||
uint32_t flags = save_and_disable_interrupts();
|
// disable flash access.
|
||||||
|
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
|
||||||
|
|
||||||
// Set chip select to Hi-Z
|
// Set the CS pin to high impedance.
|
||||||
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
|
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
|
||||||
GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
|
(GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB),
|
||||||
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
|
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
|
||||||
|
|
||||||
// Note we can't call into any sleep functions in flash right now
|
// Delay without calling any functions in flash.
|
||||||
for (volatile int i = 0; i < 1000; ++i) {;
|
uint32_t start = timer_hw->timerawl;
|
||||||
|
while ((uint32_t)(timer_hw->timerawl - start) <= MICROPY_HW_BOOTSEL_DELAY_US) {
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The HI GPIO registers in SIO can observe and control the 6 QSPI pins.
|
// The HI GPIO registers in SIO can observe and control the 6 QSPI pins.
|
||||||
// Note the button pulls the pin *low* when pressed.
|
// The button pulls the QSPI_SS pin *low* when pressed.
|
||||||
bool button_state = !(sio_hw->gpio_hi_in & (1u << CS_PIN_INDEX));
|
bool button_state = !(sio_hw->gpio_hi_in & (1 << CS_PIN_INDEX));
|
||||||
|
|
||||||
// Need to restore the state of chip select, else we are going to have a
|
// Restore the QSPI_SS pin so we can use flash again.
|
||||||
// bad time when we return to code in flash!
|
|
||||||
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
|
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
|
||||||
GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
|
(GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB),
|
||||||
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
|
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
|
||||||
|
|
||||||
restore_interrupts(flags);
|
MICROPY_END_ATOMIC_SECTION(atomic_state);
|
||||||
|
|
||||||
return button_state;
|
return button_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC mp_obj_t rp2_bootsel_button(void) {
|
STATIC mp_obj_t rp2_bootsel_button(void) {
|
||||||
return MP_OBJ_NEW_SMALL_INT(get_bootsel_button());
|
return MP_OBJ_NEW_SMALL_INT(bootsel_button());
|
||||||
}
|
}
|
||||||
MP_DEFINE_CONST_FUN_OBJ_0(rp2_bootsel_button_obj, rp2_bootsel_button);
|
MP_DEFINE_CONST_FUN_OBJ_0(rp2_bootsel_button_obj, rp2_bootsel_button);
|
||||||
|
|
||||||
|
@ -217,6 +217,10 @@ extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
|
|||||||
#define MICROPY_HW_USB_PID (0x0005) // RP2 MicroPython
|
#define MICROPY_HW_USB_PID (0x0005) // RP2 MicroPython
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MICROPY_HW_BOOTSEL_DELAY_US
|
||||||
|
#define MICROPY_HW_BOOTSEL_DELAY_US 8
|
||||||
|
#endif
|
||||||
|
|
||||||
// Entering a critical section.
|
// Entering a critical section.
|
||||||
extern uint32_t mp_thread_begin_atomic_section(void);
|
extern uint32_t mp_thread_begin_atomic_section(void);
|
||||||
extern void mp_thread_end_atomic_section(uint32_t);
|
extern void mp_thread_end_atomic_section(uint32_t);
|
||||||
|
Loading…
Reference in New Issue
Block a user