当前位置: 首页 > article >正文

国民技术N32G430开发笔记(15)- IAP升级 树莓派串口发送数据

IAP升级 树莓派串口发送数据

1、树莓派接入usb转串口模块后,会生成/dev/ttyUSB0节点,因为树莓派内核已经编译usb_serial以及各模块的驱动。
我们直接对ttyUSB0节点编程即可。
2、协议同上一节
cmd + data_lenght + data0 + …+ datax + checksum
1、获取版本号 0x01 0x02 0x00 0x00 checksum
2、升级
1、进入升级模式 0x02 0x02 0x00 0x00 checksum
2、升级文件大小 0x03 0x04 0x00 0x00 0x00 0x00 checksum
3、数据包发送 0x04 0x80 0x00 0x00 0x00 0x00 … checksum
4、数据包发送完成 0x05 0x02 0x00 0x00 checksum

checksum采用crc16的检验方法。

3、升级过程:
1、发送升级模式命令。
2、发送文件大小命令
3、循环发送Application.bin的升级包,每包数据head+64个数据+checksum。
4、发送升级完成命令。
4、代码解析如下:
在这里插入图片描述
在build目录执行 cmake …;make 即可编译出uartiap。

CMakeLists.txt

cmake_minimum_required(VERSION 3.18.4)
project (uartIap)

aux_source_directory(. C_SOURCES)
aux_source_directory(./UartIap C_SOURCES_UART)

include_directories(./UartIap)

add_executable(${PROJECT_NAME} ${C_SOURCES} ${C_SOURCES_UART})
target_link_libraries(${PROJECT_NAME} pthread)

n32g430_iap.c

#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include "uart.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;

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;

static MI_U8 isRunning = 0;
char r_data[256] = {0};
sem_t sem;

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)
{
    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);
    serialWrite(fd,get_ver_cmd,sizeof(get_ver_cmd));
}

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);
    serialWrite(fd,update_cmd,sizeof(update_cmd));
}

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

    serialWrite(fd,file_size_cmd,sizeof(file_size_cmd));
    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));
        serialWrite(fd,file_package,len);
        sem_wait(&sem);
#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);
    serialWrite(fd,update_complete_cmd,sizeof(update_complete_cmd));

    return MI_TRUE;
}

void *uart_read_thread(void *arg)
{
    int fd = *((int *)arg);
    size_t  size ;        

    sem_wait(&sem);
    while(isRunning)
    {
        size = serialRead(fd,r_data,256); //阻塞方式去读

    #if DEBUG    
        if (size > 0)
        {
            for(int i=0;i<size;i++)
            {
                printf("0x%02x  ",r_data[i]);
            }
            printf("\n");
        }
    #endif    
        sem_post(&sem);
    }

    printf("uart_read_thread exit\n");
    pthread_exit(0);
}

int main(int argc,char *argv[])
{
    int fd = 0;
    int ret;
    char w_data[] = "hello world\n";
    MI_U16 crc = 0;
    MI_BOOL status;
    pthread_t m_read_thread ;
    size_t update_file_size;

    sem_init(&sem, 0, 0);
    fd = serialOpen("/dev/ttyUSB0",115200);

    if (fd > 0)
    {
        printf("open ttyUSB0 ok\n");
    }
    else
    {
        printf("open ttyUSB0 fail\n");
        return -1;
    }

    ret = pthread_create(&m_read_thread,NULL,uart_read_thread,&fd);
    if (ret)
    {
        perror("pthread_create error\n");
        return -1;
    }
    else
    {
        isRunning = 1;
        sem_post(&sem);
    }

    sleep(1);// 获取一下N32G430C8L7的版本号
    
    memset(r_data,0,sizeof(r_data));
    send_get_version_cmd(fd);
    sem_wait(&sem);

    printf("get version == %s\n",r_data);

    memset(r_data,0,sizeof(r_data));
    send_enter_update_cmd(fd);
    sem_wait(&sem);

    status = compare(r_data,update_cmd,sizeof(update_cmd));
    if (status)
    {
        printf("send_enter_update_cmd and receive cmd success!\n");
    }
    else
    {
        perror("send_enter_update_cmd not equal receive cmd\n");
    }

    get_update_file_size(APPLICATION_PATH,&update_file_size);
    printf("get update file size == %ld\n",update_file_size);

    memset(r_data,0,sizeof(r_data));
    send_update_file_size_cmd(fd);
    sem_wait(&sem);

    status = compare(r_data,file_size_cmd,sizeof(file_size_cmd));
    if (status)
    {
        printf("send_update_file_size_cmd and receive cmd success!\n");
    }
    else
    {
        perror("send_update_file_size_cmd not equal receive cmd\n");
    }

    send_file_every_package(fd);

    memset(r_data,0,sizeof(r_data));
    send_update_complete_cmd(fd);
    sem_wait(&sem);

    pthread_cancel(m_read_thread);
    isRunning = 0;

    pthread_join(m_read_thread,NULL);
    serialClose(fd);
    printf("raspberryPi App exit!\n");
}

uart.c

#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include "uart.h"

static speed_t getBaudRate(int baudRate)
{
    switch(baudRate) {
        case 0: return B0;
        case 50: return B50;
        case 75: return B75;
        case 110: return B110;
        case 134: return B134;
        case 150: return B150;
        case 200: return B200;
        case 300: return B300;
        case 600: return B600;
        case 1200: return B1200;
        case 1800: return B1800;
        case 2400: return B2400;
        case 4800: return B4800;
        case 9600: return B9600;
        case 19200: return B19200;
        case 38400: return B38400;
        case 57600: return B57600;
        case 115200: return B115200;
        case 230400: return B230400;
        case 460800: return B460800;
        case 500000: return B500000;
        case 576000: return B576000;
        case 921600: return B921600;
        case 1000000: return B1000000;
        case 1152000: return B1152000;
        case 1500000: return B1500000;
        case 2000000: return B2000000;
        case 2500000: return B2500000;
        case 3000000: return B3000000;
        case 3500000: return B3500000;
        case 4000000: return B4000000;
        default: return -1;
    }
}

static int setParity(int fd,int dataBits,int stopBits,int parity)
{
    struct termios options;
    if (tcgetattr (fd, &options) != 0) {
        printf ("SetupSerial 1");
        return (-1);
    }
    options.c_cflag &= ~CSIZE;
    switch (dataBits) {
        case 7:
            options.c_cflag |= CS7;
            break;
        case 8:
            options.c_cflag |= CS8;
            break;
        default:
            fprintf (stderr, "Unsupported data size\n");
            return (-1);
    }

    switch (parity) {
        case 'n':
        case 'N':
            options.c_cflag &= ~PARENB; /* Clear parity enable */
            options.c_iflag &= ~INPCK;  /* Enable parity checking */
            break;
        case 'o':
        case 'O':
            options.c_cflag |= (PARODD | PARENB);
            options.c_iflag |= INPCK;   /* Disable parity checking */
            break;
        case 'e':
        case 'E':
            options.c_cflag |= PARENB;  /* Enable parity */
            options.c_cflag &= ~PARODD;
            options.c_iflag |= INPCK;   /* Disable parity checking */
            break;
        case 'S':
        case 's':           /*as no parity */
            options.c_cflag &= ~PARENB;
            options.c_cflag &= ~CSTOPB;
            break;
        default:
            fprintf (stderr, "Unsupported parity\n");
            return (-1);
    }
    switch (stopBits) {
        case 1:
            options.c_cflag &= ~CSTOPB;
            break;
        case 2:
            options.c_cflag |= CSTOPB;
            break;
        default:
            fprintf (stderr, "Unsupported stop bits\n");
            return (-1);
    }

    /* Set input parity option */
    if (parity != 'n')
        options.c_iflag |= INPCK;
    tcflush (fd, TCIFLUSH);
    options.c_cc[VTIME] = 0x01;
    options.c_cc[VMIN] =  0xFF; /* Update the options and do it NOW */
    //qd to set raw mode, which is copied from web
    options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
                         | INLCR | IGNCR | ICRNL | IXON);
    options.c_oflag &= ~OPOST;
    options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    options.c_cflag &= ~(CSIZE | PARENB);
    options.c_cflag |= CS8;

    if (tcsetattr (fd, TCSANOW, &options) != 0) {
        perror ("SetupSerial 3");
        return (-1);
    }

    return 0;
}

int serialOpen(const char *path, int baudRate)
{
    int fd;
    speed_t speed;

    /* Check arguments */
    {
        speed = getBaudRate(baudRate);
        if (speed == -1) {

            printf("get Baud rate error\n");
            return -1;
        }
    }
    {
        fd = open(path, O_RDWR);
        if (fd == -1)
        {
            printf("open serial error =%d\n",fd);
            return -1;
        }
    }
    /* Configure device */
    {
        struct termios cfg;
        if (tcgetattr(fd, &cfg))
        {
            printf("tcgetattr() failed\n");
            close(fd);
            return -1;
        }

        cfmakeraw(&cfg);
        cfsetispeed(&cfg, speed);
        cfsetospeed(&cfg, speed);

        if (tcsetattr(fd, TCSANOW, &cfg))
        {
            printf("tcsetattr() failed\n");
            close(fd);
            return -1;
        }
    }
    setParity(fd,8,1,'N');
    //printf("open Success==%d\n",fd);
    return fd;
}


int serialWrite(int fd,char *writeData,int len)
{
    if (fd > 0){
        write(fd,writeData,len);
    }else{

        printf("[File]=%s[Function]=%s error\n",__FILE__,__FUNCTION__);
        return -1;
    }
    return 0;
}

int serialRead(int fd,char *readData,int len)
{
    size_t size = 0;
    if (fd > 0)
    {
        size = read(fd,readData,len);
    }
    else
    {

        printf("[File]=%s[Function]=%s error\n",__FILE__,__FUNCTION__);
        return -1;
    }
    return size;
}

int serialClose(int fd)
{
    close(fd);
    return 0;
}

uart.h

#ifndef __UART_H__
#define __UART_H__

int serialOpen(const char *path, int baudRate);
int serialWrite(int fd,char *writeData,int len);
int serialRead(int fd,char *readData,int len);
int serialClose(int fd);

#endif

5、视频

屏幕录制2023-05-03 15.39.07

6、代码路径 : https://gitee.com/xiaoguo-tec_0/raspberrypi


http://www.kler.cn/a/17600.html

相关文章:

  • LeetCode题解:5.最长回文子串【Python题解超详细,中心拓展、动态规划、暴力解法】
  • MyBatis——增删查改(XML 方式)
  • React中 修改 html字符串 中某些元素的属性
  • 使用API有效率地管理Dynadot域名,编辑账户中whois联系人信息
  • 淘宝代购系统;海外代购系统;代购程序,代购系统源码PHP前端源码
  • 大数据新视界 -- 大数据大厂之 Impala 存储格式转换:从原理到实践,开启大数据性能优化星际之旅(下)(20/30)
  • 如何搭建chatGPT4.0模型-国内如何用chatGPT4.0
  • C语言将汉字保存到文件中
  • 如何显示文件夹的后缀和隐藏文件
  • 一分钟学会Flask框架的安装与快速使用
  • 诺派克ROPEX热封控制器维修RES-407/RES-406
  • 设计模式-创建型模式-(工厂、简单工厂、抽象工厂)
  • 有必要给孩子买台灯吗?分享四款高品质的护眼台灯
  • 处理 json 和 HttpMessageConverter--文件下载-ResponseEntity --SpringMVC 文件上传
  • 组态软件对比,未来10年发展趋势!
  • 【VAR | 时间序列】应用VAR模型时的15个注意点
  • [实训] 实验1-SPI数据传输基础实验(下)
  • 操作系统2(多处理器编程)
  • 如何使用 ChatGPT 来快速编写产品需求文档(PRD)
  • 代码随想录算法训练营(总结)|动态规划总结篇
  • 基于空间矢量脉宽调制(SVPWM)的并网逆变器研究(Simulink)
  • Java 基础进阶篇(十一)—— Arrays 与 Collections 工具类
  • 在前端开发中,何时应该使用 jQuery,何时应该使用 Vue.js
  • 定积分比较大小的常用手段。
  • 基于SpringBoot+Vue实现的酒店管理系统
  • 【关于Linux中----生产消费模型】