|
|
@@ -0,0 +1,102 @@
|
|
|
+// Copyright (C) 2020 Michael McMaster <michael@codesrc.com>
|
|
|
+//
|
|
|
+// This file is part of SCSI2SD.
|
|
|
+//
|
|
|
+// SCSI2SD is free software: you can redistribute it and/or modify
|
|
|
+// it under the terms of the GNU General Public License as published by
|
|
|
+// the Free Software Foundation, either version 3 of the License, or
|
|
|
+// (at your option) any later version.
|
|
|
+//
|
|
|
+// SCSI2SD is distributed in the hope that it will be useful,
|
|
|
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+// GNU General Public License for more details.
|
|
|
+//
|
|
|
+// You should have received a copy of the GNU General Public License
|
|
|
+// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
|
|
|
+
|
|
|
+#include "hwversion.h"
|
|
|
+#include "stm32f2xx.h"
|
|
|
+#include "config.h"
|
|
|
+#include "time.h"
|
|
|
+
|
|
|
+// Store hardware version details to the "One Time Programmable" flash memory
|
|
|
+// This is 512 bytes that can only be written to ONCE and once only.
|
|
|
+// It can be read by dfu-util, so once we write the marker it can be
|
|
|
+// detected even when the firmware isn't running.
|
|
|
+
|
|
|
+// Values for STM32F401RE
|
|
|
+const size_t OTP_SIZE = 512;
|
|
|
+const size_t OTP_BLOCKS = 16;
|
|
|
+const size_t OTP_BLOCK_SIZE = OTP_SIZE / OTP_BLOCKS;
|
|
|
+
|
|
|
+const size_t OTP_BLOCK_NUM = 0;
|
|
|
+
|
|
|
+// Define some pointers for writing, but also to allow easy reading back values
|
|
|
+#define FLASH_OTP_BASE 0x1FFF7800
|
|
|
+const uint8_t *otp = (uint8_t*)(FLASH_OTP_BASE + OTP_BLOCK_NUM * OTP_BLOCK_SIZE);
|
|
|
+const uint32_t *otp32 = (uint32_t*)(FLASH_OTP_BASE + OTP_BLOCK_NUM * OTP_BLOCK_SIZE);
|
|
|
+const uint8_t *lock = (uint8_t*)(FLASH_OTP_BASE + OTP_SIZE + OTP_BLOCK_NUM);
|
|
|
+
|
|
|
+const uint32_t marker = 0x06002019;
|
|
|
+
|
|
|
+static void
|
|
|
+checkHwSensePins()
|
|
|
+{
|
|
|
+ // Check the board version is correct.
|
|
|
+ // Sense pins are configued as pullup, and connected to GND for 2020 hw,
|
|
|
+ // or N/C for v6 ref F or older
|
|
|
+ if ((HAL_GPIO_ReadPin(UNUSED_PC4_GPIO_Port, UNUSED_PC4_Pin) == 0) ||
|
|
|
+ (HAL_GPIO_ReadPin(UNUSED_PC5_GPIO_Port, UNUSED_PC5_Pin) == 0))
|
|
|
+ {
|
|
|
+ // Oh dear, wrong version. Do not pass go.
|
|
|
+ while (1) {}
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+s2s_checkHwVersion()
|
|
|
+{
|
|
|
+ checkHwSensePins();
|
|
|
+
|
|
|
+ // Write a marker to flash that can be read by dfu-util now that we know
|
|
|
+ // the version is correct.
|
|
|
+ if (*otp32 != marker)
|
|
|
+ {
|
|
|
+ // Double-check the pins are good.
|
|
|
+ s2s_delay_ms(10);
|
|
|
+ checkHwSensePins();
|
|
|
+
|
|
|
+ // Well, pins are good. Make sure marker isn't set at all
|
|
|
+ if (*otp32 != 0xffffffff)
|
|
|
+ {
|
|
|
+ // Some other version was set.
|
|
|
+ while (1) {}
|
|
|
+ }
|
|
|
+
|
|
|
+ // Write the marker to flash.
|
|
|
+ if (HAL_FLASH_Unlock() != HAL_OK)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Write 4 bytes to the start of OTP.
|
|
|
+ if (HAL_FLASH_Program(
|
|
|
+ FLASH_TYPEPROGRAM_WORD,
|
|
|
+ (uint32_t)otp,
|
|
|
+ marker) != HAL_OK)
|
|
|
+ {
|
|
|
+ HAL_FLASH_Lock();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Lock OTP page
|
|
|
+ if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, (uint32_t)lock, 0x00)) {
|
|
|
+ HAL_FLASH_Lock();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ HAL_FLASH_Lock();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|