enable cache in SAMD51

This commit is contained in:
Dan Halbert 2018-05-07 21:55:37 -04:00
parent b0fba2864c
commit e82f37c60e
4 changed files with 85 additions and 5 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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