Skip to content

Commit 64bd95e

Browse files
authored
Merge pull request adafruit#819 from dhalbert/cache
enable cache in SAMD51
2 parents b46cc9d + e82f37c commit 64bd95e

File tree

4 files changed

+85
-5
lines changed

4 files changed

+85
-5
lines changed

ports/atmel-samd/external_flash/qspi_flash.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "mpconfigboard.h" // for EXTERNAL_FLASH_QSPI_DUAL
3333

3434
#include "external_flash/common_commands.h"
35+
#include "peripherals.h"
3536
#include "shared_dma.h"
3637

3738
#include "atmel_start_pins.h"
@@ -55,6 +56,8 @@ bool spi_flash_command(uint8_t command) {
5556
}
5657

5758
bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) {
59+
samd_peripherals_disable_and_clear_cache();
60+
5861
QSPI->INSTRCTRL.bit.INSTR = command;
5962

6063
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)
6366
QSPI_INSTRFRAME_INSTREN |
6467
QSPI_INSTRFRAME_DATAEN;
6568

69+
// Dummy read of INSTRFRAME needed to synchronize.
70+
// See Instruction Transmission Flow Diagram, figure 37.9, page 995
71+
// and Example 4, page 998, section 37.6.8.5.
72+
(volatile uint32_t) QSPI->INSTRFRAME.reg;
73+
6674
memcpy(response, (uint8_t *) QSPI_AHB, length);
6775

6876
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)
7179

7280
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
7381

82+
samd_peripherals_enable_cache();
83+
7484
return true;
7585
}
7686

7787
bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
88+
samd_peripherals_disable_and_clear_cache();
89+
7890
QSPI->INSTRCTRL.bit.INSTR = command;
7991

8092
QSPI->INSTRFRAME.reg = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI |
8193
QSPI_INSTRFRAME_ADDRLEN_24BITS |
8294
QSPI_INSTRFRAME_TFRTYPE_WRITE |
83-
QSPI_INSTRFRAME_INSTREN;
95+
QSPI_INSTRFRAME_INSTREN |
96+
(data != NULL ? QSPI_INSTRFRAME_DATAEN : 0);
8497

85-
if (data != NULL) {
86-
QSPI->INSTRFRAME.bit.DATAEN = true;
98+
// Dummy read of INSTRFRAME needed to synchronize.
99+
// See Instruction Transmission Flow Diagram, figure 37.9, page 995
100+
// and Example 4, page 998, section 37.6.8.5.
101+
(volatile uint32_t) QSPI->INSTRFRAME.reg;
87102

103+
if (data != NULL) {
88104
memcpy((uint8_t *) QSPI_AHB, data, length);
89105
}
90106

@@ -94,6 +110,8 @@ bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
94110

95111
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
96112

113+
samd_peripherals_enable_cache();
114+
97115
return true;
98116
}
99117

@@ -117,6 +135,8 @@ bool spi_flash_sector_command(uint8_t command, uint32_t address) {
117135
}
118136

119137
bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) {
138+
samd_peripherals_disable_and_clear_cache();
139+
120140
QSPI->INSTRCTRL.bit.INSTR = CMD_PAGE_PROGRAM;
121141
uint32_t mode = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI;
122142

@@ -137,10 +157,14 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) {
137157

138158
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
139159

160+
samd_peripherals_enable_cache();
161+
140162
return true;
141163
}
142164

143165
bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) {
166+
samd_peripherals_disable_and_clear_cache();
167+
144168
#ifdef EXTERNAL_FLASH_QSPI_DUAL
145169
QSPI->INSTRCTRL.bit.INSTR = CMD_DUAL_READ;
146170
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) {
167191

168192
QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND;
169193

194+
samd_peripherals_enable_cache();
195+
170196
return true;
171197
}
172198

@@ -183,7 +209,7 @@ void spi_flash_init(void) {
183209
// QSPI->BAUD.bit.BAUD = 32;
184210
// Super fast, may be unreliable when Saleae is connected to high speed lines.
185211
QSPI->BAUD.bit.BAUD = 2;
186-
QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY |
212+
QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | // Serial memory mode (map to QSPI_AHB)
187213
QSPI_CTRLB_DATALEN_8BITS |
188214
QSPI_CTRLB_CSMODE_LASTXFER;
189215

ports/atmel-samd/samd51_peripherals.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,15 @@ void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance)
163163
hri_adc_write_CALIB_BIASR2R_bf(instance, biasr2r);
164164
hri_adc_write_CALIB_BIASCOMP_bf(instance, biascomp);
165165
}
166+
167+
// Turn off cache and invalidate all data in it.
168+
void samd_peripherals_disable_and_clear_cache(void) {
169+
CMCC->CTRL.bit.CEN = 0;
170+
while (CMCC->SR.bit.CSTS) {}
171+
CMCC->MAINT0.bit.INVALL = 1;
172+
}
173+
174+
// Enable cache
175+
void samd_peripherals_enable_cache(void) {
176+
CMCC->CTRL.bit.CEN = 1;
177+
}

ports/atmel-samd/samd51_peripherals.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,7 @@ uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
3535
bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad);
3636
void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance);
3737

38+
void samd_peripherals_disable_and_clear_cache(void);
39+
void samd_peripherals_enable_cache(void);
40+
3841
#endif // MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PERIPHERALS_H

ports/atmel-samd/supervisor/port.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include "shared-bindings/rtc/__init__.h"
5858
#include "clocks.h"
5959
#include "events.h"
60+
#include "peripherals.h"
6061
#include "shared_dma.h"
6162
#include "tick.h"
6263

@@ -105,9 +106,47 @@ safe_mode_t port_init(void) {
105106
SUPC->BOD33.bit.ENABLE = 0;
106107
SUPC->BOD33.bit.LEVEL = 200; // 2.7V: 1.5V + LEVEL * 6mV.
107108
SUPC->BOD33.bit.ENABLE = 1;
108-
#endif
109109

110+
// MPU (Memory Protection Unit) setup.
111+
// We hoped we could make the QSPI region be non-cachable with the MPU,
112+
// but the CMCC doesn't seem to pay attention to the MPU settings.
113+
// Leaving this code here disabled,
114+
// because it was hard enough to figure out, and maybe there's
115+
// a mistake that could make it work in the future.
116+
#if 0
117+
// Designate QSPI memory mapped region as not cachable.
118+
119+
// Turn off MPU in case it is on.
120+
MPU->CTRL = 0;
121+
// Configure region 0.
122+
MPU->RNR = 0;
123+
// Region base: start of QSPI mapping area.
124+
// QSPI region runs from 0x04000000 up to and not including 0x05000000: 16 megabytes
125+
MPU->RBAR = QSPI_AHB;
126+
MPU->RASR =
127+
0b011 << MPU_RASR_AP_Pos | // full read/write access for privileged and user mode
128+
0b000 << MPU_RASR_TEX_Pos | // caching not allowed, strongly ordered
129+
1 << MPU_RASR_S_Pos | // sharable
130+
0 << MPU_RASR_C_Pos | // not cachable
131+
0 << MPU_RASR_B_Pos | // not bufferable
132+
0b10111 << MPU_RASR_SIZE_Pos | // 16MB region size
133+
1 << MPU_RASR_ENABLE_Pos // enable this region
134+
;
135+
// Turn off regions 1-7.
136+
for (uint32_t i = 1; i < 8; i ++) {
137+
MPU->RNR = i;
138+
MPU->RBAR = 0;
139+
MPU->RASR = 0;
140+
}
110141

142+
// Turn on MPU. Turn on PRIVDEFENA, which defines a default memory
143+
// map for all privileged access, so we don't have to set up other regions
144+
// besides QSPI.
145+
MPU->CTRL = MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
146+
#endif
147+
148+
samd_peripherals_enable_cache();
149+
#endif
111150

112151
// On power on start or external reset, set _ezero to the canary word. If it
113152
// gets killed, we boot in safe mode. _ezero is the boundary between statically

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy