// Copyright (C) 2020 Michael McMaster // // 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 . #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(); } }