EVE 1.0
cfs-coffee-arch.c
1 /***********************************************************************
2  * File name: cfs-coffee-arch.c
3  * EVE-specific coffee FS HAL and extensions.
4  *
5  * Author: DT, Jetro AS
6  ***********************************************************************/
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <stddef.h>
10 #include <string.h>
11 #include <core/mwork.h>
12 #include <lib/env.h>
13 #include <lib/assert.h>
14 #include <cfs/cfs.h>
15 #include <cfs/cfs-coffee.h>
16 #include <cfs-coffee-arch.h>
17 #include <dev/resources.h>
18 
19 /**********************************************************************
20  * Macro
21  **********************************************************************/
22 /* Disable debug spam from the module */
23 #ifndef NDEBUG
24  #define NDEBUG
25 #endif
26 
27 /** The macro provides debug print functionality */
28 #ifdef NDEBUG
29  #define PRINTD(FORMAT, args...) do {} while (0)
30 #else
31  #define PRINTD(FORMAT, args...) printf(FORMAT, ##args)
32 #endif
33 
34 #define COFFEE_PAGE_MASK (COFFEE_PAGE_SIZE - 1)
35 
36 /**********************************************************************
37  * Local types
38  **********************************************************************/
39 struct coffee_async_format_state_t
40 {
41  struct mwork_t work;
42  uint16_t sector;
43 };
44 
45 
46 /**********************************************************************
47  * Prototypes
48  **********************************************************************/
49 void coffee_async_format_callback(struct mwork_t *work);
50 
51 /**********************************************************************
52  * Variables
53  **********************************************************************/
54 
55 static struct coffee_async_format_state_t coffee_async_format_state =
56 {
57  .work = MWORK_INIT(coffee_async_format_state.work, coffee_async_format_callback),
58 };
59 
60 /***********************************************************************
61  Local constants
62 ***********************************************************************/
63 
64 static inline void negate_buffer(void *data, int32_t chunk)
65 {
66  uint32_t addr = (uint32_t) data;
67  uint32_t *p = (uint32_t *) (addr & ~0x03);
68  uint32_t ms = 0xFFFFFFFF << ((addr & 0x03) << 3);
69  chunk += addr & 0x03;
70  uint32_t fs = 0xFFFFFFFF >> ((0x04 - (chunk & 0x03)) << 3);
71  chunk >>= 2;
72  uint32_t i;
73 
74  if (chunk)
75  {
76  p[0] ^= ms;
77  p[chunk] ^= fs;
78  for (i = 1; i < chunk; ++i)
79  p[i] ^= 0xFFFFFFFF;
80  }
81  else
82  {
83  p[0] ^= (ms & fs);
84  }
85 }
86 
87 /***********************************************************************
88  * Name: flash_read
89  **********************************************************************/
90 void flash_read(uint32_t address, void *data, uint32_t length)
91 {
92  char *p = data;
93  uint32_t next;
94  uint32_t chunk;
95 
96  while (length)
97  {
98  next = (address | COFFEE_PAGE_MASK) + 1;
99  chunk = next - address;
100  if (chunk > length)
101  chunk = length;
102 
103  SpiMemoryRead(&ExtFlash, p, address, chunk);
104  negate_buffer(p, chunk);
105 
106  address = next;
107  length -= chunk;
108  p += chunk;
109  }
110 }
111 
112 /***********************************************************************
113  * Name: flash_write
114  **********************************************************************/
115 void flash_write(uint32_t address, const void *data, uint32_t length)
116 {
117  const char *p = data;
118  uint32_t next;
119  uint32_t chunk;
120 
121  assert(length == 0 || ((uint32_t) data & 0x20000000) != 0);
122 
123  while (length)
124  {
125  next = (address | COFFEE_PAGE_MASK) + 1;
126  chunk = next - address;
127  if (chunk > length)
128  chunk = length;
129 
130  negate_buffer((void *) p, chunk);
131  SpiMemoryWrite(&ExtFlash, address, p, chunk);
132  negate_buffer((void *) p, chunk);
133 
134  address = next;
135  length -= chunk;
136  p += chunk;
137  }
138 }
139 
140 /***********************************************************************
141  * Name: coffee_async_format
142  **********************************************************************/
143 enum coffee_async_format_status_t coffee_async_format_status(void)
144 {
145  if (mwork_pending(&coffee_async_format_state.work))
146  return COFFEE_ASYNC_FORMAT_ONGOING;
147  else
148  return COFFEE_ASYNC_FORMAT_IDLE;
149 }
150 
151 /***********************************************************************
152  * Name: coffee_async_format
153  **********************************************************************/
154 void coffee_async_format(void)
155 {
156  unsigned size;
157  void *mem = cfs_coffee_get_protected_mem(&size);
158 
159  swint_state_t swint = swint_disable();
160  if (mwork_pending(&coffee_async_format_state.work))
161  mwork_cancel(&coffee_async_format_state.work);
162  else
163  RequestExtFlash();
164  memset(mem, 0, size);
165  coffee_async_format_state.work.at = mwork_now();
166  coffee_async_format_state.sector = 0;
167  mwork_schedule(&coffee_async_format_state.work);
168  swint_enable(swint);
169 }
170 
171 /***********************************************************************
172  * Name: coffee_async_format
173  **********************************************************************/
174 void coffee_async_format_cancel(void)
175 {
176  swint_state_t swint = swint_disable();
177  if (mwork_pending(&coffee_async_format_state.work))
178  {
179  mwork_cancel(&coffee_async_format_state.work);
180  ReleaseExtFlash();
181  }
182  swint_enable(swint);
183 }
184 
185 /***********************************************************************
186  * Local functions
187  **********************************************************************/
188 void coffee_async_format_callback(struct mwork_t *work)
189 {
190  struct coffee_async_format_state_t *state =
191  container_of(work, struct coffee_async_format_state_t, work);
192 
193  if (SpiIsBusy(ExtFlash.Spi))
194  {
195  PRINTD("⋅");
196 reschedule_default:
197  state->work.at += MS_TO_TICKS(30);
198 reschedule:
199  mwork_schedule(&state->work);
200  return;
201  }
202 
203  if (SpiMemoryIsBusy(&ExtFlash))
204  {
205  PRINTD("$");
206  state->work.at += MS_TO_TICKS(100);
207  goto reschedule;
208  }
209 
210  if (state->sector >= COFFEE_SIZE / COFFEE_SECTOR_SIZE)
211  {
212  ReleaseExtFlash();
213  PRINTD("Ж");
214  return;
215  }
216 
217  PRINTD("*");
218  if (!SpiMemoryEraseBlockAsync(&ExtFlash, COFFEE_START_SECTOR + state->sector))
219  {
220  PRINTD("¤");
221  goto reschedule_default;
222  }
223 
224  state->sector++;
225  state->work.at += MS_TO_TICKS(300);
226  mwork_schedule(&state->work);
227 }
Header file for the EVE millisecond-scale work scheduling.
Resource manager.
bool SpiMemoryIsBusy(const struct spi_memory_t *Memory)
Name: SpiMemoryIsBusy Checks if the memory write or erase operation is in progress Called from main p...
struct work_t work
Definition: mwork.h:183
const struct spi_t * Spi
Definition: spi-memory.h:88
#define PRINTD(FORMAT, args...)
Definition: uip.c:100
Definition: mwork.h:182
#define container_of(ptr, type, mem)
Definition: env.h:114
bool SpiMemoryEraseBlockAsync(const struct spi_memory_t *Memory, uint32_t BlockIndex)
Name: SpiMemoryEraseBlockAsync Begines erasing given block in SPI memory. Called from main program le...
bool SpiMemoryWrite(const struct spi_memory_t *Memory, uint32_t DstAddress, const void *SrcBuffer, uint32_t ByteCount)
Name: SpiMemoryWrite Writes bytes from SrcBuffer to SPI memory. It the SPI memory is page based...
static mwork_time_t mwork_now()
Definition: mwork.h:200
static bool SpiIsBusy(const struct spi_t *Spi)
Name: SpiIsBusy WARNING: SpiCsEnable() must be called prior to this function. Testes if transmitter i...
Definition: spi.h:296
EVE build environment.
#define MWORK_INIT(x, callback)
Definition: mwork.h:115
static bool mwork_pending(struct mwork_t *work)
Definition: mwork.h:249
uint8_t data[USBNET_RX_BUF_SIZE]
Definition: usbnet.h:140
void mwork_schedule(struct mwork_t *work)
void swint_enable(swint_state_t state)
bool SpiMemoryRead(const struct spi_memory_t *Memory, void *DstBuffer, uint32_t SrcAddress, uint32_t ByteCount)
Name: SpiMemoryRead Reads bytes from SPI memory to DstBuffer. Called from main program level...
swint_state_t swint_disable(void)
void * cfs_coffee_get_protected_mem(unsigned *size)
Points out a memory region that may not be altered during checkpointing operations that use the file ...
Definition: cfs-coffee.c:1443
void mwork_cancel(struct mwork_t *work)