Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@
#define MICROPY_HW_BOARD_NAME "Makerdiary M60 Keyboard"
#define MICROPY_HW_MCU_NAME "nRF52840"

#define CP_RGB_STATUS_R (&pin_P0_30)
#define CP_RGB_STATUS_G (&pin_P0_29)
#define CP_RGB_STATUS_B (&pin_P0_31)
// RGB LEDs use PWM peripheral, avoid using them to save energy
// #define CP_RGB_STATUS_R (&pin_P0_30)
// #define CP_RGB_STATUS_G (&pin_P0_29)
// #define CP_RGB_STATUS_B (&pin_P0_31)

#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10)
#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14)
Expand Down
8 changes: 8 additions & 0 deletions ports/nrf/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@
#include "common-hal/audiopwmio/PWMAudioOut.h"
#endif

#if defined(MICROPY_QSPI_CS)
extern void qspi_disable(void);
#endif

static void power_warning_handler(void) {
reset_into_safe_mode(BROWNOUT);
}
Expand Down Expand Up @@ -295,6 +299,10 @@ void port_interrupt_after_ticks(uint32_t ticks) {
}

void port_sleep_until_interrupt(void) {
#if defined(MICROPY_QSPI_CS)
qspi_disable();
#endif

// Clear the FPU interrupt because it can prevent us from sleeping.
if (NVIC_GetPendingIRQ(FPU_IRQn)) {
__set_FPSCR(__get_FPSCR() & ~(0x9f));
Expand Down
42 changes: 42 additions & 0 deletions ports/nrf/supervisor/qspi_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,44 @@
#include "supervisor/shared/external_flash/common_commands.h"
#include "supervisor/shared/external_flash/qspi_flash.h"

// When USB is disconnected, disable QSPI in sleep mode to save energy
void qspi_disable(void)
{
// If VBUS is detected, no need to disable QSPI
if (NRF_QSPI->ENABLE && !(NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk)) {
// Keep CS high when QSPI is diabled
nrf_gpio_cfg_output(MICROPY_QSPI_CS);
nrf_gpio_pin_write(MICROPY_QSPI_CS, 1);

// Workaround to disable QSPI according to nRF52840 Revision 1 Errata V1.4 - 3.8
NRF_QSPI->TASKS_DEACTIVATE = 1;
*(volatile uint32_t *)0x40029054 = 1;
NRF_QSPI->ENABLE = 0;
}
}

void qspi_enable(void)
{
if (NRF_QSPI->ENABLE) {
return;
}

nrf_qspi_enable(NRF_QSPI);

nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_ACTIVATE);

uint32_t remaining_attempts = 100;
do {
if (nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY)) {
break;
}
NRFX_DELAY_US(10);
} while (--remaining_attempts);
}

bool spi_flash_command(uint8_t command) {
qspi_enable();
nrf_qspi_cinstr_conf_t cinstr_cfg = {
.opcode = command,
.length = 1,
Expand All @@ -51,6 +88,7 @@ bool spi_flash_command(uint8_t command) {
}

bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) {
qspi_enable();
nrf_qspi_cinstr_conf_t cinstr_cfg = {
.opcode = command,
.length = length + 1,
Expand All @@ -64,6 +102,7 @@ bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length)
}

bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
qspi_enable();
nrf_qspi_cinstr_conf_t cinstr_cfg = {
.opcode = command,
.length = length + 1,
Expand All @@ -76,20 +115,23 @@ bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
}

bool spi_flash_sector_command(uint8_t command, uint32_t address) {
qspi_enable();
if (command != CMD_SECTOR_ERASE) {
return false;
}
return nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, address) == NRFX_SUCCESS;
}

bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) {
qspi_enable();
// TODO: In theory, this also needs to handle unaligned data and
// non-multiple-of-4 length. (in practice, I don't think the fat layer
// generates such writes)
return nrfx_qspi_write(data, length, address) == NRFX_SUCCESS;
}

bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) {
qspi_enable();
int misaligned = ((intptr_t)data) & 3;
// If the data is misaligned, we need to read 4 bytes
// into an aligned buffer, and then copy 1, 2, or 3 bytes from the aligned
Expand Down