initial commit

This commit is contained in:
Justin Hammond 2022-12-28 17:39:27 +08:00
commit 5cc0f0c8b3
25 changed files with 3044 additions and 0 deletions

1
README.md Normal file
View file

@ -0,0 +1 @@
# bl808_coprocessor

18
m0/.vscode/c_cpp_properties.json vendored Normal file
View file

@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64",
"compileCommands": "${workspaceFolder}/build/compile_commands.json",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}

63
m0/.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,63 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "gdb",
"request": "attach",
"name": "Debug Microcontroller",
"target": "extended-remote 10.100.201.177:1025",
"executable": "${workspaceRoot}/build/build_out/ox64_coproc_bl808_m0.elf",
"cwd": "${workspaceRoot}",
"gdbpath": "gdb-multiarch",
"showDevDebugOutput": false,
"printCalls": false,
"valuesFormatting": "parseText",
"autorun": [
// "monitor tpwr enable",
// "monitor swdp_scan",
// "attach 1",
//"file ${workspaceRoot}/build/build_out/ox64_coproc_bl808_m0.elf",
"set mem inaccessible-by-default off",
//"set architecture riscv:rv32",
"set remotetimeout 250",
//"#set disassemble-next-line on",
//"#mon gdb_breakpoint_override [hard|soft|disable]",
//"#mon reset",
//"set $pc=0x58000000",
//"set $mie=0",
//"set $mstatus=0x1880",
"thb main",
"mem 0x40000000 0x40004000 rw",
"mem 0x3f000000 0x3f018000 rw",
"mem 0x3efe8000 0x3f068000 rw",
"mem 0x22030000 0x22058000 rw",
"mem 0x22020000 0x22030000 rw",
//"#rom",
"mem 0x90000000 0x90020000 ro",
//"#psram",
"mem 0x50000000 0x58000000 rw",
//"#flash",
"mem 0x58000000 0x60000000 ro",
"set $pc=0x58000000",
"set $mie=0",
"set $mstatus=0x1880",
]
},
// {
// "name": "GDB",
// "type": "cppdbg",
// "request": "launch",
// "cwd": "${workspaceRoot}",
// "target": "${workspaceRoot}/build/build_out/ox64_coproc_bl808_m0.elf",
// "gdbpath" : "/usr/bin/gdb-multiarch",
// "autorun": [
// "target remote 10.100.201.177:1025",
// "symbol-file ./build/build_out/ox64_coproc_bl808_m0.elf",
// "monitor reset"
// ]
// }
]
}

12
m0/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,12 @@
{
"files.associations": {
"*.tpl": "html",
"array": "c",
"*.tcc": "c",
"memory": "c",
"istream": "c",
"functional": "c",
"tuple": "c",
"utility": "c"
}
}

29
m0/CMakeLists.txt Normal file
View file

@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.15)
include(proj.conf)
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
sdk_add_include_directories(include)
target_sources(app PRIVATE
src/usb_descriptors.c
src/usbd_dfu.c
src/flash.c
src/console.c
src/cmd/cmd_memory.c
src/cmd/cmd_sensors.c
src/partition.c
src/softcrc.c)
target_compile_definitions(app PRIVATE -DUSBD_DFU_XFER_SIZE=1024)
target_compile_definitions(app PRIVATE -DUSBD_DFU_APP_DEFAULT_ADD=0x58000000)
target_compile_options(app PRIVATE -ggdb -O0)
# we need to set it on the shell library instead
#target_compile_definitions(app PRIVATE -DSHELL_DEFAULT_NAME="0x64>")
sdk_set_main_file(src/main.c)
sdk_set_linker_script(bl808_flash_m0.ld)
message(STATUS "Sources: ${SOURCES}")
project(ox64_coproc)

20
m0/Makefile Normal file
View file

@ -0,0 +1,20 @@
SDK_DEMO_PATH ?= .
BL_SDK_BASE ?= /home/fish/bl808/bl_mcu_sdk
export BL_SDK_BASE
CHIP ?= bl808
BOARD ?= bl808dk
CPU_ID ?= m0
CROSS_COMPILE ?= riscv64-unknown-elf-
# add custom cmake definition
#cmake_definition+=-Dxxx=sss
include $(BL_SDK_BASE)/project.build
flash:
bflb-mcu-tool --chipname=bl808 --firmware build/build_out/ox64_coproc_bl808_m0.bin
monitor:
screen /dev/ttyACM0 2000000

264
m0/bl808_flash_m0.ld Normal file
View file

@ -0,0 +1,264 @@
/****************************************************************************************
* @file flash.ld
*
* @brief This file is the link script file (gnuarm or armgcc).
*
* Copyright (C) BouffaloLab 2021
*
****************************************************************************************
*/
/* configure the CPU type */
OUTPUT_ARCH( "riscv" )
/* link with the standard c library */
INPUT(-lc)
/* link with the standard GCC library */
INPUT(-lgcc)
/* configure the entry point */
ENTRY(__start)
StackSize = 0x0400; /* 1KB */
HeapMinSize = 0x1000; /* 4KB */
MEMORY
{
xip_memory (rx) : ORIGIN = 0x58000000, LENGTH = 32M
itcm_memory (rx) : ORIGIN = 0x62020000, LENGTH = 32K
dtcm_memory (rx) : ORIGIN = 0x62028000, LENGTH = 4K
nocache_ram_memory (!rx) : ORIGIN = 0x22026000, LENGTH = 40K
ram_memory (!rx) : ORIGIN = 0x62030000, LENGTH = 160K + 64K - 20K - 4K - 40K
xram_memory (!rx) : ORIGIN = 0x40000000, LENGTH = 16K
}
SECTIONS
{
.text :
{
. = ALIGN(4);
__text_code_start__ = .;
KEEP (*(SORT_NONE(.init)))
KEEP (*(SORT_NONE(.vector)))
*(.text)
*(.text.*)
/* section information for shell */
. = ALIGN(4);
__fsymtab_start = .;
KEEP(*(FSymTab))
__fsymtab_end = .;
. = ALIGN(4);
__vsymtab_start = .;
KEEP(*(VSymTab))
__vsymtab_end = .;
/* section information for usb usbh_class_info */
. = ALIGN(4);
__usbh_class_info_start__ = .;
KEEP(*(.usbh_class_info))
. = ALIGN(4);
__usbh_class_info_end__ = .;
/*put .rodata**/
*(EXCLUDE_FILE( *bl808_glb*.o* \
*bl808_glb_gpio*.o* \
*bl808_pds*.o* \
*bl808_aon*.o* \
*bl808_hbn*.o* \
*bl808_l1c*.o* \
*bl808_common*.o* \
*bl808_clock*.o* \
*bl808_ef_ctrl*.o* \
*bl808_sf_cfg*.o* \
*bl808_sf_ctrl*.o* \
*bl808_sflash*.o* \
*bl808_xip_sflash*.o* \
*bl808_romapi_patch*.o* ) .rodata*)
*(.srodata)
*(.srodata.*)
. = ALIGN(4);
__text_code_end__ = .;
} > xip_memory
. = ALIGN(4);
__itcm_load_addr = .;
.itcm_region : AT (__itcm_load_addr)
{
. = ALIGN(4);
__tcm_code_start__ = .;
*(.tcm_code.*)
*(.tcm_const.*)
*(.sclock_rlt_code.*)
*(.sclock_rlt_const.*)
*bl808_glb*.o*(.rodata*)
*bl808_glb_gpio*.o*(.rodata*)
*bl808_pds*.o*(.rodata*)
*bl808_aon*.o*(.rodata*)
*bl808_hbn*.o*(.rodata*)
*bl808_l1c*.o*(.rodata*)
*bl808_common*.o*(.rodata*)
*bl808_clock*.o*(.rodata*)
*bl808_ef_ctrl*.o*(.rodata*)
*bl808_sf_cfg*.o*(.rodata*)
*bl808_sf_ctrl*.o*(.rodata*)
*bl808_sflash*.o*(.rodata*)
*bl808_xip_sflash*.o*(.rodata*)
*bl808_romapi_patch*.o*(.rodata*)
. = ALIGN(4);
__tcm_code_end__ = .;
} > itcm_memory
__dtcm_load_addr = __itcm_load_addr + SIZEOF(.itcm_region);
.dtcm_region : AT (__dtcm_load_addr)
{
. = ALIGN(4);
__tcm_data_start__ = .;
*(.tcm_data)
/* *finger_print.o(.data*) */
. = ALIGN(4);
__tcm_data_end__ = .;
} > dtcm_memory
/*************************************************************************/
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (NOLOAD):
{
. = ALIGN(0x4);
. = . + StackSize;
. = ALIGN(0x4);
} > dtcm_memory
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(dtcm_memory) + LENGTH(dtcm_memory);
PROVIDE( __freertos_irq_stack_top = __StackTop);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __tcm_data_end__, "region RAM overflowed with stack")
/*************************************************************************/
__nocache_ram_load_addr = __dtcm_load_addr + SIZEOF(.dtcm_region);
.nocache_ram_region : AT (__nocache_ram_load_addr)
{
. = ALIGN(4);
__nocache_ram_data_start__ = .;
*(.nocache_ram)
. = ALIGN(4);
__nocache_ram_data_end__ = .;
} > nocache_ram_memory
__system_ram_load_addr = __nocache_ram_load_addr + SIZEOF(.nocache_ram_region);
.system_ram_data_region : AT (__system_ram_load_addr)
{
. = ALIGN(4);
__system_ram_data_start__ = .;
*(.system_ram)
. = ALIGN(4);
__system_ram_data_end__ = .;
} > ram_memory
.system_ram_noinit_data_region (NOLOAD) :
{
. = ALIGN(4);
*(.system_ram_noinit)
. = ALIGN(4);
} > ram_memory
__ram_load_addr = __system_ram_load_addr + SIZEOF(.system_ram_data_region);
/* Data section */
RAM_DATA : AT (__ram_load_addr)
{
. = ALIGN(4);
__ram_data_start__ = .;
PROVIDE( __global_pointer$ = . + 0x800 );
*(.data)
*(.data.*)
*(.sdata)
*(.sdata.*)
*(.sdata2)
*(.sdata2.*)
. = ALIGN(4);
__ram_data_end__ = .;
} > ram_memory
__etext_final = (__ram_load_addr + SIZEOF (RAM_DATA));
ASSERT(__etext_final <= ORIGIN(xip_memory) + LENGTH(xip_memory), "code memory overflow")
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(.sbss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > ram_memory
.noinit_data (NOLOAD) :
{
. = ALIGN(4);
__noinit_data_start__ = .;
*(.noinit_data*)
. = ALIGN(4);
__noinit_data_end__ = .;
} > ram_memory
.nocache_noinit_ram_region (NOLOAD) :
{
. = ALIGN(4);
__nocache_noinit_ram_data_start__ = .;
*(.nocache_noinit_ram)
*(.noncacheable)
. = ALIGN(4);
__nocache_noinit_ram_data_end__ = .;
} > nocache_ram_memory
.heap (NOLOAD):
{
. = ALIGN(4);
__HeapBase = .;
/*__end__ = .;*/
/*end = __end__;*/
KEEP(*(.heap*))
. = ALIGN(4);
__HeapLimit = .;
} > ram_memory
__HeapLimit = ORIGIN(ram_memory) + LENGTH(ram_memory);
ASSERT(__HeapLimit - __HeapBase >= HeapMinSize, "heap region overflow")
}

127
m0/include/FreeRTOSConfig.h Normal file
View file

@ -0,0 +1,127 @@
/*
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
#include "stdio.h"
#ifdef BL702
#define configMTIME_BASE_ADDRESS (0x02000000UL + 0xBFF8UL)
#define configMTIMECMP_BASE_ADDRESS (0x02000000UL + 0x4000UL)
#else
#define configMTIME_BASE_ADDRESS (0xE0000000UL + 0xBFF8UL)
#define configMTIMECMP_BASE_ADDRESS (0xE0000000UL + 0x4000UL)
#endif
// #define configSUPPORT_STATIC_ALLOCATION 1
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ((uint32_t)(1 * 1000 * 1000))
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES (7)
#define configMINIMAL_STACK_SIZE ((unsigned short)1024) /* Only needs to be this high as some demo tasks also use this constant. In production only the idle task would use this. */
#define configTOTAL_HEAP_SIZE ((size_t)6 * 1024)
#define configMAX_TASK_NAME_LEN (16)
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#define configUSE_TICKLESS_IDLE 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES (2)
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)
#define configTIMER_QUEUE_LENGTH 4
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE)
/* Task priorities. Allow these to be overridden. */
#ifndef uartPRIMARY_PRIORITY
#define uartPRIMARY_PRIORITY (configMAX_PRIORITIES - 3)
#endif
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xTaskAbortDelay 1
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_xSemaphoreGetMutexHolder 1
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
void vApplicationMallocFailedHook(void);
void vAssertCalled(void);
#define configASSERT(x) \
if ((x) == 0) { \
printf("file [%s]\r\n", __FILE__); \
printf("func [%s]\r\n", __FUNCTION__); \
printf("line [%d]\r\n", __LINE__); \
printf("%s\r\n", (const char *)(#x)); \
vAssertCalled(); \
}
#if (configUSE_TICKLESS_IDLE != 0)
void vApplicationSleep(uint32_t xExpectedIdleTime);
#define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) vApplicationSleep(xExpectedIdleTime)
#endif
// #define portUSING_MPU_WRAPPERS
#endif /* FREERTOS_CONFIG_H */

6
m0/include/console.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef CONSOLE_H
#define CONSOLE_H
void console_init(void);
#endif

210
m0/include/partition.h Normal file
View file

@ -0,0 +1,210 @@
/**
******************************************************************************
* @file partition.h
* @version V1.0
* @date
* @brief This file is the standard driver header file
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#ifndef __PARTITION_H__
#define __PARTITION_H__
//#include "blsp_port.h"
#include "bl808_common.h"
/** @addtogroup BFLB_Common_Driver
* @{
*/
/** @addtogroup PARTITION
* @{
*/
/** @defgroup PARTITION_Public_Types
* @{
*/
/**
* @brief Partition table error type definition
*/
typedef enum {
PT_ERROR_SUCCESS, /*!< Partition table error type:success */
PT_ERROR_TABLE_NOT_VALID, /*!< Partition table error type:table not found */
PT_ERROR_ENTRY_NOT_FOUND, /*!< Partition table error type:entry not found */
PT_ERROR_ENTRY_UPDATE_FAIL, /*!< Partition table error type:entry update fail */
PT_ERROR_CRC32, /*!< Partition table error type:crc32 error */
PT_ERROR_PARAMETER, /*!< Partition table error type:input parameter error */
PT_ERROR_FALSH_READ, /*!< Partition table error type:flash read error */
PT_ERROR_FALSH_WRITE, /*!< Partition table error type:flash write error */
PT_ERROR_FALSH_ERASE, /*!< Partition table error type:flash erase error */
} pt_table_error_type;
/**
* @brief Partition id type definition
*/
typedef enum {
PT_TABLE_ID_0, /*!< Partition table ID 0 */
PT_TABLE_ID_1, /*!< Partition table ID 1 */
PT_TABLE_ID_INVALID, /*!< Partition table ID invalid */
} pt_table_id_type;
/**
* @brief Partition id type definition
*/
typedef enum {
PT_ENTRY_FW_CPU0, /*!< Partition entry type:CPU0 firmware */
PT_ENTRY_FW_CPU1, /*!< Partition entry type:CPU1 firmware */
PT_ENTRY_MAX = 16, /*!< Partition entry type:Max */
} pt_table_entry_type;
/**
* @brief Partition table config definition
*/
typedef struct
{
uint32_t magicCode; /*!< Partition table magic code */
uint16_t version; /*!< Partition table verdion */
uint16_t entryCnt; /*!< Partition table entry count */
uint32_t age; /*!< Partition table age */
uint32_t crc32; /*!< Partition table CRC32 value */
} pt_table_config;
/**
* @brief Partition table entry config definition
*/
typedef struct
{
uint8_t type; /*!< Partition entry type */
uint8_t device; /*!< Partition entry device */
uint8_t active_index; /*!< Partition entry active index */
uint8_t name[9]; /*!< Partition entry name */
uint32_t start_address[2]; /*!< Partition entry start address */
uint32_t max_len[2]; /*!< Partition entry max length */
uint32_t len; /*!< Partition entry length */
uint32_t age; /*!< Partition entry age */
} pt_table_entry_config;
/**
* @brief Partition table stuff config definition
*/
typedef struct
{
pt_table_config pt_table; /*!< Partition table */
pt_table_entry_config pt_entries[PT_ENTRY_MAX]; /*!< Partition entries */
uint32_t crc32; /*!< Partition entries crc32 */
} pt_table_stuff_config;
/**
* @brief Partition table iap param definition
*/
typedef struct
{
uint32_t iap_start_addr;
uint32_t iap_write_addr;
uint32_t iap_img_len;
uint8_t inactive_index;
uint8_t inactive_table_index;
} pt_table_iap_param_type;
/*@} end of group PARTITION_Public_Types */
/** @defgroup PARTITION_Public_Constants
* @{
*/
/** @defgroup pt_table_error_type
* @{
*/
#define IS_PTTABLE_ERROR_TYPE(type) (((type) == PT_ERROR_SUCCESS) || \
((type) == PT_ERROR_TABLE_NOT_VALID) || \
((type) == PT_ERROR_ENTRY_NOT_FOUND) || \
((type) == PT_ERROR_ENTRY_UPDATE_FAIL) || \
((type) == PT_ERROR_CRC32) || \
((type) == PT_ERROR_PARAMETER) || \
((type) == PT_ERROR_FALSH_READ) || \
((type) == PT_ERROR_FALSH_WRITE) || \
((type) == PT_ERROR_FALSH_ERASE))
/** @defgroup pt_table_id_type
* @{
*/
#define IS_PTTABLE_ID_TYPE(type) (((type) == PT_TABLE_ID_0) || \
((type) == PT_TABLE_ID_1) || \
((type) == PT_TABLE_ID_INVALID))
/** @defgroup pt_table_entry_type
* @{
*/
#define IS_PTTABLE_ENTRY_TYPE(type) (((type) == PT_ENTRY_FW_CPU0) || \
((type) == PT_ENTRY_FW_CPU1) || \
((type) == PT_ENTRY_MAX))
/*@} end of group PARTITION_Public_Constants */
/** @defgroup PARTITION_Public_Macros
* @{
*/
#define BFLB_PT_TABLE0_ADDRESS 0xE000
#define BFLB_PT_TABLE1_ADDRESS 0xF000
#define BFLB_PT_MAGIC_CODE 0x54504642
typedef int (*p_pt_table_flash_erase)(uint32_t startaddr, uint32_t endaddr);
typedef int (*p_pt_table_flash_write)(uint32_t addr, uint8_t *data, uint32_t len);
typedef int (*p_pt_table_flash_read)(uint32_t addr, uint8_t *data, uint32_t len);
/*@} end of group PARTITION_Public_Macros */
/** @defgroup PARTITION_Public_Functions
* @{
*/
void pt_table_set_flash_operation(p_pt_table_flash_erase erase, p_pt_table_flash_write write, p_pt_table_flash_read read);
pt_table_id_type pt_table_get_active_partition_need_lock(pt_table_stuff_config ptStuff[2]);
pt_table_error_type pt_table_get_active_entries_by_id(pt_table_stuff_config *pt_stuff,
pt_table_entry_type type,
pt_table_entry_config *pt_entry);
pt_table_error_type pt_table_get_active_entries_by_name(pt_table_stuff_config *pt_stuff,
uint8_t *name,
pt_table_entry_config *pt_entry);
pt_table_error_type pt_table_update_entry(pt_table_id_type target_table_id,
pt_table_stuff_config *pt_stuff,
pt_table_entry_config *pt_entry);
pt_table_error_type pt_table_create(pt_table_id_type pt_id);
pt_table_error_type pt_table_dump(void);
pt_table_error_type pt_table_get_iap_para(pt_table_iap_param_type *para);
pt_table_error_type pt_table_set_iap_para(pt_table_iap_param_type *para);
/*@} end of group PARTITION_Public_Functions */
/*@} end of group PARTITION */
/*@} end of group BFLB_Common_Driver */
extern pt_table_iap_param_type p_iap_param;
#endif /* __PARTITION_H__ */

45
m0/include/softcrc.h Normal file
View file

@ -0,0 +1,45 @@
/**
* *****************************************************************************
* @file softcrc.h
* @version 1.0
* @date 2022-11-23
* @brief
* *****************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* *****************************************************************************
*/
#ifndef __SOFTCRC_H__
#define __SOFTCRC_H__
#include "stdint.h"
uint16_t BFLB_Soft_CRC16(void *dataIn, uint32_t len);
uint32_t BFLB_Soft_CRC32_Ex(uint32_t initial, void *dataIn, uint32_t len);
uint32_t BFLB_Soft_CRC32(void *dataIn, uint32_t len);
#endif

132
m0/include/usb_config.h Normal file
View file

@ -0,0 +1,132 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef CHERRYUSB_CONFIG_H
#define CHERRYUSB_CONFIG_H
/* ================ USB common Configuration ================ */
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
#define usb_malloc(size) malloc(size)
#define usb_free(ptr) free(ptr)
#ifndef CONFIG_USB_DBG_LEVEL
#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
#endif
/* Enable print with color */
#define CONFIG_USB_PRINTF_COLOR_ENABLE
/* data align size when use dma */
#ifndef CONFIG_USB_ALIGN_SIZE
#define CONFIG_USB_ALIGN_SIZE 4
#endif
/* attribute data into no cache ram */
#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable")))
/* ================= USB Device Stack Configuration ================ */
/* Ep0 max transfer buffer, specially for receiving data from ep0 out */
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 4096
/* Setup packet log for debug */
//#define CONFIG_USBDEV_SETUP_LOG_PRINT
/* Check if the input descriptor is correct */
#define CONFIG_USBDEV_DESC_CHECK
/* Enable test mode */
// #define CONFIG_USBDEV_TEST_MODE
#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512
#endif
#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING
#define CONFIG_USBDEV_MSC_MANUFACTURER_STRING ""
#endif
#ifndef CONFIG_USBDEV_MSC_PRODUCT_STRING
#define CONFIG_USBDEV_MSC_PRODUCT_STRING ""
#endif
#ifndef CONFIG_USBDEV_MSC_VERSION_STRING
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
#endif
// #define CONFIG_USBDEV_MSC_THREAD
#ifdef CONFIG_USBDEV_MSC_THREAD
#ifndef CONFIG_USBDEV_MSC_STACKSIZE
#define CONFIG_USBDEV_MSC_STACKSIZE 2048
#endif
#ifndef CONFIG_USBDEV_MSC_PRIO
#define CONFIG_USBDEV_MSC_PRIO 4
#endif
#endif
#ifndef CONFIG_USBDEV_AUDIO_VERSION
#define CONFIG_USBDEV_AUDIO_VERSION 0x0100
#endif
#ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL
#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8
#endif
/* ================ USB HOST Stack Configuration ================== */
#define CONFIG_USBHOST_MAX_RHPORTS 1
#define CONFIG_USBHOST_MAX_EXTHUBS 1
#define CONFIG_USBHOST_MAX_EHPORTS 4
#define CONFIG_USBHOST_MAX_INTERFACES 6
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
#define CONFIG_USBHOST_DEV_NAMELEN 16
#ifndef CONFIG_USBHOST_PSC_PRIO
#define CONFIG_USBHOST_PSC_PRIO 4
#endif
#ifndef CONFIG_USBHOST_PSC_STACKSIZE
#define CONFIG_USBHOST_PSC_STACKSIZE 2048
#endif
//#define CONFIG_USBHOST_GET_STRING_DESC
/* Ep0 max transfer buffer */
#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
#ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500
#endif
#ifndef CONFIG_USBHOST_MSC_TIMEOUT
#define CONFIG_USBHOST_MSC_TIMEOUT 5000
#endif
/* ================ USB Device Port Configuration ================*/
//#define USBD_IRQHandler USBD_IRQHandler
//#define USB_BASE (0x40080000UL)
//#define USB_NUM_BIDIR_ENDPOINTS 4
/* ================ USB Host Port Configuration ==================*/
#define CONFIG_USBHOST_PIPE_NUM 10
/* ================ EHCI Configuration ================ */
#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000)
#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10)
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
// #define CONFIG_USB_EHCI_INFO_ENABLE
#define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE
// #define CONFIG_USB_EHCI_CONFIGFLAG
// #define CONFIG_USB_EHCI_PORT_POWER
#endif

137
m0/include/usb_dfu.h Normal file
View file

@ -0,0 +1,137 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_DFU_H
#define USB_DFU_H
/**\addtogroup USB_MODULE_DFU USB DFU class
* \brief This module contains USB Device Firmware Upgrade class definitions.
* \details This module based on
* + [USB Device Firmware Upgrade Specification, Revision 1.1]
* (https://www.usb.org/sites/default/files/DFU_1.1.pdf)
* @{ */
/** DFU Specification release */
#define DFU_VERSION 0x0110
/** DFU Class Subclass */
#define DFU_SUBCLASS_DFU 0x01
/** DFU Class runtime Protocol */
#define DFU_PROTOCOL_RUNTIME 0x01
/** DFU Class DFU mode Protocol */
#define DFU_PROTOCOL_MODE 0x02
/**
* @brief DFU Class Specific Requests
*/
#define DFU_REQUEST_DETACH 0x00
#define DFU_REQUEST_DNLOAD 0x01
#define DFU_REQUEST_UPLOAD 0x02
#define DFU_REQUEST_GETSTATUS 0x03
#define DFU_REQUEST_CLRSTATUS 0x04
#define DFU_REQUEST_GETSTATE 0x05
#define DFU_REQUEST_ABORT 0x06
/** DFU FUNCTIONAL descriptor type */
#define DFU_FUNC_DESC 0x21
/** DFU attributes DFU Functional Descriptor */
#define DFU_ATTR_WILL_DETACH 0x08
#define DFU_ATTR_MANIFESTATION_TOLERANT 0x04
#define DFU_ATTR_CAN_UPLOAD 0x02
#define DFU_ATTR_CAN_DNLOAD 0x01
/** bStatus values for the DFU_GETSTATUS response */
#define DFU_STATUS_OK 0x00U
#define DFU_STATUS_ERR_TARGET 0x01U
#define DFU_STATUS_ERR_FILE 0x02U
#define DFU_STATUS_ERR_WRITE 0x03U
#define DFU_STATUS_ERR_ERASE 0x04U
#define DFU_STATUS_ERR_CHECK_ERASED 0x05U
#define DFU_STATUS_ERR_PROG 0x06U
#define DFU_STATUS_ERR_VERIFY 0x07U
#define DFU_STATUS_ERR_ADDRESS 0x08U
#define DFU_STATUS_ERR_NOTDONE 0x09U
#define DFU_STATUS_ERR_FIRMWARE 0x0AU
#define DFU_STATUS_ERR_VENDOR 0x0BU
#define DFU_STATUS_ERR_USB 0x0CU
#define DFU_STATUS_ERR_POR 0x0DU
#define DFU_STATUS_ERR_UNKNOWN 0x0EU
#define DFU_STATUS_ERR_STALLEDPKT 0x0FU
/** bState values for the DFU_GETSTATUS response */
#define DFU_STATE_APP_IDLE 0U
#define DFU_STATE_APP_DETACH 1U
#define DFU_STATE_DFU_IDLE 2U
#define DFU_STATE_DFU_DNLOAD_SYNC 3U
#define DFU_STATE_DFU_DNLOAD_BUSY 4U
#define DFU_STATE_DFU_DNLOAD_IDLE 5U
#define DFU_STATE_DFU_MANIFEST_SYNC 6U
#define DFU_STATE_DFU_MANIFEST 7U
#define DFU_STATE_DFU_MANIFEST_WAIT_RESET 8U
#define DFU_STATE_DFU_UPLOAD_IDLE 9U
#define DFU_STATE_DFU_ERROR 10U
/** DFU Manifestation State */
#define DFU_MANIFEST_COMPLETE 0U
#define DFU_MANIFEST_IN_PROGRESS 1U
/** Special Commands with Download Request */
#define DFU_CMD_GETCOMMANDS 0U
#define DFU_CMD_SETADDRESSPOINTER 0x21U
#define DFU_CMD_ERASE 0x41U
#define DFU_MEDIA_ERASE 0x00U
#define DFU_MEDIA_PROGRAM 0x01U
/** Other defines */
/* Bit Detach capable = bit 3 in bmAttributes field */
#define DFU_DETACH_MASK (1U << 3)
#define DFU_MANIFEST_MASK (1U << 2)
/** Run-Time Functional Descriptor */
struct dfu_runtime_descriptor {
uint8_t bLength; /**<\brief Descriptor length in bytes.*/
uint8_t bDescriptorType; /**<\brief DFU functional descriptor type.*/
uint8_t bmAttributes; /**<\brief USB DFU capabilities \ref USB_DFU_CAPAB*/
uint16_t wDetachTimeout; /**<\brief USB DFU detach timeout in ms.*/
uint16_t wTransferSize; /**<\brief USB DFU maximum transfer block size in bytes.*/
uint16_t bcdDFUVersion; /**<\brief USB DFU version \ref VERSION_BCD utility macro.*/
} __PACKED;
/**\brief Payload packet to response in DFU_GETSTATUS request */
struct dfu_info {
uint8_t bStatus; /**<\brief An indication of the status resulting from the
* execution of the most recent request.*/
uint8_t bPollTimeout; /**<\brief Minimum time (LSB) in ms, that the host should wait
* before sending a subsequent DFU_GETSTATUS request.*/
uint16_t wPollTimeout; /**<\brief Minimum time (MSB) in ms, that the host should wait
* before sending a subsequent DFU_GETSTATUS request.*/
uint8_t bState; /**<\brief An indication of the state that the device is going
* to enter immediately following transmission of this response.*/
uint8_t iString; /**<\brief Index of the status string descriptor.*/
};
// clang-format off
#define DFU_DESCRIPTOR_INIT() \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x00, /* bNumEndpoints Default Control Pipe only */ \
USB_DEVICE_CLASS_APP_SPECIFIC, /* bInterfaceClass */ \
0x01, /* bInterfaceSubClass Device Firmware Upgrade */ \
0x02, /* bInterfaceProtocol DFU mode */ \
0x04, /* iInterface */ /*!< Device Firmware Update Functional Descriptor */ \
0x09, /* bLength */ \
0x21, /* DFU Functional Descriptor */ \
0x0B, /* bmAttributes */ \
WBVAL(0x00ff), /* wDetachTimeOut */ \
WBVAL(USBD_DFU_XFER_SIZE), /* wTransferSize */ \
WBVAL(0x0110) /* bcdDFUVersion */
// clang-format on
#endif /* USB_DFU_H */

9
m0/include/usb_uart.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef USBUART_H
#define USBUART_H
#include <stdint.h>
void vuart_write(uint8_t uart, char *buf, uint8_t len);
void usbuart_read(uint8_t uart, char *data, uint32_t len);
#endif

28
m0/include/usbd_dfu.h Normal file
View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_DFU_H
#define USBD_DFU_H
#include "usb_dfu.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Init dfu interface driver */
struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf);
/* Interface functions that need to be implemented by the user */
uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len);
uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len);
uint16_t dfu_erase_flash(uint32_t add);
void dfu_leave(void);
void dfu_reset(void);
#ifdef __cplusplus
}
#endif
#endif /* USBD_DFU_H */

15
m0/proj.conf Normal file
View file

@ -0,0 +1,15 @@
set(CONFIG_CHERRYUSB 1)
set(CONFIG_CHERRYUSB_DEVICE 1)
set(CONFIG_CHERRYUSB_DEVICE_CDC 1)
set(CONFIG_CHERRYUSB_DEVICE_HID 0)
set(CONFIG_CHERRYUSB_DEVICE_MSC 0)
set(CONFIG_CHERRYUSB_DEVICE_AUDIO 0)
set(CONFIG_CHERRYUSB_DEVICE_VIDEO 0)
set(CONFIG_PSRAM 1)
set(CONFIG_SHELL 1)
set(CONFIG_FREERTOS 1)
set(CONFIG_BFLOG 1)
set(CONFIG_VLIBC 1)
set(CONFIG_DEBUG 1)
set(CONFIG_ROMAPI 1)
set(CONFIG_TLSF 1)

17
m0/src/cmd/cmd_memory.c Normal file
View file

@ -0,0 +1,17 @@
#include <stdio.h>
#include <shell.h>
#ifdef CONFIG_TLSF
#include "bflb_tlsf.h"
int meminfo(int argc, char **argv)
{
if (argc != 1) {
printf("Usage: meminfo");
return 0;
}
bflb_tlsf_size_container_t *tlsf_size = bflb_tlsf_stats();
printf("Memory: Total: %dKb, Used: %dKb Free: %dKb\r\n", (tlsf_size->free + tlsf_size->used)/1024, tlsf_size->used/1024, tlsf_size->free/1024);
return 0;
}
SHELL_CMD_EXPORT(meminfo, get free memory info)
#endif

72
m0/src/cmd/cmd_sensors.c Normal file
View file

@ -0,0 +1,72 @@
#include <bflb_adc.h>
#include <shell.h>
int temp(int argc, char **argv) {
uint16_t i = 0;
float average_filter = 0.0;
struct bflb_device_s *adc = bflb_device_get_by_name("adc");
/* adc clock = XCLK / 2 / 32 */
struct bflb_adc_config_s cfg;
cfg.clk_div = ADC_CLK_DIV_32;
cfg.scan_conv_mode = false;
cfg.continuous_conv_mode = false;
cfg.differential_mode = false;
cfg.resolution = ADC_RESOLUTION_16B;
cfg.vref = ADC_VREF_2P0V;
struct bflb_adc_channel_s chan;
chan.pos_chan = ADC_CHANNEL_TSEN_P;
chan.neg_chan = ADC_CHANNEL_GND;
bflb_adc_init(adc, &cfg);
bflb_adc_channel_config(adc, &chan, 1);
bflb_adc_tsen_init(adc, ADC_TSEN_MOD_INTERNAL_DIODE);
for (i = 0; i < 50; i++) {
average_filter += bflb_adc_tsen_get_temp(adc);
bflb_mtimer_delay_ms(10);
}
printf("temp = %d\r\n", (uint32_t)(average_filter / 50.0));
return 0;
}
SHELL_CMD_EXPORT(temp, get CPU Temp)
int voltage(int argc, char **argv) {
struct bflb_device_s *adc = bflb_device_get_by_name("adc");
/* adc clock = XCLK / 2 / 32 */
struct bflb_adc_config_s cfg;
cfg.clk_div = ADC_CLK_DIV_32;
cfg.scan_conv_mode = false;
cfg.continuous_conv_mode = false;
cfg.differential_mode = false;
cfg.resolution = ADC_RESOLUTION_16B;
cfg.vref = ADC_VREF_3P2V;
struct bflb_adc_channel_s chan;
chan.pos_chan = ADC_CHANNEL_VABT_HALF;
chan.neg_chan = ADC_CHANNEL_GND;
bflb_adc_init(adc, &cfg);
bflb_adc_channel_config(adc, &chan, 1);
bflb_adc_vbat_enable(adc);
struct bflb_adc_result_s result;
bflb_adc_start_conversion(adc);
while (bflb_adc_get_count(adc) == 0) {
bflb_mtimer_delay_ms(1);
}
uint32_t raw_data = bflb_adc_read_raw(adc);
bflb_adc_parse_result(adc, &raw_data, &result, 1);
printf("vBat = %d mV\r\n", (uint32_t)(result.millivolt * 2));
bflb_adc_stop_conversion(adc);
bflb_adc_vbat_disable(adc);
return 0;
}
SHELL_CMD_EXPORT(voltage, get Voltage)

60
m0/src/console.c Normal file
View file

@ -0,0 +1,60 @@
#include <stdarg.h>
#include <bflb_core.h>
#include <FreeRTOS.h>
#include <semphr.h>
#include <shell.h>
#include <ring_buffer.h>
#include "console.h"
#include "usb_uart.h"
static TaskHandle_t usbuart_handle;
SemaphoreHandle_t usbuart_sem = NULL;
Ring_Buffer_Type usbuart_rb;
static void shell_task(void *pvParameters)
{
uint8_t data;
uint32_t len;
while (1) {
if (xSemaphoreTake(usbuart_sem, portMAX_DELAY) == pdTRUE) {
len = Ring_Buffer_Get_Length(&usbuart_rb);
for (uint32_t i = 0; i < len; i++) {
Ring_Buffer_Read_Byte(&usbuart_rb, &data);
shell_handler(data);
}
}
}
}
void usbuart_read(uint8_t uart, char *data, uint32_t len)
{
Ring_Buffer_Write(&usbuart_rb, (const uint8_t *)data, len);
xSemaphoreGive(usbuart_sem);
}
void usbuartprintf(char *fmt, ...) {
char buf[256];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
vuart_write(0, buf, strlen(buf));
}
/* implemented in the Shell Component of BFBL_SDK */
//extern void shell_init_with_task(struct bflb_device_s *shell);
extern int shell_set_print(void (*shell_printf)(char *fmt, ...));
void console_init() {
/* start a UART Shell */
struct bflb_device_s *uart0 = bflb_device_get_by_name("uart0");
shell_set_prompt("0x64>");
shell_init_with_task(uart0);
//shell_init();
//shell_set_print(usbuartprintf);
//vSemaphoreCreateBinary(usbuart_sem);
//xTaskCreate(shell_task, (char *)"usbuart_shell", SHELL_THREAD_STACK_SIZE, NULL, SHELL_THREAD_PRIO, &usbuart_handle);
}

35
m0/src/flash.c Normal file
View file

@ -0,0 +1,35 @@
#include "bflb_flash.h"
#include "usbd_dfu.h"
#include "log.h"
// uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len)
// {
// LOG_I("DFU Read %lx %lx %ld\r\n", src, dest, len);
// uint32_t i = 0;
// uint8_t *psrc = src;
// for (i = 0; i < len; i++) {
// dest[i] = *psrc++;
// }
// /* Return a valid address to avoid HardFault */
// return (uint8_t *)(dest);
// }
// uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len)
// {
// LOG_I("DFU Write %lx %lx %ld\r\n", src, dest, len);
// return 0;
// }
// uint16_t dfu_erase_flash(uint32_t add)
// {
// LOG_I("DFU Erase %lx\r\n", add);
// return 0;
// }
// void dfu_leave(void)
// {
// LOG_I("DFU Leave\r\n");
// dfu_reset();
// }

88
m0/src/main.c Normal file
View file

@ -0,0 +1,88 @@
#include <bl808_glb.h>
#include <bflb_mtimer.h>
#include <bflb_flash.h>
#ifdef CONFIG_TLSF
#include <bflb_tlsf.h>
#endif
#include <bflb_gpio.h>
#include <board.h>
#include <log.h>
#include <FreeRTOS.h>
#include <semphr.h>
#include <usbh_core.h>
#include "console.h"
extern void cdc_acm_multi_init(void);
// static uint8_t freertos_heap[configTOTAL_HEAP_SIZE];
// static HeapRegion_t xHeapRegions[] = {
// { (uint8_t *)freertos_heap, 0 },
// { NULL, 0 }, /* Terminates the array. */
// { NULL, 0 } /* Terminates the array. */
// };
extern uint32_t __start;
int main(void)
{
board_init();
struct bflb_device_s *gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(gpio, GPIO_PIN_12, GPIO_ALTERNATE | GPIO_FUNC_JTAG_M0);
bflb_gpio_init(gpio, GPIO_PIN_13, GPIO_ALTERNATE | GPIO_FUNC_JTAG_M0);
bflb_gpio_init(gpio, GPIO_PIN_6, GPIO_ALTERNATE | GPIO_FUNC_JTAG_M0);
bflb_gpio_init(gpio, GPIO_PIN_7, GPIO_ALTERNATE | GPIO_FUNC_JTAG_M0);
#ifdef CONFIG_TLSF
void *ptr = meminfo();
#endif
void *ptr2 = temp();
LOG_I("Starting 0x64_coproc on %d at 0x%08lx\r\n", GLB_Get_Core_Type(), __start);
LOG_I("Flash Offset at 0x%08lx\r\n", bflb_flash_get_image_offset());
cdc_acm_multi_init();
LOG_I("USB Running\r\n");
#ifdef CONFIG_TLSF
bflb_tlsf_size_container_t *tlsf_size = bflb_tlsf_stats();
printf("Memory: Total: %dKb, Used: %dKb Free: %dKb\r\n", (tlsf_size->free + tlsf_size->used)/1024, tlsf_size->used/1024, tlsf_size->free/1024);
#endif
LOG_I("FreeRTOS Scheduler Starting\r\n");
console_init();
LOG_I("Console Started\r\n");
pt_table_set_flash_operation(bflb_flash_erase, bflb_flash_write, bflb_flash_read);
pt_table_dump();
vTaskStartScheduler();
/* we should never get here */
}
// void vApplicationMallocFailedHook( void )
// {
// /* Called if a call to pvPortMalloc() fails because there is insufficient
// free memory available in the FreeRTOS heap. pvPortMalloc() is called
// internally by FreeRTOS API functions that create tasks, queues, software
// timers, and semaphores. The size of the FreeRTOS heap is set by the
// configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */
// LOG_E("Malloc Failed\r\n");
// bflb_mtimer_delay_ms(500);
// /* Force an assert. */
// configASSERT( ( volatile void * ) NULL );
// }
// /*-----------------------------------------------------------*/
// void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
// {
// ( void ) pcTaskName;
// ( void ) pxTask;
// /* Run time stack overflow checking is performed if
// configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
// function is called if a stack overflow is detected. */
// LOG_E("Stack Overflow\r\n");
// bflb_mtimer_delay_ms(500);
// /* Force an assert. */
// configASSERT( ( volatile void * ) NULL );
// }

542
m0/src/partition.c Normal file
View file

@ -0,0 +1,542 @@
/**
******************************************************************************
* @file partition.c
* @version V1.0
* @date
* @brief This file is the standard driver c file
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2019 Bouffalo Lab</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#include "bflb_core.h"
#include "partition.h"
#include "softcrc.h"
#include "log.h"
/** @addtogroup BFLB_Common_Driver
* @{
*/
/** @addtogroup PARTITION
* @{
*/
/** @defgroup PARTITION_Private_Macros
* @{
*/
/*@} end of group PARTITION_Private_Macros */
/** @defgroup PARTITION_Private_Types
* @{
*/
/*@} end of group PARTITION_Private_Types */
/** @defgroup PARTITION_Private_Variables
* @{
*/
p_pt_table_flash_erase gp_pt_table_flash_erase = NULL;
p_pt_table_flash_write gp_pt_table_flash_write = NULL;
p_pt_table_flash_read gp_pt_table_flash_read = NULL;
pt_table_iap_param_type p_iap_param;
/*@} end of group PARTITION_Private_Variables */
/** @defgroup PARTITION_Global_Variables
* @{
*/
extern int main(void);
/*@} end of group PARTITION_Global_Variables */
/** @defgroup PARTITION_Private_Fun_Declaration
* @{
*/
/*@} end of group PARTITION_Private_Fun_Declaration */
/** @defgroup PARTITION_Private_Functions
* @{
*/
/****************************************************************************/ /**
* @brief Judge partition table valid
*
* @param ptStuff: Partition table stuff pointer
*
* @return 0 for invalid and 1 for valid
*
*******************************************************************************/
static uint8_t pt_table_valid(pt_table_stuff_config *pt_stuff)
{
pt_table_config *pt_table = &pt_stuff->pt_table;
pt_table_entry_config *pt_entries = pt_stuff->pt_entries;
uint32_t *p_crc32;
uint32_t entriesLen = sizeof(pt_table_entry_config) * pt_table->entryCnt;
if (pt_table->magicCode == BFLB_PT_MAGIC_CODE) {
if (pt_table->entryCnt > PT_ENTRY_MAX) {
LOG_F("PT Entry Count Error\r\n");
return 0;
}
if (pt_table->crc32 !=
BFLB_Soft_CRC32((uint8_t *)pt_table, sizeof(pt_table_config) - 4)) {
LOG_F("PT CRC Error\r\n");
return 0;
}
/* ToDo it is a trap here, when entryCnt > 8, crc32 will overflow, comment by zhangcheng */
p_crc32 = (uint32_t *)((uintptr_t)pt_entries + entriesLen);
if (*p_crc32 != BFLB_Soft_CRC32((uint8_t *)pt_entries, entriesLen)) {
LOG_F("PT Entry CRC Error\r\n");
return 0;
}
return 1;
}
LOG_F("PT Invalid Partition Magic: %08lx\r\n", pt_table->magicCode);
return 0;
}
/*@} end of group PARTITION_Private_Functions */
/** @defgroup PARTITION_Public_Functions
* @{
*/
/****************************************************************************/ /**
* @brief Register partition flash read write erase fucntion
*
* @param erase: Flash erase function
* @param write: Flash write function
* @param read: Flash read function
*
* @return None
*
*******************************************************************************/
void pt_table_set_flash_operation(p_pt_table_flash_erase erase, p_pt_table_flash_write write, p_pt_table_flash_read read)
{
gp_pt_table_flash_erase = erase;
gp_pt_table_flash_write = write;
gp_pt_table_flash_read = read;
}
/****************************************************************************/ /**
* @brief Get active partition table whole stuff
*
* @param ptStuff[2]: Partition table stuff pointer
*
* @return Active partition table ID
*
*******************************************************************************/
pt_table_id_type pt_table_get_active_partition_need_lock(pt_table_stuff_config ptStuff[2])
{
uint32_t pt_valid[2] = { 0, 0 };
pt_table_id_type activePtID;
if (ptStuff == NULL) {
return PT_TABLE_ID_INVALID;
}
activePtID = PT_TABLE_ID_INVALID;
gp_pt_table_flash_read(BFLB_PT_TABLE0_ADDRESS, (uint8_t *)&ptStuff[0], sizeof(pt_table_stuff_config));
pt_valid[0] = pt_table_valid(&ptStuff[0]);
gp_pt_table_flash_read(BFLB_PT_TABLE1_ADDRESS, (uint8_t *)&ptStuff[1], sizeof(pt_table_stuff_config));
pt_valid[1] = pt_table_valid(&ptStuff[1]);
if (pt_valid[0] == 1 && pt_valid[1] == 1) {
if (ptStuff[0].pt_table.age >= ptStuff[1].pt_table.age) {
activePtID = PT_TABLE_ID_0;
} else {
activePtID = PT_TABLE_ID_1;
}
} else if (pt_valid[0] == 1) {
activePtID = PT_TABLE_ID_0;
} else if (pt_valid[1] == 1) {
activePtID = PT_TABLE_ID_1;
}
return activePtID;
}
/****************************************************************************/ /**
* @brief Get partition entry according to entry ID
*
* @param ptStuff: Partition table stuff pointer
* @param type: Type of partition entry
* @param ptEntry: Partition entry pointer to store read data
*
* @return PT_ERROR_SUCCESS or PT_ERROR_ENTRY_NOT_FOUND or PT_ERROR_PARAMETER
*
*******************************************************************************/
pt_table_error_type pt_table_get_active_entries_by_id(pt_table_stuff_config *pt_stuff,
pt_table_entry_type type,
pt_table_entry_config *pt_entry)
{
uint32_t i = 0;
if (pt_stuff == NULL || pt_entry == NULL) {
return PT_ERROR_PARAMETER;
}
for (i = 0; i < pt_stuff->pt_table.entryCnt; i++) {
if (pt_stuff->pt_entries[i].type == type) {
ARCH_MemCpy_Fast(pt_entry, &pt_stuff->pt_entries[i], sizeof(pt_table_entry_config));
return PT_ERROR_SUCCESS;
}
}
return PT_ERROR_ENTRY_NOT_FOUND;
}
/****************************************************************************/ /**
* @brief Get partition entry according to entry name
*
* @param ptStuff: Partition table stuff pointer
* @param name: Name of partition entry
* @param ptEntry: Partition entry pointer to store read data
*
* @return PT_ERROR_SUCCESS or PT_ERROR_ENTRY_NOT_FOUND or PT_ERROR_PARAMETER
*
*******************************************************************************/
pt_table_error_type pt_table_get_active_entries_by_name(pt_table_stuff_config *pt_stuff,
uint8_t *name,
pt_table_entry_config *pt_entry)
{
uint32_t i = 0;
uint32_t len = strlen((char *)name);
if (pt_stuff == NULL || pt_entry == NULL) {
return PT_ERROR_PARAMETER;
}
for (i = 0; i < pt_stuff->pt_table.entryCnt; i++) {
if (strlen((char *)pt_stuff->pt_entries[i].name) == len &&
memcmp((char *)pt_stuff->pt_entries[i].name, (char *)name, len) == 0) {
ARCH_MemCpy_Fast(pt_entry, &pt_stuff->pt_entries[i], sizeof(pt_table_entry_config));
return PT_ERROR_SUCCESS;
}
}
return PT_ERROR_ENTRY_NOT_FOUND;
}
/****************************************************************************/ /**
* @brief Update partition entry
*
* @param targetTableID: Target partition table to update
* @param ptStuff: Partition table stuff pointer
* @param ptEntry: Partition entry pointer to update
*
* @return Partition update result
*
*******************************************************************************/
pt_table_error_type pt_table_update_entry(pt_table_id_type target_table_id,
pt_table_stuff_config *pt_stuff,
pt_table_entry_config *pt_entry)
{
uint32_t i = 0;
BL_Err_Type ret;
uint32_t write_addr;
uint32_t entries_len;
pt_table_config *pt_table;
pt_table_entry_config *pt_entries;
uint32_t *crc32;
if (pt_entry == NULL || pt_stuff == NULL) {
return PT_ERROR_PARAMETER;
}
pt_table = &pt_stuff->pt_table;
pt_entries = pt_stuff->pt_entries;
if (target_table_id == PT_TABLE_ID_INVALID) {
return PT_ERROR_TABLE_NOT_VALID;
}
if (target_table_id == PT_TABLE_ID_0) {
write_addr = BFLB_PT_TABLE0_ADDRESS;
} else {
write_addr = BFLB_PT_TABLE1_ADDRESS;
}
for (i = 0; i < pt_table->entryCnt; i++) {
if (pt_entries[i].type == pt_entry->type) {
ARCH_MemCpy_Fast(&pt_entries[i], pt_entry, sizeof(pt_table_entry_config));
break;
}
}
if (i == pt_table->entryCnt) {
/* Not found this entry ,add new one */
if (pt_table->entryCnt < PT_ENTRY_MAX) {
ARCH_MemCpy_Fast(&pt_entries[pt_table->entryCnt], pt_entry, sizeof(pt_table_entry_config));
pt_table->entryCnt++;
} else {
return PT_ERROR_ENTRY_UPDATE_FAIL;
}
}
/* Prepare write back to flash */
/* Update age */
pt_table->age++;
pt_table->crc32 = BFLB_Soft_CRC32((uint8_t *)pt_table, sizeof(pt_table_config) - 4);
/* Update entries CRC */
entries_len = pt_table->entryCnt * sizeof(pt_table_entry_config);
crc32 = (uint32_t *)((uintptr_t)pt_entries + entries_len);
*crc32 = BFLB_Soft_CRC32((uint8_t *)&pt_entries[0], entries_len);
/* Write back to flash */
/* Erase flash first */
//ret = gp_pt_table_flash_erase(write_addr, write_addr + sizeof(pt_table_config) + entries_len + 4 - 1);
ret = gp_pt_table_flash_erase(write_addr, sizeof(pt_table_config) + entries_len + 4);
if (ret != SUCCESS) {
//LOG_D_ERR("Flash Erase error\r\n");
return PT_ERROR_FALSH_WRITE;
}
/* Write flash */
ret = gp_pt_table_flash_write(write_addr, (uint8_t *)pt_stuff, sizeof(pt_table_stuff_config));
if (ret != SUCCESS) {
//LOG_D_ERR("Flash Write error\r\n");
return PT_ERROR_FALSH_WRITE;
}
return PT_ERROR_SUCCESS;
}
/****************************************************************************/ /**
* @brief Create partition entry
*
* @param ptID: Partition table ID
*
* @return Partition create result
*
*******************************************************************************/
pt_table_error_type pt_table_create(pt_table_id_type pt_id)
{
uint32_t write_addr;
BL_Err_Type ret;
pt_table_config pt_table;
if (pt_id == PT_TABLE_ID_INVALID) {
return PT_ERROR_TABLE_NOT_VALID;
}
if (pt_id == PT_TABLE_ID_0) {
write_addr = BFLB_PT_TABLE0_ADDRESS;
} else {
write_addr = BFLB_PT_TABLE1_ADDRESS;
}
/* Prepare write back to flash */
pt_table.magicCode = BFLB_PT_MAGIC_CODE;
pt_table.version = 0;
pt_table.entryCnt = 0;
pt_table.age = 0;
pt_table.crc32 = BFLB_Soft_CRC32((uint8_t *)&pt_table, sizeof(pt_table_config) - 4);
/* Write back to flash */
//ret = gp_pt_table_flash_erase(write_addr, write_addr + sizeof(pt_table_config) - 1);
ret = gp_pt_table_flash_erase(write_addr, sizeof(pt_table_config));
if (ret != SUCCESS) {
//LOG_D_ERR("Flash Erase error\r\n");
return PT_ERROR_FALSH_ERASE;
}
ret = gp_pt_table_flash_write(write_addr, (uint8_t *)&pt_table, sizeof(pt_table_config));
if (ret != SUCCESS) {
//LOG_D_ERR("Flash Write error\r\n");
return PT_ERROR_FALSH_WRITE;
}
return PT_ERROR_SUCCESS;
}
pt_table_error_type pt_table_dump(void)
{
uint32_t pt_valid[2] = { 0, 0 };
pt_table_stuff_config pt_stuff[2];
gp_pt_table_flash_read(BFLB_PT_TABLE0_ADDRESS, (uint8_t *)&pt_stuff[0], sizeof(pt_table_stuff_config));
pt_valid[0] = pt_table_valid(&pt_stuff[0]);
gp_pt_table_flash_read(BFLB_PT_TABLE1_ADDRESS, (uint8_t *)&pt_stuff[1], sizeof(pt_table_stuff_config));
pt_valid[1] = pt_table_valid(&pt_stuff[1]);
if (pt_valid[0]) {
LOG_F("PT TABLE0 (%x) valid\r\n", BFLB_PT_TABLE0_ADDRESS);
} else {
LOG_F("PT TABLE0 (%x) invalid\r\n", BFLB_PT_TABLE0_ADDRESS);
}
if (pt_valid[1]) {
LOG_F("PT TABLE1 (%x) valid\r\n", BFLB_PT_TABLE1_ADDRESS);
} else {
LOG_F("PT TABLE1 (%x) invalid\r\n", BFLB_PT_TABLE1_ADDRESS);
}
for (int i = 0; i < 2; i++) {
if (pt_valid[i] == 1) {
LOG_F("ptStuff[%d].pt_table.magicCode 0x%08x\r\n", i, pt_stuff[i].pt_table.magicCode);
LOG_F("ptStuff[%d].pt_table.version 0x%08x\r\n", i, pt_stuff[i].pt_table.version);
LOG_F("ptStuff[%d].pt_table.entryCnt 0x%08x\r\n", i, pt_stuff[i].pt_table.entryCnt);
LOG_F("ptStuff[%d].pt_table.age 0x%08x\r\n", i, pt_stuff[i].pt_table.age);
LOG_F("ptStuff[%d].pt_table.crc32 0x%08x\r\n", i, pt_stuff[i].pt_table.crc32);
for (int j = 0; j < pt_stuff[i].pt_table.entryCnt; j++) {
LOG_F("ptStuff[%d].pt_entries[%d].type 0x%08x\r\n", i, j, pt_stuff[i].pt_entries[j].type);
LOG_F("ptStuff[%d].pt_entries[%d].name %s\r\n", i, j, pt_stuff[i].pt_entries[j].name);
LOG_F("ptStuff[%d].pt_entries[%d].device 0x%08x\r\n", i, j, pt_stuff[i].pt_entries[j].device);
LOG_F("ptStuff[%d].pt_entries[%d].active_index 0x%08x\r\n", i, j, pt_stuff[i].pt_entries[j].active_index);
LOG_F("ptStuff[%d].pt_entries[%d].Address[0] 0x%08x\r\n", i, j, pt_stuff[i].pt_entries[j].start_address[0]);
LOG_F("ptStuff[%d].pt_entries[%d].Address[1] 0x%08x\r\n", i, j, pt_stuff[i].pt_entries[j].start_address[1]);
LOG_F("ptStuff[%d].pt_entries[%d].maxLen[0] 0x%08x\r\n", i, j, pt_stuff[i].pt_entries[j].max_len[0]);
LOG_F("ptStuff[%d].pt_entries[%d].maxLen[1] 0x%08x\r\n", i, j, pt_stuff[i].pt_entries[j].max_len[1]);
LOG_F("ptStuff[%d].pt_entries[%d].len 0x%08x\r\n", i, j, pt_stuff[i].pt_entries[j].len);
LOG_F("ptStuff[%d].pt_entries[%d].age 0x%08x\r\n", i, j, pt_stuff[i].pt_entries[j].age);
}
}
}
return PT_ERROR_SUCCESS;
}
pt_table_error_type pt_table_get_iap_para(pt_table_iap_param_type *para)
{
uint32_t pt_valid[2] = { 0, 0 };
pt_table_stuff_config pt_stuff[2];
uint8_t active_index;
gp_pt_table_flash_read(BFLB_PT_TABLE0_ADDRESS, (uint8_t *)&pt_stuff[0], sizeof(pt_table_stuff_config));
pt_valid[0] = pt_table_valid(&pt_stuff[0]);
gp_pt_table_flash_read(BFLB_PT_TABLE1_ADDRESS, (uint8_t *)&pt_stuff[1], sizeof(pt_table_stuff_config));
pt_valid[1] = pt_table_valid(&pt_stuff[1]);
if ((pt_valid[0] == 1) && (pt_valid[1] == 1)) {
if (pt_stuff[0].pt_table.age >= pt_stuff[1].pt_table.age) {
active_index = pt_stuff[0].pt_entries[0].active_index;
para->iap_write_addr = para->iap_start_addr = pt_stuff[0].pt_entries[0].start_address[!(active_index & 0x01)];
para->inactive_index = !(active_index & 0x01);
para->inactive_table_index = 1;
} else {
active_index = pt_stuff[1].pt_entries[0].active_index;
para->iap_write_addr = para->iap_start_addr = pt_stuff[1].pt_entries[0].start_address[!(active_index & 0x01)];
para->inactive_index = !(active_index & 0x01);
para->inactive_table_index = 0;
}
} else if (pt_valid[1] == 1) {
active_index = pt_stuff[1].pt_entries[0].active_index;
para->iap_write_addr = para->iap_start_addr = pt_stuff[1].pt_entries[0].start_address[!(active_index & 0x01)];
para->inactive_index = !(active_index & 0x01);
para->inactive_table_index = 0;
} else if (pt_valid[0] == 1) {
active_index = pt_stuff[0].pt_entries[0].active_index;
para->iap_write_addr = para->iap_start_addr = pt_stuff[0].pt_entries[0].start_address[!(active_index & 0x01)];
para->inactive_index = !(active_index & 0x01);
para->inactive_table_index = 1;
} else {
return PT_ERROR_TABLE_NOT_VALID;
}
LOG_F("inactive_table_index %d, inactive index %d , IAP start addr %08x \r\n", para->inactive_table_index, para->inactive_index, para->iap_start_addr);
return PT_ERROR_SUCCESS;
}
pt_table_error_type pt_table_set_iap_para(pt_table_iap_param_type *para)
{
pt_table_stuff_config pt_stuff, pt_stuff_write;
int32_t ret;
uint32_t *p_crc32;
uint32_t entries_len;
if (para->inactive_table_index == 1) {
gp_pt_table_flash_read(BFLB_PT_TABLE0_ADDRESS, (uint8_t *)&pt_stuff, sizeof(pt_table_stuff_config));
} else if (para->inactive_table_index == 0) {
gp_pt_table_flash_read(BFLB_PT_TABLE1_ADDRESS, (uint8_t *)&pt_stuff, sizeof(pt_table_stuff_config));
}
ARCH_MemCpy_Fast((void *)&pt_stuff_write, (void *)&pt_stuff, sizeof(pt_table_stuff_config));
pt_stuff_write.pt_table.age += 1;
pt_stuff_write.pt_entries[0].active_index = !(pt_stuff_write.pt_entries[0].active_index & 0x01);
pt_stuff_write.pt_table.crc32 = BFLB_Soft_CRC32((uint8_t *)&pt_stuff_write, sizeof(pt_table_config) - 4);
entries_len = sizeof(pt_table_entry_config) * pt_stuff_write.pt_table.entryCnt;
//pt_stuff_write.crc32 = BFLB_Soft_CRC32((uint8_t*)pt_stuff_write.pt_entries,entries_len);
p_crc32 = (uint32_t *)((uintptr_t)pt_stuff_write.pt_entries + entries_len);
*p_crc32 = BFLB_Soft_CRC32((uint8_t *)pt_stuff_write.pt_entries, entries_len);
if (para->inactive_table_index == 1) {
//ret = gp_pt_table_flash_erase(BFLB_PT_TABLE1_ADDRESS, BFLB_PT_TABLE1_ADDRESS + sizeof(pt_table_stuff_config) - 1);
ret = gp_pt_table_flash_erase(BFLB_PT_TABLE1_ADDRESS, sizeof(pt_table_stuff_config));
if (ret != SUCCESS) {
//LOG_D_ERR("Flash Erase error\r\n");
return PT_ERROR_FALSH_ERASE;
}
ret = gp_pt_table_flash_write(BFLB_PT_TABLE1_ADDRESS, (uint8_t *)&pt_stuff_write, sizeof(pt_table_stuff_config));
if (ret != SUCCESS) {
//LOG_D_ERR("Flash Write error\r\n");
return PT_ERROR_FALSH_WRITE;
}
} else if (para->inactive_table_index == 0) {
//ret = gp_pt_table_flash_erase(BFLB_PT_TABLE0_ADDRESS, BFLB_PT_TABLE0_ADDRESS + sizeof(pt_table_stuff_config) - 1);
ret = gp_pt_table_flash_erase(BFLB_PT_TABLE0_ADDRESS, sizeof(pt_table_stuff_config));
if (ret != SUCCESS) {
//LOG_D_ERR("Flash Erase error\r\n");
return PT_ERROR_FALSH_ERASE;
}
ret = gp_pt_table_flash_write(BFLB_PT_TABLE0_ADDRESS, (uint8_t *)&pt_stuff_write, sizeof(pt_table_stuff_config));
if (ret != SUCCESS) {
//LOG_D_ERR("Flash Write error\r\n");
return PT_ERROR_FALSH_WRITE;
}
}
LOG_F("Update pt_table suss\r\n");
return PT_ERROR_SUCCESS;
}
/*@} end of group PARTITION_Public_Functions */
/*@} end of group PARTITION */
/*@} end of group BFLB_Common_Driver */

209
m0/src/softcrc.c Normal file
View file

@ -0,0 +1,209 @@
/**
* *****************************************************************************
* @file softcrc.c
* @version 1.0
* @date 2022-11-23
* @brief
* *****************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* *****************************************************************************
*/
#include <errno.h>
#include <stdarg.h>
#include "bflb_core.h"
#include "softcrc.h"
// ---------------- POPULAR POLYNOMIALS ----------------
// CCITT: x^16 + x^12 + x^5 + x^0 (0x1021,init 0x0000)
// CRC-16: x^16 + x^15 + x^2 + x^0 (0x8005,init 0xFFFF)
// we use 0x8005 here and
const uint8_t chCRCHTalbe[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40
};
const uint8_t chCRCLTalbe[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
0x41, 0x81, 0x80, 0x40
};
uint16_t BFLB_Soft_CRC16(void *dataIn, uint32_t len)
{
uint8_t chCRCHi = 0xFF;
uint8_t chCRCLo = 0xFF;
uint16_t wIndex;
uint8_t *data = (uint8_t *)dataIn;
while (len--) {
wIndex = chCRCLo ^ *data++;
chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];
chCRCHi = chCRCLTalbe[wIndex];
}
return ((chCRCHi << 8) | chCRCLo);
}
/*
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
*/
const uint32_t crc32Tab[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t BFLB_Soft_CRC32_Table(void *dataIn, uint32_t len)
{
uint32_t crc = 0;
uint8_t *data = (uint8_t *)dataIn;
crc = crc ^ 0xffffffff;
while (len--) {
crc = crc32Tab[(crc ^ *data++) & 0xFF] ^ (crc >> 8);
}
return crc ^ 0xffffffff;
}
/******************************************************************************
* Name: CRC-32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
* Poly: 0x4C11DB7
* Init: 0xFFFFFFF
* Refin: True
* Refout: True
* Xorout: 0xFFFFFFF
* Alias: CRC_32/ADCCP
* Use: WinRAR,ect.
*****************************************************************************/
uint32_t ATTR_TCM_SECTION BFLB_Soft_CRC32_Ex(uint32_t initial, void *dataIn, uint32_t len)
{
uint8_t i;
uint32_t crc = ~initial; // Initial value
uint8_t *data = (uint8_t *)dataIn;
while (len--) {
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i) {
if (crc & 1) {
crc = (crc >> 1) ^ 0xEDB88320; // 0xEDB88320= reverse 0x04C11DB7
} else {
crc = (crc >> 1);
}
}
}
return ~crc;
}
#ifndef BFLB_USE_ROM_DRIVER
__WEAK
uint32_t ATTR_TCM_SECTION BFLB_Soft_CRC32(void *dataIn, uint32_t len)
{
return BFLB_Soft_CRC32_Ex(0, dataIn, len);
}
#endif

397
m0/src/usb_descriptors.c Normal file
View file

@ -0,0 +1,397 @@
#include <usbd_core.h>
#include <usbd_cdc.h>
#include <log.h>
#include "usbd_dfu.h"
//#include "usb_uart.h"
/*!< endpoint address */
/* v-uart1 */
#define CDC_IN_EP1 0x81
#define CDC_OUT_EP1 0x02
#define CDC_INT_EP1 0x83
/* v-uart2 */
#define CDC_IN_EP2 0x82
#define CDC_OUT_EP2 0x03
#define CDC_INT_EP2 0x84
#if 0
/* v-uart 3*/
#define CDC_IN_EP3 0x83
#define CDC_OUT_EP3 0x04
#define CDC_INT_EP3 0x86
/* v-uart 4 */
#define CDC_IN_EP4 0x84
#define CDC_OUT_EP4 0x04
#define CDC_INT_EP4 0x88
#endif
#define USBD_VID 0x000F
#define USBD_PID 0xFFFF
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[3][256];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[3][256];
typedef void (*vuart_readcb)(uint8_t uart, char *data, uint32_t len);
typedef struct cdc_endpoints {
uint8_t uart;
uint8_t inep;
uint8_t outep;
uint8_t intep;
uint8_t *rdbuf;
uint8_t *wrbuf;
vuart_readcb readcb;
bool tx_busy;
} cdc_endpoints;
cdc_endpoints *get_vuart(uint8_t ep);
void vuart_write(uint8_t uart, char *buf, uint8_t len) {
volatile cdc_endpoints *cdcep = get_vuart(uart);
if (cdcep == NULL) {
LOG_W("Invalid vUART %d\r\n", uart);
return;
}
LOG_I("Sending (%d) %d\r\n", uart, len);
memcpy(cdcep->wrbuf, buf, len);
cdcep->tx_busy = true;
usbd_ep_start_write(cdcep->inep, cdcep->wrbuf, len);
}
void vuart_read(uint8_t uart, char *data, uint32_t len) {
char buf[256];
strlcpy(buf, data, MIN(len+1, 256));
LOG_I("Read (%d): %s - %d %d\r\n", uart, buf, MIN(len, 2047), len);
}
cdc_endpoints vuart[] = {
{1, CDC_IN_EP1, CDC_OUT_EP1, CDC_INT_EP1, read_buffer[0], write_buffer[0], &vuart_read, false},
{2, CDC_IN_EP2, CDC_OUT_EP2, CDC_INT_EP2, read_buffer[1], write_buffer[1], &vuart_read, false},
// {3, CDC_IN_EP3, CDC_OUT_EP3, CDC_INT_EP3, read_buffer[2], write_buffer[2], &vuart_read, false},
};
cdc_endpoints *get_vuart_outep(uint8_t ep) {
for (uint8_t i = 0; i < (sizeof(vuart)/sizeof(vuart[0])); i++) {
if (vuart[i].outep == ep)
return &vuart[i];
}
return NULL;
};
cdc_endpoints *get_vuart_inep(uint8_t ep) {
for (uint8_t i = 0; i < (sizeof(vuart)/sizeof(vuart[0])); i++) {
if (vuart[i].inep == ep)
return &vuart[i];
}
return NULL;
};
cdc_endpoints *get_vuart(uint8_t uart) {
for (uint8_t i = 0; i < (sizeof(vuart)/sizeof(vuart[0])); i++) {
if (vuart[i].uart == uart)
return &vuart[i];
}
return NULL;
};
/*!< config descriptor size */
/* 3 devices */
#define USB_CONFIG_SIZE (9 + 9 + 9 + (CDC_ACM_DESCRIPTOR_LEN * 1))
/*!< global descriptor */
static const uint8_t cdc_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, USB_DEVICE_CLASS_MISC, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT((0x09 + 0x12 + (CDC_ACM_DESCRIPTOR_LEN * 2)), 0x05, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
DFU_DESCRIPTOR_INIT(),
CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP1, CDC_OUT_EP1, CDC_IN_EP1, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x03, CDC_INT_EP2, CDC_OUT_EP2, CDC_IN_EP2, 0x02),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
USB_LANGID_INIT(USBD_LANGID_STRING),
///////////////////////////////////////
/// string1 descriptor
///////////////////////////////////////
0x0E, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'P', 0x00, /* wcChar0 */
'I', 0x00, /* wcChar1 */
'N', 0x00, /* wcChar2 */
'E', 0x00, /* wcChar3 */
'6', 0x00, /* wcChar4 */
'4', 0x00, /* wcChar5 */
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x0A, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'O', 0x00, /* wcChar0 */
'x', 0x00, /* wcChar1 */
'6', 0x00, /* wcChar2 */
'4', 0x00, /* wcChar3 */
///////////////////////////////////////
/// string3 descriptor
///////////////////////////////////////
0x16, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'1', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'2', 0x00, /* wcChar3 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
'6', 0x00, /* wcChar9 */
///////////////////////////////////////
/// string4 descriptor - 0x58 000 000
///////////////////////////////////////
0x56, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'@', 0x00, /* wcChar0 */
'M', 0x00, /* wcChar1 */
'0', 0x00, /* wcChar2 */
' ', 0x00, /* wcChar3 */
'F', 0x00, /* wcChar4 */
'l', 0x00, /* wcChar5 */
'a', 0x00, /* wcChar6 */
's', 0x00, /* wcChar7 */
'h', 0x00, /* wcChar8 */
' ', 0x00, /* wcChar17 */
' ', 0x00, /* wcChar17 */
' ', 0x00, /* wcChar17 */
' ', 0x00, /* wcChar17 */
'/', 0x00, /* wcChar18 */
'0', 0x00, /* wcChar19 */
'x', 0x00, /* wcChar20 */
'5', 0x00, /* wcChar21*/
'8', 0x00, /* wcChar22 */
'0', 0x00, /* wcChar23 */
'0', 0x00, /* wcChar24 */
'0', 0x00, /* wcChar25 */
'0', 0x00, /* wcChar26 */
'0', 0x00, /* wcChar27 */
'0', 0x00, /* wcChar28 */
'/', 0x00, /* wcChar29 */
'9', 0x00, /* wcChar30 */
'9', 0x00, /* wcChar31*/
'*', 0x00, /* wcChar32 */
'0', 0x00, /* wcChar33 */
'0', 0x00, /* wcChar34 */
'1', 0x00, /* wcChar35 */
'K', 0x00, /* wcChar36 */
'g', 0x00, /* wcChar37 */
',', 0x00, /* wcChar38 */
'1', 0x00, /* wcChar39 */
'1', 0x00, /* wcChar40 */
'2', 0x00, /* wcChar41*/
'*', 0x00, /* wcChar42 */
'0', 0x00, /* wcChar43 */
'1', 0x00, /* wcChar44 */
'K', 0x00, /* wcChar45 */
'g', 0x00, /* wcChar46 */
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
// 0x0a,
// USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
// 0x00,
// 0x02,
// 0x02,
// 0x02,
// 0x01,
// 0x40,
// 0x01,
// 0x00,
0x09, // len
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, // bDescriptorType
0x00, // bcdUSB
0xEF, // bDeviceClass
0x02, // bDeviceSubClass
0x01, // bDeviceProtocol
0x40, // bMaxPacketSize0
0x01, // bNumConfigurations
0x00,
#endif
0x00
};
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
void usbd_configure_done_callback(void)
{
/* setup first out ep read transfer */
for (uint8_t i = 0; i < (sizeof(vuart)/sizeof(vuart[0])); i++) {
LOG_I("Configure CDCEP: UART:%d IN:%d OUT:%d INT:%d RDptr:%p Wptr:%p\r\n", vuart[i].uart, vuart[i].inep, vuart[i].outep, vuart[i].intep, vuart[i].rdbuf, vuart[i].wrbuf);
usbd_ep_start_read(vuart[i].outep, vuart[i].rdbuf, 256);
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
{
volatile cdc_endpoints *cdcep = get_vuart_outep(ep);
if (cdcep == NULL) {
LOG_W("Invalid CDC Endpoint %d\r\n", ep);
return;
}
LOG_I("actual out len:%d ep: %d\r\n", nbytes, ep);
cdcep->readcb(cdcep->uart, (char *)cdcep->rdbuf, nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(cdcep->outep, cdcep->rdbuf, 256);
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
{
volatile cdc_endpoints *cdcep = get_vuart_inep(ep);
if (cdcep == NULL) {
LOG_W("Invalid CDC Endpoint %d\r\n", ep);
return;
}
LOG_I("actual in len:%d ep:%d\r\n", nbytes, ep);
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(cdcep->inep, NULL, 0);
} else {
cdcep->tx_busy = false;
}
}
/*!< endpoint call back */
struct usbd_endpoint cdc_out_ep1 = {
.ep_addr = CDC_OUT_EP1,
.ep_cb = usbd_cdc_acm_bulk_out
};
struct usbd_endpoint cdc_in_ep1 = {
.ep_addr = CDC_IN_EP1,
.ep_cb = usbd_cdc_acm_bulk_in
};
struct usbd_endpoint cdc_out_ep2 = {
.ep_addr = CDC_OUT_EP2,
.ep_cb = usbd_cdc_acm_bulk_out
};
struct usbd_endpoint cdc_in_ep2 = {
.ep_addr = CDC_IN_EP2,
.ep_cb = usbd_cdc_acm_bulk_in
};
#if 0
struct usbd_endpoint cdc_out_ep3 = {
.ep_addr = CDC_OUT_EP3,
.ep_cb = usbd_cdc_acm_bulk_out
};
struct usbd_endpoint cdc_in_ep3 = {
.ep_addr = CDC_IN_EP3,
.ep_cb = usbd_cdc_acm_bulk_in
};
#endif
struct usbd_interface intf0;
struct usbd_interface intf1;
struct usbd_interface intf2;
struct usbd_interface intf3;
struct usbd_interface intf4;
#if 0
struct usbd_interface intf5;
#endif
/* function ------------------------------------------------------------------*/
void cdc_acm_multi_init(void)
{
usbd_desc_register(cdc_descriptor);
/* DFU First */
usbd_add_interface(usbd_dfu_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf2));
usbd_add_endpoint(&cdc_out_ep1);
usbd_add_endpoint(&cdc_in_ep1);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf3));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf4));
usbd_add_endpoint(&cdc_out_ep2);
usbd_add_endpoint(&cdc_in_ep2);
#if 0
usbd_add_interface(usbd_cdc_acm_init_intf(&intf4));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf5));
usbd_add_endpoint(&cdc_out_ep3);
usbd_add_endpoint(&cdc_in_ep3);
#endif
usbd_initialize();
}
volatile uint8_t dtr_enable = 0;
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
{
LOG_I("DTR Change %d %d\r\n", intf, dtr);
if (dtr) {
dtr_enable = 1;
} else {
dtr_enable = 0;
}
}
void usbd_cdc_acm_set_rts(uint8_t intf, bool rts) {
LOG_I("RTS Change %d %d\r\n", intf, rts);
}
void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_coding) {
LOG_I("Line Coding Change %d %d %d %d\r\n", intf, line_coding->dwDTERate, line_coding->bCharFormat, line_coding->bParityType, line_coding->bDataBits);
}
uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len)
{
LOG_I("DFU Read %lx %lx %ld\r\n", src, dest, len);
uint32_t i = 0;
uint8_t *psrc = src;
for (i = 0; i < len; i++) {
dest[i] = *psrc++;
}
/* Return a valid address to avoid HardFault */
return (uint8_t *)(dest);
}
uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len)
{
LOG_I("DFU Write %lx %lx %ld\r\n", src, dest, len);
return 0;
}
uint16_t dfu_erase_flash(uint32_t add)
{
LOG_I("DFU Erase %lx\r\n", add);
return 0;
}
void dfu_leave(void)
{
LOG_I("DFU Leave\r\n");
dfu_reset();
}

508
m0/src/usbd_dfu.c Normal file
View file

@ -0,0 +1,508 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_dfu.h"
#include "log.h"
/** Modify the following three parameters according to different platforms */
// #ifndef USBD_DFU_XFER_SIZE
// #define USBD_DFU_XFER_SIZE 256
// #endif
#ifndef USBD_DFU_APP_DEFAULT_ADD
#define USBD_DFU_APP_DEFAULT_ADD 0x58000000
#endif
#ifndef FLASH_PROGRAM_TIME
#define FLASH_PROGRAM_TIME 50
#endif
#ifndef FLASH_ERASE_TIME
#define FLASH_ERASE_TIME 50
#endif
struct dfu_cfg_priv {
// struct dfu_info info;
union {
uint32_t d32[USBD_DFU_XFER_SIZE / 4U];
uint8_t d8[USBD_DFU_XFER_SIZE];
} buffer;
uint32_t wblock_num;
uint32_t wlength;
uint32_t data_ptr;
uint32_t alt_setting;
uint8_t dev_status[6];
uint8_t ReservedForAlign[2];
uint8_t dev_state;
uint8_t manif_state;
uint8_t firmwar_flag;
} usbd_dfu_cfg;
void dfu_reset(void)
{
memset(&usbd_dfu_cfg, 0, sizeof(usbd_dfu_cfg));
usbd_dfu_cfg.alt_setting = 0U;
usbd_dfu_cfg.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
usbd_dfu_cfg.wblock_num = 0U;
usbd_dfu_cfg.wlength = 0U;
usbd_dfu_cfg.manif_state = DFU_MANIFEST_COMPLETE;
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[5] = 0U;
}
static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
{
switch (cmd) {
case DFU_MEDIA_PROGRAM:
buffer[1] = (uint8_t)FLASH_PROGRAM_TIME;
buffer[2] = (uint8_t)(FLASH_PROGRAM_TIME << 8);
buffer[3] = 0;
break;
case DFU_MEDIA_ERASE:
buffer[1] = (uint8_t)FLASH_ERASE_TIME;
buffer[2] = (uint8_t)(FLASH_ERASE_TIME << 8);
buffer[3] = 0;
default:
break;
}
return (0);
}
static void dfu_request_detach(void)
{
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
/* Update the state machine */
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
usbd_dfu_cfg.dev_status[5] = 0U; /*iString*/
usbd_dfu_cfg.wblock_num = 0U;
usbd_dfu_cfg.wlength = 0U;
}
}
static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
struct usb_setup_packet *req = setup;
uint32_t addr;
/* Data setup request */
if (req->wLength > 0U) {
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
/* Update the global length and block number */
usbd_dfu_cfg.wblock_num = req->wValue;
usbd_dfu_cfg.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
LOG_I("upload Size %d %d\r\n", usbd_dfu_cfg.wlength, req->wLength);
/* DFU Get Command */
if (usbd_dfu_cfg.wblock_num == 0U) {
/* Update the state machine */
usbd_dfu_cfg.dev_state = (usbd_dfu_cfg.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
/* Store the values of all supported commands */
usbd_dfu_cfg.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
usbd_dfu_cfg.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
usbd_dfu_cfg.buffer.d8[2] = DFU_CMD_ERASE;
/* Send the status data over EP0 */
*data = usbd_dfu_cfg.buffer.d8;
*len = 3;
} else if (usbd_dfu_cfg.wblock_num > 1U) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
addr = ((usbd_dfu_cfg.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + usbd_dfu_cfg.data_ptr;
/* Return the physical address where data are stored */
dfu_read_flash((uint8_t *)addr, usbd_dfu_cfg.buffer.d8, usbd_dfu_cfg.wlength);
/* Send the status data over EP0 */
*data = usbd_dfu_cfg.buffer.d8;
*len = usbd_dfu_cfg.wlength;
} else /* unsupported usbd_dfu_cfg.wblock_num */
{
usbd_dfu_cfg.dev_state = DFU_STATUS_ERR_STALLEDPKT;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
/* Call the error management function (command will be NAKed */
LOG_E("Dfu_request_upload unsupported usbd_dfu_cfg.wblock_num\r\n");
}
}
/* Unsupported state */
else {
usbd_dfu_cfg.wlength = 0U;
usbd_dfu_cfg.wblock_num = 0U;
/* Call the error management function (command will be NAKed */
LOG_E("Dfu_request_upload unsupported state\r\n");
}
}
/* No Data setup request */
else {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
}
}
static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/* Data setup request */
struct usb_setup_packet *req = setup;
if (req->wLength > 0U) {
LOG_I("State %d\r\n", usbd_dfu_cfg.dev_state);
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
/* Update the global length and block number */
usbd_dfu_cfg.wblock_num = req->wValue;
usbd_dfu_cfg.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
LOG_I("download Size %d %d\r\n", usbd_dfu_cfg.wlength, req->wLength);
/* Update the state machine */
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
/*!< Data has received complete */
memcpy((uint8_t *)usbd_dfu_cfg.buffer.d8, (uint8_t *)*data, usbd_dfu_cfg.wlength);
/*!< Set flag = 1 Write the firmware to the flash in the next dfu_request_getstatus */
usbd_dfu_cfg.firmwar_flag = 1;
}
/* Unsupported state */
else {
LOG_E("Dfu_request_dnload unsupported state\r\n");
}
}
/* 0 Data DNLOAD request */
else {
/* End of DNLOAD operation*/
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE)) {
usbd_dfu_cfg.manif_state = DFU_MANIFEST_IN_PROGRESS;
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
} else {
/* Call the error management function (command will be NAKed */
LOG_E("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", usbd_dfu_cfg.dev_state);
}
}
}
static int8_t dfu_getstatus_special_handler(void)
{
uint32_t addr;
if (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
/* Decode the Special Command */
if (usbd_dfu_cfg.wblock_num == 0U) {
if (usbd_dfu_cfg.wlength == 1U) {
if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
/* Nothing to do */
}
} else if (usbd_dfu_cfg.wlength == 5U) {
if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
usbd_dfu_cfg.data_ptr = usbd_dfu_cfg.buffer.d8[1];
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[2] << 8;
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[3] << 16;
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[4] << 24;
} else if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_ERASE) {
usbd_dfu_cfg.data_ptr = usbd_dfu_cfg.buffer.d8[1];
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[2] << 8;
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[3] << 16;
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[4] << 24;
LOG_I("Erase start add %08x \r\n", usbd_dfu_cfg.data_ptr);
/*!< Erase */
dfu_erase_flash(usbd_dfu_cfg.data_ptr);
} else {
return -1;
}
} else {
/* Reset the global length and block number */
usbd_dfu_cfg.wlength = 0U;
usbd_dfu_cfg.wblock_num = 0U;
/* Call the error management function (command will be NAKed) */
LOG_E("Reset the global length and block number\r\n");
}
}
/* Regular Download Command */
else {
if (usbd_dfu_cfg.wblock_num > 1U) {
/* Decode the required address */
addr = ((usbd_dfu_cfg.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + usbd_dfu_cfg.data_ptr;
/* Perform the write operation */
/* Write flash */
LOG_I("Write start add %08x length %d\r\n", addr, usbd_dfu_cfg.wlength);
dfu_write_flash(usbd_dfu_cfg.buffer.d8, (uint8_t *)addr, usbd_dfu_cfg.wlength);
}
}
/* Reset the global length and block number */
usbd_dfu_cfg.wlength = 0U;
usbd_dfu_cfg.wblock_num = 0U;
/* Update the state machine */
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
}
return 0;
}
static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/*!< Determine whether to leave DFU mode */
if (usbd_dfu_cfg.manif_state == DFU_MANIFEST_IN_PROGRESS &&
usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
usbd_dfu_cfg.dev_status[1] == 0U &&
usbd_dfu_cfg.dev_status[2] == 0U &&
usbd_dfu_cfg.dev_status[3] == 0U &&
usbd_dfu_cfg.dev_status[4] == usbd_dfu_cfg.dev_state) {
usbd_dfu_cfg.manif_state = DFU_MANIFEST_COMPLETE;
if ((0x0B & DFU_MANIFEST_MASK) != 0U) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
return;
} else {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
/* Generate system reset to allow jumping to the user code */
dfu_leave();
}
}
switch (usbd_dfu_cfg.dev_state) {
case DFU_STATE_DFU_DNLOAD_SYNC:
if (usbd_dfu_cfg.wlength != 0U) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
if ((usbd_dfu_cfg.wblock_num == 0U) && (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_ERASE)) {
dfu_getstatus(usbd_dfu_cfg.data_ptr, DFU_MEDIA_ERASE, usbd_dfu_cfg.dev_status);
} else {
dfu_getstatus(usbd_dfu_cfg.data_ptr, DFU_MEDIA_PROGRAM, usbd_dfu_cfg.dev_status);
}
} else /* (usbd_dfu_cfg.wlength==0)*/
{
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
}
break;
case DFU_STATE_DFU_MANIFEST_SYNC:
if (usbd_dfu_cfg.manif_state == DFU_MANIFEST_IN_PROGRESS) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST;
usbd_dfu_cfg.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
} else {
if ((usbd_dfu_cfg.manif_state == DFU_MANIFEST_COMPLETE) &&
((0x0B & DFU_MANIFEST_MASK) != 0U)) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
}
}
break;
default:
break;
}
/* Send the status data over EP0 */
uint8_t temp_data[6];
memcpy(temp_data, usbd_dfu_cfg.dev_status, 6);
*data = temp_data;
*len = 6;
if (usbd_dfu_cfg.firmwar_flag == 1) {
if (dfu_getstatus_special_handler() != 0) {
LOG_E("dfu_getstatus_special_handler error \r\n");
}
usbd_dfu_cfg.firmwar_flag = 0;
}
}
static void dfu_request_clrstatus(void)
{
if (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_ERROR) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK; /* bStatus */
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state; /* bState */
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
} else {
/* State Error */
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_ERROR;
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state; /* bState */
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
}
}
static void dfu_request_getstate(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/* Return the current state of the DFU interface */
*data = &usbd_dfu_cfg.dev_state;
*len = 1;
}
void dfu_request_abort(void)
{
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
usbd_dfu_cfg.wblock_num = 0U;
usbd_dfu_cfg.wlength = 0U;
}
}
static int dfu_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
LOG_I("DFU Class request: "
"bRequest 0x%02x len %d\r\n",
setup->bRequest, len);
switch (setup->bRequest) {
case DFU_REQUEST_DETACH:
dfu_request_detach();
break;
case DFU_REQUEST_DNLOAD:
dfu_request_dnload(setup, data, len);
break;
case DFU_REQUEST_UPLOAD:
dfu_request_upload(setup, data, len);
break;
case DFU_REQUEST_GETSTATUS:
dfu_request_getstatus(setup, data, len);
break;
case DFU_REQUEST_CLRSTATUS:
dfu_request_clrstatus();
break;
case DFU_REQUEST_GETSTATE:
dfu_request_getstate(setup, data, len);
break;
case DFU_REQUEST_ABORT:
dfu_request_abort();
break;
default:
LOG_E("Unhandled DFU Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
static void dfu_notify_handler(uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
dfu_reset();
break;
default:
break;
}
}
struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf)
{
intf->class_interface_handler = dfu_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = dfu_notify_handler;
return intf;
}
__WEAK uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len)
{
return dest;
}
__WEAK uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len)
{
return 0;
}
__WEAK uint16_t dfu_erase_flash(uint32_t add)
{
return 0;
}
__WEAK void dfu_leave(void)
{
}