1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Diagnostics; 9 using System.IO; 10 using System.Net.Sockets; 11 using System.Threading; 12 using Antmicro.Renode.Core; 13 using Antmicro.Renode.Exceptions; 14 using Antmicro.Renode.Logging; 15 using Antmicro.Renode.Peripherals.I2C; 16 using Antmicro.Renode.Sockets; 17 using Antmicro.Renode.Time; 18 using Antmicro.Renode.Utilities; 19 #if !PLATFORM_WINDOWS 20 using Mono.Unix; 21 #endif 22 23 namespace Antmicro.Renode.Extensions.Mocks 24 { 25 public static class HPSHostControllerExtensions 26 { AddHPSHostController(this Emulation emulation, STM32F7_I2C device, string name = R)27 public static void AddHPSHostController(this Emulation emulation, STM32F7_I2C device, string name = "HPSHostController") 28 { 29 emulation.HostMachine.AddHostMachineElement(new HPSHostController(device), name); 30 } 31 } 32 33 public class HPSHostController : IHostMachineElement 34 { HPSHostController(STM32F7_I2C device)35 public HPSHostController(STM32F7_I2C device) 36 { 37 currentSlave = device; 38 } 39 FlashMCU(ReadFilePath path)40 public void FlashMCU(ReadFilePath path) 41 { 42 var address = 0; 43 var data = new byte[256 + 5]; 44 data[0] = ((byte)Commands.WriteMemory << 6) | (byte)MemoryBanks.MCUFlash; 45 46 var bytes = File.ReadAllBytes(path); 47 var left = bytes.Length; 48 49 while(left > 0) 50 { 51 var batchSize = Math.Min(left, 256); 52 Array.Copy(bytes, address, data, 5, batchSize); 53 data[1] = (byte)(address >> 24); 54 data[2] = (byte)(address >> 16); 55 data[3] = (byte)(address >> 8); 56 data[4] = (byte)address; 57 IssueCommand(data); 58 59 currentSlave.Read(0); 60 // Poll until all the bytes are written 61 PollForRegisterBit(RegisterBitName.RXNE); 62 63 address += 256; 64 left -= batchSize; 65 } 66 } 67 CommandEraseSPIFlash()68 public void CommandEraseSPIFlash() 69 { 70 var data = new byte[] { 71 ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.SystemCommands, 72 0x0, 73 (byte)CommonSystemCommands.EraseSPIFlash, 74 0x0 75 }; 76 IssueCommand(data); 77 currentSlave.Read(0); 78 } 79 CommandEraseStage1()80 public void CommandEraseStage1() 81 { 82 var data = new byte[] { 83 ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.SystemCommands, 84 0x0, 85 (byte)CommonSystemCommands.EraseStage1, 86 0x0 87 }; 88 IssueCommand(data); 89 currentSlave.Read(0); 90 } 91 CommandLaunchApplication()92 public void CommandLaunchApplication() 93 { 94 var data = new byte[] { 95 ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.SystemCommands, 96 0x0, 97 (byte)CommonSystemCommands.LaunchApplication, 98 0x0 99 }; 100 IssueCommand(data); 101 currentSlave.Read(0); 102 } 103 CommandLaunchStage1()104 public void CommandLaunchStage1() 105 { 106 var data = new byte[] { 107 ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.SystemCommands, 108 0x0, 109 (byte)CommonSystemCommands.LaunchStage1, 110 0x0 111 }; 112 IssueCommand(data); 113 currentSlave.Read(0); 114 } 115 CommandIssueReset()116 public void CommandIssueReset() 117 { 118 var data = new byte[] { 119 ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.SystemCommands, 120 0x0, 121 (byte)CommonSystemCommands.Reset, 122 0x0 123 }; 124 IssueCommand(data); 125 currentSlave.Read(0); 126 } 127 SetNumberOfCameraTestIterations(int count)128 public void SetNumberOfCameraTestIterations(int count) 129 { 130 var data = new byte[] { 131 ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.CameraTestIterations, 132 0x0, 133 (byte)count, 134 0x0 135 }; 136 IssueCommand(data); 137 currentSlave.Read(0); 138 } 139 SetOptionBytes(int value)140 public void SetOptionBytes(int value) 141 { 142 var data = new byte[] { 143 ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.OptionBytesConfiguration, 144 0x0, 145 (byte)(value >> 8), 146 (byte)value, 147 0x0 148 }; 149 IssueCommand(data); 150 currentSlave.Read(0); 151 } 152 153 // Register 0: ReadMagicNumber(TimeInterval timeInterval)154 public byte[] ReadMagicNumber(TimeInterval timeInterval) 155 { 156 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.MagicNumber}); 157 return GetBytesFromSlave(2, timeInterval); 158 } 159 160 // Register 1: ReadHardwareVersion(TimeInterval timeInterval)161 public byte[] ReadHardwareVersion(TimeInterval timeInterval) 162 { 163 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.HardwareVersion }); 164 return GetBytesFromSlave(2, timeInterval); 165 } 166 167 // Register 2: ReadSystemStatus(TimeInterval timeInterval)168 public string[,] ReadSystemStatus(TimeInterval timeInterval) 169 { 170 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.SystemStatus }); 171 return FormatSystemStatus(GetBytesFromSlave(2, timeInterval)); 172 } 173 174 // Register 5: ReadMemoryBankAvailable(TimeInterval timeInterval)175 public byte[] ReadMemoryBankAvailable(TimeInterval timeInterval) 176 { 177 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.MemoryBankAvailable }); 178 return GetBytesFromSlave(2, timeInterval); 179 } 180 181 // Register 6: ReadError(TimeInterval timeInterval)182 public string[,] ReadError(TimeInterval timeInterval) 183 { 184 return FormatCommonErrorStatus(ReadErrorBytes(timeInterval)); 185 } 186 ReadErrorBytes(TimeInterval timeInterval)187 public byte[] ReadErrorBytes(TimeInterval timeInterval) 188 { 189 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.Error }); 190 return GetBytesFromSlave(2, timeInterval); 191 } 192 193 // Register 7: should be RW ReadEnabledFeatures(TimeInterval timeInterval)194 public string[,] ReadEnabledFeatures(TimeInterval timeInterval) 195 { 196 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.Enabledfeatures }); 197 return FormatEnabledFeatures(GetBytesFromSlave(2, timeInterval)); 198 } 199 200 // Register 8: ReadFeature0StatusBits(TimeInterval timeInterval)201 public string[,] ReadFeature0StatusBits(TimeInterval timeInterval) 202 { 203 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.Feature0 }); 204 return FormatFeature(GetBytesFromSlave(2, timeInterval)); 205 } 206 207 // Register 9: ReadFeature1StatusBits(TimeInterval timeInterval)208 public string[,] ReadFeature1StatusBits(TimeInterval timeInterval) 209 { 210 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.Feature1 }); 211 return FormatFeature(GetBytesFromSlave(2, timeInterval)); 212 } 213 214 // Register 10: ReadFirmwareVersionHigh(TimeInterval timeInterval)215 public byte[] ReadFirmwareVersionHigh(TimeInterval timeInterval) 216 { 217 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.FirmwareVersionHIGH }); 218 return GetBytesFromSlave(2, timeInterval); 219 } 220 221 // Register 11: ReadFirmwareVersionLow(TimeInterval timeInterval)222 public byte[] ReadFirmwareVersionLow(TimeInterval timeInterval) 223 { 224 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.FirmwareVersionLOW }); 225 return GetBytesFromSlave(2, timeInterval); 226 } 227 228 // Register 12: ReadFPGABootCount(TimeInterval timeInterval)229 public byte[] ReadFPGABootCount(TimeInterval timeInterval) 230 { 231 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.FPGABootCount }); 232 return GetBytesFromSlave(2, timeInterval); 233 } 234 235 // Register 13: ReadFPGALoopCount(TimeInterval timeInterval)236 public byte[] ReadFPGALoopCount(TimeInterval timeInterval) 237 { 238 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.FPGALoopCount }); 239 return GetBytesFromSlave(2, timeInterval); 240 } 241 242 // Register 14: ReadFPGAROMVersion(TimeInterval timeInterval)243 public byte[] ReadFPGAROMVersion(TimeInterval timeInterval) 244 { 245 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.FPGAROMVersion }); 246 return GetBytesFromSlave(2, timeInterval); 247 } 248 249 // Register 15: ReadSPIFlashStatus(TimeInterval timeInterval)250 public byte[] ReadSPIFlashStatus(TimeInterval timeInterval) 251 { 252 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.SPIFlashStatusBits }); 253 return GetBytesFromSlave(2, timeInterval); 254 } 255 256 // Register 16: ReadDebugIndex(TimeInterval timeInterval)257 public byte[] ReadDebugIndex(TimeInterval timeInterval) 258 { 259 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.DebugIndex }); 260 return GetBytesFromSlave(2, timeInterval); 261 } 262 263 // Register 17: ReadDebugValue(TimeInterval timeInterval)264 public byte[] ReadDebugValue(TimeInterval timeInterval) 265 { 266 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.DebugValue }); 267 return GetBytesFromSlave(2, timeInterval); 268 } 269 270 // Register 18: ReadCameraConfiguration(TimeInterval timeInterval)271 public string[,] ReadCameraConfiguration(TimeInterval timeInterval) 272 { 273 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.CameraConfiguration }); 274 return FormatCameraConfiguration(GetBytesFromSlave(2, timeInterval)); 275 } 276 277 // Register 19: ReadCameraTestIterations(TimeInterval timeInterval)278 public byte[] ReadCameraTestIterations(TimeInterval timeInterval) 279 { 280 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.CameraTestIterations }); 281 return GetBytesFromSlave(2, timeInterval); 282 } 283 284 // Register 20: ReadOptionBytes(TimeInterval timeInterval)285 public byte[] ReadOptionBytes(TimeInterval timeInterval) 286 { 287 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.OptionBytesConfiguration }); 288 return GetBytesFromSlave(2, timeInterval); 289 } 290 291 // Register 21: ReadPartIDs(TimeInterval timeInterval)292 public byte[] ReadPartIDs(TimeInterval timeInterval) 293 { 294 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.PartIDs }); 295 return GetBytesFromSlave(20, timeInterval); 296 } 297 298 // Register 22: ReadPreviousCrash(TimeInterval timeInterval)299 public byte[] ReadPreviousCrash(TimeInterval timeInterval) 300 { 301 IssueCommand(new byte[] { ((byte)Commands.RegisterAccess << 6) | (byte)RegisterAccessType.PreviousCrash }); 302 // PreviousCrash register can return up to 256 bytes, but we are limited to 255 bytes because the NBYTES field 303 // in STM32F7_I2C model is 8 bytes long. 304 return GetBytesFromSlave(255, timeInterval); 305 } 306 GetBytesFromSlave(int count, TimeInterval timeInterval)307 private byte[] GetBytesFromSlave(int count, TimeInterval timeInterval) 308 { 309 if(currentSlave == null) 310 { 311 throw new RecoverableException("Cannot read data because no slave is connected."); 312 } 313 var result = new byte[count]; 314 var sw = new Stopwatch(); 315 sw.Start(); 316 do 317 { 318 result = currentSlave.Read(count); 319 if(result.Length == count) 320 { 321 break; 322 } 323 if(sw.Elapsed > timeInterval.ToTimeSpan()) 324 { 325 currentSlave.Read(0); 326 result = new byte[count]; 327 break; 328 } 329 } while(result.Length == 0); 330 return result; 331 } 332 333 // This method is for getting OA1EN, 334 // returns true when OA1EN is enabled. OA1ENEnabled()335 private bool OA1ENEnabled() 336 { 337 return currentSlave.OwnAddress1Enabled; 338 } 339 340 // This method is for getting RXEN, 341 // returns true when the buffer is empty. RXNECleared()342 private bool RXNECleared() 343 { 344 return !currentSlave.RxNotEmpty; 345 } 346 PollForRegisterBit(RegisterBitName bitName)347 private void PollForRegisterBit(RegisterBitName bitName) 348 { 349 int i = 0; 350 Func<bool> registerAccess; 351 switch(bitName) 352 { 353 case RegisterBitName.OA1EN: 354 registerAccess = OA1ENEnabled; 355 break; 356 case RegisterBitName.RXNE: 357 registerAccess = RXNECleared; 358 break; 359 default: 360 throw new RecoverableException("Register bit name does not exist."); 361 } 362 while(!registerAccess() && i < 8) 363 { 364 Thread.Sleep(500); 365 i++; 366 } 367 } 368 PollForError(TimeInterval timeInterval)369 private void PollForError(TimeInterval timeInterval) 370 { 371 for(int i = 0; i < 3; i++) 372 { 373 var errors = ReadErrorBytes(timeInterval); 374 if(errors[0] + errors[1] != 0x00) 375 { 376 break; 377 } 378 Thread.Sleep(1000); 379 } 380 } 381 382 // When we need to read for more than 255 bytes, we will need this method GetLongBytes(int count, TimeInterval timeInterval)383 private byte[] GetLongBytes(int count, TimeInterval timeInterval) 384 { 385 var result = new byte[count]; 386 var rounds = count / ReadChunkSize; 387 var remainder = count % ReadChunkSize; 388 for(int i = 0; i <= rounds; i++) 389 { 390 int toRead = i == rounds ? remainder : ReadChunkSize; 391 Array.Copy(GetBytesFromSlave(toRead, timeInterval), 0, result, i * ReadChunkSize, toRead); 392 } 393 return result; 394 } 395 StartSocketServer(TimeInterval timeInterval)396 public void StartSocketServer(TimeInterval timeInterval) 397 { 398 #if PLATFORM_WINDOWS 399 throw new RecoverableException("This method is not supported on Windows"); 400 #else 401 string path = "/tmp/i2c.sock"; 402 if(File.Exists(path)) 403 { 404 File.Delete(path); 405 } 406 this.Log(LogLevel.Info, "Server starting at{0}", path); 407 var socket = SocketsManager.Instance.AcquireSocket(this, AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified, new UnixEndPoint(path)); 408 this.Log(LogLevel.Info, "Connection established"); 409 410 currentSlave.Read(0); 411 var connection = socket.Accept(); 412 413 var commandBuffer = new byte[(int)NumberOfBytes.MessageType]; 414 var prevWrite = false; 415 var length = 0; 416 417 while(SocketConnected(connection)) 418 { 419 PollForRegisterBit(RegisterBitName.OA1EN); 420 try 421 { 422 PollForSocketData(connection, commandBuffer); 423 } 424 catch(Exception e) 425 { 426 this.Log(LogLevel.Error, "{0} Exception caught.", e); 427 return; 428 } 429 switch((SocketI2CMessageType)commandBuffer[0]) 430 { 431 case SocketI2CMessageType.Stop: 432 currentSlave.FinishTransmission(); 433 break; 434 // Parse read command 435 case SocketI2CMessageType.Read: 436 prevWrite = false; 437 length = GetLength(connection); 438 439 byte[] dataToSend = GetLongBytes(length, timeInterval); 440 try 441 { 442 PollForSocketData(connection, dataToSend, true); 443 } 444 catch(Exception e) 445 { 446 this.Log(LogLevel.Error, "{0} Exception caught.", e); 447 return; 448 } 449 break; 450 // Parse write command 451 case SocketI2CMessageType.Write: 452 // Seems that the slave needs a read operation 453 // to flush out the bits written 454 if(prevWrite) 455 { 456 currentSlave.Read(0); 457 PollForRegisterBit(RegisterBitName.RXNE); 458 } 459 prevWrite = true; 460 length = GetLength(connection); 461 byte[] data = new byte[length]; 462 try 463 { 464 PollForSocketData(connection, data); 465 } 466 catch(Exception e) 467 { 468 this.Log(LogLevel.Error, "{0} Exception caught.", e); 469 return; 470 } 471 if(data.Length == 1 && data[0] == 0x86) 472 { 473 PollForError(timeInterval); 474 Thread.Sleep(10); 475 } 476 IssueCommand(data); 477 break; 478 } 479 } 480 #endif 481 } 482 GetLength(Socket connection)483 private int GetLength(Socket connection) 484 { 485 var lengthBytes = new byte[(int)NumberOfBytes.LengthBytes]; 486 PollForSocketData(connection, lengthBytes); 487 var combined = (int)lengthBytes[0] << 8 | lengthBytes[1]; 488 return combined; 489 } 490 PollForSocketData(Socket connection, byte[] data, bool send = false)491 private void PollForSocketData(Socket connection, byte[] data, bool send = false) 492 { 493 var tempLength = 0; 494 var sendReceive = (send == true) 495 ? connection.Send 496 : (Func<byte[], int, int, SocketFlags, int>)connection.Receive; 497 498 while(tempLength < data.Length) 499 { 500 tempLength += sendReceive(data, tempLength, data.Length - tempLength, SocketFlags.None); 501 } 502 } 503 IssueCommand(byte[] data)504 private void IssueCommand(byte[] data) 505 { 506 if(currentSlave == null) 507 { 508 throw new RecoverableException("Cannot issue command because no slave is connected."); 509 } 510 currentSlave.Write(data); 511 } 512 SocketConnected(Socket s)513 private bool SocketConnected(Socket s) 514 { 515 bool dataAvailableForReading = s.Poll(1000, SelectMode.SelectRead); 516 bool availableBytesIsEmpty = (s.Available == 0); 517 return !(dataAvailableForReading && availableBytesIsEmpty); 518 } 519 FormatSystemStatus(byte[] data)520 private string[,] FormatSystemStatus(byte[] data) 521 { 522 if(data.Length != 2) 523 { 524 throw new RecoverableException(string.Format("Received {0} bytes of data (expected 2) from System Status register.", data.Length)); 525 } 526 var table = new Table().AddRow("Value", "Bit", "Name", "Description"); 527 table.AddRow(string.Empty, "15", string.Empty, string.Empty); 528 table.AddRow(string.Empty, "14", string.Empty, string.Empty); 529 table.AddRow((data[0] & 0x20) >> 5 == 1 ? "1" : "0", "13", "ONE_TIME_INIT", "Whether the one_time_init binary is running"); 530 table.AddRow((data[0] & 0x10) >> 4 == 1 ? "1" : "0", "12", "STAGE0_PERM_LOCKED", "Whether stage0 has been made permanently read-only"); 531 table.AddRow((data[0] & 0x8) >> 3 == 1 ? "1" : "0", "11", "STAGE0_LOCKED", "Whether stage0 has been make read-only"); 532 table.AddRow((data[0] & 0x4) >> 2 == 1 ? "1" : "0", "10", "CMDINPROGRESS", "A command is in-progress"); 533 table.AddRow((data[0] & 0x2) >> 1 == 1 ? "1" : "0", "9", "APPLREADY", "Application is running, and features may be enabled"); 534 table.AddRow((data[0] & 0x1) == 1 ? "1" : "0", "8", "APPLRUN", "Stage 1 has been launched, and is now running"); 535 table.AddRow(string.Empty, "7", string.Empty, string.Empty); 536 table.AddRow(string.Empty, "6", string.Empty, string.Empty); 537 table.AddRow((data[1] & 0x20) >> 5 == 1 ? "1" : "0", "5", "WPOFF", "Write protect pin off"); 538 table.AddRow((data[1] & 0x10) >> 4 == 1 ? "1" : "0", "4", "WPON", "Write protect pin on"); 539 table.AddRow((data[1] & 0x8) >> 3 == 1 ? "1" : "0", "3", "STAGE0", "Stage 0 is running"); 540 table.AddRow(string.Empty, "2", string.Empty, string.Empty); 541 table.AddRow((data[1] & 0x2) >> 1 == 1 ? "1" : "0", "1", "FAULT", "System has an unrecoverable fault"); 542 table.AddRow((data[1] & 0x1) == 1 ? "1" : "0", "0", "OK", "System is operational"); 543 return table.ToArray(); 544 } 545 FormatCommonErrorStatus(byte[] data)546 private string[,] FormatCommonErrorStatus(byte[] data) 547 { 548 if(data.Length != 2) 549 { 550 throw new RecoverableException(string.Format("Received {0} bytes of data (expected 2) from Error Status register.", data.Length)); 551 } 552 var table = new Table().AddRow("Value", "Bit", "Name", "Description"); 553 table.AddRow(string.Empty, "15", string.Empty, string.Empty); 554 table.AddRow(string.Empty, "14", string.Empty, string.Empty); 555 table.AddRow(string.Empty, "13", string.Empty, string.Empty); 556 table.AddRow(string.Empty, "12", string.Empty, string.Empty); 557 table.AddRow(string.Empty, "11", string.Empty, string.Empty); 558 table.AddRow(string.Empty, "10", string.Empty, string.Empty); 559 table.AddRow((data[0] & 0x2) >> 1 == 1 ? "1" : "0", "9", "BUFORUN", "Buffer overrun"); 560 table.AddRow((data[0] & 0x1) == 1 ? "1" : "0", "8", "BUFNAVAIL", "Buffer not available"); 561 table.AddRow((data[1] & 0x80) >> 7 == 1 ? "1" : "0", "7", "I2CBADREQ", "A bad I2C request was made"); 562 table.AddRow((data[1] & 0x40) >> 6 == 1 ? "1" : "0", "6", "SPIFLASH", "SPI flash access failed"); 563 table.AddRow((data[1] & 0x20) >> 5 == 1 ? "1" : "0", "5", "CAMERA", "Camera not functional"); 564 table.AddRow((data[1] & 0x10) >> 4 == 1 ? "1" : "0", "4", "I2CORUN", "I2C overrun"); 565 table.AddRow((data[1] & 0x8) >> 3 == 1 ? "1" : "0", "3", "I2CBERR", "I2C bus error"); 566 table.AddRow((data[1] & 0x4) >> 2 == 1 ? "1" : "0", "2", "PANIC", "A panic occurred"); 567 table.AddRow((data[1] & 0x2) >> 1 == 1 ? "1" : "0", "1", "MCUFLASH", "Error writing to MCU flash"); 568 table.AddRow((data[1] & 0x1) == 1 ? "1" : "0", "0", "I2CURUN", "I2C underrun"); 569 return table.ToArray(); 570 } 571 FormatEnabledFeatures(byte[] data)572 private string[,] FormatEnabledFeatures(byte[] data) 573 { 574 if(data.Length != 2) 575 { 576 throw new RecoverableException(string.Format("Received {0} bytes of data (expected 2) from Enabled Features register.", data.Length)); 577 } 578 var table = new Table().AddRow("Value", "Bit", "Name", "Description"); 579 table.AddRow(string.Empty, "15", string.Empty, string.Empty); 580 table.AddRow(string.Empty, "14", string.Empty, string.Empty); 581 table.AddRow(string.Empty, "13", string.Empty, string.Empty); 582 table.AddRow(string.Empty, "12", string.Empty, string.Empty); 583 table.AddRow(string.Empty, "11", string.Empty, string.Empty); 584 table.AddRow(string.Empty, "10", string.Empty, string.Empty); 585 table.AddRow(string.Empty, "9", string.Empty, string.Empty); 586 table.AddRow(string.Empty, "8", string.Empty, string.Empty); 587 table.AddRow(string.Empty, "7", string.Empty, string.Empty); 588 table.AddRow(string.Empty, "6", string.Empty, string.Empty); 589 table.AddRow(string.Empty, "5", string.Empty, string.Empty); 590 table.AddRow(string.Empty, "4", string.Empty, string.Empty); 591 table.AddRow(string.Empty, "3", string.Empty, string.Empty); 592 table.AddRow(string.Empty, "2", string.Empty, string.Empty); 593 table.AddRow((data[1] & 0x2) >> 1 == 1 ? "1" : "0", "1", "FEATURE1", "Enable feature 1"); 594 table.AddRow((data[1] & 0x1) == 1 ? "1" : "0", "0", "FEATURE0", "Enable feature 0"); 595 return table.ToArray(); 596 } 597 FormatFeature(byte[] data)598 private string[,] FormatFeature(byte[] data) 599 { 600 if(data.Length != 2) 601 { 602 throw new RecoverableException(string.Format("Received {0} bytes of data (expected 2) from Feature N register.", data.Length)); 603 } 604 var table = new Table().AddRow("Value", "Bit", "Name", "Description"); 605 table.AddRow((data[0] & 0x80) >> 7 == 1 ? "1" : "0", "15", "USABLE", "The feature result is valid to use"); 606 table.AddRow(string.Empty, "14", string.Empty, string.Empty); 607 table.AddRow(string.Empty, "13", string.Empty, string.Empty); 608 table.AddRow(string.Empty, "12", string.Empty, string.Empty); 609 table.AddRow(string.Empty, "11", string.Empty, string.Empty); 610 table.AddRow(string.Empty, "10", string.Empty, string.Empty); 611 table.AddRow(string.Empty, "9", string.Empty, string.Empty); 612 table.AddRow(string.Empty, "8", string.Empty, string.Empty); 613 table.AddRow(string.Empty, "7", string.Empty, string.Empty); 614 table.AddRow(string.Empty, "6", string.Empty, string.Empty); 615 table.AddRow(string.Empty, "5", string.Empty, string.Empty); 616 table.AddRow(string.Empty, "4", string.Empty, string.Empty); 617 table.AddRow(string.Empty, "3", string.Empty, string.Empty); 618 table.AddRow(string.Empty, "2", string.Empty, string.Empty); 619 table.AddRow(string.Empty, "1", string.Empty, string.Empty); 620 table.AddRow(string.Empty, "0", string.Empty, string.Empty); 621 return table.ToArray(); 622 } 623 FormatCameraConfiguration(byte[] data)624 private string[,] FormatCameraConfiguration(byte[] data) 625 { 626 if(data.Length != 2) 627 { 628 throw new RecoverableException(string.Format("Received {0} bytes of data (expected 2) from Camera Configuration register.", data.Length)); 629 } 630 var table = new Table().AddRow("Value", "Bit", "Name", "Description"); 631 table.AddRow(string.Empty, "15", string.Empty, string.Empty); 632 table.AddRow(string.Empty, "14", string.Empty, string.Empty); 633 table.AddRow(string.Empty, "13", string.Empty, string.Empty); 634 table.AddRow(string.Empty, "12", string.Empty, string.Empty); 635 table.AddRow(string.Empty, "11", string.Empty, string.Empty); 636 table.AddRow(string.Empty, "10", string.Empty, string.Empty); 637 table.AddRow(string.Empty, "9", string.Empty, string.Empty); 638 table.AddRow(string.Empty, "8", string.Empty, string.Empty); 639 table.AddRow(string.Empty, "7", string.Empty, string.Empty); 640 table.AddRow(string.Empty, "6", string.Empty, string.Empty); 641 table.AddRow(string.Empty, "5", string.Empty, string.Empty); 642 table.AddRow(string.Empty, "4", string.Empty, string.Empty); 643 table.AddRow(string.Empty, "3", string.Empty, string.Empty); 644 table.AddRow(string.Empty, "2", string.Empty, string.Empty); 645 table.AddRow((data[1] & 0x2) >> 1 == 1 ? "1" : "0", "1", "ROTATION", "Rotation bit 1"); 646 table.AddRow((data[1] & 0x1) == 1 ? "1" : "0", "0", "ROTATION", "Rotation bit 0"); 647 return table.ToArray(); 648 } 649 650 private STM32F7_I2C currentSlave; 651 652 private const int ReadChunkSize = 255; 653 654 private enum Commands 655 { 656 WriteMemory = 0, 657 Unused = 1, 658 RegisterAccess = 2 659 } 660 661 private enum MemoryBanks 662 { 663 MCUFlash = 0, 664 SPIFlash = 1 665 } 666 667 private enum RegisterAccessType 668 { 669 MagicNumber = 0, 670 HardwareVersion = 1, 671 SystemStatus = 2, 672 SystemCommands = 3, 673 Unused = 4, 674 MemoryBankAvailable = 5, 675 Error = 6, 676 Enabledfeatures = 7, 677 Feature0 = 8, 678 Feature1 = 9, 679 FirmwareVersionHIGH = 10, 680 FirmwareVersionLOW = 11, 681 FPGABootCount = 12, 682 FPGALoopCount = 13, 683 FPGAROMVersion = 14, 684 SPIFlashStatusBits = 15, 685 DebugIndex = 16, 686 DebugValue = 17, 687 CameraConfiguration = 18, 688 CameraTestIterations = 19, 689 OptionBytesConfiguration = 20, 690 PartIDs = 21, 691 PreviousCrash = 22, 692 } 693 694 private enum CommonSystemCommands 695 { 696 Reset = 1, 697 LaunchStage1 = 2, 698 LaunchApplication = 4, 699 EraseStage1 = 8, 700 EraseSPIFlash = 16, 701 } 702 703 private enum RegisterBitName 704 { 705 OA1EN = 1, 706 RXNE = 2, 707 } 708 709 private enum SocketI2CMessageType 710 { 711 Stop = 0, 712 Read = 1, 713 Write = 2, 714 } 715 716 private enum NumberOfBytes 717 { 718 MessageType = 1, 719 LengthBytes = 2, 720 } 721 } 722 } 723