//! @brief Read from peripheral until specified number of bytes received. static status_t read_data(uint8_t * buffer, uint32_t byteCount, uint32_t timeoutMs) { #ifdef BOOTLOADER_HOST // Host will not be relying on interrupts for reads so manually read the data out return g_bootloaderContext.activePeripheral->byteInterface->read( g_bootloaderContext.activePeripheral, buffer, byteCount); #else // On the target we read from our interrupt buffer uint32_t currentBytesRead = 0; uint64_t startTicks = microseconds_get_ticks(); uint64_t timeOutTicks = microseconds_convert_to_ticks(timeoutMs * 1000); while(currentBytesRead != byteCount) { if (timeOutTicks && ((microseconds_get_ticks() - startTicks) >= timeOutTicks)) { return kStatus_Timeout; } if (g_serialContext.readOffset != g_serialContext.writeOffset) { buffer[currentBytesRead++] = g_serialContext.callbackBuffer[g_serialContext.readOffset++]; g_serialContext.readOffset &= kCallbackBufferSize - 1; } } return kStatus_Success; #endif }
//! @brief Determines the active peripheral. //! //! This function has several stages: //! - Init enabled peripherals. //! - Compute timeout. //! - Wait for peripheral activity with timeout. //! - Shutdown inactive peripherals. //! //! If peripheral detection times out, then this function will call jump_to_application() to //! directly enter the user application. //! //! The timeout value comes from the BCA if set, or the #BL_DEFAULT_PERIPHERAL_DETECT_TIMEOUT //! configuration macro. If the boot pin is asserted, or if there is not a valid user application //! in flash, then the timeout is disabled and peripheral detection will continue infinitely. static peripheral_descriptor_t const *get_active_peripheral(void) { peripheral_descriptor_t const *peripheral; peripheral_descriptor_t const *activePeripheral = NULL; bootloader_configuration_data_t *configurationData = &g_bootloaderContext.propertyInterface->store->configurationData; // Bring up all the peripherals for (peripheral = g_peripherals; peripheral->typeMask != 0; ++peripheral) { // Check that the peripheral is enabled in the user configuration data if (configurationData->enabledPeripherals & peripheral->typeMask) { assert(peripheral->controlInterface->init); debug_printf("Initing %s\r\n", get_peripheral_name(peripheral->typeMask)); peripheral->controlInterface->init(peripheral, peripheral->packetInterface->byteReceivedCallback); } } #if !BL_FEATURE_TIMEOUT uint64_t lastTicks = 0; // Value of our last recorded ticks second marker uint64_t timeoutTicks = 120000000; // SGF Add timeout to make the bootloader Jump to application after some time. 0 means no timeout. const uint64_t ticksPerMillisecond = microseconds_convert_to_ticks(1000); // Get the user application entry point and stack pointer. uint32_t applicationAddress, stackPointer; get_user_application_entry(&applicationAddress, &stackPointer); // If the boot to rom option is not set AND there is a valid jump application determine the timeout value if (!is_boot_pin_asserted() && is_application_ready_for_executing(applicationAddress)) { if (is_direct_boot()) { if (RCM->SRS0 & RCM_SRS0_POR_MASK || (IS_WORMHOLE_OPEN && Wormhole.enumerationMode != EnumerationMode_Bootloader)) { jump_to_application(applicationAddress, stackPointer); } } // Calculate how many ticks we need to wait based on the bootloader config. Check to see if // there is a valid configuration data value for the timeout. If there's not, use the // default timeout value. uint32_t milliseconds; if (configurationData->peripheralDetectionTimeoutMs != 0xFFFF) { milliseconds = configurationData->peripheralDetectionTimeoutMs; } else { milliseconds = BL_DEFAULT_PERIPHERAL_DETECT_TIMEOUT; } if (IS_WORMHOLE_OPEN) { milliseconds = Wormhole.timeoutMs; } if (milliseconds < BL_MIN_PERIPHERAL_DETECT_TIMEOUT) { milliseconds = BL_MIN_PERIPHERAL_DETECT_TIMEOUT; } timeoutTicks = milliseconds * ticksPerMillisecond; // save how many ticks we're currently at before the detection loop starts lastTicks = microseconds_get_ticks(); } #endif // !BL_FEATURE_TIMEOUT // Wait for a peripheral to become active while (activePeripheral == NULL) { #if !BL_FEATURE_TIMEOUT // If timeout is enabled, check to see if we've exceeded it. if (timeoutTicks) { // Note that we assume that the tick counter won't overflow and wrap back to 0. // The timeout value is only up to 65536 milliseconds, and the tick count starts // at zero when when inited the microseconds driver just a few moments ago. uint64_t elapsedTicks = microseconds_get_ticks() - lastTicks; // Check if the elapsed time is longer than the timeout. if (elapsedTicks >= timeoutTicks) { // In the case of the typical peripheral timeout, jump to the user application. if (is_application_ready_for_executing(applicationAddress)) { jump_to_application(applicationAddress, stackPointer); } } } #endif // !BL_FEATURE_TIMEOUT // Traverse through all the peripherals for (peripheral = g_peripherals; peripheral->typeMask != 0; ++peripheral) { // Check that the peripheral is enabled in the user configuration data if (configurationData->enabledPeripherals & peripheral->typeMask) { assert(peripheral->controlInterface->pollForActivity); if (peripheral->controlInterface->pollForActivity(peripheral)) { debug_printf("%s is active\r\n", get_peripheral_name(peripheral->typeMask)); activePeripheral = peripheral; break; } } } } // Shut down all non active peripherals for (peripheral = g_peripherals; peripheral->typeMask != 0; ++peripheral) { // Check that the peripheral is enabled in the user configuration data if (configurationData->enabledPeripherals & peripheral->typeMask) { if (activePeripheral != peripheral) { debug_printf("Shutting down %s\r\n", get_peripheral_name(peripheral->typeMask)); assert(peripheral->controlInterface->shutdown); peripheral->controlInterface->shutdown(peripheral); } } } return activePeripheral; }