-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbsp_flash.cpp
227 lines (185 loc) · 6.25 KB
/
bsp_flash.cpp
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
* bsp-motorctrl, a board support package library for a STM32 based motor
* control PCB. It is designed to abstract access to HW features in a generic
* and simple way. Please note thet it should not conain any buissness logic.
*
* Copyright (C) 2019 Julian Friedrich
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* You can file issues at https://github.com/fjulian79/bsp-motorctrl
*/
#include "bsp/bsp_flash.h"
#include <stm32f1xx.h>
#include <stm32f1xx_hal_flash.h>
#include <stdint.h>
/**
* Defines the bsp internal timeout in ms for flash operations.
*
* I have cosidered this to become a part of the bsp configuration, but it has
* turned out that on a stm32f103 a write or erase opteration block the flash
* controller from fetching further instructions. Therefore no code can be
* executed while programming or erasing flash. The wait function does not
* really makes that much sense!
*
* Therefore this setting is hidden and hardcoded to 1ms!
*/
#define BSP_FLASH_TIMEOUT 1
/**
* @brief Bitmask of all the flash operation mode bits.
*/
#define BSP_FLASH_MODEBITS \
\
(FLASH_CR_PG | FLASH_CR_PER | FLASH_CR_MER | FLASH_CR_OPTPG)
/**
* @brief Needed to make shure to hae only the desired mode bit set.
*/
#define BSP_FLASH_SETMODE(_mode) \
\
do \
{ \
CLEAR_BIT(FLASH->CR, BSP_FLASH_MODEBITS); \
SET_BIT(FLASH->CR, _mode); \
}while(0);
/**
* @brief Like errno.
*/
uint32_t bspFlashErr = 0;
/**
* @brief Used to check the error flags and clean them if needed. Actually it
* seams as further operations will fail until a set error flag gets cleared.
*
* In case of a error bspFlashGetErr() will provide the error code.
*
* @return BSP_OK In case of ne error
* In case of any error.
*/
bspStatus_t bspFlashSetErr(void)
{
bspFlashErr = 0;
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR))
{
bspFlashErr |= HAL_FLASH_ERROR_WRP;
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR);
}
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
{
bspFlashErr |= HAL_FLASH_ERROR_PROG;
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGERR);
}
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR))
{
bspFlashErr |= HAL_FLASH_ERROR_OPTV;
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
}
return bspFlashErr == 0 ? BSP_OK : BSP_ERR;
}
uint32_t bspFlashGetErr(void)
{
return bspFlashErr;
}
bspStatus_t bspFlashUnlock(void)
{
if (HAL_IS_BIT_SET(FLASH->CR, FLASH_CR_LOCK))
{
WRITE_REG(FLASH->KEYR, FLASH_KEY1);
WRITE_REG(FLASH->KEYR, FLASH_KEY2);
if (HAL_IS_BIT_SET(FLASH->CR, FLASH_CR_LOCK))
{
return BSP_ERR;
}
}
return BSP_OK;
}
bspStatus_t bspFlashLock(void)
{
/* Set the LOCK Bit if it is not set to lock the
* FLASH Registers access */
if (!HAL_IS_BIT_SET(FLASH->CR, FLASH_CR_LOCK))
{
SET_BIT(FLASH->CR, FLASH_CR_LOCK);
if (!HAL_IS_BIT_SET(FLASH->CR, FLASH_CR_LOCK))
{
return BSP_ERR;
}
}
return BSP_OK;
}
bspStatus_t bspFlashProgHalfWord(uint16_t *addr, uint16_t data)
{
if (HAL_IS_BIT_SET(FLASH->CR, FLASH_CR_LOCK))
return BSP_ELOCK;
if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
return BSP_EBUSY;
if (addr < (uint16_t*)FLASH_BASE || (addr+1) > (uint16_t*)FLASH_BANK1_END)
return BSP_ERANGE;
/* Proceed to program the new data */
BSP_FLASH_SETMODE(FLASH_CR_PG);
*(__IO uint16_t*)addr = data;
return bspFlashWaitForLastOperation(BSP_FLASH_TIMEOUT);
}
bspStatus_t bspFlashProg(uint16_t *addr, uint16_t *pData, size_t siz)
{
bspStatus_t ret = BSP_OK;
if (HAL_IS_BIT_SET(FLASH->CR, FLASH_CR_LOCK))
return BSP_ELOCK;
if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
return BSP_EBUSY;
if (addr < (uint16_t*)FLASH_BASE || (addr+siz) > (uint16_t*)FLASH_BANK1_END)
return BSP_ERANGE;
if (siz%2 != 0)
return BSP_ESIZE;
BSP_FLASH_SETMODE(FLASH_CR_PG);
for(size_t i = 0; i < siz; i++)
{
*(__IO uint16_t*)&addr[i] = pData[i];
ret = bspFlashWaitForLastOperation(BSP_FLASH_TIMEOUT);
if (ret != BSP_OK)
break;
}
return ret;
}
bspStatus_t bspFlashErasePage(uint32_t addr)
{
if (HAL_IS_BIT_SET(FLASH->CR, FLASH_CR_LOCK))
return BSP_ELOCK;
if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
return BSP_EBUSY;
BSP_FLASH_SETMODE(FLASH_CR_PER);
WRITE_REG(FLASH->AR, addr);
SET_BIT(FLASH->CR, FLASH_CR_STRT);
return bspFlashWaitForLastOperation(BSP_FLASH_TIMEOUT);
}
bspStatus_t bspFlashWaitForLastOperation(uint32_t timeout)
{
uint32_t tickStart = bspGetSysTick();
/* guarantee minimum wait */
timeout++;
/* Wait for the FLASH operation to complete by polling on BUSY flag to be
* reset. Even if the FLASH operation fails, the BUSY flag will be reset
* and an error flag will be set. The error check is performed by
* bspFlashSetErr();
* */
while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
{
if (timeout != HAL_MAX_DELAY)
{
if((timeout == 0) || ((bspGetSysTick()-tickStart) > timeout))
return BSP_ETIMEOUT;
}
}
if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
return bspFlashSetErr();
}