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
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
Generated on Sun Jul 17 2022 14:01:42 by 1.7.2