hwversion.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright (C) 2020 Michael McMaster <michael@codesrc.com>
  2. //
  3. // This file is part of SCSI2SD.
  4. //
  5. // SCSI2SD is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // SCSI2SD is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
  17. #include "hwversion.h"
  18. #include "stm32f2xx.h"
  19. #include "config.h"
  20. #include "time.h"
  21. // Store hardware version details to the "One Time Programmable" flash memory
  22. // This is 512 bytes that can only be written to ONCE and once only.
  23. // It can be read by dfu-util, so once we write the marker it can be
  24. // detected even when the firmware isn't running.
  25. // Values for STM32F401RE
  26. const size_t OTP_SIZE = 512;
  27. const size_t OTP_BLOCKS = 16;
  28. const size_t OTP_BLOCK_SIZE = OTP_SIZE / OTP_BLOCKS;
  29. const size_t OTP_BLOCK_NUM = 0;
  30. // Define some pointers for writing, but also to allow easy reading back values
  31. #define FLASH_OTP_BASE 0x1FFF7800
  32. const uint8_t *otp = (uint8_t*)(FLASH_OTP_BASE + OTP_BLOCK_NUM * OTP_BLOCK_SIZE);
  33. const uint32_t *otp32 = (uint32_t*)(FLASH_OTP_BASE + OTP_BLOCK_NUM * OTP_BLOCK_SIZE);
  34. const uint8_t *lock = (uint8_t*)(FLASH_OTP_BASE + OTP_SIZE + OTP_BLOCK_NUM);
  35. const uint32_t marker = 0x06002019;
  36. static void
  37. checkHwSensePins()
  38. {
  39. // Check the board version is correct.
  40. // Sense pins are configued as pullup, and connected to GND for 2020 hw,
  41. // or N/C for v6 ref F or older
  42. if ((HAL_GPIO_ReadPin(UNUSED_PC4_GPIO_Port, UNUSED_PC4_Pin) == 0) ||
  43. (HAL_GPIO_ReadPin(UNUSED_PC5_GPIO_Port, UNUSED_PC5_Pin) == 0))
  44. {
  45. // Oh dear, wrong version. Do not pass go.
  46. while (1) {}
  47. }
  48. }
  49. void
  50. s2s_checkHwVersion()
  51. {
  52. checkHwSensePins();
  53. // Write a marker to flash that can be read by dfu-util now that we know
  54. // the version is correct.
  55. if (*otp32 != marker)
  56. {
  57. // Double-check the pins are good.
  58. s2s_delay_ms(10);
  59. checkHwSensePins();
  60. // Well, pins are good. Make sure marker isn't set at all
  61. if (*otp32 != 0xffffffff)
  62. {
  63. // Some other version was set.
  64. while (1) {}
  65. }
  66. // Write the marker to flash.
  67. if (HAL_FLASH_Unlock() != HAL_OK)
  68. {
  69. return;
  70. }
  71. // Write 4 bytes to the start of OTP.
  72. if (HAL_FLASH_Program(
  73. FLASH_TYPEPROGRAM_WORD,
  74. (uint32_t)otp,
  75. marker) != HAL_OK)
  76. {
  77. HAL_FLASH_Lock();
  78. return;
  79. }
  80. // Lock OTP page
  81. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, (uint32_t)lock, 0x00)) {
  82. HAL_FLASH_Lock();
  83. return;
  84. }
  85. HAL_FLASH_Lock();
  86. }
  87. }