void SignalActivity( void ) { g_State.WaitForActivity = FALSE; if(g_State.SerialPortActive) return; g_State.SerialPortActive = TRUE; hal_printf( "Receiving upload of SREC file...\r\n" ); LCD_Clear(); hal_fprintf( STREAM_LCD, "\fFlashing...\r\n\r\n" ); }
UINT32 MicroBooter_PrepareForExecution(UINT32 physicalEntryPointAddress) { if (physicalEntryPointAddress == CODE_BASEADDRESS) { BlockStorageDevice *device; ByteAddress ByteAddress; UINT32 physicalAddress = CODE_BASEADDRESS; if (BlockStorageList::FindDeviceForPhysicalAddress( &device, physicalAddress, ByteAddress)) { BlockStorageStream stream; if(stream.Initialize(BlockUsage::CODE, device)) { BYTE *dst; if(stream.CurrentAddress() != CODE_BASEADDRESS) { hal_fprintf( STREAM_LCD, "Warn: at wrong offset: 0x%08x\r\n", (UINT32)stream.CurrentAddress()); debug_printf( "Warn: at wrong offset: 0x%08x\r\n", (UINT32)stream.CurrentAddress()); stream.Seek(CODE_BASEADDRESS - stream.CurrentAddress(), BlockStorageStream::SeekCurrent); } // load ER_FLASH only dst =(BYTE *) EXCODE_BASEADDRESS ; stream.Read( &dst, CODE_SIZE ); CPU_DrainWriteBuffers(); } } } return EXCODE_BASEADDRESS; }
void ApplicationEntryPoint() { INT32 timeout = 20000; // 20 second timeout bool enterBootMode = false; // crypto API needs to allocate memory. Initialize simple heap for it. UINT8* BaseAddress; UINT32 SizeInBytes; HeapLocation ( BaseAddress, SizeInBytes ); SimpleHeap_Initialize( BaseAddress, SizeInBytes ); g_eng.Initialize( HalSystemConfig.DebuggerPorts[ 0 ] ); // internal reset and stop check enterBootMode = g_PrimaryConfigManager.IsBootLoaderRequired( timeout ); // ODM defined method to enter bootloader mode if(!enterBootMode) { enterBootMode = WaitForTinyBooterUpload( timeout ); } if(!enterBootMode) { if(!g_eng.EnumerateAndLaunch()) { timeout = -1; enterBootMode = true; } } if(enterBootMode) { LCD_Clear(); hal_fprintf( STREAM_LCD, "TinyBooter v%d.%d.%d.%d\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION); hal_fprintf( STREAM_LCD, "%s Build Date:\r\n\t%s %s\r\n", HalName, __DATE__, __TIME__ ); DebuggerPort_Initialize( HalSystemConfig.DebuggerPorts[ 0 ] ); TinyBooter_OnStateChange( State_EnterBooterMode, NULL ); DebuggerPort_Flush( HalSystemConfig.DebugTextPort ); hal_printf( "TinyBooter v%d.%d.%d.%d\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION); hal_printf( "%s Build Date: %s %s\r\n", HalName, __DATE__, __TIME__ ); #if defined(__GNUC__) hal_printf("GNU Compiler version %d\r\n", __GNUC__); #elif defined(_ARC) hal_printf("ARC Compiler version %d\r\n", _ARCVER); #elif defined(__ADSPBLACKFIN__) hal_printf( "Blackfin Compiler version %d\r\n", __VERSIONNUM__ ); #elif defined(__RENESAS__) hal_printf( "Renesas Compiler version %d\r\n", __RENESAS_VERSION__ ); #else hal_printf( "ARM Compiler version %d\r\n", __ARMCC_VERSION ); #endif DebuggerPort_Flush( HalSystemConfig.DebugTextPort ); // // Send "presence" ping. // { CLR_DBG_Commands::Monitor_Ping cmd; cmd.m_source = CLR_DBG_Commands::Monitor_Ping::c_Ping_Source_TinyBooter; g_eng.m_controller.SendProtocolMessage( CLR_DBG_Commands::c_Monitor_Ping, WP_Flags::c_NonCritical, sizeof(cmd), (UINT8*)&cmd ); } UINT64 ticksStart = HAL_Time_CurrentTicks(); // // Wait for somebody to press a button; if no button press comes in, lauch the image // do { const UINT32 c_EventsMask = SYSTEM_EVENT_FLAG_COM_IN | SYSTEM_EVENT_FLAG_USB_IN | SYSTEM_EVENT_FLAG_BUTTON; UINT32 events = ::Events_WaitForEvents( c_EventsMask, timeout ); if(events != 0) { Events_Clear( events ); } if(events & SYSTEM_EVENT_FLAG_BUTTON) { TinyBooter_OnStateChange( State_ButtonPress, (void*)&timeout ); } if(events & (SYSTEM_EVENT_FLAG_COM_IN | SYSTEM_EVENT_FLAG_USB_IN)) { g_eng.ProcessCommands(); } if(LOADER_ENGINE_ISFLAGSET(&g_eng, Loader_Engine::c_LoaderEngineFlag_ValidConnection)) { LOADER_ENGINE_CLEARFLAG(&g_eng, Loader_Engine::c_LoaderEngineFlag_ValidConnection); TinyBooter_OnStateChange( State_ValidCommunication, (void*)&timeout ); ticksStart = HAL_Time_CurrentTicks(); } else if((timeout != -1) && (HAL_Time_CurrentTicks()-ticksStart) > CPU_MillisecondsToTicks((UINT32)timeout)) { TinyBooter_OnStateChange( State_Timeout, NULL ); g_eng.EnumerateAndLaunch(); } } while(true); } ::CPU_Reset(); }
//////////////////////////////////////////////////////////////////////////////// // The TinyBooter_OnStateChange method is an event handler for state changes in // the TinyBooter. It is designed to help porting kit users control the tinybooter // execution and allow them to add diagnostics. //////////////////////////////////////////////////////////////////////////////// void TinyBooter_OnStateChange( TinyBooterState state, void* data, void ** retData ) { switch(state) { //////////////////////////////////////////////////////////////////////////////////// // State_EnterBooterMode - TinyBooter has entered upload mode //////////////////////////////////////////////////////////////////////////////////// case State_EnterBooterMode: CPU_GPIO_EnableOutputPin(LED1, TRUE); CPU_GPIO_EnableOutputPin(LED2, TRUE); CPU_GPIO_EnableOutputPin(LED3, TRUE); #if defined(TARGETLOCATION_RAM) CPU_GPIO_EnableOutputPin(LED4, TRUE); #else CPU_GPIO_EnableOutputPin(LED4, FALSE); #endif hal_fprintf( STREAM_LCD, "Waiting\r" ); break; //////////////////////////////////////////////////////////////////////////////////// // State_ButtonPress - A button was pressed while Tinybooter // The data parameter is a pointer to the timeout value for the booter mode. //////////////////////////////////////////////////////////////////////////////////// case State_ButtonPress: if(NULL != data) { UINT32 down, up; INT32* timeout_ms = (INT32*)data; // wait forever if a button was pressed *timeout_ms = -1; // process buttons while(Buttons_GetNextStateChange(down, up)) { // leave a way to exit boot mode incase it was accidentally entered if(0 != (down & BUTTON_ENTR)) { // force an enumerate and launch *timeout_ms = 0; } } } break; //////////////////////////////////////////////////////////////////////////////////// // State_ValidCommunication - TinyBooter has received valid communication from the host // The data parameter is a pointer to the timeout value for the booter mode. //////////////////////////////////////////////////////////////////////////////////// case State_ValidCommunication: if(NULL != data) { INT32* timeout_ms = (INT32*)data; // if we received any com/usb data then let's change the timeout to at least 20 seconds if(*timeout_ms != -1 && *timeout_ms < 20000) { *timeout_ms = 20000; } } break; //////////////////////////////////////////////////////////////////////////////////// // State_Timeout - The default timeout for TinyBooter has expired and TinyBooter will // perform an EnumerateAndLaunch //////////////////////////////////////////////////////////////////////////////////// case State_Timeout: break; //////////////////////////////////////////////////////////////////////////////////// // State_MemoryXXX - Identifies memory accesses. //////////////////////////////////////////////////////////////////////////////////// case State_MemoryWrite: hal_fprintf( STREAM_LCD, "Wr: 0x%08x\r", (UINT32)data ); break; case State_MemoryErase: hal_fprintf( STREAM_LCD, "Er: 0x%08x\r", (UINT32)data ); break; //////////////////////////////////////////////////////////////////////////////////// // State_CryptoXXX - Start and result of Crypto signature check //////////////////////////////////////////////////////////////////////////////////// case State_CryptoStart: hal_fprintf( STREAM_LCD, "Chk signature \r" ); hal_printf( "Chk signature \r" ); break; // The data parameter is a boolean that represents signature PASS/FAILURE case State_CryptoResult: if((bool)data) { hal_fprintf( STREAM_LCD, "Signature PASS\r\n\r\n" ); hal_printf( "Signature PASS\r\n\r\n" ); } else { hal_fprintf( STREAM_LCD, "Signature FAIL\r\n\r\n" ); hal_printf( "Signature FAIL\r\n\r\n" ); } DebuggerPort_Flush(HalSystemConfig.DebugTextPort); break; //////////////////////////////////////////////////////////////////////////////////// // State_Launch - The host has requested to launch an application at a given address, // or a timeout has occured and TinyBooter is about to launch the // first application it finds in FLASH. // // The data parameter is a UINT32 value representing the launch address //////////////////////////////////////////////////////////////////////////////////// case State_Launch: if(NULL != data) { CPU_GPIO_EnableOutputPin(LED1, FALSE); hal_fprintf( STREAM_LCD, "Starting application at 0x%08x\r\n", (UINT32)data ); // copy the native code from the Load area to execute area. // set the *retAddres to real execute address after loading the data // *retData = exeAddress *retData =(void*) ((UINT32)data | 1); // set Thumb bit! } break; } }
void ApplicationEntryPoint() { UINT32 ComEvent; g_State.Initialize(); ComEvent = 0; if(COM_IsSerial(g_State.UsartPort) && (g_State.UsartPort != COM_NULL)) { ComEvent = SYSTEM_EVENT_FLAG_COM_IN; } #if !defined(TARGETLOCATION_RAM) g_State.WaitForActivity = (g_State.ProgramCount != 0); // is there a main app? #else g_State.WaitForActivity = FALSE; // forever #endif { UINT32 ButtonsPressed; UINT32 ButtonsReleased; char c; // clear any events present from startup while(Events_Get( SYSTEM_EVENT_FLAG_ALL )); // clear any junk from com port buffers while(DebuggerPort_Read( g_State.UsartPort, &c, sizeof(c) )); // clear any junk from button buffer while(Buttons_GetNextStateChange( ButtonsPressed, ButtonsReleased )); } { BOOL ProcessingSREC = FALSE; BOOL ProcessingXREC = FALSE; INT32 ProcessingZENFLASH = 0; INT32 Mode = 0; INT32 MenuChoice = 1; // main application location when USB not enabled BOOL MenuUpdate = TRUE; UINT32 USBEvent = 0; COM_HANDLE ReadPort = COM_NULL; int MenuOffset = 1; // no USB enabled INT64 WaitTimeout = 0; #if defined(PLATFORM_ARM_MOTE2) CPU_GPIO_SetPinState( LED1_GREEN, LED_ON ); #endif if(g_State.WaitForActivity) { WaitTimeout = HAL_Time_CurrentTime() + (INT64)g_State.WaitInterval * (10 * 1000); hal_printf( "Waiting %d.%03d second(s) for hex upload\r\n", g_State.WaitInterval / 1000, g_State.WaitInterval % 1000 ); } else { hal_printf( "Waiting forever for hex upload\r\n" ); } // checking the existence of Usb Driver, all the default values are set to no USB if( USB_DEVICE_STATE_NO_CONTROLLER != USB_GetStatus( ConvertCOM_UsbController(g_State.UsbPort) ) ) { g_State.UsingUsb = TRUE; MenuChoice = 2; MenuOffset = 2; } while(true) { if(MenuUpdate) { MenuUpdate = FALSE; LCD_Clear(); hal_fprintf( STREAM_LCD, "\f"); switch(Mode) { case 0: hal_fprintf( STREAM_LCD, " Zen Boot\r\n\r\n" ); hal_fprintf( STREAM_LCD, "%c PortBooter\r\n", MenuChoice == 0 ? '*' : ' ' ); if(g_State.UsingUsb) { hal_fprintf( STREAM_LCD, "%c FlashUSB\r\n", MenuChoice == 1 ? '*' : ' ' ); } for(int i = 0; i < g_State.ProgramCount; i++) { hal_fprintf( STREAM_LCD, "%c Prg:%08x\r\n", (i+MenuOffset) == MenuChoice ? '*' : ' ', g_State.Programs[i] ); } break; case 1: hal_printf( "PortBooter v%d.%d.%d.%d\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION); hal_fprintf( STREAM_LCD, "Waiting forever for hex upload\r\n" ); break; case 2: hal_fprintf( STREAM_LCD, "FlashUSB\r\n" ); hal_fprintf( STREAM_LCD, "Waiting forever for hex upload\r\n" ); break; } } UINT32 Events = Events_WaitForEvents( ComEvent | SYSTEM_EVENT_FLAG_BUTTON | SYSTEM_EVENT_FLAG_USB_IN, 2000 ); if(Events & SYSTEM_EVENT_FLAG_BUTTON) { UINT32 ButtonsPressed; UINT32 ButtonsReleased; Events_Clear( SYSTEM_EVENT_FLAG_BUTTON ); while(Buttons_GetNextStateChange( ButtonsPressed, ButtonsReleased )); { if(g_State.SerialPortActive == FALSE) { //printf("%02x %02x\r\n", ButtonsPressed, ButtonsReleased); // up if(ButtonsPressed & BUTTON_UP) { switch(Mode) { case 0: MenuChoice = __max( MenuChoice-1, 0 ); break; } g_State.WaitForActivity = FALSE; MenuUpdate = TRUE; } // down if(ButtonsPressed & BUTTON_DOWN) { switch(Mode) { case 0: MenuChoice = __min( MenuChoice+1, g_State.ProgramCount + MenuOffset-1 ); break; } g_State.WaitForActivity = FALSE; MenuUpdate = TRUE; } // enter button if(ButtonsPressed & BUTTON_ENTR) { switch(Mode) { case 0: if(MenuChoice == 0) { Mode = 1; //UsingUsb = FALSE; } else if(g_State.UsingUsb && MenuChoice == 1) { Mode = 2; USB_Configure( ConvertCOM_UsbController(g_State.UsbPort), &UsbDefaultConfiguration ); USB_Initialize( ConvertCOM_UsbController(g_State.UsbPort) ); USB_OpenStream( ConvertCOM_UsbStream(g_State.UsbPort), USB_DEBUG_EP_WRITE, USB_DEBUG_EP_READ ); //UsingUsb = TRUE; } else { StartApplication( (void (*)())g_State.Programs[MenuChoice-MenuOffset] ); } break; case 1: Mode = 0; break; case 2: // USB_Uninitialize(); Mode = 0; break; } g_State.WaitForActivity = FALSE; MenuUpdate = TRUE; } if(ButtonsReleased) { MenuUpdate = TRUE; } } } } if((Events & ComEvent) || (Events & SYSTEM_EVENT_FLAG_USB_IN)) { char c; if(Events & ComEvent) { Events_Clear( ComEvent ); ReadPort = g_State.UsartPort; g_State.pStreamOutput = ReadPort; } else { USBEvent = USB_GetEvent( ConvertCOM_UsbController(g_State.UsbPort), USB_EVENT_ALL ); if( !(USBEvent & g_State.UsbEventCode) ) continue; g_State.pStreamOutput = g_State.UsbPort; ReadPort = g_State.UsbPort; } while(DebuggerPort_Read( ReadPort, &c, sizeof(c) )) { if(ProcessingSREC) { ProcessingSREC = g_SREC.Process( c ); } else if(ProcessingXREC) { ProcessingXREC = g_XREC.Process( c ); } else if(ProcessingZENFLASH) { const char Signature[] = "ZENFLASH\r"; //printf( "Got %d at %d\r\n", c, ProcessingZENFLASH ); if(Signature[ProcessingZENFLASH++] == c) { if(Signature[ProcessingZENFLASH] == 0) { SignalActivity(); ProcessingZENFLASH = 0; } } else { ProcessingZENFLASH = 0; } } else if('S' == c) { ProcessingSREC = TRUE; } else if('X' == c) { ProcessingXREC = TRUE; } else if('Z' == c) { ProcessingZENFLASH = 1; } } } if(g_State.WaitForActivity && WaitTimeout < HAL_Time_CurrentTime()) { #if defined(PLATFORM_ARM_MOTE2) CPU_GPIO_SetPinState(LED1_GREEN, LED_OFF); // Turn off Green LED for iMOTE2 #endif // we didn't see anything on serial port for wait interval (2 seconds nominally), // continue with code - just run the normal application StartApplication( (void (*)())g_State.Programs[0] ); } } } }
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; }
BOOL Process( char c ) { switch(c) { case XON: case XOFF: // swallow these and go on break; case '\r': case '\n': { // terminate string! m_LineBuffer[m_Pos] = 0; if(ParseLine( m_LineBuffer )) { if(m_StartAddress) { if(!m_Failures) { StartApplication( (void (*)())m_StartAddress ); } else { // after getting a failed complete download, clear the error and start anew m_StartAddress = 0; m_Failures = FALSE; LCD_Clear(); hal_fprintf( STREAM_LCD, "\fFlashing...\r\n\r\n" ); } } } else { // bad characters! realign and don't exec m_Failures = TRUE; hal_fprintf( STREAM_LCD, "%12s\r\n", m_LineBuffer ); } m_Pos = 0; return FALSE; // Always align again after getting a full record. } break; default: { if(!((c < 0x80) && (c > 0x20))) { // bad characters! m_Failures = TRUE; m_Pos = 0; hal_fprintf( STREAM_LCD, "\r\nL:%d\r\n", c ); return FALSE; // Realign. } else { // if we have a non whitespace character, store it m_LineBuffer[m_Pos++] = c; // don't overrun stuff in case of bizarre failures that appear OK char by char if(m_Pos >= sizeof(m_LineBuffer)) { m_Failures = TRUE; m_Pos = 0; hal_fprintf( STREAM_LCD, "OVERFLOW\r\n" ); return FALSE; // Realign. } } } break; } return TRUE; }
//////////////////////////////////////////////////////////////////////////////// // The TinyBooter_OnStateChange method is an event handler for state changes in // the TinyBooter. It is designed to help porting kit users control the tinybooter // execution and allow them to add diagnostics. //////////////////////////////////////////////////////////////////////////////// void TinyBooter_OnStateChange(TinyBooterState state, void* data, void ** retData) { switch (state) { //////////////////////////////////////////////////////////////////////////////////// // State_EnterBooterMode - TinyBooter has entered upload mode //////////////////////////////////////////////////////////////////////////////////// case State_EnterBooterMode: hal_fprintf(STREAM_LCD, "Waiting\r"); break; //////////////////////////////////////////////////////////////////////////////////// // State_ButtonPress - A button was pressed while Tinybooter // The data parameter is a pointer to the timeout value for the booter mode. //////////////////////////////////////////////////////////////////////////////////// case State_ButtonPress: if (NULL != data) { UINT32 down, up; INT32* timeout_ms = (INT32*)data; // wait forever if a button was pressed *timeout_ms = -1; // process buttons while (Buttons_GetNextStateChange(down, up)) { // leave a way to exit boot mode incase it was accidentally entered if (0 != (down & BUTTON_ENTR)) { // force an enumerate and launch *timeout_ms = 0; } } } break; //////////////////////////////////////////////////////////////////////////////////// // State_ValidCommunication - TinyBooter has received valid communication from the host // The data parameter is a pointer to the timeout value for the booter mode. //////////////////////////////////////////////////////////////////////////////////// case State_ValidCommunication: if (NULL != data) { INT32* timeout_ms = (INT32*)data; // if we received any com/usb data then let's change the timeout to at least 20 seconds if (*timeout_ms != -1 && *timeout_ms < 20000) { *timeout_ms = 20000; } } break; //////////////////////////////////////////////////////////////////////////////////// // State_Timeout - The default timeout for TinyBooter has expired and TinyBooter will // perform an EnumerateAndLaunch //////////////////////////////////////////////////////////////////////////////////// case State_Timeout: break; //////////////////////////////////////////////////////////////////////////////////// // State_MemoryXXX - Identifies memory accesses. //////////////////////////////////////////////////////////////////////////////////// case State_MemoryWrite: hal_fprintf(STREAM_LCD, "Wr: 0x%08x\r", (UINT32)data); break; case State_MemoryErase: hal_fprintf(STREAM_LCD, "Er: 0x%08x\r", (UINT32)data); break; //////////////////////////////////////////////////////////////////////////////////// // State_CryptoXXX - Start and result of Crypto signature check //////////////////////////////////////////////////////////////////////////////////// case State_CryptoStart: hal_fprintf(STREAM_LCD, "Chk signature \r"); hal_printf("Chk signature \r"); break; // The data parameter is a boolean that represents signature PASS/FAILURE case State_CryptoResult: if ((bool)data) { hal_fprintf(STREAM_LCD, "Signature PASS\r\n\r\n"); hal_printf("Signature PASS\r\n\r\n"); } else { hal_fprintf(STREAM_LCD, "Signature FAIL\r\n\r\n"); hal_printf("Signature FAIL\r\n\r\n"); } DebuggerPort_Flush(HalSystemConfig.DebugTextPort); break; //////////////////////////////////////////////////////////////////////////////////// // State_Launch - The host has requested to launch an application at a given address, // or a timeout has occured and TinyBooter is about to launch the // first application it finds in FLASH. // // The data parameter is a UINT32 value representing the launch address //////////////////////////////////////////////////////////////////////////////////// case State_Launch: UINT32 address = (UINT32)data; if (NULL != data) { hal_fprintf(STREAM_LCD, "Starting application at 0x%08x\r\n", address); debug_printf("Starting application at 0x%08x\r\n", address); if (address == CODE_BASEADDRESS || address == EXCODE_BASEADDRESS) { BlockStorageDevice *device; ByteAddress ByteAddress; UINT32 physicalAddress = CODE_BASEADDRESS; if (BlockStorageList::FindDeviceForPhysicalAddress(&device, physicalAddress, ByteAddress)) { BlockStorageStream stream; if (stream.Initialize(BlockUsage::CODE, device)) { if (stream.CurrentAddress() != CODE_BASEADDRESS) { hal_fprintf(STREAM_LCD, "Warn: at wrong offset: 0x%08x\r\n", (UINT32)stream.CurrentAddress()); debug_printf("Warn: at wrong offset: 0x%08x\r\n", (UINT32)stream.CurrentAddress()); stream.Seek(CODE_BASEADDRESS - stream.CurrentAddress(), BlockStorageStream::SeekCurrent); } BYTE *dst; dst = (BYTE *)EXCODE_BASEADDRESS; stream.Read(&dst, CODE_SIZE); if (retData != NULL) { *retData = (void*)EXCODE_BASEADDRESS; } CPU_DrainWriteBuffers(); } } } else if (retData != NULL) { *retData = (void*)data; } } break; } }