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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers qspi_mem.cpp Source File

qspi_mem.cpp

00001 #include "mbed.h"
00002 #include "Electric_Loco.h"
00003 
00004 #include "QSPI_DISCO_F746NG.h"
00005 
00006 extern  error_handling_Jan_2019   Controller_Error    ;
00007 
00008 struct  log_element {
00009     uint32_t    pulsetot;   //  Total distance ever in metres
00010     uint16_t    powerW;     //  during previous second
00011     uint16_t    volts;      //  during previous second
00012 }   ;
00013 
00014 static  const   int START_BANK  = 97;    //  Which 4k segment to start at
00015 static  const   int BANKS_4K    = 4;  //  Numof 4k byte pages used to store recent records
00016 
00017 QSPI_DISCO_F746NG qspi;
00018 extern  Serial pc;
00019 //extern  uint32_t    historic_distance;    no longer exkists Apr 2018
00020 
00021     QSPI_Info pQSPI_Info;
00022 
00023 bool    qspimemcheck    ()  {
00024     qspi.GetInfo(&pQSPI_Info);
00025     if ((pQSPI_Info.FlashSize          != N25Q128A_FLASH_SIZE) ||
00026         (pQSPI_Info.EraseSectorSize    != N25Q128A_SUBSECTOR_SIZE) || 
00027         (pQSPI_Info.ProgPageSize       != N25Q128A_PAGE_SIZE) ||
00028         (pQSPI_Info.EraseSectorsNumber != N25Q128A_SUBSECTOR_SIZE) ||
00029         (pQSPI_Info.ProgPagesNumber    != N25Q128A_SECTOR_SIZE))
00030     {
00031       error("Get informations FAILED\r\n");
00032       return    false;  //  Controller_Error.set gets called from main    ;
00033     }
00034     else
00035     {
00036 /*        pc.printf("Get N25Q128A QSPI mem informations PASSED\r\n");
00037         pc.printf   ("FLASH_SIZE\t\t%d\r\n", N25Q128A_FLASH_SIZE);
00038         pc.printf   ("ERASE_SECTOR_SIZE\t%d\r\n", N25Q128A_SUBSECTOR_SIZE);
00039         pc.printf   ("PROG_PAGE_SIZE\t\t%d\r\n", N25Q128A_PAGE_SIZE);
00040         pc.printf   ("Erase sectors number\t%d\r\n", N25Q128A_SUBSECTOR_SIZE);
00041         pc.printf   ("N25Q128A_SECTOR_SIZE\t%d\r\n", N25Q128A_SECTOR_SIZE); */
00042         return    true;
00043     }
00044 }
00045 
00046 bool    test_qspi   ()  {
00047     if  ((qspi.Init() == QSPI_OK) && (qspimemcheck    ()))
00048         return  true;
00049     return  false;
00050 }
00051 
00052 void    show_bank   (uint32_t    bank)   {
00053     uint8_t bu[4096];
00054     struct  log_element * p = (log_element *)bu;
00055     if  (qspi.Read(bu, bank << 12, 4096) != QSPI_OK)  {
00056         pc.printf   ("Error reading qspi mem in show_bank\r\n");
00057         Controller_Error.set    (FAULT_QSPI, 1);
00058         return  ;
00059     }
00060     pc.printf   ("Listing records in bank %d\r\n", bank);
00061     for (int i = 0; i < 4095 / sizeof(struct log_element); i++) {
00062         pc.printf   ("p->pulsetot%ld, powerW %d, volts %d, addr %lx\r\n", p->pulsetot, p->powerW, p->volts, (uint32_t)p++);
00063     }
00064 }
00065 
00066 void    show_all_banks  ();
00067 void    show_all_banks  ()  {
00068     for (int bank = START_BANK; bank < START_BANK + BANKS_4K; bank++)
00069         show_bank   (bank);
00070 }
00071 
00072 class   distance_measurement {
00073     uint32_t    total_distance; //  Replaces historic_distance from previous iterations
00074     uint32_t    bank;
00075     uint32_t    ptr;
00076     uint8_t     buff[4096];     //  Reqd qspi ram 4k at a time into here
00077 
00078     bool        test_element_free  (uint8_t* p)   ;
00079     bool        test_bank_free  (uint32_t addr)  ;
00080     bool        test_buff_free  ()  ;
00081 public:
00082     bool        zero    ()  ;
00083     uint32_t    out ()  ;
00084     bool        update  (uint32_t pulsetot, uint16_t pow, uint16_t volt)  ;
00085 
00086     distance_measurement () {   //  Constructor
00087         uint32_t    obank = 0, optr = 0, lptr = 0;
00088         bool    free_elem_found = false;
00089         qspi.Init   ();
00090 
00091         bank = START_BANK;
00092         while   (bank < START_BANK + BANKS_4K && !free_elem_found)    {
00093             if  (qspi.Read(buff, bank << 12, 4096) != QSPI_OK)  {
00094                 Controller_Error.set    (FAULT_QSPI, 1);
00095 //                pc.printf   ("Error reading qspi mem\r\n");
00096             }
00097             for (ptr = 0; !free_elem_found && ptr < 4096; ptr += sizeof(struct log_element)) {
00098                 free_elem_found = test_element_free  (&buff[ptr]);
00099                 if  (free_elem_found)   {
00100                     obank = bank;
00101                     optr = ptr;
00102 //                    pc.printf   ("Found free element at bank %d, ptr %x\r\n", bank, ptr);
00103                 }
00104                 else    {   //  Not free element found
00105                     lptr = ptr;
00106                 }
00107             }
00108             bank++;
00109         }
00110         bank = obank;
00111         ptr = optr;
00112         struct  log_element * p = (log_element *)(buff + lptr);
00113 
00114 //        historic_distance = p->pulsetot;  //  This needs replacing
00115         total_distance = p->pulsetot;   //  New May 2018, total_distance is metres. Update info arrives in mm.
00116 
00117 //        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);
00118     }   //  endof constructor
00119 }   odometer;
00120 
00121 
00122 bool    distance_measurement::test_element_free  (uint8_t* p)  {
00123     for (int i = 0; i < sizeof(log_element); i++)
00124         if  (*(p + i) != 0xff)
00125             return  false;
00126     return  true;
00127 }
00128 
00129 bool    distance_measurement::test_buff_free  ()  {
00130     for (int i = 0; i < 4096; i++)
00131         if  (buff[i] != 0xff)
00132             return  false;
00133     return  true;
00134 }
00135 
00136 bool    distance_measurement::test_bank_free  (uint32_t addr)  {
00137     if  (qspi.Read   (buff, addr & 0xfffff000, 4096) != QSPI_OK)   {
00138         pc.printf   ("Read error in test_bank_free\r\n");
00139         return  false;
00140     }
00141     return  test_buff_free  ();
00142 }
00143 
00144 bool    distance_measurement::zero  ()  {
00145     bool    rv = true;
00146     total_distance = 0;
00147     for (int i = START_BANK; i < START_BANK + BANKS_4K; i++)    {
00148         if  (qspi.Erase_Block(i << 12) != QSPI_OK)  {
00149             pc.printf   ("Error zeroing odometer!\r\n");
00150             rv = false;
00151         }
00152         if  (!test_bank_free    (i << 12))
00153             pc.printf   ("Bank [%d] not freed in zero\r\n", i);
00154         else
00155             pc.printf   ("Cleared bank [%d] in zero\r\n", i);
00156     }
00157     bank = START_BANK;
00158     ptr = 0;
00159     return  rv;
00160 }
00161 
00162 bool    distance_measurement::update  (uint32_t new_metres_travelled, uint16_t powr, uint16_t volt)  {
00163     bool    rv = true;
00164     total_distance += new_metres_travelled;
00165     struct  log_element d;
00166     d.pulsetot   = total_distance;
00167     d.powerW     = powr;
00168     d.volts      = volt;
00169     uint32_t    addr = ptr + (bank << 12);
00170     if  (qspi.Write  ((uint8_t*)&d, addr, sizeof(struct log_element)) != QSPI_OK) {
00171         pc.printf   ("Write error in odometer update\r\n");
00172         qspi.Init();    //  Attempt error recovery
00173         return  false;
00174     }
00175     ptr += sizeof(struct log_element);
00176     if  (ptr >= 4096)   {
00177         ptr -= 4096;
00178         bank++;
00179         if  (bank >= START_BANK + BANKS_4K)
00180             bank = START_BANK;
00181         //erase bank
00182         pc.printf   ("About to erase bank %d\r\n", bank);
00183         if  (qspi.Erase_Block(bank << 12) != QSPI_OK)  {
00184             pc.printf   ("Erase error in odometer update\r\n");
00185             rv = false;
00186         }
00187     }
00188     return  rv;
00189 }
00190 
00191 uint32_t    distance_measurement::out  ()    {
00192     return  total_distance;
00193 }
00194 
00195 
00196 bool    odometer_zero   ()  ;   //  Returns true on success
00197 bool    odometer_zero   ()  {   //  Returns true on success
00198     return  odometer.zero   ();
00199 }
00200 
00201 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
00202 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
00203     return  odometer.update (pulsetot, pow, volt);
00204 }
00205 
00206 uint32_t    odometer_out  ()    {
00207     return  odometer.out();
00208 }