?????我们平时在使用
S
T
M
32
STM32
STM32系列芯片的时候,在编译好程序之后,可能就是一个简单的鼠标操作,单机一下
K
e
i
l
M
D
K
I
D
E
Keil\quad MDK\quad IDE
KeilMDKIDE上的
D
o
w
n
l
o
a
d
Download
Download就可以了,但是实际上在下载程序到
F
l
a
s
h
Flash
Flash上的时候还需要一个叫做
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm的东西,如图1所示。因为我们知道一般芯片内部的
F
l
a
s
h
Flash
Flash如果要进行烧录的话,需要先擦除,那么这个
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm就相当于给
K
e
i
l
M
D
K
I
D
E
Keil\quad MDK\quad IDE
KeilMDKIDE提供了一系列操作内部的
F
l
a
s
h
Flash
Flash的接口。
图1.
?????一般情况下,芯片供应商已经在对应的
P
A
C
K
PACK
PACK包里面为你准备好了对应的
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm。那我们现在的问题是如何自己去构建
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm文件。关于这一点大家可以先看一看
A
R
M
ARM
ARM公司关于这一块的官方介绍。下面我将简单的介绍一下
C
O
R
T
E
X
?
M
CORTEX-M
CORTEX?M系列芯片的
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm文件的构建过程,注意这里是
C
O
R
T
E
X
?
M
CORTEX-M
CORTEX?M系列芯片,
A
R
M
ARM
ARM公司其他系列芯片的
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm文件的构建过程可能还不同。下面的讲解主要基于
C
M
S
I
S
CMSIS
CMSIS官方介绍。 ?????首先找到你的
K
e
i
l
M
D
K
I
D
E
Keil\quad MDK\quad IDE
KeilMDKIDE的
P
A
C
K
PACK
PACK包的安装目录,然后将到图1(这里是我的
K
e
i
l
M
D
K
I
D
E
Keil\quad MDK\quad IDE
KeilMDKIDE的
P
A
C
K
PACK
PACK包的安装目录,你需要确定你自己的)所示的
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm模板工程复制出来。然后可以根据自己的喜好改一下图4和图5中的名字,当然这里不改也是可以的,但是图3的地方还是需要改一下,因为我打算用
S
T
M
32
F
103
STM32F103
STM32F103作为测试的例子,
S
T
M
32
F
103
STM32F103
STM32F103是
M
3
M3
M3的内核,因此这里选择
M
3
M3
M3。最后一步也是最重要的一步是更改图6中的那两个文件,也就是一系列操作内部的
F
l
a
s
h
Flash
Flash的接口,接下来我们会重点讲到。有了这些之后编译这个工程就会生成你所需的
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm。
图2.
图3.
图4.
图5.
图6.
?????文件
F
l
a
s
h
D
e
v
.
c
FlashDev.c
FlashDev.c里面主要是一些参数定义,定义在一个结构体中。图7是这个参数结构体的定义,结构体的第1个元素是下载算法的版本,这里自己填写,第2个元素是芯片相关描述,这里自己填写,第3个元素是
F
l
a
s
h
Flash
Flash所在位置,是片上(
O
N
C
H
I
P
ONCHIP
ONCHIP),还是片外(
E
X
T
_
x
_
B
I
T
EXT\_x\_BIT
EXT_x_BIT),这里自己填写。第4个元素和第5个元素分别是
F
l
a
s
h
Flash
Flash的起始地址和大小(因为我这里的测试芯片是
S
T
M
32
F
103
Z
E
T
6
STM32F103ZET6
STM32F103ZET6,因此
F
l
a
s
h
Flash
Flash是
512
K
B
=
0
x
00080000
512KB=0x00080000
512KB=0x00080000,虽然芯片在启动的时候,地址
0
x
00000000
0x00000000
0x00000000可以自动映射到地址
0
x
08000000
0x08000000
0x08000000,但是这里的起始地址只能写为
0
x
08000000
0x08000000
0x08000000),第6个元素是
F
l
a
s
h
Flash
Flash的一个页的大小,
S
T
M
32
F
103
Z
E
T
6
STM32F103ZET6
STM32F103ZET6的
F
l
a
s
h
Flash
Flash的一个页的大小为
2
K
B
=
2048
B
Y
T
E
S
2KB=2048BYTES
2KB=2048BYTES,第7个元素保留,第8个元素说明
F
l
a
s
h
Flash
Flash擦除完之后的内容,一般擦除完之后都是全F。第9个元素和第10个元素分别是
F
l
a
s
h
Flash
Flash页擦除和片擦除超时时间。最后一个元素定义了整片
F
l
a
s
h
Flash
Flash的页的分布情况,它是一个结构体数组。这个结构体有两个元素,第一个是一个页的大小,另一个是页的起始地址,要注意的是这里不用把每一个页的起始地址和大小都列出来,比如
S
T
M
32
F
103
Z
E
T
6
STM32F103ZET6
STM32F103ZET6的
F
l
a
s
h
Flash
Flash一共有256个页,每一个页的大小都是
2
K
B
=
2048
B
Y
T
E
S
2KB=2048BYTES
2KB=2048BYTES,因此这里结构体数组的第0个元素写为
(
2048
,
0
x
00000000
)
(2048,0x00000000)
(2048,0x00000000)就可以了(注意这里的起始地址只能写为
0
x
00000000
0x00000000
0x00000000而不能写为
0
x
08000000
0x08000000
0x08000000,具体的细节的原因我占时不知道,如果你这里写为
0
x
08000000
0x08000000
0x08000000,在下载程序的时候会报错,程序无法下载成功),这就表明整片
F
l
a
s
h
Flash
Flash的大小都是
2
K
B
=
2048
B
Y
T
E
S
2KB=2048BYTES
2KB=2048BYTES。别忘了最后还要加一个数组元素
S
E
C
T
O
R
_
E
N
D
SECTOR\_END
SECTOR_END。那如果出现
F
l
a
s
h
Flash
Flash的所有页不是同样大小的情况怎么样,我们现在举一个简单的例子,假如
F
l
a
s
h
Flash
Flash开头的8页,每一页的大小都是
8
K
B
8KB
8KB,接下来的两页,每一页的大小都是
64
K
B
64KB
64KB,接下来的所有页,每一页的大小都是
8
K
B
8KB
8KB,如图8所示,这个例子也是上面复制的模板工程里面原来的代码。改完之后的参数结构体如图9所示。
图7.
图8.
图9.
?????下面我们来详细介绍一下
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm需要用到的一些接口函数以及相应的流程,这些函数都在文
F
l
a
s
h
P
r
g
.
c
FlashPrg.c
FlashPrg.c中,如下所示,其中前面4个是必须的,后面3个可以根据需求可选,这里我在测试的时候只实现了必须要实现的接口函数。
-
I
n
i
t
,(必须)
Init,(必须)
Init,(必须)
-
U
n
I
n
i
t
,(必须)
UnInit,(必须)
UnInit,(必须)
-
E
r
a
s
e
S
e
c
t
o
r
,(必须)
EraseSector,(必须)
EraseSector,(必须)
-
P
r
o
g
r
a
m
P
a
g
e
,(必须)
ProgramPage,(必须)
ProgramPage,(必须)
-
E
r
a
s
e
C
h
i
p
,(可选)
EraseChip,(可选)
EraseChip,(可选)
-
B
l
a
n
k
C
h
e
c
k
,(可选)
BlankCheck,(可选)
BlankCheck,(可选)
-
V
e
r
i
f
y
,(可选)
Verify,(可选)
Verify,(可选)
?????接口函数
B
l
a
n
k
C
h
e
c
k
BlankCheck
BlankCheck主要的功能是用来检查当前的
F
l
a
s
h
Flash
Flash区域是否是空的,注意对于
F
l
a
s
h
Flash
Flash区域来说空的含义就是这个区域的每一个字节的内容都是全
F
F
F,
0
x
F
F
0xFF
0xFF,起始如果对于一个区域是全
F
F
F的话,我们不去擦除就可以直接去烧录。当然这个函数也可以用来检查一块特定的
F
l
a
s
h
Flash
Flash区域的内容是否等于特定的值,比如每一个字节的内容是否等于
0
x
A
A
0xAA
0xAA。其中参数
a
d
r
adr
adr表示要检查的
F
l
a
s
h
Flash
Flash区域的起始地址,参数
s
z
sz
sz表示要检查的
F
l
a
s
h
Flash
Flash区域的大小,参数
p
a
t
pat
pat表示要检查的
F
l
a
s
h
Flash
Flash区域的预期的特定值,比如
0
x
F
F
0xFF
0xFF。
int BlankCheck (unsigned long adr, unsigned long sz, unsigned char pat);
Parameters
adr Block start address
sz Block size in bytes
pat Pattern to compare
Returns
status information:0 when the block content is equal to the pattern pat.
status information:1 when the block content differs from the pattern pat.
?????接口函数
E
r
a
s
e
C
h
i
p
EraseChip
EraseChip主要的功能是用来擦除整片
F
l
a
s
h
Flash
Flash区域,如果我们在图10中配置下载算法的对话框中勾选了
E
r
a
s
e
F
u
l
l
C
h
i
p
Erase\quad Full\quad Chip
EraseFullChip的话,在下载程序的过程中,
K
e
i
l
M
D
K
I
D
E
Keil\quad MDK\quad IDE
KeilMDKIDE就会调用下载算法中的这个接口首先将整片
F
l
a
s
h
Flash
Flash区域擦除,这个函数实现起来是比较简单的,一般芯片设计公司提供的库函数里面就有响应功能的接口函数,参考一下就可以了,比如
S
T
ST
ST公司的
S
T
M
32
F
103
STM32F103
STM32F103提供的擦除整片
F
l
a
s
h
Flash
Flash区域的接口函数如图11所示。如果我们没有实现这个接口函数的话,
K
e
i
l
M
D
K
I
D
E
Keil\quad MDK\quad IDE
KeilMDKIDE会不断调用
E
r
a
s
e
S
e
c
t
o
r
EraseSector
EraseSector接口函数,直到整片
F
l
a
s
h
Flash
Flash区域被擦除。
int EraseChip (void);
Returns
status information: 0 on success.
status information: 1 on failure.
图10.
int EraseChip (void)
{
FLASH_Status status = FLASH_COMPLETE;
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
FLASH->CR |= CR_MER_Set;
FLASH->CR |= CR_STRT_Set;
status = FLASH_WaitForLastOperation(EraseTimeout);
FLASH->CR &= CR_MER_Reset;
}
if(status == FLASH_COMPLETE)
{
return (0);
}
else
{
return (1);
}
}
图11.
?????接口函数
E
r
a
s
e
S
e
c
t
o
r
EraseSector
EraseSector主要的功能是用来擦除
F
l
a
s
h
Flash
Flash区域的一页内容,如果我们在图10中配置下载算法的对话框中勾选了
E
r
a
s
e
F
u
l
l
S
e
c
t
o
r
s
Erase\quad Full\quad Sectors
EraseFullSectors的话,在下载程序的过程中,
K
e
i
l
M
D
K
I
D
E
Keil\quad MDK\quad IDE
KeilMDKIDE就会调用下载算法中的这个接口。参数
a
d
r
adr
adr表示要擦除的
F
l
a
s
h
Flash
Flash区域的页的起始地址,这个函数实现起来是比较简单的,一般芯片设计公司提供的库函数里面就有响应功能的接口函数,参考一下就可以了,比如
S
T
ST
ST公司的
S
T
M
32
F
103
STM32F103
STM32F103提供的擦除
F
l
a
s
h
Flash
Flash区域的一页接口函数如图12所示。
int EraseSector (unsigned long adr);
Parameters
adr Sector address
Returns
status information:0 on success.
status information:1 on failure.
?????接口函数
E
r
a
s
e
S
e
c
t
o
r
EraseSector
EraseSector我的具体实现如下所示,因为原本的工程里面没有下面函数中
F
L
A
S
H
FLASH
FLASH等结构体的定义,因此这些结构体的定义,你需要自己添加进去。
int EraseSector (unsigned long adr)
{
FLASH_Status status = FLASH_COMPLETE;
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
FLASH->CR|= CR_PER_Set;
FLASH->AR = adr;
FLASH->CR|= CR_STRT_Set;
status = FLASH_WaitForLastOperation(EraseTimeout);
FLASH->CR &= CR_PER_Reset;
}
if(status == FLASH_COMPLETE)
{
return (0);
}
else
{
return (1);
}
}
图12.
?????接口函数
I
n
i
t
Init
Init用来在操作
F
l
a
s
h
Flash
Flash区域前的一些初始化操作,像最基本的,在操作
F
l
a
s
h
Flash
Flash相关的寄存器前需要先解锁。参数
a
d
r
adr
adr表示
F
l
a
s
h
Flash
Flash设备的基地址,参数
f
n
c
fnc
fnc表示不同的操作,1表示擦除,2表示烧录,3表示验证,参数
c
l
k
clk
clk表示操作时的时钟频率,但是我看官方的模板函数里面这三个参数基本没有用到,这里我也没有细究了。这里我的具体实现也比较简单,也就是给
F
l
a
s
h
Flash
Flash操作解锁了。
int Init (unsigned long adr, unsigned long clk, unsigned long fnc);
Parameters
adr Device base address
clk Clock frequency (Hz)
fnc Function code
Returns
status information:0 on success.
status information:1 on failure.
int Init (unsigned long adr, unsigned long clk, unsigned long fnc)
{
FLASH_Unlock();
return (0);
}
?????接口函数
P
r
o
g
r
a
m
P
a
g
e
ProgramPage
ProgramPage主要的功能是在下载程序的过程中将编译好的代码文件烧录到
F
l
a
s
h
Flash
Flash区域中,每调用一次该函数只能烧录一页的内容。参数
a
d
r
adr
adr表示要烧录的
F
l
a
s
h
Flash
Flash区域的页的起始地址,参数
s
z
sz
sz表示要烧录的
F
l
a
s
h
Flash
Flash区域的页的大小,参数
b
u
f
buf
buf存储要烧录到
F
l
a
s
h
Flash
Flash区域的页中的代码的实际内容。这个函数实现起来是比较简单的,但是这里
S
T
ST
ST公司的
S
T
M
32
F
103
STM32F103
STM32F103的库函数里面没有直接的烧录一页的接口函数,只有烧录一个字或半个字的接口函数,
S
T
M
32
F
103
STM32F103
STM32F103的
F
l
a
s
h
Flash
Flash区域一次只能烧录半个字,我们可以可以调用如图13所示的烧录半个字的接口来实现烧录一页的接口函数。
int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf);
Parameters
adr Page start address
sz Page size
buf Data to be written
Returns
status information: 0 on success.
status information: 1 on failure.
int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf)
{
FLASH_Status status = FLASH_COMPLETE;
sz = (sz + 1) & ~1;
while (sz)
{
status = FLASH_COMPLETE;
status=FLASH_ProgramHalfWord(adr, *((unsigned short *)buf));
if(status != FLASH_COMPLETE)
{
return (1);
}
adr += 2;
buf += 2;
sz -= 2;
}
return (0);
}
图13.
?????接口函数
U
n
I
n
i
t
UnInit
UnInit用来进行在操作(擦除,烧录,验证)
F
l
a
s
h
Flash
Flash区域后的一些操作,像最基本的,对
F
l
a
s
h
Flash
Flash相关的寄存器重新上锁。参数
f
n
c
fnc
fnc表示不同的操作,1表示擦除,2表示烧录,3表示验证,但是我看官方的模板函数里面这个参数基本没有用到,这里我也没有细究了。这里我的具体实现也比较简单,也就是给
F
l
a
s
h
Flash
Flash重新上锁。
int UnInit (unsigned long fnc);
Parameters
fnc Function code
Returns
status information:0 on success.
status information:1 on failure.
int UnInit (unsigned long fnc)
{
FLASH_Lock();
return (0);
}
?????接口函数
V
e
r
i
f
y
Verify
Verify主要的功能是对比已经下载到
F
l
a
s
h
Flash
Flash区域中的代码和代码文件,也就是看下载到
F
l
a
s
h
Flash
Flash区域中的代码和编译生成的代码是否一致。参数
a
d
r
adr
adr表示要对比的
F
l
a
s
h
Flash
Flash区域的起始地址,参数
s
z
sz
sz表示要对比的
F
l
a
s
h
Flash
Flash区域的大小,参数
b
u
f
buf
buf存储要对比的代码的实际内容。
unsigned long Verify (unsigned long adr, unsigned long sz, unsigned char *buf);
Parameters
adr Start address
sz Size in bytes
buf Data to be compared
Returns
status information:the sum of (adr+sz) - on success.
status information:any other number - on failure, and represents the failing address.
?????有了以上修改之后,编译这个模板工程就可以生成你所需的下载算法了,下载算法的文件名后缀为
F
L
M
FLM
FLM,可以将这个生成的下载算法替代以前的下载算法,测试看看能否下载成功。最后图14是
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm的擦除流程,图15是
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm的程序烧录流程,图16是
F
l
a
s
h
p
r
o
g
r
a
m
m
i
n
g
a
l
g
o
r
i
t
h
m
Flash\quad programming\quad algorithm
Flashprogrammingalgorithm的验证流程。我的测试工程在这里。
图14.
图15.
图16.
|