diff --git a/doc/tutorials/freertos/examples/dfu.rst b/doc/tutorials/freertos/examples/dfu.rst new file mode 100644 index 000000000..1535f3263 --- /dev/null +++ b/doc/tutorials/freertos/examples/dfu.rst @@ -0,0 +1 @@ +.. include:: ../../../../examples/freertos/dfu/README.rst diff --git a/examples/examples.cmake b/examples/examples.cmake index e509e1478..3bf4baa86 100644 --- a/examples/examples.cmake +++ b/examples/examples.cmake @@ -4,6 +4,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL XCORE_XS3A) include(${CMAKE_CURRENT_LIST_DIR}/bare-metal/explorer_board/explorer_board.cmake) ## FreeRTOS examples + include(${CMAKE_CURRENT_LIST_DIR}/freertos/dfu/dfu.cmake) include(${CMAKE_CURRENT_LIST_DIR}/freertos/device_control/device_control.cmake) include(${CMAKE_CURRENT_LIST_DIR}/freertos/dispatcher/dispatcher.cmake) include(${CMAKE_CURRENT_LIST_DIR}/freertos/explorer_board/explorer_board.cmake) diff --git a/examples/freertos/dfu/README.rst b/examples/freertos/dfu/README.rst new file mode 100644 index 000000000..a498269c0 --- /dev/null +++ b/examples/freertos/dfu/README.rst @@ -0,0 +1,249 @@ +############## +DFU +############## + +This example application demonstrates a method to add DFU to a FreeRTOS application on XCORE. + +********************** +Preparing the host +********************** + +This application supports any host host application that is capable of USB DFU Class V1.1. + +The application was verified using dfu-util. + +Installation instructions for respective operating system can be found `here `__ + +If on Linux the user may need to add the USB device to their udev rules. This example defaults to Vendor ID 0xCAFE with Product ID 0x4000. + +If on Windows the user may need to use a tool such as Zadig to install USB drivers. + +********************* +Building the firmware +********************* + +Run the following commands in the xcore_sdk root folder to build the firmware: + +.. tab:: Linux and Mac + + .. code-block:: console + + cmake -B build -DCMAKE_TOOLCHAIN_FILE=xmos_cmake_toolchain/xs3a.cmake + cd build + make example_freertos_dfu_v1 + make example_freertos_dfu_v2 + +.. tab:: Windows + + .. code-block:: console + + cmake -G "NMake Makefiles" -B build -DCMAKE_TOOLCHAIN_FILE=xmos_cmake_toolchain/xs3a.cmake + cd build + nmake example_freertos_dfu_v1 + nmake example_freertos_dfu_v2 + +********************** +Preparing the hardware +********************** + +It is recommended to begin from an erased flash. To erase flash run: + +.. tab:: Linux and Mac + + .. code-block:: console + + make erase_all_example_freertos_dfu_v1 + +.. tab:: Windows + + .. code-block:: console + + nmake erase_all_example_freertos_dfu_v1 + +This target will use `xflash` to erase the flash of the device specified by the provided target XN file. + +After building the firmware and erasing the flash, the factory image must be flashed. From the xcore_sdk build folder run: + +.. tab:: Linux and Mac + + .. code-block:: console + + make flash_app_example_freertos_dfu_v1 + +.. tab:: Windows + + .. code-block:: console + + nmake flash_app_example_freertos_dfu_v1 + +This target will use `xflash` to flash the application as a factory image with a boot partition size specified in dfu.cmake. + +The board may then be power cycled and will boot up the application. + +.. tab:: Linux and Mac + + .. code-block:: console + + make create_upgrade_img_example_freertos_dfu_v2 + +.. tab:: Windows + + .. code-block:: console + + nmake create_upgrade_img_example_freertos_dfu_v2 + +This target will use `xflash` to create an upgrade image for the specified target. + +******************** +Running the firmware +******************** + +After flashed, the factory image will run by default. The user may opt to manually run via xrun to see debug messages. + +From the xcore_sdk build folder run: + +.. tab:: Linux and Mac + + .. code-block:: console + + make run_example_freertos_dfu_v1 + +.. tab:: Windows + + .. code-block:: console + + nmake run_example_freertos_dfu_v1 + +******************** +Upgrading the firmware via DFU +******************** + +Once the application is running, a USB DFU v1.1 tool can be used to perform various actions. This example will demonstrate with dfu-util commands. + +MacOS users may need to sudo the following commands. + +To verify the device is running run: + +.. code-block:: console + + dfu-util -l + +The output of this command will very based on which image is running. +For example_freertos_dfu_v1, the output should contain: + +.. code-block:: console + + Found DFU: [cafe:4000] ver=0100, devnum=53, cfg=1, intf=0, path="3-4.1", alt=2, name="DFU dev DATAPARTITION v1", serial="123456" + Found DFU: [cafe:4000] ver=0100, devnum=53, cfg=1, intf=0, path="3-4.1", alt=1, name="DFU dev UPGRADE v1", serial="123456" + Found DFU: [cafe:4000] ver=0100, devnum=53, cfg=1, intf=0, path="3-4.1", alt=0, name="DFU dev FACTORY v1", serial="123456" + +For example_freertos_dfu_v2, the output should contain: + +.. code-block:: console + + Found DFU: [cafe:4000] ver=0100, devnum=53, cfg=1, intf=0, path="3-4.1", alt=2, name="DFU dev DATAPARTITION v2", serial="123456" + Found DFU: [cafe:4000] ver=0100, devnum=53, cfg=1, intf=0, path="3-4.1", alt=1, name="DFU dev UPGRADE v2", serial="123456" + Found DFU: [cafe:4000] ver=0100, devnum=53, cfg=1, intf=0, path="3-4.1", alt=0, name="DFU dev FACTORY v2", serial="123456" + +The factory image can be read back by running: + +.. code-block:: console + + dfu-util -e -d 4000 -a 0 -U readback_factory_img.bin + +From the xcore_sdk build folder, the upgrade image can be written by running: + +.. code-block:: console + + dfu-util -e -d 4000 -a 1 -D example_freertos_dfu_v2_upgrade.bin + +After updating the upgrade image it may be necessary to unplug the USB device to initiate a host re-enumeration. + +The upgrade image can be read back by running: + +.. code-block:: console + + dfu-util -e -d 4000 -a 1 -U readback_upgrade_img.bin + +The data partition image can be read back by running: + +.. code-block:: console + + dfu-util -e -d 4000 -a 2 -U readback_data_partition_img.bin + +The data partition image can be written by running: + +.. code-block:: console + + dfu-util -e -d 4000 -a 2 -D readback_data_partition_img.bin + +If running the application with the run_example_freertos_dfu_v1 target, information is printed to verify behavior. + +Initially, the debug prints will contain: + +.. code-block:: console + + DFU Image Info + Factory: + Addr:0x1C70 + Size:103108 + Version:0 + Upgrade: + Addr:0x1B000 + Size:0 + Version:0 + Data Partition + Addr:0x100000 + First word at data partition start is: 0xFFFFFFFF + +After writing an upgrade image the debug prints will contain: + +.. code-block:: console + + DFU Image Info + Factory: + Addr:0x1C70 + Size:103108 + Version:0 + Upgrade: + Addr:0x1B000 + Size:103108 + Version:0 + Data Partition + Addr:0x100000 + First word at data partition start is: 0xFFFFFFFF + +The debug prints include the value of the first word at the start of the data partition. Writing a text file containing "XMOS" will result in: + +.. code-block:: console + + DFU Image Info + Factory: + Addr:0x1C70 + Size:103108 + Version:0 + Upgrade: + Addr:0x1B000 + Size:103108 + Version:0 + Data Partition + Addr:0x100000 + First word at data partition start is: 0x534F4D58 + +******************************** +Debugging the firmware with xgdb +******************************** + +From the xcore_sdk build folder run: + +.. tab:: Linux and Mac + + .. code-block:: console + + make debug_example_freertos_dfu_v1 + +.. tab:: Windows + + .. code-block:: console + + nmake debug_example_freertos_dfu_v1 diff --git a/examples/freertos/dfu/XCORE-AI-EXPLORER.xn b/examples/freertos/dfu/XCORE-AI-EXPLORER.xn new file mode 100644 index 000000000..4dde19f84 --- /dev/null +++ b/examples/freertos/dfu/XCORE-AI-EXPLORER.xn @@ -0,0 +1,109 @@ + + + Board + xcore.ai Explorer Kit + + + tileref tile[2] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/freertos/dfu/bsp_config/CMakeLists.txt b/examples/freertos/dfu/bsp_config/CMakeLists.txt new file mode 100644 index 000000000..e7321512e --- /dev/null +++ b/examples/freertos/dfu/bsp_config/CMakeLists.txt @@ -0,0 +1,35 @@ +## Create Explorer Board 2V0 target +add_library(example_freertos_dfu_board_support_config_xcore_ai_explorer_2V0 INTERFACE) +target_sources(example_freertos_dfu_board_support_config_xcore_ai_explorer_2V0 + INTERFACE + XCORE-AI-EXPLORER_2V0/platform/driver_instances.c + XCORE-AI-EXPLORER_2V0/platform/platform_init.c + XCORE-AI-EXPLORER_2V0/platform/platform_start.c +) +target_include_directories(example_freertos_dfu_board_support_config_xcore_ai_explorer_2V0 + INTERFACE + XCORE-AI-EXPLORER_2V0 +) +target_link_libraries(example_freertos_dfu_board_support_config_xcore_ai_explorer_2V0 + INTERFACE + core::general + rtos::freertos + rtos::drivers::general + rtos::drivers::usb + rtos::drivers::dfu_image + rtos::sw_services::usb + +) +target_compile_definitions(example_freertos_dfu_board_support_config_xcore_ai_explorer_2V0 + INTERFACE + XCOREAI_EXPLORER=1 + PLATFORM_SUPPORTS_TILE_0=1 + PLATFORM_SUPPORTS_TILE_1=1 + PLATFORM_SUPPORTS_TILE_2=0 + PLATFORM_SUPPORTS_TILE_3=0 + USB_TILE_NO=0 + USB_TILE=tile[USB_TILE_NO] +) + +## Create an alias +add_library(example::freertos::dfu::bsp_config::xcore_ai_explorer ALIAS example_freertos_dfu_board_support_config_xcore_ai_explorer_2V0) diff --git a/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/driver_instances.c b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/driver_instances.c new file mode 100644 index 000000000..d5344d6e2 --- /dev/null +++ b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/driver_instances.c @@ -0,0 +1,34 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +#include "platform/driver_instances.h" + +static rtos_intertile_t intertile_ctx_s; +rtos_intertile_t *intertile_ctx = &intertile_ctx_s; + +static rtos_qspi_flash_t qspi_flash_ctx_s; +rtos_qspi_flash_t *qspi_flash_ctx = &qspi_flash_ctx_s; + +static rtos_spi_master_t spi_master_ctx_s; +rtos_spi_master_t *spi_master_ctx = &spi_master_ctx_s; + +static rtos_spi_master_device_t wifi_device_ctx_s; +rtos_spi_master_device_t *wifi_device_ctx = &wifi_device_ctx_s; + +static rtos_gpio_t gpio_ctx_t0_s; +rtos_gpio_t *gpio_ctx_t0 = &gpio_ctx_t0_s; + +static rtos_gpio_t gpio_ctx_t1_s; +rtos_gpio_t *gpio_ctx_t1 = &gpio_ctx_t1_s; + +static rtos_i2c_master_t i2c_master_ctx_s; +rtos_i2c_master_t *i2c_master_ctx = &i2c_master_ctx_s; + +static rtos_uart_tx_t uart_tx_ctx_s; +rtos_uart_tx_t *uart_tx_ctx = &uart_tx_ctx_s; + +static rtos_uart_rx_t uart_rx_ctx_s; +rtos_uart_rx_t *uart_rx_ctx = &uart_rx_ctx_s; + +static rtos_dfu_image_t dfu_image_ctx_s; +rtos_dfu_image_t *dfu_image_ctx = &dfu_image_ctx_s; diff --git a/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/driver_instances.h b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/driver_instances.h new file mode 100644 index 000000000..ee4a4d65a --- /dev/null +++ b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/driver_instances.h @@ -0,0 +1,46 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +#ifndef DRIVER_INSTANCES_H_ +#define DRIVER_INSTANCES_H_ + +#include "rtos_intertile.h" +#include "rtos_i2c_master.h" +#include "rtos_spi_master.h" +#include "rtos_qspi_flash.h" +#include "rtos_dfu_image.h" +#include "rtos_gpio.h" +#include "rtos_uart_tx.h" +#include "rtos_uart_rx.h" +#include "usb_support.h" + +#define FLASH_TILE_NO 0 +#define I2C_TILE_NO 0 +#define UART_TILE_NO 1 + +/** TILE 0 Clock Blocks */ +#define FLASH_CLKBLK XS1_CLKBLK_1 +// #define UNUSED_CLKBLK XS1_CLKBLK_2 +#define SPI_CLKBLK XS1_CLKBLK_3 +#define XUD_CLKBLK_1 XS1_CLKBLK_4 /* Reserved for lib_xud */ +#define XUD_CLKBLK_2 XS1_CLKBLK_5 /* Reserved for lib_xud */ + +/** TILE 1 Clock Blocks */ +// #define UNUSED_CLKBLK XS1_CLKBLK_1 +// #define UNUSED_CLKBLK XS1_CLKBLK_2 +// #define UNUSED_CLKBLK XS1_CLKBLK_3 +// #define UNUSED_CLKBLK XS1_CLKBLK_4 +// #define UNUSED_CLKBLK XS1_CLKBLK_5 + +extern rtos_intertile_t *intertile_ctx; +extern rtos_qspi_flash_t *qspi_flash_ctx; +extern rtos_spi_master_t *spi_master_ctx; +extern rtos_spi_master_device_t *wifi_device_ctx; +extern rtos_gpio_t *gpio_ctx_t0; +extern rtos_gpio_t *gpio_ctx_t1; +extern rtos_i2c_master_t *i2c_master_ctx; +extern rtos_uart_tx_t *uart_tx_ctx; +extern rtos_uart_rx_t *uart_rx_ctx; +extern rtos_dfu_image_t *dfu_image_ctx; + +#endif /* DRIVER_INSTANCES_H_ */ diff --git a/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_conf.h b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_conf.h new file mode 100644 index 000000000..80d2d56aa --- /dev/null +++ b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_conf.h @@ -0,0 +1,135 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +#ifndef PLATFORM_CONF_H_ +#define PLATFORM_CONF_H_ + +/* + * This file contains defaults to build a basic project targetting the + * XCORE-AI-EXPLORER board. Users may create their own app_conf.h to override + * any default settings. + * + * For a different soft tapeout design, it is recommended to create an entirely + * different board support package. + */ + +#if __has_include("app_conf.h") +#include "app_conf.h" +#endif /* __has_include("app_conf.h") */ + +/*****************************************/ +/* Intertile Communication Configuration */ +/*****************************************/ +#ifndef appconfI2C_MASTER_RPC_PORT +#define appconfI2C_MASTER_RPC_PORT 10 +#endif /* appconfI2C_MASTER_RPC_PORT */ + +#ifndef appconfI2C_MASTER_RPC_PRIORITY +#define appconfI2C_MASTER_RPC_PRIORITY (configMAX_PRIORITIES/2) +#endif /* appconfI2C_MASTER_RPC_PRIORITY */ + +#ifndef appconfGPIO_T0_RPC_PORT +#define appconfGPIO_T0_RPC_PORT 11 +#endif /* appconfGPIO_T0_RPC_PORT */ + +#ifndef appconfGPIO_T1_RPC_PORT +#define appconfGPIO_T1_RPC_PORT 12 +#endif /* appconfGPIO_T1_RPC_PORT */ + +#ifndef appconfGPIO_RPC_PRIORITY +#define appconfGPIO_RPC_PRIORITY (configMAX_PRIORITIES/2) +#endif /* appconfGPIO_RPC_PRIORITY */ + +/*****************************************/ +/* I/O and interrupt cores for Tile 0 */ +/*****************************************/ +#ifndef appconfI2C_IO_CORE +#define appconfI2C_IO_CORE 2 /* Must be kept off core 0 with the RTOS tick ISR */ +#endif /* appconfI2C_IO_CORE */ + +#ifndef appconfI2C_INTERRUPT_CORE +#define appconfI2C_INTERRUPT_CORE 0 /* Must be kept off I/O cores. */ +#endif /* appconfI2C_INTERRUPT_CORE */ + +/*****************************************/ +/* I/O and interrupt cores for Tile 1 */ +/*****************************************/ +#ifndef appconfUART_RX_IO_CORE +#define appconfUART_RX_IO_CORE 3 /* Must be kept off core 0 with the RTOS tick ISR */ +#endif /* appconfUART_RX_IO_CORE */ + +#ifndef appconfUART_RX_INTERRUPT_CORE +#define appconfUART_RX_INTERRUPT_CORE 4 /* Must be kept off I/O cores. Best kept off core 0 with the tick ISR. */ +#endif /* appconfUART_RX_INTERRUPT_CORE */ + +/*****************************************/ +/* I/O Settings */ +/*****************************************/ +#ifndef appconfUART_BAUD_RATE +#define appconfUART_BAUD_RATE 115200 +#endif /* appconfUART_BAUD_RATE */ + +/*****************************************/ +/* I/O Task Priorities */ +/*****************************************/ +#ifndef appconfSPI_MASTER_TASK_PRIORITY +#define appconfSPI_MASTER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#endif /* appconfSPI_MASTER_TASK_PRIORITY */ + +#ifndef appconfQSPI_FLASH_TASK_PRIORITY +#define appconfQSPI_FLASH_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#endif /* appconfQSPI_FLASH_TASK_PRIORITY */ + +/*****************************************/ +/* DFU Settings */ +/*****************************************/ +#define FL_QUADDEVICE_AT25FF321A \ +{ \ + 0, /* UNKNOWN */ \ + 256, /* page size */ \ + 16384, /* num pages */ \ + 3, /* address size */ \ + 3, /* log2 clock divider */ \ + 0x9F, /* QSPI_RDID */ \ + 0, /* id dummy bytes */ \ + 3, /* id size in bytes */ \ + 0x1F4708, /* device id */ \ + 0x20, /* QSPI_SE */ \ + 4096, /* Sector erase is always 4KB */ \ + 0x06, /* QSPI_WREN */ \ + 0x04, /* QSPI_WRDI */ \ + PROT_TYPE_SR, /* Protection via SR */ \ + {{0x3C,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \ + 0x02, /* QSPI_PP */ \ + 0xEB, /* QSPI_READ_FAST */ \ + 1, /* 1 read dummy byte */ \ + SECTOR_LAYOUT_REGULAR, /* mad sectors */ \ + {4096,{0,{0}}}, /* regular sector sizes */ \ + 0x05, /* QSPI_RDSR */ \ + 0x01, /* QSPI_WRSR */ \ + 0x01, /* QSPI_WIP_BIT_MASK */ \ +} + +#ifndef BOARD_QSPI_SPEC +/* Set up a default SPI spec if the app has not provided + * one explicitly. + * Note: The version checks only work in XTC Tools >15.3.0 + * By default FL_QUADDEVICE_AT25FF321A is used + */ +#ifdef __XMOS_XTC_VERSION_MAJOR__ +#if (__XMOS_XTC_VERSION_MAJOR__ == 15) \ + && (__XMOS_XTC_VERSION_MINOR__ >= 2) \ + && (__XMOS_XTC_VERSION_PATCH__ >= 0) +/* In XTC >15.2.0 some SFDP support enables a generic + * default spec + */ +#define BOARD_QSPI_SPEC FL_QUADDEVICE_DEFAULT +#else +#define BOARD_QSPI_SPEC FL_QUADDEVICE_AT25FF321A +#endif +#else +#define BOARD_QSPI_SPEC FL_QUADDEVICE_AT25FF321A +#endif /* __XMOS_XTC_VERSION_MAJOR__ */ +#endif /* BOARD_QSPI_SPEC */ + +#endif /* PLATFORM_CONF_H_ */ diff --git a/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_init.c b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_init.c new file mode 100644 index 000000000..b9e722960 --- /dev/null +++ b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_init.c @@ -0,0 +1,213 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +#include +#include + +#include "platform_conf.h" +#include "platform/driver_instances.h" +#include +#include + +static void flash_init(void) +{ +#if ON_TILE(FLASH_TILE_NO) + fl_QuadDeviceSpec qspi_spec = BOARD_QSPI_SPEC; + fl_QSPIPorts qspi_ports = { + .qspiCS = PORT_SQI_CS, + .qspiSCLK = PORT_SQI_SCLK, + .qspiSIO = PORT_SQI_SIO, + .qspiClkblk = FLASH_CLKBLK, + }; + + rtos_dfu_image_init( + dfu_image_ctx, + &qspi_ports, + &qspi_spec, + 1); + + qspi_flash_ctx->ctx.sfdp_skip = true; + qspi_flash_ctx->ctx.sfdp_supported = false; + qspi_flash_ctx->ctx.page_size_bytes = 256; + qspi_flash_ctx->ctx.page_count = 16384; + qspi_flash_ctx->ctx.flash_size_kbytes = 4096; + qspi_flash_ctx->ctx.address_bytes = 3; + qspi_flash_ctx->ctx.erase_info[0].size_log2 = 12; + qspi_flash_ctx->ctx.erase_info[0].cmd = 0xEEFEEEEE; + qspi_flash_ctx->ctx.erase_info[1].size_log2 = 15; + qspi_flash_ctx->ctx.erase_info[1].cmd = 0xEFEFEEFE; + qspi_flash_ctx->ctx.erase_info[2].size_log2 = 16; + qspi_flash_ctx->ctx.erase_info[2].cmd = 0xFFEFFEEE; + qspi_flash_ctx->ctx.erase_info[3].size_log2 = 0; + qspi_flash_ctx->ctx.erase_info[3].cmd = 0; + qspi_flash_ctx->ctx.busy_poll_cmd = 0xEEEEEFEF; + qspi_flash_ctx->ctx.busy_poll_bit = 0; + qspi_flash_ctx->ctx.busy_poll_ready_value = 0; + qspi_flash_ctx->ctx.qe_reg = 2; + qspi_flash_ctx->ctx.qe_bit = 1; + qspi_flash_ctx->ctx.sr2_read_cmd = 0xEEFFEFEF; + qspi_flash_ctx->ctx.sr2_write_cmd = 0xEEEEEEEE; + + rtos_qspi_flash_init( + qspi_flash_ctx, + FLASH_CLKBLK, + PORT_SQI_CS, + PORT_SQI_SCLK, + PORT_SQI_SIO, + + /** Derive QSPI clock from the 600 MHz xcore clock **/ + qspi_io_source_clock_xcore, + + /** Full speed clock configuration **/ + 5, // 600 MHz / (2*5) -> 60 MHz, + 1, + qspi_io_sample_edge_rising, + 0, + + /** SPI read clock configuration **/ + 12, // 600 MHz / (2*12) -> 25 MHz + 0, + qspi_io_sample_edge_falling, + 0, + + qspi_flash_page_program_1_1_4); +#endif +} + +static void gpio_init(void) +{ + static rtos_driver_rpc_t gpio_rpc_config_t0; + static rtos_driver_rpc_t gpio_rpc_config_t1; + rtos_intertile_t *client_intertile_ctx[1] = {intertile_ctx}; + +#if ON_TILE(0) + rtos_gpio_init(gpio_ctx_t0); + + rtos_gpio_rpc_host_init( + gpio_ctx_t0, + &gpio_rpc_config_t0, + client_intertile_ctx, + 1); + + rtos_gpio_rpc_client_init( + gpio_ctx_t1, + &gpio_rpc_config_t1, + intertile_ctx); +#endif + +#if ON_TILE(1) + rtos_gpio_init(gpio_ctx_t1); + + rtos_gpio_rpc_client_init( + gpio_ctx_t0, + &gpio_rpc_config_t0, + intertile_ctx); + + rtos_gpio_rpc_host_init( + gpio_ctx_t1, + &gpio_rpc_config_t1, + client_intertile_ctx, + 1); +#endif +} + +static void i2c_init(void) +{ + static rtos_driver_rpc_t i2c_rpc_config; + +#if ON_TILE(I2C_TILE_NO) + rtos_intertile_t *client_intertile_ctx[1] = {intertile_ctx}; + rtos_i2c_master_init( + i2c_master_ctx, + PORT_I2C_SCL, 0, 0, + PORT_I2C_SDA, 0, 0, + 0, + 100); + + rtos_i2c_master_rpc_host_init( + i2c_master_ctx, + &i2c_rpc_config, + client_intertile_ctx, + 1); +#else + rtos_i2c_master_rpc_client_init( + i2c_master_ctx, + &i2c_rpc_config, + intertile_ctx); +#endif +} + +static void spi_init(void) +{ +#if ON_TILE(0) + rtos_spi_master_init( + spi_master_ctx, + SPI_CLKBLK, + WIFI_CS_N, + WIFI_CLK, + WIFI_MOSI, + WIFI_MISO); + + rtos_spi_master_device_init( + wifi_device_ctx, + spi_master_ctx, + 1, /* WiFi CS pin is on bit 1 of the CS port */ + SPI_MODE_0, + spi_master_source_clock_ref, + 0, /* 50 MHz */ + spi_master_sample_delay_2, /* what should this be? 2? 3? 4? */ + 0, /* should this be > 0 if the above is 3-4 ? */ + 1, + 0, + 0); +#endif +} + + +static void uart_init(void) +{ +#if ON_TILE(UART_TILE_NO) + hwtimer_t tmr_rx = hwtimer_alloc(); + + rtos_uart_rx_init( + uart_rx_ctx, + (1 << appconfUART_RX_IO_CORE), + XS1_PORT_1M, //X1D36 + appconfUART_BAUD_RATE, + 8, + UART_PARITY_NONE, + 1, + tmr_rx); + + + hwtimer_t tmr_tx = hwtimer_alloc(); + + rtos_uart_tx_init( + uart_tx_ctx, + XS1_PORT_1P, //X1D39 + appconfUART_BAUD_RATE, + 8, + UART_PARITY_NONE, + 1, + tmr_tx); +#endif +} + +void usb_init(void) +{ +#if ON_TILE(USB_TILE_NO) + usb_manager_init(); +#endif +} + +void platform_init(chanend_t other_tile_c) +{ + rtos_intertile_init(intertile_ctx, other_tile_c); + + flash_init(); + gpio_init(); + spi_init(); + i2c_init(); + uart_init(); + usb_init(); +} diff --git a/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_init.h b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_init.h new file mode 100644 index 000000000..bae19eb7a --- /dev/null +++ b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_init.h @@ -0,0 +1,12 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +#ifndef PLATFORM_INIT_H_ +#define PLATFORM_INIT_H_ + +#include + +void platform_init(chanend_t other_tile_c); +void platform_start(void); + +#endif /* PLATFORM_INIT_H_ */ diff --git a/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_start.c b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_start.c new file mode 100644 index 000000000..caa1e6613 --- /dev/null +++ b/examples/freertos/dfu/bsp_config/XCORE-AI-EXPLORER_2V0/platform/platform_start.c @@ -0,0 +1,60 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +#include + +#include "platform_conf.h" +#include "platform/driver_instances.h" + +static void gpio_start(void) +{ + rtos_gpio_rpc_config(gpio_ctx_t0, appconfGPIO_T0_RPC_PORT, appconfGPIO_RPC_PRIORITY); + rtos_gpio_rpc_config(gpio_ctx_t1, appconfGPIO_T1_RPC_PORT, appconfGPIO_RPC_PRIORITY); + +#if ON_TILE(0) + rtos_gpio_start(gpio_ctx_t0); +#endif +#if ON_TILE(1) + rtos_gpio_start(gpio_ctx_t1); +#endif +} + +static void spi_start(void) +{ +#if ON_TILE(0) + rtos_spi_master_start(spi_master_ctx, appconfSPI_MASTER_TASK_PRIORITY); +#endif +} + +static void i2c_start(void) +{ + rtos_i2c_master_rpc_config(i2c_master_ctx, appconfI2C_MASTER_RPC_PORT, appconfI2C_MASTER_RPC_PRIORITY); +#if ON_TILE(I2C_TILE_NO) + rtos_i2c_master_start(i2c_master_ctx); +#endif +} + +static void flash_start(void) +{ +#if ON_TILE(0) + rtos_qspi_flash_start(qspi_flash_ctx, appconfQSPI_FLASH_TASK_PRIORITY); +#endif +} + +static void usb_start(void) +{ +#if ON_TILE(USB_TILE_NO) + usb_manager_start(appconfUSB_MANAGER_TASK_PRIORITY); +#endif +} + +void platform_start(void) +{ + rtos_intertile_start(intertile_ctx); + + gpio_start(); + spi_start(); + flash_start(); + i2c_start(); + usb_start(); +} diff --git a/examples/freertos/dfu/dfu.cmake b/examples/freertos/dfu/dfu.cmake new file mode 100644 index 000000000..d63611f4b --- /dev/null +++ b/examples/freertos/dfu/dfu.cmake @@ -0,0 +1,119 @@ +#********************** +# Gather Sources +#********************** +file(GLOB_RECURSE APP_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/*.c) +set(APP_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/src) + +#********************** +# Import example specific bsp_config +#********************** +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/bsp_config) + +#********************** +# Flags +#********************** +set(APP_COMPILER_FLAGS + -Os + -g + -report + -fxscope + -mcmodel=large + -Wno-xcore-fptrgroup + ${CMAKE_CURRENT_LIST_DIR}/src/config.xscope + ${CMAKE_CURRENT_LIST_DIR}/XCORE-AI-EXPLORER.xn +) +set(APP_COMPILE_DEFINITIONS + DEBUG_PRINT_ENABLE=1 + PLATFORM_USES_TILE_0=1 + PLATFORM_USES_TILE_1=1 + + XUD_CORE_CLOCK=600 +) + +set(APP_LINK_OPTIONS + -fxscope + -report + ${CMAKE_CURRENT_LIST_DIR}/XCORE-AI-EXPLORER.xn + ${CMAKE_CURRENT_LIST_DIR}/src/config.xscope +) + +set(APP_LINK_LIBRARIES + example::freertos::dfu::bsp_config::xcore_ai_explorer +) + +#********************** +# Tile Targets +#********************** +set(TARGET_NAME tile0_example_freertos_dfu_v1) +add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) +target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES}) +target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES}) +target_compile_definitions(${TARGET_NAME} PUBLIC ${APP_COMPILE_DEFINITIONS} THIS_XCORE_TILE=0 VERSION=1) +target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) +target_link_libraries(${TARGET_NAME} PUBLIC ${APP_LINK_LIBRARIES}) +target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) +unset(TARGET_NAME) + +set(TARGET_NAME tile1_example_freertos_dfu_v1) +add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) +target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES}) +target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES}) +target_compile_definitions(${TARGET_NAME} PUBLIC ${APP_COMPILE_DEFINITIONS} THIS_XCORE_TILE=1 VERSION=1) +target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) +target_link_libraries(${TARGET_NAME} PUBLIC ${APP_LINK_LIBRARIES}) +target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) +unset(TARGET_NAME) + +set(TARGET_NAME tile0_example_freertos_dfu_v2) +add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) +target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES}) +target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES}) +target_compile_definitions(${TARGET_NAME} PUBLIC ${APP_COMPILE_DEFINITIONS} THIS_XCORE_TILE=0 VERSION=2) +target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) +target_link_libraries(${TARGET_NAME} PUBLIC ${APP_LINK_LIBRARIES}) +target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) +unset(TARGET_NAME) + +set(TARGET_NAME tile1_example_freertos_dfu_v2) +add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) +target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES}) +target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES}) +target_compile_definitions(${TARGET_NAME} PUBLIC ${APP_COMPILE_DEFINITIONS} THIS_XCORE_TILE=1 VERSION=2) +target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) +target_link_libraries(${TARGET_NAME} PUBLIC ${APP_LINK_LIBRARIES}) +target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) +unset(TARGET_NAME) + +#********************** +# Merge binaries +#********************** +merge_binaries(example_freertos_dfu_v1 tile0_example_freertos_dfu_v1 tile1_example_freertos_dfu_v1 1) +merge_binaries(example_freertos_dfu_v2 tile0_example_freertos_dfu_v2 tile1_example_freertos_dfu_v2 1) + +#********************** +# Create run and debug targets +#********************** +create_run_target(example_freertos_dfu_v1) +create_debug_target(example_freertos_dfu_v1) +create_flash_app_target( + #[[ Target ]] example_freertos_dfu_v1 + #[[ Boot Partition Size ]] 0x100000 + #[[ Data Parition Contents ]] + #[[ Dependencies ]] +) +query_tools_version() +create_upgrade_img_target(example_freertos_dfu_v1 ${XTC_VERSION_MAJOR} ${XTC_VERSION_MINOR}) +create_install_target(example_freertos_dfu_v1) +create_erase_all_target(example_freertos_dfu_v1 ${CMAKE_CURRENT_LIST_DIR}/XCORE-AI-EXPLORER.xn) + +create_run_target(example_freertos_dfu_v2) +create_debug_target(example_freertos_dfu_v2) +create_flash_app_target( + #[[ Target ]] example_freertos_dfu_v2 + #[[ Boot Partition Size ]] 0x100000 + #[[ Data Parition Contents ]] + #[[ Dependencies ]] +) +create_upgrade_img_target(example_freertos_dfu_v2 ${XTC_VERSION_MAJOR} ${XTC_VERSION_MINOR}) +create_install_target(example_freertos_dfu_v2) +create_erase_all_target(example_freertos_dfu_v2 ${CMAKE_CURRENT_LIST_DIR}/XCORE-AI-EXPLORER.xn) diff --git a/examples/freertos/dfu/src/FreeRTOSConfig.h b/examples/freertos/dfu/src/FreeRTOSConfig.h new file mode 100644 index 000000000..e45891dac --- /dev/null +++ b/examples/freertos/dfu/src/FreeRTOSConfig.h @@ -0,0 +1,113 @@ +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/* Here is a good place to include header files that are required across +your application. */ +#include "platform.h" + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configUSE_TICKLESS_IDLE 0 +#define configCPU_CLOCK_HZ 100000000 +#define configNUM_CORES 5 +#define configTICK_RATE_HZ 1000 +#define configMAX_PRIORITIES 32 +#define configRUN_MULTIPLE_PRIORITIES 1 +#define configUSE_TASK_PREEMPTION_DISABLE 1 +#define configUSE_CORE_AFFINITY 1 +#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 1256 +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 2 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */ +#define configQUEUE_REGISTRY_SIZE 10 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TIME_SLICING 1 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 /* Required for FreeRTOS_TCP_WIN.c TODO: active closed bug, may have been fixed upstream */ +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 +#define configSTACK_DEPTH_TYPE uint32_t +#define configMESSAGE_BUFFER_LENGTH_TYPE size_t + + +/* Memory allocation related definitions. */ +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configTOTAL_HEAP_SIZE 256*1024 +#define configAPPLICATION_ALLOCATED_HEAP 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_MINIMAL_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 0 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 +#define configUSE_CORE_INIT_HOOK 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 0 +#define configUSE_STATS_FORMATTING_FUNCTIONS 2 /* Setting to 2 does not include in tasks.c */ + +/* Co-routine related definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 1 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE << 2 ) + +/* Define to trap errors during development. */ +#define configASSERT(x) xassert(x) + +/* Define to enable debug_printf() */ +#define configENABLE_DEBUG_PRINTF 1 + +/* Define to map sprintf and snprintf to the + * lite versions in lib_rtos_support */ + #include +#define configUSE_DEBUG_SPRINTF 1 + +/* Define to enable debug prints from tasks.c */ +#if ON_TILE(0) +#define configTASKS_DEBUG 0 +#endif +#if ON_TILE(1) +#define configTASKS_DEBUG 0 +#endif + +/* FreeRTOS MPU specific definitions. */ +#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_xResumeFromISR 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xEventGroupSetBitFromISR 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xTaskResumeFromISR 1 +#define INCLUDE_xQueueGetMutexHolder 1 + +/* A header file that defines trace macro can be included here. */ +// #include "xcore_trace.h" + +#endif /* FREERTOS_CONFIG_H */ diff --git a/examples/freertos/dfu/src/app_conf.h b/examples/freertos/dfu/src/app_conf.h new file mode 100644 index 000000000..9d3762515 --- /dev/null +++ b/examples/freertos/dfu/src/app_conf.h @@ -0,0 +1,38 @@ +// Copyright 2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +#ifndef APP_CONF_H_ +#define APP_CONF_H_ + +/* Intertile Communication Configuration */ +#define appconfI2C_MASTER_RPC_PORT 10 +#define appconfI2C_MASTER_RPC_PRIORITY (configMAX_PRIORITIES/2) + +#define appconfGPIO_T0_RPC_PORT 11 +#define appconfGPIO_T1_RPC_PORT 12 +#define appconfGPIO_RPC_PRIORITY (configMAX_PRIORITIES/2) + +/* I/O and interrupt cores for Tile 0 */ +#define appconfI2C_IO_CORE 4 /* Must be kept off core 0 with the RTOS tick ISR */ +#define appconfI2C_INTERRUPT_CORE 0 /* Must be kept off I/O cores. */ +#define appconfXUD_IO_CORE 1 /* Must be kept off core 0 with the RTOS tick ISR */ +#define appconfUSB_INTERRUPT_CORE 3 /* Must be kept off I/O cores. Best kept off core 0 with the tick ISR. */ +#define appconfUSB_SOF_INTERRUPT_CORE 4 /* Must be kept off I/O cores. Best kept off cores with other ISRs. */ +#define appconfSPI_IO_CORE 4 /* Must be kept off core 0 with the RTOS tick ISR */ +#define appconfSPI_INTERRUPT_CORE 0 /* Must be kept off I/O cores. */ + +/* I/O and interrupt cores for Tile 1 */ +#define appconfUART_RX_IO_CORE 3 /* Must be kept off core 0 with the RTOS tick ISR */ +#define appconfUART_RX_INTERRUPT_CORE 4 /* Must be kept off I/O cores. Best kept off core 0 with the tick ISR. */ + +/* UART Configuration */ +#define appconfUART_BAUD_RATE 806400 + +/* Task Priorities */ +#define appconfSTARTUP_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define appconfSPI_MASTER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define appconfQSPI_FLASH_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define appconfUART_RX_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define appconfUSB_MANAGER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) + +#endif /* APP_CONF_H_ */ diff --git a/examples/freertos/dfu/src/config.xscope b/examples/freertos/dfu/src/config.xscope new file mode 100644 index 000000000..bb71bfe23 --- /dev/null +++ b/examples/freertos/dfu/src/config.xscope @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/freertos/dfu/src/main.c b/examples/freertos/dfu/src/main.c new file mode 100644 index 000000000..e440adfe3 --- /dev/null +++ b/examples/freertos/dfu/src/main.c @@ -0,0 +1,118 @@ +// Copyright 2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +/* System headers */ +#include +#include + +/* FreeRTOS headers */ +#include "FreeRTOS.h" +#include "queue.h" + +/* Library headers */ + +/* App headers */ +#include "app_conf.h" +#include "usb_support.h" +#include "xcore/channel_streaming.h" +#include "platform/platform_init.h" +#include "platform/driver_instances.h" + +void vApplicationMallocFailedHook( void ) +{ + rtos_printf("Malloc Failed on tile %d!\n", THIS_XCORE_TILE); + for(;;); +} + +void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName) { + rtos_printf("\nStack Overflow!!! %d %s!\n", THIS_XCORE_TILE, pcTaskName); + configASSERT(0); +} + +void blinky_task(void *arg) { + uint32_t gpio_port = rtos_gpio_port(PORT_LEDS); + uint32_t led_val = 0; + + rtos_gpio_port_enable(gpio_ctx_t0, gpio_port); + + for (;;) { + rtos_gpio_port_out(gpio_ctx_t0, gpio_port, led_val); + led_val ^= VERSION; + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +void startup_task(void *arg) +{ + rtos_printf("Startup task running from tile %d on core %d\n", THIS_XCORE_TILE, portGET_CORE_ID()); + + platform_start(); + +#if ON_TILE(0) + rtos_dfu_image_print_debug(dfu_image_ctx); + + uint32_t data; + rtos_qspi_flash_read( + qspi_flash_ctx, + (uint8_t*)&data, + rtos_dfu_image_get_data_partition_addr(dfu_image_ctx), + sizeof(int32_t)); + rtos_printf("First word at data partition start is: 0x%x\n", data); +#endif + + for (;;) { + rtos_printf("Tile[%d]:\n\tMinimum heap free: %d\n\tCurrent heap free: %d\n", THIS_XCORE_TILE, xPortGetMinimumEverFreeHeapSize(), xPortGetFreeHeapSize()); + vTaskDelay(pdMS_TO_TICKS(5000)); + } +} + +void vApplicationMinimalIdleHook(void) +{ + rtos_printf("idle hook on tile %d core %d\n", THIS_XCORE_TILE, rtos_core_id_get()); + asm volatile("waiteu"); +} + +void tile_common_init(chanend_t c) +{ + platform_init(c); + chanend_free(c); + + xTaskCreate((TaskFunction_t) startup_task, + "startup_task", + RTOS_THREAD_STACK_SIZE(startup_task), + NULL, + appconfSTARTUP_TASK_PRIORITY, + NULL); + +#if ON_TILE(0) + xTaskCreate((TaskFunction_t) blinky_task, + "blinky_task", + RTOS_THREAD_STACK_SIZE(blinky_task), + NULL, + appconfSTARTUP_TASK_PRIORITY / 2, + NULL); +#endif + + rtos_printf("start scheduler on tile %d\n", THIS_XCORE_TILE); + vTaskStartScheduler(); +} + +#if ON_TILE(0) +void main_tile0(chanend_t c0, chanend_t c1, chanend_t c2, chanend_t c3) { + (void)c0; + (void)c2; + (void)c3; + + tile_common_init(c1); +} +#endif + +#if ON_TILE(1) +void main_tile1(chanend_t c0, chanend_t c1, chanend_t c2, chanend_t c3) { + (void)c1; + (void)c2; + (void)c3; + + tile_common_init(c0); +} +#endif diff --git a/examples/freertos/dfu/src/tusb_config.h b/examples/freertos/dfu/src/tusb_config.h new file mode 100644 index 000000000..21fe4c315 --- /dev/null +++ b/examples/freertos/dfu/src/tusb_config.h @@ -0,0 +1,50 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "app_conf.h" + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#define CFG_TUSB_OS OPT_OS_CUSTOM + +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(8))) + +#define CFG_TUSB_DEBUG_PRINTF rtos_printf + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#define CFG_TUD_EP_MAX 12 +#define CFG_TUD_TASK_QUEUE_SZ 8 +#define CFG_TUD_ENDPOINT0_SIZE 64 + +#define CFG_TUD_XCORE_INTERRUPT_CORE appconfUSB_INTERRUPT_CORE +#define CFG_TUD_XCORE_SOF_INTERRUPT_CORE appconfUSB_SOF_INTERRUPT_CORE +#define CFG_TUD_XCORE_IO_CORE_MASK (1 << appconfXUD_IO_CORE) + +//------------- CLASS -------------// +#define CFG_TUD_DFU 1 + +// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR +#define CFG_TUD_DFU_XFER_BUFSIZE 4096 + +#ifdef __cplusplus + } +#endif + +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/freertos/dfu/src/usb/app_dfu.c b/examples/freertos/dfu/src/usb/app_dfu.c new file mode 100644 index 000000000..316f72c8c --- /dev/null +++ b/examples/freertos/dfu/src/usb/app_dfu.c @@ -0,0 +1,264 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include +#include +#include +#include + +#include "FreeRTOS.h" +#include "timers.h" +#include "platform/driver_instances.h" +#include "tusb.h" + +/* + * After device is enumerated in dfu mode run the following commands + * + * To transfer firmware from host to device + * + * $ dfu-util -d cafe -a 0 -D [filename] + * $ dfu-util -d cafe -a 1 -D [filename] + * + * To transfer firmware from device to host: + * + * $ dfu-util -d cafe -a 0 -U [filename] + * $ dfu-util -d cafe -a 1 -U [filename] + * + */ + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ +static void reboot(void); + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + rtos_printf("mounted\n"); +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + rtos_printf("unmounted\n"); +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + rtos_printf("suspended\n"); +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + rtos_printf("resumed\n"); +} + +//--------------------------------------------------------------------+ +// DFU callbacks +// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. +//--------------------------------------------------------------------+ + +static size_t total_len = 0; +static size_t bytes_avail = 0; +static uint32_t dn_base_addr = 0; + +// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) +// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. +// During this period, USB host won't try to communicate with us. +uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) +{ + if ( state == DFU_DNBUSY ) { + return 10; // 10 ms + } else if (state == DFU_MANIFEST) { + // since we don't buffer entire image and do any flashing in manifest stage + return 0; + } + + return 0; +} + +// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests +// This callback could be returned before flashing op is complete (async). +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_download_cb(uint8_t alt, uint16_t block_num, uint8_t const* data, uint16_t length) +{ + rtos_printf("Received Alt %d BlockNum %d of length %d\n", alt, block_num, length); + + unsigned data_partition_base_addr = rtos_dfu_image_get_data_partition_addr(dfu_image_ctx); + switch(alt) { + default: + case 0: + tud_dfu_finish_flashing(DFU_STATUS_ERR_WRITE); + break; + case 1: + if (dn_base_addr == 0) { + total_len = 0; + dn_base_addr = rtos_dfu_image_get_upgrade_addr(dfu_image_ctx); + bytes_avail = data_partition_base_addr - dn_base_addr; + } + /* fallthrough */ + case 2: + if (dn_base_addr == 0) { + total_len = 0; + dn_base_addr = data_partition_base_addr; + bytes_avail = rtos_qspi_flash_size_get(qspi_flash_ctx) - dn_base_addr; + } + rtos_printf("Using addr 0x%x\nsize %u\n", dn_base_addr, bytes_avail); + if(length > 0) { + unsigned cur_addr = dn_base_addr + (block_num * CFG_TUD_DFU_XFER_BUFSIZE); + if((bytes_avail - total_len) >= length) { + rtos_printf("write %d at 0x%x\n", length, cur_addr); + + size_t sector_size = rtos_qspi_flash_sector_size_get(qspi_flash_ctx); + xassert(CFG_TUD_DFU_XFER_BUFSIZE == sector_size); + + uint8_t *tmp_buf = rtos_osal_malloc( sizeof(uint8_t) * sector_size); + rtos_qspi_flash_lock(qspi_flash_ctx); + { + rtos_qspi_flash_read( + qspi_flash_ctx, + tmp_buf, + cur_addr, + sector_size); + memcpy(tmp_buf, data, length); + rtos_qspi_flash_erase( + qspi_flash_ctx, + cur_addr, + sector_size); + rtos_qspi_flash_write( + qspi_flash_ctx, + (uint8_t *) tmp_buf, + cur_addr, + sector_size); + } + rtos_qspi_flash_unlock(qspi_flash_ctx); + rtos_osal_free(tmp_buf); + total_len += length; + } else { + rtos_printf("Insufficient space\n"); + tud_dfu_finish_flashing(DFU_STATUS_ERR_ADDRESS); + } + } + + tud_dfu_finish_flashing(DFU_STATUS_OK); + break; + } +} + +// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) +// Application can do checksum, or actual flashing if buffered entire image previously. +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_manifest_cb(uint8_t alt) +{ + (void) alt; + rtos_printf("Download completed, enter manifestation\n"); + + /* Perform a read to ensure all writes have been flushed */ + uint32_t dummy = 0; + rtos_qspi_flash_read( + qspi_flash_ctx, + (uint8_t *)&dummy, + 0, + sizeof(dummy)); + + /* Reset download */ + dn_base_addr = 0; + + // flashing op for manifest is complete without error + // Application can perform checksum, should it fail, use appropriate status such as errVERIFY. + tud_dfu_finish_flashing(DFU_STATUS_OK); +} + +// Invoked when received DFU_UPLOAD request +// Application must populate data with up to length bytes and +// Return the number of written bytes +uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length) +{ + uint32_t endaddr = 0; + uint16_t retval = 0; + uint32_t addr = block_num * CFG_TUD_DFU_XFER_BUFSIZE; + + rtos_printf("Upload Alt %d BlockNum %d of length %d\n", alt, block_num, length); + + switch(alt) { + default: + break; + case 0: + if (rtos_dfu_image_get_factory_size(dfu_image_ctx) > 0) { + addr += rtos_dfu_image_get_factory_addr(dfu_image_ctx); + endaddr = rtos_dfu_image_get_factory_addr(dfu_image_ctx) + rtos_dfu_image_get_factory_size(dfu_image_ctx); + } + break; + case 1: + if (rtos_dfu_image_get_upgrade_size(dfu_image_ctx) > 0) { + addr += rtos_dfu_image_get_upgrade_addr(dfu_image_ctx); + endaddr = rtos_dfu_image_get_upgrade_addr(dfu_image_ctx) + rtos_dfu_image_get_upgrade_size(dfu_image_ctx); + } + break; + case 2: + if ((rtos_qspi_flash_size_get(qspi_flash_ctx) - rtos_dfu_image_get_data_partition_addr(dfu_image_ctx)) > 0) { + addr += rtos_dfu_image_get_data_partition_addr(dfu_image_ctx); + endaddr = rtos_qspi_flash_size_get(qspi_flash_ctx); /* End of flash */ + } + break; + } + + if (addr < endaddr) { + rtos_qspi_flash_read(qspi_flash_ctx, data, addr, length); + retval = length; + } + return retval; +} + +// Invoked when the Host has terminated a download or upload transfer +void tud_dfu_abort_cb(uint8_t alt) +{ + (void) alt; + rtos_printf("Host aborted transfer\n"); +} + +// Invoked when a DFU_DETACH request is received +void tud_dfu_detach_cb(void) +{ + rtos_printf("Host detach, we should probably reboot\n"); + reboot(); +} + +static void reboot(void) +{ + rtos_printf("Reboot initiated by tile:0x%x\n", get_local_tile_id()); + write_sswitch_reg_no_ack(get_local_tile_id(), XS1_SSWITCH_WATCHDOG_COUNT_NUM, 0x10000); + write_sswitch_reg_no_ack(get_local_tile_id(), XS1_SSWITCH_WATCHDOG_CFG_NUM, (1 << XS1_WATCHDOG_COUNT_ENABLE_SHIFT) | (1 << XS1_WATCHDOG_TRIGGER_ENABLE_SHIFT) ); + while(1) {;} +} diff --git a/examples/freertos/dfu/src/usb/usb_descriptors.c b/examples/freertos/dfu/src/usb/usb_descriptors.c new file mode 100644 index 000000000..503e0cc1c --- /dev/null +++ b/examples/freertos/dfu/src/usb/usb_descriptors.c @@ -0,0 +1,173 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "tusb.h" +#include "class/dfu/dfu_device.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + #if CFG_TUD_CDC + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + #else + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + #endif + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ + +// Number of Alternate Interface (each for 1 flash partition) +#define ALT_COUNT 3 + +enum +{ + ITF_NUM_DFU_MODE, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_DESC_LEN(ALT_COUNT)) + +#define FUNC_ATTRS (DFU_ATTR_CAN_UPLOAD | DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_WILL_DETACH | DFU_ATTR_MANIFESTATION_TOLERANT) + +uint8_t const desc_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + // Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size + TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, ALT_COUNT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_XFER_BUFSIZE), +}; + + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + "123456", // 3: Serials, should use chip ID + "DFU dev FACTORY v" XCORE_UTILS_STRINGIFY(VERSION), // 4: DFU device + "DFU dev UPGRADE v" XCORE_UTILS_STRINGIFY(VERSION), // 5: DFU device + "DFU dev DATAPARTITION v" XCORE_UTILS_STRINGIFY(VERSION), // 6: DFU device +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; + + size_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + } + else + { + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) { + chr_count = 31; + } + + // Convert ASCII string into UTF-16 + for(uint8_t i=0; iapp_data, 0, &dummy, 1); // dummy read to ensure flash writes have completed - reboot(); - return true; + if ( state == DFU_DNBUSY ) + { + return 10; /* 10 ms */ + } + else if (state == DFU_MANIFEST) + { + // since we don't buffer entire image and do any flashing in manifest stage + return 0; + } + + return 0; } -void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length) +// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests +// This callback could be returned before flashing op is complete (async). +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_download_cb(uint8_t alt, uint16_t block_num, uint8_t const* data, uint16_t length) { - // rtos_printf("Block[%u] Len[%u] Buffer\n", wBlockNum, length); - - if (dn_base_addr == 0) - { - uint32_t addr = 0; - total_len = 0; - int tmp = boot_image_locate_available_spot(bim_ctx_ptr, &addr, &bytes_avail); - if(tmp == -1) - { - boot_image_t* imgptr = NULL; - imgptr = boot_image_get_last_image(bim_ctx_ptr); - addr = imgptr->startAddress; - bytes_avail = bim_ctx_ptr->boot_partition_size - addr; - } - rtos_printf("Using addr 0x%x\nsize %u\n", addr, bytes_avail); - dn_base_addr = addr; - } - - if(length > 0) - { - unsigned cur_addr = dn_base_addr + (wBlockNum * bim_ctx_ptr->page_size); - if((bytes_avail - total_len) >= length) + (void) alt; + rtos_printf("Block[%u] Len[%u] Buffer\n", block_num, length); + if (dn_base_addr == 0) { - // rtos_printf("write %d at 0x%x\n", length, cur_addr); - boot_image_write(bim_ctx_ptr->app_data, cur_addr, data, length); - total_len += length; + uint32_t addr = 0; + total_len = 0; + int tmp = boot_image_locate_available_spot(bim_ctx_ptr, &addr, &bytes_avail); + if(tmp == -1) + { + boot_image_t* imgptr = NULL; + imgptr = boot_image_get_last_image(bim_ctx_ptr); + addr = imgptr->startAddress; + bytes_avail = bim_ctx_ptr->boot_partition_size - addr; + } + rtos_printf("Using addr 0x%x\nsize %u\n", addr, bytes_avail); + dn_base_addr = addr; + } - tud_dfu_dnload_complete(); - } else { - rtos_printf("Insufficient space\n"); + if(length > 0) + { + unsigned cur_addr = dn_base_addr + (block_num * bim_ctx_ptr->page_size); + if((bytes_avail - total_len) >= length) + { + // rtos_printf("write %d at 0x%x\n", length, cur_addr); + boot_image_write(bim_ctx_ptr->app_data, cur_addr, data, length); + total_len += length; + } else { + rtos_printf("Insufficient space\n"); + } } - } } -bool tud_dfu_device_data_done_check_cb() +// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) +// Application can do checksum, or actual flashing if buffered entire image previously. +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_manifest_cb(uint8_t alt) { - rtos_printf("Dummy device data done check... Returning true\n"); - return true; -} + (void) alt; + rtos_printf("Download completed, enter manifestation\n"); + uint8_t dummy; -void tud_dfu_abort_cb() -{ - rtos_printf("Host Aborted transfer\n"); + rtos_printf("Pass firmware validity check addr 0x%x size %u\n", dn_base_addr, total_len); + set_rt_mode(); + boot_image_read(bim_ctx_ptr->app_data, 0, &dummy, 1); // dummy read to ensure flash writes have completed + reboot(); + + /* TODO actually verify */ + // tud_dfu_finish_flashing(DFU_STATUS_ERR_VERIFY); + // flashing op for manifest is complete without error + // Application can perform checksum, should it fail, use appropriate status such as errVERIFY. + tud_dfu_finish_flashing(DFU_STATUS_OK); } -uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length) +// Invoked when received DFU_UPLOAD request +// Application must populate data with up to length bytes and +// Return the number of written bytes +uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length) { - memset(data, 0x00, length); - uint32_t addr = block_num * FLASH_PAGE_SIZE; - uint32_t endaddr; + (void) alt; + + memset(data, 0x00, length); + uint32_t addr = block_num * FLASH_PAGE_SIZE; + uint32_t endaddr; #if 0 - // Test code which will just read out all of flash rather than a specific image - endaddr = 0x800000; + // Test code which will just read out all of flash rather than a specific image + endaddr = 0x800000; #else - boot_image_t* imgptr = NULL; - imgptr = boot_image_get_last_image(bim_ctx_ptr); - addr += imgptr->startAddress; - endaddr = imgptr->startAddress + imgptr->size; + boot_image_t* imgptr = NULL; + imgptr = boot_image_get_last_image(bim_ctx_ptr); + addr += imgptr->startAddress; + endaddr = imgptr->startAddress + imgptr->size; #endif - return (addr >= endaddr) ? 0 : (uint16_t)boot_image_read(bim_ctx_ptr->app_data, addr, data, length); + return (addr >= endaddr) ? 0 : (uint16_t)boot_image_read(bim_ctx_ptr->app_data, addr, data, length); } -static void reboot(void) +// Invoked when the Host has terminated a download or upload transfer +void tud_dfu_abort_cb(uint8_t alt) { - rtos_printf("Reboot initiated by tile:0x%x\n", get_local_tile_id()); - write_sswitch_reg_no_ack(get_local_tile_id(), XS1_SSWITCH_WATCHDOG_COUNT_NUM, 0x10000); - write_sswitch_reg_no_ack(get_local_tile_id(), XS1_SSWITCH_WATCHDOG_CFG_NUM, (1 << XS1_WATCHDOG_COUNT_ENABLE_SHIFT) | (1 << XS1_WATCHDOG_TRIGGER_ENABLE_SHIFT) ); - while(1) {;} + (void) alt; + uint8_t dummy; + rtos_printf("Host Aborted transfer. Reboot to RT\n"); + set_rt_mode(); + boot_image_read(bim_ctx_ptr->app_data, 0, &dummy, 1); // dummy read to ensure flash writes have completed + reboot(); +} + +// Invoked when a DFU_DETACH request is received +void tud_dfu_detach_cb(void) +{ + rtos_printf("Host detach, reboot\n"); + set_rt_mode(); + reboot(); } void tud_dfu_runtime_reboot_to_dfu_cb(void) { + rtos_printf("Host detach, reboot\n"); set_dfu_mode(); reboot(); } +static void reboot(void) +{ + rtos_printf("Reboot initiated by tile:0x%x\n", get_local_tile_id()); + write_sswitch_reg_no_ack(get_local_tile_id(), XS1_SSWITCH_WATCHDOG_COUNT_NUM, 0x10000); + write_sswitch_reg_no_ack(get_local_tile_id(), XS1_SSWITCH_WATCHDOG_CFG_NUM, (1 << XS1_WATCHDOG_COUNT_ENABLE_SHIFT) | (1 << XS1_WATCHDOG_TRIGGER_ENABLE_SHIFT) ); + while(1) {;} +} + //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ diff --git a/examples/freertos/usb/tinyusb_demos/dfu_runtime/src/tusb_config.h b/examples/freertos/usb/tinyusb_demos/dfu_runtime/src/tusb_config.h index 92648f3a4..319b2072b 100644 --- a/examples/freertos/usb/tinyusb_demos/dfu_runtime/src/tusb_config.h +++ b/examples/freertos/usb/tinyusb_demos/dfu_runtime/src/tusb_config.h @@ -76,12 +76,14 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif -#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 +// #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 +#define CFG_TUD_DFU_XFER_BUFSIZE ( OPT_MODE_HIGH_SPEED ? 512 : 64 ) //------------- CLASS -------------// -#define CFG_TUD_DFU_RUNTIME 1 -#define CFG_TUD_DFU_MODE 1 +// #define CFG_TUD_DFU_RUNTIME 1 +// #define CFG_TUD_DFU_MODE 1 +#define CFG_TUD_DFU 1 #ifdef __cplusplus } diff --git a/examples/freertos/usb/tinyusb_demos/dfu_runtime/src/usb_descriptors.c b/examples/freertos/usb/tinyusb_demos/dfu_runtime/src/usb_descriptors.c index 6e0f0e31d..2e153bbab 100644 --- a/examples/freertos/usb/tinyusb_demos/dfu_runtime/src/usb_descriptors.c +++ b/examples/freertos/usb/tinyusb_demos/dfu_runtime/src/usb_descriptors.c @@ -119,11 +119,9 @@ enum ITF1_NUM_TOTAL }; -#define CONFIG_1_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN ) +#define CONFIG_1_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_DESC_LEN(1) ) -#define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) -// #define FUNC_ATTRS (DFU_FUNC_ATTR_WILL_DETACH_BITMASK | DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) -// #define FUNC_ATTRS 0x0d // original +#define FUNC_ATTRS (DFU_ATTR_CAN_UPLOAD | DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_MANIFESTATION_TOLERANT) uint8_t const desc_configuration_rt[] = { @@ -131,7 +129,7 @@ uint8_t const desc_configuration_rt[] = TUD_CONFIG_DESCRIPTOR(1, ITF0_NUM_TOTAL, 0, CONFIG_0_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_RT_DESCRIPTOR(ITF0_NUM_DFU_RT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), + TUD_DFU_RT_DESCRIPTOR(ITF0_NUM_DFU_RT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_XFER_BUFSIZE), }; uint8_t const desc_configuration_mode[] = @@ -140,7 +138,7 @@ uint8_t const desc_configuration_mode[] = TUD_CONFIG_DESCRIPTOR(1, ITF1_NUM_TOTAL, 0, CONFIG_1_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_MODE_DESCRIPTOR(ITF1_NUM_DFU_MODE, 0, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), + TUD_DFU_DESCRIPTOR(ITF1_NUM_DFU_MODE, 1, 5, FUNC_ATTRS, 1000, CFG_TUD_DFU_XFER_BUFSIZE), }; // Invoked when received GET CONFIGURATION DESCRIPTOR @@ -149,7 +147,9 @@ uint8_t const desc_configuration_mode[] = uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return check_dfu_mode() ? desc_configuration_rt : desc_configuration_mode; + return desc_configuration_mode; + /* TODO tmp always mode for now*/ + // return check_dfu_mode() ? desc_configuration_rt : desc_configuration_mode; } //--------------------------------------------------------------------+ @@ -164,6 +164,7 @@ char const* string_desc_arr [] = "TinyUSB Device", // 2: Product "123456", // 3: Serials, should use chip ID "TinyUSB DFU runtime", // 4: DFU runtime + "TinyUSB DFU FLASH", // 5: DFU device }; static uint16_t _desc_str[32]; diff --git a/examples/freertos/usb/usb.cmake b/examples/freertos/usb/usb.cmake index b6fbd19e5..15d124543 100644 --- a/examples/freertos/usb/usb.cmake +++ b/examples/freertos/usb/usb.cmake @@ -211,48 +211,47 @@ create_run_target(example_freertos_usb_tusb_demo_dfu) create_debug_target(example_freertos_usb_tusb_demo_dfu) -# Incomplete pending xcore tools updates #********************** # DFU Runtime Tile Targets #********************** -# file(GLOB_RECURSE DEMO_SOURCES ${CMAKE_CURRENT_LIST_DIR}/tinyusb_demos/dfu_runtime/src/*.c ) -# set(DEMO_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/tinyusb_demos/dfu_runtime/src/) -# set(DEMO_COMPILE_DEFINITIONS BOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED -# DFU_DEMO=1 -# ) -# set(TARGET_NAME tile0_example_freertos_usb_tusb_demo_dfu_runtime) -# add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) -# target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES} ${DEMO_SOURCES}) -# target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES} ${DEMO_INCLUDES}) -# target_compile_definitions(${TARGET_NAME} PUBLIC ${APP_COMPILE_DEFINITIONS} ${DEMO_COMPILE_DEFINITIONS} THIS_XCORE_TILE=0) -# target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) -# target_link_libraries(${TARGET_NAME} PUBLIC ${APP_LINK_LIBRARIES}) -# target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) -# unset(TARGET_NAME) -# -# set(TARGET_NAME tile1_example_freertos_usb_tusb_demo_dfu_runtime) -# add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) -# target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES} ${DEMO_SOURCES}) -# target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES} ${DEMO_INCLUDES}) -# target_compile_definitions(${TARGET_NAME} PUBLIC ${APP_COMPILE_DEFINITIONS} ${DEMO_COMPILE_DEFINITIONS} THIS_XCORE_TILE=1) -# target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) -# target_link_libraries(${TARGET_NAME} PUBLIC ${APP_LINK_LIBRARIES}) -# target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) -# unset(TARGET_NAME) -# unset(DEMO_SOURCES) -# unset(DEMO_INCLUDES) -# unset(DEMO_COMPILE_DEFINITIONS) -# -# #********************** -# # Merge binaries -# #********************** -# merge_binaries(example_freertos_usb_tusb_demo_dfu_runtime tile0_example_freertos_usb_tusb_demo_dfu_runtime tile1_example_freertos_usb_tusb_demo_dfu_runtime 1) -# -# #********************** -# # Create run and debug targets -# #********************** -# create_run_target(example_freertos_usb_tusb_demo_dfu_runtime) -# create_debug_target(example_freertos_usb_tusb_demo_dfu_runtime) +file(GLOB_RECURSE DEMO_SOURCES ${CMAKE_CURRENT_LIST_DIR}/tinyusb_demos/dfu_runtime/src/*.c ) +set(DEMO_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/tinyusb_demos/dfu_runtime/src/) +set(DEMO_COMPILE_DEFINITIONS BOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + DFU_DEMO=1 +) +set(TARGET_NAME tile0_example_freertos_usb_tusb_demo_dfu_runtime) +add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) +target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES} ${DEMO_SOURCES}) +target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES} ${DEMO_INCLUDES}) +target_compile_definitions(${TARGET_NAME} PUBLIC ${APP_COMPILE_DEFINITIONS} ${DEMO_COMPILE_DEFINITIONS} THIS_XCORE_TILE=0) +target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) +target_link_libraries(${TARGET_NAME} PUBLIC ${APP_LINK_LIBRARIES}) +target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) +unset(TARGET_NAME) + +set(TARGET_NAME tile1_example_freertos_usb_tusb_demo_dfu_runtime) +add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) +target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES} ${DEMO_SOURCES}) +target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES} ${DEMO_INCLUDES}) +target_compile_definitions(${TARGET_NAME} PUBLIC ${APP_COMPILE_DEFINITIONS} ${DEMO_COMPILE_DEFINITIONS} THIS_XCORE_TILE=1) +target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) +target_link_libraries(${TARGET_NAME} PUBLIC ${APP_LINK_LIBRARIES}) +target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) +unset(TARGET_NAME) +unset(DEMO_SOURCES) +unset(DEMO_INCLUDES) +unset(DEMO_COMPILE_DEFINITIONS) + +#********************** +# Merge binaries +#********************** +merge_binaries(example_freertos_usb_tusb_demo_dfu_runtime tile0_example_freertos_usb_tusb_demo_dfu_runtime tile1_example_freertos_usb_tusb_demo_dfu_runtime 1) + +#********************** +# Create run and debug targets +#********************** +create_run_target(example_freertos_usb_tusb_demo_dfu_runtime) +create_debug_target(example_freertos_usb_tusb_demo_dfu_runtime) #********************** diff --git a/modules/rtos b/modules/rtos index ad077ebba..5c1e94444 160000 --- a/modules/rtos +++ b/modules/rtos @@ -1 +1 @@ -Subproject commit ad077ebbad55ccc640711a5255e8fd09206a4de5 +Subproject commit 5c1e94444b023f07232b55a9b9971fb2f9271053 diff --git a/tools/ci/build_rtos_core_examples.sh b/tools/ci/build_rtos_core_examples.sh index e1874eedb..3dcad32e0 100755 --- a/tools/ci/build_rtos_core_examples.sh +++ b/tools/ci/build_rtos_core_examples.sh @@ -16,17 +16,21 @@ if [ -d "${DIST_HOST_DIR}" ]; then find ${DIST_HOST_DIR} -type f -exec chmod a+x {} + fi -# row format is: "target min_tools_version run_fs_target run_swmem_target board toolchain" +# row format is: "target min_tools_version run_fs_target run_swmem_target run_upgrade_img_target board toolchain" applications=( - "example_freertos_device_control 15.1.0 No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" - "example_freertos_dispatcher 15.1.0 No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" - "example_freertos_explorer_board 15.1.0 Yes No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" - "example_freertos_getting_started 15.1.0 No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" - "example_freertos_l2_cache 15.1.0 No Yes XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" - "example_freertos_tracealyzer 15.1.0 No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" - "example_freertos_xlink_0 15.2.0 No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" - "example_freertos_xlink_1 15.2.0 No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" - "example_freertos_xscope_fileio 15.1.0 No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_device_control 15.1.0 No No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_dfu_v1 15.1.3 No No Yes XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_dfu_v2 15.1.3 No No Yes XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_dfu_v1 15.2.0 No No Yes XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_dfu_v2 15.2.0 No No Yes XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_dispatcher 15.1.0 No No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_explorer_board 15.1.0 Yes No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_getting_started 15.1.0 No No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_l2_cache 15.1.0 No Yes No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_tracealyzer 15.1.0 No No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_xlink_0 15.2.0 No No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_xlink_1 15.2.0 No No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" + "example_freertos_xscope_fileio 15.1.0 No No No XCORE-AI-EXPLORER xmos_cmake_toolchain/xs3a.cmake" ) # perform builds @@ -36,8 +40,9 @@ for ((i = 0; i < ${#applications[@]}; i += 1)); do min_tools_version="${FIELDS[1]}" run_fs_target="${FIELDS[2]}" run_swmem_target="${FIELDS[3]}" - board="${FIELDS[4]}" - toolchain_file="${XCORE_SDK_ROOT}/${FIELDS[5]}" + run_upgrade_img_target="${FIELDS[4]}" + board="${FIELDS[5]}" + toolchain_file="${XCORE_SDK_ROOT}/${FIELDS[6]}" path="${XCORE_SDK_ROOT}" if check_tools_version ${min_tools_version} @@ -63,5 +68,12 @@ for ((i = 0; i < ${#applications[@]}; i += 1)); do (cd ${path}/build_${board}; log_errors make make_swmem_${app_target} -j) (cd ${path}/build_${board}; cp ${app_target}.swmem ${DIST_DIR}) fi + if [ "$run_upgrade_img_target" = "Yes" ]; then + echo '======================================================' + echo '= Making upgrade image for' ${app_target} + echo '======================================================' + (cd ${path}/build_${board}; log_errors make create_upgrade_img_${app_target} -j) + (cd ${path}/build_${board}; cp ${app_target}_upgrade.bin ${DIST_DIR}) + fi fi done