void StartOfUserCode ( void ) { Configure(); if ( ENABLE_DEBUG_CONSOLE ) { const unsigned codeSize = unsigned( uintptr_t( &_etext ) - uintptr_t( &_sfixed ) ); const unsigned initDataSize = unsigned( uintptr_t( &_erelocate ) - uintptr_t( &_srelocate ) ); const unsigned bssDataSize = unsigned( uintptr_t( &_ebss ) - uintptr_t( &_sbss ) ); SerialSyncWriteStr( "Code size: 0x" ); SerialSyncWriteUint32Hex( codeSize ); SerialSyncWriteStr( ", initialised data size: 0x" ); SerialSyncWriteUint32Hex( initDataSize ); SerialSyncWriteStr( ", BSS size: 0x" ); SerialSyncWriteUint32Hex( bssDataSize ); SerialSyncWriteStr( "." EOL ); } // ------ Main loop ------ if ( ENABLE_DEBUG_CONSOLE ) { SerialSyncWriteStr( "Entering the main loop, which just waits forever." EOL ); } for (;;) { } }
static void PrintPanicMsg ( const char * const msg ) { if ( ENABLE_DEBUG_CONSOLE ) { // This routine is called with interrupts disabled and should rely // on as little other code as possible. SerialSyncWriteStr( EOL ); SerialSyncWriteStr( "PANIC: " ); SerialSyncWriteStr( msg ); SerialSyncWriteStr( EOL ); // Here it would be a good place to print a stack backtrace, // but I have not been able to figure out yet how to do that // with the ARM Thumb platform. } }
void HardFault_Handler ( void ) { // Note that instruction BKPT causes a HardFault when no debugger is currently attached. if ( ENABLE_DEBUG_CONSOLE ) { SerialSyncWriteStr( "HardFault" EOL ); } ForeverHangAfterPanic(); }
static void Configure ( void ) { // ------- Configure the UART connected to the AVR controller ------- if ( ENABLE_DEBUG_CONSOLE ) { VERIFY( pio_configure( PIOA, PIO_PERIPH_A, PIO_PA8A_URXD | PIO_PA9A_UTXD, PIO_DEFAULT ) ); // Enable the pull-up resistor for RX0. pio_pull_up( PIOA, PIO_PA8A_URXD, ENABLE ) ; InitSerialPort( false ); SerialSyncWriteStr( "--- EmptyDue " PACKAGE_VERSION " ---" EOL ); SerialSyncWriteStr( "Welcome to the Arduino Due's programming USB serial port." EOL ); } SetUserPanicMsgFunction( &PrintPanicMsg ); // ------- Perform some assorted checks ------- assert( IsJtagTdoPullUpActive() ); // Check that the brown-out detector is active. #ifndef NDEBUG const uint32_t supcMr = SUPC->SUPC_MR; assert( ( supcMr & SUPC_MR_BODDIS ) == SUPC_MR_BODDIS_ENABLE ); assert( ( supcMr & SUPC_MR_BODRSTEN ) == SUPC_MR_BODRSTEN_ENABLE ); #endif // ------- Configure the watchdog ------- WDT->WDT_MR = WDT_MR_WDDIS; }
void CCommandProcessor::ParseCommand ( const char * const cmdBegin, const uint64_t currentTime ) { const char * const cmdEnd = SkipCharsNotInSet( cmdBegin, SPACE_AND_TAB ); assert( cmdBegin != cmdEnd ); const char * const paramBegin = SkipCharsInSet( cmdEnd, SPACE_AND_TAB ); bool extraParamsFound = false; if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_QUESTION_MARK, true, false, &extraParamsFound ) || IsCmd( cmdBegin, cmdEnd, CMDNAME_HELP, false, false, &extraParamsFound ) ) { PrintStr( "This console is similar to the Bus Pirate console." EOL ); PrintStr( "Commands longer than 1 character are case insensitive." EOL ); PrintStr( "WARNING: If a command takes too long to run, the watchdog may reset the board." EOL ); PrintStr( "Commands are:" EOL ); Printf( " %s, %s: Show this help text." EOL, CMDNAME_QUESTION_MARK, CMDNAME_HELP ); Printf( " %s: Show version information." EOL, CMDNAME_I ); Printf( " %s: Test USB transfer speed." EOL, CMDNAME_USBSPEEDTEST ); Printf( " %s: Show JTAG pin status (read as inputs)." EOL, CMDNAME_JTAGPINS ); Printf( " %s: Test JTAG shift speed. WARNING: Do NOT connect any JTAG device." EOL, CMDNAME_JTAGSHIFTSPEEDTEST ); Printf( " %s: Exercises malloc()." EOL, CMDNAME_MALLOCTEST ); Printf( " %s: Exercises C++ exceptions." EOL, CMDNAME_CPP_EXCEPTION_TEST ); Printf( " %s: Shows memory usage." EOL, CMDNAME_MEMORY_USAGE ); Printf( " %s" EOL, CMDNAME_CPU_LOAD ); Printf( " %s" EOL, CMDNAME_UPTIME ); Printf( " %s" EOL, CMDNAME_RESET ); Printf( " %s" EOL, CMDNAME_RESET_CAUSE ); Printf( " %s <addr> <byte count>" EOL, CMDNAME_PRINT_MEMORY ); Printf( " %s <milliseconds>" EOL, CMDNAME_BUSY_WAIT ); Printf( " %s <command|protocol>" EOL, CMDNAME_SIMULATE_ERROR ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_I, true, false, &extraParamsFound ) ) { #ifndef NDEBUG const char buildType[] = "Debug build"; #else const char buildType[] = "Release build"; #endif Printf( "JtagDue %s" EOL, PACKAGE_VERSION ); Printf( "%s, compiler version %s" EOL, buildType, __VERSION__ ); Printf( "Watchdog %s" EOL, ENABLE_WDT ? "enabled" : "disabled" ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_RESET, false, false, &extraParamsFound ) ) { // This message does not reach the other side, we would need to add some delay. // UsbPrint( txBuffer, "Resetting the board..." EOL ); __disable_irq(); // Note that this message always goes to the serial port console, // even if the user is connected over USB. It might be possible to send // it over USB and then wait for the outgoing buffer to be empty. SerialSyncWriteStr( "Resetting the board..." EOL ); SerialWaitForDataSent(); ResetBoard( ENABLE_WDT ); assert( false ); // We should never reach this point. return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_CPU_LOAD, false, false, &extraParamsFound ) ) { if ( ENABLE_CPU_SLEEP ) PrintStr( "CPU load statistics not available." EOL ); else DisplayCpuLoad(); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_UPTIME, false, false, &extraParamsFound ) ) { char buffer[ CONVERT_TO_DEC_BUF_SIZE ]; Printf( "Uptime: %s seconds." EOL, convert_unsigned_to_dec_th( GetUptime() / 1000, buffer, ',' ) ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_RESET_CAUSE, false, false, &extraParamsFound ) ) { DisplayResetCause(); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_PRINT_MEMORY, false, true, &extraParamsFound ) ) { PrintMemory( paramBegin ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_BUSY_WAIT, false, true, &extraParamsFound ) ) { BusyWait( paramBegin ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_USBSPEEDTEST, false, true, &extraParamsFound ) ) { ProcessUsbSpeedTestCmd( paramBegin, currentTime ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_JTAGPINS, false, false, &extraParamsFound ) ) { PrintJtagPinStatus(); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_JTAGSHIFTSPEEDTEST, false, false, &extraParamsFound ) ) { if ( !IsNativeUsbPort() ) throw std::runtime_error( "This command is only available on the 'Native' USB port." ); // Fill the Rx buffer with some test data. assert( m_rxBuffer != NULL ); m_rxBuffer->Reset(); for ( uint32_t i = 0; !m_rxBuffer->IsFull(); ++i ) { m_rxBuffer->WriteElem( CUsbRxBuffer::ElemType( i ) ); } // If the mode is set to MODE_HIZ, you cannot see the generated signal with the oscilloscope. // Note also that the built-in pull-ups on the Atmel ATSAM3X8 are too weak (between 50 and 100 KOhm, // yields too slow a rising time) to be of any use. const bool oldPullUps = GetJtagPullups(); SetJtagPullups( false ); const JtagPinModeEnum oldMode = GetJtagPinMode(); SetJtagPinMode ( MODE_JTAG ); // Each JTAG transfer needs 2 bits in the Rx buffer, TMS and TDI, // but produces only 1 bit, TDO. const uint32_t jtagByteCount = m_rxBuffer->GetElemCount() / 2; const uint16_t bitCount = jtagByteCount * 8; // Shift all JTAG data through several times. const uint64_t startTime = GetUptime(); const uint32_t iterCount = 50; for ( uint32_t i = 0; i < iterCount; ++i ) { // We hope that this will not clear the buffer contents. assert( m_rxBuffer != NULL ); assert( m_txBuffer != NULL ); m_rxBuffer->Reset(); m_rxBuffer->CommitWrittenElements( jtagByteCount * 2 ); m_txBuffer->Reset(); ShiftJtagData( m_rxBuffer, m_txBuffer, bitCount ); assert( m_txBuffer->GetElemCount() == jtagByteCount ); } const uint64_t finishTime = GetUptime(); const uint32_t elapsedTime = uint32_t( finishTime - startTime ); m_rxBuffer->Reset(); m_txBuffer->Reset(); const unsigned kBitsPerSec = unsigned( uint64_t(bitCount) * iterCount * 1000 / elapsedTime / 1024 ); SetJtagPinMode( oldMode ); SetJtagPullups( oldPullUps ); // I am getting 221 KiB/s with GCC 4.7.3 and optimisation level "-O3". Printf( EOL "Finished JTAG shift speed test, throughput %u Kbits/s (%u KiB/s)." EOL, kBitsPerSec, kBitsPerSec / 8 ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_MALLOCTEST, false, false, &extraParamsFound ) ) { PrintStr( "Allocalling memory..." EOL ); volatile uint32_t * const volatile mallocTest = (volatile uint32_t *) malloc(123); *mallocTest = 123; PrintStr( "Releasing memory..." EOL ); free( const_cast< uint32_t * >( mallocTest ) ); PrintStr( "Test finished." EOL ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_CPP_EXCEPTION_TEST, false, false, &extraParamsFound ) ) { try { PrintStr( "Throwing integer exception..." EOL ); throw 123; PrintStr( "Throw did not work." EOL ); assert( false ); } catch ( ... ) { PrintStr( "Caught integer exception." EOL ); } PrintStr( "Test finished." EOL ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_SIMULATE_ERROR, false, true, &extraParamsFound ) ) { SimulateError( paramBegin ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_MEMORY_USAGE, false, false, &extraParamsFound ) ) { const unsigned heapSize = unsigned( GetHeapEndAddr() - uintptr_t( &_end ) ); Printf( "Partitions: malloc heap: %u bytes, free: %u bytes, stack: %u bytes." EOL, heapSize, GetStackStartAddr() - GetHeapEndAddr(), STACK_SIZE ); Printf( "Used stack (estimated): %u from %u bytes." EOL, unsigned( GetStackSizeUsageEstimate() ), STACK_SIZE ); const struct mallinfo mi = mallinfo(); const unsigned heapSizeAccordingToNewlib = unsigned( mi.arena ); Printf( "Heap: %u allocated from %u bytes." EOL, unsigned( mi.uordblks ), unsigned( mi.arena ) ); assert( heapSize == heapSizeAccordingToNewlib ); UNUSED_IN_RELEASE( heapSizeAccordingToNewlib ); return; } if ( extraParamsFound ) Printf( "Command \"%.*s\" does not take any parameters." EOL, cmdEnd - cmdBegin, cmdBegin ); else Printf( "Unknown command \"%.*s\"." EOL, cmdEnd - cmdBegin, cmdBegin ); }