An input/output controller for virtual pinball machines, with plunger position tracking, accelerometer-based nudge sensing, button input encoding, and feedback device control.

Dependencies:   USBDevice mbed FastAnalogIn FastIO FastPWM SimpleDMA

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FreescaleIAP.cpp Source File

FreescaleIAP.cpp

00001 #include "FreescaleIAP.h"
00002  
00003 //#define IAPDEBUG
00004  
00005 enum FCMD {
00006     Read1s = 0x01,
00007     ProgramCheck = 0x02,
00008     ReadResource = 0x03,
00009     ProgramLongword = 0x06,
00010     EraseSector = 0x09,
00011     Read1sBlock = 0x40,
00012     ReadOnce = 0x41,
00013     ProgramOnce = 0x43,
00014     EraseAll = 0x44,
00015     VerifyBackdoor = 0x45
00016 };
00017 
00018 static inline void run_command(FTFA_Type *);
00019 bool check_boundary(int address, unsigned int length);
00020 bool check_align(int address);
00021 IAPCode check_error(void);
00022     
00023 FreescaleIAP::FreescaleIAP()
00024 {
00025 }
00026  
00027 FreescaleIAP::~FreescaleIAP()
00028 {
00029 } 
00030 
00031 // execute an FTFA command
00032 static inline void run_command(FTFA_Type *ftfa) 
00033 {    
00034     // disable interupts
00035     __disable_irq();
00036     
00037     // Clear possible old errors, start command, wait until done
00038     ftfa->FSTAT = FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_RDCOLERR_MASK;
00039     ftfa->FSTAT = FTFA_FSTAT_CCIF_MASK;
00040     while (!(ftfa->FSTAT & FTFA_FSTAT_CCIF_MASK));
00041     
00042     // re-enable interrupts
00043     __enable_irq();
00044 }    
00045 
00046  
00047 IAPCode FreescaleIAP::erase_sector(int address) {
00048     #ifdef IAPDEBUG
00049     printf("IAP: Erasing at %x\r\n", address);
00050     #endif
00051     if (check_align(address))
00052         return AlignError;
00053     
00054     //Setup command
00055     FTFA->FCCOB0 = EraseSector;
00056     FTFA->FCCOB1 = (address >> 16) & 0xFF;
00057     FTFA->FCCOB2 = (address >> 8) & 0xFF;
00058     FTFA->FCCOB3 = address & 0xFF;
00059     
00060     run_command(FTFA);
00061     
00062     return check_error();
00063 }
00064  
00065 IAPCode FreescaleIAP::program_flash(int address, const void *vp, unsigned int length) {
00066     
00067     const char *data = (const char *)vp;
00068     
00069     #ifdef IAPDEBUG
00070     printf("IAP: Programming flash at %x with length %d\r\n", address, length);
00071     #endif
00072     if (check_align(address))
00073         return AlignError;
00074         
00075     IAPCode eraseCheck = verify_erased(address, length);
00076     if (eraseCheck != Success)
00077         return eraseCheck;
00078     
00079     IAPCode progResult;
00080     for (int i = 0; i < length; i+=4) {
00081         progResult = program_word(address + i, data + i);
00082         if (progResult != Success)
00083             return progResult;
00084     }
00085     
00086     return Success;
00087 }
00088  
00089 uint32_t FreescaleIAP::flash_size(void) {
00090     uint32_t retval = (SIM->FCFG2 & 0x7F000000u) >> (24-13);
00091     if (SIM->FCFG2 & (1<<23))           //Possible second flash bank
00092         retval += (SIM->FCFG2 & 0x007F0000u) >> (16-13);
00093     return retval;
00094 }
00095  
00096 IAPCode FreescaleIAP::program_word(int address, const char *data) {
00097     #ifdef IAPDEBUG
00098     printf("IAP: Programming word at %x, %d - %d - %d - %d\r\n", address, data[0], data[1], data[2], data[3]);
00099     #endif
00100     if (check_align(address))
00101         return AlignError;
00102     
00103     //Setup command
00104     FTFA->FCCOB0 = ProgramLongword;
00105     FTFA->FCCOB1 = (address >> 16) & 0xFF;
00106     FTFA->FCCOB2 = (address >> 8) & 0xFF;
00107     FTFA->FCCOB3 = address & 0xFF;
00108     FTFA->FCCOB4 = data[3];
00109     FTFA->FCCOB5 = data[2];
00110     FTFA->FCCOB6 = data[1];
00111     FTFA->FCCOB7 = data[0];
00112     
00113     run_command(FTFA);
00114     
00115     return check_error();
00116 }
00117  
00118 /* Check if no flash boundary is violated
00119    Returns true on violation */
00120 bool check_boundary(int address, unsigned int length) {
00121     int temp = (address+length - 1) / SECTOR_SIZE;
00122     address /= SECTOR_SIZE;
00123     bool retval = (address != temp);
00124     #ifdef IAPDEBUG
00125     if (retval)
00126         printf("IAP: Boundary violation\r\n");
00127     #endif
00128     return retval;
00129 }
00130  
00131 /* Check if address is correctly aligned
00132    Returns true on violation */
00133 bool check_align(int address) {
00134     bool retval = address & 0x03;
00135     #ifdef IAPDEBUG
00136     if (retval)
00137         printf("IAP: Alignment violation\r\n");
00138     #endif
00139     return retval;
00140 }
00141  
00142 /* Check if an area of flash memory is erased
00143    Returns error code or Success (in case of fully erased) */
00144 IAPCode FreescaleIAP::verify_erased(int address, unsigned int length) {
00145     #ifdef IAPDEBUG
00146     printf("IAP: Verify erased at %x with length %d\r\n", address, length);
00147     #endif
00148     
00149     if (check_align(address))
00150         return AlignError;
00151     
00152     //Setup command
00153     FTFA->FCCOB0 = Read1s;
00154     FTFA->FCCOB1 = (address >> 16) & 0xFF;
00155     FTFA->FCCOB2 = (address >> 8) & 0xFF;
00156     FTFA->FCCOB3 = address & 0xFF;
00157     FTFA->FCCOB4 = (length >> 10) & 0xFF;
00158     FTFA->FCCOB5 = (length >> 2) & 0xFF;
00159     FTFA->FCCOB6 = 0;
00160     
00161     run_command(FTFA);
00162     
00163     IAPCode retval = check_error();
00164     if (retval == RuntimeError) {
00165         #ifdef IAPDEBUG
00166         printf("IAP: Flash was not erased\r\n");
00167         #endif
00168         return EraseError;
00169     }
00170     return retval;
00171         
00172 }
00173  
00174 /* Check if an error occured 
00175    Returns error code or Success*/
00176 IAPCode check_error(void) {
00177     if (FTFA->FSTAT & FTFA_FSTAT_FPVIOL_MASK) {
00178         #ifdef IAPDEBUG
00179         printf("IAP: Protection violation\r\n");
00180         #endif
00181         return ProtectionError;
00182     }
00183     if (FTFA->FSTAT & FTFA_FSTAT_ACCERR_MASK) {
00184         #ifdef IAPDEBUG
00185         printf("IAP: Flash access error\r\n");
00186         #endif
00187         return AccessError;
00188     }
00189     if (FTFA->FSTAT & FTFA_FSTAT_RDCOLERR_MASK) {
00190         #ifdef IAPDEBUG
00191         printf("IAP: Collision error\r\n");
00192         #endif
00193         return CollisionError;
00194     }
00195     if (FTFA->FSTAT & FTFA_FSTAT_MGSTAT0_MASK) {
00196         #ifdef IAPDEBUG
00197         printf("IAP: Runtime error\r\n");
00198         #endif
00199         return RuntimeError;
00200     }
00201     #ifdef IAPDEBUG
00202     printf("IAP: No error reported\r\n");
00203     #endif
00204     return Success;
00205 }