Contiki 2.5
avr_flash.c
Go to the documentation of this file.
1 /* This file has been prepared for Doxygen automatic documentation generation.*/
2 /*! \file avr_flash.c *********************************************************
3  *
4  * \brief
5  * This file writes/reads to/from flash memory internal to the AVR.
6  *
7  * \addtogroup usbstick
8  *
9  * \author
10  * Colin O'Flynn <coflynn@newae.com>
11  ******************************************************************************/
12 /*
13  Copyright (c) 2008 Colin O'Flynn
14  All rights reserved.
15 
16  Redistribution and use in source and binary forms, with or without
17  modification, are permitted provided that the following conditions are met:
18 
19  * Redistributions of source code must retain the above copyright
20  notice, this list of conditions and the following disclaimer.
21  * Redistributions in binary form must reproduce the above copyright
22  notice, this list of conditions and the following disclaimer in
23  the documentation and/or other materials provided with the
24  distribution.
25  * Neither the name of the copyright holders nor the names of
26  contributors may be used to endorse or promote products derived
27  from this software without specific prior written permission.
28 
29  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39  POSSIBILITY OF SUCH DAMAGE.
40 */
41 
42 /**
43  \addtogroup usbstorage
44  @{
45 */
46 
47 //_____ I N C L U D E S ___________________________________________________
48 
49 #include "config.h" // system configuration
50 #include "storage/avr_flash.h"
51 
52 #include <avr/pgmspace.h>
53 #include <avr/boot.h>
54 
55 #ifndef SPM_PAGESIZE
56 #error SPM_PAGESIZE undefined!!!
57 #endif
58 
59 
60 //_____ M A C R O S ________________________________________________________
61 //_____ P R I V A T E D E C L A R A T I O N _____________________________
62 
63 
64 //_____ D E F I N I T I O N ________________________________________________
65 
66 
67 #define MEM_BASE_ADDRESS 0x10000UL
68 
69 
70 DATA U32 gl_ptr_mem; /* memory data pointer */
71 
72 
73 /* Disk management */
74 bit reserved_disk_space = FALSE; /* reserved space for application on disk */
75 
76 
77 U32 AVRF_DISK_SIZE = 111; /* 57 KB, some room at end saved for bootloader section */
78 
79 
80 void avrf_check_init( void );
81 
82 
83 //_____ D E C L A R A T I O N ______________________________________________
84 
85 //!
86 //! @brief This function initializes the hw/sw ressources required to drive the AVR Flash
87 //!
88 //! @warning Code:?? bytes (function code length)
89 //!
90 //!/
91 void avrf_mem_init(void)
92 {
93  ;
94 }
95 
96 
97 //!
98 //! @brief This function tests the state of the AVR Flash
99 //!
100 //! @warning Code:?? bytes (function code length)
101 //!
102 //! @return Ctrl_status
103 //! It is ready -> CTRL_GOOD
104 //! Else -> CTRL_NO_PRESENT
105 //!/
107 {
108  return CTRL_GOOD;
109 }
110 
111 
112 //!
113 //! @brief This function gives the address of the last valid sector.
114 //!
115 //! @warning Code:?? bytes (function code length)
116 //!
117 //! @param *u32_nb_sector number of sector (sector = 512B). OUT
118 //!
119 //! @return Ctrl_status
120 //! It is ready -> CTRL_GOOD
121 //!/
122 Ctrl_status avrf_read_capacity( U32 *u32_nb_sector )
123 {
124  *u32_nb_sector = AVRF_DISK_SIZE;
125  return CTRL_GOOD;
126 }
127 
128 
129 //!
130 //! @brief This function returns the write protected status of the memory.
131 //!
132 //! Only used by memory removal with a HARDWARE SPECIFIC write protected detection
133 //! !!! The customer must unplug the memory to change this write protected status,
134 //! which cannot be for a DF.
135 //!
136 //! @warning Code:?? bytes (function code length)
137 //!
138 //! @return FALSE -> the memory is not write-protected (always)
139 //!/
140 Bool avrf_wr_protect(void)
141 {
142  return FALSE;
143 }
144 
145 
146 //!
147 //! @brief This function tells if the memory has been removed or not.
148 //!
149 //! @warning Code:?? bytes (function code length)
150 //!
151 //! @return FALSE -> The memory isn't removed
152 //!/
153 Bool avrf_removal(void)
154 {
155  return FALSE;
156 }
157 
158 
159 
160 //------------ STANDARD FUNCTIONS to read/write the memory --------------------
161 
162 //!
163 //! @brief This function performs a read operation of n sectors from a given address on.
164 //! (sector = 512B)
165 //!
166 //! DATA FLOW is: AVRF => USB
167 //!
168 //!
169 //! @warning Code:?? bytes (function code length)
170 //!
171 //! @param addr Sector address to start the read from
172 //! @param nb_sector Number of sectors to transfer
173 //!
174 //! @return Ctrl_status
175 //! It is ready -> CTRL_GOOD
176 //! A error occur -> CTRL_FAIL
177 //!
178 Ctrl_status avrf_read_10( U32 addr , U16 nb_sector )
179 {
180  avrf_read_open(addr); // wait device is not busy, then send command & address
181  avrf_read_sector(nb_sector); // transfer data from memory to USB
182  avrf_read_close(); // unselect memory
183  return CTRL_GOOD;
184 }
185 
186 
187 //! This fonction initialise the memory for a write operation
188 //!
189 //! DATA FLOW is: USB => DF
190 //!
191 //!
192 //! (sector = 512B)
193 //! @param addr Sector address to start write
194 //! @param nb_sector Number of sectors to transfer
195 //!
196 //! @return Ctrl_status
197 //! It is ready -> CTRL_GOOD
198 //! A error occur -> CTRL_FAIL
199 //!
200 Ctrl_status avrf_write_10( U32 addr , U16 nb_sector )
201 {
202 
203  avrf_write_open(addr); // wait device is not busy, then send command & address
204  avrf_write_sector(nb_sector); // transfer data from memory to USB
205  avrf_write_close(); // unselect memory
206  return CTRL_GOOD;
207 }
208 
209 
210 //------------ AVR FLASH LOWER LEVEL ROUTIENS -----------------------------------------
211 
212 //!
213 //! @brief This function opens a DF memory in read mode at a given sector address.
214 //!
215 //! NOTE: Address may not be synchronized on the beginning of a page (depending on the DF page size).
216 //!
217 //! @warning Code:?? bytes (function code length)
218 //!
219 //! @param pos Logical sector address
220 //!
221 //! @return bit
222 //! The open succeeded -> OK
223 //!/
224 bit avrf_read_open (Uint32 pos)
225 {
226  // Set the global memory ptr at a Byte address.
227  gl_ptr_mem = (pos * 512) + MEM_BASE_ADDRESS;
228 
229  return OK;
230 }
231 
232 
233 //!
234 //! @brief This function unselects the current DF memory.
235 //!
236 //! @warning Code:?? bytes (function code length)
237 //!
238 //!/
239 void avrf_read_close (void)
240 {
241  ;
242 }
243 
244 
245 
246 //!
247 //! @brief This function is optimized and writes nb-sector * 512 Bytes from
248 //! DataFlash memory to USB controller
249 //!
250 //! DATA FLOW is: DF => USB
251 //!
252 //!
253 //! NOTE:
254 //! - First call must be preceded by a call to the df_read_open() function,
255 //! - The USB EPIN must have been previously selected,
256 //! - USB ping-pong buffers are free,
257 //! - As 512 is always a sub-multiple of page size, there is no need to check
258 //! page end for each Bytes,
259 //! - Interrupts are disabled during transfer to avoid timer interrupt,
260 //! - nb_sector always >= 1, cannot be zero.
261 //!
262 //! @warning code:?? bytes (function code length)
263 //!
264 //! @param nb_sector number of contiguous sectors to read [IN]
265 //!
266 //! @return bit
267 //! The read succeeded -> OK
268 //!/
269 bit avrf_read_sector (Uint16 nb_sector)
270 {
271  U8 i,j;
272  do
273  {
274  for (i = 8; i != 0; i--)
275  {
276  Disable_interrupt(); // Global disable.
277 
278  for (j = 0; j < 64; j++) {
279  Usb_write_byte(pgm_read_byte_far(gl_ptr_mem++));
280  }
281 
282 
283  //# Send the USB FIFO IN content to the USB Host.
284  Usb_send_in(); // Send the FIFO IN content to the USB Host.
285 
286  Enable_interrupt(); // Global interrupt re-enable.
287 
288  // Wait until the tx is done so that we may write to the FIFO IN again.
289  while(Is_usb_write_enabled()==FALSE);
290  }
291  nb_sector--; // 1 more sector read
292  }
293  while (nb_sector != 0);
294 
295  return OK; // Read done.
296 }
297 
298 
299 //!
300 //! @brief This function opens a DF memory in write mode at a given sector
301 //! address.
302 //!
303 //! NOTE: If page buffer > 512 bytes, page content is first loaded in buffer to
304 //! be partially updated by write_byte or write64 functions.
305 //!
306 //! @warning Code:?? bytes (function code length)
307 //!
308 //! @param pos Sector address
309 //!
310 //! @return bit
311 //! The open succeeded -> OK
312 //!/
313 bit avrf_write_open (Uint32 pos)
314 {
315  // Set the global memory ptr at a Byte address.
316  gl_ptr_mem = (pos * 512) + MEM_BASE_ADDRESS;
317 
318  return OK;
319 }
320 
321 
322 //!
323 //! @brief This function fills the end of the logical sector (512B) and launch
324 //! page programming.
325 //!
326 //! @warning Code:?? bytes (function code length)
327 //!
328 //!/
329 void avrf_write_close (void)
330 {
331  ;
332 }
333 
334 
335 
336 /* This code can be setup to work with the DFU bootloader, which comes with the AT90USB1287. However I haven't
337  had time to test it with such */
338 #define LAST_BOOT_ENTRY 0xFFFE
339 
340 
341 void dfuclone_boot_buffer_write(uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word);
342 void dfuclone_boot_page_erase(uint32_t dummy1, uint16_t dummy2, uint32_t address);
343 void dfuclone_boot_page_write(uint32_t dummy1, uint16_t dummy2, uint32_t address);
344 
345 
346 /* Enable the use of the AVR DFU bootloader by defining "USE_AVRDFU_BOOTLOADER", it will
347 then call the low-level routines already in the bootloader. */
348 #ifdef USE_AVRDFU_BOOTLOADER
349 
350 #error UNTESTED/UNSUPPORTED AT THIS TIME
351 
352 // These functions pointers are used to call functions entry points in bootloader
353 void (*dfu_boot_buffer_write) (uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word)=
354  (void (*)(uint16_t, uint32_t, uint16_t, uint16_t))(LAST_BOOT_ENTRY-6);
355 
356 void (*dfu_boot_page_write) (uint32_t dummy1, uint16_t dummy2, uint32_t address)=
357  (void (*)(uint32_t, uint16_t, uint32_t))(LAST_BOOT_ENTRY-4);
358 
359 void (*dfu_boot_page_erase) (uint32_t dummy1, uint16_t dummy2, uint32_t address)=
360  (void (*)(uint32_t, uint16_t, uint32_t))(LAST_BOOT_ENTRY-2);
361 
362 #else
363 
364 // These functions pointers are used to call functions entry points in bootloader
365 void (*dfu_boot_buffer_write) (uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word)=
366  dfuclone_boot_buffer_write;
367 
368 void (*dfu_boot_page_write) (uint32_t dummy1, uint16_t dummy2, uint32_t address)=
369  dfuclone_boot_page_write;
370 
371 void (*dfu_boot_page_erase) (uint32_t dummy1, uint16_t dummy2, uint32_t address)=
372  dfuclone_boot_page_erase;
373 
374 
375 
376 #endif
377 
378 //!
379 //! @brief This function is optimized and writes nb-sector * 512 Bytes from
380 //! USB controller to DataFlash memory
381 //!
382 //! DATA FLOW is: USB => DF
383 //!
384 //!
385 //! NOTE:
386 //! - First call must be preceded by a call to the df_write_open() function,
387 //! - As 512 is always a sub-multiple of page size, there is no need to check
388 //! page end for each Bytes,
389 //! - The USB EPOUT must have been previously selected,
390 //! - Interrupts are disabled during transfer to avoid timer interrupt,
391 //! - nb_sector always >= 1, cannot be zero.
392 //!
393 //! @warning code:?? bytes (function code length)
394 //!
395 //! @param nb_sector number of contiguous sectors to write [IN]
396 //!
397 //! @return bit
398 //! The write succeeded -> OK
399 //!/
400 bit avrf_write_sector (Uint16 nb_sector)
401 {
402  Byte i, j;
403  U16 w;
404 
405  U16 pgindex = 0;
406  U16 sector_bytecounter = 0;
407 
408 
409  do
410  {
411  //# Write 8x64b = 512b from the USB FIFO OUT.
412  for (i = 8; i != 0; i--)
413  {
414  // Wait end of rx in USB EPOUT.
415  while(Is_usb_read_enabled()==FALSE);
416 
417  Disable_interrupt(); // Global disable.
418 
419  //If start of page, erase it!
420  if (pgindex == 0) {
421  (*dfu_boot_page_erase)(0, 0, gl_ptr_mem);
422  }
423 
424  //For all the data in the endpoint, write to flash temp page
425  for (j = 0; j < 32; j++) {
426  w = Usb_read_byte();
427  w += Usb_read_byte() << 8;
428  (*dfu_boot_buffer_write)(0, gl_ptr_mem, pgindex, w);
429  pgindex += 2;
430  }
431 
432  Usb_ack_receive_out(); // USB EPOUT read acknowledgement.
433 
434  //If we have filled flash page, write that sucker to memory
435  if (pgindex == SPM_PAGESIZE) {
436 
437  (*dfu_boot_page_write)(0,0, gl_ptr_mem);
438 
439  Enable_interrupt(); // Global enable again
440 
441  gl_ptr_mem += SPM_PAGESIZE; // Update the memory pointer.
442  pgindex = 0;
443 
444  sector_bytecounter += SPM_PAGESIZE;
445 
446  if(sector_bytecounter == 512) {
447  nb_sector--; // 1 more sector written
448  sector_bytecounter = 0;
449  }
450 
451  }
452 
453  } // for (i = 8; i != 0; i--)
454 
455  }
456  while (nb_sector != 0);
457 
458  return OK; // Write done
459 }
460 
461 
462 #ifndef USE_AVRDFU_BOOTLOADER
463 /* Perform read/write of FLASH, using same calling convention as low-level routines in AVR DFU bootloader */
464 
465 BOOTLOADER_SECTION void dfuclone_boot_buffer_write(uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word)
466 {
467  boot_page_fill(baseaddr + pageaddr, word);
468  return;
469 }
470 
471 
472 BOOTLOADER_SECTION void dfuclone_boot_page_erase(uint32_t dummy1, uint16_t dummy2, uint32_t address)
473 {
474  boot_page_erase(address);
475  boot_spm_busy_wait();
476  boot_rww_enable();
477  return;
478 }
479 
480 BOOTLOADER_SECTION void dfuclone_boot_page_write(uint32_t dummy1, uint16_t dummy2, uint32_t address)
481 {
482  boot_page_write(address);
483  boot_spm_busy_wait();
484  boot_rww_enable();
485  return;
486 }
487 #endif //USE_AVRDFU_BOOTLOADER
488 
489 //------------ SPECIFIC FONCTION USB TRANSFER -----------------------------------------
490 
491 //** If your device transfer have a specific transfer for USB (Particularity of Chejudo product, or bootloader)
492 // !!! In this case the driver must be know the USB access
493 
494 //! This fonction transfer the memory data (programed in scsi_read_10) directly to the usb interface
495 //!
496 //! @return Ctrl_status
497 //! It is ready -> CTRL_GOOD
498 //!
500 {
501  return CTRL_GOOD;
502 }
503 
504 
505 //! This fonction transfer the usb data (programed in scsi_write_10) directly to the memory data
506 //!
507 //! @return Ctrl_status
508 //! It is ready -> CTRL_GOOD
509 //!
511 {
512  return CTRL_GOOD;
513 }
514 
515 /** @} */