2 ******************************************************************************
4 * @file pios_flash_internal.c
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
6 * @brief brief goes here.
8 * @see The GNU Public License (GPL) Version 3
10 *****************************************************************************/
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #ifdef PIOS_INCLUDE_FLASH_INTERNAL
31 #include "stm32f10x_flash.h"
32 #include "pios_flash_internal_priv.h"
33 #include "pios_flash.h"
36 struct device_flash_sector
{
42 static bool PIOS_Flash_Internal_GetSectorInfo(uint32_t address
, uint8_t *sector_number
, uint32_t *sector_start
, uint32_t *sector_size
)
44 uint16_t sector
= (address
- 0x08000000) / 1024;
47 /* address lies within this sector */
48 *sector_number
= sector
;
49 *sector_start
= sector
* 1024 + 0x08000000;
57 enum pios_internal_flash_dev_magic
{
58 PIOS_INTERNAL_FLASH_DEV_MAGIC
= 0x33445902,
61 struct pios_internal_flash_dev
{
62 enum pios_internal_flash_dev_magic magic
;
64 #if defined(PIOS_INCLUDE_FREERTOS)
65 xSemaphoreHandle transaction_lock
;
66 #endif /* defined(PIOS_INCLUDE_FREERTOS) */
69 static bool PIOS_Flash_Internal_Validate(struct pios_internal_flash_dev
*flash_dev
)
71 return flash_dev
&& (flash_dev
->magic
== PIOS_INTERNAL_FLASH_DEV_MAGIC
);
74 #if defined(PIOS_INCLUDE_FREERTOS)
75 static struct pios_internal_flash_dev
*PIOS_Flash_Internal_alloc(void)
77 struct pios_internal_flash_dev
*flash_dev
;
79 flash_dev
= (struct pios_internal_flash_dev
*)pvPortMalloc(sizeof(*flash_dev
));
84 flash_dev
->magic
= PIOS_INTERNAL_FLASH_DEV_MAGIC
;
89 static struct pios_internal_flash_dev pios_internal_flash_devs
[PIOS_INTERNAL_FLASH_MAX_DEVS
];
90 static uint8_t pios_internal_flash_num_devs
;
91 static struct pios_internal_flash_dev
*PIOS_Flash_Internal_alloc(void)
93 struct pios_internal_flash_dev
*flash_dev
;
95 if (pios_internal_flash_num_devs
>= PIOS_INTERNAL_FLASH_MAX_DEVS
) {
99 flash_dev
= &pios_internal_flash_devs
[pios_internal_flash_num_devs
++];
100 flash_dev
->magic
= PIOS_INTERNAL_FLASH_DEV_MAGIC
;
105 #endif /* defined(PIOS_INCLUDE_FREERTOS) */
107 int32_t PIOS_Flash_Internal_Init(uintptr_t *flash_id
, __attribute__((unused
)) const struct pios_flash_internal_cfg
*cfg
)
109 struct pios_internal_flash_dev
*flash_dev
;
111 flash_dev
= PIOS_Flash_Internal_alloc();
112 if (flash_dev
== NULL
) {
116 #if defined(PIOS_INCLUDE_FREERTOS)
117 flash_dev
->transaction_lock
= xSemaphoreCreateMutex();
118 #endif /* defined(PIOS_INCLUDE_FREERTOS) */
120 *flash_id
= (uintptr_t)flash_dev
;
125 /**********************************
127 * Provide a PIOS flash driver API
129 *********************************/
130 #include "pios_flash.h"
132 static int32_t PIOS_Flash_Internal_StartTransaction(uintptr_t flash_id
)
134 struct pios_internal_flash_dev
*flash_dev
= (struct pios_internal_flash_dev
*)flash_id
;
136 if (!PIOS_Flash_Internal_Validate(flash_dev
)) {
140 #if defined(PIOS_INCLUDE_FREERTOS)
141 if (xSemaphoreTake(flash_dev
->transaction_lock
, portMAX_DELAY
) != pdTRUE
) {
144 #endif /* defined(PIOS_INCLUDE_FREERTOS) */
146 /* Unlock the internal flash so we can write to it */
151 static int32_t PIOS_Flash_Internal_EndTransaction(uintptr_t flash_id
)
153 struct pios_internal_flash_dev
*flash_dev
= (struct pios_internal_flash_dev
*)flash_id
;
155 if (!PIOS_Flash_Internal_Validate(flash_dev
)) {
159 #if defined(PIOS_INCLUDE_FREERTOS)
160 if (xSemaphoreGive(flash_dev
->transaction_lock
) != pdTRUE
) {
163 #endif /* defined(PIOS_INCLUDE_FREERTOS) */
165 /* Lock the internal flash again so we can no longer write to it */
171 static int32_t PIOS_Flash_Internal_EraseSector(uintptr_t flash_id
, uint32_t addr
)
173 struct pios_internal_flash_dev
*flash_dev
= (struct pios_internal_flash_dev
*)flash_id
;
175 if (!PIOS_Flash_Internal_Validate(flash_dev
)) {
179 uint8_t sector_number
;
180 uint32_t sector_start
;
181 uint32_t sector_size
;
182 if (!PIOS_Flash_Internal_GetSectorInfo(addr
,
186 /* We're asking for an invalid flash address */
190 if (FLASH_ErasePage(sector_start
) != FLASH_COMPLETE
) {
197 static int32_t PIOS_Flash_Internal_WriteData(uintptr_t flash_id
, uint32_t addr
, uint8_t *data
, uint16_t len
)
201 struct pios_internal_flash_dev
*flash_dev
= (struct pios_internal_flash_dev
*)flash_id
;
203 if (!PIOS_Flash_Internal_Validate(flash_dev
)) {
207 uint8_t sector_number
;
208 uint32_t sector_start
;
209 uint32_t sector_size
;
213 /* Ensure that the base address is in a valid sector */
214 if (!PIOS_Flash_Internal_GetSectorInfo(addr
,
218 /* We're asking for an invalid flash address */
222 /* Ensure that the entire write occurs within the same sector */
223 if ((uintptr_t)addr
+ len
> sector_start
+ sector_size
) {
224 /* Write crosses the end of the sector */
229 uint32_t temp_addr
= addr
;
230 uint16_t numberOfhWords
= len
/ 2;
233 for (x
= 0; x
< numberOfhWords
; ++x
) {
235 hword_data
= (data
[offset
+ 1] << 8) | data
[offset
];
237 if (hword_data
!= *(uint16_t *)(temp_addr
+ offset
)) {
238 status
= FLASH_ProgramHalfWord(temp_addr
+ offset
, hword_data
);
240 status
= FLASH_COMPLETE
;
242 PIOS_Assert(status
== FLASH_COMPLETE
);
245 uint16_t mod
= len
% 2;
248 hword_data
= 0xFF00 | data
[offset
];
249 if (hword_data
!= *(uint16_t *)(temp_addr
+ offset
)) {
250 status
= FLASH_ProgramHalfWord(temp_addr
+ offset
, hword_data
);
252 status
= FLASH_COMPLETE
;
254 PIOS_Assert(status
== FLASH_COMPLETE
);
260 static int32_t PIOS_Flash_Internal_ReadData(uintptr_t flash_id
, uint32_t addr
, uint8_t *data
, uint16_t len
)
264 struct pios_internal_flash_dev
*flash_dev
= (struct pios_internal_flash_dev
*)flash_id
;
266 if (!PIOS_Flash_Internal_Validate(flash_dev
)) {
270 uint8_t sector_number
;
271 uint32_t sector_start
;
272 uint32_t sector_size
;
274 /* Ensure that the base address is in a valid sector */
275 if (!PIOS_Flash_Internal_GetSectorInfo(addr
,
279 /* We're asking for an invalid flash address */
283 /* Ensure that the entire read occurs within the same sector */
284 if ((uintptr_t)addr
+ len
> sector_start
+ sector_size
) {
285 /* Read crosses the end of the sector */
289 /* Read the data into the buffer directly */
290 memcpy(data
, (void *)addr
, len
);
295 /* Provide a flash driver to external drivers */
296 const struct pios_flash_driver pios_internal_flash_driver
= {
297 .start_transaction
= PIOS_Flash_Internal_StartTransaction
,
298 .end_transaction
= PIOS_Flash_Internal_EndTransaction
,
299 .erase_sector
= PIOS_Flash_Internal_EraseSector
,
300 .write_data
= PIOS_Flash_Internal_WriteData
,
301 .read_data
= PIOS_Flash_Internal_ReadData
,
304 #endif /* PIOS_INCLUDE_FLASH_INTERNAL */