//----------------------------------------------------------------------------- // Test binary data transmission. // Format in: // <byte size>:<mode> // Format out: // <4 bytes binary checksum><#size bytes data> // If echo mode, also: // Format in: // <#size bytes data> // Format out: // OK/ER - according to CRC match on incomin data // Format in: // DONE // // To Do: // o Add mode/flag specifying 5-8 bit transfer. // Test that 0xff gets masked off accordingly when transfered. // (This should be an INFO result if failing) // o Clean up the DUPLEX_ECHO implementation. Currently it's an ugly hack // that doesn't match the arguments / behavior of the two other modes. void CeCosTestSerialFilter::CMD_TestBinary(CeCosSerial &pSer, char* args) { int size; cyg_mode_t mode; unsigned char *data_out, *data_in; int i; int crc; int loop_count = 0; INIT_VALUE(args); SET_VALUE(int, size); SET_VALUE(cyg_mode_t, mode); // Change behavior for DUPLEX mode. if (MODE_DUPLEX_ECHO == mode) { loop_count = size; size = 1024; // must be at least 4*block_size } // Generate data. data_out = (unsigned char*) malloc(size); if (!data_out) { fprintf(stderr, "Could not allocate %d byte buffer for data!\n", size); throw "data_out malloc failed"; } data_in = (unsigned char*) malloc(size); if (!data_in) { fprintf(stderr, "Could not allocate %d byte buffer for data!\n", size); throw "data_in malloc failed"; } int count = 0; for (i = 0; i < size; i++) { // Output 255 chars, not 256 so that we aren't a multiple/factor of the // likely buffer sizes in the system, this can mask problems as I've // found to my cost! unsigned char c = (unsigned char) (count++ % 255); // don't allow $s and @s in the data, nor 0x03 (GDB C-c), nor flow // control chars if ('$' == c || '@' == c || 0x03 == c || 0x11 == c || 0x13 == c) c = (unsigned char) '*'; data_out[i] = c; } // Do checksum. crc = DoCRC(data_out, size); // Send checksum to target. SendChecksum(pSer, crc); // Give the target 1/10th of a sec to digest it CeCosThreadUtils::Sleep(100); switch (mode) { case MODE_NO_ECHO: { // Simple transmit. Don't expect target to echo data back. TargetWrite(pSer, data_out, size); ReceiveDone(pSer, NULL, 0); } break; case MODE_EOP_ECHO: { int in_crc; TargetWrite(pSer, data_out, size); Trace("Finished write, waiting for target echo.\n"); // Expect target to echo the data TargetRead(pSer, data_in, size); // Check echoed data, and reply OK/ER accordingly. in_crc = DoCRC(data_in, size); SendStatus(pSer, (in_crc == crc)); // Dump seen/expected on console. if (in_crc != crc) { Trace("Data seen:\n"); PrintHex(data_in, size); Trace("<end>\n"); Trace("Data expected:\n"); PrintHex(data_out, size); Trace("<end>\n"); } ReceiveDone(pSer, data_in, size); } break; case MODE_DUPLEX_ECHO: { int block_size = 64; int fail, j; // This is a simple implementation (maybe too simple). // Host sends 4 packets with the same size (64 bytes atm). // Target echoes in this way: // packet1 -> packet1 // packet2 -> packet2, packet2 // packet3 -> packet3 // packet4 -> /dev/null // // The reads/writes are interleaved in a way that should ensure // the target out buffer to be full before the target starts to read // packet3. That is, the target should be both receiving (packet3) // and sending (packet2) at the same time. // This code needs restructuring. It's not very obvious what's // happening: The same block of data is output several times, // the target echoes the data back (one of the blocks is // echoed twice). Then the echoed data is compared agains the // outgoing data block. fail = 0; while (loop_count--) { int i; for (i = 0; i < block_size*4; i++) data_in[i] = 0; // out1: block_size -> block_size TargetWrite(pSer, data_out, block_size); // out2: block_size -> 2 x block_size TargetWrite(pSer, data_out, block_size); // in1: TargetRead(pSer, data_in, block_size); // out3: block_size -> block_size TargetWrite(pSer, data_out, block_size); // in2: TargetRead(pSer, &data_in[block_size], 2*block_size); // out4: block_size -> 0 TargetWrite(pSer, data_out, block_size); // in3: TargetRead(pSer, &data_in[block_size*3], block_size); if (0 == loop_count % 10) Trace("%d loops to go\n", loop_count); // Verify data. if (!fail) { for (j = 0; j < 4 && !fail; j++) { for (i = 0; i < block_size && !fail; i++) { if (data_out[i] != data_in[j*block_size + i]) { fail = 1; Trace("Failed at byte %d\n", j*block_size + i); Trace("Data seen:\n"); PrintHex(&data_in[j*block_size], block_size); Trace("<end>\n"); Trace("Data expected:\n"); PrintHex(data_out, block_size); Trace("<end>\n"); } } } } } // Check echoed data, and reply OK/ER accordingly. SendStatus(pSer, (!fail)); ReceiveDone(pSer, data_in, block_size*4); } break; default: Trace("Unknown mode. Ignoring.\n"); } // Free buffer. free(data_in); free(data_out); }
// TODO: Refactor this with some of the timer changes // TODO: Write unit tests BootloaderState BootloaderFSM(BootloaderState state) { BootloaderState next_state; // Leave like this for static analysis to catch or set to set state? char comByte; switch(state) { case Check: // Check that the program has been programmed correctly. If so, go to Boot. Otherwise, go to Not Loaded. if(*header == HEADER_CONSTANT) { // We want to read from the header, so let's set a pointer to it that we can advance uint32_t* read_header = header; // We should be pointing to start now read_header++; // Read start address, length, version, and footer address start = (uint32_t*)*read_header++; length = *read_header++; version = *read_header++; footer = (uint32_t*)*read_header++; crc = *(footer + 1); // TODO: Validate data if(*footer == FOOTER_CONSTANT) { uint32_t crc = DoCRC(start, length); if(crc == crc) { next_state = Booting; } else { SetError(error, "CrcFaild"); next_state = NotLoaded; } } else { SetError(error, "BadFootr"); next_state = NotLoaded; } } else { SetError(error, "BadHeadr"); next_state = NotLoaded; } break; case NotLoaded: // Wait for 5 seconds. If no communication during that time, then power down if(power_down_time == 0) { power_down_time = *timer + FIVE_SECONDS; next_state = NotLoaded; } // Check for a message to push us into communicate comByte = Rs232GetByte(); if(IsBootCommand(comByte)) { next_state = Communicate; } else { // Otherwise, check if we need to power down if(*timer > power_down_time) { // 5 seconds have passed, power the device down next_state = PowerDown; } else { // Keep waiting. // TODO: Wait here? next_state = NotLoaded; } } break; case Booting: // Wait for 0.5 ms. If no communication during that time, boot our program. if(boot_time == 0) { boot_time = *timer + FIVE_HUNDRED_MS; } // Check if a service tool wants to communicate comByte = Rs232GetByte(); if(IsBootCommand(comByte)) { // Move to communicate state if so next_state = Communicate; } else { // Otherwise, check if it's time to boot if(boot_time > *timer) { // Point of No Return // Boot(); } else { // Keep waiting // TODO: Wait here? next_state = Booting; } } break; case PowerDown: // PowerDown(); // Once we come out of sleep, then go to check next_state = Check; break; case Communicate: DoProtocol(); next_state = Check; break; } return next_state; }
//////////////////////////////////////////////////////////////////////////// // Parameter: // 1, CFile& : hex file preference, to be read // 2, char* : a memory pointer, has been allocate in heep, it's a valid memory space. // 3, int : specify parameter 2, memory space's size. // return: // int : it's the truely length of the used buffer, also useful byte number after hex file been parsed. // 读扩展线性地址记录的hex file-最大32位的地址空间 BOOL CHexFileParser::ReadExtLinearHexFile(CFile& hexfile, char* pBuf, int nBufLen) { //CArchive ar(&m_hex_file,CArchive::load); //ASSERT(nBufLen >= 0xFFFF); if (pBuf) { delete[] pBuf; pBuf = NULL; } pBuf = new char[c_nHexFileBufLen]; CString strGetData; int nBufCount = 0; //*****************inspect the file********************* unsigned int nLineNumErr=0; DWORD dwHiAddr = 0; // 高位地址 char a[256]; ZeroMemory(a, 256); //while(NULL!=ar.ReadString(strGetData)) //循环读取文件,直到文件结束 while(ReadLineFromFile(hexfile, a)) { // 取得高位地址,可能不止一处扩展 if( a[8] == '4') { CString strTemp(a); dwHiAddr = GetHighAddrFromFile(strTemp); dwHiAddr <<= 16; if( nBufCount != 0) { m_szFlags.push_back(nBufCount); } // do CRC continue; } //get a line from the file,check "crc" for total file nLineNumErr++; //the line number that the wrong hex file; TS_UC get_hex[128]={0};//get hex data,it is get from the line char //the number is (i-1) //int nLen = strGetData.GetLength(); for(UINT i=0; i<strlen(a); i++) // 去掉冒号 { a[i]=a[i+1]; } int nLen = strlen(a)-2; // 不算回车换行的长度 if(strlen(a)%2==0) turn_hex_file_line_to_unsigned_char(a);//turn every char to int else { wchar_t p_c_temp[74]={'\0'}; swprintf_s(p_c_temp,_T("Error: the hex file had error at %d line!"),nLineNumErr); //AddStringToOutPuts(p_c_temp); nBufCount = 0; AfxMessageBox(p_c_temp); //close_com(); goto END; return 0; } turn_int_to_unsigned_char(a,nLen,get_hex);//turn to hex if(get_hex[3]==1) //for to seektobegin() function,because to end of the file break; if(!DoCRC( get_hex, nLen/2)) { wchar_t p_c_temp[74]={'\0'}; swprintf_s(p_c_temp,_T("Error: the hex file had error at %d line!"),nLineNumErr); //AddStringToOutPuts(p_c_temp); nBufCount = 0; AfxMessageBox(p_c_temp, MB_OK); //close_com(); goto END; return 0; } // if(get_hex[1]==0 && get_hex[2]==0) // get_hex[4]=255;//for the 0000 register to write 255 int temp; char temp_buf[32]; if (nLineNumErr==9) { for (int i=0;i<32;i++) { temp_buf[i]=a[i+8]; } for (int i=0;i<20;i++) { temp=temp_buf[2*i]*16+temp_buf[2*i+1]; m_DeviceInfor[i]=temp; } //m_softwareRev = (temp_buf[30] + temp_buf[31]*256)/10.0; //m_ProductModel=m_DeviceInfor[0]; m_softwareRev= ((a[38]*16+a[39]) + (a[40]*16 + a[41])*256)/10.0; m_ProductName.Empty(); for (int i=0;i<10;i++) { CString temp1; temp1.Format(_T("%C"),m_DeviceInfor[5+i]); m_ProductName = m_ProductName + temp1; } } unsigned int ltemp; ltemp=get_hex[1]*256+get_hex[2] + dwHiAddr; // if (m_IsRAM) // { // ltemp-=0x00008000; // } for(int j=0;j<get_hex[0];j++) pBuf[ltemp+j]=get_hex[4+j];//get the data if((UINT)nBufCount<(ltemp+get_hex[0])) nBufCount=ltemp+get_hex[0]; ZeroMemory(a, 256); }//end while m_szFlags.push_back(nBufCount); END: hexfile.Close();//close the file return nBufCount; //return 0 ; }