Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Sami Nurmenniemi
u-boot-stm32
Commits
fd070806
Commit
fd070806
authored
Oct 07, 2011
by
Sergei Poselenov
Browse files
RT #72064. Implemented erase/program support for the STM32 embedded flash.
This version supports the whole flash erase only.
parent
9a50acfd
Changes
1
Hide whitespace changes
Inline
Side-by-side
cpu/arm_cortexm3/stm32/envm.c
View file @
fd070806
/*
*
(C) Copyright 2011
*
STM32 Embedded flash programming support.
*
* (C) Copyright 2011
* Yuri Tikhonov, Emcraft Systems, yur@emcraft.com
* Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -20,37 +22,166 @@
*/
#include
<common.h>
#include
<asm/arch/stm32.h>
#include
<errno.h>
#include
"envm.h"
/*
* Flash data area definitions
*/
#define STM32_FLASH_BASE 0x08000000
#define STM32_FLASH_SIZE (8*128*1024)
/*
* Flash registers base
*/
#define STM32F2_FLASH_BASE (STM32_AHB1PERITH_BASE + 0x3C00)
#define STM32_FLASHREGS_BASE (STM32_AHB1PERITH_BASE + 0x3C00)
/*
* Flash register map
*/
struct
stm32_flash_regs
{
u32
acr
;
/* Access control */
u32
keyr
;
/* Key */
u32
optkeyr
;
/* Option key */
u32
sr
;
/* Status */
u32
cr
;
/* Control */
u32
optcr
;
/* Option control */
};
#define STM32_FLASH_REGS ((volatile struct stm32_flash_regs *) \
STM32_FLASHREGS_BASE)
/*
* Flash CR definitions
*/
#define STM32_FLASH_CR_LOCK (1 << 31)
#define STM32_FLASH_CR_ERRIE (1 << 25)
#define STM32_FLASH_CR_EOPIE (1 << 24)
#define STM32_FLASH_CR_START (1 << 16)
#define STM32_FLASH_CR_PSIZE_SHIFT 8
#define STM32_FLASH_CR_PSIZE_MSK 0x3
#define STM32_FLASH_CR_PSIZE_32x (2 << STM32_FLASH_CR_PSIZE_SHIFT)
#define STM32_FLASH_CR_SECT_SHIFT 3
#define STM32_FLASH_CR_SECT_MSK 0xf
#define STM32_FLASH_CR_MER (1 << 2)
#define STM32_FLASH_CR_SER (1 << 1)
#define STM32_FLASH_CR_PG (1 << 0)
/*
* Flash ACR definitions
*/
#define STM32F2_FLASH_ACR_LAT_BIT 0
/* Latency */
#define STM32F2_FLASH_ACR_LAT_MSK 0x3
#define STM32_FLASH_ACR_LAT_BIT 0
/* Latency */
#define STM32_FLASH_ACR_LAT_MSK 0x3
#define STM32_FLASH_ACR_PRFTEN (1 << 8)
/* Prefetch enable */
#define STM32_FLASH_ACR_ICEN (1 << 9)
/* Instruction cache enable */
/*
* Flash KEYR definitions
*/
#define STM32_FLASH_KEYR_KEY1 0x45670123
/* KEY1 value to unlock CR */
#define STM32_FLASH_KEYR_KEY2 0xCDEF89AB
/* KEY2 value to unlock CR */
#define STM32F2_FLASH_ACR_PRFTEN (1 << 8)
/* Prefetch enable */
#define STM32F2_FLASH_ACR_ICEN (1 << 9)
/* Instruction cache enable*/
/*
* Flash SR definitions
*/
#define STM32_FLASH_SR_BSY (1 << 16)
#define STM32_FLASH_SR_PGSERR (1 << 7)
#define STM32_FLASH_SR_PGPERR (1 << 6)
#define STM32_FLASH_SR_PGAERR (1 << 5)
#define STM32_FLASH_SR_WRPERR (1 << 4)
#define STM32_FLASH_SR_OPERR (1 << 1)
#define STM32_FLASH_SR_EOP (1 << 0)
/*
*
Flash r
egister
map
*
Unlock the Flash Command R
egister
*/
struct
stm32f2_flash_regs
{
u32
acr
;
/* Access control */
u32
keyr
;
/* Key */
u32
optkeyr
;
/* Option key */
u32
sr
;
/* Status */
u32
cr
;
/* Control */
u32
optcr
;
/* Option control */
};
#define STM32F2_FLASH ((volatile struct stm32f2_flash_regs *) \
STM32F2_FLASH_BASE)
static
void
__attribute__
((
section
(
".ramcode"
)))
__attribute__
((
long_call
))
stm32_flash_cr_unlock
(
void
)
{
if
(
STM32_FLASH_REGS
->
cr
&
STM32_FLASH_CR_LOCK
)
{
STM32_FLASH_REGS
->
keyr
=
STM32_FLASH_KEYR_KEY1
;
STM32_FLASH_REGS
->
keyr
=
STM32_FLASH_KEYR_KEY2
;
}
}
/*
* Lock the Flash Command Register
*/
static
void
__attribute__
((
section
(
".ramcode"
)))
__attribute__
((
long_call
))
stm32_flash_cr_lock
(
void
)
{
STM32_FLASH_REGS
->
cr
|=
STM32_FLASH_CR_LOCK
;
}
/*
* Erase the whole embedded flash of the STM32.
*/
static
int
__attribute__
((
section
(
".ramcode"
)))
__attribute__
((
long_call
))
stm32_flash_erase
(
uint32_t
offset
,
uint32_t
size
)
{
int32_t
ret
=
-
EBUSY
;
/* No sanity check of address here, proceed to erase */
/* Check there is no pending operations */
if
(
STM32_FLASH_REGS
->
sr
&
STM32_FLASH_SR_BSY
)
{
printf
(
"%s: Flash is busy
\n
"
,
__func__
);
goto
xit
;
}
stm32_flash_cr_unlock
();
STM32_FLASH_REGS
->
cr
|=
STM32_FLASH_CR_MER
;
STM32_FLASH_REGS
->
cr
|=
STM32_FLASH_CR_START
;
/*
* Warning! As soon as the erase operation starts, you can't access
* U-Boot functions except of marked as ".ramcode".
*/
while
(
STM32_FLASH_REGS
->
sr
&
STM32_FLASH_SR_BSY
)
;
STM32_FLASH_REGS
->
cr
&=
~
STM32_FLASH_CR_MER
;
stm32_flash_cr_lock
();
ret
=
0
;
xit:
return
ret
;
}
static
int
__attribute__
((
section
(
".ramcode"
)))
__attribute__
((
long_call
))
stm32_flash_program
(
uint32_t
offset
,
void
*
buf
,
uint32_t
size
)
{
uint32_t
*
src
=
(
uint32_t
*
)
buf
;
uint32_t
*
dst
=
(
uint32_t
*
)
offset
;
/* I know I can read 1-3 bytes beyond the input buffer, but this is OK */
uint32_t
words
=
(
size
+
sizeof
(
uint32_t
)
-
1
)
/
sizeof
(
uint32_t
);
int32_t
ret
=
-
EBUSY
;
/* No sanity check on flash address here, proceed to program */
/* Check there is no pending operations */
if
(
STM32_FLASH_REGS
->
sr
&
STM32_FLASH_SR_BSY
)
goto
xit
;
stm32_flash_cr_unlock
();
STM32_FLASH_REGS
->
cr
|=
STM32_FLASH_CR_PG
;
/* Since we are using 32x parallelism (set in CR), copy by 4 bytes */
while
(
words
--
)
{
*
dst
++
=
*
src
++
;
while
(
STM32_FLASH_REGS
->
sr
&
STM32_FLASH_SR_BSY
)
;
}
STM32_FLASH_REGS
->
cr
&=
~
STM32_FLASH_CR_PG
;
stm32_flash_cr_lock
();
ret
=
0
;
xit:
return
ret
;
}
/*
* Enable instruction cache, prefetch and set the Flash wait latency
...
...
@@ -62,12 +193,12 @@ struct stm32f2_flash_regs {
*/
void
envm_config
(
u32
wait_states
)
{
if
(
wait_states
>
STM32
F2
_FLASH_ACR_LAT_MSK
)
wait_states
=
STM32
F2
_FLASH_ACR_LAT_MSK
;
if
(
wait_states
>
STM32_FLASH_ACR_LAT_MSK
)
wait_states
=
STM32_FLASH_ACR_LAT_MSK
;
STM32
F2
_FLASH
->
acr
=
STM32
F2
_FLASH_ACR_PRFTEN
|
STM32
F2
_FLASH_ACR_ICEN
|
(
wait_states
<<
STM32
F2
_FLASH_ACR_LAT_BIT
);
STM32_FLASH
_REGS
->
acr
=
STM32_FLASH_ACR_PRFTEN
|
STM32_FLASH_ACR_ICEN
|
(
wait_states
<<
STM32_FLASH_ACR_LAT_BIT
);
}
/*
...
...
@@ -75,11 +206,12 @@ void envm_config(u32 wait_states)
*/
void
envm_init
(
void
)
{
/*
* TBD
*/
return
;
stm32_flash_cr_unlock
();
/* Clear ints, set the parallelism */
STM32_FLASH_REGS
->
cr
&=
~
(
STM32_FLASH_CR_PSIZE_MSK
|
STM32_FLASH_CR_ERRIE
|
STM32_FLASH_CR_EOPIE
);
STM32_FLASH_REGS
->
cr
|=
STM32_FLASH_CR_PSIZE_32x
;
stm32_flash_cr_lock
();
}
/*
...
...
@@ -89,11 +221,22 @@ void envm_init(void)
*/
unsigned
int
__attribute__
((
section
(
".ramcode"
)))
__attribute__
((
long_call
))
envm_write
(
u
nsigned
in
t
offset
,
void
*
buf
,
u
nsigned
in
t
size
)
envm_write
(
u
int32_
t
offset
,
void
*
buf
,
u
int32_
t
size
)
{
/*
* TBD
*/
int32_t
ret
=
0
;
/* Sanity check */
if
((
offset
<
STM32_FLASH_BASE
)
||
((
offset
+
size
)
>
(
STM32_FLASH_BASE
+
STM32_FLASH_SIZE
)))
{
printf
(
"Offset %#x is not in flash or size %d is too big
\n
"
,
offset
,
size
);
goto
xit
;
}
if
(
stm32_flash_erase
(
offset
,
size
)
<
0
||
(
stm32_flash_program
(
offset
,
buf
,
size
)
<
0
))
goto
xit
;
return
0
;
ret
=
size
;
xit:
return
ret
;
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment