BQ 27510電量計の校正のC言語実現
TI公式MSP 430プラットフォーム移植修正によると、Omap 37 xx(wince)プラットフォームテストでは、理論的にはプラットフォームとは関係なく、手を伸ばして党に手を伸ばし、急いで貼り付けコードをコピーしましょう.もしこの文章があなたを助けてくれたら、好評をあげてもいいです.
/*
================================================================================
* Texas Instruments OMAP(TM) Platform Software
* (c) Copyright Texas Instruments, Incorporated. All Rights Reserved.
*
* Use of this software is controlled by the terms and conditions found
* in the license agreement under which this software has been supplied.
*
================================================================================
*/
//
// File: bqtool.c
//
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <i2cproxy.h>
#include "bq27500.h"
#define CMD_MAX_DATA_SIZE 512
#define MAX_LINE_LEN ((CMD_MAX_DATA_SIZE + 4) * 3)
#define CMD_RETRY_DELAY 100 /* in ms */
#define RETRY_LIMIT 3
typedef enum {
CMD_INVALID = 0,
CMD_R, /* Read */
CMD_W, /* Write */
CMD_C, /* Compare */
CMD_X, /* Delay */
} cmd_type_t;
/*
* DO NOT change the order of fields - particularly reg
* should be immediately followed by data
*/
typedef struct {
cmd_type_t cmd_type;
unsigned char addr;
unsigned char reg;
union {
unsigned char bytes[CMD_MAX_DATA_SIZE + 1];
UINT delay;
} data;
unsigned char data_len;
UINT32 line_num;
CHAR *line;
}cmd_t;
static UINT32 line_num;
/* Parse S into tokens separated by characters in DELIM.
If S is NULL, the saved pointer in SAVE_PTR is used as
the next starting point. For example:
char s[] = "-abc-=-def";
char *sp;
x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def"
x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL
x = strtok_r(NULL, "=", &sp); // x = NULL
// s = "abc/0-def/0"
*/
static char *strtok_r(char *s, const char *delim, char **save_ptr) {
char *token;
if (s == NULL) s = *save_ptr;
/* Scan leading delimiters. */
s += strspn(s, delim);
if (*s == '\0')
return NULL;
/* Find the end of the token. */
token = s;
s = strpbrk(token, delim);
if (s == NULL)
/* This token finishes the string. */
*save_ptr = strchr(token, '\0');
else {
/* Terminate the token and make *SAVE_PTR point past it. */
*s = '\0';
*save_ptr = s + 1;
}
return token;
}
static char *strtok(char *s, const char *delim)
{
static char *last;
return strtok_r(s, delim, &last);
}
// I2C,
static BOOL i2c_write(HANDLE hI2C, cmd_t *cmd)
{
int ret;
DWORD udwTemp;
if(hI2C)
{
udwTemp=cmd->addr >>1;
DeviceIoControl(hI2C, IOCTL_I2C_SET_SLAVE_ADDRESS, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
SetFilePointer(hI2C,LOWORD(cmd->reg),NULL,FILE_BEGIN);
if(!WriteFile(hI2C, cmd->data.bytes, cmd->data_len, &udwTemp, NULL))
{
RETAILMSG(1,(TEXT("ERROR: i2c_write: I2c WriteFile failed.\r
")));
}
}
return TRUE;
}
// I2C,
static BOOL i2c_Read(HANDLE hI2C, cmd_t *cmd)
{
int ret;
DWORD udwTemp;
if(hI2C)
{
udwTemp=cmd->addr >>1;
DeviceIoControl(hI2C, IOCTL_I2C_SET_SLAVE_ADDRESS, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
SetFilePointer(hI2C,LOWORD(cmd->reg),NULL,FILE_BEGIN);
if(!ReadFile(hI2C, cmd->data.bytes, cmd->data_len,&udwTemp, NULL))
{
RETAILMSG(1,(TEXT("ERROR: i2c_Read: I2c ReadFile failed.\r
")));
return FALSE;
}else
{
cmd->data_len=udwTemp;
}
}
return TRUE;
}
static BOOL do_exec_cmd(HANDLE i2c_file, cmd_t *cmd)
{
unsigned char tmp_buf[CMD_MAX_DATA_SIZE];
int j=0;
switch (cmd->cmd_type) {
case CMD_R:
return i2c_Read(i2c_file, cmd);
case CMD_W:
return i2c_write(i2c_file, cmd);
case CMD_C:
memcpy(tmp_buf, cmd->data.bytes, cmd->data_len);
if (!i2c_Read(i2c_file, cmd))
return FALSE;
if (memcmp(tmp_buf, cmd->data.bytes, cmd->data_len)) {
RETAILMSG(1, (TEXT("Command C failed at line %d\r
"),cmd->line_num));
return FALSE;
}
return TRUE;
case CMD_X:
Sleep(cmd->data.delay);
return TRUE;
default:
RETAILMSG(1, (TEXT("Unsupported command at line %d\r
"),cmd->line_num));
return FALSE;
}
}
static BOOL execute_cmd(HANDLE i2c_file, cmd_t *cmd)
{
int i = 1,j=0;
BOOL ret;
RETAILMSG(0,(TEXT("cmd:cmd_type=%d;addr=%02x,reg=%02x,cmd->data_len=%d,"),cmd->cmd_type,cmd->addr,cmd->reg,cmd->data_len));
#if 0 //only for debug TODO:delete
RETAILMSG(1,(TEXT("line=%d:"),cmd->line_num));
for(j=0;j<cmd->data_len;j++)
{
RETAILMSG(1,(TEXT("%02x "),cmd->data.bytes[j]));
}
RETAILMSG(1,(TEXT("\r
")));
#endif
ret = do_exec_cmd(i2c_file, cmd);
//if execute failed,retry three times
while (!ret && i < RETRY_LIMIT) {
Sleep(CMD_RETRY_DELAY);
ret = do_exec_cmd(i2c_file, cmd);
i++;
}
if (!ret) {
RETAILMSG(1, (TEXT("Command execution failed at line %d addr=0x%02x reg=0x%02x\r
"),cmd->line_num, cmd->addr, cmd->reg));
}
return ret;
}
static BOOL get_delay(UINT *delay)
{
char *tok;
UINT temp;
tok = strtok(NULL, " ");
if (!tok)
return FALSE; /*end of line or file */
if (1 != sscanf(tok, "%u", &temp)) {
RETAILMSG(1, (TEXT("Syntax error while parsing delay at line %d\r
"),line_num));
return FALSE; /* syntax error */
}
*delay = (UINT)temp;
return TRUE;
}
/*
* Returns:
* 0: success
* 1: EOF
* -1: Parse error
*/
static int get_byte(unsigned char *byte)
{
char *tok;
unsigned char temp;
tok = strtok(NULL, " ");
if (!tok)
return 1; /*end of line or file */
if ((strlen(tok) != 2) || (sscanf(tok, "%2x", &temp) != 1)) {
RETAILMSG(1, (TEXT("Syntax error at line %d\r
"), line_num));
return -1; /* syntax error */
}
*byte = (unsigned char)temp;
return 0; /* success */
}
static BOOL get_addr_n_reg(cmd_t *cmd)
{
if (get_byte(&cmd->addr))
return FALSE;
if (get_byte(&cmd->reg))
return FALSE;
return TRUE;
}
static BOOL get_data_bytes(cmd_t *cmd)
{
int ret, i = 0;
cmd->data_len = 0;
do {
ret = get_byte(&cmd->data.bytes[i++]);
} while ((ret == 0) && (i <= CMD_MAX_DATA_SIZE));
if (ret == 0) {
RETAILMSG(1, (TEXT("More than allowed number of data bytes at line %d, data_len %d, i %d\r
"), cmd->line_num,cmd->data_len, i));
return FALSE;
}
cmd->data_len = i - 1;
return TRUE;
}
static BOOL get_line(FILE *bqfs_file, char **buffer)
{
int c;
int i = 0;
BOOL ret = TRUE;
char *buf;
buf = malloc(MAX_LINE_LEN);
line_num++;
while (1) {
c = fgetc(bqfs_file);
if (feof(bqfs_file)) {
break;
} else if (ferror(bqfs_file)) {
RETAILMSG(1, (TEXT("File read error\r
")));
ret = FALSE;
break;
}
if (((c == '\r') || (c == '
') || (c == '\t')
|| (c == ' ')) && (i == 0)) {
/*
* Skip leading white space, if any, at the beginning
* of the line because this interferes with strtok
*/
RETAILMSG(1, (TEXT("Leading whitespace at line %d\r
"),line_num));
if (c == '
')
line_num++;
continue; /* blank line, let's continue */
} else if (c == '
') {
/* We've reached end of line */
break;
}
buf[i++] = c;
if (i == MAX_LINE_LEN) {
/*
* Re-allocate in case the line is longer than
* expected
*/
buf = realloc(buf, MAX_LINE_LEN * 2);
RETAILMSG(1, (TEXT("Line %d longer than expected,reallocating..\r
"), line_num));
} else if (i == MAX_LINE_LEN * 2) {
/*
* The line is already twice the expected maximum length
* - maybe the bqfs/dffs needs to be fixed
*/
RETAILMSG(1, (TEXT("Line %d too long, abort parsing..\r
"),line_num));
ret = FALSE;
break;
}
}
*buffer = buf;
buf[i] = '\0';
if (i < 1)
ret = FALSE;
return ret;
}
static BOOL get_cmd(FILE *bqfs_file, cmd_t *cmd)
{
char *res;
char *tok;
char *buf = NULL;
BOOL ret;
while ((ret = get_line(bqfs_file, &buf))) {
if (buf[0] == ';') {
/*
* Comment line - ignore it and get the
* next line
*/
RETAILMSG(0, (TEXT("Comment line,line_num=%d\r
"),line_num));
free(buf);
} else {
break;
}
}
if (!ret)
goto error;
cmd->line_num = line_num;
tok = strtok(buf, ":");
if (!tok || (strlen(tok) != 1)) {
RETAILMSG(1, (TEXT("Error parsing command at line %d\r
"),line_num));
goto error;
}
switch (tok[0]) {
case 'R':
case 'r':
cmd->cmd_type = CMD_R;
if (!get_addr_n_reg(cmd))
goto error;
break;
case 'W':
case 'w':
cmd->cmd_type = CMD_W;
if (!get_addr_n_reg(cmd))
goto error;
if (!get_data_bytes(cmd))
goto error;
break;
case 'C':
case 'c':
cmd->cmd_type = CMD_C;
if (!get_addr_n_reg(cmd))
goto error;
if (!get_data_bytes(cmd))
goto error;
break;
case 'X':
case 'x':
cmd->cmd_type = CMD_X;
cmd->data_len = 1; //only one data
if (!get_delay(&cmd->data.delay))
goto error;
break;
default:
RETAILMSG(1, (TEXT("No command or unexpected command at line %d.\r
"),line_num));
goto error;
}
if(buf)
{
free(buf);
}
return TRUE;
error:
RETAILMSG(1, (TEXT("get_line error,line_num=%d\r
"),line_num));
cmd->cmd_type = CMD_INVALID;
free(buf);
return FALSE;
}
//Param:char *fname
// File to flash BQ27510 generate by TI's engineer.
// for example:bq27510G3.bqfs(with G2 update G3 firmware)
int bqfs_flash(char *fname)
{
FILE *bqfs_file = NULL;
cmd_t *cmd = NULL;
int ret = 0;
DWORD udwTemp;
HANDLE hI2C=NULL;
RETAILMSG(0,(TEXT("bqfs_flush beging...\r
")));
bqfs_file = fopen(fname, "r");
if (!bqfs_file) {
RETAILMSG(1,(TEXT("bqfs_flush fopen failed.\r
")));
ret = -1;
goto end;
}
hI2C=CreateFile(BATT_I2C_PORT, GENERIC_READ | GENERIC_WRITE, 0,NULL, OPEN_EXISTING, 0, NULL);
if(!hI2C)
{
RETAILMSG(1,(TEXT("bqfs_flash: I2c CreateFile failed.\r
")));
ret = -1;
goto end;
}
//I2C ,
//set slave address
udwTemp=I2CSLAVEADDR;
DeviceIoControl(hI2C, IOCTL_I2C_SET_SLAVE_ADDRESS, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
//set i2c work mode
udwTemp=I2C_SUBADDRESS_MODE_8;
DeviceIoControl(hI2C, IOCTL_I2C_SET_SUBADDRESS_MODE, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
//set i2c transfer speed
udwTemp=SLOWSPEED_MODE;
DeviceIoControl(hI2C, IOCTL_I2C_SET_BAUD_INDEX, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
cmd = malloc(sizeof(cmd_t));
if(!cmd)
{
RETAILMSG(1, (TEXT("bqfs_flash malloc failed.\r
")));
ret=-1;
goto end;
}
while (get_cmd(bqfs_file, cmd) && execute_cmd(hI2C, cmd));
if (feof(bqfs_file)) {
RETAILMSG(1, (TEXT("programmed successfully!\r
")));
ret = 0;
} else {
RETAILMSG(1, (TEXT("programming failed!!\r
")));
ret = -1;
}
end:
if (cmd)
free(cmd);
if(hI2C)
{
CloseHandle(hI2C);
hI2C=NULL;
}
if (bqfs_file)
fclose(bqfs_file);
return ret;
}