stm32f4xx/
fsmc.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use crate::clocks::{phclk, Stm32f4Clocks};
6use core::cell::Cell;
7use kernel::deferred_call::{DeferredCall, DeferredCallClient};
8use kernel::hil::bus8080::{Bus8080, BusAddr8080, BusWidth, Client};
9use kernel::platform::chip::ClockInterface;
10use kernel::utilities::cells::{OptionalCell, TakeCell};
11use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
12use kernel::utilities::registers::{register_bitfields, ReadWrite};
13use kernel::utilities::StaticRef;
14use kernel::ErrorCode;
15
16/// FSMC peripheral interface
17#[repr(C)]
18struct FsmcBankRegisters {
19    /// SRAM/NOR-Flash chip-select control register
20    bcr1: ReadWrite<u32, BCR::Register>,
21    /// SRAM/NOR-Flash chip-select timing register
22    btr1: ReadWrite<u32, BTR::Register>,
23    /// SRAM/NOR-Flash chip-select control register
24    bcr2: ReadWrite<u32, BCR::Register>,
25    /// SRAM/NOR-Flash chip-select timing register
26    btr2: ReadWrite<u32, BTR::Register>,
27    /// SRAM/NOR-Flash chip-select control register
28    bcr3: ReadWrite<u32, BCR::Register>,
29    /// SRAM/NOR-Flash chip-select timing register
30    btr3: ReadWrite<u32, BTR::Register>,
31    /// SRAM/NOR-Flash chip-select control register
32    bcr4: ReadWrite<u32, BCR::Register>,
33    /// SRAM/NOR-Flash chip-select timing register
34    btr4: ReadWrite<u32, BTR::Register>,
35    _reseved: [u8; 228],
36    /// SRAM/NOR-Flash write timing registers
37    bwtr1: ReadWrite<u32, BWTR::Register>,
38    /// SRAM/NOR-Flash write timing registers
39    bwtr2: ReadWrite<u32, BWTR::Register>,
40    /// SRAM/NOR-Flash write timing registers
41    bwtr3: ReadWrite<u32, BWTR::Register>,
42    /// SRAM/NOR-Flash write timing registers
43    bwtr4: ReadWrite<u32, BWTR::Register>,
44}
45
46register_bitfields![u32,
47    BCR [
48        /// Write FIFO Disable
49        WFDIS OFFSET(21) NUMBITS(1) [],
50        /// Continuous Clock Enable
51        CCLKEN OFFSET(20) NUMBITS(1) [],
52        /// Write burst enable
53        CBURSTRW OFFSET(19) NUMBITS(1) [],
54        /// CRAM page size
55        CPSIZE OFFSET(16) NUMBITS(3) [
56            NO_BURST = 0b000,
57            BYTES_128 = 0b001,
58            BYTES_256 = 0b010,
59            BYTES_1024 = 0b011
60        ],
61        /// Wait signal during asynchronous transfers
62        ASYNCWAIT OFFSET(15) NUMBITS(1) [],
63        /// Extended mode enable
64        EXTMOD OFFSET(14) NUMBITS(1) [],
65        /// Wait enable bit
66        WAITEN OFFSET(13) NUMBITS(1) [],
67        /// Write enable bit
68        WREN OFFSET(12) NUMBITS(1) [],
69        /// Wait timing configuration
70        WAITCFG OFFSET(11) NUMBITS(1) [],
71        /// Wait signal polarity bit
72        WAITPOL OFFSET(9) NUMBITS(1) [],
73        /// Burst enable bit
74        BURSTEN OFFSET(8) NUMBITS(1) [],
75        /// Flash access enable
76        /// Enables NOR Flash memory access operations
77        FACCEN OFFSET(6) NUMBITS(1) [],
78        /// Memory data bus_width width
79        MWID OFFSET(4) NUMBITS(2) [
80            BITS_8 = 0b00,
81            BITS_16 = 0b01
82        ],
83        /// Memory type
84        MTYP OFFSET(2) NUMBITS(2) [
85            SRAM = 0b00,
86            PSRAM = 0b01,
87            NOR = 0b10
88        ],
89        /// Address/data multiplexing enable bit
90        MUXEN OFFSET(1) NUMBITS(1) [],
91        /// Memory bank enable bit
92        MBKEN OFFSET(0) NUMBITS(1) []
93    ],
94    BTR [
95        /// Access mode
96        ACCMOD OFFSET(28) NUMBITS(2) [
97            A = 0b00,
98            B = 0b01,
99            C = 0b10,
100            D = 0b11
101        ],
102        /// Data latency for synchronous memory
103        DATLAT OFFSET(24) NUMBITS(4) [],
104        /// Clock divide ratio (for FSMC_CLK signal)
105        CLKDIV OFFSET(20) NUMBITS(4) [],
106        /// Bus turnaround phase duration
107        BUSTURN OFFSET(16) NUMBITS(4) [],
108        /// Data-phase duration
109        DATAST OFFSET(8) NUMBITS(8) [],
110        /// Address-hold phase duration
111        ADDHLD OFFSET(4) NUMBITS(4) [],
112        /// Address setup phase duration
113        ADDSET OFFSET(0) NUMBITS(4) []
114    ],
115    BWTR [
116        /// Access mode
117        ACCMOD OFFSET(28) NUMBITS(2) [
118            A = 0b00,
119            B = 0b01,
120            C = 0b10,
121            D = 0b11
122        ],
123        BUSTURN OFFSET(16) NUMBITS(4) [],
124        /// Data-phase duration
125        DATAST OFFSET(8) NUMBITS(8) [],
126        /// Address-hold phase duration
127        ADDHLD OFFSET(4) NUMBITS(4) [],
128        /// Address setup phase duration
129        ADDSET OFFSET(0) NUMBITS(4) []
130    ]
131];
132
133const FSMC_BASE: StaticRef<FsmcBankRegisters> =
134    unsafe { StaticRef::new(0xA000_0000 as *const FsmcBankRegisters) };
135
136/// FSMC Bank
137#[repr(C)]
138pub struct FsmcBank {
139    /// Address
140    reg: ReadWrite<u16>,
141    /// Data
142    ram: ReadWrite<u16>,
143}
144
145#[repr(usize)]
146pub enum FsmcBanks {
147    Bank1 = 0,
148    Bank2 = 1,
149    Bank3 = 2,
150    Bank4 = 3,
151}
152
153pub const FSMC_BANK1: StaticRef<FsmcBank> =
154    unsafe { StaticRef::new(0x60000000 as *const FsmcBank) };
155// const FSMC_BANK2_RESERVED: StaticRef<FsmcBank> = unsafe { StaticRef::new(0x0 as *const FsmcBank) };
156pub const FSMC_BANK3: StaticRef<FsmcBank> =
157    unsafe { StaticRef::new(0x68000000 as *const FsmcBank) };
158// const FSMC_BANK4_RESERVED: StaticRef<FsmcBank> = unsafe { StaticRef::new(0x0 as *const FsmcBank) };
159
160pub struct Fsmc<'a> {
161    registers: StaticRef<FsmcBankRegisters>,
162    bank: [Option<StaticRef<FsmcBank>>; 4],
163    clock: FsmcClock<'a>,
164
165    client: OptionalCell<&'static dyn Client>,
166
167    buffer: TakeCell<'static, [u8]>,
168    bus_width: Cell<usize>,
169    len: Cell<usize>,
170
171    deferred_call: DeferredCall,
172}
173
174impl<'a> Fsmc<'a> {
175    pub fn new(bank_addr: [Option<StaticRef<FsmcBank>>; 4], clocks: &'a dyn Stm32f4Clocks) -> Self {
176        Self {
177            registers: FSMC_BASE,
178            bank: bank_addr,
179            clock: FsmcClock(phclk::PeripheralClock::new(
180                phclk::PeripheralClockType::AHB3(phclk::HCLK3::FMC),
181                clocks,
182            )),
183            client: OptionalCell::empty(),
184
185            buffer: TakeCell::empty(),
186            bus_width: Cell::new(1),
187            len: Cell::new(0),
188
189            deferred_call: DeferredCall::new(),
190        }
191    }
192
193    pub fn enable(&self) {
194        self.registers.bcr1.modify(
195            BCR::MBKEN::SET
196                + BCR::MUXEN::CLEAR
197                + BCR::MTYP::SRAM
198                + BCR::MWID::BITS_16
199                + BCR::BURSTEN::CLEAR
200                + BCR::WAITPOL::CLEAR
201                + BCR::WAITCFG::CLEAR
202                + BCR::WREN::SET
203                + BCR::WAITEN::CLEAR
204                + BCR::EXTMOD::SET
205                + BCR::ASYNCWAIT::CLEAR
206                + BCR::CBURSTRW::CLEAR
207                + BCR::WFDIS::SET
208                + BCR::CPSIZE::NO_BURST
209                + BCR::CCLKEN::CLEAR,
210        );
211        self.registers.btr1.modify(
212            BTR::ADDSET.val(9)
213                + BTR::ADDHLD.val(1)
214                + BTR::DATAST.val(36)
215                + BTR::BUSTURN.val(1)
216                + BTR::CLKDIV.val(2)
217                + BTR::DATLAT.val(2)
218                + BTR::ACCMOD::A,
219        );
220        self.registers.bwtr1.modify(
221            BWTR::ADDSET.val(1)
222                + BWTR::ADDHLD.val(1)
223                + BWTR::DATAST.val(7)
224                + BWTR::BUSTURN.val(0)
225                + BWTR::ACCMOD::A,
226        );
227        self.enable_clock();
228    }
229
230    pub fn disable(&self) {
231        self.disable_clock();
232    }
233
234    pub fn enable_clock(&self) {
235        self.clock.enable();
236    }
237
238    pub fn disable_clock(&self) {
239        self.clock.disable();
240    }
241
242    #[inline]
243    pub fn read_reg(&self, bank: FsmcBanks) -> Option<u16> {
244        self.bank[bank as usize].map_or(None, |bank| Some(bank.ram.get()))
245    }
246
247    #[cfg(any(doc, all(target_arch = "arm", target_os = "none")))]
248    #[inline]
249    fn write_reg(&self, bank: FsmcBanks, addr: u16) {
250        use kernel::utilities::registers::interfaces::Writeable;
251        self.bank[bank as usize].map(|bank| bank.reg.set(addr));
252        unsafe {
253            use core::arch::asm;
254            asm!("dsb 0xf");
255        }
256    }
257
258    #[cfg(any(doc, all(target_arch = "arm", target_os = "none")))]
259    #[inline]
260    fn write_data(&self, bank: FsmcBanks, data: u16) {
261        use kernel::utilities::registers::interfaces::Writeable;
262        self.bank[bank as usize].map(|bank| bank.ram.set(data));
263        unsafe {
264            use core::arch::asm;
265            asm!("dsb 0xf");
266        }
267    }
268
269    #[cfg(not(any(doc, all(target_arch = "arm", target_os = "none"))))]
270    fn write_reg(&self, _bank: FsmcBanks, _addr: u16) {
271        unimplemented!()
272    }
273
274    #[cfg(not(any(doc, all(target_arch = "arm", target_os = "none"))))]
275    fn write_data(&self, _bank: FsmcBanks, _data: u16) {
276        unimplemented!()
277    }
278}
279
280impl DeferredCallClient for Fsmc<'_> {
281    fn register(&'static self) {
282        self.deferred_call.register(self);
283    }
284
285    fn handle_deferred_call(&self) {
286        self.buffer.take().map_or_else(
287            || {
288                self.client.map(move |client| {
289                    client.command_complete(None, 0, Ok(()));
290                });
291            },
292            |buffer| {
293                self.client.map(move |client| {
294                    client.command_complete(Some(buffer), self.len.get(), Ok(()));
295                });
296            },
297        );
298    }
299}
300
301struct FsmcClock<'a>(phclk::PeripheralClock<'a>);
302
303impl ClockInterface for FsmcClock<'_> {
304    fn is_enabled(&self) -> bool {
305        self.0.is_enabled()
306    }
307
308    fn enable(&self) {
309        self.0.enable();
310    }
311
312    fn disable(&self) {
313        self.0.disable();
314    }
315}
316
317impl Bus8080<'static> for Fsmc<'_> {
318    fn set_addr(&self, addr: BusAddr8080) -> Result<(), ErrorCode> {
319        match addr {
320            BusAddr8080::BusAddr8(addr) => {
321                self.write_reg(FsmcBanks::Bank1, addr as u16);
322                self.deferred_call.set();
323                Ok(())
324            }
325            _ => Err(ErrorCode::NOSUPPORT),
326        }
327    }
328
329    fn write(
330        &self,
331        data_width: BusWidth,
332        buffer: &'static mut [u8],
333        len: usize,
334    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
335        let bytes = data_width.width_in_bytes();
336        if buffer.len() >= len * bytes {
337            for pos in 0..len {
338                let mut data: u16 = 0;
339                for byte in 0..bytes {
340                    data |= (buffer[bytes * pos
341                        + match data_width {
342                            BusWidth::Bits8 | BusWidth::Bits16LE => byte,
343                            BusWidth::Bits16BE => bytes - byte - 1,
344                        }] as u16)
345                        << (8 * byte);
346                }
347                self.write_data(FsmcBanks::Bank1, data);
348            }
349            self.buffer.replace(buffer);
350            self.bus_width.set(bytes);
351            self.len.set(len);
352            self.deferred_call.set();
353            Ok(())
354        } else {
355            Err((ErrorCode::NOMEM, buffer))
356        }
357    }
358
359    fn read(
360        &self,
361        data_width: BusWidth,
362        buffer: &'static mut [u8],
363        len: usize,
364    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
365        let bytes = data_width.width_in_bytes();
366        if buffer.len() >= len * bytes {
367            for pos in 0..len {
368                if let Some(data) = self.read_reg(FsmcBanks::Bank1) {
369                    for byte in 0..bytes {
370                        buffer[bytes * pos
371                            + match data_width {
372                                BusWidth::Bits8 | BusWidth::Bits16LE => byte,
373                                BusWidth::Bits16BE => bytes - byte - 1,
374                            }] = (data >> (8 * byte)) as u8;
375                    }
376                } else {
377                    return Err((ErrorCode::NOMEM, buffer));
378                }
379            }
380            self.buffer.replace(buffer);
381            self.bus_width.set(bytes);
382            self.len.set(len);
383            self.deferred_call.set();
384            Ok(())
385        } else {
386            Err((ErrorCode::NOMEM, buffer))
387        }
388    }
389
390    fn set_client(&self, client: &'static dyn Client) {
391        self.client.replace(client);
392    }
393}