00001 /* This file has been prepared for Doxygen automatic documentation generation.*/ 00002 /*! \file avr_flash.c ********************************************************* 00003 * 00004 * \brief 00005 * This file writes/reads to/from flash memory internal to the AVR. 00006 * 00007 * \addtogroup usbstick 00008 * 00009 * \author 00010 * Colin O'Flynn <coflynn@newae.com> 00011 ******************************************************************************/ 00012 /* 00013 Copyright (c) 2008 Colin O'Flynn 00014 All rights reserved. 00015 00016 Redistribution and use in source and binary forms, with or without 00017 modification, are permitted provided that the following conditions are met: 00018 00019 * Redistributions of source code must retain the above copyright 00020 notice, this list of conditions and the following disclaimer. 00021 * Redistributions in binary form must reproduce the above copyright 00022 notice, this list of conditions and the following disclaimer in 00023 the documentation and/or other materials provided with the 00024 distribution. 00025 * Neither the name of the copyright holders nor the names of 00026 contributors may be used to endorse or promote products derived 00027 from this software without specific prior written permission. 00028 00029 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00030 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00031 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00032 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00033 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00034 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00035 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00036 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00037 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00038 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00039 POSSIBILITY OF SUCH DAMAGE. 00040 */ 00041 00042 /** 00043 \addtogroup usbstorage 00044 @{ 00045 */ 00046 00047 //_____ I N C L U D E S ___________________________________________________ 00048 00049 #include "config.h" // system configuration 00050 #include "storage/avr_flash.h" 00051 00052 #include <avr/pgmspace.h> 00053 #include <avr/boot.h> 00054 00055 #ifndef SPM_PAGESIZE 00056 #error SPM_PAGESIZE undefined!!! 00057 #endif 00058 00059 00060 //_____ M A C R O S ________________________________________________________ 00061 //_____ P R I V A T E D E C L A R A T I O N _____________________________ 00062 00063 00064 //_____ D E F I N I T I O N ________________________________________________ 00065 00066 00067 #define MEM_BASE_ADDRESS 0x10000UL 00068 00069 00070 DATA U32 gl_ptr_mem; /* memory data pointer */ 00071 00072 00073 /* Disk management */ 00074 bit reserved_disk_space = FALSE; /* reserved space for application on disk */ 00075 00076 00077 U32 AVRF_DISK_SIZE = 111; /* 57 KB, some room at end saved for bootloader section */ 00078 00079 00080 void avrf_check_init( void ); 00081 00082 00083 //_____ D E C L A R A T I O N ______________________________________________ 00084 00085 //! 00086 //! @brief This function initializes the hw/sw ressources required to drive the AVR Flash 00087 //! 00088 //! @warning Code:?? bytes (function code length) 00089 //! 00090 //!/ 00091 void avrf_mem_init(void) 00092 { 00093 ; 00094 } 00095 00096 00097 //! 00098 //! @brief This function tests the state of the AVR Flash 00099 //! 00100 //! @warning Code:?? bytes (function code length) 00101 //! 00102 //! @return Ctrl_status 00103 //! It is ready -> CTRL_GOOD 00104 //! Else -> CTRL_NO_PRESENT 00105 //!/ 00106 Ctrl_status avrf_test_unit_ready(void) 00107 { 00108 return CTRL_GOOD; 00109 } 00110 00111 00112 //! 00113 //! @brief This function gives the address of the last valid sector. 00114 //! 00115 //! @warning Code:?? bytes (function code length) 00116 //! 00117 //! @param *u32_nb_sector number of sector (sector = 512B). OUT 00118 //! 00119 //! @return Ctrl_status 00120 //! It is ready -> CTRL_GOOD 00121 //!/ 00122 Ctrl_status avrf_read_capacity( U32 *u32_nb_sector ) 00123 { 00124 *u32_nb_sector = AVRF_DISK_SIZE; 00125 return CTRL_GOOD; 00126 } 00127 00128 00129 //! 00130 //! @brief This function returns the write protected status of the memory. 00131 //! 00132 //! Only used by memory removal with a HARDWARE SPECIFIC write protected detection 00133 //! !!! The customer must unplug the memory to change this write protected status, 00134 //! which cannot be for a DF. 00135 //! 00136 //! @warning Code:?? bytes (function code length) 00137 //! 00138 //! @return FALSE -> the memory is not write-protected (always) 00139 //!/ 00140 Bool avrf_wr_protect(void) 00141 { 00142 return FALSE; 00143 } 00144 00145 00146 //! 00147 //! @brief This function tells if the memory has been removed or not. 00148 //! 00149 //! @warning Code:?? bytes (function code length) 00150 //! 00151 //! @return FALSE -> The memory isn't removed 00152 //!/ 00153 Bool avrf_removal(void) 00154 { 00155 return FALSE; 00156 } 00157 00158 00159 00160 //------------ STANDARD FUNCTIONS to read/write the memory -------------------- 00161 00162 //! 00163 //! @brief This function performs a read operation of n sectors from a given address on. 00164 //! (sector = 512B) 00165 //! 00166 //! DATA FLOW is: AVRF => USB 00167 //! 00168 //! 00169 //! @warning Code:?? bytes (function code length) 00170 //! 00171 //! @param addr Sector address to start the read from 00172 //! @param nb_sector Number of sectors to transfer 00173 //! 00174 //! @return Ctrl_status 00175 //! It is ready -> CTRL_GOOD 00176 //! A error occur -> CTRL_FAIL 00177 //! 00178 Ctrl_status avrf_read_10( U32 addr , U16 nb_sector ) 00179 { 00180 avrf_read_open(addr); // wait device is not busy, then send command & address 00181 avrf_read_sector(nb_sector); // transfer data from memory to USB 00182 avrf_read_close(); // unselect memory 00183 return CTRL_GOOD; 00184 } 00185 00186 00187 //! This fonction initialise the memory for a write operation 00188 //! 00189 //! DATA FLOW is: USB => DF 00190 //! 00191 //! 00192 //! (sector = 512B) 00193 //! @param addr Sector address to start write 00194 //! @param nb_sector Number of sectors to transfer 00195 //! 00196 //! @return Ctrl_status 00197 //! It is ready -> CTRL_GOOD 00198 //! A error occur -> CTRL_FAIL 00199 //! 00200 Ctrl_status avrf_write_10( U32 addr , U16 nb_sector ) 00201 { 00202 00203 avrf_write_open(addr); // wait device is not busy, then send command & address 00204 avrf_write_sector(nb_sector); // transfer data from memory to USB 00205 avrf_write_close(); // unselect memory 00206 return CTRL_GOOD; 00207 } 00208 00209 00210 //------------ AVR FLASH LOWER LEVEL ROUTIENS ----------------------------------------- 00211 00212 //! 00213 //! @brief This function opens a DF memory in read mode at a given sector address. 00214 //! 00215 //! NOTE: Address may not be synchronized on the beginning of a page (depending on the DF page size). 00216 //! 00217 //! @warning Code:?? bytes (function code length) 00218 //! 00219 //! @param pos Logical sector address 00220 //! 00221 //! @return bit 00222 //! The open succeeded -> OK 00223 //!/ 00224 bit avrf_read_open (Uint32 pos) 00225 { 00226 // Set the global memory ptr at a Byte address. 00227 gl_ptr_mem = (pos * 512) + MEM_BASE_ADDRESS; 00228 00229 return OK; 00230 } 00231 00232 00233 //! 00234 //! @brief This function unselects the current DF memory. 00235 //! 00236 //! @warning Code:?? bytes (function code length) 00237 //! 00238 //!/ 00239 void avrf_read_close (void) 00240 { 00241 ; 00242 } 00243 00244 00245 00246 //! 00247 //! @brief This function is optimized and writes nb-sector * 512 Bytes from 00248 //! DataFlash memory to USB controller 00249 //! 00250 //! DATA FLOW is: DF => USB 00251 //! 00252 //! 00253 //! NOTE: 00254 //! - First call must be preceded by a call to the df_read_open() function, 00255 //! - The USB EPIN must have been previously selected, 00256 //! - USB ping-pong buffers are free, 00257 //! - As 512 is always a sub-multiple of page size, there is no need to check 00258 //! page end for each Bytes, 00259 //! - Interrupts are disabled during transfer to avoid timer interrupt, 00260 //! - nb_sector always >= 1, cannot be zero. 00261 //! 00262 //! @warning code:?? bytes (function code length) 00263 //! 00264 //! @param nb_sector number of contiguous sectors to read [IN] 00265 //! 00266 //! @return bit 00267 //! The read succeeded -> OK 00268 //!/ 00269 bit avrf_read_sector (Uint16 nb_sector) 00270 { 00271 U8 i,j; 00272 do 00273 { 00274 for (i = 8; i != 0; i--) 00275 { 00276 Disable_interrupt(); // Global disable. 00277 00278 for (j = 0; j < 64; j++) { 00279 Usb_write_byte(pgm_read_byte_far(gl_ptr_mem++)); 00280 } 00281 00282 00283 //# Send the USB FIFO IN content to the USB Host. 00284 Usb_send_in(); // Send the FIFO IN content to the USB Host. 00285 00286 Enable_interrupt(); // Global interrupt re-enable. 00287 00288 // Wait until the tx is done so that we may write to the FIFO IN again. 00289 while(Is_usb_write_enabled()==FALSE); 00290 } 00291 nb_sector--; // 1 more sector read 00292 } 00293 while (nb_sector != 0); 00294 00295 return OK; // Read done. 00296 } 00297 00298 00299 //! 00300 //! @brief This function opens a DF memory in write mode at a given sector 00301 //! address. 00302 //! 00303 //! NOTE: If page buffer > 512 bytes, page content is first loaded in buffer to 00304 //! be partially updated by write_byte or write64 functions. 00305 //! 00306 //! @warning Code:?? bytes (function code length) 00307 //! 00308 //! @param pos Sector address 00309 //! 00310 //! @return bit 00311 //! The open succeeded -> OK 00312 //!/ 00313 bit avrf_write_open (Uint32 pos) 00314 { 00315 // Set the global memory ptr at a Byte address. 00316 gl_ptr_mem = (pos * 512) + MEM_BASE_ADDRESS; 00317 00318 return OK; 00319 } 00320 00321 00322 //! 00323 //! @brief This function fills the end of the logical sector (512B) and launch 00324 //! page programming. 00325 //! 00326 //! @warning Code:?? bytes (function code length) 00327 //! 00328 //!/ 00329 void avrf_write_close (void) 00330 { 00331 ; 00332 } 00333 00334 00335 00336 /* This code can be setup to work with the DFU bootloader, which comes with the AT90USB1287. However I haven't 00337 had time to test it with such */ 00338 #define LAST_BOOT_ENTRY 0xFFFE 00339 00340 00341 void dfuclone_boot_buffer_write(uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word); 00342 void dfuclone_boot_page_erase(uint32_t dummy1, uint16_t dummy2, uint32_t address); 00343 void dfuclone_boot_page_write(uint32_t dummy1, uint16_t dummy2, uint32_t address); 00344 00345 00346 /* Enable the use of the AVR DFU bootloader by defining "USE_AVRDFU_BOOTLOADER", it will 00347 then call the low-level routines already in the bootloader. */ 00348 #ifdef USE_AVRDFU_BOOTLOADER 00349 00350 #error UNTESTED/UNSUPPORTED AT THIS TIME 00351 00352 // These functions pointers are used to call functions entry points in bootloader 00353 void (*dfu_boot_buffer_write) (uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word)= 00354 (void (*)(uint16_t, uint32_t, uint16_t, uint16_t))(LAST_BOOT_ENTRY-6); 00355 00356 void (*dfu_boot_page_write) (uint32_t dummy1, uint16_t dummy2, uint32_t address)= 00357 (void (*)(uint32_t, uint16_t, uint32_t))(LAST_BOOT_ENTRY-4); 00358 00359 void (*dfu_boot_page_erase) (uint32_t dummy1, uint16_t dummy2, uint32_t address)= 00360 (void (*)(uint32_t, uint16_t, uint32_t))(LAST_BOOT_ENTRY-2); 00361 00362 #else 00363 00364 // These functions pointers are used to call functions entry points in bootloader 00365 void (*dfu_boot_buffer_write) (uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word)= 00366 dfuclone_boot_buffer_write; 00367 00368 void (*dfu_boot_page_write) (uint32_t dummy1, uint16_t dummy2, uint32_t address)= 00369 dfuclone_boot_page_write; 00370 00371 void (*dfu_boot_page_erase) (uint32_t dummy1, uint16_t dummy2, uint32_t address)= 00372 dfuclone_boot_page_erase; 00373 00374 00375 00376 #endif 00377 00378 //! 00379 //! @brief This function is optimized and writes nb-sector * 512 Bytes from 00380 //! USB controller to DataFlash memory 00381 //! 00382 //! DATA FLOW is: USB => DF 00383 //! 00384 //! 00385 //! NOTE: 00386 //! - First call must be preceded by a call to the df_write_open() function, 00387 //! - As 512 is always a sub-multiple of page size, there is no need to check 00388 //! page end for each Bytes, 00389 //! - The USB EPOUT must have been previously selected, 00390 //! - Interrupts are disabled during transfer to avoid timer interrupt, 00391 //! - nb_sector always >= 1, cannot be zero. 00392 //! 00393 //! @warning code:?? bytes (function code length) 00394 //! 00395 //! @param nb_sector number of contiguous sectors to write [IN] 00396 //! 00397 //! @return bit 00398 //! The write succeeded -> OK 00399 //!/ 00400 bit avrf_write_sector (Uint16 nb_sector) 00401 { 00402 Byte i, j; 00403 U16 w; 00404 00405 U16 pgindex = 0; 00406 U16 sector_bytecounter = 0; 00407 00408 00409 do 00410 { 00411 //# Write 8x64b = 512b from the USB FIFO OUT. 00412 for (i = 8; i != 0; i--) 00413 { 00414 // Wait end of rx in USB EPOUT. 00415 while(Is_usb_read_enabled()==FALSE); 00416 00417 Disable_interrupt(); // Global disable. 00418 00419 //If start of page, erase it! 00420 if (pgindex == 0) { 00421 (*dfu_boot_page_erase)(0, 0, gl_ptr_mem); 00422 } 00423 00424 //For all the data in the endpoint, write to flash temp page 00425 for (j = 0; j < 32; j++) { 00426 w = Usb_read_byte(); 00427 w += Usb_read_byte() << 8; 00428 (*dfu_boot_buffer_write)(0, gl_ptr_mem, pgindex, w); 00429 pgindex += 2; 00430 } 00431 00432 Usb_ack_receive_out(); // USB EPOUT read acknowledgement. 00433 00434 //If we have filled flash page, write that sucker to memory 00435 if (pgindex == SPM_PAGESIZE) { 00436 00437 (*dfu_boot_page_write)(0,0, gl_ptr_mem); 00438 00439 Enable_interrupt(); // Global enable again 00440 00441 gl_ptr_mem += SPM_PAGESIZE; // Update the memory pointer. 00442 pgindex = 0; 00443 00444 sector_bytecounter += SPM_PAGESIZE; 00445 00446 if(sector_bytecounter == 512) { 00447 nb_sector--; // 1 more sector written 00448 sector_bytecounter = 0; 00449 } 00450 00451 } 00452 00453 } // for (i = 8; i != 0; i--) 00454 00455 } 00456 while (nb_sector != 0); 00457 00458 return OK; // Write done 00459 } 00460 00461 00462 #ifndef USE_AVRDFU_BOOTLOADER 00463 /* Perform read/write of FLASH, using same calling convention as low-level routines in AVR DFU bootloader */ 00464 00465 BOOTLOADER_SECTION void dfuclone_boot_buffer_write(uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word) 00466 { 00467 boot_page_fill(baseaddr + pageaddr, word); 00468 return; 00469 } 00470 00471 00472 BOOTLOADER_SECTION void dfuclone_boot_page_erase(uint32_t dummy1, uint16_t dummy2, uint32_t address) 00473 { 00474 boot_page_erase(address); 00475 boot_spm_busy_wait(); 00476 boot_rww_enable(); 00477 return; 00478 } 00479 00480 BOOTLOADER_SECTION void dfuclone_boot_page_write(uint32_t dummy1, uint16_t dummy2, uint32_t address) 00481 { 00482 boot_page_write(address); 00483 boot_spm_busy_wait(); 00484 boot_rww_enable(); 00485 return; 00486 } 00487 #endif //USE_AVRDFU_BOOTLOADER 00488 00489 //------------ SPECIFIC FONCTION USB TRANSFER ----------------------------------------- 00490 00491 //** If your device transfer have a specific transfer for USB (Particularity of Chejudo product, or bootloader) 00492 // !!! In this case the driver must be know the USB access 00493 00494 //! This fonction transfer the memory data (programed in scsi_read_10) directly to the usb interface 00495 //! 00496 //! @return Ctrl_status 00497 //! It is ready -> CTRL_GOOD 00498 //! 00499 Ctrl_status avrf_usb_read() 00500 { 00501 return CTRL_GOOD; 00502 } 00503 00504 00505 //! This fonction transfer the usb data (programed in scsi_write_10) directly to the memory data 00506 //! 00507 //! @return Ctrl_status 00508 //! It is ready -> CTRL_GOOD 00509 //! 00510 Ctrl_status avrf_usb_write( void ) 00511 { 00512 return CTRL_GOOD; 00513 } 00514 00515 /** @} */