单片机GD32F303RCT6 (Macos环境)开发 (三十)—— GD32设置i2c从机模式的IAP升级

GD32设置i2c从机模式的IAP升级

1、gd32的I2C从机设置

关于i2c从机的设置在17节讲过,这里我们就在17节的基础上将i2c1设置为从机模式,七位从机地址为0x18.

2、升级协议

同上一节的协议,只是每包发送的数据变成了64 个,

/*串口升级协议如下:
    cmd + data length + data0 + ....+ data_n + checksum
    1、获取版本号             0x01 0x02 0x00 0x00 checksum
    2、升级
        1、进入升级模式        0x02 0x02 0x00 0x00 checksum
        2、升级文件大小        0x03 0x04 0x00 0x00 0x00 0x00 checksum
        3、数据包发送          0x04 0x40 0x00 0x00 0x00 0x00 .....  checksum
        4、数据包发送完成       0x05 0x02 0x00 0x00 checksum
*/

3、gd32代码添加

a、获取版本号:

MI_BOOL send_i2c_message(MI_U8 *p_buff,MI_U32 len)
{
    switch (p_buff[UART_CMD_INDEX])
    {
    case I2C_GET_SYSTEM_VERSION_CMD/* constant-expression */:
        /* 获取系统版本号 */
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            char version[28] = {0};
            sprintf(version,"%s %s",APPCATION_VERSION_DATE,APPCATION_VERSION_TIME);
            memset(i2c_txbuffer,0,128);
            memcpy(i2c_txbuffer,version,strlen(version));
            printf("get version = %s\r\n",version);
        }
        break;
    default:
        break;
    }    
    return MI_TRUE;
}

这里的i2c_txbuffer通过i2c回调函数发送出去。
在这里插入图片描述
b、升级相关代码处理。

MI_BOOL handle_i2c_message(MI_U8 *p_buff,MI_U32 len)
{
    switch (p_buff[I2C_CMD_INDEX])
    {
    case I2C_GET_SYSTEM_VERSION_CMD/* constant-expression */:
        /* 获取系统版本号 */
        /* Noting to do send_i2c_message 中处理*/
        break;
    case I2C_ENTER_SYSTEM_UPDATE_MODE_CMD:
        /* 进入升级模式命令 指示灯变为100ms闪烁一次*/
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            led_freq = 100;
            w_time = 0;
            packets_numer = 0;
            upgrade_file_size = 0;
            remain_packets_numer = 0;
            isRunningUpdate = 1;
            printf("Mcu Receive Update Command and Wait Receive Data Packets \r\n");
            printf("Now to Erase Download Pages \r\n");
            printf("\r\n");
            gd32_flash_erase(DOWNLOAD_START_ADDRESS,DOWNLOAD_END_ADDRESS);
            printf("\r\n");
        }
        break;
    case I2C_GET_SYSTEM_FILE_SIZE_CMD:
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            int a = (int)p_buff[2];
            int b = (int)p_buff[3];
            int c = (int)p_buff[4];
            int d = (int)p_buff[5];
            upgrade_file_size = (a<<24) | (b<<16) | (c<<8) | (d);

            if (upgrade_file_size % I2C_UPGRADE_DATA_PACKAGES_LENGHT == 0)  //如果整除128 
            {
                packets_numer = upgrade_file_size/I2C_UPGRADE_DATA_PACKAGES_LENGHT;
            }
            else
            {
                packets_numer = ((upgrade_file_size/I2C_UPGRADE_DATA_PACKAGES_LENGHT) + 1);
            }
            printf("End Erase Download Pages DONE!!\r\n");
            printf("\r\n");
            printf("receive upgrade file size %d\r\n",upgrade_file_size);
            printf("data packets number  %d\r\n",packets_numer);
            printf("\r\n");
        }
        break; 
    case I2C_RECEIVE_SYSTEM_UPDATE_CMD:
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            printf("receive packets........................%03d [100] \r\n",(((w_time + 1) * 100) / packets_numer));
            memset(i2c_w_buff,0,sizeof(i2c_w_buff));
            memcpy(i2c_w_buff,&p_buff[2],sizeof(i2c_w_buff));

            gd32_flash_write(DOWNLOAD_START_ADDRESS+(w_time * I2C_UPGRADE_DATA_PACKAGES_LENGHT),i2c_w_buff,sizeof(i2c_w_buff));

            if (w_time + 1 == packets_numer)
            {
                led_freq = 500;
                printf("receive packets........................ done!\r\n");
            }
            w_time ++;
        }
        break;
    case I2C_COMPLETE_SYSTEM_UPDATE_CMD:
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            system_info_set_update_flag(1);
            printf("Now Reboot !\r\n");
            app_soft_reset();
        }
        break;   

    default:break;
    }

#if DEBUG
    if(p_buff != 0)
    {
        for(int i=0;i<len;i++)
        {
            printf("0x%02x " ,p_buff[i]);
        }
        printf("\r\n");
    }
#endif    
    return MI_TRUE;
}

整体逻辑同蓝牙串口模块升级类似,只不过i2c是通过树莓派作为i2c主设备来升级的。

树莓升级代码

#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <strings.h>	/* for strcasecmp() */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>

#define APPLICATION_PATH                "Application.bin"
#define UPGRADE_DATA_PACKAGES_LENGHT    0x40
#define UPGRADE_PACKAGES_LENGHT         0x40 + 0x04


typedef enum{

    MI_FALSE  =   0,
    MI_TRUE   =   1,

}MI_BOOL;

typedef unsigned char   MI_U8;
typedef unsigned short  MI_U16;

static int i2c_write(int fd,int slave_addr,unsigned char *p_data,unsigned short len);
static int i2c_read(int fd,int slave_addr,unsigned char *w_data,
							unsigned short w_len,unsigned char *p_data,unsigned short len);
MI_U8 get_ver_cmd[6]            = {0x01,0x02,0x00,0x00,0x00,0x00};
MI_U8 update_cmd[6]             = {0x02,0x02,0x00,0x00,0x00,0x00};
MI_U8 file_size_cmd[8]          = {0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00};
MI_U8 file_package[UPGRADE_PACKAGES_LENGHT]         = {0x04,UPGRADE_DATA_PACKAGES_LENGHT};
MI_U8 update_complete_cmd[6]    = {0x05,0x02,0x00,0x00};
MI_U16 w_num = 0;
char r_data[256] = {0};
#define I2C_DATA_LENGTH_MAX 132

#define MISSING_FUNC_FMT	"Error: Adapter does not have %s capability\n"

static MI_BOOL get_update_file_size(char * file_path,size_t *size)
{
    FILE *file;

    file = fopen(file_path,"rb");

    if (!file)
    {
        perror("get_update_file_size fopen error\n");
        return MI_FALSE;
    }
    fseek(file, 0L, SEEK_END);

    *size = ftell(file);

    fclose(file);
    return MI_TRUE;
}

static MI_U16 CRC16(MI_U8 * buf, MI_U16 len)
{
	MI_U16 i;
	MI_U16 crc = 0xffff;
 
	if (len == 0) {
		len = 1;
	}
	while (len--) {
        
		crc ^= *buf;
		for (i = 0; i<8; i++) 
		{            
			if (crc & 1) {               
				crc >>= 1;        
				crc ^= 0xA001;            
			}      
			else {               
				crc >>= 1;            
			}       
		}     
		buf++;
	}
	return(crc);
}

static MI_BOOL compare(MI_U8 *des,MI_U8 *src,int len)
{
    while (len--)
    {
        if (*des != *src)
        {
            return MI_FALSE;
        }

        des++;
        src++;
    }

    return MI_TRUE;
}

static void send_get_version_cmd(int fd,MI_U8 *p_data,MI_U16 r_len)
{
    int len = sizeof(get_ver_cmd);
    int crc = CRC16(get_ver_cmd,len-2);
    get_ver_cmd[len-2] = crc & 0x00ff;
    get_ver_cmd[len-1] = ((crc >> 8) & 0x00ff);
	i2c_read(fd,0x18,get_ver_cmd,len,p_data,r_len);
}

static void send_enter_update_cmd(int fd)
{
    int len = sizeof(update_cmd);
    int crc = CRC16(update_cmd,len-2);
    update_cmd[len-2] = crc & 0x00ff;
    update_cmd[len-1] = ((crc >> 8) & 0x00ff);
	i2c_write(fd,0x18,update_cmd,len);
}

static MI_BOOL send_update_file_size_cmd(int fd)
{
    int len = sizeof(file_size_cmd);
    size_t file_size = 0;
    get_update_file_size(APPLICATION_PATH,&file_size);

    file_size_cmd[2] = (file_size >> 24 & (0xff));
    file_size_cmd[3] = (file_size >> 16 & (0xff));
    file_size_cmd[4] = (file_size >> 8 & (0xff));
    file_size_cmd[5] = (file_size & (0xff));

    int crc = CRC16(file_size_cmd,len-2);
    file_size_cmd[len-2] = crc & 0x00ff;
    file_size_cmd[len-1] = ((crc >> 8) & 0x00ff);

	i2c_write(fd,0x18,file_size_cmd,len);
    return MI_TRUE;
}

static MI_BOOL send_file_every_package(int fd)
{
    int len = sizeof(file_package);
    FILE *fp;
    size_t file_size;
    int package_num;
    MI_U8 package_buff[UPGRADE_DATA_PACKAGES_LENGHT] = {0};

    fp = fopen(APPLICATION_PATH,"rb");
    if (!fp)
    {
        perror("fopen error\n");
        return MI_FALSE;
    }
    get_update_file_size(APPLICATION_PATH,&file_size);

    if (file_size % UPGRADE_DATA_PACKAGES_LENGHT == 0 )
    {
        package_num = file_size / UPGRADE_DATA_PACKAGES_LENGHT;
    }
    else
    {
        package_num = (file_size / UPGRADE_DATA_PACKAGES_LENGHT) + 1;
    }

    printf("pageage_num == %d\n",package_num);
    while (!feof(fp)/* condition */)
    {
        /* code */
        int r_len = fread(package_buff,1,UPGRADE_DATA_PACKAGES_LENGHT,fp);
        
        // 最后读出来不满128 ,用0xff补全。
        if (r_len != UPGRADE_DATA_PACKAGES_LENGHT)
        {
            for (int i=r_len;i<UPGRADE_DATA_PACKAGES_LENGHT;i++)
            {
                package_buff[i] = 0xff;
            }
        }

        memcpy(&file_package[2],package_buff,sizeof(package_buff));

        int crc = CRC16(file_package,sizeof(file_package)-2);
        file_package[sizeof(file_package)-2] = crc & 0x00ff;
        file_package[sizeof(file_package)-1] = ((crc >> 8) & 0x00ff);


        usleep(30 * 1000);
        w_num++;

        printf("send package process == [%03d]\n", ((w_num * 100)/package_num));

#if DEBUG
        for(int i=0;i< len;i++)
        {
            printf("0x%02x  ",file_package[i]);
            if ((i+1) % 16 == 0)
                printf("\n");
        }
        printf("\n");

#endif
        memset(r_data,0,sizeof(r_data));
        i2c_write(fd,0x18,file_package,len);
#if DEBUG
        // for(int i=0;i< len;i++)
        // {
        //     printf("0x%02x  ",r_data[i]);
        //     if ((i+1) % 16 == 0)
        //         printf("\n");
        // }
        // printf("\n");


        // int status = compare(r_data,file_package,20);
        // if (status)
        // {
        //     printf("send_file_every_package and receive cmd success!\n");
        // }
        // else
        // {
        //     perror("send_file_every_package not equal receive cmd\n");
        // }
       
        //printf("read len == %d  w_num == %d \n",len,w_num);
 #endif        
    }
    
    fclose(fp);
    return MI_TRUE;
}

static MI_BOOL send_update_complete_cmd(int fd)
{
    int len = sizeof(update_complete_cmd);
    int crc = CRC16(update_complete_cmd,len-2);
    update_complete_cmd[len-2] = crc & 0x00ff;
    update_complete_cmd[len-1] = ((crc >> 8) & 0x00ff);
    i2c_write(fd,0x18,update_complete_cmd,sizeof(update_complete_cmd));

    return MI_TRUE;
}

static void print_register_value(unsigned char  *p_buff,unsigned short len)
{
    for(int i=0;i<len;i++)
    {
        printf("0x%02x " , p_buff[i]);

        if ((i +1)% 16 == 0)
        {
            printf("\r\n");
        }
    }
    printf("\r\n");
}

int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet)
{
	int file, len;

	len = snprintf(filename, size, "/dev/i2c/%d", i2cbus);
	if (len >= (int)size) {
		fprintf(stderr, "%s: path truncated\n", filename);
		return -EOVERFLOW;
	}
	file = open(filename, O_RDWR);

	if (file < 0 && (errno == ENOENT || errno == ENOTDIR)) {
		len = snprintf(filename, size, "/dev/i2c-%d", i2cbus);
		if (len >= (int)size) {
			fprintf(stderr, "%s: path truncated\n", filename);
			return -EOVERFLOW;
		}
		file = open(filename, O_RDWR);
	}

	if (file < 0 && !quiet) {
		if (errno == ENOENT) {
			fprintf(stderr, "Error: Could not open file "
				"`/dev/i2c-%d' or `/dev/i2c/%d': %s\n",
				i2cbus, i2cbus, strerror(ENOENT));
		} else {
			fprintf(stderr, "Error: Could not open file "
				"`%s': %s\n", filename, strerror(errno));
			if (errno == EACCES)
				fprintf(stderr, "Run as root?\n");
		}
	}

	return file;
}

static int check_funcs(int file)
{
	unsigned long funcs;

	/* check adapter functionality */
	if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
		fprintf(stderr, "Error: Could not get the adapter "
			"functionality matrix: %s\n", strerror(errno));
		return -1;
	}

	if (!(funcs & I2C_FUNC_I2C)) {
		fprintf(stderr, MISSING_FUNC_FMT, "I2C transfers");
		return -1;
	}

	return 0;
}

static int i2c_write(int fd,int slave_addr,unsigned char *p_data,unsigned short len)
{	
	struct i2c_rdwr_ioctl_data rdwr;
	int ret = 0;
 
	rdwr.nmsgs = 1;
	rdwr.msgs = (struct i2c_msg *)malloc(rdwr.nmsgs * sizeof(struct i2c_msg));
	if(!rdwr.msgs)
	{
		printf("msgs memery alloc error\n");
		close(fd);
		return -1;
	} 
	if ((rdwr.msgs[0].buf = (unsigned char *)malloc(len * sizeof(unsigned char))) == NULL)
	{
		printf("buf memery alloc error...\n");
		close(fd);
		return -1;
	}
 
	(rdwr.msgs[0]).len = len;
	(rdwr.msgs[0]).flags = !I2C_M_RD;
	(rdwr.msgs[0]).addr = slave_addr;

	memcpy((rdwr.msgs[0]).buf,p_data,len);
 
	rdwr.nmsgs = 1;
 
	ret = ioctl(fd, I2C_RDWR, (unsigned long) &rdwr);
	if(ret < 0)
	{
		printf("Error during I2C_RDWR ioctl with error code: %d\n", ret);
		return -1;
	}
	
	free(rdwr.msgs[0].buf);
	free(rdwr.msgs);

	return 0;
}

static int i2c_read(int fd,int slave_addr,unsigned char *w_data,
							unsigned short w_len,unsigned char *p_data,unsigned short len)
{
	struct i2c_rdwr_ioctl_data rdwr;
	unsigned char val;
	int ret;
 
	rdwr.nmsgs = 2;
	rdwr.msgs = (struct i2c_msg *)malloc(rdwr.nmsgs *sizeof(struct i2c_msg));
 
	if(!rdwr.msgs)
	{
		printf("Memery alloc error\n");
		close(fd);
		return -1;
	}

	if ((rdwr.msgs[0].buf = (unsigned char *)malloc(w_len * sizeof(unsigned char))) == NULL)
	{
		printf("buf memery alloc error...\n");
		close(fd);
		return -1;
	}

 
	(rdwr.msgs[0]).len = w_len;
	(rdwr.msgs[0]).flags = 0;
	(rdwr.msgs[0]).addr = slave_addr;
	memcpy((rdwr.msgs[0]).buf,w_data,w_len);
 
 	if ((rdwr.msgs[1].buf = (unsigned char *)malloc(len * sizeof(unsigned char))) == NULL)
	{
		printf("buf memery alloc error...\n");
		close(fd);
		return -1;
	}
	
	(rdwr.msgs[1]).len = len;
	(rdwr.msgs[1]).flags = 1;
	(rdwr.msgs[1]).addr = slave_addr;

	ret = ioctl(fd, I2C_RDWR, (unsigned long) &rdwr);
	if(ret < 0)
	{
		printf("Error during I2C_RDWR ioctl with error code: %d\n", ret);
		return -1;
	}
	memcpy(p_data,(rdwr.msgs[1]).buf,len);
 
 	free(rdwr.msgs[0].buf);
 	free(rdwr.msgs[1].buf);
	free(rdwr.msgs);
}

int main(int argc,char *argv[])
{
    int fd;
    char filename[20];
	size_t update_file_size;

    fd = open_i2c_dev(1, filename, sizeof(filename), 0);
	if (fd < 0 || check_funcs(fd))
		exit(1);

	memset(r_data,0,sizeof(r_data));
    send_get_version_cmd(fd,r_data,20);

    printf("get version == %s\n",r_data);
	usleep(30 * 1000);

	send_enter_update_cmd(fd);
	usleep(30 * 1000);

	get_update_file_size(APPLICATION_PATH,&update_file_size);
    printf("get update file size == %ld\n",update_file_size);
    send_update_file_size_cmd(fd);
	usleep(30 * 1000);
    send_file_every_package(fd);

    usleep(30 * 1000);
    memset(r_data,0,sizeof(r_data));
    send_update_complete_cmd(fd);

    close(fd);
    return 0;
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值