BOOL Process( UINT8 c ) { while(true) { switch(m_phase) { // // Setup 'address' reception. // case 0: m_ptr = (char*)&m_address; m_len = sizeof(m_address); m_phase++; break; // // Setup 'size' reception. // case 2: //printf( "Got address %08x\r\n", m_address ); m_ptr = (char*)&m_size; m_len = sizeof(m_size); m_phase++; return TRUE; // // Setup 'crc' reception. // case 4: //printf( "Got size %08x\r\n", m_size ); m_ptr = (char*)&m_crc; m_len = sizeof(m_crc); m_phase++; return TRUE; // // Setup 'data' reception or jump to entrypoint. // case 6: //printf( "Got crc %08x\r\n", m_crc ); m_crc += m_address; m_crc += m_size; if(m_size == 0) { if(m_crc != 0) { hal_fprintf( g_State.pStreamOutput, "X crc %08x %08x\r\n", m_address, m_crc ); // bad characters! realign m_phase = 0; return FALSE; } hal_fprintf( g_State.pStreamOutput, "X start %08x\r\n", m_address ); #if defined(PLATFORM_ARM_MOTE2) CPU_GPIO_SetPinState(LED1_GREEN, LED_OFF); // Turn off Green LED for iMote2 #endif StartApplication( (void (*)())m_address ); } if(m_size > sizeof(m_data) || (m_size % sizeof(FLASH_WORD)) != 0) { hal_fprintf( g_State.pStreamOutput, "X size %d\r\n", m_size ); // bad characters! realign m_phase = 0; return FALSE; } m_ptr = (char*)m_data; m_len = m_size; m_phase++; return TRUE; case 8: { FLASH_WORD* src = (FLASH_WORD*)m_data; FLASH_WORD* dst = (FLASH_WORD*)m_address; BOOL success = TRUE; int i; BlockStorageDevice * pDevice; ByteAddress WriteByteAddress ; for(i=0; i<m_size; i++) { m_crc += m_data[i]; } if(m_crc != 0) { hal_fprintf( g_State.pStreamOutput, "X crc %08x %08x\r\n", m_address, m_crc ); // bad characters! realign m_phase = 0; return FALSE; } SignalActivity(); // this slows things down to print every address, only print once per line hal_fprintf( STREAM_LCD, "WR: 0x%08x\r", (UINT32)dst ); // if it not Block Device, assume it is RAM if (BlockStorageList::FindDeviceForPhysicalAddress( & pDevice, m_address, WriteByteAddress)) { UINT32 regionIndex, rangeIndex; const BlockDeviceInfo* deviceInfo = pDevice->GetDeviceInfo() ; if(!(pDevice->FindRegionFromAddress(WriteByteAddress, regionIndex, rangeIndex))) { #if !defined(BUILD_RTM) hal_printf(" Invalid condition - Fail to find the block number from the ByteAddress %x \r\n",WriteByteAddress); #endif return FALSE; } // start from the block where the sector sits. UINT32 iRegion = regionIndex; UINT32 accessPhyAddress = (UINT32)m_address; BYTE* bufPtr = (BYTE*)src; BOOL success = TRUE; INT32 writeLenInBytes = m_size; while (writeLenInBytes > 0) { for(; iRegion < deviceInfo->NumRegions; iRegion++) { const BlockRegionInfo *pRegion = &(deviceInfo->Regions[iRegion]); ByteAddress blkAddr = pRegion->Start; while(blkAddr < accessPhyAddress) { blkAddr += pRegion->BytesPerBlock; } //writeMaxLength =the current largest number of bytes can be read from the block from the address to its block boundary. UINT32 NumOfBytes = __min(pRegion->BytesPerBlock, writeLenInBytes); if (accessPhyAddress == blkAddr && !pDevice->IsBlockErased(blkAddr, pRegion->BytesPerBlock)) { hal_fprintf( STREAM_LCD, "ER: 0x%08x\r", blkAddr ); pDevice->EraseBlock(blkAddr); blkAddr += pRegion->BytesPerBlock; } success = pDevice->Write(accessPhyAddress , NumOfBytes, (BYTE *)bufPtr, FALSE); writeLenInBytes -= NumOfBytes; if ((writeLenInBytes <=0) || (!success)) break; bufPtr += NumOfBytes; } if ((writeLenInBytes <=0) || (!success)) break; } } else { // must be RAM but don't verify, we write anyway, possibly causing a data abort if the address is bogus memcpy( dst, src, m_size ); } hal_fprintf( g_State.pStreamOutput, "X %s %08x\r\n", success ? "ack" : "nack", m_address ); m_phase = 0; return FALSE; } break; // // Read data. // case 1: case 3: case 5: case 7: *m_ptr++ = c; if(--m_len) return TRUE; m_phase++; break; } } }
BOOL ParseLine( const char* SRECLine ) { UINT32 Address; int i; UINT32 BytesRemaining = 0; UINT32 Temp = 0; UINT32 Data32; UINT32 RecordType; UINT32 CheckSum; UINT32 WordCount = 0; UINT32 ByteCount = 0; FLASH_WORD WordData[16/sizeof(FLASH_WORD)]; // we support 16 bytes of data per record max, 4 words, 8 shorts UINT8 ByteData[16]; // we support 16 bytes of data per record max, 4 words, 8 shorts BlockStorageDevice *pDevice; UINT32 m_size; ByteAddress WriteByteAddress; RecordType = *SRECLine++; SRECLine = htoi( SRECLine, 2, BytesRemaining ); if(!SRECLine) return FALSE; // start the checksum with this byte CheckSum = BytesRemaining; // get the destination address // do bytes only to make checksum calc easier Data32 = 0; for(i = 0; i < 4; i++) { SRECLine = htoi( SRECLine, 2, Temp ); if(!SRECLine) return FALSE; CheckSum += Temp; Data32 <<= 8; Data32 |= Temp; BytesRemaining -= 1; } Address = Data32; // take off one byte for CRC; m_size = BytesRemaining -1; switch(RecordType) { case '3': { while(BytesRemaining > 1) { // get bytes into words, and checksum Data32 = 0; for(i = 0; i < sizeof(FLASH_WORD); i++) { SRECLine = htoi( SRECLine, 2, Temp ); if(!SRECLine) return FALSE; CheckSum += Temp; Data32 |= Temp << (i*8); // little endian format ByteData[ByteCount++] = Temp; BytesRemaining -= 1; // leave the checksum in place if(1 == BytesRemaining) break; } ASSERT(WordCount < (16/sizeof(FLASH_WORD))); WordData[WordCount++] = Data32; } } break; case '7': // just a return address (starting location) m_StartAddress = (UINT32)Address; break; default: // we only support S3 and S7 records, for now return FALSE; } // get the checksum SRECLine = htoi( SRECLine, 2, Temp ); if(!SRECLine) return FALSE; CheckSum += Temp; BytesRemaining -= 1; ASSERT(0 == BytesRemaining); // make sure we had a NULL terminator for line, and not more characters if(*SRECLine != 0) { return FALSE; } if(0xff != (CheckSum & 0xff)) { return FALSE; } else { // only write if we succeeded the checksum entirely for whole line if(m_size > 0) { SignalActivity(); // this slows things down to print every address, only print once per line hal_fprintf( STREAM_LCD, "WR: 0x%08x\r", (UINT32)Address ); if (BlockStorageList::FindDeviceForPhysicalAddress( &pDevice, Address, WriteByteAddress)) { UINT32 regionIndex, rangeIndex; const BlockDeviceInfo* deviceInfo = pDevice->GetDeviceInfo() ; if(!(pDevice->FindRegionFromAddress(WriteByteAddress, regionIndex, rangeIndex))) { #if !defined(BUILD_RTM) hal_printf(" Invalid condition - Fail to find the block number from the ByteAddress %x \r\n",WriteByteAddress); #endif return FALSE; } // start from the block where the sector sits. UINT32 iRegion = regionIndex; UINT32 accessPhyAddress = (UINT32)Address; BYTE* bufPtr = (BYTE*)ByteData; BOOL success = TRUE; INT32 writeLenInBytes = m_size; while (writeLenInBytes > 0) { for(; iRegion < deviceInfo->NumRegions; iRegion++) { const BlockRegionInfo *pRegion = &(deviceInfo->Regions[iRegion]); ByteAddress blkAddr = pRegion->Start; while(blkAddr < accessPhyAddress) { blkAddr += pRegion->BytesPerBlock; } //writeMaxLength =the current largest number of bytes can be read from the block from the address to its block boundary. UINT32 NumOfBytes = __min(pRegion->BytesPerBlock, writeLenInBytes); if (accessPhyAddress == blkAddr && !pDevice->IsBlockErased(blkAddr, pRegion->BytesPerBlock)) { hal_fprintf( STREAM_LCD, "ER: 0x%08x\r", blkAddr ); pDevice->EraseBlock(blkAddr); blkAddr += pRegion->BytesPerBlock; } success = pDevice->Write(accessPhyAddress , NumOfBytes, (BYTE *)bufPtr, FALSE); writeLenInBytes -= NumOfBytes; if ((writeLenInBytes <=0) || (!success)) break; bufPtr += NumOfBytes; } if ((writeLenInBytes <=0) || (!success)) break; } } else { FLASH_WORD *Addr = (FLASH_WORD *) Address; for(i = 0; i < WordCount; i++) { // must be RAM but don't verify, we write anyway, possibly causing a data abort if the address is bogus *Addr++ = WordData[i]; } } } } return TRUE; }