Skip to content

Commit 7c63ef1

Browse files
committed
Add Flash memory driver for STM32 embedded flash.
1 parent 0ace79c commit 7c63ef1

4 files changed

Lines changed: 520 additions & 0 deletions

File tree

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
------------------------------------------------------------------------------
2+
-- --
3+
-- Copyright (C) 2026, AdaCore --
4+
-- --
5+
-- Redistribution and use in source and binary forms, with or without --
6+
-- modification, are permitted provided that the following conditions are --
7+
-- met: --
8+
-- 1. Redistributions of source code must retain the above copyright --
9+
-- notice, this list of conditions and the following disclaimer. --
10+
-- 2. Redistributions in binary form must reproduce the above copyright --
11+
-- notice, this list of conditions and the following disclaimer in --
12+
-- the documentation and/or other materials provided with the --
13+
-- distribution. --
14+
-- 3. Neither the name of the copyright holder nor the names of its --
15+
-- contributors may be used to endorse or promote products derived --
16+
-- from this software without specific prior written permission. --
17+
-- --
18+
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS --
19+
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT --
20+
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR --
21+
-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT --
22+
-- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, --
23+
-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT --
24+
-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, --
25+
-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY --
26+
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT --
27+
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE --
28+
-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --
29+
-- --
30+
------------------------------------------------------------------------------
31+
32+
with Memory_Barriers;
33+
34+
with STM32_SVD.FLASH;
35+
36+
package body STM32.Flash is
37+
38+
FLASH_Periph : STM32_SVD.FLASH.FLASH_Peripheral renames
39+
STM32_SVD.FLASH.FLASH_Periph;
40+
41+
Whole_Flash : constant HAL.Flash.Memory_Region := (0, 16#F_FFFF#);
42+
43+
subtype Memory_Region is HAL.UInt8_Array (1 .. 16#F_FFFF#);
44+
45+
procedure Wait_Flash;
46+
-- Spin CPU while the flash is busy
47+
48+
---------------------
49+
-- Erasable_Region --
50+
---------------------
51+
52+
overriding function Erasable_Region
53+
(This : in out Flash_Memory;
54+
Region : HAL.Flash.Memory_Region)
55+
return HAL.Flash.Memory_Region
56+
is
57+
Result : HAL.Flash.Memory_Region;
58+
begin
59+
case Region.From is
60+
when 0 .. 16#FFFF# =>
61+
Result.From := Region.From / (16 * 1024) * 16 * 1024;
62+
Result.To := Region.From + 16 * 1024 - 1;
63+
when 16#1_0000# .. 16#1_FFFF# =>
64+
Result.From := 16#1_0000#;
65+
Result.To := 16#1_FFFF#;
66+
when 16#2_0000# .. 16#F_FFFF# =>
67+
Result.From := Region.From / (128 * 1024) * 128 * 1024;
68+
Result.To := Region.From + 128 * 1024 - 1;
69+
when others =>
70+
Result := Whole_Flash;
71+
end case;
72+
73+
return
74+
(if Region.To in Result.From .. Result.To
75+
then Result
76+
else Whole_Flash);
77+
end Erasable_Region;
78+
79+
-----------
80+
-- Erase --
81+
-----------
82+
83+
overriding procedure Erase
84+
(This : in out Flash_Memory;
85+
Region : HAL.Flash.Memory_Region;
86+
Success : out Boolean)
87+
is
88+
Sector : Natural range 0 .. 27;
89+
Size : Positive;
90+
begin
91+
if Region = Whole_Flash then
92+
raise Program_Error with "Unimplemented";
93+
end if;
94+
95+
case Region.From is
96+
when 16#0_0000# .. 16#0_FFFF# =>
97+
Size := 16 * 1024;
98+
Sector := (Region.From - 16#0_0000#) / Size;
99+
100+
when 16#1_0000# .. 16#1_FFFF# =>
101+
Size := 64 * 1024;
102+
Sector := 4;
103+
104+
when 16#2_0000# .. 16#F_FFFF# =>
105+
Size := 128 * 1024;
106+
Sector := 5 + (Region.From - 16#2_0000#) / Size;
107+
108+
when others =>
109+
Success := False;
110+
return;
111+
end case;
112+
113+
Sector := Sector + (This.Bank - 1) * 16;
114+
115+
Unlock;
116+
117+
Wait_Flash;
118+
119+
FLASH_Periph.SR.EOP := True; -- Clear interrupt flag
120+
121+
FLASH_Periph.CR :=
122+
(LOCK => False, -- (No-)Lock
123+
SER => True, -- Sector erase
124+
SNB => STM32_SVD.FLASH.CR_SNB_Field (Sector),
125+
PSIZE => 2, -- Parallelism size x32
126+
STRT => True, -- Start
127+
EOPIE => False, -- interrupt on EOP bit = 1
128+
ERRIE => False,
129+
others => <>);
130+
131+
Success := True;
132+
end Erase;
133+
134+
overriding function Is_Busy (This : Flash_Memory) return Boolean is
135+
(FLASH_Periph.SR.BSY);
136+
137+
-----------
138+
-- Write --
139+
-----------
140+
141+
overriding procedure Write
142+
(This : in out Flash_Memory;
143+
Offset : Natural;
144+
Data : HAL.UInt8_Array;
145+
Success : out Boolean)
146+
is
147+
function Get_Word (J : Natural) return HAL.UInt32 is
148+
(HAL.UInt32 (Data (Data'First + 4 * J)) +
149+
HAL.Shift_Left (HAL.UInt32 (Data (Data'First + 4 * J + 1)), 8) +
150+
HAL.Shift_Left (HAL.UInt32 (Data (Data'First + 4 * J + 2)), 16) +
151+
HAL.Shift_Left (HAL.UInt32 (Data (Data'First + 4 * J + 3)), 24));
152+
153+
Memory : Memory_Region
154+
with
155+
Import,
156+
Address => (if This.Bank = 1 then First_Bank else Second_Bank);
157+
158+
Memory_32 : HAL.UInt32_Array (0 .. 16#F_FFFF# / 4)
159+
with
160+
Import,
161+
Address => (if This.Bank = 1 then First_Bank else Second_Bank);
162+
begin
163+
Unlock;
164+
165+
if Data'Length mod 4 = 0 then
166+
for J in 0 .. Data'Length / 4 - 1 loop
167+
Programming (By_Word => True);
168+
Memory_32 (Offset + J) := Get_Word (J);
169+
end loop;
170+
else
171+
for J in Data'Range loop
172+
Programming (By_Word => False);
173+
Memory (Offset + J - Data'First) := Data (J);
174+
end loop;
175+
end if;
176+
177+
Lock;
178+
179+
Success := True;
180+
end Write;
181+
182+
----------
183+
-- Lock --
184+
----------
185+
186+
procedure Lock is
187+
begin
188+
FLASH_Periph.CR :=
189+
(LOCK => True, -- Lock
190+
others => <>);
191+
end Lock;
192+
193+
-----------------
194+
-- Programming --
195+
-----------------
196+
197+
procedure Programming (By_Word : Boolean) is
198+
begin
199+
Wait_Flash;
200+
201+
FLASH_Periph.CR :=
202+
(LOCK => False, -- (No-)Lock
203+
PG => True, -- Programming
204+
PSIZE => (if By_Word then 2 else 0), -- Parallelism size x32/x8
205+
others => <>);
206+
end Programming;
207+
208+
----------
209+
-- Read --
210+
----------
211+
212+
overriding procedure Read
213+
(This : in out Flash_Memory;
214+
Offset : Natural;
215+
Data : out HAL.UInt8_Array;
216+
Success : out Boolean)
217+
is
218+
Memory : Memory_Region
219+
with
220+
Import,
221+
Address => (if This.Bank = 1 then First_Bank else Second_Bank);
222+
begin
223+
Success := Offset in Memory'Range;
224+
225+
if Success then
226+
Data := Memory (Offset .. Offset + Data'Length - 1);
227+
end if;
228+
end Read;
229+
230+
------------
231+
-- Unlock --
232+
------------
233+
234+
procedure Unlock is
235+
begin
236+
FLASH_Periph.KEYR := 16#4567_0123#;
237+
Memory_Barriers.Data_Synchronization_Barrier;
238+
FLASH_Periph.KEYR := 16#CDEF_89AB#;
239+
Memory_Barriers.Data_Synchronization_Barrier;
240+
Wait_Flash;
241+
end Unlock;
242+
243+
----------------
244+
-- Wait_Flash --
245+
----------------
246+
247+
procedure Wait_Flash is
248+
begin
249+
while FLASH_Periph.SR.BSY loop
250+
null;
251+
end loop;
252+
end Wait_Flash;
253+
254+
end STM32.Flash;
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
------------------------------------------------------------------------------
2+
-- --
3+
-- Copyright (C) 2026, AdaCore --
4+
-- --
5+
-- Redistribution and use in source and binary forms, with or without --
6+
-- modification, are permitted provided that the following conditions are --
7+
-- met: --
8+
-- 1. Redistributions of source code must retain the above copyright --
9+
-- notice, this list of conditions and the following disclaimer. --
10+
-- 2. Redistributions in binary form must reproduce the above copyright --
11+
-- notice, this list of conditions and the following disclaimer in --
12+
-- the documentation and/or other materials provided with the --
13+
-- distribution. --
14+
-- 3. Neither the name of the copyright holder nor the names of its --
15+
-- contributors may be used to endorse or promote products derived --
16+
-- from this software without specific prior written permission. --
17+
-- --
18+
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS --
19+
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT --
20+
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR --
21+
-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT --
22+
-- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, --
23+
-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT --
24+
-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, --
25+
-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY --
26+
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT --
27+
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE --
28+
-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --
29+
-- --
30+
------------------------------------------------------------------------------
31+
32+
-- Embedded Flash memory for STM32F4xx with two banks.
33+
--
34+
-- Embedded STM32 Flash memory has two 1M-byte banks. Each bank organized into
35+
-- 12 sectors (4 x 16, 1 x 64, 7 x 128 kilo bytes).
36+
37+
with HAL.Flash;
38+
with System;
39+
40+
package STM32.Flash is
41+
pragma Preelaborate;
42+
43+
subtype Flash_Bank is Natural range 1 .. 2;
44+
45+
type Flash_Memory (Bank : Flash_Bank) is
46+
limited new HAL.Flash.Flash_Memory with private;
47+
48+
Bank_Size : constant := 2 ** 20; -- 1 MB per bank
49+
First_Bank : constant System.Address := System'To_Address (16#0800_0000#);
50+
Second_Bank : constant System.Address := System'To_Address (16#0810_0000#);
51+
52+
overriding function Size (This : Flash_Memory) return Natural
53+
is (Bank_Size);
54+
55+
overriding function Is_Busy (This : Flash_Memory) return Boolean;
56+
57+
overriding function Erasable_Region
58+
(This : in out Flash_Memory;
59+
Region : HAL.Flash.Memory_Region)
60+
return HAL.Flash.Memory_Region;
61+
62+
use type HAL.Flash.Memory_Region;
63+
64+
overriding procedure Erase
65+
(This : in out Flash_Memory;
66+
Region : HAL.Flash.Memory_Region;
67+
Success : out Boolean)
68+
with Pre => Region = Erasable_Region (This, Region);
69+
70+
overriding procedure Read
71+
(This : in out Flash_Memory;
72+
Offset : Natural;
73+
Data : out HAL.UInt8_Array;
74+
Success : out Boolean);
75+
76+
overriding procedure Write
77+
(This : in out Flash_Memory;
78+
Offset : Natural;
79+
Data : HAL.UInt8_Array;
80+
Success : out Boolean);
81+
-- The chip is able to write up to 256 bytes in one go if they are fitted
82+
-- in aligned 256 bytes blocks. Otherwise, Write is split in several
83+
-- commands and execution is blocked until all except the last one is
84+
-- finished.
85+
86+
procedure Lock;
87+
procedure Unlock;
88+
procedure Programming (By_Word : Boolean);
89+
90+
private
91+
92+
type Flash_Memory (Bank : Flash_Bank)
93+
is limited new HAL.Flash.Flash_Memory with null record;
94+
95+
end STM32.Flash;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
with "../../boards/stm32f429_discovery/stm32f429_discovery_full.gpr";
2+
3+
project Flash_F429Disco extends "../shared/common/common.gpr" is
4+
5+
for Runtime ("Ada") use STM32F429_Discovery_Full'Runtime("Ada");
6+
for Target use "arm-eabi";
7+
for Main use ("flash.adb");
8+
for Languages use ("Ada");
9+
for Source_Dirs use ("../shared/stm32_flash/src", "../../arch/ARM/STM32/drivers/flash");
10+
for Object_Dir use "../shared/stm32_flash/obj/stm32f429disco";
11+
for Create_Missing_Dirs use "True";
12+
13+
package Compiler renames STM32F429_Discovery_Full.Compiler;
14+
15+
end Flash_F429Disco;

0 commit comments

Comments
 (0)