diff --git a/CMakeLists.txt b/CMakeLists.txt index 8af9907..0b493db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ target_link_libraries(picowota hardware_structs pico_cyw43_arch_lwip_poll pico_stdlib + pico_multicore pico_sync pico_util picowota_reboot @@ -89,6 +90,8 @@ endfunction() picowota_retrieve_variable(PICOWOTA_WIFI_SSID false) picowota_retrieve_variable(PICOWOTA_WIFI_PASS true) picowota_retrieve_variable(PICOWOTA_WIFI_AP false) +picowota_retrieve_variable(PICOWOTA_ENTRY_PIN false) +picowota_retrieve_variable(PICOWOTA_ENTRY_AUTORE false) if ((NOT PICOWOTA_WIFI_SSID) OR (NOT PICOWOTA_WIFI_PASS)) message(FATAL_ERROR @@ -107,6 +110,17 @@ if (PICOWOTA_WIFI_AP) message("Building in WiFi AP mode.") endif() +# Use the WiFi AP mode upon request +if (PICOWOTA_ENTRY_AUTORE) + target_compile_definitions(picowota PUBLIC PICOWOTA_ENTRY_AUTORE=1) + message("Building with ota mode timeout auto reset.") +endif() + +if (PICOWOTA_ENTRY_PIN) + target_compile_definitions(picowota PUBLIC PICOWOTA_ENTRY_PIN=${PICOWOTA_ENTRY_PIN}) + message("Building with custom PICOWOTA_ENTRY_PIN.") +endif() + # Provide a helper to build a standalone target function(picowota_build_standalone NAME) get_target_property(PICOWOTA_SRC_DIR picowota SOURCE_DIR) @@ -160,16 +174,16 @@ function(picowota_build_combined NAME) COMMAND ${CMAKE_OBJCOPY} -Obinary ${COMBINED}.elf ${COMBINED}.bin ) - if (NOT ELF2UF2_FOUND) - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PICO_SDK_PATH}/tools) - find_package(ELF2UF2) - endif() - if (ELF2UF2_FOUND) - add_custom_command(TARGET ${COMBINED} POST_BUILD - COMMAND ELF2UF2 ${COMBINED}.elf ${COMBINED}.uf2 - ) - list(APPEND clean_files ${COMBINED}.uf2) - endif() +# if (NOT ELF2UF2_FOUND) +# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PICO_SDK_PATH}/tools) +# find_package(ELF2UF2) +# endif() +# if (ELF2UF2_FOUND) +# add_custom_command(TARGET ${COMBINED} POST_BUILD +# COMMAND ELF2UF2 ${COMBINED}.elf ${COMBINED}.uf2 +# ) +# list(APPEND clean_files ${COMBINED}.uf2) +# endif() set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${clean_files}") endfunction() diff --git a/README.md b/README.md index f8e51ba..6533060 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ as CMake variables: PICOWOTA_WIFI_SSID # The WiFi network SSID PICOWOTA_WIFI_PASS # The WiFi network password PICOWOTA_WIFI_AP # Optional; 0 = connect to the network, 1 = create it +PICOWOTA_ENTRY_PIN # Optional; default use pin 15, you can change it ``` Then, you can either build just your standalone app binary (suitable for diff --git a/main.c b/main.c index 8223c63..aed1584 100644 --- a/main.c +++ b/main.c @@ -22,9 +22,13 @@ #include "hardware/resets.h" #include "hardware/uart.h" #include "hardware/watchdog.h" +#include "hardware/sync.h" #include "pico/stdlib.h" #include "pico/cyw43_arch.h" +#if PICOWOTA_ENTRY_AUTORE == 1 +#include "pico/multicore.h" +#endif #include "tcp_comm.h" @@ -83,7 +87,11 @@ struct event { }; }; +#ifndef PICOWOTA_ENTRY_PIN #define BOOTLOADER_ENTRY_PIN 15 +#else +#define BOOTLOADER_ENTRY_PIN PICOWOTA_ENTRY_PIN +#endif #define TCP_PORT 4242 @@ -441,13 +449,13 @@ struct comm_command seal_cmd = { .handle = &handle_seal, }; -static void disable_interrupts(void) -{ - SysTick->CTRL &= ~1; - - NVIC->ICER[0] = 0xFFFFFFFF; - NVIC->ICPR[0] = 0xFFFFFFFF; -} +//static void disable_interrupts(void) +//{ +// SysTick->CTRL &= ~1; +// +// NVIC->ICER[0] = 0xFFFFFFFF; +// NVIC->ICPR[0] = 0xFFFFFFFF; +//} static void reset_peripherals(void) { @@ -572,6 +580,16 @@ static void network_deinit() cyw43_arch_deinit(); } +#if PICOWOTA_ENTRY_AUTORE == 1 +void core1_entry() +{ + // timout 5 minutes + sleep_ms(1000 * 60 * 5); + //auto reset(to bootloader) + picowota_reboot(true); +} +#endif + int main() { err_t err; @@ -587,6 +605,7 @@ int main() disable_interrupts(); reset_peripherals(); jump_to_vtor(vtor); + return 0; } DBG_PRINTF_INIT(); @@ -621,7 +640,11 @@ int main() } #endif - critical_section_init(&critical_section); +#if PICOWOTA_ENTRY_AUTORE == 1 + multicore_launch_core1(core1_entry); +#endif + + critical_section_init(&critical_section); const struct comm_command *cmds[] = { &sync_cmd, diff --git a/picowota_reboot/micropython.cmake b/picowota_reboot/micropython.cmake new file mode 100644 index 0000000..3b90b26 --- /dev/null +++ b/picowota_reboot/micropython.cmake @@ -0,0 +1,16 @@ +# Create an INTERFACE library for our C module. +add_library(usermod_picowotareboot INTERFACE) + +# Add our source files to the lib +target_sources(usermod_picowotareboot INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/reboot.c + ${CMAKE_CURRENT_LIST_DIR}/reboot_mp.c +) + +# Add the current directory as an include directory. +target_include_directories(usermod_picowotareboot INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/include +) + +# Link our INTERFACE library to the usermod target. +target_link_libraries(usermod INTERFACE usermod_picowotareboot) \ No newline at end of file diff --git a/picowota_reboot/micropython.mk b/picowota_reboot/micropython.mk new file mode 100644 index 0000000..d4ad880 --- /dev/null +++ b/picowota_reboot/micropython.mk @@ -0,0 +1,10 @@ +EXAMPLE_MOD_DIR := $(USERMOD_DIR) + +# Add all C files to SRC_USERMOD. +SRC_USERMOD += $(EXAMPLE_MOD_DIR)/reboot.c +SRC_USERMOD += $(EXAMPLE_MOD_DIR)/reboot_mp.c + +# We can add our module folder to include paths if needed +# This is not actually needed in this example. +CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR) +CEXAMPLE_MOD_DIR := $(USERMOD_DIR) diff --git a/picowota_reboot/reboot_mp.c b/picowota_reboot/reboot_mp.c new file mode 100644 index 0000000..75cf811 --- /dev/null +++ b/picowota_reboot/reboot_mp.c @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2023 KisChang + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include "py/runtime.h" +#include "py/obj.h" + +#include "picowota/reboot.h" + +static mp_obj_t mp_picowota_reboot(mp_obj_t arg_obj) { + bool arg = mp_obj_is_true(arg_obj); + picowota_reboot(arg); + return mp_obj_new_int(1); +} + +static MP_DEFINE_CONST_FUN_OBJ_1(mp_picowota_reboot_obj, mp_picowota_reboot); + +static const mp_rom_map_elem_t example_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picowota_reboot) }, + { MP_ROM_QSTR(MP_QSTR_reboot), MP_ROM_PTR(&mp_picowota_reboot_obj) }, +}; +static MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table); + +// Define module object. +const mp_obj_module_t user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&example_module_globals, +}; + +// Register the module to make it available in Python. +MP_REGISTER_MODULE(MP_QSTR_picowota_reboot, user_cmodule); diff --git a/standalone.ld b/standalone.ld index 040f6ad..69bd929 100644 --- a/standalone.ld +++ b/standalone.ld @@ -223,11 +223,18 @@ SECTIONS __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); __StackBottom = __StackTop - SIZEOF(.stack_dummy); + /* Define start and end of GC heap */ + __GcHeapStart = __bss_end__; + __GcHeapEnd = __StackLimit; PROVIDE(__stack = __StackTop); /* Check if data + heap + stack exceeds RAM limit */ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + /* Check GC heap is at least 128 KB */ + /* On a RP2040 using all SRAM this should always be the case. */ + ASSERT((__GcHeapEnd - __GcHeapStart) > 128*1024, "GcHeap is too small") + ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") /* todo assert on extra code */ }