diff --git a/CMakeLists.txt b/CMakeLists.txt index 7132769..94e77d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,12 +3,19 @@ cmake_minimum_required(VERSION 3.18) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) -# Project/hardware-specific setup - set platform in project.cmake +include(build_options.cmake) + +# Project/hardware-specific setup - set platform, board, and requested hardware +# options in project.cmake include(project.cmake) + +# Set the hardware directory and load any prebuild which may be present. set(hardware_dir ${CMAKE_CURRENT_SOURCE_DIR}/hardware/${PLATFORM}) if(EXISTS ${hardware_dir}/prebuild.cmake) include(${hardware_dir}/prebuild.cmake) endif() + +# Main project definition project(${PROJ_NAME} C CXX ASM) add_definitions(-DPROJECT_NAME=${PROJ_NAME}) # pass the project name to the preprocessor for use in the code @@ -39,13 +46,7 @@ target_link_libraries(${PROJ_NAME} PUBLIC cli littlefs cmake_git_version_tracking - hardware_i2c - hardware_spi - hardware_flash - hardware_adc - cmsis_core - tinyusb_device - ${hardware_libs} + board_hal ) target_include_directories(${PROJ_NAME} PUBLIC ${PROJECT_SOURCE_DIR} @@ -54,20 +55,16 @@ target_include_directories(${PROJ_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/driver_lib ${PROJECT_SOURCE_DIR}/littlefs/littlefs ${PROJECT_SOURCE_DIR}/git_version - ${PROJECT_SOURCE_DIR}/${hardware_includes} ) add_subdirectory(${PROJECT_SOURCE_DIR}/rtos) add_subdirectory(${PROJECT_SOURCE_DIR}/services) add_subdirectory(${PROJECT_SOURCE_DIR}/driver_lib) + if(DEFINED hardware_dir) add_subdirectory(${hardware_dir}) endif() -# add any additional definitions, options -target_compile_definitions(${PROJ_NAME} PUBLIC - CFG_TUSB_CONFIG_FILE="hardware_config.h" # override standard TinyUSB config file location -) target_compile_options( ${PROJ_NAME} PRIVATE diff --git a/build_options.cmake b/build_options.cmake new file mode 100644 index 0000000..7538d05 --- /dev/null +++ b/build_options.cmake @@ -0,0 +1,3 @@ +# This file contains all of the user-configurable option toggles for the OS. +# Options can be set to true/false here, on the command line, or through the cmake-gui tool. +option(HW_WIFI "Enable wifi support" false) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 63e479c..ce2e1d3 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -28,22 +28,24 @@ add_library(cli STATIC ${CMAKE_CURRENT_LIST_DIR}/node_etc.c ${CMAKE_CURRENT_LIST_DIR}/node_lib.c ) + target_link_libraries(cli PUBLIC microshell - pico_stdlib FreeRTOS-Kernel cmake_git_version_tracking + board_hal ) + target_include_directories(cli PUBLIC ${CMAKE_CURRENT_LIST_DIR} ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/rtos - ${PROJECT_SOURCE_DIR}/hardware/rp2040 ${PROJECT_SOURCE_DIR}/driver_lib ${PROJECT_SOURCE_DIR}/services ${PROJECT_SOURCE_DIR}/littlefs/littlefs ${PROJECT_SOURCE_DIR}/git_version ) + target_compile_options( cli PRIVATE diff --git a/hardware/rp2040/CMakeLists.txt b/hardware/rp2040/CMakeLists.txt index d068473..baaccdf 100644 --- a/hardware/rp2040/CMakeLists.txt +++ b/hardware/rp2040/CMakeLists.txt @@ -1,5 +1,7 @@ +add_library(board_hal INTERFACE) + # add source files to the top-level project -target_sources(${PROJ_NAME} PRIVATE +target_sources(board_hal INTERFACE hardware_config.c hw_gpio.c hw_uart.c @@ -16,16 +18,42 @@ target_sources(${PROJ_NAME} PRIVATE hw_versions.c ) +target_include_directories(board_hal INTERFACE + ${CMAKE_CURRENT_LIST_DIR} +) + +target_link_libraries(board_hal INTERFACE + pico_stdlib + pico_unique_id + hardware_i2c + hardware_spi + hardware_flash + hardware_adc + tinyusb_device +) + +target_compile_definitions(board_hal INTERFACE CFG_TUSB_CONFIG_FILE="hardware_config.h") + +if(PICO_BOARD STREQUAL pico_w) + target_compile_definitions(board_hal INTERFACE USING_CYW43=1) + + if(HW_WIFI) + message(STATUS "including hw_wifi and lwIP stack for pico_w") + target_compile_definitions(board_hal INTERFACE HW_WIFI=1) # cmake options come through as quoted strings for some reason + target_sources(board_hal INTERFACE hw_wifi.c) + target_link_libraries(board_hal INTERFACE pico_cyw43_arch_lwip_sys_freertos) + target_include_directories(board_hal INTERFACE ${CMAKE_CURRENT_LIST_DIR}/lwip_config) + else() + message(STATUS "lwIP stack will be unavailable : HW_WIFI set to 0") + target_compile_definitions(board_hal INTERFACE HW_WIFI=0) + target_link_libraries(board_hal INTERFACE pico_cyw43_arch_none) + endif() +endif() + function(hardware_build_extra) # initialize the Pico/RP2040 SDK pico_sdk_init() - if(PICO_BOARD STREQUAL "pico_w") - # Pass this parameter to the preprocessor if board type is pico_w - # since some HW config needs to change - target_compile_definitions(cli PUBLIC -DUSING_PICOW) - endif() - # disable Pico STDIO - interacting with CLI will be done via RTOS task queue only, no printf pico_enable_stdio_usb(${PROJ_NAME} 0) pico_enable_stdio_uart(${PROJ_NAME} 0) diff --git a/hardware/rp2040/hardware_config.c b/hardware/rp2040/hardware_config.c index 7a55447..980aa5e 100644 --- a/hardware/rp2040/hardware_config.c +++ b/hardware/rp2040/hardware_config.c @@ -8,20 +8,16 @@ * @author Cavin McKinley (MCKNLY LLC) * * @date 02-14-2024 - * + * * @copyright Copyright (c) 2024 Cavin McKinley (MCKNLY LLC) * Released under the MIT License - * + * * SPDX-License-Identifier: MIT ******************************************************************************/ #include #include "hardware_config.h" -#ifdef USING_CYW43 -#include "pico/cyw43_arch.h" -#endif - void hardware_init(void) { // mutexes for accessing hardware peripherals (created within each hw init function) SemaphoreHandle_t gpio_mutex = NULL; @@ -37,7 +33,11 @@ void hardware_init(void) { cli_uart_init(); // on pico w, we need to initialize the wifi chip -#ifdef USING_CYW43 + + // we only want to initialize the cyw43 arch if the hardware isn't using wifi +#if (HW_WIFI == 0) & defined(USING_CYW43) + #include "pico/cyw43_arch.h" + if(cyw43_arch_init()) { uart_puts(UART_ID_CLI, timestamp()); uart_puts(UART_ID_CLI, "Failed to initialize CYW43 hardware.\r\n"); diff --git a/hardware/rp2040/hw_wifi.c b/hardware/rp2040/hw_wifi.c new file mode 100644 index 0000000..5e57183 --- /dev/null +++ b/hardware/rp2040/hw_wifi.c @@ -0,0 +1,108 @@ +#include "hw_wifi.h" + +#include "pico/cyw43_arch.h" + +bool hw_wifi_is_initialized() { + return cyw43_is_initialized(&cyw43_state); +} + +bool hw_wifi_init() { + if (hw_wifi_is_initialized()) return true; + return !cyw43_arch_init(); +} + +bool hw_wifi_init_with_country(hw_wifi_country_t country_code) { + if (hw_wifi_is_initialized()) return true; + return !cyw43_arch_init_with_country(country_code); +} + +void hw_wifi_deinit() { + if (hw_wifi_is_initialized()) return; + cyw43_arch_deinit(); +} + +// todo : this is locked to lwIP, and we maybe don't want that? +const ip_addr_t *hw_wifi_get_addr() { + return netif_ip4_addr(netif_list); +} + +static uint32_t hw_wifi_auth_to_cyw43(hw_wifi_auth_t auth) { + switch (auth) { + case HW_WIFI_AUTH_MIXED: + return CYW43_AUTH_WPA2_MIXED_PSK; + case HW_WIFI_AUTH_WPA_TPIK_PSK: + return CYW43_AUTH_WPA_TKIP_PSK; + case HW_WIFI_AUTH_WPA2_AES_PSK: + return CYW43_AUTH_WPA2_AES_PSK; + default: + return CYW43_AUTH_OPEN; + } +} + +bool hw_wifi_connect(const char *ssid, const char *password, hw_wifi_auth_t auth_type) { + uint32_t cw_auth = hw_wifi_auth_to_cyw43(auth_type); + + return !cyw43_arch_wifi_connect_blocking(ssid, password, cw_auth); +} + +bool hw_wifi_connect_async(const char *ssid, const char *password, hw_wifi_auth_t auth_type) { + uint32_t cw_auth = hw_wifi_auth_to_cyw43(auth_type); + + return !cyw43_arch_wifi_connect_async(ssid, password, cw_auth); +} + +static hw_wifi_mode_t current_mode = HW_WIFI_MODE_NONE; + +// NOTE: the pico_w will _technically_ support simultaneous AP and STA mode +// connections, but this implementation does not. +void hw_wifi_enable_sta_mode() { + hw_wifi_disable_ap_mode(); + cyw43_arch_enable_sta_mode(); + current_mode = HW_WIFI_MODE_STA; +} + +void hw_wifi_disable_sta_mode() { + if (current_mode == HW_WIFI_MODE_STA) { + cyw43_arch_disable_sta_mode(); + current_mode = HW_WIFI_MODE_NONE; + } +} + +void hw_wifi_enable_ap_mode(const char *ssid, const char *password, hw_wifi_auth_t auth_type) { + hw_wifi_disable_sta_mode(); + cyw43_arch_enable_ap_mode(ssid, password, hw_wifi_auth_to_cyw43(auth_type)); +} + +void hw_wifi_disable_ap_mode() { + if (current_mode == HW_WIFI_MODE_AP) { + cyw43_arch_disable_ap_mode(); + current_mode = HW_WIFI_MODE_NONE; + } +} + +hw_wifi_status_t hw_wifi_get_status() { + // AP mode always returns LINKDOWN from cyw43 + if (current_mode == HW_WIFI_MODE_AP) { + return HW_WIFI_STATUS_LINK_DOWN; + } + + uint32_t status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); + switch (status) { + case CYW43_LINK_DOWN: + return HW_WIFI_STATUS_LINK_DOWN; + case CYW43_LINK_JOIN: + return HW_WIFI_STATUS_JOINING; + case CYW43_LINK_NOIP: + return HW_WIFI_STATUS_NOIP; + case CYW43_LINK_UP: + return HW_WIFI_STATUS_UP; + case CYW43_LINK_FAIL: + return HW_WIFI_STATUS_FAIL; + case CYW43_LINK_NONET: + return HW_WIFI_STATUS_NONET; + case CYW43_LINK_BADAUTH: + return HW_WIFI_STATUS_BADAUTH; + default: + return HW_WIFI_STATUS_UNKNOWN; + } +} diff --git a/hardware/rp2040/hw_wifi.h b/hardware/rp2040/hw_wifi.h new file mode 100644 index 0000000..be28b8a --- /dev/null +++ b/hardware/rp2040/hw_wifi.h @@ -0,0 +1,113 @@ +#ifndef rp2040_WIFI_H +#define rp2040_WIFI_H + +#include +#include + +#include "pico/cyw43_arch.h" + +typedef uint32_t hw_wifi_country_t ; + +/*! + * \brief create a country code from the two character country and revision number + */ +#define HW_WIFI_COUNTRY(A, B, REV) (hw_wifi_country_t)((unsigned char)(A) | ((unsigned char)(B) << 8) | ((REV) << 16)) + +// Worldwide Locale (passive Ch12-14) +#define HW_WIFI_COUNTRY_WORLDWIDE HW_WIFI_COUNTRY('X', 'X', 0) + +#define HW_WIFI_COUNTRY_AUSTRALIA HW_WIFI_COUNTRY('A', 'U', 0) +#define HW_WIFI_COUNTRY_AUSTRIA HW_WIFI_COUNTRY('A', 'T', 0) +#define HW_WIFI_COUNTRY_BELGIUM HW_WIFI_COUNTRY('B', 'E', 0) +#define HW_WIFI_COUNTRY_BRAZIL HW_WIFI_COUNTRY('B', 'R', 0) +#define HW_WIFI_COUNTRY_CANADA HW_WIFI_COUNTRY('C', 'A', 0) +#define HW_WIFI_COUNTRY_CHILE HW_WIFI_COUNTRY('C', 'L', 0) +#define HW_WIFI_COUNTRY_CHINA HW_WIFI_COUNTRY('C', 'N', 0) +#define HW_WIFI_COUNTRY_COLOMBIA HW_WIFI_COUNTRY('C', 'O', 0) +#define HW_WIFI_COUNTRY_CZECH_REPUBLIC HW_WIFI_COUNTRY('C', 'Z', 0) +#define HW_WIFI_COUNTRY_DENMARK HW_WIFI_COUNTRY('D', 'K', 0) +#define HW_WIFI_COUNTRY_ESTONIA HW_WIFI_COUNTRY('E', 'E', 0) +#define HW_WIFI_COUNTRY_FINLAND HW_WIFI_COUNTRY('F', 'I', 0) +#define HW_WIFI_COUNTRY_FRANCE HW_WIFI_COUNTRY('F', 'R', 0) +#define HW_WIFI_COUNTRY_GERMANY HW_WIFI_COUNTRY('D', 'E', 0) +#define HW_WIFI_COUNTRY_GREECE HW_WIFI_COUNTRY('G', 'R', 0) +#define HW_WIFI_COUNTRY_HONG_KONG HW_WIFI_COUNTRY('H', 'K', 0) +#define HW_WIFI_COUNTRY_HUNGARY HW_WIFI_COUNTRY('H', 'U', 0) +#define HW_WIFI_COUNTRY_ICELAND HW_WIFI_COUNTRY('I', 'S', 0) +#define HW_WIFI_COUNTRY_INDIA HW_WIFI_COUNTRY('I', 'N', 0) +#define HW_WIFI_COUNTRY_ISRAEL HW_WIFI_COUNTRY('I', 'L', 0) +#define HW_WIFI_COUNTRY_ITALY HW_WIFI_COUNTRY('I', 'T', 0) +#define HW_WIFI_COUNTRY_JAPAN HW_WIFI_COUNTRY('J', 'P', 0) +#define HW_WIFI_COUNTRY_KENYA HW_WIFI_COUNTRY('K', 'E', 0) +#define HW_WIFI_COUNTRY_LATVIA HW_WIFI_COUNTRY('L', 'V', 0) +#define HW_WIFI_COUNTRY_LIECHTENSTEIN HW_WIFI_COUNTRY('L', 'I', 0) +#define HW_WIFI_COUNTRY_LITHUANIA HW_WIFI_COUNTRY('L', 'T', 0) +#define HW_WIFI_COUNTRY_LUXEMBOURG HW_WIFI_COUNTRY('L', 'U', 0) +#define HW_WIFI_COUNTRY_MALAYSIA HW_WIFI_COUNTRY('M', 'Y', 0) +#define HW_WIFI_COUNTRY_MALTA HW_WIFI_COUNTRY('M', 'T', 0) +#define HW_WIFI_COUNTRY_MEXICO HW_WIFI_COUNTRY('M', 'X', 0) +#define HW_WIFI_COUNTRY_NETHERLANDS HW_WIFI_COUNTRY('N', 'L', 0) +#define HW_WIFI_COUNTRY_NEW_ZEALAND HW_WIFI_COUNTRY('N', 'Z', 0) +#define HW_WIFI_COUNTRY_NIGERIA HW_WIFI_COUNTRY('N', 'G', 0) +#define HW_WIFI_COUNTRY_NORWAY HW_WIFI_COUNTRY('N', 'O', 0) +#define HW_WIFI_COUNTRY_PERU HW_WIFI_COUNTRY('P', 'E', 0) +#define HW_WIFI_COUNTRY_PHILIPPINES HW_WIFI_COUNTRY('P', 'H', 0) +#define HW_WIFI_COUNTRY_POLAND HW_WIFI_COUNTRY('P', 'L', 0) +#define HW_WIFI_COUNTRY_PORTUGAL HW_WIFI_COUNTRY('P', 'T', 0) +#define HW_WIFI_COUNTRY_SINGAPORE HW_WIFI_COUNTRY('S', 'G', 0) +#define HW_WIFI_COUNTRY_SLOVAKIA HW_WIFI_COUNTRY('S', 'K', 0) +#define HW_WIFI_COUNTRY_SLOVENIA HW_WIFI_COUNTRY('S', 'I', 0) +#define HW_WIFI_COUNTRY_SOUTH_AFRICA HW_WIFI_COUNTRY('Z', 'A', 0) +#define HW_WIFI_COUNTRY_SOUTH_KOREA HW_WIFI_COUNTRY('K', 'R', 0) +#define HW_WIFI_COUNTRY_SPAIN HW_WIFI_COUNTRY('E', 'S', 0) +#define HW_WIFI_COUNTRY_SWEDEN HW_WIFI_COUNTRY('S', 'E', 0) +#define HW_WIFI_COUNTRY_SWITZERLAND HW_WIFI_COUNTRY('C', 'H', 0) +#define HW_WIFI_COUNTRY_TAIWAN HW_WIFI_COUNTRY('T', 'W', 0) +#define HW_WIFI_COUNTRY_THAILAND HW_WIFI_COUNTRY('T', 'H', 0) +#define HW_WIFI_COUNTRY_TURKEY HW_WIFI_COUNTRY('T', 'R', 0) +#define HW_WIFI_COUNTRY_UK HW_WIFI_COUNTRY('G', 'B', 0) +#define HW_WIFI_COUNTRY_USA HW_WIFI_COUNTRY('U', 'S', 0) + +typedef enum{ + HW_WIFI_AUTH_OPEN, + HW_WIFI_AUTH_WPA_TPIK_PSK, + HW_WIFI_AUTH_WPA2_AES_PSK, + HW_WIFI_AUTH_MIXED, +} hw_wifi_auth_t ; + +typedef enum{ + HW_WIFI_MODE_NONE, + HW_WIFI_MODE_STA, + HW_WIFI_MODE_AP, +} hw_wifi_mode_t ; + +typedef enum{ + HW_WIFI_STATUS_LINK_DOWN, + HW_WIFI_STATUS_JOINING, + HW_WIFI_STATUS_NOIP, + HW_WIFI_STATUS_UP, + HW_WIFI_STATUS_FAIL, + HW_WIFI_STATUS_BADAUTH, + HW_WIFI_STATUS_NONET, + + HW_WIFI_STATUS_UNKNOWN, +} hw_wifi_status_t ; + +bool hw_wifi_is_initialized(); +bool hw_wifi_init(); +bool hw_wifi_init_with_country(uint32_t country_code); +void hw_wifi_deinit(); + +// NOTE: the pico_w will _technically_ support simultaneous AP and STA mode +// connections, but this implementation does not. +void hw_wifi_enable_sta_mode(); +void hw_wifi_disable_sta_mode(); +void hw_wifi_enable_ap_mode(const char *ssid, const char *password, hw_wifi_auth_t auth_type); +void hw_wifi_disable_ap_mode(); + +const ip_addr_t *hw_wifi_get_addr(); +bool hw_wifi_connect(const char *ssid, const char *password, hw_wifi_auth_t auth_type); +bool hw_wifi_connect_async(const char *ssid, const char *password, hw_wifi_auth_t auth_type); +hw_wifi_status_t hw_wifi_get_status(); + +#endif diff --git a/hardware/rp2040/lwip_config/lwipopts.h b/hardware/rp2040/lwip_config/lwipopts.h new file mode 100644 index 0000000..180ea54 --- /dev/null +++ b/hardware/rp2040/lwip_config/lwipopts.h @@ -0,0 +1,89 @@ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + + +#define TCPIP_THREAD_PRIO 2 +#define TCPIP_THREAD_STACKSIZE 2048 //1024 +#define DEFAULT_THREAD_STACKSIZE 1024 +#define DEFAULT_RAW_RECVMBOX_SIZE 8 +#define TCPIP_MBOX_SIZE 8 +#define LWIP_TIMEVAL_PRIVATE 0 + +#define LWIP_SOCKET 1 + +#define MEM_LIBC_MALLOC 1 + +#define MEM_ALIGNMENT 4 +#define MEM_SIZE 4000 +#define MEMP_NUM_TCP_SEG 32 +#define MEMP_NUM_ARP_QUEUE 10 +#define PBUF_POOL_SIZE 24 +#define LWIP_ARP 1 +#define LWIP_ETHERNET 1 +#define LWIP_ICMP 1 +#define LWIP_RAW 1 +#define TCP_WND (8 * TCP_MSS) +#define TCP_MSS 1460 +#define TCP_SND_BUF (8 * TCP_MSS) +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS)) +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define LWIP_NETIF_HOSTNAME 1 +#define LWIP_NETCONN 1 +#define MEM_STATS 0 +#define SYS_STATS 0 +#define MEMP_STATS 0 +#define LINK_STATS 0 +// #define ETH_PAD_SIZE 2 +#define LWIP_CHKSUM_ALGORITHM 3 +#define LWIP_DHCP 1 +#define LWIP_IPV4 1 +#define LWIP_TCP 1 +#define LWIP_UDP 1 +#define LWIP_DNS 1 +#define LWIP_TCP_KEEPALIVE 1 +#define LWIP_NETIF_TX_SINGLE_PBUF 1 +#define DHCP_DOES_ARP_CHECK 1 +#define LWIP_DHCP_DOES_ACD_CHECK 0 + +#ifndef NDEBUG +#define LWIP_DEBUG 1 +#define LWIP_STATS 1 +#define LWIP_STATS_DISPLAY 1 +#endif + +#define ETHARP_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_OFF +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define RAW_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define PPP_DEBUG LWIP_DBG_OFF +#define SLIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_OFF + + +#define DEFAULT_TCP_RECVMBOX_SIZE 128 + + + +#endif /* __LWIPOPTS_H__ */ diff --git a/main.c b/main.c index 1c3794d..8b43053 100644 --- a/main.c +++ b/main.c @@ -6,10 +6,10 @@ * @author Cavin McKinley (MCKNLY LLC) * * @date 02-14-2024 - * + * * @copyright Copyright (c) 2024 Cavin McKinley (MCKNLY LLC) * Released under the MIT License - * + * * SPDX-License-Identifier: MIT ******************************************************************************/ @@ -31,12 +31,15 @@ void main() // initialize any connected peripheral devices driver_init(); +#if !defined(HW_WIFI) || (HW_WIFI == 0) // register the taskmanager base service taskman_service(); - +#else + wifi_service(); +#endif // start the rtos scheduler (boot the system!) vTaskStartScheduler(); // will not reach here unless rtos crashes, reboot if that happens force_watchdog_reboot(); -} \ No newline at end of file +} diff --git a/rtos/FreeRTOSConfig.h b/rtos/FreeRTOSConfig.h index dee2f02..5614621 100644 --- a/rtos/FreeRTOSConfig.h +++ b/rtos/FreeRTOSConfig.h @@ -6,10 +6,10 @@ * @author Cavin McKinley (MCKNLY LLC) * * @date 02-14-2024 - * + * * @copyright Copyright (c) 2024 Cavin McKinley (MCKNLY LLC) * Released under the MIT License - * + * * * FreeRTOS V202212.00 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. @@ -55,6 +55,7 @@ #define configUSE_PREEMPTION 1 #define configUSE_TICKLESS_IDLE 0 #define configUSE_IDLE_HOOK 0 +#define configUSE_PASSIVE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) #define configMAX_PRIORITIES 32 @@ -72,7 +73,7 @@ #define configUSE_QUEUE_SETS 1 #define configUSE_TIME_SLICING 1 #define configUSE_NEWLIB_REENTRANT 0 -#define configENABLE_BACKWARD_COMPATIBILITY 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 /* System */ @@ -82,7 +83,7 @@ /* Memory allocation related definitions. */ #define configSUPPORT_STATIC_ALLOCATION 0 #define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configTOTAL_HEAP_SIZE (230*1024) // figure out what linker will accept +#define configTOTAL_HEAP_SIZE (192*1024) // figure out what linker will accept #define configAPPLICATION_ALLOCATED_HEAP 0 /* Hook function related definitions. */ @@ -111,8 +112,10 @@ /* SMP port only */ #define configNUM_CORES 2 -#define configTICK_CORE 1 +#define configNUMBER_OF_CORES configNUM_CORES +#define configTICK_CORE 0 #define configRUN_MULTIPLE_PRIORITIES 1 +#define configUSE_CORE_AFFINITY 1 /* RP2040 specific */ #define configSUPPORT_PICO_SYNC_INTEROP 1 diff --git a/services/CMakeLists.txt b/services/CMakeLists.txt index 2df3d0b..c3947bd 100644 --- a/services/CMakeLists.txt +++ b/services/CMakeLists.txt @@ -8,4 +8,15 @@ target_sources(${PROJ_NAME} PRIVATE storman_service.c watchdog_service.c heartbeat_service.c -) \ No newline at end of file +) + +if (DEFINED HW_WIFI AND HW_WIFI) + target_sources(${PROJ_NAME} PRIVATE wifi_service.c) + if(NOT DEFINED ENV{WIFI_SSID} OR NOT DEFINED ENV{WIFI_PASSWORD}) + message(FATAL_ERROR "must define WIFI_SSID and WIFI_PASSWORD environment variables to use wifi") + endif() + target_compile_definitions(${PROJ_NAME} PRIVATE + WIFI_SSID=\"$ENV{WIFI_SSID}\" + WIFI_PASSWORD=\"$ENV{WIFI_PASSWORD}\" + ) +endif() diff --git a/services/services.c b/services/services.c index 080113a..2eff514 100644 --- a/services/services.c +++ b/services/services.c @@ -12,10 +12,10 @@ * @author @nbes4 (github) * * @date 06-18-2024 - * + * * @copyright Copyright (c) 2024 @nbes4 (github) * Released under the MIT License - * + * * SPDX-License-Identifier: MIT ******************************************************************************/ @@ -25,31 +25,38 @@ // note: use xstr() to convert the SERVICE_NAME_ #define from services.h to a usable string // (e.g. xstr(SERVICE_NAME_HEARTBEAT)) const service_desc_t service_descriptors[] = { - { - .name = xstr(SERVICE_NAME_USB), - .service_func = usb_service, - .startup = true - }, - { - .name = xstr(SERVICE_NAME_CLI), - .service_func = cli_service, - .startup = true - }, - { - .name = xstr(SERVICE_NAME_STORMAN), - .service_func = storman_service, - .startup = true - }, - { - .name = xstr(SERVICE_NAME_WATCHDOG), - .service_func = watchdog_service, - .startup = true - }, - { - .name = xstr(SERVICE_NAME_HEARTBEAT), - .service_func = heartbeat_service, - .startup = false - } + { + .name = xstr(SERVICE_NAME_USB), + .service_func = usb_service, + .startup = true + }, + { + .name = xstr(SERVICE_NAME_CLI), + .service_func = cli_service, + .startup = true + }, + { + .name = xstr(SERVICE_NAME_STORMAN), + .service_func = storman_service, + .startup = true + }, + { + .name = xstr(SERVICE_NAME_WATCHDOG), + .service_func = watchdog_service, + .startup = true + }, + { + .name = xstr(SERVICE_NAME_HEARTBEAT), + .service_func = heartbeat_service, + .startup = false + }, +#if (HW_WIFI == 1) + { + .name = "wifi", + .service_func = wifi_service, + .startup = true + } +#endif }; -const size_t service_descriptors_length = sizeof(service_descriptors)/sizeof(service_desc_t); \ No newline at end of file +const size_t service_descriptors_length = sizeof(service_descriptors) / sizeof(service_desc_t); diff --git a/services/services.h b/services/services.h index b98b492..63f37f9 100644 --- a/services/services.h +++ b/services/services.h @@ -10,10 +10,10 @@ * @author Cavin McKinley (MCKNLY LLC) * * @date 02-14-2024 - * + * * @copyright Copyright (c) 2024 Cavin McKinley (MCKNLY LLC) * Released under the MIT License - * + * * SPDX-License-Identifier: MIT ******************************************************************************/ @@ -31,7 +31,7 @@ * Services - Dynamic tasks to run in FreeRTOS. * Services can be launched at boot or started/suspended/stopped at * any time via 'taskmanager', the base service. - * + * * If a new service is added, a SERVICE_NAME must be defined for it, * and the service implementation and FreeRTOS task launcher must be * created in a separate source file (see "heartbeat_service.c" for @@ -39,7 +39,7 @@ * to the service_descriptors[] array in services.c, which associates * the service's main function pointer with its name string, and * defines whether the service should run at boot. - * + * * The service schedule within FreeRTOS is determined by 3 parameters: * Priority, Repeat, and Delay. Upon any given scheduler tick, the OS * will run the task (service) with the highest priority. After a task @@ -48,13 +48,13 @@ * of times it will block itself for the specified number of ticks * based on the DELAY parameter. This essentially means a task's run * percentage (within a priority level) is given by REPEAT/DELAY. - * + * * Pro tip: uncomment add_definitions(-DSCHED_TEST_DELAY) in the * top-level CMakeLists.txt to burn extra cycles in each service, and * then use the 'bin/top' CLI command to show FreeRTOS task runtime * percentages to help tune the scheduler! Don't forget to comment * this back out after testing! - * + * * Note that by default, 1 OS tick is 1 ms. * This can be changed in FreeRTOSConfig.h, see 'configTICK_RATE_HZ' *******************************************************************************/ @@ -78,12 +78,12 @@ #define PRIORITY_CLI 1 #define PRIORITY_USB 2 #define PRIORITY_STORMAN 3 -#define PRIORITY_WATCHDOG 1 +#define PRIORITY_WATCHDOG 3 // todo: this needs to go back to 1 before final merge of the feature #define PRIORITY_HEARTBEAT 1 // number of sequential time slices to run each service before beginning the // delay interval set below. If a service should run most of the time, set REPEAT -// to a higher number and DELAY to a lower number. +// to a higher number and DELAY to a lower number. #define REPEAT_TASKMAN 1 #define REPEAT_CLI 1 #define REPEAT_USB 1 @@ -211,6 +211,8 @@ BaseType_t watchdog_service(void); BaseType_t heartbeat_service(void); +BaseType_t wifi_service(void); + /************************ * Service Descriptors *************************/ @@ -241,4 +243,4 @@ extern const service_desc_t service_descriptors[]; extern const size_t service_descriptors_length; -#endif /* SERVICES_H */ \ No newline at end of file +#endif /* SERVICES_H */ diff --git a/services/wifi_service.c b/services/wifi_service.c new file mode 100644 index 0000000..d6a9ce3 --- /dev/null +++ b/services/wifi_service.c @@ -0,0 +1,58 @@ + +#include "hardware_config.h" +#include "services.h" +#include "rtos_utils.h" +#include "FreeRTOS.h" +#include "task.h" + +#include "hw_wifi.h" + +static void prvWifiTask(__unused void *params); + +TaskHandle_t xWifiTask; + +BaseType_t wifi_service() { + cli_uart_puts(timestamp()); + + BaseType_t retval = xTaskCreate( + prvWifiTask, + "WifiTask", + configMINIMAL_STACK_SIZE, + NULL, + 1, + &xWifiTask); + + if (retval == pdPASS) { + cli_uart_puts("Wifi task started.\n"); + } else { + cli_uart_puts("Error starting wifi task.\r\n"); + } + + return retval; +} + +static void prvWifiTask(__unused void *params) { + bool connecting = false; + cli_uart_puts(timestamp()); + cli_uart_puts("initializing wifi...\r\n"); + // todo: wifi country should be configurable + if (hw_wifi_init_with_country(HW_WIFI_COUNTRY_USA)) { + cli_uart_puts(timestamp()); + cli_uart_puts("wifi initialized\r\n"); + hw_wifi_enable_sta_mode(); + cli_uart_puts(timestamp()); + cli_uart_puts("station mode enabled, attempting to join.\r\n"); + if (hw_wifi_connect(WIFI_SSID, WIFI_PASSWORD, HW_WIFI_AUTH_MIXED)) { + cli_uart_puts(timestamp()); + cli_uart_puts("wifi connected: "); + cli_uart_puts(ip4addr_ntoa(hw_wifi_get_addr())); + cli_uart_puts("\n"); + } else { + cli_uart_puts("could not start wifi connection\r\n"); + } + } else { + cli_uart_puts("could not initialize wifi\r\n"); + } + + vTaskDelete(NULL); +}