diff --git a/demo/iap/eeprom_iap.c b/demo/iap/eeprom_iap.c new file mode 100644 index 0000000..00eff12 --- /dev/null +++ b/demo/iap/eeprom_iap.c @@ -0,0 +1,108 @@ +// Copyright 2021 IOsetting +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*** + * Demo: EEPROM IAP read, write, erase and software reset + */ + +#include "fw_hal.h" + +#define TEST_ADDR 0x0400 +#define TEST_SIZE 32 + +void TestIAPRead(uint16_t addr, uint8_t size) +{ + uint8_t pos = 0; + UART1_TxString("IAP_CmdRead: "); + for (pos = 0; pos < size; pos++) + { + IAP_CmdRead(addr + pos); + if (IAP_IsCmdFailed()) + { + UART1_TxString("__ "); + IAP_ClearCmdFailFlag(); + } + else + { + UART1_TxHex(IAP_ReadData()); + UART1_TxChar(' '); + } + } + UART1_TxString("\r\n"); +} + +void TestIAPWrite(uint16_t addr, uint8_t size) +{ + uint8_t pos = 0; + UART1_TxString("IAP_CmdWrite: "); + for (pos = 0; pos < size; pos++) + { + IAP_WriteData(pos); + IAP_CmdWrite(addr + pos); + if (IAP_IsCmdFailed()) + { + UART1_TxString("__ "); + IAP_ClearCmdFailFlag(); + } + else + { + UART1_TxHex(pos); + UART1_TxChar(' '); + } + } + UART1_TxString("\r\n"); +} + +void TestIAPErase(uint16_t addr) +{ + uint8_t pos = 0; + UART1_TxString("IAP_CmdErase: "); + IAP_CmdErase(addr); + if (IAP_IsCmdFailed()) + { + UART1_TxString("failed.\r\n"); + IAP_ClearCmdFailFlag(); + } + else + { + UART1_TxString("succeeded.\r\n"); + } +} + +int main(void) +{ + SYS_SetClock(); + UART1_Config8bitUart(UART1_BaudSource_Timer2, HAL_State_ON, 115200); + UART1_TxString("Test restarted\r\n"); + IAP_SetWaitTime(); + IAP_SetEnabled(HAL_State_ON); + + TestIAPRead(TEST_ADDR, TEST_SIZE); + SYS_Delay(500); + TestIAPWrite(TEST_ADDR, TEST_SIZE); + SYS_Delay(500); + TestIAPRead(TEST_ADDR, TEST_SIZE); + SYS_Delay(500); + TestIAPErase(TEST_ADDR); + SYS_Delay(500); + TestIAPRead(TEST_ADDR, TEST_SIZE); + IAP_SetEnabled(HAL_State_OFF); + SYS_Delay(2000); + + UART1_TxString("Software reset\r\n"); + SYS_Delay(1000); + IAP_SoftReset(); + + return 0; +} diff --git a/include/fw_hal.h b/include/fw_hal.h index 4792128..82ad4dc 100644 --- a/include/fw_hal.h +++ b/include/fw_hal.h @@ -26,6 +26,7 @@ #include "fw_adc.h" #include "fw_i2c.h" #include "fw_spi.h" +#include "fw_iap.h" #include "fw_util.h" #if (__CONF_MCU_TYPE == 2 ) diff --git a/include/fw_iap.h b/include/fw_iap.h new file mode 100644 index 0000000..902d9cd --- /dev/null +++ b/include/fw_iap.h @@ -0,0 +1,106 @@ +// Copyright 2021 IOsetting +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ___FW_IAP_H___ +#define ___FW_IAP_H___ + +#include "fw_conf.h" +#include "fw_types.h" + +/** + * EEPROM size and IAP address of different series + * + * | LINE | SIZE | ADDR START | ADDR END | + * | --------- | --- | ----- | ----- | + * | STC8H1K08 | 4K | 0x0000 | 0x0FFF | + * | STC8H1K24 | 4K | 0x0000 | 0x0FFF | + * | STC8H3K60S2 | 4K | 0x0000 | 0x0FFF | + * | STC8H3K60S4 | 4K | 0x0000 | 0x0FFF | + * | STC8H8K60U | 4K | 0x0000 | 0x0FFF | + * | STC8H1K16 | 12K | 0x0000 | 0x2FFF | + * | STC8H3K48S2 | 16K | 0x0000 | 0x3FFF | + * | STC8H3K48S4 | 16K | 0x0000 | 0x3FFF | + * | STC8H8K48U | 16K | 0x0000 | 0x3FFF | + * | STC8H3K32S2 | 32K | 0x0000 | 0x7FFF | + * | STC8H3K32S4 | 32K | 0x0000 | 0x7FFF | + * | STC8H8K32U | 32K | 0x0000 | 0x7FFF | + * +*/ + +typedef enum +{ + IAP_RestartFrom_UserCode = 0x00, + IAP_RestartFrom_ISPCode = 0x01, +} IAP_RestartFrom_t; + +#define IAP_SetWaitTime() (IAP_TPS = (uint8_t)(__CONF_FOSC / 1000000UL)) +#define IAP_ReadData() (IAP_DATA) +#define IAP_WriteData(__BYTE__) (IAP_DATA = (__BYTE__)) + +/** + * Set cmd to idle +*/ +#define IAP_SetIdle() (IAP_CMD = IAP_CMD & ~(0x03)) + +/** + * Read one byte +*/ +#define IAP_CmdRead(__16BIT_ADDR__) do{ \ + EA = 0; \ + IAP_ADDRH = ((__16BIT_ADDR__) >> 8); \ + IAP_ADDRL = ((__16BIT_ADDR__) & 0xFF); \ + IAP_CMD = IAP_CMD & ~(0x03) | 0x01; \ + IAP_TRIG = 0x5A; \ + IAP_TRIG = 0xA5; \ + NOP();NOP(); \ + IAP_SetIdle(); \ + EA = 1; \ + }while(0) +/** + * Write one byte, 1->0 only +*/ +#define IAP_CmdWrite(__16BIT_ADDR__) do{ \ + EA = 0; \ + IAP_ADDRH = ((__16BIT_ADDR__) >> 8); \ + IAP_ADDRL = ((__16BIT_ADDR__) & 0xFF); \ + IAP_CMD = IAP_CMD & ~(0x03) | 0x02; \ + IAP_TRIG = 0x5A; \ + IAP_TRIG = 0xA5; \ + NOP();NOP(); \ + IAP_SetIdle(); \ + EA = 1; \ + }while(0) +/** + * Erase one section (512 bytes), set all bytes to 0xFF +*/ +#define IAP_CmdErase(__16BIT_ADDR__) do{ \ + EA = 0; \ + IAP_ADDRH = ((__16BIT_ADDR__) >> 8); \ + IAP_ADDRL = ((__16BIT_ADDR__) & 0xFF); \ + IAP_CMD = IAP_CMD & ~(0x03) | 0x03; \ + IAP_TRIG = 0x5A; \ + IAP_TRIG = 0xA5; \ + NOP();NOP(); \ + IAP_SetIdle(); \ + EA = 1; \ + }while(0) + +#define IAP_SetEnabled(__STATE__) SFR_ASSIGN(IAP_CONTR, 7, __STATE__) +#define IAP_SetRestartFrom(__FROM__) SFR_ASSIGN(IAP_CONTR, 6, __FROM__) +#define IAP_SoftReset() SFR_SET(IAP_CONTR, 5) +#define IAP_IsCmdFailed() (IAP_CONTR & (0x01 << 4)) +#define IAP_ClearCmdFailFlag() SFR_RESET(IAP_CONTR, 4) + + +#endif