From 53de825c4c4d8325c02341177f62ab84897eb5ee Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Sat, 25 Jul 2026 22:09:43 +0800
Subject: [PATCH] update vscode task.json and add stm32flash tools

---
 ex2.i2c-bitbang/Board/isl1208.c |  367 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 367 insertions(+), 0 deletions(-)

diff --git a/ex2.i2c-bitbang/Board/isl1208.c b/ex2.i2c-bitbang/Board/isl1208.c
new file mode 100644
index 0000000..d9dcd5d
--- /dev/null
+++ b/ex2.i2c-bitbang/Board/isl1208.c
@@ -0,0 +1,367 @@
+/**********************************************************************
+ * Copyright: (C)2026 LingYun IoT System Studio
+ * Author: GuoWenxue<guowenxue@gmail.com>
+ *
+ * Description: ISL1208 RTC driver on ISKBoard (Unlocked Core Pattern)
+ *
+ * ChangeLog:
+ * Version    Date       Author            Description
+ * V1.1.0  2026.07.08    GuoWenxue      Refactor with unlocked core functions
+ *
+ ***********************************************************************/
+
+#include <stdio.h>
+#include "isl1208.h"
+
+/* 隐藏在私有源文件内部的 ISL1208 寄存器映射与参数 */
+#define ISL1208_I2C_ADDR        0x6F
+
+#define ISL1208_REG_SC          0x00    /* 秒 (00-59) */
+#define ISL1208_REG_MN          0x01    /* 分 (00-59) */
+#define ISL1208_REG_HR          0x02    /* 时 (24小时模式) */
+#define ISL1208_REG_DT          0x03    /* 日 (01-31) */
+#define ISL1208_REG_MO          0x04    /* 月 (01-12) */
+#define ISL1208_REG_YR          0x05    /* 年 (00-99) */
+#define ISL1208_REG_DW          0x06    /* 星期 (00-06) */
+
+#define ISL1208_REG_SR          0x07    /* 状态寄存器 */
+#define ISL1208_SR_RTCF         0x80    /* 掉电/晶振失效标志位 */
+#define ISL1208_SR_WRTC         0x10    /* 写使能位 */
+
+/* 前置私有静态辅助函数声明 (无锁底层业务函数) */
+static int __isl1208_set_time_unlocked(const rtc_time_t *time);
+static int __isl1208_get_time_unlocked(rtc_time_t *time);
+
+/*
+ *+---------------------------------+
+ *|     RTC 公共接口函数(带锁)       |
+ *+---------------------------------+
+ */
+
+/* I2C 设备 RTC */
+static i2c_dev_t rtc;
+
+/**
+ * @brief  ISL1208 硬件初始化与掉电自愈函数
+ * @note   只有检测到掉电(RTCF=1)或停振(ST=1)时,才强制清理控制位并激活时钟,平时不干扰原有走时
+ * @param  bus: 绑定的 I2C 物理总线指针 (如 &i2c1_bus)
+ * @retval 0: 初始化成功; -1: 总线通信失败或芯片未响应
+ */
+int isl1208_init(i2c_bus_t *bus)
+{
+    uint8_t sr_val;
+    uint8_t sc_val;
+    int rv = -1;
+
+    if (!bus)
+        return -1;
+
+    /* 绑定设备及其设备号到 I2C 总线上 */
+    i2c_bind_dev(&rtc, bus, ISL1208_I2C_ADDR);
+
+    /* 将I2C总线加锁让设备独占总线 */
+    i2c_lock_dev(&rtc);
+
+    /* 读取当前状态寄存器 (检查 RTCF) */
+    if (i2c_read(rtc.bus, rtc.dev_addr, ISL1208_REG_SR, &sr_val, 1) != I2C_OK)
+    {
+        goto cleanup;
+    }
+
+    /* 读取当前秒寄存器 (检查 ST) */
+    if (i2c_read(rtc.bus, rtc.dev_addr, ISL1208_REG_SC, &sc_val, 1) != I2C_OK)
+    {
+        goto cleanup;
+    }
+
+    /* 条件触发:只要 SBIB 位为 1 证明是断电冷启动,必须强制清除解冻 */
+    if (sr_val & 0x01)
+    {
+        printf("ISL1208 Power-Loss or Stop detected! Activating oscillator...\r\n");
+
+        /* 强开写保护 (WRTC=1),并抹除 SBIB 冻结位 */
+        sr_val = ISL1208_SR_WRTC;
+        if (i2c_write(rtc.bus, rtc.dev_addr, ISL1208_REG_SR, &sr_val, 1) != I2C_OK)
+        {
+            goto cleanup;
+        }
+
+        /* 写入完整的 2026-01-01 00:00:00 (星期四) 基准时间 */
+        uint8_t init_buf[7];
+        init_buf[0] = 0x00; /* 00秒,同时最高位 ST=0 激活晶振起振 */
+        init_buf[1] = 0x00; /* 00分 */
+        init_buf[2] = 0x80; /* 00时,Bit7=1 代表开启 24 小时制 */
+        init_buf[3] = 0x01; /* 01日 (BCD: 0x01) */
+        init_buf[4] = 0x01; /* 01月 (BCD: 0x01) */
+        init_buf[5] = 0x26; /* 26年 (BCD: 0x26 代表 2026年) */
+        init_buf[6] = 0x04; /* 星期四 (BCD: 0x04) */
+
+        /* 写入 7 个时间寄存器 */
+        if (i2c_write(rtc.bus, rtc.dev_addr, ISL1208_REG_SC, init_buf, 7) != I2C_OK)
+        {
+            goto cleanup;
+        }
+
+        /* 强制将秒寄存器的最高位 ST (Stop) 清零以激活晶振 */
+        sc_val &= 0x7F;
+        if (i2c_write(rtc.bus, rtc.dev_addr, ISL1208_REG_SC, &sc_val, 1) != I2C_OK)
+        {
+            goto cleanup;
+        }
+
+        /* 关闭写保护,并将状态寄存器洗干净 (SBIB 清零) */
+        sr_val = 0x00;
+        if (i2c_write(rtc.bus, rtc.dev_addr, ISL1208_REG_SR, &sr_val, 1) != I2C_OK)
+        {
+            goto cleanup;
+        }
+    }
+
+    rv = 0;
+
+cleanup:
+    i2c_free_dev(&rtc);
+    return rv;
+}
+
+/**
+ * @brief  应用层设置 RTC 时间接口函数(rtc_time_t格式)
+ * @param  time  指向待写入时间数据的 rtc_time_t 结构体常指针
+ * @retval 0:成功, -1:失败
+ */
+int isl1208_set_time(const rtc_time_t *time)
+{
+    int rv = -1;
+
+    if (!rtc.bus || !time)
+    {
+        return -1;
+    }
+
+    i2c_lock_dev(&rtc);
+
+    /* 调用无锁底层核心实现写操作 */
+    rv = __isl1208_set_time_unlocked(time);
+
+    i2c_free_dev(&rtc);
+
+    return rv;
+}
+
+/**
+ * @brief  应用层设置 RTC 时间接口函数(字符串格式)
+ * @param  time_str  输入的时间字符串指针,格式如 "2026-01-01 10:00:00"
+ * @retval 0:成功, -1:失败
+ */
+int isl1208_set_time_str(const char *time_str)
+{
+    rtc_time_t tm;
+    int year, month, day, hour, minute, second;
+
+    if (!time_str)
+    {
+        return -1;
+    }
+
+    /* 1. 解析时间字符串 */
+    if (sscanf(time_str, "%d-%d-%d %d:%d:%d",
+               &year, &month, &day, &hour, &minute, &second) != 6)
+    {
+        return -1;
+    }
+
+    /* 2. 填充结构体(年份仅保留低两位) */
+    tm.year    = year % 100;
+    tm.month   = month;
+    tm.day     = day;
+    tm.hour    = hour;
+    tm.minute  = minute;
+    tm.second  = second;
+    tm.weekday = 0;
+
+    /* 3. 直接调用带锁的原本接口 */
+    return isl1208_set_time(&tm);
+}
+
+/**
+ * @brief  应用层获取 RTC 时间接口函数
+ * @param  time  指向用于接收时间数据的 rtc_time_t 结构体指针
+ * @retval 0:成功, -1:失败
+ */
+int isl1208_get_time(rtc_time_t *time)
+{
+    int rv = -1;
+
+    if (!rtc.bus || !time)
+    {
+        return -1;
+    }
+
+    i2c_lock_dev(&rtc);
+
+    /* 调用无锁底层核心实现读操作 */
+    rv = __isl1208_get_time_unlocked(time);
+
+    i2c_free_dev(&rtc);
+    return rv;
+}
+
+/**
+ * @brief  应用层获取 RTC 时间接口函数(字符串格式)
+ * @param  buf      用于存储格式化时间字符串的缓冲区指针
+ * @param  buf_len  接收缓冲区长度(建议至少20字节)
+ * @retval 0:成功, -1:失败
+ */
+int isl1208_get_time_str(char *buf, size_t buf_len)
+{
+    rtc_time_t tm;
+    int rv = -1;
+
+    if (!buf || buf_len < 20)
+    {
+        return -1;
+    }
+
+    /* 直接调用带锁的原本接口获取时间结构体 */
+    rv = isl1208_get_time(&tm);
+    if (rv != 0)
+    {
+        return rv;
+    }
+
+    /* 格式化为字符串输出 */
+    snprintf(buf, buf_len, "20%02d-%02d-%02d %02d:%02d:%02d",
+             tm.year, tm.month, tm.day,
+             tm.hour, tm.minute, tm.second);
+
+    return 0;
+}
+
+/**
+ * @brief  获取并格式化打印当前 RTC 时间接口函数
+ * @param  bus  指向已初始化的 I2C 总线结构体指针
+ * @retval 0:成功, -1:失败
+ */
+int isl1208_print_time(void)
+{
+    char time_str[32];
+
+    /* 直接调用刚刚封装好的获取字符串接口 */
+    if (isl1208_get_time_str(time_str, sizeof(time_str)) != 0)
+    {
+        return -1;
+    }
+
+    /* 格式化输出 */
+    printf("ISL1208 Time: %s\r\n", time_str);
+    return 0;
+}
+
+/*
+ *+---------------------------------+
+ *|     RTC 私有底层函数(无锁)       |
+ *+---------------------------------+
+ */
+
+/**
+ * @brief  十进制转 BCD 码
+ */
+static inline uint8_t rtc_dec_to_bcd(uint8_t dec)
+{
+    uint8_t high;
+    uint8_t low;
+
+    high = dec / 10;
+    low = dec % 10;
+
+    return (uint8_t)((high << 4) | low);
+}
+
+/**
+ * @brief  BCD 码转十进制
+ */
+static inline uint8_t rtc_bcd_to_dec(uint8_t bcd)
+{
+    uint8_t high;
+    uint8_t low;
+
+    high = bcd >> 4;
+    low = bcd & 0x0F;
+
+    return (uint8_t)((high * 10) + low);
+}
+
+/**
+ * @brief  向 RTC 芯片写入时间
+ */
+static int __isl1208_set_time_unlocked(const rtc_time_t *time)
+{
+    uint8_t time_buf[7];
+    uint8_t sr_val;
+
+    if( !rtc.bus )
+        return -1;
+
+    /* 读取当前状态寄存器 */
+    if (i2c_read(rtc.bus, ISL1208_I2C_ADDR, ISL1208_REG_SR, &sr_val, 1) != I2C_OK)
+    {
+        return -1;
+    }
+
+    /* 解除 RTC 写保护 (WRTC 置 1) */
+    sr_val |= ISL1208_SR_WRTC;
+    if (i2c_write(rtc.bus, ISL1208_I2C_ADDR, ISL1208_REG_SR, &sr_val, 1) != I2C_OK)
+    {
+        return -1;
+    }
+
+    /* 将标准十进制转换为 BCD 码并打包 */
+    time_buf[0] = rtc_dec_to_bcd(time->second);
+    time_buf[1] = rtc_dec_to_bcd(time->minute);
+    time_buf[2] = (rtc_dec_to_bcd(time->hour) & 0x3F) | 0x80;
+    time_buf[3] = rtc_dec_to_bcd(time->day);
+    time_buf[4] = rtc_dec_to_bcd(time->month);
+    time_buf[5] = rtc_dec_to_bcd(time->year);
+    time_buf[6] = rtc_dec_to_bcd(time->weekday);
+
+    /* 写入 7 个时间寄存器 */
+    if (i2c_write(rtc.bus, ISL1208_I2C_ADDR, ISL1208_REG_SC, time_buf, 7) != I2C_OK)
+    {
+        return -1;
+    }
+
+    /* 恢复写保护并同时清除掉电失效位 (WRTC = 0, RTCF = 0) */
+    sr_val &= ~ISL1208_SR_WRTC;
+    sr_val &= ~ISL1208_SR_RTCF;
+    if (i2c_write(rtc.bus, ISL1208_I2C_ADDR, ISL1208_REG_SR, &sr_val, 1) != I2C_OK)
+    {
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
+ * @brief  从 RTC 芯片读取时间
+ */
+static int __isl1208_get_time_unlocked(rtc_time_t *time)
+{
+    uint8_t time_buf[7];
+
+    /* 连续读取 7 个寄存器的原始 BCD 数据 */
+    if (i2c_read(rtc.bus, ISL1208_I2C_ADDR, ISL1208_REG_SC, time_buf, 7) != I2C_OK)
+    {
+        return -1;
+    }
+
+    /* 解析 BCD 码并做去噪掩码隔离 */
+    time->second  = rtc_bcd_to_dec(time_buf[0] & 0x7F);
+    time->minute  = rtc_bcd_to_dec(time_buf[1] & 0x7F);
+    time->hour    = rtc_bcd_to_dec(time_buf[2] & 0x3F);
+    time->day     = rtc_bcd_to_dec(time_buf[3] & 0x3F);
+    time->month   = rtc_bcd_to_dec(time_buf[4] & 0x1F);
+    time->year    = rtc_bcd_to_dec(time_buf[5]);
+    time->weekday = rtc_bcd_to_dec(time_buf[6] & 0x07);
+
+    return 0;
+}

--
Gitblit v1.10.0