dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_flash_internal.c
Go to the documentation of this file.
1 
12 /*
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  * for more details.
22  *
23  * You should have received a copy of the GNU General Public License along
24  * with this program; if not, see <http://www.gnu.org/licenses/>
25  */
26 
27 #include "pios.h"
28 
29 #if defined(PIOS_INCLUDE_FLASH_INTERNAL)
30 
31 #include "stm32f30x_flash.h"
33 #include "pios_wdg.h"
34 #include "pios_semaphore.h"
35 #include <stdbool.h>
36 
37 #define STM32F30X_FLASH_SECTOR_SIZE 2048
38 
39 enum pios_internal_flash_dev_magic {
40  PIOS_INTERNAL_FLASH_DEV_MAGIC = 0xae82c65d,
41 };
42 
43 struct pios_internal_flash_dev {
44  enum pios_internal_flash_dev_magic magic;
45 
46  const struct pios_flash_internal_cfg *cfg;
47 
48  struct pios_semaphore *transaction_lock;
49 };
50 
51 static bool PIOS_Flash_Internal_Validate(struct pios_internal_flash_dev *flash_dev) {
52  return (flash_dev && (flash_dev->magic == PIOS_INTERNAL_FLASH_DEV_MAGIC));
53 }
54 
55 static struct pios_internal_flash_dev *PIOS_Flash_Internal_alloc(void)
56 {
57  struct pios_internal_flash_dev *flash_dev;
58 
59  flash_dev = (struct pios_internal_flash_dev *)PIOS_malloc(sizeof(*flash_dev));
60  if (!flash_dev) return (NULL);
61 
62  flash_dev->magic = PIOS_INTERNAL_FLASH_DEV_MAGIC;
63 
64  return(flash_dev);
65 }
66 
67 void FLASH_IRQHandler() {
68  PIOS_Assert(0);
69 }
70 
71 int32_t PIOS_Flash_Internal_Init(uintptr_t *chip_id, const struct pios_flash_internal_cfg *cfg)
72 {
73  struct pios_internal_flash_dev *flash_dev;
74 
75  flash_dev = PIOS_Flash_Internal_alloc();
76  if (flash_dev == NULL)
77  return -1;
78 
79  flash_dev->transaction_lock = PIOS_Semaphore_Create();
80 
81  flash_dev->cfg = cfg;
82 
83  /* Catch ERRIE interrupt indicating a flash error.
84  * These are usually null-pointer dereferences inadvertently
85  * accessing flash memory.
86  */
87  NVIC_InitTypeDef intr = {
88  .NVIC_IRQChannel = FLASH_IRQn,
89  .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST,
90  .NVIC_IRQChannelSubPriority = 0,
91  .NVIC_IRQChannelCmd = ENABLE,
92  };
93 
94  NVIC_Init(&intr);
95  FLASH_ITConfig(FLASH_IT_ERR, ENABLE);
96 
97  *chip_id = (uintptr_t) flash_dev;
98 
99  return 0;
100 }
101 
102 /**********************************
103  *
104  * Provide a PIOS flash driver API
105  *
106  *********************************/
107 #include "pios_flash_priv.h"
108 
109 static int32_t PIOS_Flash_Internal_StartTransaction(uintptr_t chip_id)
110 {
111  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
112 
113  if (!PIOS_Flash_Internal_Validate(flash_dev))
114  return -1;
115 
116  if (PIOS_Semaphore_Take(flash_dev->transaction_lock, PIOS_SEMAPHORE_TIMEOUT_MAX) != true)
117  return -2;
118 
119  /* Unlock the internal flash so we can write to it */
120  FLASH_Unlock();
121 
122  return 0;
123 }
124 
125 static int32_t PIOS_Flash_Internal_EndTransaction(uintptr_t chip_id)
126 {
127  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
128 
129  if (!PIOS_Flash_Internal_Validate(flash_dev))
130  return -1;
131 
132  if (PIOS_Semaphore_Give(flash_dev->transaction_lock) != true)
133  return -2;
134 
135  /* Lock the internal flash again so we can no longer write to it */
136  FLASH_Lock();
137 
138  return 0;
139 }
140 
141 static int32_t PIOS_Flash_Internal_EraseSector(uintptr_t chip_id, uint32_t chip_sector, uint32_t chip_offset)
142 {
143  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
144 
145  if (!PIOS_Flash_Internal_Validate(flash_dev))
146  return -1;
147 
148 #if defined(PIOS_INCLUDE_WDG)
149  PIOS_WDG_Clear();
150 #endif
151 
152  FLASH_Status ret = FLASH_ErasePage(FLASH_BASE + chip_offset);
153  if (ret != FLASH_COMPLETE)
154  return -3;
155 
156  return 0;
157 }
158 
159 static int32_t PIOS_Flash_Internal_ReadData(uintptr_t chip_id, uint32_t chip_offset, uint8_t *data, uint16_t len)
160 {
161  PIOS_Assert(data);
162 
163  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
164 
165  if (!PIOS_Flash_Internal_Validate(flash_dev))
166  return -1;
167 
168  /* Read the data into the buffer directly */
169  memcpy(data, (void *)(FLASH_BASE + chip_offset), len);
170 
171  return 0;
172 }
173 
174 static int32_t PIOS_Flash_Internal_WriteData(uintptr_t chip_id, uint32_t chip_offset, const uint8_t *data, uint16_t len)
175 {
176  PIOS_Assert(data);
177  PIOS_Assert((chip_offset & 0x0001) == 0);
178 
179  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
180 
181  if (!PIOS_Flash_Internal_Validate(flash_dev))
182  return -1;
183 
184  /* Write the data */
185  for (uint16_t i = 0; i < (len & ~1); i += 2) {
186  /* Check if content has been changed prior to write.
187  * This should enhance performance and make this compatible with the F3 chip.
188  */
189  uint8_t temp[2];
190  if (PIOS_Flash_Internal_ReadData(chip_id, chip_offset + i, temp, sizeof(temp)) != 0)
191  return -4;
192 
193  if (temp[0] == data[i] && temp[1] == data[i + 1])
194  continue;
195 
196  FLASH_Status status;
197  status = FLASH_ProgramHalfWord(FLASH_BASE + chip_offset + i, data[i + 1] << 8 | data[i]);
198  PIOS_Assert(status == FLASH_COMPLETE);
199  }
200  /* Handle uneven writes by filling up with 0xff*/
201  if ((len & 1) != 0) {
202  FLASH_Status status;
203  status = FLASH_ProgramHalfWord(FLASH_BASE + chip_offset + len - 1, 0xff << 8 | data[len - 1]);
204  PIOS_Assert(status == FLASH_COMPLETE);
205  }
206 
207  return 0;
208 }
209 
210 static void * PIOS_Flash_Internal_GetPointer(uintptr_t chip_id, uint32_t chip_offset)
211 {
212  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
213 
214  PIOS_Assert(PIOS_Flash_Internal_Validate(flash_dev));
215 
216  return (void *)(FLASH_BASE + chip_offset);
217 }
218 
219 /* Provide a flash driver to external drivers */
221  .start_transaction = PIOS_Flash_Internal_StartTransaction,
222  .end_transaction = PIOS_Flash_Internal_EndTransaction,
223  .erase_sector = PIOS_Flash_Internal_EraseSector,
224  .write_data = PIOS_Flash_Internal_WriteData,
225  .read_data = PIOS_Flash_Internal_ReadData,
226  .get_pointer = PIOS_Flash_Internal_GetPointer,
227 };
228 
229 #endif /* defined(PIOS_INCLUDE_FLASH_INTERNAL) */
230 
int32_t PIOS_Flash_Internal_Init(uintptr_t *flash_id, const struct pios_flash_internal_cfg *cfg)
#define PIOS_SEMAPHORE_TIMEOUT_MAX
Main PiOS header to include all the compiled in PiOS options.
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
#define PIOS_IRQ_PRIO_HIGHEST
Definition: pios_board.h:172
#define FLASH_IRQHandler
uint8_t data[XFER_BYTES_PER_PACKET]
Definition: bl_messages.h:129
void PIOS_WDG_Clear(void)
Clear the watchdog timer.
Definition: pios_wdg.c:147
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
int16_t status
Definition: main.c:61
struct pios_semaphore * PIOS_Semaphore_Create(void)
Creates a binary semaphore.
SPI functions header.
uint8_t i
Definition: msp_messages.h:97
bool PIOS_Semaphore_Give(struct pios_semaphore *sema)
Gives binary semaphore.
uint32_t magic
bool PIOS_Semaphore_Take(struct pios_semaphore *sema, uint32_t timeout_ms)
Takes binary semaphore.
#define PIOS_Assert(test)
Definition: pios_debug.h:52
int32_t(* start_transaction)(uintptr_t chip_id)
const struct pios_flash_driver pios_internal_flash_driver