commit
64bd95ea01
|
@ -32,6 +32,7 @@
|
|||
#include "mpconfigboard.h" // for EXTERNAL_FLASH_QSPI_DUAL
|
||||
|
||||
#include "external_flash/common_commands.h"
|
||||
#include "peripherals.h"
|
||||
#include "shared_dma.h"
|
||||
|
||||
#include "atmel_start_pins.h"
|
||||
|
@ -55,6 +56,8 @@ bool spi_flash_command(uint8_t command) {
|
|||
}
|
||||
|
||||
bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) {
|
||||
samd_peripherals_disable_and_clear_cache();
|
||||
|
||||
QSPI->INSTRCTRL.bit.INSTR = command;
|
||||
|
||||
QSPI->INSTRFRAME.reg = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI |
|
||||
|
@ -63,6 +66,11 @@ bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length)
|
|||
QSPI_INSTRFRAME_INSTREN |
|
||||
QSPI_INSTRFRAME_DATAEN;
|
||||
|
||||
// Dummy read of INSTRFRAME needed to synchronize.
|
||||
// See Instruction Transmission Flow Diagram, figure 37.9, page 995
|
||||
// and Example 4, page 998, section 37.6.8.5.
|
||||
(volatile uint32_t) QSPI->INSTRFRAME.reg;
|
||||
|
||||
memcpy(response, (uint8_t *) QSPI_AHB, length);
|
||||
|
||||
QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER;
|
||||
|
@ -71,20 +79,28 @@ bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length)
|
|||
|
||||
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
|
||||
|
||||
samd_peripherals_enable_cache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
|
||||
samd_peripherals_disable_and_clear_cache();
|
||||
|
||||
QSPI->INSTRCTRL.bit.INSTR = command;
|
||||
|
||||
QSPI->INSTRFRAME.reg = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI |
|
||||
QSPI_INSTRFRAME_ADDRLEN_24BITS |
|
||||
QSPI_INSTRFRAME_TFRTYPE_WRITE |
|
||||
QSPI_INSTRFRAME_INSTREN;
|
||||
QSPI_INSTRFRAME_INSTREN |
|
||||
(data != NULL ? QSPI_INSTRFRAME_DATAEN : 0);
|
||||
|
||||
// Dummy read of INSTRFRAME needed to synchronize.
|
||||
// See Instruction Transmission Flow Diagram, figure 37.9, page 995
|
||||
// and Example 4, page 998, section 37.6.8.5.
|
||||
(volatile uint32_t) QSPI->INSTRFRAME.reg;
|
||||
|
||||
if (data != NULL) {
|
||||
QSPI->INSTRFRAME.bit.DATAEN = true;
|
||||
|
||||
memcpy((uint8_t *) QSPI_AHB, data, length);
|
||||
}
|
||||
|
||||
|
@ -94,6 +110,8 @@ bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
|
|||
|
||||
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
|
||||
|
||||
samd_peripherals_enable_cache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -117,6 +135,8 @@ bool spi_flash_sector_command(uint8_t command, uint32_t address) {
|
|||
}
|
||||
|
||||
bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) {
|
||||
samd_peripherals_disable_and_clear_cache();
|
||||
|
||||
QSPI->INSTRCTRL.bit.INSTR = CMD_PAGE_PROGRAM;
|
||||
uint32_t mode = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI;
|
||||
|
||||
|
@ -137,10 +157,14 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) {
|
|||
|
||||
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
|
||||
|
||||
samd_peripherals_enable_cache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) {
|
||||
samd_peripherals_disable_and_clear_cache();
|
||||
|
||||
#ifdef EXTERNAL_FLASH_QSPI_DUAL
|
||||
QSPI->INSTRCTRL.bit.INSTR = CMD_DUAL_READ;
|
||||
uint32_t mode = QSPI_INSTRFRAME_WIDTH_DUAL_OUTPUT;
|
||||
|
@ -167,6 +191,8 @@ bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) {
|
|||
|
||||
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
|
||||
|
||||
samd_peripherals_enable_cache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -183,7 +209,7 @@ void spi_flash_init(void) {
|
|||
// QSPI->BAUD.bit.BAUD = 32;
|
||||
// Super fast, may be unreliable when Saleae is connected to high speed lines.
|
||||
QSPI->BAUD.bit.BAUD = 2;
|
||||
QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY |
|
||||
QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | // Serial memory mode (map to QSPI_AHB)
|
||||
QSPI_CTRLB_DATALEN_8BITS |
|
||||
QSPI_CTRLB_CSMODE_LASTXFER;
|
||||
|
||||
|
|
|
@ -163,3 +163,15 @@ void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance)
|
|||
hri_adc_write_CALIB_BIASR2R_bf(instance, biasr2r);
|
||||
hri_adc_write_CALIB_BIASCOMP_bf(instance, biascomp);
|
||||
}
|
||||
|
||||
// Turn off cache and invalidate all data in it.
|
||||
void samd_peripherals_disable_and_clear_cache(void) {
|
||||
CMCC->CTRL.bit.CEN = 0;
|
||||
while (CMCC->SR.bit.CSTS) {}
|
||||
CMCC->MAINT0.bit.INVALL = 1;
|
||||
}
|
||||
|
||||
// Enable cache
|
||||
void samd_peripherals_enable_cache(void) {
|
||||
CMCC->CTRL.bit.CEN = 1;
|
||||
}
|
||||
|
|
|
@ -35,4 +35,7 @@ uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
|
|||
bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad);
|
||||
void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance);
|
||||
|
||||
void samd_peripherals_disable_and_clear_cache(void);
|
||||
void samd_peripherals_enable_cache(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PERIPHERALS_H
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "shared-bindings/rtc/__init__.h"
|
||||
#include "clocks.h"
|
||||
#include "events.h"
|
||||
#include "peripherals.h"
|
||||
#include "shared_dma.h"
|
||||
#include "tick.h"
|
||||
|
||||
|
@ -105,9 +106,47 @@ safe_mode_t port_init(void) {
|
|||
SUPC->BOD33.bit.ENABLE = 0;
|
||||
SUPC->BOD33.bit.LEVEL = 200; // 2.7V: 1.5V + LEVEL * 6mV.
|
||||
SUPC->BOD33.bit.ENABLE = 1;
|
||||
|
||||
// MPU (Memory Protection Unit) setup.
|
||||
// We hoped we could make the QSPI region be non-cachable with the MPU,
|
||||
// but the CMCC doesn't seem to pay attention to the MPU settings.
|
||||
// Leaving this code here disabled,
|
||||
// because it was hard enough to figure out, and maybe there's
|
||||
// a mistake that could make it work in the future.
|
||||
#if 0
|
||||
// Designate QSPI memory mapped region as not cachable.
|
||||
|
||||
// Turn off MPU in case it is on.
|
||||
MPU->CTRL = 0;
|
||||
// Configure region 0.
|
||||
MPU->RNR = 0;
|
||||
// Region base: start of QSPI mapping area.
|
||||
// QSPI region runs from 0x04000000 up to and not including 0x05000000: 16 megabytes
|
||||
MPU->RBAR = QSPI_AHB;
|
||||
MPU->RASR =
|
||||
0b011 << MPU_RASR_AP_Pos | // full read/write access for privileged and user mode
|
||||
0b000 << MPU_RASR_TEX_Pos | // caching not allowed, strongly ordered
|
||||
1 << MPU_RASR_S_Pos | // sharable
|
||||
0 << MPU_RASR_C_Pos | // not cachable
|
||||
0 << MPU_RASR_B_Pos | // not bufferable
|
||||
0b10111 << MPU_RASR_SIZE_Pos | // 16MB region size
|
||||
1 << MPU_RASR_ENABLE_Pos // enable this region
|
||||
;
|
||||
// Turn off regions 1-7.
|
||||
for (uint32_t i = 1; i < 8; i ++) {
|
||||
MPU->RNR = i;
|
||||
MPU->RBAR = 0;
|
||||
MPU->RASR = 0;
|
||||
}
|
||||
|
||||
// Turn on MPU. Turn on PRIVDEFENA, which defines a default memory
|
||||
// map for all privileged access, so we don't have to set up other regions
|
||||
// besides QSPI.
|
||||
MPU->CTRL = MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
|
||||
#endif
|
||||
|
||||
|
||||
samd_peripherals_enable_cache();
|
||||
#endif
|
||||
|
||||
// On power on start or external reset, set _ezero to the canary word. If it
|
||||
// gets killed, we boot in safe mode. _ezero is the boundary between statically
|
||||
|
|
Loading…
Reference in New Issue