Electric Locomotive control system. Touch screen driver control, includes regenerative braking, drives 4 brushless motors, displays speed MPH, system volts and power

Dependencies:   BSP_DISCO_F746NG FastPWM LCD_DISCO_F746NG SD_DISCO_F746NG TS_DISCO_F746NG mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sd_card.cpp Source File

sd_card.cpp

00001 #include "mbed.h"
00002 #include "Electric_Loco.h"
00003 #include "SD_DISCO_F746NG.h"
00004 /*
00005 SD card used only to keep log of total distance travelled.
00006 Odometer is trivial.
00007 This file treats SD card as random access memory.
00008 A better implementation would use library functions for FAT file system etc.
00009 
00010 May revisit this.
00011 
00012 */
00013 SD_DISCO_F746NG     sd;
00014 extern  Serial pc;
00015 extern  uint32_t    historic_distance;
00016 extern  uint32_t    get_pulse_total ()  ;
00017 
00018 static  const   int
00019     SD_BLOCKSIZE        = 512;   /* SD card data Block Size in Bytes      */
00020 //  Assume SD card size is 4Gbyte, might be 8 Gbyte
00021 //  Then can use 8388608 blocks (8 * 1024 * 1024)
00022 
00023 uint64_t    SD_blockptr = 0;
00024 uint32_t    SDBuffer[(SD_BLOCKSIZE >> 2)];   //  = space for (512 / 4) uint32_t
00025 uint8_t     SD_state = SD_OK,   sd_jf = 0;
00026 
00027 static  const    uint64_t    GIGAB = 1024 * 1024 * 1024;
00028 //static  const    uint64_t    SDBLOCKS = (GIGAB / SD_BLOCKSIZE) * 4;    //  software drives SD up to 4Gbyte only - 8 M block
00029 static  const    uint64_t    SDBLOCKS = (GIGAB / SD_BLOCKSIZE) * 2;    //  software drives SD up to 4Gbyte only - 8 M block
00030 //  If data logger takes 2 minutes to fill 1 block, a 4G card takes 32 years run-time to fill
00031 //  If system generates approx 320 pulses per metre travelled, max distance recordable in uint32_t is 65536 * 65536 / 320 = 13421.772 km
00032 bool    sd_error    ()  {   //  Test and Clear error code sd_jf, return true if any error bits set, false on 0
00033     bool    retval = false;
00034     if  (sd_jf != 0)    {
00035         retval = true;
00036         sd_jf = 0;
00037     }
00038     return  retval;
00039 }
00040 
00041 bool    check_SD_block_clear    (uint32_t block) {
00042     uint32_t    b[(SD_BLOCKSIZE >> 2)];
00043     SD_state    = sd.ReadBlocks(b, (uint64_t)(SD_BLOCKSIZE * block), SD_BLOCKSIZE, 1);
00044     if(SD_state != SD_OK)   {
00045         sd_jf = 1;
00046         pc.printf   ("Failed, not SD_OK, erasing block %d\r\n", block);
00047         return  false;
00048     }
00049     for (int i = 0; i < (SD_BLOCKSIZE >> 2); i++)
00050         if  (b[i] != 0)
00051             return  false;
00052     return  true;
00053 }
00054 
00055 bool    read_SD_state   ()  {
00056     if  (SD_state == SD_OK)
00057         return  true;
00058     return  false;
00059 }
00060 /*bool erase_block (uint32_t    block2erase)    {
00061     uint64_t addr = SD_BLOCKSIZE * (uint64_t)block2erase;
00062     SD_state = sd.Erase(addr, addr + SD_BLOCKSIZE);
00063     if  (SD_state != SD_OK) {
00064         sd_jf = 1;  //  Assert error flag
00065         pc.printf   ("Failed, not SD_OK, erasing block %d\r\n", block2erase);
00066         return  false;
00067     }
00068     return  check_SD_block_clear (block2erase);
00069 }*/
00070 
00071 bool    SD_find_next_clear_block    (uint64_t * blok)  {   //  Successive approximation algorithm to quickly find next vacant SD card 512 byte block
00072     uint64_t toaddsub = SDBLOCKS / 2, stab = SDBLOCKS - 1;
00073     pc.printf   ("At SD_find_next_clear_block \r\n");
00074     while   (toaddsub)  {
00075         pc.printf   ("stab = %lld, toadsub = %lld\r\n", stab, toaddsub);    //  lld for long long int
00076         bool    clear_block = true;
00077         SD_state    = sd.ReadBlocks(SDBuffer, SD_BLOCKSIZE * stab, SD_BLOCKSIZE, 1);
00078         if(SD_state != SD_OK)   {
00079             sd_jf = 1;
00080             pc.printf   ("SD error in SD_find_next_clear_block, returning -1\r\n");
00081             return false;
00082         }
00083         for (int i = 0; i < (SD_BLOCKSIZE >> 2); i++)   {
00084             if  (SDBuffer[i] != 0) {
00085                 clear_block = false;
00086                 pc.printf   ("Buff at %d contains %x\r\n", i, SDBuffer[i]);
00087                 i = SD_BLOCKSIZE;  //  to exit loop
00088             }
00089         }
00090         if  (clear_block)
00091             stab -= toaddsub;
00092         else
00093             stab += toaddsub;
00094         toaddsub >>= 1;
00095     }
00096     if  (!check_SD_block_clear(stab))
00097         stab++;
00098     if  (sd_error())    {   //  sd_error() tests and clears error bits
00099         pc.printf   ("check_SD_block_clear(%ld)returned ERROR in SD_find_next_clear_block\r\n", stab);
00100         sd_jf = 1;  //  reassert error flag
00101         return  false;
00102     }
00103     pc.printf   ("Completed find_next, stab = %d\r\n", stab);
00104     *blok = stab;   //  block number of next free block
00105     return  true;
00106 }
00107 
00108 bool SD_card_erase_all   (void)  {   //  assumes sd card is 4 Gbyte, erases 4 Gbyte. Called from CLI
00109     uint64_t    EndAddr  = GIGAB * 4, 
00110                 StartAddr = 0LL;
00111     sd_jf = 0;
00112     pc.printf   ("Erasing SD card ... ");
00113     //  uint8_t Erase(uint64_t StartAddr, uint64_t EndAddr);
00114     SD_state    = sd.Erase(StartAddr, EndAddr);
00115     if  (SD_state != SD_OK) {
00116         pc.printf   ("SD_card_erase_all FAILED\r\n");
00117         sd_jf = 1;
00118         return  false;
00119     }
00120     pc.printf   ("no error detected\r\n");
00121     return  true;
00122 }
00123 
00124 
00125 bool mainSDtest()
00126 {
00127     SD_state = sd.Init();
00128     if(SD_state != SD_OK) {
00129         pc.printf   ("sd.Init set SD_state to %0x\r\n", SD_state);
00130         if(SD_state == MSD_ERROR_SD_NOT_PRESENT) {
00131             pc.printf("SD shall be inserted before running test\r\n");
00132         } else {
00133             pc.printf("SD Initialization : FAIL.\r\n");
00134         }
00135         pc.printf("SD Test Aborted.\r\n");
00136         return  false;
00137     } 
00138 //    else {    //  SD_state is SD_OK
00139     pc.printf("SD Initialization : OK.\r\n");
00140 
00141 
00142 
00143 //        SD_card_erase_all();
00144 //        if    (sd_error())
00145 //            pc.printf ("SD_card_erase_all() reports ERROR");
00146 
00147 
00148 
00149     SD_find_next_clear_block(& SD_blockptr);
00150     pc.printf   ("SD_find_next_clear_block returned %lld\r\n\n\n", SD_blockptr);
00151     if  (sd_error())    {
00152         pc.printf   ("***** ERROR returned from SD_find_next_clear_block ***** SD ops aborted\r\n");
00153         return  false;
00154     }   
00155     pc.printf("SD_find_next_clear_block() returned %ld\r\n", SD_blockptr);
00156     if  (SD_blockptr < 1)   {
00157         pc.printf   ("Looks like card newly erased, SD_blockptr value of %d\r\n", SD_blockptr);
00158         SD_blockptr = 0;
00159         historic_distance = 0;
00160     }
00161     else    {
00162         SD_state = sd.ReadBlocks(SDBuffer, SD_BLOCKSIZE * (SD_blockptr - 1), SD_BLOCKSIZE, 1);
00163         if  (SD_state != SD_OK) {
00164             pc.printf   ("Error reading last block from SD block %d\r\n", SD_blockptr - 1);
00165             return  false;
00166         }
00167         for (int i = 0; i < (SD_BLOCKSIZE >> 2); i++)
00168             pc.printf   ("%lx\t", SDBuffer[i]);
00169         historic_distance = SDBuffer[(SD_BLOCKSIZE >> 2) - 1];
00170         pc.printf   ("\r\nAbove, data read from last filled SD block %lld, using historic_distance = %lx\r\n", SD_blockptr - 1, historic_distance);
00171     }
00172     if  (SD_blockptr > 2)   {
00173         for (int i = SD_blockptr - 2; i < SD_blockptr + 2; i++)    {
00174             pc.printf   ("check_SD_block_clear (%d) ", i);
00175             if  (check_SD_block_clear(i))
00176                 pc.printf   ("block %ld is CLEAR\r\n", i);
00177             else
00178                 pc.printf   ("block %ld is NOT clear\r\n", i);
00179             if  (sd_error())    {
00180                 pc.printf   ("ERROR from check_SD_block_clear ()\r\n");
00181             }
00182         }
00183     }
00184     return  true;
00185 }
00186 
00187 void    update_SD_card  ()  {   //  Hall pulse total updated once per sec and saved in blocks of 128 to SD card
00188     static int index = 0;
00189     static uint32_t    buff[(SD_BLOCKSIZE >> 2) + 2];
00190 //    buff[index++] = speed.pulse_total();        //  pulse_total for all time, add this to buffer to write to SD
00191     buff[index++] = get_pulse_total();        //  pulse_total for all time, add this to buffer to write to SD
00192     if  (index >= (SD_BLOCKSIZE >> 2)) {
00193         pc.printf   ("Writing new SD block %d ... ", SD_blockptr);
00194         SD_state = sd.WriteBlocks(buff, SD_BLOCKSIZE * SD_blockptr, SD_BLOCKSIZE, 1);
00195         SD_blockptr++;
00196         if  (SD_state == SD_OK)
00197             pc.printf   ("OK, distance %d\r\n", buff[index - 1] / (int)PULSES_PER_METRE);
00198         else
00199             pc.printf   ("ERROR\r\n");
00200         index = 0;
00201     }
00202 }
00203 
00204