初始提交
This commit is contained in:
582
driver/extern/rtc/src/bl8025t_driver.c
vendored
Normal file
582
driver/extern/rtc/src/bl8025t_driver.c
vendored
Normal file
@@ -0,0 +1,582 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
||||
* be copied by any method or incorporated into another program without
|
||||
* the express written consent of Aerospace C.Power. This Information or any portion
|
||||
* thereof remains the property of Aerospace C.Power. The Information contained herein
|
||||
* is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
||||
* liability for its use in any way and conveys no license or title under
|
||||
* any patent or copyright and makes no representation or warranty that this
|
||||
* Information is free from patent or copyright infringement.
|
||||
*
|
||||
* ****************************************************************************/
|
||||
|
||||
/* os_ship header files */
|
||||
#include "os_utils_api.h"
|
||||
|
||||
/* iot common header files */
|
||||
#include "iot_config_api.h"
|
||||
#include "iot_utils_api.h"
|
||||
#include "iot_i2c_api.h"
|
||||
#include "iot_gpio_api.h"
|
||||
#include "iot_board_api.h"
|
||||
#include "iot_io_api.h"
|
||||
#include "iot_errno_api.h"
|
||||
#include "iot_config.h"
|
||||
|
||||
/* iot common header files */
|
||||
#include "iot_rtc_api.h"
|
||||
#include "iot_rtc_ext.h"
|
||||
|
||||
#if IOT_EXT_RTC_BL8025T_ENABLE
|
||||
|
||||
#define BL8025T_TRANS_BUF_CNT 16
|
||||
|
||||
/* the iic config of bl8025t. */
|
||||
#define BL8025T_IIC_PHY_ADDR 0x32 /* shift as (0x32 << 1) in driver. */
|
||||
#define BL8025T_IIC_DEF_PORT 0 /* Port#0. */
|
||||
#define BL8025T_IIC_DEF_SPEED 100 /* 100K. */
|
||||
#define BL8025T_IIC_DEF_NACK_NUM 1 /* N-ACK number. */
|
||||
|
||||
/* bl8025t fOUT frequency selection, frequency is 32768HZ */
|
||||
#define BL8025T_FOUT_FRE_32768HZ 0
|
||||
/* bl8025t fOUT frequency selection, frequency is 1024HZ */
|
||||
#define BL8025T_FOUT_FRE_1024HZ 1
|
||||
/* bl8025t fOUT frequency selection, frequency is 1HZ */
|
||||
#define BL8025T_FOUT_FRE_1HZ 2
|
||||
/* bl8025t fOUT frequency selection, frequency is 32768HZ */
|
||||
#define BL8025T_FOUT_FRE_32768HZ2 3
|
||||
|
||||
/* bl8025t register internal address definition */
|
||||
#define BL8025T_SEC_REG_ADDR 0x00
|
||||
#define BL8025T_MIN_REG_ADDR 0x01
|
||||
#define BL8025T_HOUR_REG_ADDR 0x02
|
||||
#define BL8025T_WEEK_REG_ADDR 0x03
|
||||
#define BL8025T_DAY_REG_ADDR 0x04
|
||||
#define BL8025T_MON_REG_ADDR 0x05
|
||||
#define BL8025T_YAER_REG_ADDR 0x06
|
||||
#define BL8025T_EXTEND_REG_ADDR 0x0D
|
||||
#define BL8025T_FLAG_REG_ADDR 0x0E
|
||||
#define BL8025T_CTRL_REG_ADDR 0x0F
|
||||
|
||||
|
||||
/* bl8025t sec register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - seconds, BCD format */
|
||||
uint8_t sec :7,
|
||||
/* flag to mark if oscillator fail */
|
||||
rsvd :1;
|
||||
} bl8025t_sec_reg_t;
|
||||
|
||||
/* bl8025t min register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - min, BCD format */
|
||||
uint8_t min :7,
|
||||
/* flag to mark if oscillator fail */
|
||||
rsvd :1;
|
||||
} bl8025t_min_reg_t;
|
||||
|
||||
/* bl8025t hour register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - hour, BCD format */
|
||||
uint8_t hour :6,
|
||||
/* don't care */
|
||||
rsvd :2;
|
||||
} bl8025t_hour_reg_t;
|
||||
|
||||
/* bl8025t week register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - week */
|
||||
uint8_t week :6,
|
||||
/* don't care */
|
||||
rsvd :2;
|
||||
} bl8025t_week_reg_t;
|
||||
|
||||
/* bl8025t day register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - day, BCD format */
|
||||
uint8_t day :6,
|
||||
/* don't care */
|
||||
rsvd :2;
|
||||
} bl8025t_day_reg_t;
|
||||
|
||||
/* bl8025t mon register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - mon, BCD format */
|
||||
uint8_t mon :5,
|
||||
/* don't care */
|
||||
rsvd :3;
|
||||
} bl8025t_mon_reg_t;
|
||||
|
||||
/* bl8025t year register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - year, BCD format */
|
||||
uint8_t year;
|
||||
} bl8025t_year_reg_t;
|
||||
|
||||
/* bl8025t flag register layout definition */
|
||||
typedef struct {
|
||||
/* don't care */
|
||||
uint8_t rsvd :2,
|
||||
/* Alarm interrupt flag */
|
||||
uf :1,
|
||||
/* Timing interrupt flag */
|
||||
tf :1,
|
||||
/* update interrupt flag */
|
||||
af :1,
|
||||
/* don't care */
|
||||
rsvd1 :1,
|
||||
/* electric low flag */
|
||||
vlf :1,
|
||||
/* voltage detection mark */
|
||||
vdet :1;
|
||||
} bl8025t_flag_reg_t;
|
||||
|
||||
/* bl8025t ctrl register layout definition */
|
||||
typedef struct {
|
||||
/* temperature compensation time select */
|
||||
uint8_t csel :2,
|
||||
/* alarm interrupt enable */
|
||||
uie :1,
|
||||
/* timing interrupt enable */
|
||||
tie :1,
|
||||
/* update interrupt enable */
|
||||
aie :1,
|
||||
/* don't care */
|
||||
rsvd :2,
|
||||
/* reset */
|
||||
reset :1;
|
||||
} bl8025t_ctrl_reg_t;
|
||||
|
||||
/* bl8025t calendar layout */
|
||||
typedef struct {
|
||||
/* sec register */
|
||||
bl8025t_sec_reg_t sec_reg;
|
||||
/* min register */
|
||||
bl8025t_min_reg_t min_reg;
|
||||
/* hour register */
|
||||
bl8025t_hour_reg_t hour_reg;
|
||||
/* week register */
|
||||
bl8025t_week_reg_t week_reg;
|
||||
/* day register */
|
||||
bl8025t_day_reg_t day_reg;
|
||||
/* mon register */
|
||||
bl8025t_mon_reg_t mon_reg;
|
||||
/* year register */
|
||||
bl8025t_year_reg_t year_reg;
|
||||
} bl8025t_calendar_reg_t;
|
||||
|
||||
/* bl8025t calendar layout */
|
||||
typedef struct {
|
||||
/* flag register */
|
||||
bl8025t_flag_reg_t flag_reg;
|
||||
/* ctrl register */
|
||||
bl8025t_ctrl_reg_t ctrl_reg;
|
||||
} bl8025t_check_reg_t;
|
||||
|
||||
/* bl8025t extend register layout definition */
|
||||
typedef struct {
|
||||
/* countdown cycle selector bit */
|
||||
uint8_t tsel :2,
|
||||
/* FOUT frequency selector bit */
|
||||
fsel :2,
|
||||
/* Timing function enable bit */
|
||||
te :1,
|
||||
/* Periodic updates interrupt the selection bit */
|
||||
usel :1,
|
||||
/* day and calendar alarm options */
|
||||
wada :1,
|
||||
/* factory test bit */
|
||||
test :1;
|
||||
} bl8025t_extend_reg_t;
|
||||
|
||||
/* check the validity of the calendar register */
|
||||
#define bl8025t_sec_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x59)
|
||||
#define bl8025t_min_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x59)
|
||||
#define bl8025t_hour_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x23)
|
||||
#define bl8025t_day_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x31 && (x) >= 1)
|
||||
#define bl8025t_mon_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x12 && (x) >= 1)
|
||||
#define bl8025t_year_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x99)
|
||||
|
||||
static uint8_t buf[BL8025T_TRANS_BUF_CNT];
|
||||
|
||||
static uint8_t bl8025t_regs_is_valid(bl8025t_calendar_reg_t *cal_regs)
|
||||
{
|
||||
uint8_t reason = 0;
|
||||
if (!cal_regs) {
|
||||
reason = 1;
|
||||
IOT_ASSERT(0);
|
||||
goto err;
|
||||
}
|
||||
if (!bl8025t_sec_is_valid(cal_regs->sec_reg.sec)) {
|
||||
reason = 2;
|
||||
goto err;
|
||||
}
|
||||
if (!bl8025t_min_is_valid(cal_regs->min_reg.min)) {
|
||||
reason = 3;
|
||||
goto err;
|
||||
}
|
||||
if (!bl8025t_hour_is_valid(cal_regs->hour_reg.hour)) {
|
||||
reason = 4;
|
||||
goto err;
|
||||
}
|
||||
if (!bl8025t_day_is_valid(cal_regs->day_reg.day)) {
|
||||
reason = 5;
|
||||
goto err;
|
||||
}
|
||||
if (!bl8025t_mon_is_valid(cal_regs->mon_reg.mon)) {
|
||||
reason = 6;
|
||||
goto err;
|
||||
}
|
||||
if (!bl8025t_year_is_valid(cal_regs->year_reg.year)) {
|
||||
reason = 7;
|
||||
goto err;
|
||||
}
|
||||
return ERR_OK;
|
||||
err:
|
||||
iot_printf("%s err, reason %lu\n", __FUNCTION__, reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
||||
static uint32_t bl8025t_read_regs(uint8_t addr, uint8_t *data, uint8_t cnt)
|
||||
{
|
||||
uint8_t reason = 0;
|
||||
if(ERR_OK != iot_i2c_write(BL8025T_IIC_DEF_PORT, BL8025T_IIC_PHY_ADDR,
|
||||
(char *)&addr, 1)) {
|
||||
reason = 1;
|
||||
goto out;
|
||||
}
|
||||
os_delay(10);
|
||||
|
||||
if(ERR_OK != iot_i2c_read(BL8025T_IIC_DEF_PORT, BL8025T_IIC_PHY_ADDR,
|
||||
(char *)data, cnt)) {
|
||||
reason = 1;
|
||||
goto out;
|
||||
}
|
||||
os_delay(5);
|
||||
out:
|
||||
if (reason) {
|
||||
iot_printf("%s fail, reason %lu\n", __FUNCTION__, reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static uint32_t bl8025t_write_regs(uint8_t addr, uint8_t *data, uint8_t cnt)
|
||||
{
|
||||
buf[0] = addr;
|
||||
os_mem_cpy(buf + 1, data, cnt);
|
||||
if (cnt > (IOT_ARRAY_CNT(buf) - 1)) {
|
||||
return ERR_NOMEM;
|
||||
}
|
||||
iot_i2c_write(BL8025T_IIC_DEF_PORT, BL8025T_IIC_PHY_ADDR,
|
||||
(char *)buf, cnt + 1);
|
||||
os_delay(10);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void arx8025t_software_reset ()
|
||||
{
|
||||
buf[0] = BL8025T_CTRL_REG_ADDR;
|
||||
bl8025t_ctrl_reg_t ctrl_reg;
|
||||
ctrl_reg.reset = 1;
|
||||
os_mem_cpy(buf + 1, &ctrl_reg, 1);
|
||||
iot_i2c_write(BL8025T_IIC_DEF_PORT, BL8025T_IIC_PHY_ADDR,
|
||||
(char *)buf, 2);
|
||||
os_delay(10);
|
||||
}
|
||||
|
||||
static uint32_t bl8025t_get_time(iot_time_tm_t *tm)
|
||||
{
|
||||
uint32_t ret;
|
||||
iot_time_tm_t in_tm;
|
||||
uint8_t reason = 0;
|
||||
bl8025t_calendar_reg_t cal_regs = { 0 };
|
||||
bl8025t_check_reg_t check_regs = { 0 };
|
||||
ret = bl8025t_read_regs(BL8025T_SEC_REG_ADDR,
|
||||
(uint8_t *)&cal_regs, sizeof(cal_regs));
|
||||
if (ret != ERR_OK) {
|
||||
reason = 1;
|
||||
goto err;
|
||||
}
|
||||
ret = bl8025t_read_regs(BL8025T_FLAG_REG_ADDR, (uint8_t *)&check_regs,
|
||||
sizeof(check_regs));
|
||||
if (ret != ERR_OK) {
|
||||
reason = 2;
|
||||
goto err;
|
||||
}
|
||||
if (check_regs.flag_reg.vdet || check_regs.flag_reg.vlf) {
|
||||
check_regs.flag_reg.vdet = 0;
|
||||
check_regs.flag_reg.vlf = 0;
|
||||
if (iot_rtc_data_is_revised()) {
|
||||
iot_rtc_get(&in_tm);
|
||||
cal_regs.sec_reg.sec = iot_byte_to_bcd(in_tm.tm_sec);
|
||||
cal_regs.min_reg.min = iot_byte_to_bcd(in_tm.tm_min);
|
||||
cal_regs.hour_reg.hour = iot_byte_to_bcd(in_tm.tm_hour);
|
||||
cal_regs.day_reg.day = iot_byte_to_bcd(in_tm.tm_mday);
|
||||
cal_regs.mon_reg.mon = iot_byte_to_bcd(in_tm.tm_mon);
|
||||
if (in_tm.tm_year < 2000) {
|
||||
in_tm.tm_year = 2000;
|
||||
}
|
||||
cal_regs.year_reg.year = iot_byte_to_bcd(in_tm.tm_year - 2000);
|
||||
}
|
||||
ret = bl8025t_write_regs(BL8025T_SEC_REG_ADDR, (uint8_t*)&cal_regs,
|
||||
sizeof(cal_regs));
|
||||
if (ret) {
|
||||
reason = 2;
|
||||
goto err;
|
||||
}
|
||||
ret = bl8025t_write_regs(BL8025T_FLAG_REG_ADDR, (uint8_t*)&cal_regs,
|
||||
sizeof(cal_regs));
|
||||
reason = 3;
|
||||
goto err;
|
||||
}
|
||||
if (bl8025t_regs_is_valid(&cal_regs) != ERR_OK) {
|
||||
reason = 4;
|
||||
goto err;
|
||||
}
|
||||
tm->tm_sec = iot_bcd_to_byte(cal_regs.sec_reg.sec);
|
||||
tm->tm_min = iot_bcd_to_byte(cal_regs.min_reg.min);
|
||||
tm->tm_hour = iot_bcd_to_byte(cal_regs.hour_reg.hour);
|
||||
tm->tm_mday = iot_bcd_to_byte(cal_regs.day_reg.day);
|
||||
tm->tm_mon = iot_bcd_to_byte(cal_regs.mon_reg.mon);
|
||||
tm->tm_year = iot_bcd_to_byte(cal_regs.year_reg.year) + 2000;
|
||||
iot_printf("%s %lu-%lu-%lu %lu:%lu:%lu\n", __FUNCTION__,
|
||||
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
|
||||
tm->tm_sec);
|
||||
return ERR_OK;
|
||||
err:
|
||||
iot_printf("%s err, reason %lu\n", __FUNCTION__, reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
||||
static uint32_t bl8025t_set_time(iot_time_tm_t *tm, uint8_t week)
|
||||
{
|
||||
uint32_t ret;
|
||||
bl8025t_calendar_reg_t cal_regs = { 0 };
|
||||
bl8025t_check_reg_t check_regs = { 0 };
|
||||
|
||||
ret = bl8025t_read_regs(BL8025T_FLAG_REG_ADDR,
|
||||
(uint8_t *)&check_regs, sizeof(check_regs));
|
||||
if (ret) {
|
||||
goto err;
|
||||
}
|
||||
if (check_regs.flag_reg.vdet || check_regs.flag_reg.vlf) {
|
||||
goto err;
|
||||
}
|
||||
ret = bl8025t_read_regs(BL8025T_SEC_REG_ADDR,
|
||||
(uint8_t *)&cal_regs, sizeof(cal_regs));
|
||||
if (ret) {
|
||||
goto err;
|
||||
}
|
||||
cal_regs.sec_reg.sec = iot_byte_to_bcd(tm->tm_sec);
|
||||
cal_regs.min_reg.min = iot_byte_to_bcd(tm->tm_min);
|
||||
cal_regs.hour_reg.hour = iot_byte_to_bcd(tm->tm_hour);
|
||||
cal_regs.day_reg.day = iot_byte_to_bcd(tm->tm_mday);
|
||||
cal_regs.week_reg.week = 1 << week;
|
||||
cal_regs.mon_reg.mon = iot_byte_to_bcd(tm->tm_mon);
|
||||
cal_regs.year_reg.year = iot_byte_to_bcd(tm->tm_year - 2000);
|
||||
iot_printf("%s %02x-%02x-%02x %02x:%02x:%02x week %lu\n",
|
||||
__FUNCTION__, cal_regs.year_reg.year,
|
||||
cal_regs.mon_reg.mon, cal_regs.day_reg.day, cal_regs.hour_reg.hour,
|
||||
cal_regs.min_reg.min, cal_regs.sec_reg.sec, week);
|
||||
ret = bl8025t_write_regs(BL8025T_SEC_REG_ADDR,
|
||||
(uint8_t *)&cal_regs, sizeof(cal_regs));
|
||||
if (ret) {
|
||||
IOT_ASSERT(0);
|
||||
goto err;
|
||||
}
|
||||
return ERR_OK;
|
||||
err:
|
||||
IOT_ASSERT(0);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
||||
static uint32_t bl8025t_is_startup(iot_time_tm_t *tm)
|
||||
{
|
||||
uint32_t ret;
|
||||
bl8025t_calendar_reg_t cal_regs = { 0 };
|
||||
bl8025t_check_reg_t check_regs = { 0 };
|
||||
|
||||
ret = bl8025t_read_regs(BL8025T_FLAG_REG_ADDR,
|
||||
(uint8_t *)&check_regs, sizeof(check_regs));
|
||||
IOT_ASSERT(ret == ERR_OK);
|
||||
if (!check_regs.flag_reg.vlf) {
|
||||
ret = bl8025t_read_regs(BL8025T_SEC_REG_ADDR,
|
||||
(uint8_t *)&cal_regs, sizeof(cal_regs));
|
||||
tm->tm_sec = iot_bcd_to_byte(cal_regs.sec_reg.sec);
|
||||
tm->tm_min = iot_bcd_to_byte(cal_regs.min_reg.min);
|
||||
tm->tm_hour = iot_bcd_to_byte(cal_regs.hour_reg.hour);
|
||||
tm->tm_mday = iot_bcd_to_byte(cal_regs.day_reg.day);
|
||||
tm->tm_mon = iot_bcd_to_byte(cal_regs.mon_reg.mon);
|
||||
tm->tm_year = iot_bcd_to_byte(cal_regs.year_reg.year) + 2000;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t bl8025t_init(iot_time_tm_t *tm, uint32_t *done)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint8_t reg_is_valid = 1;
|
||||
bl8025t_calendar_reg_t cal_regs = { 0 };
|
||||
bl8025t_check_reg_t check_regs = {0};
|
||||
bl8025t_extend_reg_t extend_reg = {0};
|
||||
*done = 0;
|
||||
|
||||
ret = bl8025t_read_regs(BL8025T_SEC_REG_ADDR,
|
||||
(uint8_t*)&cal_regs, sizeof(cal_regs));
|
||||
if (ret) {
|
||||
IOT_ASSERT(0);
|
||||
ret = ERR_FAIL;
|
||||
goto err;
|
||||
}
|
||||
ret = bl8025t_read_regs(BL8025T_FLAG_REG_ADDR,
|
||||
(uint8_t*)&check_regs, sizeof(check_regs));
|
||||
if (ret) {
|
||||
IOT_ASSERT(0);
|
||||
ret = ERR_FAIL;
|
||||
goto err;
|
||||
}
|
||||
if (bl8025t_regs_is_valid(&cal_regs) != ERR_OK) {
|
||||
reg_is_valid = 0;
|
||||
}
|
||||
if (check_regs.flag_reg.vlf || check_regs.flag_reg.vdet || !reg_is_valid) {
|
||||
/* if the electric low flag, initialize external RTC */
|
||||
iot_printf("%s waring - electric low flag vlf %lu, vdet %lu\n",
|
||||
__FUNCTION__, check_regs.flag_reg.vlf, check_regs.flag_reg.vdet);
|
||||
iot_printf("%s bl8025t register time value, sec = %lu, min = %lu,"
|
||||
"hour = %lu, week =%lu, day = %lu, mon = %lu, year = %lu\n",
|
||||
__FUNCTION__, cal_regs.sec_reg.sec, cal_regs.min_reg.min,
|
||||
cal_regs.hour_reg.hour, cal_regs.week_reg.week,
|
||||
cal_regs.day_reg.day, cal_regs.year_reg.year);
|
||||
arx8025t_software_reset();
|
||||
os_delay(1000);
|
||||
/* write logic 0 and start the oscillator */
|
||||
check_regs.flag_reg.vlf = 0;
|
||||
check_regs.flag_reg.vdet = 0;
|
||||
if (!reg_is_valid) {
|
||||
cal_regs.sec_reg.sec = iot_byte_to_bcd(tm->tm_sec);
|
||||
cal_regs.min_reg.min = iot_byte_to_bcd(tm->tm_min);
|
||||
cal_regs.hour_reg.hour = iot_byte_to_bcd(tm->tm_hour);
|
||||
cal_regs.day_reg.day = iot_byte_to_bcd(tm->tm_mday);
|
||||
cal_regs.mon_reg.mon = iot_byte_to_bcd(tm->tm_mon);
|
||||
if (tm->tm_year < 2000) {
|
||||
tm->tm_year = 2000;
|
||||
}
|
||||
cal_regs.year_reg.year = iot_byte_to_bcd(tm->tm_year - 2000);
|
||||
}
|
||||
ret = bl8025t_write_regs(BL8025T_SEC_REG_ADDR, (uint8_t*)&cal_regs,
|
||||
sizeof(cal_regs));
|
||||
if (ret) {
|
||||
ret = ERR_BUSY;
|
||||
goto err;
|
||||
}
|
||||
ret = bl8025t_write_regs(BL8025T_FLAG_REG_ADDR, (uint8_t*)&check_regs,
|
||||
sizeof(check_regs));
|
||||
if (ret) {
|
||||
ret = ERR_BUSY;
|
||||
goto err;
|
||||
}
|
||||
if (!reg_is_valid) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* set fout pin output 1ZH frequency */
|
||||
ret = bl8025t_read_regs(BL8025T_EXTEND_REG_ADDR, (uint8_t*)&extend_reg,
|
||||
sizeof(extend_reg));
|
||||
if (ret) {
|
||||
IOT_ASSERT(0);
|
||||
ret = ERR_FAIL;
|
||||
goto err;
|
||||
}
|
||||
iot_printf("%s fout = %d!\n", __FUNCTION__, extend_reg.fsel);
|
||||
if (extend_reg.fsel != BL8025T_FOUT_FRE_1HZ) {
|
||||
extend_reg.fsel = BL8025T_FOUT_FRE_1HZ;
|
||||
ret = bl8025t_write_regs(BL8025T_EXTEND_REG_ADDR,
|
||||
(uint8_t*)&extend_reg, sizeof(extend_reg));
|
||||
if (ret) {
|
||||
IOT_ASSERT(0);
|
||||
ret = ERR_FAIL;
|
||||
goto err;
|
||||
}
|
||||
iot_printf("%s set fout %d!\n", __FUNCTION__, extend_reg.fsel);
|
||||
}
|
||||
tm->tm_sec = iot_bcd_to_byte(cal_regs.sec_reg.sec);
|
||||
tm->tm_min = iot_bcd_to_byte(cal_regs.min_reg.min);
|
||||
tm->tm_hour = iot_bcd_to_byte(cal_regs.hour_reg.hour);
|
||||
tm->tm_mday = iot_bcd_to_byte(cal_regs.day_reg.day);
|
||||
tm->tm_mon = iot_bcd_to_byte(cal_regs.mon_reg.mon);
|
||||
tm->tm_year = iot_bcd_to_byte(cal_regs.year_reg.year) + 2000;
|
||||
*done = 1;
|
||||
goto out;
|
||||
|
||||
err:
|
||||
iot_printf("%s fail\n", __FUNCTION__);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bl8025t_deinit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static uint32_t bl8025t_probe(void)
|
||||
{
|
||||
uint8_t addr;
|
||||
uint32_t ret = ERR_OK;
|
||||
iot_i2c_module_cfg_t iic_cfg = { 0 };
|
||||
|
||||
/* I2C configuration */
|
||||
iic_cfg.baud = BL8025T_IIC_DEF_SPEED;
|
||||
iic_cfg.gpio.scl = iot_board_get_gpio(GPIO_EXT_RTC_I2C_SCL);
|
||||
iic_cfg.gpio.sda = iot_board_get_gpio(GPIO_EXT_RTC_I2C_SDA);
|
||||
iic_cfg.nack_wait_num = BL8025T_IIC_DEF_NACK_NUM;
|
||||
iic_cfg.port = BL8025T_IIC_DEF_PORT;
|
||||
|
||||
if ((GPIO_NO_VALID == iic_cfg.gpio.scl) ||
|
||||
(GPIO_NO_VALID == iic_cfg.gpio.sda)) {
|
||||
ret = ERR_NOSUPP;
|
||||
return ret;
|
||||
}
|
||||
/* iot_gpio_open_as_output can cancel the function bound on the GPIO.
|
||||
* This is not necessary if those GPIOs are not multiplex.
|
||||
*/
|
||||
if ((ERR_OK != iot_gpio_open_as_output(iic_cfg.gpio.scl))
|
||||
|| (ERR_OK != iot_gpio_open_as_output(iic_cfg.gpio.sda))) {
|
||||
iot_printf("%s open iic gpio fail!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
if (ERR_OK != iot_i2c_module_init(&iic_cfg)) {
|
||||
iot_printf("%s init i2c module fail!\n", __FUNCTION__);
|
||||
ret = ERR_NOSUPP;
|
||||
return ret;
|
||||
}
|
||||
if (ERR_OK != bl8025t_read_regs(BL8025T_SEC_REG_ADDR, (uint8_t*)&addr, 1)) {
|
||||
ret = ERR_NOSUPP;
|
||||
return ret;
|
||||
}
|
||||
iot_printf("%s rtc chip is BL8025! \n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* define bl8025t device */
|
||||
const iot_ext_rtc_drv_t g_bl8025t_drv = {
|
||||
.drv_prode = bl8025t_probe,
|
||||
.drv_init = bl8025t_init,
|
||||
.drv_deinit = bl8025t_deinit,
|
||||
.drv_get_time = bl8025t_get_time,
|
||||
.drv_set_time = bl8025t_set_time,
|
||||
.drv_is_startup = bl8025t_is_startup,
|
||||
};
|
||||
|
||||
#endif /* IOT_EXT_RTC_BL8025T_ENABLE */
|
||||
163
driver/extern/rtc/src/iot_rtc_ext.c
vendored
Normal file
163
driver/extern/rtc/src/iot_rtc_ext.c
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
||||
* be copied by any method or incorporated into another program without
|
||||
* the express written consent of Aerospace C.Power. This Information or any portion
|
||||
* thereof remains the property of Aerospace C.Power. The Information contained herein
|
||||
* is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
||||
* liability for its use in any way and conveys no license or title under
|
||||
* any patent or copyright and makes no representation or warranty that this
|
||||
* Information is free from patent or copyright infringement.
|
||||
*
|
||||
* ****************************************************************************/
|
||||
|
||||
/* os_ship header files */
|
||||
#include "os_timer_api.h"
|
||||
#include "os_utils_api.h"
|
||||
|
||||
/* iot common header files */
|
||||
#include "iot_config_api.h"
|
||||
#include "iot_utils_api.h"
|
||||
#include "iot_gpio_api.h"
|
||||
#include "iot_io_api.h"
|
||||
#include "iot_errno_api.h"
|
||||
#include "iot_rtc_api.h"
|
||||
#include "iot_config.h"
|
||||
#include "iot_rtc_ext.h"
|
||||
|
||||
#if IOT_RTC_EXT_ENABLE
|
||||
|
||||
#if HW_PLATFORM != HW_PLATFORM_SIMU
|
||||
#if IOT_EXT_RTC_M41T0_ENABLE
|
||||
extern iot_ext_rtc_drv_t g_m41t0_drv;
|
||||
#endif
|
||||
#if IOT_EXT_RTC_BL8025T_ENABLE
|
||||
extern iot_ext_rtc_drv_t g_bl8025t_drv;
|
||||
#endif
|
||||
#if IOT_EXT_RTC_RX8010_ENABLE
|
||||
extern iot_ext_rtc_drv_t g_rx8010_drv;
|
||||
#endif
|
||||
#else
|
||||
extern iot_ext_rtc_drv_t g_simu_rtc_drv;
|
||||
#endif
|
||||
|
||||
iot_ext_rtc_drv_t *g_ext_rtc_drv_table[IOT_EXT_RTC_DRV_TABLE_SIZE] = {
|
||||
#if HW_PLATFORM != HW_PLATFORM_SIMU
|
||||
#if IOT_EXT_RTC_RX8010_ENABLE
|
||||
&g_rx8010_drv,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
|
||||
#if IOT_EXT_RTC_M41T0_ENABLE
|
||||
&g_m41t0_drv,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
|
||||
#if IOT_EXT_RTC_BL8025T_ENABLE
|
||||
&g_bl8025t_drv,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
NULL,
|
||||
#else
|
||||
&g_simu_rtc_drv,
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
static iot_ext_rtc_drv_t *g_ext_rtc = NULL;
|
||||
|
||||
uint32_t iot_rtc_ext_get_time(iot_time_tm_t *tm)
|
||||
{
|
||||
if (NULL == g_ext_rtc) {
|
||||
return ERR_NOSUPP;
|
||||
}
|
||||
IOT_ASSERT(g_ext_rtc->drv_get_time);
|
||||
return g_ext_rtc->drv_get_time(tm);
|
||||
}
|
||||
|
||||
uint32_t iot_rtc_ext_set_time(iot_time_tm_t *tm, uint8_t week)
|
||||
{
|
||||
if (NULL == g_ext_rtc) {
|
||||
return ERR_NOSUPP;
|
||||
}
|
||||
IOT_ASSERT(g_ext_rtc->drv_set_time);
|
||||
return g_ext_rtc->drv_set_time(tm, week);
|
||||
}
|
||||
|
||||
uint32_t iot_rtc_ext_is_startup(iot_time_tm_t *tm)
|
||||
{
|
||||
if (NULL == g_ext_rtc) {
|
||||
return 0;
|
||||
}
|
||||
IOT_ASSERT(g_ext_rtc->drv_is_startup);
|
||||
return g_ext_rtc->drv_is_startup(tm);
|
||||
}
|
||||
|
||||
uint32_t iot_rtc_ext_init(iot_time_tm_t *tm, uint32_t *done)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < IOT_EXT_RTC_DRV_TABLE_SIZE; i++) {
|
||||
if (g_ext_rtc_drv_table[i] &&
|
||||
ERR_OK == g_ext_rtc_drv_table[i]->drv_prode()) {
|
||||
g_ext_rtc = g_ext_rtc_drv_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!g_ext_rtc) {
|
||||
return ERR_NOSUPP;
|
||||
}
|
||||
if (ERR_OK != g_ext_rtc->drv_init(tm, done)) {
|
||||
g_ext_rtc = NULL;
|
||||
return ERR_NOSUPP;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void iot_rtc_ext_deinit(void)
|
||||
{
|
||||
if (g_ext_rtc) {
|
||||
IOT_ASSERT(g_ext_rtc->drv_deinit);
|
||||
g_ext_rtc->drv_deinit();
|
||||
}
|
||||
}
|
||||
|
||||
#else /* IOT_RTC_EXT_ENABLE */
|
||||
|
||||
uint32_t iot_rtc_ext_get_time(iot_time_tm_t *tm)
|
||||
{
|
||||
(void)tm;
|
||||
return ERR_NOSUPP;
|
||||
}
|
||||
|
||||
uint32_t iot_rtc_ext_set_time(iot_time_tm_t *tm, uint8_t week)
|
||||
{
|
||||
(void)tm;
|
||||
(void)week;
|
||||
return ERR_NOSUPP;
|
||||
}
|
||||
|
||||
uint32_t iot_rtc_ext_is_startup(iot_time_tm_t *tm)
|
||||
{
|
||||
(void)tm;
|
||||
return ERR_NOSUPP;
|
||||
}
|
||||
|
||||
uint32_t iot_rtc_ext_init(iot_time_tm_t *tm, uint32_t *done)
|
||||
{
|
||||
(void)tm;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void iot_rtc_ext_deinit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif /* IOT_RTC_EXT_ENABLE */
|
||||
|
||||
440
driver/extern/rtc/src/m41t0_driver.c
vendored
Normal file
440
driver/extern/rtc/src/m41t0_driver.c
vendored
Normal file
@@ -0,0 +1,440 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
||||
* be copied by any method or incorporated into another program without
|
||||
* the express written consent of Aerospace C.Power. This Information or any portion
|
||||
* thereof remains the property of Aerospace C.Power. The Information contained herein
|
||||
* is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
||||
* liability for its use in any way and conveys no license or title under
|
||||
* any patent or copyright and makes no representation or warranty that this
|
||||
* Information is free from patent or copyright infringement.
|
||||
*
|
||||
* ****************************************************************************/
|
||||
|
||||
/* os_ship header files */
|
||||
#include "os_utils_api.h"
|
||||
|
||||
/* iot common header files */
|
||||
#include "iot_config_api.h"
|
||||
#include "iot_utils_api.h"
|
||||
#include "iot_i2c_api.h"
|
||||
#include "iot_gpio_api.h"
|
||||
#include "iot_board_api.h"
|
||||
#include "iot_io_api.h"
|
||||
#include "iot_errno_api.h"
|
||||
#include "iot_config.h"
|
||||
|
||||
/* iot common header files */
|
||||
#include "iot_rtc_api.h"
|
||||
#include "iot_rtc_ext.h"
|
||||
|
||||
#if IOT_EXT_RTC_M41T0_ENABLE
|
||||
|
||||
#define M41T0_TRANS_BUF_CNT 16
|
||||
|
||||
/* the iic config of m41t0. */
|
||||
#define M41T0_IIC_PHY_ADDR 0x68 /* shift as (0x68 << 1) in driver. */
|
||||
#define M41T0_IIC_DEF_PORT 0 /* Port#0. */
|
||||
#define M41T0_IIC_DEF_SPEED 100 /* 100K. */
|
||||
#define M41T0_IIC_DEF_NACK_NUM 1 /* N-ACK number. */
|
||||
|
||||
/* m41t0 register internal address definition */
|
||||
#define M41T0_SEC_REG_ADDR 0x00
|
||||
#define M41T0_MIN_REG_ADDR 0x01
|
||||
#define M41T0_HOUR_REG_ADDR 0x02
|
||||
#define M41T0_WEEK_REG_ADDR 0x03
|
||||
#define M41T0_DAY_REG_ADDR 0x04
|
||||
#define M41T0_MON_REG_ADDR 0x05
|
||||
#define M41T0_YAER_REG_ADDR 0x06
|
||||
#define M41T0_CTRL_REG_ADDR 0x07
|
||||
|
||||
/* m41t0 sec register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - seconds, BCD format */
|
||||
uint8_t sec :7,
|
||||
/* flag to mark if oscillator fail */
|
||||
stop :1;
|
||||
} m41t0_sec_reg_t;
|
||||
|
||||
/* m41t0 min register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - min, BCD format */
|
||||
uint8_t min :7,
|
||||
/* flag to mark if oscillator fail */
|
||||
of :1;
|
||||
} m41t0_min_reg_t;
|
||||
|
||||
/* m41t0 hour register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - hour, BCD format */
|
||||
uint8_t hour :6,
|
||||
/* don't care */
|
||||
rsvd :2;
|
||||
} m41t0_hour_reg_t;
|
||||
|
||||
/* m41t0 week register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - week, BCD format */
|
||||
uint8_t week :3,
|
||||
/* don't care */
|
||||
rsvd :5;
|
||||
} m41t0_week_reg_t;
|
||||
|
||||
/* m41t0 day register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - day, BCD format */
|
||||
uint8_t day :6,
|
||||
/* don't care */
|
||||
rsvd :2;
|
||||
} m41t0_day_reg_t;
|
||||
|
||||
/* m41t0 mon register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - mon, BCD format */
|
||||
uint8_t mon :5,
|
||||
/* don't care */
|
||||
rsvd :3;
|
||||
} m41t0_mon_reg_t;
|
||||
|
||||
/* m41t0 year register layout definition */
|
||||
typedef struct {
|
||||
/* calendar time - year, BCD format */
|
||||
uint8_t year;
|
||||
} m41t0_year_reg_t;
|
||||
|
||||
/* m41t0 calendar layout */
|
||||
typedef struct {
|
||||
/* sec register */
|
||||
m41t0_sec_reg_t sec_reg;
|
||||
/* min register */
|
||||
m41t0_min_reg_t min_reg;
|
||||
/* hour register */
|
||||
m41t0_hour_reg_t hour_reg;
|
||||
/* week register */
|
||||
m41t0_week_reg_t week_reg;
|
||||
/* day register */
|
||||
m41t0_day_reg_t day_reg;
|
||||
/* mon register */
|
||||
m41t0_mon_reg_t mon_reg;
|
||||
/* year register */
|
||||
m41t0_year_reg_t year_reg;
|
||||
} m41t0_calendar_reg_t;
|
||||
|
||||
/* check the validity of the calendar register */
|
||||
#define m41t0_sec_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x59)
|
||||
#define m41t0_min_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x59)
|
||||
#define m41t0_hour_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x23)
|
||||
#define m41t0_day_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x31 && (x) >= 1)
|
||||
#define m41t0_mon_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x12 && (x) >= 1)
|
||||
#define m41t0_year_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x99)
|
||||
|
||||
static uint8_t buf[M41T0_TRANS_BUF_CNT];
|
||||
|
||||
static uint8_t m41t0_regs_is_valid(m41t0_calendar_reg_t *regs)
|
||||
{
|
||||
uint8_t reason = 0;
|
||||
if (!regs) {
|
||||
reason = 1;
|
||||
IOT_ASSERT(0);
|
||||
goto err;
|
||||
}
|
||||
if (!m41t0_sec_is_valid(regs->sec_reg.sec)) {
|
||||
reason = 2;
|
||||
goto err;
|
||||
}
|
||||
if (!m41t0_min_is_valid(regs->min_reg.min)) {
|
||||
reason = 3;
|
||||
goto err;
|
||||
}
|
||||
if (!m41t0_hour_is_valid(regs->hour_reg.hour)) {
|
||||
reason = 4;
|
||||
goto err;
|
||||
}
|
||||
if (!m41t0_day_is_valid(regs->day_reg.day)) {
|
||||
reason = 5;
|
||||
goto err;
|
||||
}
|
||||
if (!m41t0_mon_is_valid(regs->mon_reg.mon)) {
|
||||
reason = 6;
|
||||
goto err;
|
||||
}
|
||||
if (!m41t0_year_is_valid(regs->year_reg.year)) {
|
||||
reason = 7;
|
||||
goto err;
|
||||
}
|
||||
return ERR_OK;
|
||||
err:
|
||||
iot_printf("%s err, reason %lu\n", __FUNCTION__, reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
||||
static uint32_t m41t0_read_regs(uint8_t addr, uint8_t *data, uint8_t cnt)
|
||||
{
|
||||
uint8_t reason = 0;
|
||||
if(ERR_OK != iot_i2c_write(M41T0_IIC_DEF_PORT, M41T0_IIC_PHY_ADDR,
|
||||
(char *)&addr, 1)) {
|
||||
reason = 1;
|
||||
goto out;
|
||||
}
|
||||
os_delay(10);
|
||||
|
||||
if(ERR_OK != iot_i2c_read(M41T0_IIC_DEF_PORT, M41T0_IIC_PHY_ADDR,
|
||||
(char *)data, cnt)) {
|
||||
reason = 1;
|
||||
goto out;
|
||||
}
|
||||
os_delay(5);
|
||||
out:
|
||||
if (reason) {
|
||||
iot_printf("%s fail, reason %lu\n", __FUNCTION__, reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static uint32_t m41t0_write_regs(uint8_t addr, uint8_t *data, uint8_t cnt)
|
||||
{
|
||||
buf[0] = addr;
|
||||
os_mem_cpy(buf + 1, data, cnt);
|
||||
if (cnt > (IOT_ARRAY_CNT(buf) - 1)) {
|
||||
return ERR_NOMEM;
|
||||
}
|
||||
iot_i2c_write(M41T0_IIC_DEF_PORT, M41T0_IIC_PHY_ADDR,
|
||||
(char *)buf, cnt + 1);
|
||||
os_delay(10);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static uint32_t m41t0_get_time(iot_time_tm_t *tm)
|
||||
{
|
||||
uint32_t ret;
|
||||
iot_time_tm_t in_tm;
|
||||
uint8_t reason = 0;
|
||||
m41t0_calendar_reg_t regs = { 0 };
|
||||
ret = m41t0_read_regs(M41T0_SEC_REG_ADDR, (uint8_t *)®s, sizeof(regs));
|
||||
if (ret != ERR_OK) {
|
||||
reason = 1;
|
||||
goto err;
|
||||
}
|
||||
if (regs.sec_reg.stop || regs.min_reg.of) {
|
||||
regs.min_reg.of = 0;
|
||||
regs.sec_reg.stop = 0;
|
||||
if (iot_rtc_data_is_revised()) {
|
||||
iot_rtc_get(&in_tm);
|
||||
regs.sec_reg.sec = iot_byte_to_bcd(in_tm.tm_sec);
|
||||
regs.min_reg.min = iot_byte_to_bcd(in_tm.tm_min);
|
||||
regs.hour_reg.hour = iot_byte_to_bcd(in_tm.tm_hour);
|
||||
regs.day_reg.day = iot_byte_to_bcd(in_tm.tm_mday);
|
||||
regs.mon_reg.mon = iot_byte_to_bcd(in_tm.tm_mon);
|
||||
if (in_tm.tm_year < 2000) {
|
||||
in_tm.tm_year = 2000;
|
||||
}
|
||||
regs.year_reg.year = iot_byte_to_bcd(in_tm.tm_year - 2000);
|
||||
}
|
||||
ret = m41t0_write_regs(M41T0_SEC_REG_ADDR, (uint8_t*)®s,
|
||||
sizeof(regs));
|
||||
if (ret) {
|
||||
reason = 2;
|
||||
goto err;
|
||||
}
|
||||
reason = 3;
|
||||
goto err;
|
||||
}
|
||||
if (m41t0_regs_is_valid(®s) != ERR_OK) {
|
||||
reason = 4;
|
||||
goto err;
|
||||
}
|
||||
tm->tm_sec = iot_bcd_to_byte(regs.sec_reg.sec);
|
||||
tm->tm_min = iot_bcd_to_byte(regs.min_reg.min);
|
||||
tm->tm_hour = iot_bcd_to_byte(regs.hour_reg.hour);
|
||||
tm->tm_mday = iot_bcd_to_byte(regs.day_reg.day);
|
||||
tm->tm_mon = iot_bcd_to_byte(regs.mon_reg.mon);
|
||||
tm->tm_year = iot_bcd_to_byte(regs.year_reg.year) + 2000;
|
||||
iot_printf("%s %lu-%lu-%lu %lu:%lu:%lu\n", __FUNCTION__,
|
||||
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
|
||||
tm->tm_sec);
|
||||
return ERR_OK;
|
||||
err:
|
||||
iot_printf("%s err, reason %lu\n", __FUNCTION__, reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
||||
static uint32_t m41t0_set_time(iot_time_tm_t *tm, uint8_t week)
|
||||
{
|
||||
uint32_t ret;
|
||||
m41t0_calendar_reg_t regs = { 0 };
|
||||
ret = m41t0_read_regs(M41T0_SEC_REG_ADDR, (uint8_t *)®s, sizeof(regs));
|
||||
if (ret) {
|
||||
goto err;
|
||||
}
|
||||
if (regs.sec_reg.stop || regs.min_reg.of) {
|
||||
goto err;
|
||||
}
|
||||
regs.sec_reg.sec = iot_byte_to_bcd(tm->tm_sec);
|
||||
regs.min_reg.min = iot_byte_to_bcd(tm->tm_min);
|
||||
regs.hour_reg.hour = iot_byte_to_bcd(tm->tm_hour);
|
||||
regs.day_reg.day = iot_byte_to_bcd(tm->tm_mday);
|
||||
regs.week_reg.week = week;
|
||||
regs.mon_reg.mon = iot_byte_to_bcd(tm->tm_mon);
|
||||
regs.year_reg.year = iot_byte_to_bcd(tm->tm_year - 2000);
|
||||
iot_printf("%s %02x-%02x-%02x %02x:%02x:%02x week %lu\n",
|
||||
__FUNCTION__, regs.year_reg.year,
|
||||
regs.mon_reg.mon, regs.day_reg.day, regs.hour_reg.hour,
|
||||
regs.min_reg.min, regs.sec_reg.sec, week);
|
||||
ret = m41t0_write_regs(M41T0_SEC_REG_ADDR, (uint8_t *)®s, sizeof(regs));
|
||||
if (ret) {
|
||||
IOT_ASSERT(0);
|
||||
goto err;
|
||||
}
|
||||
return ERR_OK;
|
||||
|
||||
err:
|
||||
IOT_ASSERT(0);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
||||
static uint32_t m41t0_is_startup(iot_time_tm_t *tm)
|
||||
{
|
||||
uint32_t ret;
|
||||
m41t0_calendar_reg_t regs;
|
||||
ret = m41t0_read_regs(M41T0_SEC_REG_ADDR, (uint8_t *)®s, sizeof(regs));
|
||||
IOT_ASSERT(ret == ERR_OK);
|
||||
if (!regs.min_reg.of) {
|
||||
tm->tm_sec = iot_bcd_to_byte(regs.sec_reg.sec);
|
||||
tm->tm_min = iot_bcd_to_byte(regs.min_reg.min);
|
||||
tm->tm_hour = iot_bcd_to_byte(regs.hour_reg.hour);
|
||||
tm->tm_mday = iot_bcd_to_byte(regs.day_reg.day);
|
||||
tm->tm_mon = iot_bcd_to_byte(regs.mon_reg.mon);
|
||||
tm->tm_year = iot_bcd_to_byte(regs.year_reg.year) + 2000;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t m41t0_init(iot_time_tm_t *tm, uint32_t *done)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint8_t reg_is_valid = 1;
|
||||
m41t0_calendar_reg_t regs = { 0 };
|
||||
*done = 0;
|
||||
|
||||
ret = m41t0_read_regs(M41T0_SEC_REG_ADDR, (uint8_t*)®s, sizeof(regs));
|
||||
if (ret) {
|
||||
IOT_ASSERT(0);
|
||||
ret = ERR_FAIL;
|
||||
goto err;
|
||||
}
|
||||
if (m41t0_regs_is_valid(®s) != ERR_OK) {
|
||||
reg_is_valid = 0;
|
||||
}
|
||||
if (regs.min_reg.of || !reg_is_valid) {
|
||||
/* if the oscillator stops, get system time, initialize external RTC */
|
||||
iot_printf("%s waring - oscillator stop, of %lu, stop %lu\n",
|
||||
__FUNCTION__, regs.min_reg.of, regs.sec_reg.stop);
|
||||
iot_printf("%s m41t0 register time value, sec = %lu, min = %lu,"
|
||||
"hour = %lu, week =%lu, day = %lu, mon = %lu, year = %lu\n",
|
||||
__FUNCTION__, regs.sec_reg.sec, regs.min_reg.min,
|
||||
regs.hour_reg.hour, regs.week_reg.week, regs.day_reg.day,
|
||||
regs.year_reg.year);
|
||||
|
||||
/* write logic 0 and start the oscillator */
|
||||
regs.min_reg.of = 0;
|
||||
regs.sec_reg.stop = 0;
|
||||
if (!reg_is_valid) {
|
||||
regs.sec_reg.sec = iot_byte_to_bcd(tm->tm_sec);
|
||||
regs.min_reg.min = iot_byte_to_bcd(tm->tm_min);
|
||||
regs.hour_reg.hour = iot_byte_to_bcd(tm->tm_hour);
|
||||
regs.day_reg.day = iot_byte_to_bcd(tm->tm_mday);
|
||||
regs.mon_reg.mon = iot_byte_to_bcd(tm->tm_mon);
|
||||
if (tm->tm_year < 2000) {
|
||||
tm->tm_year = 2000;
|
||||
}
|
||||
regs.year_reg.year = iot_byte_to_bcd(tm->tm_year - 2000);
|
||||
}
|
||||
ret = m41t0_write_regs(M41T0_SEC_REG_ADDR, (uint8_t*)®s,
|
||||
sizeof(regs));
|
||||
if (ret) {
|
||||
ret = ERR_BUSY;
|
||||
goto err;
|
||||
}
|
||||
if (!reg_is_valid) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
tm->tm_sec = iot_bcd_to_byte(regs.sec_reg.sec);
|
||||
tm->tm_min = iot_bcd_to_byte(regs.min_reg.min);
|
||||
tm->tm_hour = iot_bcd_to_byte(regs.hour_reg.hour);
|
||||
tm->tm_mday = iot_bcd_to_byte(regs.day_reg.day);
|
||||
tm->tm_mon = iot_bcd_to_byte(regs.mon_reg.mon);
|
||||
tm->tm_year = iot_bcd_to_byte(regs.year_reg.year) + 2000;
|
||||
*done = 1;
|
||||
goto out;
|
||||
|
||||
err:
|
||||
iot_printf("%s fail\n", __FUNCTION__);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void m41t0_deinit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static uint32_t m41t0_probe(void)
|
||||
{
|
||||
uint8_t addr;
|
||||
uint32_t ret = ERR_OK;
|
||||
iot_i2c_module_cfg_t iic_cfg = { 0 };
|
||||
|
||||
/* I2C configuration */
|
||||
iic_cfg.baud = M41T0_IIC_DEF_SPEED;
|
||||
iic_cfg.gpio.scl = iot_board_get_gpio(GPIO_EXT_RTC_I2C_SCL);
|
||||
iic_cfg.gpio.sda = iot_board_get_gpio(GPIO_EXT_RTC_I2C_SDA);
|
||||
iic_cfg.nack_wait_num = M41T0_IIC_DEF_NACK_NUM;
|
||||
iic_cfg.port = M41T0_IIC_DEF_PORT;
|
||||
|
||||
if ((GPIO_NO_VALID == iic_cfg.gpio.scl) ||
|
||||
(GPIO_NO_VALID == iic_cfg.gpio.sda)) {
|
||||
ret = ERR_NOSUPP;
|
||||
return ret;
|
||||
}
|
||||
/* iot_gpio_open_as_output can cancel the function bound on the GPIO.
|
||||
* This is not necessary if those GPIOs are not multiplex.
|
||||
*/
|
||||
if ((ERR_OK != iot_gpio_open_as_output(iic_cfg.gpio.scl))
|
||||
|| (ERR_OK != iot_gpio_open_as_output(iic_cfg.gpio.sda))) {
|
||||
iot_printf("%s open iic gpio fail!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
if (ERR_OK != iot_i2c_module_init(&iic_cfg)) {
|
||||
iot_printf("%s init i2c module fail!\n", __FUNCTION__);
|
||||
IOT_ASSERT(0);
|
||||
}
|
||||
if (ERR_OK != m41t0_read_regs(M41T0_SEC_REG_ADDR, (uint8_t*)&addr, 1)) {
|
||||
ret = ERR_NOSUPP;
|
||||
return ret;
|
||||
}
|
||||
iot_printf("%s rtc chip is M41T0 \n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* define external RTC devices m41t0 */
|
||||
const iot_ext_rtc_drv_t g_m41t0_drv = {
|
||||
.drv_prode = m41t0_probe,
|
||||
.drv_init = m41t0_init,
|
||||
.drv_deinit = m41t0_deinit,
|
||||
.drv_get_time = m41t0_get_time,
|
||||
.drv_set_time = m41t0_set_time,
|
||||
.drv_is_startup = m41t0_is_startup,
|
||||
};
|
||||
|
||||
#endif /* IOT_EXT_RTC_M41T0_ENABLE */
|
||||
522
driver/extern/rtc/src/rx8010_driver.c
vendored
Normal file
522
driver/extern/rtc/src/rx8010_driver.c
vendored
Normal file
@@ -0,0 +1,522 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
||||
* be copied by any method or incorporated into another program without
|
||||
* the express written consent of Aerospace C.Power. This Information or any portion
|
||||
* thereof remains the property of Aerospace C.Power. The Information contained herein
|
||||
* is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
||||
* liability for its use in any way and conveys no license or title under
|
||||
* any patent or copyright and makes no representation or warranty that this
|
||||
* Information is free from patent or copyright infringement.
|
||||
*
|
||||
* Driver for the Epson RTC module RX-8010 SJ
|
||||
*
|
||||
* ****************************************************************************/
|
||||
|
||||
/* os_ship header files */
|
||||
#include "os_utils_api.h"
|
||||
|
||||
/* iot common header files */
|
||||
#include "iot_config_api.h"
|
||||
#include "iot_utils_api.h"
|
||||
#include "iot_i2c_api.h"
|
||||
#include "iot_gpio_api.h"
|
||||
#include "iot_board_api.h"
|
||||
#include "iot_io_api.h"
|
||||
#include "iot_errno_api.h"
|
||||
#include "iot_config.h"
|
||||
|
||||
/* iot common header files */
|
||||
#include "iot_rtc_api.h"
|
||||
#include "iot_rtc_ext.h"
|
||||
|
||||
#if IOT_EXT_RTC_RX8010_ENABLE
|
||||
|
||||
#define RX8010_TRANS_BUF_CNT 16
|
||||
|
||||
#define RX8010_YEAR_BASE 1900
|
||||
|
||||
/* the iic config of rx8010. */
|
||||
#define RX8010_IIC_PHY_ADDR 0x32 /* shift as (0x32 << 1) in driver. */
|
||||
#define RX8010_IIC_DEF_PORT 1 /* Port#1. */
|
||||
#define RX8010_IIC_DEF_SPEED 400 /* 400K. */
|
||||
#define RX8010_IIC_DEF_NACK_NUM 10 /* N-ACK number. */
|
||||
|
||||
// RX-8010 Register definitions
|
||||
#define RX8010_REG_SEC 0x10
|
||||
#define RX8010_REG_MIN 0x11
|
||||
#define RX8010_REG_HOUR 0x12
|
||||
#define RX8010_REG_WDAY 0x13
|
||||
#define RX8010_REG_MDAY 0x14
|
||||
#define RX8010_REG_MONTH 0x15
|
||||
#define RX8010_REG_YEAR 0x16
|
||||
// 0x17 is reserved
|
||||
#define RX8010_REG_ALMIN 0x18
|
||||
#define RX8010_REG_ALHOUR 0x19
|
||||
#define RX8010_REG_ALWDAY 0x1A
|
||||
#define RX8010_REG_TCOUNT0 0x1B
|
||||
#define RX8010_REG_TCOUNT1 0x1C
|
||||
#define RX8010_REG_EXT 0x1D
|
||||
#define RX8010_REG_FLAG 0x1E
|
||||
#define RX8010_REG_CTRL 0x1F
|
||||
#define RX8010_REG_USER0 0x20
|
||||
#define RX8010_REG_USER1 0x21
|
||||
#define RX8010_REG_USER2 0x22
|
||||
#define RX8010_REG_USER3 0x23
|
||||
#define RX8010_REG_USER4 0x24
|
||||
#define RX8010_REG_USER5 0x25
|
||||
#define RX8010_REG_USER6 0x26
|
||||
#define RX8010_REG_USER7 0x27
|
||||
#define RX8010_REG_USER8 0x28
|
||||
#define RX8010_REG_USER9 0x29
|
||||
#define RX8010_REG_USERA 0x2A
|
||||
#define RX8010_REG_USERB 0x2B
|
||||
#define RX8010_REG_USERC 0x2C
|
||||
#define RX8010_REG_USERD 0x2D
|
||||
#define RX8010_REG_USERE 0x2E
|
||||
#define RX8010_REG_USERF 0x2F
|
||||
// 0x30 is reserved
|
||||
// 0x31 is reserved
|
||||
#define RX8010_REG_IRQ 0x32
|
||||
|
||||
// Extension Register (1Dh) bit positions
|
||||
#define RX8010_BIT_EXT_TSEL (7 << 0)
|
||||
#define RX8010_BIT_EXT_WADA (1 << 3)
|
||||
#define RX8010_BIT_EXT_TE (1 << 4)
|
||||
#define RX8010_BIT_EXT_USEL (1 << 5)
|
||||
#define RX8010_BIT_EXT_FSEL (3 << 6)
|
||||
|
||||
// Flag Register (1Eh) bit positions
|
||||
#define RX8010_BIT_FLAG_VLF (1 << 1)
|
||||
#define RX8010_BIT_FLAG_AF (1 << 3)
|
||||
#define RX8010_BIT_FLAG_TF (1 << 4)
|
||||
#define RX8010_BIT_FLAG_UF (1 << 5)
|
||||
|
||||
// Control Register (1Fh) bit positions
|
||||
#define RX8010_BIT_CTRL_TSTP (1 << 2)
|
||||
#define RX8010_BIT_CTRL_AIE (1 << 3)
|
||||
#define RX8010_BIT_CTRL_TIE (1 << 4)
|
||||
#define RX8010_BIT_CTRL_UIE (1 << 5)
|
||||
#define RX8010_BIT_CTRL_STOP (1 << 6)
|
||||
#define RX8010_BIT_CTRL_TEST (1 << 7)
|
||||
|
||||
/* check the validity of the calendar register */
|
||||
#define rx8010_sec_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x59)
|
||||
#define rx8010_min_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x59)
|
||||
#define rx8010_hour_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x23)
|
||||
#define rx8010_day_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x31 && (x) >= 1)
|
||||
#define rx8010_mon_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x12 && (x) >= 1)
|
||||
#define rx8010_year_is_valid(x) \
|
||||
(iot_bcd_check(x) && (x) <= 0x99)
|
||||
|
||||
static uint8_t buf[RX8010_TRANS_BUF_CNT];
|
||||
|
||||
static uint8_t rx8010_tm_is_valid(uint8_t *date)
|
||||
{
|
||||
uint8_t reason = 0;
|
||||
if (!date) {
|
||||
reason = 1;
|
||||
IOT_ASSERT(0);
|
||||
goto err;
|
||||
}
|
||||
if (!rx8010_sec_is_valid(date[RX8010_REG_SEC-0x10] & 0x7f)) {
|
||||
reason = 2;
|
||||
goto err;
|
||||
}
|
||||
if (!rx8010_min_is_valid(date[RX8010_REG_MIN-0x10] & 0x7f)) {
|
||||
reason = 3;
|
||||
goto err;
|
||||
}
|
||||
if (!rx8010_hour_is_valid(date[RX8010_REG_HOUR-0x10] & 0x3f)) {
|
||||
reason = 4;
|
||||
goto err;
|
||||
}
|
||||
if (!rx8010_day_is_valid(date[RX8010_REG_MDAY-0x10] & 0x3f)) {
|
||||
reason = 5;
|
||||
goto err;
|
||||
}
|
||||
if (!rx8010_mon_is_valid(date[RX8010_REG_MONTH-0x10] & 0x1f)) {
|
||||
reason = 6;
|
||||
goto err;
|
||||
}
|
||||
if (!rx8010_year_is_valid(date[RX8010_REG_YEAR-0x10])) {
|
||||
reason = 7;
|
||||
goto err;
|
||||
}
|
||||
return ERR_OK;
|
||||
err:
|
||||
iot_printf("%s err, reason %lu\n", __FUNCTION__, reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
||||
static uint32_t rx8010_read_regs(uint8_t addr, uint8_t *data, uint8_t cnt)
|
||||
{
|
||||
uint8_t reason = 0;
|
||||
if(ERR_OK != iot_i2c_write(RX8010_IIC_DEF_PORT, RX8010_IIC_PHY_ADDR,
|
||||
(char *)&addr, 1)) {
|
||||
reason = 1;
|
||||
goto out;
|
||||
}
|
||||
os_delay(10);
|
||||
|
||||
if(ERR_OK != iot_i2c_read(RX8010_IIC_DEF_PORT, RX8010_IIC_PHY_ADDR,
|
||||
(char *)data, cnt)) {
|
||||
reason = 1;
|
||||
goto out;
|
||||
}
|
||||
os_delay(5);
|
||||
out:
|
||||
if (reason) {
|
||||
iot_printf("%s fail, reason %lu\n", __FUNCTION__, reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static inline uint32_t rx8010_read_reg(uint8_t addr, uint8_t *data)
|
||||
{
|
||||
return rx8010_read_regs(addr, data, 1);
|
||||
}
|
||||
|
||||
static uint32_t rx8010_write_regs(uint8_t addr, uint8_t *data, uint8_t cnt)
|
||||
{
|
||||
buf[0] = addr;
|
||||
os_mem_cpy(buf + 1, data, cnt);
|
||||
if (cnt > (IOT_ARRAY_CNT(buf) - 1)) {
|
||||
return ERR_NOMEM;
|
||||
}
|
||||
iot_i2c_write(RX8010_IIC_DEF_PORT, RX8010_IIC_PHY_ADDR,
|
||||
(char *)buf, cnt + 1);
|
||||
os_delay(10);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static inline uint32_t rx8010_write_reg(uint8_t addr, uint8_t data)
|
||||
{
|
||||
return rx8010_write_regs(addr, &data, 1);
|
||||
}
|
||||
|
||||
/* calculating Week of zeller formula */
|
||||
static uint8_t zeller_calc_week(iot_time_tm_t *tm)
|
||||
{
|
||||
iot_time_tm_t tm_temp = *tm;
|
||||
if (tm_temp.tm_mon < 3) {
|
||||
tm_temp.tm_year -= 1;
|
||||
tm_temp.tm_mon += 12;
|
||||
}
|
||||
int32_t c = tm_temp.tm_year / 100;
|
||||
int32_t y = tm_temp.tm_year % 100;
|
||||
int32_t ans = (c / 4 - 2 * c + y + y / 4 + ( 26 * ( tm_temp.tm_mon + 1)) \
|
||||
/ 10 + tm_temp.tm_mday - 1 ) % 7;
|
||||
|
||||
if (ans < 0)
|
||||
ans += 7;
|
||||
return (uint8_t)ans;
|
||||
}
|
||||
|
||||
static uint32_t rx8010_set_time(iot_time_tm_t *tm, uint8_t week)
|
||||
{
|
||||
uint8_t date[7];
|
||||
uint8_t ctrl;
|
||||
uint32_t reason;
|
||||
uint32_t ret = ERR_OK;
|
||||
|
||||
//set STOP bit before changing clock/calendar
|
||||
ret |= rx8010_read_reg(RX8010_REG_CTRL, &ctrl);
|
||||
ctrl |= RX8010_BIT_CTRL_STOP;
|
||||
ret |= rx8010_write_reg(RX8010_REG_CTRL, ctrl);
|
||||
if (ERR_OK != ret) {
|
||||
reason = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//Note: need to subtract 0x10 for index as register offset starts at 0x10
|
||||
date[RX8010_REG_SEC-0x10] = iot_byte_to_bcd(tm->tm_sec);
|
||||
date[RX8010_REG_MIN-0x10] = iot_byte_to_bcd(tm->tm_min);
|
||||
date[RX8010_REG_HOUR-0x10] = iot_byte_to_bcd(tm->tm_hour); //only 24hr time
|
||||
date[RX8010_REG_MDAY-0x10] = iot_byte_to_bcd(tm->tm_mday);
|
||||
date[RX8010_REG_MONTH-0x10] = iot_byte_to_bcd(tm->tm_mon + 1);
|
||||
date[RX8010_REG_YEAR-0x10] = iot_byte_to_bcd(tm->tm_year % 100);
|
||||
date[RX8010_REG_WDAY-0x10] = iot_byte_to_bcd(week);
|
||||
|
||||
iot_printf("%s: write 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
|
||||
__func__, date[0], date[1], date[2], date[3], date[4], date[5],date[6]);
|
||||
|
||||
ret = rx8010_write_regs(RX8010_REG_SEC, date, 7);
|
||||
if (ERR_OK != ret) {
|
||||
reason = 2;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//clear STOP bit after changing clock/calendar
|
||||
ret |= rx8010_read_reg(RX8010_REG_CTRL, &ctrl);
|
||||
ctrl = ctrl & ~RX8010_BIT_CTRL_STOP;
|
||||
ret |= rx8010_write_reg(RX8010_REG_CTRL, ctrl);
|
||||
if (ERR_OK != ret) {
|
||||
reason = 3;
|
||||
goto err;
|
||||
}
|
||||
return ERR_OK;
|
||||
|
||||
err:
|
||||
iot_printf("%s: rx8010 set time failed, reason:%d\n", __func__, reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
||||
static uint32_t rx8010_get_time(iot_time_tm_t *tm)
|
||||
{
|
||||
uint8_t date[7];
|
||||
uint8_t ctrl;
|
||||
uint32_t err;
|
||||
uint32_t reason = 0;
|
||||
iot_time_tm_t in_tm;
|
||||
|
||||
err = rx8010_read_reg(RX8010_REG_CTRL, &ctrl);
|
||||
if (ERR_OK != err) {
|
||||
reason = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (RX8010_BIT_CTRL_STOP == (ctrl & RX8010_BIT_CTRL_STOP)) {
|
||||
if (iot_rtc_data_is_revised()) {
|
||||
iot_rtc_get(&in_tm);
|
||||
if (ERR_OK != rx8010_set_time(&in_tm, zeller_calc_week(&in_tm))) {
|
||||
reason = 2;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
reason = 3;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = rx8010_read_regs(RX8010_REG_SEC, date, 7);
|
||||
if (ERR_OK != err) {
|
||||
reason = 4;
|
||||
goto err;
|
||||
}
|
||||
|
||||
iot_printf("%s: read 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
|
||||
__func__, date[0], date[1], date[2], date[3], date[4], date[5],date[6]);
|
||||
|
||||
if (ERR_OK != rx8010_tm_is_valid(date)) {
|
||||
reason = 5;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//Note: need to subtract 0x10 for index as register offset starts at 0x10
|
||||
tm->tm_sec = iot_bcd_to_byte(date[RX8010_REG_SEC-0x10] & 0x7f);
|
||||
tm->tm_min = iot_bcd_to_byte(date[RX8010_REG_MIN-0x10] & 0x7f);
|
||||
tm->tm_hour = iot_bcd_to_byte(date[RX8010_REG_HOUR-0x10] & 0x3f); //only 24-hour clock
|
||||
tm->tm_mday = iot_bcd_to_byte(date[RX8010_REG_MDAY-0x10] & 0x3f);
|
||||
tm->tm_mon = iot_bcd_to_byte(date[RX8010_REG_MONTH-0x10] & 0x1f) - 1;
|
||||
tm->tm_year = iot_bcd_to_byte(date[RX8010_REG_YEAR-0x10]);
|
||||
|
||||
if (tm->tm_year < 70)
|
||||
tm->tm_year += 100;
|
||||
|
||||
tm->tm_year += RX8010_YEAR_BASE;
|
||||
|
||||
iot_printf("%s: date %d-%d-%d %d:%d:%d\n", __func__,
|
||||
tm->tm_year, tm->tm_mon, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
|
||||
return ERR_OK;
|
||||
|
||||
err:
|
||||
iot_printf("%s err, reason %lu\n", __FUNCTION__, reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
||||
static uint32_t rx8010_is_startup(iot_time_tm_t *tm)
|
||||
{
|
||||
iot_printf("%s: try to get time\n");
|
||||
return rx8010_get_time(tm);
|
||||
}
|
||||
|
||||
static uint32_t rx8010_init(iot_time_tm_t *tm, uint32_t *done)
|
||||
{
|
||||
uint8_t ctrl[3];
|
||||
uint8_t need_clear = 0;
|
||||
uint8_t need_reset = 0;
|
||||
uint32_t reason = 0;
|
||||
uint32_t ret;
|
||||
|
||||
*done = 0;
|
||||
|
||||
//set reserved register 0x17 with specified value of 0xD8
|
||||
ret = rx8010_write_reg(0x17, 0xD8);
|
||||
if (ret) {
|
||||
reason = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//set reserved register 0x30 with specified value of 0x00
|
||||
ret = rx8010_write_reg(0x30, 0x00);
|
||||
if (ret) {
|
||||
reason = 2;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//set reserved register 0x31 with specified value of 0x08
|
||||
ret = rx8010_write_reg(0x31, 0x08);
|
||||
if (ret) {
|
||||
reason = 3;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//set reserved register 0x32 with default value
|
||||
ret = rx8010_write_reg(RX8010_REG_IRQ, 0x00);
|
||||
if (ret) {
|
||||
reason = 4;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//get current extension, flag, control register values
|
||||
ret = rx8010_read_regs(RX8010_REG_EXT, ctrl, 3);
|
||||
if (ret) {
|
||||
reason = 5;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//check for VLF Flag (set at power-on)
|
||||
if ((ctrl[1] & RX8010_BIT_FLAG_VLF)) {
|
||||
iot_printf("Frequency stop was detected, "
|
||||
"probably due to a supply voltage drop\n");
|
||||
need_reset = 1;
|
||||
}
|
||||
|
||||
//check for Alarm Flag
|
||||
if (ctrl[1] & RX8010_BIT_FLAG_AF) {
|
||||
iot_printf("Alarm was detected\n");
|
||||
need_clear = 1;
|
||||
}
|
||||
|
||||
//check for Periodic Timer Flag
|
||||
if (ctrl[1] & RX8010_BIT_FLAG_TF) {
|
||||
iot_printf("Periodic timer was detected\n");
|
||||
need_clear = 1;
|
||||
}
|
||||
|
||||
//check for Update Timer Flag
|
||||
if (ctrl[1] & RX8010_BIT_FLAG_UF) {
|
||||
iot_printf("Update timer was detected\n");
|
||||
need_clear = 1;
|
||||
}
|
||||
|
||||
//reset or clear needed?
|
||||
if (need_reset) {
|
||||
//clear 1d, 1e, 1f registers
|
||||
ctrl[0] = ctrl[1] = ctrl[2] = 0;
|
||||
ret = rx8010_write_regs(RX8010_REG_EXT, ctrl, 3);
|
||||
if (ERR_OK != ret) {
|
||||
reason = 6;
|
||||
goto err;
|
||||
}
|
||||
if (ERR_OK != rx8010_set_time(tm, zeller_calc_week(tm))) {
|
||||
reason = 7;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else if(need_clear){
|
||||
//clear flag register
|
||||
ret = rx8010_write_reg(RX8010_REG_FLAG, 0x00);
|
||||
if (ERR_OK != ret) {
|
||||
reason = 8;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = rx8010_get_time(tm);
|
||||
if (ERR_OK != ret) {
|
||||
reason = 9;
|
||||
goto err;
|
||||
}
|
||||
|
||||
*done = 1;
|
||||
return ERR_OK;
|
||||
|
||||
err:
|
||||
iot_printf("%s failed, reason = %d\n", reason);
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
||||
static void rx8010_deinit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static uint32_t rx8010_probe(void)
|
||||
{
|
||||
uint8_t data[8], i;
|
||||
uint32_t ret = ERR_OK;
|
||||
iot_i2c_module_cfg_t iic_cfg = { 0 };
|
||||
|
||||
/* I2C configuration */
|
||||
iic_cfg.baud = RX8010_IIC_DEF_SPEED;
|
||||
iic_cfg.gpio.scl = iot_board_get_gpio(GPIO_EXT_RTC_I2C_SCL);
|
||||
iic_cfg.gpio.sda = iot_board_get_gpio(GPIO_EXT_RTC_I2C_SDA);
|
||||
iic_cfg.nack_wait_num = RX8010_IIC_DEF_NACK_NUM;
|
||||
iic_cfg.port = RX8010_IIC_DEF_PORT;
|
||||
|
||||
iot_printf("scl pin = %d, sda pin = %d\n", iic_cfg.gpio.scl, iic_cfg.gpio.sda);
|
||||
|
||||
if ((GPIO_NO_VALID == iic_cfg.gpio.scl) ||
|
||||
(GPIO_NO_VALID == iic_cfg.gpio.sda)) {
|
||||
ret = ERR_NOSUPP;
|
||||
return ret;
|
||||
}
|
||||
/* iot_gpio_open_as_output can cancel the function bound on the GPIO.
|
||||
* This is not necessary if those GPIOs are not multiplex.
|
||||
*/
|
||||
if ((ERR_OK != iot_gpio_open_as_output(iic_cfg.gpio.scl))
|
||||
|| (ERR_OK != iot_gpio_open_as_output(iic_cfg.gpio.sda))) {
|
||||
iot_printf("%s open iic gpio fail!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
if (ERR_OK != iot_i2c_module_init(&iic_cfg)) {
|
||||
iot_printf("%s init i2c module fail!\n", __FUNCTION__);
|
||||
IOT_ASSERT(0);
|
||||
}
|
||||
|
||||
os_mem_set(data, 0xff, sizeof(data));
|
||||
if (ERR_OK != rx8010_write_regs(RX8010_REG_USER0, data, sizeof(data))) {
|
||||
iot_printf("%s write ram failed!\n", __FUNCTION__);
|
||||
ret = ERR_NOSUPP;
|
||||
return ret;
|
||||
}
|
||||
os_mem_set(data, 0, sizeof(data));
|
||||
if (ERR_OK != rx8010_read_regs(RX8010_REG_USER0, data, sizeof(data))) {
|
||||
iot_printf("%s read ram failed!\n", __FUNCTION__);
|
||||
ret = ERR_NOSUPP;
|
||||
return ret;
|
||||
}
|
||||
for (i = 0; i < sizeof(data); i++) {
|
||||
if (data[i] != 0xff) {
|
||||
ret = ERR_NOSUPP;
|
||||
iot_printf("%s read ram incorrect data!\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
iot_printf("%s rtc chip is RX8010 \n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* define external RTC devices rx8010 */
|
||||
const iot_ext_rtc_drv_t g_rx8010_drv = {
|
||||
.drv_prode = rx8010_probe,
|
||||
.drv_init = rx8010_init,
|
||||
.drv_deinit = rx8010_deinit,
|
||||
.drv_get_time = rx8010_get_time,
|
||||
.drv_set_time = rx8010_set_time,
|
||||
.drv_is_startup = rx8010_is_startup,
|
||||
};
|
||||
|
||||
#endif /* IOT_EXT_RTC_RX8010_ENABLE */
|
||||
90
driver/extern/rtc/src/simu_rtc_driver.c
vendored
Normal file
90
driver/extern/rtc/src/simu_rtc_driver.c
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
||||
* be copied by any method or incorporated into another program without
|
||||
* the express written consent of Aerospace C.Power. This Information or any portion
|
||||
* thereof remains the property of Aerospace C.Power. The Information contained herein
|
||||
* is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
||||
* liability for its use in any way and conveys no license or title under
|
||||
* any patent or copyright and makes no representation or warranty that this
|
||||
* Information is free from patent or copyright infringement.
|
||||
*
|
||||
* ****************************************************************************/
|
||||
|
||||
/* os_ship header files */
|
||||
#include "os_timer_api.h"
|
||||
|
||||
/* iot common header files */
|
||||
#include "iot_config_api.h"
|
||||
#include "iot_rtc_api.h"
|
||||
#include "iot_errno_api.h"
|
||||
#include "iot_config.h"
|
||||
#include "iot_rtc_ext.h"
|
||||
|
||||
#if (IOT_RTC_EXT_ENABLE && HW_PLATFORM == HW_PLATFORM_SIMU)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
static uint32_t simu_rtc_get_time(iot_time_tm_t *tm)
|
||||
{
|
||||
SYSTEMTIME win_time;
|
||||
GetLocalTime(&win_time);
|
||||
tm->tm_sec = (uint8_t)win_time.wSecond;
|
||||
tm->tm_min = (uint8_t)win_time.wMinute;
|
||||
tm->tm_hour = (uint8_t)win_time.wHour;
|
||||
tm->tm_mday = (uint8_t)win_time.wDay;
|
||||
tm->tm_mon = (uint8_t)win_time.wMonth;
|
||||
tm->tm_year = (uint16_t)win_time.wYear;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static uint32_t simu_rtc_set_time(iot_time_tm_t *tm, uint8_t week)
|
||||
{
|
||||
(void)tm;
|
||||
(void)week;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static uint32_t simu_rtc_is_startup(iot_time_tm_t *tm)
|
||||
{
|
||||
(void)tm;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t simu_rtc_init(iot_time_tm_t *tm, uint32_t *done)
|
||||
{
|
||||
SYSTEMTIME win_time;
|
||||
GetLocalTime(&win_time);
|
||||
tm->tm_sec = (uint8_t)win_time.wSecond;
|
||||
tm->tm_min = (uint8_t)win_time.wMinute;
|
||||
tm->tm_hour = (uint8_t)win_time.wHour;
|
||||
tm->tm_mday = (uint8_t)win_time.wDay;
|
||||
tm->tm_mon = (uint8_t)win_time.wMonth;
|
||||
tm->tm_year = (uint16_t)win_time.wYear;
|
||||
*done = 1;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void simu_rtc_deinit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static uint32_t simu_rtc_probe(void)
|
||||
{
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* define simu_rtc device */
|
||||
const iot_ext_rtc_drv_t g_simu_rtc_drv = {
|
||||
.drv_prode = simu_rtc_probe,
|
||||
.drv_init = simu_rtc_init,
|
||||
.drv_deinit = simu_rtc_deinit,
|
||||
.drv_get_time = simu_rtc_get_time,
|
||||
.drv_set_time = simu_rtc_set_time,
|
||||
.drv_is_startup = simu_rtc_is_startup,
|
||||
};
|
||||
|
||||
#endif /* IOT_RTC_EXT_ENABLE && HW_PLATFORM == HW_PLATFORM_SIMU */
|
||||
Reference in New Issue
Block a user