AJA NTV2 SDK  17.0.1.1246
NTV2 SDK 17.0.1.1246
ntv2spiinterface.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
7 #include "ntv2spiinterface.h"
8 
9 #include <cmath>
10 #include <algorithm>
11 #include <fstream>
12 #include <sstream>
13 #include <string>
14 #include <vector>
15 
16 #include "ntv2registersmb.h"
17 #include "ntv2mcsfile.h"
18 
19 using namespace std;
20 
21 static bool verify_vectors(const std::vector<uint8_t> &dataWritten, const std::vector<uint8_t> &dataRead, bool verbose = false)
22 {
23  bool result = false;
24 
25  if (equal(dataWritten.begin(), dataWritten.end(), dataRead.begin()))
26  {
27  result = true;
28  }
29  else
30  {
31  result = false;
32  if (verbose)
33  {
34  pair<vector<uint8_t>::const_iterator, vector<uint8_t>::const_iterator> p;
35  p = mismatch(dataWritten.begin(), dataWritten.end(), dataRead.begin());
36  int64_t byteMismatchOffset = distance(dataWritten.begin(), p.first);
37  ostringstream ossWrite;
38  ossWrite << "0x" << std::setw(2) << std::setfill('0') << hex << (int)*p.first;
39  ostringstream ossRead;
40  ossRead << "0x" << std::setw(2) << std::setfill('0') << hex << (int)*p.second;
41 
42  ++p.first; ++p.second;
43  p = mismatch(p.first, dataWritten.end(), p.second);
44 
45  int errorCount = 0;
46  while(p.first != dataWritten.end() && p.second != dataRead.end())
47  {
48  errorCount++;
49  ++p.first; ++p.second;
50  p = mismatch(p.first, dataWritten.end(), p.second);
51  }
52 
53  cout << "Verifying write of: " << dataWritten.size() << " bytes, failed at byte index: " << byteMismatchOffset <<
54  ", byte written to device should be: " << ossWrite.str() << ", byte read back from device is: " << ossRead.str() << ".\n" <<
55  "There are " << errorCount << " other mismatches after this." << endl;
56  }
57  }
58 
59  return result;
60 }
61 
62 inline void print_flash_status(const string& label, uint32_t curValue, uint32_t maxValue, uint32_t& lastPercentage)
63 {
64  if (maxValue == 0)
65  return;
66 
67  uint32_t percentage = (uint32_t)(((double)curValue/(double)maxValue)*100.0);
68  if (percentage != lastPercentage)
69  {
70  lastPercentage = percentage;
71  cout << label << " status: " << dec << lastPercentage << "% \r" << flush;
72  }
73 }
74 
75 inline void print_flash_status_final(const string& label)
76 {
77  cout << label << " status: 100% " << endl;
78 }
79 
80 // Cypress/Spansion commands
81 
82 //const uint32_t CYPRESS_FLASH_WRITE_STATUS_COMMAND = 0x01;
83 const uint32_t CYPRESS_FLASH_WRITEDISABLE_COMMAND = 0x04;
84 const uint32_t CYPRESS_FLASH_READ_STATUS_COMMAND = 0x05;
85 const uint32_t CYPRESS_FLASH_WRITEENABLE_COMMAND = 0x06;
86 const uint32_t CYPRESS_FLASH_READFAST_COMMAND = 0x0C; //4 byte address
87 const uint32_t CYPRESS_FLASH_PAGE_PROGRAM_COMMAND = 0x12; //4 byte address
88 //const uint32_t CYPRESS_FLASH_READ_COMMAND = 0x13; //4 byte address
89 const uint32_t CYPRESS_FLASH_READBANK_COMMAND = 0x16;
90 const uint32_t CYPRESS_FLASH_WRITEBANK_COMMAND = 0x17;
91 const uint32_t CYPRESS_FLASH_SECTOR4K_ERASE_COMMAND= 0x21; //4 byte address
92 const uint32_t CYPRESS_FLASH_READ_CONFIG_COMMAND = 0x35;
94 const uint32_t CYPRESS_FLASH_SECTOR_ERASE_COMMAND = 0xDC; //4 byte address
95 
96 inline bool has_4k_start_sectors(const uint32_t reportedSectorSize)
97 {
98  return false;
99 // if (reportedSectorSize <= 0x20000)
100 // return true;
101 // else
102 // return false;
103 }
104 
105 static uint32_t size_for_sector_number(const uint32_t reportedSectorSize, const uint32_t sector)
106 {
107  if (has_4k_start_sectors(reportedSectorSize) && sector < 32)
108  return 4 * 1024;
109  else
110  return reportedSectorSize;
111 }
112 
113 static uint32_t erase_cmd_for_sector(const uint32_t reportedSectorSize, const uint32_t sector)
114 {
115  if (has_4k_start_sectors(reportedSectorSize) && sector < 32)
116  return CYPRESS_FLASH_SECTOR4K_ERASE_COMMAND; // 4P4E command, 4byte
117  else
118  return CYPRESS_FLASH_SECTOR_ERASE_COMMAND; // 4SE command, 4byte
119 }
120 
121 static uint32_t sector_for_address(uint32_t sectorSizeBytes, uint32_t address)
122 {
123  if (sectorSizeBytes == 0)
124  return 0;
125 
126  uint32_t sector = 0;
127  if (has_4k_start_sectors(sectorSizeBytes))
128  {
129  if (address < 0x20000)
130  {
131  uint32_t sector4kSizeBytes = size_for_sector_number(sectorSizeBytes, 0);
132  sector = address / sector4kSizeBytes;
133  }
134  else
135  {
136  sector += 32;
137  sector += (address-0x20000) / sectorSizeBytes;
138  }
139  }
140  else
141  {
142  sector = address / sectorSizeBytes;
143  }
144 
145  return sector;
146 }
147 
148 static uint32_t address_for_sector(uint32_t sectorSizeBytes, uint32_t sector)
149 {
150  uint32_t address=0;
151  if (has_4k_start_sectors(sectorSizeBytes))
152  {
153  if (sector < 32)
154  address = sector * size_for_sector_number(sectorSizeBytes, 0);
155  else
156  {
157  address = 32 * size_for_sector_number(sectorSizeBytes, 0);
158  address += (sector - 32) * sectorSizeBytes;
159  }
160  }
161  else
162  {
163  address = sector * sectorSizeBytes;
164  }
165 
166  return address;
167 }
168 
169 inline ProgramState programstate_for_address(uint32_t address, int mode)
170 {
171  ProgramState ps;
172  switch(mode)
173  {
174  case 0: ps = (address < 0x100000) ? kProgramStateEraseBank3 : kProgramStateEraseBank4; break;
175  case 1: ps = (address < 0x100000) ? kProgramStateProgramBank3 : kProgramStateProgramBank4; break;
176  case 2: ps = (address < 0x100000) ? kProgramStateVerifyBank3 : kProgramStateVerifyBank4; break;
177  default: ps = kProgramStateFinished; break;
178  }
179 
180  return ps;
181 }
182 
183 inline uint32_t make_spi_ready(CNTV2Card& device)
184 {
185  uint32_t deviceId=0;
186  device.ReadRegister(kRegBoardID, deviceId);
187  return deviceId;
188 }
189 
190 #define wait_for_flash_status_ready() { uint8_t fs=0x00; do { FlashReadStatus(fs); } while(fs & 0x1); }
191 
192 CNTV2AxiSpiFlash::CNTV2AxiSpiFlash(int index, bool verbose)
193  : CNTV2SpiFlash(verbose), mBaseByteAddress(0x300000), mSize(0), mSectorSize(0)
194 {
195  mSpiResetReg = (mBaseByteAddress + 0x40) / 4;
196  mSpiControlReg = (mBaseByteAddress + 0x60) / 4;
197  mSpiStatusReg = (mBaseByteAddress + 0x64) / 4;
198  mSpiWriteReg = (mBaseByteAddress + 0x68) / 4;
199  mSpiReadReg = (mBaseByteAddress + 0x6c) / 4;
200  mSpiSlaveReg = (mBaseByteAddress + 0x70) / 4;
201  mSpiGlobalIntReg = (mBaseByteAddress + 0x1c) / 4;
202  AsNTV2DriverInterfaceRef(mDevice).Open(UWord(index));
203 
204  SpiReset();
205 
206  uint8_t manufactureID;
207  uint8_t memInerfaceType;
208  uint8_t memDensity;
209  uint8_t sectorArchitecture;
210  uint8_t familyID;
211  bool good = FlashDeviceInfo(manufactureID, memInerfaceType, memDensity, sectorArchitecture, familyID);
212  if (good)
213  {
214  switch(memDensity)
215  {
216  case 0x18: mSize = 16 * 1024 * 1024; break;
217  case 0x19: mSize = 32 * 1024 * 1024; break;
218  case 0x20: mSize = 64 * 1024 * 1024; break;
219  default: mSize = 0; break;
220  }
221 
222  sectorArchitecture &= 0x03;
223  switch(sectorArchitecture)
224  {
225  case 0x00:
226  {
227  mSectorSize = (manufactureID == 0x20) ? 64 * 1024 : 256 * 1024;
228  break;
229  }
230  case 0x01: mSectorSize = 64 * 1024; break;
231  default: mSectorSize = 0; break;
232  }
233 
234  mManufactureID = manufactureID;
235  }
236 
237  //uint8_t configValue;
238  //good = FlashReadConfig(configValue);
239  //uint8_t statusValue;
240  //good = FlashReadStatus(statusValue);
241 }
242 
244 {
245 }
246 
248 {
249  if ((deviceId == DEVICE_ID_IOIP_2022) ||
250  (deviceId == DEVICE_ID_IOIP_2110) ||
251  (deviceId == DEVICE_ID_IOIP_2110_RGB12) ||
252  (deviceId == DEVICE_ID_KONAX) ||
253  (deviceId == DEVICE_ID_KONAXM))
254  {
255  return true;
256  }
257  else
258  {
259  return false;
260  }
261 }
262 
263 bool CNTV2AxiSpiFlash::Read(const uint32_t address, std::vector<uint8_t> &data, uint32_t maxBytes)
264 {
265  const uint32_t pageSize = 128;
266  ProgramState ps = programstate_for_address(address, 2);
267 
268  uint32_t pageAddress = address;
269  uint32_t numPages = (uint32_t)ceil((double)maxBytes/(double)pageSize);
270 
271  uint32_t bytesLeftToTransfer = maxBytes;
272  uint32_t bytesTransfered = 0;
273  mDevice.WriteRegister(kVRegFlashState, ps);
274  mDevice.WriteRegister(kVRegFlashSize, bytesLeftToTransfer);
275  mDevice.WriteRegister(kVRegFlashStatus, 0);
276 
277  uint32_t lastPercent = 0;
278  for(uint32_t p=0;p<numPages;p++)
279  {
280  vector<uint8_t> commandSequence;
281  commandSequence.push_back(CYPRESS_FLASH_READFAST_COMMAND);
282  FlashFixAddress(pageAddress, commandSequence);
283 
284  uint32_t bytesToTransfer = pageSize;
285  if (bytesLeftToTransfer < pageSize)
286  bytesToTransfer = bytesLeftToTransfer;
287 
288  vector<uint8_t> dummyInput;
289  SpiTransfer(commandSequence, dummyInput, data, bytesToTransfer);
291 
292  bytesLeftToTransfer -= bytesToTransfer;
293  pageAddress += pageSize;
294 
295  bytesTransfered += bytesToTransfer;
296 
297  if (mVerbose && maxBytes > 0)
298  print_flash_status("Verify", bytesTransfered, maxBytes, lastPercent);
299 
300  mDevice.WriteRegister(kVRegFlashState, ps);
301  mDevice.WriteRegister(kVRegFlashStatus, bytesTransfered);
302  }
303 
304  if (mVerbose)
305  print_flash_status_final("Verify");
306 
307  return true;
308 }
309 
310 bool CNTV2AxiSpiFlash::Write(const uint32_t address, const std::vector<uint8_t> data, uint32_t maxBytes)
311 {
312  const uint32_t pageSize = 128;
313  ProgramState ps = programstate_for_address(address, 1);
314 
315  uint32_t maxWrite = maxBytes;
316  if (maxWrite > data.size())
317  maxWrite = (uint32_t)data.size();
318 
319  std::vector<uint8_t> dummyOutput;
320 
321  uint32_t pageAddress = address;
322  uint32_t numPages = (uint32_t)ceil((double)maxWrite/(double)pageSize);
323 
324  uint32_t bytesTransfered = 0;
325  mDevice.WriteRegister(kVRegFlashState, ps);
326  mDevice.WriteRegister(kVRegFlashSize, maxWrite);
327  mDevice.WriteRegister(kVRegFlashStatus, 0);
328 
329  uint32_t lastPercent = 0;
330  for(uint32_t p=0;p<numPages;p++)
331  {
332  vector<uint8_t> commandSequence;
333  commandSequence.push_back(CYPRESS_FLASH_PAGE_PROGRAM_COMMAND);
334  FlashFixAddress(pageAddress, commandSequence);
335 
336  vector<uint8_t> pageData;
337  for(unsigned i=0;i<pageSize;i++)
338  {
339  uint32_t offset = (p*pageSize)+i;
340  if (offset >= data.size())
341  break;
342 
343  pageData.push_back(data.at(offset));
344  }
345 
346  // enable write
347  SpiEnableWrite(true);
348 
349  SpiTransfer(commandSequence, pageData, dummyOutput, (uint32_t)pageData.size());
351 
352  // disable write
353  SpiEnableWrite(false);
354 
355  pageAddress += pageSize;
356  bytesTransfered += static_cast<uint32_t>(pageData.size());
357 
358  if (mVerbose && maxWrite > 0)
359  print_flash_status("Program", bytesTransfered, maxWrite, lastPercent);
360 
361  mDevice.WriteRegister(kVRegFlashState, ps);
362  mDevice.WriteRegister(kVRegFlashStatus, bytesTransfered);
363  }
364 
365  if (mVerbose)
366  print_flash_status_final("Program");
367 
368  return true;
369 }
370 
371 bool CNTV2AxiSpiFlash::Erase(const uint32_t address, uint32_t bytes)
372 {
373  //testing
374 #if 0
375  // 64k
376  uint32_t test1Addr = 0x20000;
377  uint32_t test1ExpectedSector = 32;
378 
379  // 4k
380  uint32_t test2Addr = 0x1F000;
381  uint32_t test2ExpectedSector = 31;
382 
383  // 64k
384  uint32_t test3Addr = 0x1FF0000;
385  uint32_t test3ExpectedSector = 541;
386 
387  uint32_t test1Res = sector_for_address(mSectorSize, test1Addr);
388  uint32_t test2Res = sector_for_address(mSectorSize, test2Addr);
389  uint32_t test3Res = sector_for_address(mSectorSize, test3Addr);
390 
391  uint32_t test1AddrRes = address_for_sector(mSectorSize, test1ExpectedSector);
392  uint32_t test2AddrRes = address_for_sector(mSectorSize, test2ExpectedSector);
393  uint32_t test3AddrRes = address_for_sector(mSectorSize, test3ExpectedSector);
394 
395  uint32_t test1Cmd = erase_cmd_for_sector(mSectorSize, test1ExpectedSector);
396  uint32_t test2Cmd = erase_cmd_for_sector(mSectorSize, test2ExpectedSector);
397  uint32_t test3Cmd = erase_cmd_for_sector(mSectorSize, test3ExpectedSector);
398  return true;
399 #endif
400 
401  ProgramState ps = programstate_for_address(address, 0);
402 
403  uint32_t startSector = sector_for_address(mSectorSize, address);
404  uint32_t endSector = sector_for_address(mSectorSize, address + bytes);
405 
406  uint32_t cmd = erase_cmd_for_sector(mSectorSize, startSector);
407  uint32_t sectorAddress = address_for_sector(mSectorSize, startSector);
408 
409  vector<uint8_t> commandSequence;
410  commandSequence.push_back(cmd);
411  FlashFixAddress(address, commandSequence);
412 
413  uint32_t lastPercent = 0;
414 
415  if (mVerbose && endSector > startSector)
416  print_flash_status("Erase", startSector, endSector-startSector, lastPercent);
417 
418  // enable write
419  SpiEnableWrite(true);
420 
421  vector<uint8_t> dummyInput;
422  vector<uint8_t> dummyOutput;
423  SpiTransfer(commandSequence, dummyInput, dummyOutput, bytes);
425 
426  // disable write
427  //SpiEnableWrite(false);
428 
429  // Handle the case of erase spanning sectors
430  if (endSector > startSector)
431  {
432  uint32_t numSectors = endSector-startSector;
433  mDevice.WriteRegister(kVRegFlashState, ps);
434  mDevice.WriteRegister(kVRegFlashSize, numSectors);
435  mDevice.WriteRegister(kVRegFlashStatus, 0);
436 
437  uint32_t start = startSector;
438  while (start < endSector)
439  {
440  ++start;
441  cmd = erase_cmd_for_sector(mSectorSize, start);
442  sectorAddress = address_for_sector(mSectorSize, start);
443 
444  vector<uint8_t> commandSequence2;
445  commandSequence2.push_back(cmd);
446  FlashFixAddress(sectorAddress, commandSequence2);
447 
448  // enable write
449  SpiEnableWrite(true);
450 
451  //vector<uint8_t> dummyInput;
452  SpiTransfer(commandSequence2, dummyInput, dummyOutput, bytes);
454 
455  // disable write
456  SpiEnableWrite(false);
457 
458  uint32_t curProgress = start-startSector;
459  if (mVerbose)
460  print_flash_status("Erase", curProgress, endSector-startSector, lastPercent);
461 
462  mDevice.WriteRegister(kVRegFlashState, ps);
463  mDevice.WriteRegister(kVRegFlashStatus, curProgress);
464  }
465 
466  if (mVerbose)
467  print_flash_status_final("Erase");
468 
469  }
470 
471  return true;
472 }
473 
474 bool CNTV2AxiSpiFlash::Verify(const uint32_t address, const std::vector<uint8_t>& dataWritten)
475 {
476  vector<uint8_t> verifyData;
477  bool readGood = Read(address, verifyData, uint32_t(dataWritten.size()));
478 
479  if (readGood == false)
480  return false;
481 
482  return verify_vectors(dataWritten, verifyData, mVerbose);
483 }
484 
486 {
487  uint32_t retVal = 0;
488 
489  switch(sectionID)
490  {
491  case SPI_FLASH_SECTION_UBOOT: retVal = 0x00080000; break;
492  case SPI_FLASH_SECTION_KERNEL: retVal = 0x00C00000; break;
493  case SPI_FLASH_SECTION_LICENSE: retVal = 0x00040000; break;
494  case SPI_FLASH_SECTION_MCSINFO: retVal = 0x00040000; break;
495  case SPI_FLASH_SECTION_MAC: retVal = 0x00040000; break;
496  case SPI_FLASH_SECTION_SERIAL: retVal = 0x00040000; break;
497  case SPI_FLASH_SECTION_TOTAL: retVal = mSize; break;
498 
499  default:
500  break;
501  }
502 
503  return retVal;
504 }
505 
507 {
508  uint32_t retVal = 0xffffffff;
509 
510  switch(sectionID)
511  {
512  case SPI_FLASH_SECTION_UBOOT: retVal = 0x00000000; break;
513  case SPI_FLASH_SECTION_KERNEL: retVal = 0x00100000; break;
514  case SPI_FLASH_SECTION_LICENSE: retVal = 0x01F00000; break;
515  case SPI_FLASH_SECTION_MCSINFO: retVal = 0x01F40000; break;
516  case SPI_FLASH_SECTION_MAC: retVal = 0x01F80000; break;
517  case SPI_FLASH_SECTION_SERIAL: retVal = 0x01FC0000; break;
518  case SPI_FLASH_SECTION_TOTAL: retVal = 0; break;
519 
520  default:
521  break;
522  }
523 
524  return retVal;
525 }
526 
527 bool CNTV2AxiSpiFlash::NTV2DeviceOk()
528 {
529  if (mDevice.IsOpen() == false)
530  return false;
531  if (DeviceSupported(mDevice.GetDeviceID()) == false)
532  return false;
533 
534  return true;
535 }
536 
537 void CNTV2AxiSpiFlash::SpiReset()
538 {
539  if (!NTV2DeviceOk())
540  return;
541 
542  mDevice.WriteRegister(mSpiSlaveReg, 0x0);
543  SpiResetFifos();
544 
545  // make sure in 32bit mode
546  uint8_t bankAddressVal=0;
547 }
548 
549 bool CNTV2AxiSpiFlash::SpiResetFifos()
550 {
551  if (!NTV2DeviceOk())
552  return false;
553 
554  uint32_t spi_ctrl_val=0x1e6;
555  return mDevice.WriteRegister(mSpiControlReg, spi_ctrl_val);
556 }
557 
558 void CNTV2AxiSpiFlash::SpiEnableWrite(bool enable)
559 {
560  // see AXI Quad SPI v3.2 guide page 105
561 
562  // 1 disable master transaction and reset fifos
563  make_spi_ready(mDevice);
564  SpiResetFifos();
565 
566  // 2 issue the write enable command
567  if (enable)
568  {
569  make_spi_ready(mDevice);
570  mDevice.WriteRegister(mSpiWriteReg, CYPRESS_FLASH_WRITEENABLE_COMMAND);
571  SpiSendFIFOData();
572  }
573  else
574  {
575  make_spi_ready(mDevice);
576  //mDevice.WriteRegister(mSpiWriteReg, CYPRESS_FLASH_WRITEDISABLE_COMMAND);
577  //SpiSendFIFOData();
578  }
579  // Steps 3,4,5,6
580  //SpiSendFIFOData();
581 }
582 
583 bool CNTV2AxiSpiFlash::FlashDeviceInfo(uint8_t& manufactureID, uint8_t& memInerfaceType,
584  uint8_t& memDensity, uint8_t& sectorArchitecture,
585  uint8_t& familyID)
586 {
587  vector<uint8_t> commandSequence;
588  commandSequence.push_back(CYPRESS_FLASH_READ_JEDEC_ID_COMMAND);
589 
590  vector<uint8_t> dummyInput;
591  vector<uint8_t> resultData;
592  bool result = SpiTransfer(commandSequence, dummyInput, resultData, 6);
593  if (result && resultData.size() >= 6)
594  {
595  manufactureID = resultData.at(0);
596  memInerfaceType = resultData.at(1);
597  memDensity = resultData.at(2);
598  sectorArchitecture = resultData.at(4);
599  familyID = resultData.at(5);
600  }
601 
602  return result;
603 }
604 
605 bool CNTV2AxiSpiFlash::FlashReadConfig(uint8_t& configValue)
606 {
607  vector<uint8_t> commandSequence;
608  commandSequence.push_back(CYPRESS_FLASH_READ_CONFIG_COMMAND);
609 
610  vector<uint8_t> dummyInput;
611  vector<uint8_t> resultData;
612  bool result = SpiTransfer(commandSequence, dummyInput, resultData, 1);
613  if (result && resultData.size() > 0)
614  {
615  configValue = resultData.at(0);
616  }
617  return result;
618 }
619 
620 bool CNTV2AxiSpiFlash::FlashReadStatus(uint8_t& statusValue)
621 {
622  vector<uint8_t> commandSequence;
623  commandSequence.push_back(CYPRESS_FLASH_READ_STATUS_COMMAND);
624 
625  vector<uint8_t> dummyInput;
626  vector<uint8_t> resultData;
627  bool result = SpiTransfer(commandSequence, dummyInput, resultData, 1);
628  if (result && resultData.size() > 0)
629  {
630  statusValue = resultData.at(0);
631  }
632  return result;
633 }
634 
635 bool CNTV2AxiSpiFlash::FlashReadBankAddress(uint8_t& bankAddressVal)
636 {
637  if(mManufactureID != 0x20)
638  {
639  vector<uint8_t> commandSequence;
640  commandSequence.push_back(CYPRESS_FLASH_READBANK_COMMAND);
641 
642  vector<uint8_t> dummyInput;
643  vector<uint8_t> resultData;
644  bool result = SpiTransfer(commandSequence, dummyInput, resultData, 1);
645  if (result && resultData.size() > 0)
646  {
647  bankAddressVal = resultData.at(0);
648  }
649  return result;
650  }
651  return true;
652 }
653 
654 bool CNTV2AxiSpiFlash::FlashWriteBankAddress(const uint8_t bankAddressVal)
655 {
656  if (mManufactureID != 0x20)
657  {
658  vector<uint8_t> commandSequence;
659  commandSequence.push_back(CYPRESS_FLASH_WRITEBANK_COMMAND);
660 
661  vector<uint8_t> input;
662  input.push_back(bankAddressVal);
663  std::vector<uint8_t> dummyOutput;
664  return SpiTransfer(commandSequence, input, dummyOutput, 1);
665  }
666  return true;
667 }
668 
669 void CNTV2AxiSpiFlash::FlashFixAddress(const uint32_t address, std::vector<uint8_t>& commandSequence)
670 {
671  // turn the address into a bytes stream and change ordering to match what
672  // the flash chip wants to see (MSB)
673  commandSequence.push_back((address & (0xff000000)) >> 24);
674  commandSequence.push_back((address & (0x00ff0000)) >> 16);
675  commandSequence.push_back((address & (0x0000ff00)) >> 8);
676  commandSequence.push_back((address & (0x000000ff)) >> 0);
677 }
678 
679 void CNTV2AxiSpiFlash::SpiSendFIFOData()
680 {
681  // The step number is determined by the transaction type
682  // Step 3/4 issue chip select
683  make_spi_ready(mDevice);
684  mDevice.WriteRegister(mSpiSlaveReg, 0x00);
685 
686  // Step 4/5 enable the master transaction by setting 0x100 low in spi control reg
687  uint32_t spi_ctrl_val = 0;
688  make_spi_ready(mDevice);
689  mDevice.ReadRegister(mSpiControlReg, spi_ctrl_val);
690  spi_ctrl_val &= ~0x100;
691  make_spi_ready(mDevice);
692  mDevice.WriteRegister(mSpiControlReg, spi_ctrl_val);
693 
694  bool txFIFOEmpty = false;
695  uint32_t notEmptyCount = 0;
696  while(!txFIFOEmpty && notEmptyCount < 1000)
697  {
698  uint32_t Tx_Empty = 0;
699  mDevice.ReadRegister(mSpiStatusReg, Tx_Empty, BIT(2), 2);
700  txFIFOEmpty = Tx_Empty ? true : false;
701  notEmptyCount++;
702  }
703 
704  // Step 5/6 deassert chip select
705  make_spi_ready(mDevice);
706  mDevice.WriteRegister(mSpiSlaveReg, 0x01);
707 
708  // Step 6/7 disable the master transaction by setting 0x100 high in spi control reg
709  make_spi_ready(mDevice);
710  mDevice.ReadRegister(mSpiControlReg, spi_ctrl_val);
711  spi_ctrl_val |= 0x100;
712  make_spi_ready(mDevice);
713  mDevice.WriteRegister(mSpiControlReg, spi_ctrl_val);
714 }
715 
716 bool CNTV2AxiSpiFlash::SpiTransfer(std::vector<uint8_t> commandSequence,
717  const std::vector<uint8_t> inputData,
718  std::vector<uint8_t>& outputData, uint32_t maxByteCutoff)
719 {
720  // see AXI Quad SPI v3.2 guide page 106
721 
722  bool retVal = true;
723 
724  if (commandSequence.empty())
725  return false;
726 
727  make_spi_ready(mDevice);
728 
729  // 1 Reset
730  SpiResetFifos();
731 
732  // 2 issue the command & arguments
733  uint32_t dummyVal = 0;
734  uint32_t numDummyBytes = 0;
735  for(unsigned i=0;i<commandSequence.size();++i)
736  {
737  make_spi_ready(mDevice);
738  mDevice.WriteRegister(mSpiWriteReg, (ULWord)commandSequence.at(i));
739  numDummyBytes++;
740  }
741 
742  if(commandSequence.at(0) == CYPRESS_FLASH_READFAST_COMMAND)
743  numDummyBytes++;
744 
745  // 3 Load data(write) or dummy bytes(read)
746  if (commandSequence.at(0) == CYPRESS_FLASH_SECTOR4K_ERASE_COMMAND ||
747  commandSequence.at(0) == CYPRESS_FLASH_SECTOR_ERASE_COMMAND)
748  {
749  // steps 3,4,5,6
750  SpiSendFIFOData();
751  }
752  else if (inputData.empty() == false)
753  {
754  // a write command
755  // 3 load data into fifo
756  uint32_t maxWrite = maxByteCutoff;
757  if (maxWrite > inputData.size())
758  maxWrite = (uint32_t)inputData.size();
759 
760  for(uint32_t i=0;i<maxWrite;++i)
761  {
762  make_spi_ready(mDevice);
763  mDevice.WriteRegister(mSpiWriteReg, inputData.at(i));
764  }
765 
766  // 4,5,6,7
767  SpiSendFIFOData();
768  }
769  else
770  {
771  // a read command
772  // 3 load fifo with dummy bytes
773  uint32_t val = 0;
774  for(uint32_t i=0;i<=maxByteCutoff;++i)
775  {
776  make_spi_ready(mDevice);
777  mDevice.WriteRegister(mSpiWriteReg, 0x0); //dummy
778  }
779 
780  // 4,5,6,7
781  SpiSendFIFOData();
782  make_spi_ready(mDevice);
783 
784  // 8 read data from fifo
785  bool rxFIFOEmpty = false;
786  uint32_t notEmptyCount = 0;
787  while(!rxFIFOEmpty && notEmptyCount < 1000)
788  {
789  make_spi_ready(mDevice);
790  mDevice.ReadRegister(mSpiReadReg, val);
791 
792  // the first byte back is a dummy when reading flash
793  if (notEmptyCount >= numDummyBytes && notEmptyCount <= (maxByteCutoff + numDummyBytes))
794  {
795  outputData.push_back(val);
796  //printf("Pushed %X\n", val);
797  }
798  else
799  {
800  //printf("Dumped %x\n", val);
801  }
802  uint32_t Rx_Empty = 0;
803  mDevice.ReadRegister(mSpiStatusReg, Rx_Empty, BIT(0), 0);
804  rxFIFOEmpty = Rx_Empty ? true : false;
805  //printf("Not empty Rx_Empty = %d, count = %d\n", Rx_Empty, notEmptyCount);
806  notEmptyCount++;
807  }
808  }
809 
810  return retVal;
811 }
CYPRESS_FLASH_WRITEBANK_COMMAND
const uint32_t CYPRESS_FLASH_WRITEBANK_COMMAND
Definition: ntv2spiinterface.cpp:90
CYPRESS_FLASH_READFAST_COMMAND
const uint32_t CYPRESS_FLASH_READFAST_COMMAND
Definition: ntv2spiinterface.cpp:86
kProgramStateEraseBank4
@ kProgramStateEraseBank4
Definition: ntv2publicinterface.h:4840
verify_vectors
static bool verify_vectors(const std::vector< uint8_t > &dataWritten, const std::vector< uint8_t > &dataRead, bool verbose=false)
Definition: ntv2spiinterface.cpp:21
address_for_sector
static uint32_t address_for_sector(uint32_t sectorSizeBytes, uint32_t sector)
Definition: ntv2spiinterface.cpp:148
CNTV2SpiFlash::mVerbose
bool mVerbose
Definition: ntv2spiinterface.h:42
kRegBoardID
@ kRegBoardID
Definition: ntv2publicinterface.h:124
CNTV2MacDriverInterface::ReadRegister
virtual bool ReadRegister(const ULWord inRegNum, ULWord &outValue, const ULWord inMask=0xFFFFFFFF, const ULWord inShift=0)
Reads all or part of the 32-bit contents of a specific register (real or virtual) on the AJA device....
Definition: ntv2macdriverinterface.cpp:709
CNTV2AxiSpiFlash::Offset
virtual uint32_t Offset(SpiFlashSection sectionID=SPI_FLASH_SECTION_TOTAL)
Definition: ntv2spiinterface.cpp:506
has_4k_start_sectors
bool has_4k_start_sectors(const uint32_t reportedSectorSize)
Definition: ntv2spiinterface.cpp:96
CNTV2AxiSpiFlash::DeviceSupported
static bool DeviceSupported(NTV2DeviceID deviceId)
Definition: ntv2spiinterface.cpp:247
kVRegFlashState
@ kVRegFlashState
Definition: ntv2virtualregisters.h:302
SPI_FLASH_SECTION_TOTAL
@ SPI_FLASH_SECTION_TOTAL
Definition: ntv2spiinterface.h:21
DEVICE_ID_IOIP_2022
@ DEVICE_ID_IOIP_2022
See Io IP.
Definition: ntv2enums.h:38
NTV2DeviceID
NTV2DeviceID
Identifies a specific AJA NTV2 device model number. The NTV2DeviceID is actually the PROM part number...
Definition: ntv2enums.h:20
SPI_FLASH_SECTION_SERIAL
@ SPI_FLASH_SECTION_SERIAL
Definition: ntv2spiinterface.h:19
CNTV2AxiSpiFlash::Size
virtual uint32_t Size(SpiFlashSection sectionID=SPI_FLASH_SECTION_TOTAL)
Definition: ntv2spiinterface.cpp:485
kVRegFlashSize
@ kVRegFlashSize
Definition: ntv2virtualregisters.h:300
ntv2registersmb.h
Defines the KonaIP/IoIP registers.
ntv2mcsfile.h
Declares the CNTV2MCSfile class.
kProgramStateProgramBank3
@ kProgramStateProgramBank3
Definition: ntv2publicinterface.h:4838
CYPRESS_FLASH_READBANK_COMMAND
const uint32_t CYPRESS_FLASH_READBANK_COMMAND
Definition: ntv2spiinterface.cpp:89
ULWord
uint32_t ULWord
Definition: ajatypes.h:246
CYPRESS_FLASH_WRITEDISABLE_COMMAND
const uint32_t CYPRESS_FLASH_WRITEDISABLE_COMMAND
Definition: ntv2spiinterface.cpp:83
DEVICE_ID_KONAXM
@ DEVICE_ID_KONAXM
See KONA XM™.
Definition: ntv2enums.h:78
AsNTV2DriverInterfaceRef
#define AsNTV2DriverInterfaceRef(_x_)
Definition: ntv2driverinterface.h:48
DEVICE_ID_KONAX
@ DEVICE_ID_KONAX
See KONA X.
Definition: ntv2enums.h:77
programstate_for_address
ProgramState programstate_for_address(uint32_t address, int mode)
Definition: ntv2spiinterface.cpp:169
print_flash_status_final
void print_flash_status_final(const string &label)
Definition: ntv2spiinterface.cpp:75
CYPRESS_FLASH_READ_JEDEC_ID_COMMAND
const uint32_t CYPRESS_FLASH_READ_JEDEC_ID_COMMAND
Definition: ntv2spiinterface.cpp:93
CYPRESS_FLASH_SECTOR_ERASE_COMMAND
const uint32_t CYPRESS_FLASH_SECTOR_ERASE_COMMAND
Definition: ntv2spiinterface.cpp:94
CNTV2AxiSpiFlash::Erase
virtual bool Erase(const uint32_t address, uint32_t bytes)
Definition: ntv2spiinterface.cpp:371
UWord
uint16_t UWord
Definition: ajatypes.h:244
sector_for_address
static uint32_t sector_for_address(uint32_t sectorSizeBytes, uint32_t address)
Definition: ntv2spiinterface.cpp:121
erase_cmd_for_sector
static uint32_t erase_cmd_for_sector(const uint32_t reportedSectorSize, const uint32_t sector)
Definition: ntv2spiinterface.cpp:113
CNTV2Card
I interrogate and control an AJA video/audio capture/playout device.
Definition: ntv2card.h:262
SpiFlashSection
SpiFlashSection
Definition: ntv2spiinterface.h:12
SPI_FLASH_SECTION_MCSINFO
@ SPI_FLASH_SECTION_MCSINFO
Definition: ntv2spiinterface.h:17
kProgramStateVerifyBank3
@ kProgramStateVerifyBank3
Definition: ntv2publicinterface.h:4839
CNTV2AxiSpiFlash::CNTV2AxiSpiFlash
CNTV2AxiSpiFlash(int index=0, bool verbose=false)
Definition: ntv2spiinterface.cpp:192
ProgramState
ProgramState
Definition: ntv2publicinterface.h:4829
DEVICE_ID_IOIP_2110
@ DEVICE_ID_IOIP_2110
See Io IP.
Definition: ntv2enums.h:39
CYPRESS_FLASH_READ_STATUS_COMMAND
const uint32_t CYPRESS_FLASH_READ_STATUS_COMMAND
Definition: ntv2spiinterface.cpp:84
kVRegFlashStatus
@ kVRegFlashStatus
Definition: ntv2virtualregisters.h:301
CYPRESS_FLASH_SECTOR4K_ERASE_COMMAND
const uint32_t CYPRESS_FLASH_SECTOR4K_ERASE_COMMAND
Definition: ntv2spiinterface.cpp:91
SPI_FLASH_SECTION_UBOOT
@ SPI_FLASH_SECTION_UBOOT
Definition: ntv2spiinterface.h:14
kProgramStateProgramBank4
@ kProgramStateProgramBank4
Definition: ntv2publicinterface.h:4841
size_for_sector_number
static uint32_t size_for_sector_number(const uint32_t reportedSectorSize, const uint32_t sector)
Definition: ntv2spiinterface.cpp:105
SPI_FLASH_SECTION_MAC
@ SPI_FLASH_SECTION_MAC
Definition: ntv2spiinterface.h:18
ntv2spiinterface.h
Declares the CNTV2SpiFlash and CNTV2AxiSpiFlash classes.
wait_for_flash_status_ready
#define wait_for_flash_status_ready()
Definition: ntv2spiinterface.cpp:190
CNTV2AxiSpiFlash::Read
virtual bool Read(const uint32_t address, std::vector< uint8_t > &data, uint32_t maxBytes=1)
Definition: ntv2spiinterface.cpp:263
make_spi_ready
uint32_t make_spi_ready(CNTV2Card &device)
Definition: ntv2spiinterface.cpp:183
kProgramStateVerifyBank4
@ kProgramStateVerifyBank4
Definition: ntv2publicinterface.h:4842
kProgramStateFinished
@ kProgramStateFinished
Definition: ntv2publicinterface.h:4836
true
#define true
Definition: ntv2devicefeatures.h:26
CNTV2DriverInterface::GetDeviceID
virtual NTV2DeviceID GetDeviceID(void)
Definition: ntv2driverinterface.cpp:371
CNTV2AxiSpiFlash::Verify
virtual bool Verify(const uint32_t address, const std::vector< uint8_t > &dataWritten)
Definition: ntv2spiinterface.cpp:474
CNTV2SpiFlash
Definition: ntv2spiinterface.h:24
SPI_FLASH_SECTION_LICENSE
@ SPI_FLASH_SECTION_LICENSE
Definition: ntv2spiinterface.h:16
CYPRESS_FLASH_PAGE_PROGRAM_COMMAND
const uint32_t CYPRESS_FLASH_PAGE_PROGRAM_COMMAND
Definition: ntv2spiinterface.cpp:87
print_flash_status
void print_flash_status(const string &label, uint32_t curValue, uint32_t maxValue, uint32_t &lastPercentage)
Definition: ntv2spiinterface.cpp:62
CNTV2AxiSpiFlash::Write
virtual bool Write(const uint32_t address, const std::vector< uint8_t > data, uint32_t maxBytes=1)
Definition: ntv2spiinterface.cpp:310
BIT
#define BIT(_x_)
Definition: ajatypes.h:654
CYPRESS_FLASH_WRITEENABLE_COMMAND
const uint32_t CYPRESS_FLASH_WRITEENABLE_COMMAND
Definition: ntv2spiinterface.cpp:85
DEVICE_ID_IOIP_2110_RGB12
@ DEVICE_ID_IOIP_2110_RGB12
See Io IP.
Definition: ntv2enums.h:40
CYPRESS_FLASH_READ_CONFIG_COMMAND
const uint32_t CYPRESS_FLASH_READ_CONFIG_COMMAND
Definition: ntv2spiinterface.cpp:92
CNTV2MacDriverInterface::WriteRegister
virtual bool WriteRegister(const ULWord inRegNum, const ULWord inValue, const ULWord inMask=0xFFFFFFFF, const ULWord inShift=0)
Updates or replaces all or part of the 32-bit contents of a specific register (real or virtual) on th...
Definition: ntv2macdriverinterface.cpp:754
kProgramStateEraseBank3
@ kProgramStateEraseBank3
Definition: ntv2publicinterface.h:4837
CNTV2AxiSpiFlash::~CNTV2AxiSpiFlash
virtual ~CNTV2AxiSpiFlash()
Definition: ntv2spiinterface.cpp:243
SPI_FLASH_SECTION_KERNEL
@ SPI_FLASH_SECTION_KERNEL
Definition: ntv2spiinterface.h:15