/** library to program EEPROM using block programming * @file * @author King Kévin * @copyright SPDX-License-Identifier: GPL-3.0-or-later * @date 2021 * @warning functions need to be put in and run from RAM (because block programming is used) */ // RAM code-putting from https://lujji.github.io/blog/executing-code-from-ram-on-stm8/ /* standard libraries */ #include // standard integer types #include // boolean types #include "stm8s.h" // STM8S definitions #include "eeprom_blockprog.h" // own definitions // start address of EEPROM #define EEPROM_ADDR 0x4000 // block size from low-density devices (including STM8S103) #define DATA_BLOCK_SIZE 64U #pragma codeseg RAM_SEG bool eeprom_blockprog(const uint8_t* data, uint16_t length) { if (0 == length) { return true; // nothing to do } if (!data) { return false; // data missing } if (0 != (length % DATA_BLOCK_SIZE)) { return false; // we can only program whole blocks } // disable DATA (e.g. EEPROM) write protection // don't check if it is locked this it does not save that much time and uses memory) FLASH_DUKR = FLASH_DUKR_KEY1; FLASH_DUKR = FLASH_DUKR_KEY2; // don't verify if unlock succeeded to save memory // if (!(FLASH_IAPSR & FLASH_IAPSR_DUL)) { // un-protecting failed // return false; // } // program data uint8_t* eeprom = (uint8_t*)(EEPROM_ADDR); while (length) { // enable standard block programming FLASH_CR2 |= FLASH_CR2_PRG; FLASH_NCR2 &= ~FLASH_NCR2_NPRG; // program block for (uint8_t i = 0; i < DATA_BLOCK_SIZE; i++) { *(eeprom++) = *(data++); } length -= DATA_BLOCK_SIZE; // wait until program completed while (FLASH_CR2 & FLASH_CR2_PRG); // check if programming failed // we don't check for WR_PG_DIS (while checking EOP) because EEPROM isn't (and can't be) write protected if (!(FLASH_IAPSR & FLASH_IAPSR_EOP)) { FLASH_IAPSR &= ~FLASH_IAPSR_DUL; // re-enable write protection return false; } } FLASH_IAPSR &= ~FLASH_IAPSR_DUL; // re-enable write protection return true; }