Touch screen drivers control dashboard for miniature locomotive. Features meters for speed, volts, power. Switches for lights, horns. Drives multiple STM3_ESC brushless motor controllers for complete brushless loco system as used in "The Brute" - www.jons-workshop.com
Dependencies: TS_DISCO_F746NG mbed Servo LCD_DISCO_F746NG BSP_DISCO_F746NG QSPI_DISCO_F746NG AsyncSerial FastPWM
qspi_mem.cpp@7:3b1f44cd4735, 2018-05-09 (annotated)
- Committer:
- JonFreeman
- Date:
- Wed May 09 15:42:43 2018 +0000
- Revision:
- 7:3b1f44cd4735
- Parent:
- 5:21a8ac83142c
- Child:
- 9:644867052318
Panic recovery from updating mbed lib causing total wipeout
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
JonFreeman | 4:67478861c670 | 1 | #include "mbed.h" |
JonFreeman | 4:67478861c670 | 2 | #include "Electric_Loco.h" |
JonFreeman | 4:67478861c670 | 3 | |
JonFreeman | 4:67478861c670 | 4 | #ifdef QSPI // Defined in Electric_Loco.h |
JonFreeman | 4:67478861c670 | 5 | #include "QSPI_DISCO_F746NG.h" |
JonFreeman | 4:67478861c670 | 6 | |
JonFreeman | 4:67478861c670 | 7 | struct log_element { |
JonFreeman | 4:67478861c670 | 8 | uint32_t pulsetot; // Total distance ever in pulse count |
JonFreeman | 4:67478861c670 | 9 | uint16_t powerW; // during previous second |
JonFreeman | 4:67478861c670 | 10 | uint16_t volts; // during previous second |
JonFreeman | 4:67478861c670 | 11 | } ; |
JonFreeman | 4:67478861c670 | 12 | |
JonFreeman | 4:67478861c670 | 13 | static const int START_BANK = 97; // Which 4k segment to start at |
JonFreeman | 4:67478861c670 | 14 | static const int BANKS_4K = 4; // Numof 4k byte pages used to store recent records |
JonFreeman | 4:67478861c670 | 15 | |
JonFreeman | 4:67478861c670 | 16 | QSPI_DISCO_F746NG qspi; |
JonFreeman | 4:67478861c670 | 17 | extern Serial pc; |
JonFreeman | 5:21a8ac83142c | 18 | //extern uint32_t historic_distance; no longer exkists Apr 2018 |
JonFreeman | 4:67478861c670 | 19 | |
JonFreeman | 4:67478861c670 | 20 | QSPI_Info pQSPI_Info; |
JonFreeman | 4:67478861c670 | 21 | |
JonFreeman | 4:67478861c670 | 22 | bool qspimemcheck () { |
JonFreeman | 4:67478861c670 | 23 | qspi.GetInfo(&pQSPI_Info); |
JonFreeman | 4:67478861c670 | 24 | if ((pQSPI_Info.FlashSize != N25Q128A_FLASH_SIZE) || |
JonFreeman | 4:67478861c670 | 25 | (pQSPI_Info.EraseSectorSize != N25Q128A_SUBSECTOR_SIZE) || |
JonFreeman | 4:67478861c670 | 26 | (pQSPI_Info.ProgPageSize != N25Q128A_PAGE_SIZE) || |
JonFreeman | 4:67478861c670 | 27 | (pQSPI_Info.EraseSectorsNumber != N25Q128A_SUBSECTOR_SIZE) || |
JonFreeman | 4:67478861c670 | 28 | (pQSPI_Info.ProgPagesNumber != N25Q128A_SECTOR_SIZE)) |
JonFreeman | 4:67478861c670 | 29 | { |
JonFreeman | 4:67478861c670 | 30 | error("Get informations FAILED\r\n"); |
JonFreeman | 4:67478861c670 | 31 | return false; |
JonFreeman | 4:67478861c670 | 32 | } |
JonFreeman | 4:67478861c670 | 33 | else |
JonFreeman | 4:67478861c670 | 34 | { |
JonFreeman | 4:67478861c670 | 35 | pc.printf("Get informations PASSED\r\n"); |
JonFreeman | 4:67478861c670 | 36 | pc.printf ("FLASH_SIZE\t\t%d\r\n", N25Q128A_FLASH_SIZE); |
JonFreeman | 4:67478861c670 | 37 | pc.printf ("ERASE_SECTOR_SIZE\t%d\r\n", N25Q128A_SUBSECTOR_SIZE); |
JonFreeman | 4:67478861c670 | 38 | pc.printf ("PROG_PAGE_SIZE\t\t%d\r\n", N25Q128A_PAGE_SIZE); |
JonFreeman | 4:67478861c670 | 39 | pc.printf ("Erase sectors number\t%d\r\n", N25Q128A_SUBSECTOR_SIZE); |
JonFreeman | 4:67478861c670 | 40 | pc.printf ("N25Q128A_SECTOR_SIZE\t%d\r\n", N25Q128A_SECTOR_SIZE); |
JonFreeman | 4:67478861c670 | 41 | return true; |
JonFreeman | 4:67478861c670 | 42 | } |
JonFreeman | 4:67478861c670 | 43 | } |
JonFreeman | 4:67478861c670 | 44 | |
JonFreeman | 4:67478861c670 | 45 | int ask_QSPI_OK () { |
JonFreeman | 4:67478861c670 | 46 | return QSPI_OK; |
JonFreeman | 4:67478861c670 | 47 | } |
JonFreeman | 4:67478861c670 | 48 | |
JonFreeman | 4:67478861c670 | 49 | int qspiinit () { |
JonFreeman | 4:67478861c670 | 50 | int r = qspi.Init(); |
JonFreeman | 4:67478861c670 | 51 | if (r != QSPI_OK) |
JonFreeman | 4:67478861c670 | 52 | pc.printf ("QSPI Init failed.\r\n"); |
JonFreeman | 4:67478861c670 | 53 | return r; |
JonFreeman | 4:67478861c670 | 54 | } |
JonFreeman | 4:67478861c670 | 55 | |
JonFreeman | 4:67478861c670 | 56 | void show_bank (uint32_t bank) { |
JonFreeman | 4:67478861c670 | 57 | uint8_t bu[4096]; |
JonFreeman | 4:67478861c670 | 58 | struct log_element * p = (log_element *)bu; |
JonFreeman | 4:67478861c670 | 59 | if (qspi.Read(bu, bank << 12, 4096) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 60 | pc.printf ("Error reading qspi mem in show_bank\r\n"); |
JonFreeman | 4:67478861c670 | 61 | return ; |
JonFreeman | 4:67478861c670 | 62 | } |
JonFreeman | 4:67478861c670 | 63 | pc.printf ("Listing records in bank %d\r\n", bank); |
JonFreeman | 4:67478861c670 | 64 | for (int i = 0; i < 4095 / sizeof(struct log_element); i++) { |
JonFreeman | 4:67478861c670 | 65 | pc.printf ("p->pulsetot%ld, powerW %d, volts %d, addr %lx\r\n", p->pulsetot, p->powerW, p->volts, (uint32_t)p++); |
JonFreeman | 4:67478861c670 | 66 | } |
JonFreeman | 4:67478861c670 | 67 | } |
JonFreeman | 4:67478861c670 | 68 | |
JonFreeman | 4:67478861c670 | 69 | void show_all_banks (); |
JonFreeman | 4:67478861c670 | 70 | void show_all_banks () { |
JonFreeman | 4:67478861c670 | 71 | for (int bank = START_BANK; bank < START_BANK + BANKS_4K; bank++) |
JonFreeman | 4:67478861c670 | 72 | show_bank (bank); |
JonFreeman | 4:67478861c670 | 73 | } |
JonFreeman | 4:67478861c670 | 74 | |
JonFreeman | 4:67478861c670 | 75 | class distance_measurement { |
JonFreeman | 7:3b1f44cd4735 | 76 | uint32_t total_distance; // Replaces historic_distance from previous iterations |
JonFreeman | 4:67478861c670 | 77 | uint32_t bank; |
JonFreeman | 4:67478861c670 | 78 | uint32_t ptr; |
JonFreeman | 4:67478861c670 | 79 | uint8_t buff[4096]; // Reqd qspi ram 4k at a time into here |
JonFreeman | 4:67478861c670 | 80 | |
JonFreeman | 4:67478861c670 | 81 | bool test_element_free (uint8_t* p) ; |
JonFreeman | 4:67478861c670 | 82 | bool test_bank_free (uint32_t addr) ; |
JonFreeman | 4:67478861c670 | 83 | bool test_buff_free () ; |
JonFreeman | 4:67478861c670 | 84 | public: |
JonFreeman | 4:67478861c670 | 85 | bool zero () ; |
JonFreeman | 7:3b1f44cd4735 | 86 | uint32_t out () ; |
JonFreeman | 4:67478861c670 | 87 | bool update (uint32_t pulsetot, uint16_t pow, uint16_t volt) ; |
JonFreeman | 4:67478861c670 | 88 | |
JonFreeman | 4:67478861c670 | 89 | distance_measurement () { // Constructor |
JonFreeman | 4:67478861c670 | 90 | uint32_t obank = 0, optr = 0, lptr = 0; |
JonFreeman | 4:67478861c670 | 91 | bool free_elem_found = false; |
JonFreeman | 4:67478861c670 | 92 | qspi.Init (); |
JonFreeman | 4:67478861c670 | 93 | |
JonFreeman | 4:67478861c670 | 94 | bank = START_BANK; |
JonFreeman | 4:67478861c670 | 95 | while (bank < START_BANK + BANKS_4K && !free_elem_found) { |
JonFreeman | 4:67478861c670 | 96 | if (qspi.Read(buff, bank << 12, 4096) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 97 | pc.printf ("Error reading qspi mem\r\n"); |
JonFreeman | 4:67478861c670 | 98 | } |
JonFreeman | 4:67478861c670 | 99 | for (ptr = 0; !free_elem_found && ptr < 4096; ptr += sizeof(struct log_element)) { |
JonFreeman | 4:67478861c670 | 100 | free_elem_found = test_element_free (&buff[ptr]); |
JonFreeman | 4:67478861c670 | 101 | if (free_elem_found) { |
JonFreeman | 4:67478861c670 | 102 | obank = bank; |
JonFreeman | 4:67478861c670 | 103 | optr = ptr; |
JonFreeman | 4:67478861c670 | 104 | pc.printf ("Found free element at bank %d, ptr %x\r\n", bank, ptr); |
JonFreeman | 4:67478861c670 | 105 | } |
JonFreeman | 4:67478861c670 | 106 | else { // Not free element found |
JonFreeman | 4:67478861c670 | 107 | lptr = ptr; |
JonFreeman | 4:67478861c670 | 108 | } |
JonFreeman | 4:67478861c670 | 109 | } |
JonFreeman | 4:67478861c670 | 110 | bank++; |
JonFreeman | 4:67478861c670 | 111 | } |
JonFreeman | 4:67478861c670 | 112 | bank = obank; |
JonFreeman | 4:67478861c670 | 113 | ptr = optr; |
JonFreeman | 4:67478861c670 | 114 | struct log_element * p = (log_element *)(buff + lptr); |
JonFreeman | 5:21a8ac83142c | 115 | |
JonFreeman | 7:3b1f44cd4735 | 116 | // historic_distance = p->pulsetot; // This needs replacing |
JonFreeman | 7:3b1f44cd4735 | 117 | total_distance = p->pulsetot; // New May 2018, total_distance is metres. Update info arrives in mm. |
JonFreeman | 5:21a8ac83142c | 118 | |
JonFreeman | 4:67478861c670 | 119 | pc.printf ("Constructor found free elem at bank %d, position %d, previous total %ld, volts %.3f\r\n", bank, ptr, p->pulsetot, ((double)p->volts) / 500.0); |
JonFreeman | 4:67478861c670 | 120 | } // endof constructor |
JonFreeman | 4:67478861c670 | 121 | } odometer; |
JonFreeman | 4:67478861c670 | 122 | |
JonFreeman | 4:67478861c670 | 123 | |
JonFreeman | 4:67478861c670 | 124 | bool distance_measurement::test_element_free (uint8_t* p) { |
JonFreeman | 4:67478861c670 | 125 | for (int i = 0; i < sizeof(log_element); i++) |
JonFreeman | 4:67478861c670 | 126 | if (*(p + i) != 0xff) |
JonFreeman | 4:67478861c670 | 127 | return false; |
JonFreeman | 4:67478861c670 | 128 | return true; |
JonFreeman | 4:67478861c670 | 129 | } |
JonFreeman | 4:67478861c670 | 130 | |
JonFreeman | 4:67478861c670 | 131 | bool distance_measurement::test_buff_free () { |
JonFreeman | 4:67478861c670 | 132 | for (int i = 0; i < 4096; i++) |
JonFreeman | 4:67478861c670 | 133 | if (buff[i] != 0xff) |
JonFreeman | 4:67478861c670 | 134 | return false; |
JonFreeman | 4:67478861c670 | 135 | return true; |
JonFreeman | 4:67478861c670 | 136 | } |
JonFreeman | 4:67478861c670 | 137 | |
JonFreeman | 4:67478861c670 | 138 | bool distance_measurement::test_bank_free (uint32_t addr) { |
JonFreeman | 4:67478861c670 | 139 | if (qspi.Read (buff, addr & 0xfffff000, 4096) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 140 | pc.printf ("Read error in test_bank_free\r\n"); |
JonFreeman | 4:67478861c670 | 141 | return false; |
JonFreeman | 4:67478861c670 | 142 | } |
JonFreeman | 4:67478861c670 | 143 | return test_buff_free (); |
JonFreeman | 4:67478861c670 | 144 | } |
JonFreeman | 4:67478861c670 | 145 | |
JonFreeman | 4:67478861c670 | 146 | bool distance_measurement::zero () { |
JonFreeman | 4:67478861c670 | 147 | bool rv = true; |
JonFreeman | 7:3b1f44cd4735 | 148 | total_distance = 0; |
JonFreeman | 4:67478861c670 | 149 | for (int i = START_BANK; i < START_BANK + BANKS_4K; i++) { |
JonFreeman | 4:67478861c670 | 150 | if (qspi.Erase_Block(i << 12) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 151 | pc.printf ("Error zeroing odometer!\r\n"); |
JonFreeman | 4:67478861c670 | 152 | rv = false; |
JonFreeman | 4:67478861c670 | 153 | } |
JonFreeman | 4:67478861c670 | 154 | if (!test_bank_free (i << 12)) |
JonFreeman | 4:67478861c670 | 155 | pc.printf ("Bank [%d] not freed in zero\r\n", i); |
JonFreeman | 4:67478861c670 | 156 | else |
JonFreeman | 4:67478861c670 | 157 | pc.printf ("Cleared bank [%d] in zero\r\n", i); |
JonFreeman | 4:67478861c670 | 158 | } |
JonFreeman | 4:67478861c670 | 159 | bank = START_BANK; |
JonFreeman | 4:67478861c670 | 160 | ptr = 0; |
JonFreeman | 4:67478861c670 | 161 | return rv; |
JonFreeman | 4:67478861c670 | 162 | } |
JonFreeman | 4:67478861c670 | 163 | |
JonFreeman | 7:3b1f44cd4735 | 164 | bool distance_measurement::update (uint32_t new_metres_travelled, uint16_t powr, uint16_t volt) { |
JonFreeman | 4:67478861c670 | 165 | bool rv = true; |
JonFreeman | 7:3b1f44cd4735 | 166 | total_distance += new_metres_travelled; |
JonFreeman | 4:67478861c670 | 167 | struct log_element d; |
JonFreeman | 7:3b1f44cd4735 | 168 | d.pulsetot = total_distance; |
JonFreeman | 4:67478861c670 | 169 | d.powerW = powr; |
JonFreeman | 4:67478861c670 | 170 | d.volts = volt; |
JonFreeman | 4:67478861c670 | 171 | uint32_t addr = ptr + (bank << 12); |
JonFreeman | 4:67478861c670 | 172 | if (qspi.Write ((uint8_t*)&d, addr, sizeof(struct log_element)) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 173 | pc.printf ("Write error in odometer update\r\n"); |
JonFreeman | 4:67478861c670 | 174 | qspi.Init(); // Attempt error recovery |
JonFreeman | 4:67478861c670 | 175 | return false; |
JonFreeman | 4:67478861c670 | 176 | } |
JonFreeman | 4:67478861c670 | 177 | ptr += sizeof(struct log_element); |
JonFreeman | 4:67478861c670 | 178 | if (ptr >= 4096) { |
JonFreeman | 4:67478861c670 | 179 | ptr -= 4096; |
JonFreeman | 4:67478861c670 | 180 | bank++; |
JonFreeman | 4:67478861c670 | 181 | if (bank >= START_BANK + BANKS_4K) |
JonFreeman | 4:67478861c670 | 182 | bank = START_BANK; |
JonFreeman | 4:67478861c670 | 183 | //erase bank |
JonFreeman | 4:67478861c670 | 184 | pc.printf ("About to erase bank %d\r\n", bank); |
JonFreeman | 4:67478861c670 | 185 | if (qspi.Erase_Block(bank << 12) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 186 | pc.printf ("Erase error in odometer update\r\n"); |
JonFreeman | 4:67478861c670 | 187 | rv = false; |
JonFreeman | 4:67478861c670 | 188 | } |
JonFreeman | 4:67478861c670 | 189 | } |
JonFreeman | 4:67478861c670 | 190 | return rv; |
JonFreeman | 4:67478861c670 | 191 | } |
JonFreeman | 4:67478861c670 | 192 | |
JonFreeman | 7:3b1f44cd4735 | 193 | uint32_t distance_measurement::out () { |
JonFreeman | 7:3b1f44cd4735 | 194 | return total_distance; |
JonFreeman | 7:3b1f44cd4735 | 195 | } |
JonFreeman | 7:3b1f44cd4735 | 196 | |
JonFreeman | 7:3b1f44cd4735 | 197 | |
JonFreeman | 4:67478861c670 | 198 | bool odometer_zero () ; // Returns true on success |
JonFreeman | 4:67478861c670 | 199 | bool odometer_zero () { // Returns true on success |
JonFreeman | 4:67478861c670 | 200 | return odometer.zero (); |
JonFreeman | 4:67478861c670 | 201 | } |
JonFreeman | 4:67478861c670 | 202 | |
JonFreeman | 4:67478861c670 | 203 | bool odometer_update (uint32_t pulsetot, uint16_t pow, uint16_t volt) ; // Hall pulse total updated once per sec and saved in blocks of 4096 bytes on QSPI onboard memory |
JonFreeman | 4:67478861c670 | 204 | bool odometer_update (uint32_t pulsetot, uint16_t pow, uint16_t volt) { // Hall pulse total updated once per sec and saved in blocks of 4096 bytes on QSPI onboard memory |
JonFreeman | 4:67478861c670 | 205 | return odometer.update (pulsetot, pow, volt); |
JonFreeman | 4:67478861c670 | 206 | } |
JonFreeman | 4:67478861c670 | 207 | |
JonFreeman | 7:3b1f44cd4735 | 208 | uint32_t odometer_out () { |
JonFreeman | 7:3b1f44cd4735 | 209 | return odometer.out(); |
JonFreeman | 7:3b1f44cd4735 | 210 | } |
JonFreeman | 4:67478861c670 | 211 | #endif |