成都便宜網(wǎng)站建設(shè)西安網(wǎng)站制作建設(shè)
IAP升級 樹莓派串口發(fā)送數(shù)據(jù)
1、樹莓派接入usb轉(zhuǎn)串口模塊后,會生成/dev/ttyUSB0節(jié)點,因為樹莓派內(nèi)核已經(jīng)編譯usb_serial以及各模塊的驅(qū)動。
我們直接對ttyUSB0節(jié)點編程即可。
2、協(xié)議同上一節(jié)
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、數(shù)據(jù)包發(fā)送 0x04 0x80 0x00 0x00 0x00 0x00 … checksum
4、數(shù)據(jù)包發(fā)送完成 0x05 0x02 0x00 0x00 checksum
checksum采用crc16的檢驗方法。
3、升級過程:
1、發(fā)送升級模式命令。
2、發(fā)送文件大小命令
3、循環(huán)發(fā)送Application.bin的升級包,每包數(shù)據(jù)head+64個數(shù)據(jù)+checksum。
4、發(fā)送升級完成命令。
4、代碼解析如下:
在build目錄執(zhí)行 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 + 0x04typedef 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 DEBUGfor(int i=0;i< len;i++){printf("0x%02x ",file_package[i]);if ((i+1) % 16 == 0)printf("\n");}printf("\n");#endifmemset(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 weboptions.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