static int xmodem_transfer(char *base) { unsigned char c; unsigned int i; unsigned int crc; unsigned int filesize=0; unsigned char BlockCount=1; //数据块累计(仅8位,无须考虑溢出) //向PC机发送开始提示信息 STATUS=ST_WAIT_START; //并且数据='d'或'D',进入XMODEM c=0; while(1) { tgt_putchar(XMODEM_WAIT_CHAR); if(testchar()>0)break; } while(STATUS!=ST_OK) //循环接收,直到全部发完 { i=get_data(&strXMODEM.SOH,BLOCKSIZE+5,1000); //限时1秒,接收133字节数据 if(i) { //分析数据包的第一个数据 SOH/EOT/CAN switch(strXMODEM.SOH) { case XMODEM_SOH: //收到开始符SOH if (i>=(BLOCKSIZE+5)) { STATUS=ST_BLOCK_OK; } else { STATUS=ST_BLOCK_FAIL; //如果数据不足,要求重发当前数据块 tgt_putchar(XMODEM_NAK); } break; case XMODEM_EOT: //收到结束符EOT tgt_putchar(XMODEM_ACK); //通知PC机全部收到 STATUS=ST_OK; printf("transfer succeed!\n"); break; case XMODEM_CAN: //收到取消符CAN tgt_putchar(XMODEM_ACK); //回应PC机 STATUS=ST_OK; printf("Warning:use cancelled!\n"); break; default: //起始字节错误 tgt_putchar(XMODEM_NAK); //要求重发当前数据块 STATUS=ST_BLOCK_FAIL; break; } } else { dbg_printf("time out!\n"); break; } if (STATUS==ST_BLOCK_OK) //接收133字节OK,且起始字节正确 { dbg_printf("BlockCount=%d,strXMODEM.BlockNo=%d\n",BlockCount,strXMODEM.BlockNo); if (BlockCount != strXMODEM.BlockNo)//核对数据块编号正确 { tgt_putchar(XMODEM_NAK); //数据块编号错误,要求重发当前数据块 continue; } if (BlockCount !=(unsigned char)(~strXMODEM.nBlockNo)) { tgt_putchar(XMODEM_NAK); //数据块编号反码错误,要求重发当前数据块 continue; } crc=strXMODEM.CRC16hi<<8; crc+=strXMODEM.CRC16lo; //AVR的16位整数是低位在先,XMODEM的CRC16是高位在先 if(calcrc(&strXMODEM.Xdata[0],BLOCKSIZE)!=crc) { tgt_putchar(XMODEM_NAK); //CRC错误,要求重发当前数据块 dbg_printf("crc error\n"); continue; } //正确接收128个字节数据,刚好是M16的一页 memcpy(base+filesize,strXMODEM.Xdata,128); filesize+=128; tgt_putchar(XMODEM_ACK); //回应已正确收到一个数据块 BlockCount++; //数据块累计加1 } } //退出Bootloader程序,从0x0000处执行应用程序 printf("xmodem finished\n"); return filesize; }
int decode_frame(struct frame *framedata, char * Rframe) { /* return 0 if error bits in return set to specify different things bit 0: No errors bit 1: for me bit 2: set = INFOFRAME, not set = SUPEFRAME bit 3: first frame bit 4: last frame bit 5: Broadcast */ put_string("\r\n>>>Start decode_frame\r\n"); int retval = 0; if(Rframe[0] == HEADER && Rframe[strlen(Rframe)-1] == FOOTER ) { // put_string("\r\nBefore unbytestuff: "); // put_string(Rframe); unbytestuff(Rframe); // put_string("\r\nafter unbytestuff: "); // put_string(Rframe); strncpy(Rframe, Rframe, strlen(Rframe)-1); // put_string("\r\nRemoved footer: "); // put_string(Rframe); // put_string("\r\nstrlen: "); // put_number(strlen(Rframe)); Rframe[strlen(Rframe)-1] = '\0'; // put_string("\r\nadd zero: "); // put_string(Rframe); // put_string("\r\nstrlen: "); // put_number(strlen(Rframe)); uint16_t crc = (Rframe[strlen(Rframe) - 2] << 8); crc |= (Rframe[strlen(Rframe) - 1] & 0x00ff); //put_hex(crc, 2); //put_string("\r\nSegment Valid: "); //put_hex(calcrc(segment, (strlen(segment)-2)), 2); if(crc == calcrc(Rframe, (strlen(Rframe)-2))) { //put_string("\nNo Errors!\n"); retval |= 1; int i; for(i = 0; i < 10; i++) { if(i < CONTROLLEN) { framedata->control[i] = Rframe[HEADERLEN + i]; } if(i < ADDRESSLEN) { framedata->address[i] = Rframe[HEADERLEN + CONTROLLEN + i]; } if(i < LENGTHLEN) { framedata->length[i] = Rframe[HEADERLEN + CONTROLLEN + ADDRESSLEN + i]; } } framedata->control[CONTROLLEN] = 0; framedata->address[ADDRESSLEN] = 0; framedata->length[LENGTHLEN] = 0; for(i = 0; i < framedata->length[0]; i++) { framedata->data[i] = Rframe[HEADERLEN + CONTROLLEN + ADDRESSLEN + LENGTHLEN + i]; } //get rid of start and end bits////// // if(Rframe[HEADERLEN + CONTROLLEN + ADDRESSLEN + LENGTHLEN] == START) { // strcpy(framedata->data, framedata->data); // } // if(framedata->data[(int)framedata->length[0] - 1] == END) { // framedata->data[(int)framedata->length[0] - 1] = 0; // } ///////////////////////////////////// framedata->data[(int)framedata->length[0]] = 0; put_string("\r\nRframe.data: "); put_string(framedata->data); if((uint8_t)framedata->address[1] == (uint8_t)BROADCAST || (uint8_t)framedata->address[1] == (uint8_t)callsign) { put_string("\r\nFrame for me!"); retval |= 1 << 1; if(framedata->control[1] == START) { put_string("\r\nFirst Frame\r\n"); retval |= 1<< 3; // strcpy(framedata->data, framedata->data+1); } if(framedata->control[1] == END) { put_string("\r\nLast Frame\r\n"); retval |= 1<<4; // framedata->data[(int)framedata->length[0] - 1] = 0; } if(framedata->control[0] == INFOFRAME[0]) { put_string("\r\nInfoFrame\r\n"); retval |= 1 << 2; } if((uint8_t)framedata->address[1] == (uint8_t)BROADCAST) { put_string("\r\nBroadcast\r\n"); retval |= 1<<5; } } else { // not intended recepient put_string("\r\nDestination address: "); put_number(framedata->address[1]); put_string("\r\nBroadcast address: "); put_number(BROADCAST); put_string("\r\nNot for me!\n"); //retval = 1; } } else { // error in transmission //retval = 1; put_string("\r\nCRC failed"); } } put_string("\r\n>>>End decode_frame\r\n"); return retval; }
//主程序 void main(void) { uint i = 0; uint timercount = 0; uchar packNO = 1; uint bufferPoint = 0; uint crc; #ifdef UPDATE_USB uchar s; uint j; unsigned long UpdateSize = 0; uint LabCount = 0,lastdatanum = 0; uchar string[50] = {0}; #endif //初始化M128的USART0 UBRR0L = BAUD_L; //Set baud rate UBRR0H = BAUD_H; UCSR0B = ((1<<RXEN0)|(1<<TXEN0)); //接收器与发送器使能; UCSR0C = (1<<USBS0)|(3<<UCSZ00); //设置帧格式: 8 个数据位, 1 个停止位; #ifdef UPDATE_USB //初始化M128的USART1 UBRR1L = 8; UBRR1H = 0; UCSR1B = ((1<<RXEN1)|(1<<TXEN1)); //接收器与发送器使能; UCSR1C = (1<<USBS1)|(3<<UCSZ10); //设置帧格式: 8 个数据位, 1 个停止位; #endif //初始化M128的T/C0,15ms自动重载 OCR0 = 0x75; TCCR0 = 0x0F; TCNT0 = 0; DDRB.0 = 1; PORTB.0 = 1; /* USART_Send_string(a4String1); while(uart_getchar()!='O'); while(uart_getchar()!='K'); USART_Send_string(a4String2); while(uart_getchar()!='O'); while(uart_getchar()!='K'); */ USART_Send_string(startupString);//向PC机发送开始提示信息 while(1) { if(uart_getchar()=='d')break; if(TIFR&0x02) { if(++timercount>500) //若没有进入串口升级模式,则进入U盘升级模式 200*15ms=3s { #ifdef UPDATE_USB sprintf((char*)string,"Enter the USB_Disk Update!\n",UpdateSize); USART_Send_string(string); //++++++++++++++++初始化CH376S++++++++++++++++++++++++ //CH376_PORT_INIT( ); /* 接口硬件初始化 */ xWriteCH376Cmd(CMD11_CHECK_EXIST); /* 测试单片机与CH376之间的通讯接口 */ xWriteCH376Data(0x65); s = xReadCH376Data( ); if (s != 0x9A) uart_putchar(ERR_USB_UNKNOWN); /* 通讯接口不正常,可能原因有:接口连接异常,其它设备影响(片选不唯一),串口波特率,一直在复位,晶振不工作 */ xWriteCH376Cmd(CMD11_SET_USB_MODE); /* 设备USB工作模式 */ xWriteCH376Data(0x06); s = xReadCH376Data( ); if (s != CMD_RET_SUCCESS) { sprintf((char*)string,"USB_Disk is wrong init!\n",UpdateSize); USART_Send_string(string); quit(); } //++++++++++++++++++++++END+++++++++++++++++++++++++++++++++ //检查U盘是否连接好 i = 0; while(CH376DiskConnect() != USB_INT_SUCCESS) { if(++i > 5) { sprintf((char*)string,"USB_Disk is not Connection!\n",UpdateSize); USART_Send_string(string); quit(); } delay_ms(100); } i = 0; // 对于检测到USB设备的,最多等待10*50mS if(CH376DiskMount() != USB_INT_SUCCESS) { if(++i > 5) { sprintf((char*)string,"USB_Disk Test Wrong!\n",UpdateSize); USART_Send_string(string); quit(); } delay_ms(100); } //打开升级文件 s = CH376FileOpen("J8A-1.U");//每台机子,对应升级文件。 if (s == ERR_MISS_FILE) //没有找到升级文件则退出 { CH376FileClose(TRUE); sprintf((char*)string,"I can't fined the Update_File!\n",UpdateSize); USART_Send_string(string); quit(); } UpdateSize = CH376GetFileSize(); sprintf((char*)string,"The Update_File size is :%dl\n",UpdateSize); USART_Send_string(string); LabCount = UpdateSize/SPM_PAGESIZE; lastdatanum = UpdateSize%SPM_PAGESIZE; if(lastdatanum) LabCount++; if(LabCount > (512-32))//mega128的flash页数 { sprintf((char*)string,"The Update_File size is too big!",UpdateSize); USART_Send_string(string); CH376FileClose(FALSE); quit(); } //读取升级文件数据 for(i = 0; i < LabCount; i++) { if(lastdatanum && (i == (LabCount - 1))) { CH376ByteRead(data, lastdatanum, NULL); for(j = lastdatanum; j < SPM_PAGESIZE; j++) data[j] = 0xFF; } else CH376ByteRead(data, SPM_PAGESIZE, NULL); write_one_page(); address = address + SPM_PAGESIZE; //Flash页加1 } //write_one_page(); //收到256字节写入一页Flash中 //address = address + SPM_PAGESIZE; //Flash页加1 //关闭文件 CH376FileClose(FALSE); #endif quit(); } TIFR=TIFR|0x02; } } //每秒向PC机发送一个控制字符"C",等待控制字〈soh〉 while(uart_getchar()!= XMODEM_SOH) //receive the start of Xmodem { if(TIFR & 0x02) //timer0 over flow { if(++timercount > 100) //wait about 1 second { uart_putchar(XMODEM_RECIEVING_WAIT_CHAR); //send a "C" timercount = 0; } TIFR = TIFR&0x02; } } //开始接收数据块 do { if ((packNO == uart_waitchar()) && (packNO ==(~uart_waitchar()))) { //核对数据块编号正确 for(i=0;i<128;i++) //接收128个字节数据 { data[bufferPoint]= uart_waitchar(); bufferPoint++; } crc = (uint)(uart_waitchar())<<8; crc = crc | uart_waitchar(); //接收2个字节的CRC效验字 if(calcrc(&data[bufferPoint-128],128) == crc) //CRC校验验证 { //正确接收128个字节数据 while(bufferPoint >= SPM_PAGESIZE) { //正确接受256个字节的数据 write_one_page(); //收到256字节写入一页Flash中 address = address + SPM_PAGESIZE; //Flash页加1 bufferPoint = 0; } uart_putchar(XMODEM_ACK); //正确收到一个数据块 packNO++; //数据块编号加1 } else { uart_putchar(XMODEM_NAK); //要求重发数据块 } } else { uart_putchar(XMODEM_NAK); //要求重发数据块 } }while(uart_waitchar()!=XMODEM_EOT); //循环接收,直到全部发完 uart_putchar(XMODEM_ACK); //通知PC机全部收到 if(bufferPoint) write_one_page(); //把剩余的数据写入Flash中 quit(); //退出Bootloader程序,从0x0000处执行应用程序 }
static int ProcessPacket() { int id = (u_char)packet[0] ; int idc = (u_char)packet[1] ; int i ; if( idc != 255-id ) return rejectPacket() ; if( id == packetId ) /* duplicate */ return acceptPacket() ; if( id != (packetId+1)%256 ) { /* out of sequence */ (void) sendCancel() ; return XmErrSequence ; } if( protocol == Xmodem ) { /* compute checksum */ int csum = calcChecksum(packet+2, pktLen) ; if( csum != (u_char) packet[2+pktLen] ) return rejectPacket() ; } else { int crc0 = (u_char)packet[pktLen+2] << 8 | (u_char)packet[pktLen+3] ; int crc1 = calcrc(packet+2, pktLen) ; if( crc0 != crc1 ) return rejectPacket() ; } /* it's a good packet */ packetId = (packetId+1)%256 ; /* is this the first packet? */ if( packetCount == 0 ) { if( ymodem ) { if( packet[2] == '\0' ) { /* last file */ (void) acceptPacket() ; return XmDone ; } if( packet[2] == '/' ) strcpy(xmFilename, packet+2) ; else { strcpy(xmFilename, xmDefPath) ; strcat(xmFilename, packet+2) ; } fileLen = fileDate = fileMode = -1 ; sscanf(packet+2+strlen(packet)+1, "%d %o %o", &fileLen, &fileDate, &fileMode) ; } if( (ofile = fopen(xmFilename, "w")) == NULL ) { sendCancel() ; return XmErrCantOpen ; } if( ymodem ) { packetCount = 1 ; (void) acceptPacket() ; return sendFlush('C') ; } else state = Packet ; } ++packetCount ; /* TODO: ymodem: if this is last packet, truncate it */ if( (i=fwrite(packet+2, 1, pktLen, ofile)) != pktLen ) { sendCancel() ; return XmErrSys ; } else return acceptPacket() ; }