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; }