Contiki 2.6

avr_flash.c

Go to the documentation of this file.
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 /** @} */