1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use crate::pins::SdRamPins;
use cortex_m::peripheral::{MPU, SCB};
use embassy_stm32::{self as hal, Peri};
use hal::fmc::Fmc;
use hal::peripherals::FMC;
use stm32_fmc::Sdram;
pub use stm32_fmc::devices::as4c16m32msa_6::As4c16m32msa as FmcDevice;
pub const SDRAM_SIZE: usize = 64 * 1024 * 1024;
pub struct SdRamBuilder<'a> {
pub pins: SdRamPins<'a>,
pub instance: Peri<'a, FMC>,
}
impl<'a> SdRamBuilder<'a> {
pub fn build(self, mpu: &mut MPU, scb: &mut SCB) -> Sdram<Fmc<'a, FMC>, FmcDevice> {
// Configure MPU for external SDRAM
// MPU config for SDRAM write-through
// Refer to ARM®v7-M Architecture Reference Manual ARM DDI 0403
// Version E.b Section B3.5
const MEMFAULTENA: u32 = 1 << 16;
unsafe {
/* Make sure outstanding transfers are done */
cortex_m::asm::dmb();
scb.shcsr.modify(|r| r & !MEMFAULTENA);
/* Disable the MPU and clear the control register*/
mpu.ctrl.write(0);
}
const REGION_NUMBER0: u32 = 0x00;
const REGION_BASE_ADDRESS: u32 = 0xD000_0000;
const REGION_FULL_ACCESS: u32 = 0x03;
const REGION_CACHEABLE: u32 = 0x01;
const REGION_WRITE_BACK: u32 = 0x01;
const REGION_ENABLE: u32 = 0x01;
assert_eq!(
SDRAM_SIZE & (SDRAM_SIZE - 1),
0,
"SDRAM memory region size must be a power of 2"
);
assert_eq!(
SDRAM_SIZE & 0x1F,
0,
"SDRAM memory region size must be 32 bytes or more"
);
fn log2minus1(sz: u32) -> u32 {
for i in 5..=31 {
if sz == (1 << i) {
return i - 1;
}
}
panic!("Unknown SDRAM memory region size!");
}
// Configure region 0
//
// Cacheable, outer and inner write-back, no write allocate. So
// reads are cached, but writes always write all the way to SDRAM
unsafe {
mpu.rnr.write(REGION_NUMBER0);
mpu.rbar.write(REGION_BASE_ADDRESS);
mpu.rasr.write(
(REGION_FULL_ACCESS << 24)
| (REGION_CACHEABLE << 17)
| (REGION_WRITE_BACK << 16)
| (log2minus1(SDRAM_SIZE as u32) << 1)
| REGION_ENABLE,
);
}
const MPU_ENABLE: u32 = 0x01;
const MPU_DEFAULT_MMAP_FOR_PRIVILEGED: u32 = 0x04;
// Enable
unsafe {
mpu.ctrl
.modify(|r| r | MPU_DEFAULT_MMAP_FOR_PRIVILEGED | MPU_ENABLE);
scb.shcsr.modify(|r| r | MEMFAULTENA);
// Ensure MPU settings take effect
cortex_m::asm::dsb();
cortex_m::asm::isb();
}
let Self { pins, instance } = self;
Fmc::sdram_a13bits_d32bits_4banks_bank1(
instance,
// A0-A12
pins.ff0,
pins.ff1,
pins.ff2,
pins.ff3,
pins.ff4,
pins.ff5,
pins.ff12,
pins.ff13,
pins.ff14,
pins.ff15,
pins.gg0,
pins.gg1,
pins.gg2,
// BA0-BA1
pins.gg4,
pins.gg5,
// D0-D31
pins.dd14,
pins.dd15,
pins.dd0,
pins.dd1,
pins.ee7,
pins.ee8,
pins.ee9,
pins.ee10,
pins.ee11,
pins.ee12,
pins.ee13,
pins.ee14,
pins.ee15,
pins.dd8,
pins.dd9,
pins.dd10,
pins.hh8,
pins.hh9,
pins.hh10,
pins.hh11,
pins.hh12,
pins.hh13,
pins.hh14,
pins.hh15,
pins.ii0,
pins.ii1,
pins.ii2,
pins.ii3,
pins.ii6,
pins.ii7,
pins.ii9,
pins.ii10,
// NBL0 - NBL3
pins.ee0,
pins.ee1,
pins.ii4,
pins.ii5,
pins.hh2, // SDCKE0
pins.gg8, // SDCLK
pins.gg15, // SDNCAS
pins.hh3, // SDNE0
pins.ff11, // SDRAS
pins.hh5, // SDNWE
FmcDevice {},
)
}
}