系统函数 常用技巧 常见的坑。。。。
1,一些寄存器字符串操作
字符数组注意是否要加'\0'
下面这个没加 所以用ARRAY_SIZE计算个数 用%c打印字符
static int fg_read_manufacturing_data(struct bq_fg_chip *bq, u8 *buf)
{
unsigned char t_buf[64] = { 0 };
int ret, i, len;
char manufacturing_date[8] = {'2', '0', '2', '0', '0', '0', '0', '0'};
ret = fg_mac_read_block(bq, FG_MAC_CMD_BATT_SN, t_buf, 32);
if (ret < 0) {
mca_log_info("failed to get BATT_SN\n");
return ret;
}
manufacturing_date[3] = '0' + (t_buf[6] & 0xF);
manufacturing_date[6] = '0' + (t_buf[8] & 0xF);
manufacturing_date[7] = '0' + (t_buf[9] & 0xF);
switch (t_buf[7]) {
case 10:
manufacturing_date[4] = '1';
break;
case 11:
manufacturing_date[4] = '1';
manufacturing_date[5] = '1';
break;
case 12:
manufacturing_date[4] = '1';
manufacturing_date[5] = '2';
break;
default:
manufacturing_date[5] = '0' + (t_buf[7] & 0xF);
break;
}
len = ARRAY_SIZE(manufacturing_date);
mca_log_info("read manufacturing_date=%c,%c,%c,%c,%c,len=%d\n",
manufacturing_date[3], manufacturing_date[4], manufacturing_date[5], manufacturing_date[6], manufacturing_date[7], len);
for (i = 0; i < len; i++)
buf[i] = manufacturing_date[i];
return 0;
}
static int fg_read_first_usage_data(struct bq_fg_chip *bq, u8 *buf)
{
unsigned char t_buf[64] = { 0 };
int ret, i, len;
char first_usage_data[9] = {'0', '0', '0', '0', '0', '0', '0', '0', '\0'};
这个就带了'\0' 所以可以用strlen计算个数(从开头统计到'\0')用%s打印(打印到'\0'结束)
没有'\0' len超了 会数组越界,会%s打印用strlen出错 会crash!!!crashcrashcrash
ret = fg_mac_read_block(bq, FG_MAC_CMD_UI_SOH, t_buf, 32);
if (ret < 0) {// read error, show 9999999
memcpy(buf,"99999999",8);
mca_log_info("failed to get first_usage_data\n");
return ret;
}
这里16进制转字符 例如0x0A转为 字符’10‘,如下操作 应该没有其他好办法
first_usage_data[3] = '0' + (t_buf[11] & 0xF);
first_usage_data[6] = '0' + (t_buf[13] & 0xF);
first_usage_data[7] = '0' + (t_buf[14] & 0xF);
switch (t_buf[12]){
case 10:
first_usage_data[4] = '1';
break;
case 11:
first_usage_data[4] = '1';
first_usage_data[5] = '1';
break;
case 12:
first_usage_data[4] = '1';
first_usage_data[5] = '2';
break;
default:
first_usage_data[5] = '0' + (t_buf[12] & 0xF);
break;
}
mca_log_info("read first_usage_data=%s\n", first_usage_data);
if (strncmp(&first_usage_date[3], "00000", 5)) {
first_usage_data[0] = '2';
first_usage_data[2] = '2';
} //read date != 00000000, show date
len = strlen(first_usage_data);
for (i = 0; i < len; i++)
buf[i] = first_usage_data[i];
return 0;
}
static void fg_write_first_usage_data(struct bq_fg_chip *bq, const char *buf, size_t size)
{
int ret, len;
unsigned char data[32] = { 0 };
char *tmp_buf = NULL;
tmp_buf = kzalloc(size + 1, GFP_KERNEL);
if (!tmp_buf)
return;
len = strlen(tmp_buf);
strscpy(tmp_buf, buf, size + 1);
mca_log_info("write first_usage_data=%s,len=%d\n", tmp_buf,len);
ret = fg_mac_read_block(bq, FG_MAC_CMD_UI_SOH, data, 32);
if (ret < 0) {
mca_log_info("failed to get first_usage\n");
return;
}
/*example,2024 12(0x0B)20,2024 08(0x08)20*/
data[11] = tmp_buf[3];
data[13] = tmp_buf[6];
data[14] = tmp_buf[7];
if (tmp_buf[4] == 1)
data[12] = 0x0A;
else
data[12] = 0x00;
data[12] = data[12] + tmp_buf[5];
if (fg_mac_write_block(bq, FG_MAC_CMD_UI_SOH, data, 32))
mca_log_err("write first_usage_data failed\n");
}
不同模块之间调用函数最直接的逻辑就是直接调用,但是太过低效。比如一个ic的adc操作函数,多个ic调用,或者多个业务逻辑场景要调用。直接调用就会很乱。
10,实例
具体的ic申请了chager设备,本质上是一个全局结构体。其他模块想用的话,就获取一下,从而实现调用。
操作pump adc
get_charger_by_name("cp_master")
申请charger_device_register并绑定其ops函数
adc操作函数的封装
20,系统函数分析
get_charger_by_name(const char *name)
charger_device_register
注册一个charger设备