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 #ifdef PIOS_INCLUDE_FLASH_INTERNAL
30 
31 #include "stm32f10x_flash.h"
33 #include "pios_wdg.h"
34 #include "pios_semaphore.h"
35 #include <stdbool.h>
36 
37 enum pios_internal_flash_dev_magic {
38  PIOS_INTERNAL_FLASH_DEV_MAGIC = 0xae82c65d,
39 };
40 
41 struct pios_internal_flash_dev {
42  enum pios_internal_flash_dev_magic magic;
43 
44  const struct pios_flash_internal_cfg *cfg;
45 
46  struct pios_semaphore *transaction_lock;
47 };
48 
49 static bool PIOS_Flash_Internal_Validate(struct pios_internal_flash_dev *flash_dev) {
50  return (flash_dev && (flash_dev->magic == PIOS_INTERNAL_FLASH_DEV_MAGIC));
51 }
52 
53 static struct pios_internal_flash_dev *PIOS_Flash_Internal_alloc(void)
54 {
55  struct pios_internal_flash_dev *flash_dev;
56 
57  flash_dev = (struct pios_internal_flash_dev *)PIOS_malloc(sizeof(*flash_dev));
58  if (!flash_dev) return (NULL);
59 
60  flash_dev->magic = PIOS_INTERNAL_FLASH_DEV_MAGIC;
61 
62  return(flash_dev);
63 }
64 
65 
66 void FLASH_IRQHandler() {
67  PIOS_Assert(0);
68 }
69 
70 int32_t PIOS_Flash_Internal_Init(uintptr_t *chip_id, const struct pios_flash_internal_cfg *cfg)
71 {
72  struct pios_internal_flash_dev *flash_dev;
73 
74  flash_dev = PIOS_Flash_Internal_alloc();
75  if (flash_dev == NULL)
76  return -1;
77 
78  flash_dev->transaction_lock = PIOS_Semaphore_Create();
79 
80  flash_dev->cfg = cfg;
81 
82  /* Catch ERRIE interrupt indicating a flash error.
83  * These are usually null-pointer dereferences inadvertently
84  * accessing flash memory.
85  */
86  NVIC_InitTypeDef intr = {
87  .NVIC_IRQChannel = FLASH_IRQn,
88  .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST,
89  .NVIC_IRQChannelSubPriority = 0,
90  .NVIC_IRQChannelCmd = ENABLE,
91  };
92 
93  NVIC_Init(&intr);
94  FLASH_ITConfig(FLASH_IT_ERROR, ENABLE);
95 
96  *chip_id = (uintptr_t) flash_dev;
97 
98  return 0;
99 }
100 
101 /**********************************
102  *
103  * Provide a PIOS flash driver API
104  *
105  *********************************/
106 #include "pios_flash_priv.h"
107 
108 static int32_t PIOS_Flash_Internal_StartTransaction(uintptr_t chip_id)
109 {
110  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
111 
112  if (!PIOS_Flash_Internal_Validate(flash_dev))
113  return -1;
114 
115  if (PIOS_Semaphore_Take(flash_dev->transaction_lock, PIOS_SEMAPHORE_TIMEOUT_MAX) != true)
116  return -2;
117 
118  /* Unlock the internal flash so we can write to it */
119  FLASH_Unlock();
120 
121  return 0;
122 }
123 
124 static int32_t PIOS_Flash_Internal_EndTransaction(uintptr_t chip_id)
125 {
126  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
127 
128  if (!PIOS_Flash_Internal_Validate(flash_dev))
129  return -1;
130 
131  if (PIOS_Semaphore_Give(flash_dev->transaction_lock) != true)
132  return -2;
133 
134  /* Lock the internal flash again so we can no longer write to it */
135  FLASH_Lock();
136 
137  return 0;
138 }
139 
140 static int32_t PIOS_Flash_Internal_EraseSector(uintptr_t chip_id, uint32_t chip_sector, uint32_t chip_offset)
141 {
142  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
143 
144  if (!PIOS_Flash_Internal_Validate(flash_dev))
145  return -1;
146 
147 #if defined(PIOS_INCLUDE_WDG)
148  PIOS_WDG_Clear();
149 #endif
150 
151  FLASH_Status ret = FLASH_ErasePage(FLASH_BASE + chip_offset);
152  if (ret != FLASH_COMPLETE)
153  return -3;
154 
155  return 0;
156 }
157 
158 static int32_t PIOS_Flash_Internal_ReadData(uintptr_t chip_id, uint32_t chip_offset, uint8_t *data, uint16_t len)
159 {
160  PIOS_Assert(data);
161 
162  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
163 
164  if (!PIOS_Flash_Internal_Validate(flash_dev))
165  return -1;
166 
167  /* Read the data into the buffer directly */
168  memcpy(data, (void *)(FLASH_BASE + chip_offset), len);
169 
170  return 0;
171 }
172 
173 static int32_t PIOS_Flash_Internal_WriteData(uintptr_t chip_id, uint32_t chip_offset, const uint8_t *data, uint16_t len)
174 {
175  PIOS_Assert(data);
176 
177  struct pios_internal_flash_dev *flash_dev = (struct pios_internal_flash_dev *)chip_id;
178 
179  if (!PIOS_Flash_Internal_Validate(flash_dev))
180  return -1;
181 
182  /* Write the data */
183  uint16_t numberOfhWords = len / 2;
184  uint16_t x = 0;
185  FLASH_Status status;
186  for ( x = 0; x < numberOfhWords; ++x) {
187  uint32_t offset = 2 * x;
188  uint32_t hword_data = (data[offset + 1] << 8) | data[offset];
189 
190  if (hword_data != *(uint16_t *)(FLASH_BASE + chip_offset + offset)) {
191  status = FLASH_ProgramHalfWord(FLASH_BASE + chip_offset + offset, hword_data);
192  } else {
193  status = FLASH_COMPLETE;
194  }
195  PIOS_Assert(status == FLASH_COMPLETE);
196  }
197 
198  uint16_t mod = len % 2;
199  if (mod == 1) {
200  uint32_t offset = 2 * x;
201  uint32_t hword_data = 0xFF00 | data[offset];
202  if (hword_data != *(uint16_t *)(FLASH_BASE + chip_offset + offset)) {
203  status = FLASH_ProgramHalfWord(FLASH_BASE + chip_offset + offset, hword_data);
204  } else {
205  status = FLASH_COMPLETE;
206  }
207  PIOS_Assert(status == FLASH_COMPLETE);
208  }
209 
210  return 0;
211 }
212 
213 /* Provide a flash driver to external drivers */
215  .start_transaction = PIOS_Flash_Internal_StartTransaction,
216  .end_transaction = PIOS_Flash_Internal_EndTransaction,
217  .erase_sector = PIOS_Flash_Internal_EraseSector,
218  .write_data = PIOS_Flash_Internal_WriteData,
219  .read_data = PIOS_Flash_Internal_ReadData,
220 };
221 
222 #endif /* PIOS_INCLUDE_FLASH_INTERNAL */
223 
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.
bool PIOS_Semaphore_Give(struct pios_semaphore *sema)
Gives binary semaphore.
uint32_t magic
uint32_t offset
Definition: uavtalk_priv.h:51
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