Compare commits
48 Commits
v1.6.0
...
v1.5.3-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c746f57ddc | ||
|
|
3882560646 | ||
|
|
9cf680148e | ||
|
|
e25c12f6a8 | ||
|
|
f09198704b | ||
|
|
af519ac42c | ||
|
|
c34cbc5bfb | ||
|
|
38dff565cf | ||
|
|
6067343775 | ||
|
|
6c34938883 | ||
|
|
7cd4ff71d7 | ||
|
|
999ddb1a9d | ||
|
|
01b22bb138 | ||
|
|
e0dc9c9890 | ||
|
|
6105d7a1d6 | ||
|
|
757187e967 | ||
|
|
a33396fa93 | ||
|
|
ab8efcb07d | ||
|
|
5c9550d00e | ||
|
|
c8a713a49a | ||
|
|
87c49f9359 | ||
|
|
6e8a63fd77 | ||
|
|
71a966bbd5 | ||
|
|
32cf0e0b3c | ||
|
|
88b1158b4f | ||
|
|
38a4c5e375 | ||
|
|
b758fa814a | ||
|
|
9730f63b2c | ||
|
|
0365aa0d63 | ||
|
|
649ad6686b | ||
|
|
868dbee668 | ||
|
|
84b1d3feeb | ||
|
|
1045f877c8 | ||
|
|
12694eed49 | ||
|
|
ed344579ff | ||
|
|
c3b01eed25 | ||
|
|
f087e0777a | ||
|
|
82487c80aa | ||
|
|
86e9422e06 | ||
|
|
6c239e175f | ||
|
|
1b973b5cc5 | ||
|
|
102af3be37 | ||
|
|
347df77372 | ||
|
|
778465654b | ||
|
|
e2791c7d04 | ||
|
|
7902c1c352 | ||
|
|
1768079a89 | ||
|
|
c77557510e |
83
.github/workflows/build_tests.yml
vendored
Normal file
83
.github/workflows/build_tests.yml
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
name: Build Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release/v1.5
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- release/v1.5
|
||||
|
||||
jobs:
|
||||
build_hpmicro:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get install -y cmake ninja-build
|
||||
|
||||
- name: Download hpm_sdk
|
||||
run: |
|
||||
cd ~
|
||||
git clone https://github.com/hpmicro/hpm_sdk.git
|
||||
|
||||
- name: Download RISC-V toolchain
|
||||
run: |
|
||||
cd ~
|
||||
wget https://github.com/hpmicro/riscv-gnu-toolchain/releases/download/2023.10.18/rv32imac_zicsr_zifencei_multilib_b_ext-linux.tar.gz
|
||||
tar -xzf rv32imac_zicsr_zifencei_multilib_b_ext-linux.tar.gz
|
||||
|
||||
- name: Build hpm demo
|
||||
run: |
|
||||
cd tests/hpmicro
|
||||
export HPM_SDK_BASE=~/hpm_sdk
|
||||
export GNURISCV_TOOLCHAIN_PATH=~/rv32imac_zicsr_zifencei_multilib_b_ext-linux
|
||||
export HPM_SDK_TOOLCHAIN_VARIANT=
|
||||
cmake -S . -B build -GNinja -DBOARD=hpm6800evk -DHPM_BUILD_TYPE=flash_sdram_xip -DCMAKE_BUILD_TYPE=debug -DEXTRA_C_FLAGS="-Werror";cmake --build build
|
||||
|
||||
build_bouffalolab:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get install -y cmake make
|
||||
|
||||
- name: Download bouffalo_sdk
|
||||
run: |
|
||||
cd ~
|
||||
git clone https://github.com/bouffalolab/bouffalo_sdk.git
|
||||
|
||||
- name: Download RISC-V toolchain
|
||||
run: |
|
||||
cd ~
|
||||
git clone https://github.com/bouffalolab/toolchain_gcc_t-head_linux.git
|
||||
|
||||
- name: Build bouffalo demo
|
||||
run: |
|
||||
cd tests/bouffalolab
|
||||
export BL_SDK_BASE=~/bouffalo_sdk
|
||||
export PATH=~/toolchain_gcc_t-head_linux/bin:$PATH
|
||||
make CHIP=bl616 BOARD=bl616dk -j12
|
||||
|
||||
build_espressif:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
runs-on: ubuntu-latest
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Build espressif demo
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager ruamel.yaml idf-build-apps --upgrade
|
||||
idf-build-apps build -p ./tests/espressif --recursive --target esp32s3
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.vscode
|
||||
build
|
||||
**/Drivers/**
|
||||
**/MDK-ARM/DebugConfig/**
|
||||
**/MDK-ARM/RTE/**
|
||||
|
||||
@@ -64,6 +64,14 @@ elseif(ESP_PLATFORM)
|
||||
|
||||
idf_component_get_property(freertos_include freertos ORIG_INCLUDE_PATH)
|
||||
|
||||
if(CONFIG_CHERRYUSB_HOST_MSC)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/platform/idf/usbh_fatfs.c)
|
||||
endif()
|
||||
|
||||
set(priv_req esp_mm esp_netif esp_timer fatfs)
|
||||
if(${IDF_VERSION_MAJOR} LESS 6)
|
||||
list(APPEND priv_req usb)
|
||||
endif()
|
||||
idf_component_register(
|
||||
SRCS
|
||||
${cherryusb_srcs}
|
||||
@@ -71,7 +79,7 @@ elseif(ESP_PLATFORM)
|
||||
${cherryusb_incs}
|
||||
${freertos_include}
|
||||
PRIV_REQUIRES
|
||||
usb esp_mm esp_netif esp_timer
|
||||
${priv_req}
|
||||
LDFRAGMENTS
|
||||
${ldfragments}
|
||||
)
|
||||
|
||||
2
Kconfig
2
Kconfig
@@ -118,6 +118,7 @@ if CHERRYUSB
|
||||
config CHERRYUSB_DEVICE_CDC_NCM
|
||||
bool
|
||||
prompt "Enable usb cdc ncm device"
|
||||
depends on !IDF_CMAKE
|
||||
default n
|
||||
|
||||
config CHERRYUSB_DEVICE_MTP
|
||||
@@ -338,6 +339,7 @@ if CHERRYUSB
|
||||
config CHERRYUSB_HOST_BLUETOOTH
|
||||
bool
|
||||
prompt "Enable usb bluetooth driver"
|
||||
depends on !IDF_CMAKE
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_ASIX
|
||||
|
||||
@@ -465,12 +465,14 @@ if PKG_USING_CHERRYUSB
|
||||
|
||||
choice
|
||||
prompt "Version"
|
||||
default PKG_USING_CHERRYUSB_V010502
|
||||
default PKG_USING_CHERRYUSB_V010503
|
||||
help
|
||||
Select the package version
|
||||
|
||||
config PKG_USING_CHERRYUSB_LATEST_VERSION
|
||||
bool "latest"
|
||||
config PKG_USING_CHERRYUSB_V010502
|
||||
bool "v1.5.3"
|
||||
config PKG_USING_CHERRYUSB_V010502
|
||||
bool "v1.5.2"
|
||||
config PKG_USING_CHERRYUSB_V010501
|
||||
@@ -490,6 +492,7 @@ if PKG_USING_CHERRYUSB
|
||||
config PKG_CHERRYUSB_VER
|
||||
string
|
||||
default "latest" if PKG_USING_CHERRYUSB_LATEST_VERSION
|
||||
default "v1.5.3" if PKG_USING_CHERRYUSB_V010503
|
||||
default "v1.5.2" if PKG_USING_CHERRYUSB_V010502
|
||||
default "v1.5.1" if PKG_USING_CHERRYUSB_V010501
|
||||
default "v1.5.0" if PKG_USING_CHERRYUSB_V010500
|
||||
|
||||
@@ -197,7 +197,7 @@ TODO
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Official |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0 | Official |
|
||||
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Official |
|
||||
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Official ongoing |
|
||||
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)/[espressif](https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb)|<= latest | Official |
|
||||
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/k230_sdk)|v1.2.0 | Official |
|
||||
|Actionstech | ATS30xx | dwc2 |[action_zephyr_repo](https://github.com/CherryUSB/lv_port_actions_technology/tree/master/action_technology_sdk)|>=1.4.0 | Official |
|
||||
|SiFli | SF32LB5x | musb |[SiFli_sdk](https://github.com/OpenSiFli/SiFli-SDK)|>=1.5.0 | Official |
|
||||
|
||||
@@ -197,7 +197,7 @@ TODO
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Official |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0 | Official |
|
||||
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Official |
|
||||
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Official ongoing |
|
||||
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)/[espressif](https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb)|<= latest | Official |
|
||||
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/k230_sdk)|v1.2.0 | Official |
|
||||
|Actionstech | ATS30xx | dwc2 |[action_zephyr_repo](https://github.com/CherryUSB/lv_port_actions_technology/tree/master/action_technology_sdk)|>=1.4.0 | Official |
|
||||
|SiFli | SF32LB5x | musb |[SiFli_sdk](https://github.com/OpenSiFli/SiFli-SDK)|>=1.5.0 | Official |
|
||||
|
||||
2
VERSION
2
VERSION
@@ -1,5 +1,5 @@
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 5
|
||||
PATCHLEVEL = 2
|
||||
PATCHLEVEL = 3
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION = 0
|
||||
|
||||
@@ -340,6 +340,10 @@ if(CONFIG_CHERRYUSB_HOST)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYUSB_DEVICE AND CONFIG_CHERRYUSB_HOST)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbotg_core.c)
|
||||
endif()
|
||||
|
||||
if(DEFINED CONFIG_CHERRYUSB_OSAL)
|
||||
if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_freertos.c)
|
||||
|
||||
@@ -301,6 +301,7 @@
|
||||
/* ---------------- MUSB Configuration ---------------- */
|
||||
#define CONFIG_USB_MUSB_PIPE_NUM 8
|
||||
// #define CONFIG_USB_MUSB_SUNXI
|
||||
// #define CONFIG_USB_MUSB_WITHOUT_MULTIPOINT
|
||||
|
||||
/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode,
|
||||
* the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS.
|
||||
@@ -317,4 +318,7 @@
|
||||
#define usb_ramaddr2phyaddr(addr) (addr)
|
||||
#endif
|
||||
|
||||
/* Enable OTG support, only support hpmicro now */
|
||||
// #define CONFIG_USB_OTG_ENABLE
|
||||
|
||||
#endif
|
||||
|
||||
@@ -176,9 +176,6 @@ int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *repo
|
||||
int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
uint8_t len;
|
||||
uint32_t offset;
|
||||
|
||||
if (!aoa_class || !aoa_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
@@ -198,7 +195,6 @@ int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *ev
|
||||
static int usbh_aoa_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_aoa *aoa_class = &g_aoa_class;
|
||||
|
||||
|
||||
@@ -266,11 +266,20 @@ const struct usbh_class_driver cdc_data_class_driver = {
|
||||
.disconnect = usbh_cdc_data_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_none_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
|
||||
.bInterfaceSubClass = CDC_ABSTRACT_CONTROL_MODEL,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE,
|
||||
.id_table = NULL,
|
||||
.class_driver = &cdc_acm_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_at_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
|
||||
.bInterfaceSubClass = CDC_ABSTRACT_CONTROL_MODEL,
|
||||
.bInterfaceProtocol = CDC_COMMON_PROTOCOL_AT_COMMANDS,
|
||||
.id_table = NULL,
|
||||
.class_driver = &cdc_acm_class_driver
|
||||
};
|
||||
|
||||
@@ -106,7 +106,6 @@ static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
{
|
||||
struct usb_setup_packet *req = setup;
|
||||
uint32_t addr;
|
||||
uint8_t *phaddr;
|
||||
/* Data setup request */
|
||||
if (req->wLength > 0U) {
|
||||
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
|
||||
@@ -143,7 +142,7 @@ static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
|
||||
|
||||
/* Return the physical address where data are stored */
|
||||
phaddr = dfu_read_flash((uint8_t *)addr, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
|
||||
dfu_read_flash((uint8_t *)addr, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
|
||||
|
||||
/* Send the status data over EP0 */
|
||||
memcpy(*data, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
|
||||
|
||||
@@ -106,7 +106,7 @@ int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
|
||||
if (ret < 8) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hid_buf[hid_class->minor], MIN(ret - 8, 1));
|
||||
memcpy(buffer, g_hid_buf[hid_class->minor], MIN((uint32_t)ret - 8, 1));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ int usbh_hid_get_protocol(struct usbh_hid *hid_class, uint8_t *protocol)
|
||||
if (ret < 8) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(protocol, g_hid_buf[hid_class->minor], MIN(ret - 8, 1));
|
||||
memcpy(protocol, g_hid_buf[hid_class->minor], MIN((uint32_t)ret - 8, 1));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t
|
||||
if (ret < 8) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hid_buf[hid_class->minor], MIN(ret - 8, buflen));
|
||||
memcpy(buffer, g_hid_buf[hid_class->minor], MIN((uint32_t)ret - 8, buflen));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -373,6 +373,11 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
hub->tt_think = ((hub->hub_desc.wHubCharacteristics & HUB_CHAR_TTTT_MASK) >> 5);
|
||||
}
|
||||
|
||||
if (hub->nports > CONFIG_USBHOST_MAX_EHPORTS) {
|
||||
USB_LOG_ERR("Hub nports %u overflow\r\n", hub->nports);
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hub->child[port].port = port + 1;
|
||||
hub->child[port].parent = hub;
|
||||
@@ -708,7 +713,6 @@ int usbh_hub_deinitialize(struct usbh_bus *bus)
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_hub *hub;
|
||||
size_t flags;
|
||||
|
||||
hub = &bus->hcd.roothub;
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
@@ -717,14 +721,10 @@ int usbh_hub_deinitialize(struct usbh_bus *bus)
|
||||
usbh_hubport_release(hport);
|
||||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
usb_hc_deinit(bus);
|
||||
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
usb_osal_mq_delete(bus->hub_mq);
|
||||
usb_osal_thread_delete(bus->hub_thread);
|
||||
usb_osal_mq_delete(bus->hub_mq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
6
class/vendor/net/usbh_rtl8152.c
vendored
6
class/vendor/net/usbh_rtl8152.c
vendored
@@ -1034,17 +1034,17 @@ static int generic_ocp_read(struct usbh_rtl8152 *tp, uint16_t index, uint16_t si
|
||||
static int generic_ocp_write(struct usbh_rtl8152 *tp, uint16_t index, uint16_t byteen,
|
||||
uint16_t size, void *data, uint16_t type)
|
||||
{
|
||||
int ret;
|
||||
int ret = -USB_ERR_INVAL;
|
||||
uint16_t byteen_start, byteen_end, byen;
|
||||
uint16_t limit = 512;
|
||||
uint8_t *buf = data;
|
||||
|
||||
/* both size and indix must be 4 bytes align */
|
||||
if ((size & 3) || !size || (index & 3) || !buf)
|
||||
return -USB_ERR_INVAL;
|
||||
return ret;
|
||||
|
||||
if ((uint32_t)index + (uint32_t)size > 0xffff)
|
||||
return -USB_ERR_INVAL;
|
||||
return ret;
|
||||
|
||||
byteen_start = byteen & BYTE_EN_START_MASK;
|
||||
byteen_end = byteen & BYTE_EN_END_MASK;
|
||||
|
||||
@@ -122,12 +122,12 @@ int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class)
|
||||
return usbh_video_get(video_class, VIDEO_REQUEST_GET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
}
|
||||
|
||||
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
|
||||
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwFrameInterval)
|
||||
{
|
||||
video_class->probe.bFormatIndex = formatindex;
|
||||
video_class->probe.bFrameIndex = frameindex;
|
||||
video_class->probe.dwMaxPayloadTransferSize = 0;
|
||||
video_class->probe.dwFrameInterval = 333333;
|
||||
video_class->probe.dwFrameInterval = dwFrameInterval;
|
||||
return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
|
||||
}
|
||||
|
||||
@@ -136,7 +136,6 @@ int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t f
|
||||
memcpy(&video_class->commit, &video_class->probe, sizeof(struct video_probe_and_commit_controls));
|
||||
video_class->commit.bFormatIndex = formatindex;
|
||||
video_class->commit.bFrameIndex = frameindex;
|
||||
video_class->commit.dwFrameInterval = 333333;
|
||||
return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
|
||||
}
|
||||
|
||||
@@ -154,6 +153,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
bool found = false;
|
||||
uint8_t formatidx = 0;
|
||||
uint8_t frameidx = 0;
|
||||
uint32_t dwDefaultFrameInterval = 0;
|
||||
uint8_t step;
|
||||
|
||||
if (!video_class || !video_class->hport) {
|
||||
@@ -172,6 +172,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
if ((wWidth == video_class->format[i].frame[j].wWidth) &&
|
||||
(wHeight == video_class->format[i].frame[j].wHeight)) {
|
||||
frameidx = j + 1;
|
||||
dwDefaultFrameInterval = video_class->format[i].frame[j].dwDefaultFrameInterval;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -204,7 +205,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
}
|
||||
|
||||
step = 1;
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx, dwDefaultFrameInterval);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
@@ -228,7 +229,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
}
|
||||
|
||||
step = 5;
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
|
||||
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx, dwDefaultFrameInterval);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
@@ -246,26 +247,30 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
}
|
||||
|
||||
step = 8;
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = altsetting;
|
||||
setup->wIndex = video_class->data_intf;
|
||||
setup->wLength = 0;
|
||||
if (!video_class->is_bulk) {
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = altsetting;
|
||||
setup->wIndex = video_class->data_intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
ret = usbh_control_transfer(video_class->hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[altsetting].ep[0].ep_desc;
|
||||
mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
|
||||
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
video_class->isoin_mps = mps * (mult + 1);
|
||||
USBH_EP_INIT(video_class->isoin, ep_desc);
|
||||
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[altsetting].ep[0].ep_desc;
|
||||
mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
|
||||
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
video_class->isoin_mps = mps * (mult + 1);
|
||||
USBH_EP_INIT(video_class->isoin, ep_desc);
|
||||
} else {
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
} else {
|
||||
video_class->isoout_mps = mps * (mult + 1);
|
||||
USBH_EP_INIT(video_class->isoout, ep_desc);
|
||||
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[0].ep[0].ep_desc;
|
||||
USBH_EP_INIT(video_class->bulkin, ep_desc);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Open video and select formatidx:%u, frameidx:%u, altsetting:%u\r\n", formatidx, frameidx, altsetting);
|
||||
@@ -292,54 +297,62 @@ int usbh_video_close(struct usbh_video *video_class)
|
||||
|
||||
video_class->is_opened = false;
|
||||
|
||||
if (video_class->isoin) {
|
||||
video_class->isoin = NULL;
|
||||
if (video_class->is_bulk) {
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_ENDPOINT;
|
||||
setup->bRequest = USB_REQUEST_CLEAR_FEATURE;
|
||||
setup->wValue = USB_FEATURE_ENDPOINT_HALT;
|
||||
setup->wIndex = video_class->bulkin->bEndpointAddress;
|
||||
setup->wLength = 0;
|
||||
} else {
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = video_class->data_intf;
|
||||
setup->wLength = 0;
|
||||
}
|
||||
|
||||
if (video_class->isoout) {
|
||||
video_class->isoout = NULL;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = video_class->data_intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(video_class->hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_video_list_info(struct usbh_video *video_class)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
uint8_t mult;
|
||||
uint16_t mps;
|
||||
|
||||
USB_LOG_INFO("============= Video device information ===================\r\n");
|
||||
USB_LOG_RAW("bcdVDC:%04x\r\n", video_class->bcdVDC);
|
||||
USB_LOG_RAW("Num of altsettings:%u\r\n", video_class->num_of_intf_altsettings);
|
||||
USB_LOG_RAW("Num of altsettings:%u (%s mode)\r\n", video_class->num_of_intf_altsettings, video_class->num_of_intf_altsettings == 1 ? "bulk" : "iso");
|
||||
|
||||
for (uint8_t i = 0; i < video_class->num_of_intf_altsettings; i++) {
|
||||
if (i == 0) {
|
||||
USB_LOG_RAW("Ingore altsetting 0\r\n");
|
||||
continue;
|
||||
video_class->is_bulk = video_class->num_of_intf_altsettings == 1 ? true : false;
|
||||
|
||||
if (video_class->is_bulk) {
|
||||
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[0].ep[0].ep_desc;
|
||||
USB_LOG_RAW("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
|
||||
ep_desc->bEndpointAddress,
|
||||
ep_desc->bmAttributes,
|
||||
USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize),
|
||||
ep_desc->bInterval,
|
||||
USB_GET_MULT(ep_desc->wMaxPacketSize));
|
||||
} else {
|
||||
for (uint8_t i = 0; i < video_class->num_of_intf_altsettings; i++) {
|
||||
if (i == 0) {
|
||||
USB_LOG_RAW("Ingore altsetting 0\r\n");
|
||||
continue;
|
||||
}
|
||||
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[i].ep[0].ep_desc;
|
||||
|
||||
USB_LOG_RAW("Altsetting:%u, Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
|
||||
i,
|
||||
ep_desc->bEndpointAddress,
|
||||
ep_desc->bmAttributes,
|
||||
USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize),
|
||||
ep_desc->bInterval,
|
||||
USB_GET_MULT(ep_desc->wMaxPacketSize));
|
||||
}
|
||||
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[i].ep[0].ep_desc;
|
||||
|
||||
mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
|
||||
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
|
||||
USB_LOG_RAW("Altsetting:%u, Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
|
||||
i,
|
||||
ep_desc->bEndpointAddress,
|
||||
ep_desc->bmAttributes,
|
||||
mps,
|
||||
ep_desc->bInterval,
|
||||
mult);
|
||||
}
|
||||
|
||||
USB_LOG_RAW("bNumFormats:%u\r\n", video_class->num_of_formats);
|
||||
@@ -350,9 +363,10 @@ void usbh_video_list_info(struct usbh_video *video_class)
|
||||
USB_LOG_RAW(" Resolution:\r\n");
|
||||
for (uint8_t j = 0; j < video_class->format[i].num_of_frames; j++) {
|
||||
USB_LOG_RAW(" FrameIndex:%u\r\n", j + 1);
|
||||
USB_LOG_RAW(" wWidth: %d, wHeight: %d\r\n",
|
||||
video_class->format[i].frame[j].wWidth,
|
||||
video_class->format[i].frame[j].wHeight);
|
||||
USB_LOG_RAW(" wWidth: %d, wHeight: %d, fps: %d\r\n",
|
||||
video_class->format[i].frame[j].wWidth,
|
||||
video_class->format[i].frame[j].wHeight,
|
||||
(1000 / (video_class->format[i].frame[j].dwDefaultFrameInterval / 10000)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,12 +452,14 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
video_class->format[format_index - 1].frame[frame_index - 1].wWidth = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->wWidth;
|
||||
video_class->format[format_index - 1].frame[frame_index - 1].wHeight = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->wHeight;
|
||||
video_class->format[format_index - 1].frame[frame_index - 1].dwDefaultFrameInterval = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->dwDefaultFrameInterval;
|
||||
break;
|
||||
case VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE:
|
||||
frame_index = p[DESC_bFrameIndex];
|
||||
|
||||
video_class->format[format_index - 1].frame[frame_index - 1].wWidth = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->wWidth;
|
||||
video_class->format[format_index - 1].frame[frame_index - 1].wHeight = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->wHeight;
|
||||
video_class->format[format_index - 1].frame[frame_index - 1].dwDefaultFrameInterval = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->dwDefaultFrameInterval;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -476,12 +492,6 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usbh_video *video_class = (struct usbh_video *)hport->config.intf[intf].priv;
|
||||
|
||||
if (video_class) {
|
||||
if (video_class->isoin) {
|
||||
}
|
||||
|
||||
if (video_class->isoout) {
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
usb_osal_thread_schedule_other();
|
||||
USB_LOG_INFO("Unregister Video Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
struct usbh_video_resolution {
|
||||
uint16_t wWidth;
|
||||
uint16_t wHeight;
|
||||
uint32_t dwDefaultFrameInterval;
|
||||
};
|
||||
|
||||
struct usbh_video_format {
|
||||
@@ -40,7 +41,7 @@ struct usbh_videostreaming {
|
||||
struct usbh_video {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *isoin; /* ISO IN endpoint */
|
||||
struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
|
||||
uint8_t ctrl_intf; /* interface number */
|
||||
uint8_t data_intf; /* interface number */
|
||||
@@ -48,9 +49,9 @@ struct usbh_video {
|
||||
struct video_probe_and_commit_controls probe;
|
||||
struct video_probe_and_commit_controls commit;
|
||||
uint16_t isoin_mps;
|
||||
uint16_t isoout_mps;
|
||||
bool is_opened;
|
||||
uint8_t current_format;
|
||||
bool is_bulk;
|
||||
uint16_t bcdVDC;
|
||||
uint8_t num_of_intf_altsettings;
|
||||
uint8_t num_of_formats;
|
||||
|
||||
@@ -602,3 +602,12 @@ CLASS_INFO_DEFINE const struct usbh_class_info rndis_class_info = {
|
||||
.id_table = NULL,
|
||||
.class_driver = &rndis_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info rndis_cdcacm_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
|
||||
.bInterfaceSubClass = CDC_ABSTRACT_CONTROL_MODEL,
|
||||
.bInterfaceProtocol = 0xff,
|
||||
.id_table = NULL,
|
||||
.class_driver = &rndis_class_driver
|
||||
};
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define USBOTG_MODE_HOST 0
|
||||
#define USBOTG_MODE_DEVICE 1
|
||||
#define USBOTG_MODE_OTG 2
|
||||
|
||||
/**
|
||||
* @brief usb otg controller hardware or gpio id simulator init.
|
||||
*
|
||||
@@ -24,12 +28,6 @@ int usb_otg_init(uint8_t busid);
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usb_otg_deinit(uint8_t busid);
|
||||
/**
|
||||
* @brief get current role mode.
|
||||
*
|
||||
* @return return USBOTG_MODE_HOST or USBOTG_MODE_DEVICE.
|
||||
*/
|
||||
uint8_t usbotg_get_current_mode(uint8_t busid);
|
||||
|
||||
/* called by user */
|
||||
void USBOTG_IRQHandler(uint8_t busid);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#undef CHERRYUSB_VERSION_STR
|
||||
#endif
|
||||
|
||||
#define CHERRYUSB_VERSION 0x010502
|
||||
#define CHERRYUSB_VERSION_STR "v1.5.2"
|
||||
#define CHERRYUSB_VERSION 0x010503
|
||||
#define CHERRYUSB_VERSION_STR "v1.5.3"
|
||||
|
||||
#endif
|
||||
@@ -1145,18 +1145,26 @@ void usbd_event_suspend_handler(uint8_t busid)
|
||||
|
||||
void usbd_event_reset_handler(uint8_t busid)
|
||||
{
|
||||
struct usb_endpoint_descriptor ep0;
|
||||
|
||||
usbd_set_address(busid, 0);
|
||||
g_usbd_core[busid].device_address = 0;
|
||||
g_usbd_core[busid].configuration = 0;
|
||||
g_usbd_core[busid].ep0_next_state = USBD_EP0_STATE_SETUP;
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
g_usbd_core[busid].speed = USB_SPEED_UNKNOWN;
|
||||
|
||||
USB_ASSERT_MSG(g_usbd_core[busid].descriptors->device_descriptor_callback != NULL,
|
||||
"device_descriptor_callback is NULL\r\n");
|
||||
|
||||
struct usb_device_descriptor *device_desc = (struct usb_device_descriptor *)g_usbd_core[busid].descriptors->device_descriptor_callback(g_usbd_core[busid].speed);
|
||||
ep0.wMaxPacketSize = device_desc->bMaxPacketSize0;
|
||||
#else
|
||||
ep0.wMaxPacketSize = USB_CTRL_EP_MPS;
|
||||
#endif
|
||||
struct usb_endpoint_descriptor ep0;
|
||||
|
||||
ep0.bLength = 7;
|
||||
ep0.bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT;
|
||||
ep0.wMaxPacketSize = USB_CTRL_EP_MPS;
|
||||
ep0.bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
|
||||
ep0.bEndpointAddress = USB_CONTROL_IN_EP0;
|
||||
ep0.bInterval = 0;
|
||||
@@ -1536,11 +1544,7 @@ int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uin
|
||||
int ret;
|
||||
struct usbd_bus *bus;
|
||||
|
||||
if (busid >= CONFIG_USBDEV_MAX_BUS) {
|
||||
USB_LOG_ERR("bus overflow\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
USB_ASSERT_MSG(busid < CONFIG_USBDEV_MAX_BUS, "bus overflow\r\n");
|
||||
|
||||
bus = &g_usbdev_bus[busid];
|
||||
bus->reg_base = reg_base;
|
||||
@@ -1569,23 +1573,18 @@ int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uin
|
||||
|
||||
int usbd_deinitialize(uint8_t busid)
|
||||
{
|
||||
if (busid >= CONFIG_USBDEV_MAX_BUS) {
|
||||
USB_LOG_ERR("bus overflow\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
USB_ASSERT_MSG(busid < CONFIG_USBDEV_MAX_BUS, "bus overflow\r\n");
|
||||
|
||||
g_usbd_core[busid].event_handler(busid, USBD_EVENT_DEINIT);
|
||||
usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
|
||||
usb_dc_deinit(busid);
|
||||
g_usbd_core[busid].intf_offset = 0;
|
||||
#ifdef CONFIG_USBDEV_EP0_THREAD
|
||||
if (g_usbd_core[busid].usbd_ep0_mq) {
|
||||
usb_osal_mq_delete(g_usbd_core[busid].usbd_ep0_mq);
|
||||
}
|
||||
if (g_usbd_core[busid].usbd_ep0_thread) {
|
||||
usb_osal_thread_delete(g_usbd_core[busid].usbd_ep0_thread);
|
||||
}
|
||||
if (g_usbd_core[busid].usbd_ep0_mq) {
|
||||
usb_osal_mq_delete(g_usbd_core[busid].usbd_ep0_mq);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
562
core/usbh_core.c
562
core/usbh_core.c
@@ -33,29 +33,27 @@ struct usbh_bus g_usbhost_bus[CONFIG_USBHOST_MAX_BUS];
|
||||
|
||||
static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
|
||||
{
|
||||
uint8_t startaddr = devgen->next;
|
||||
uint8_t devaddr;
|
||||
uint8_t lastaddr = devgen->last;
|
||||
uint8_t devaddr = lastaddr;
|
||||
int index;
|
||||
int bitno;
|
||||
|
||||
for (;;) {
|
||||
devaddr = devgen->next;
|
||||
if (devgen->next >= 0x7f) {
|
||||
devgen->next = 2;
|
||||
} else {
|
||||
devgen->next++;
|
||||
devaddr++;
|
||||
if (devaddr > 0x7f) {
|
||||
devaddr = 2;
|
||||
}
|
||||
if (devaddr == lastaddr) {
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
index = devaddr >> 5;
|
||||
bitno = devaddr & 0x1f;
|
||||
if ((devgen->alloctab[index] & (1 << bitno)) == 0) {
|
||||
devgen->alloctab[index] |= (1 << bitno);
|
||||
if ((devgen->alloctab[index] & (1ul << bitno)) == 0) {
|
||||
devgen->alloctab[index] |= (1ul << bitno);
|
||||
devgen->last = devaddr;
|
||||
return (int)devaddr;
|
||||
}
|
||||
|
||||
if (startaddr == devaddr) {
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,15 +67,11 @@ static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
|
||||
bitno = devaddr & USB_DEV_ADDR_MARK_MASK;
|
||||
|
||||
/* Free the address */
|
||||
if ((devgen->alloctab[index] |= (1 << bitno)) != 0) {
|
||||
devgen->alloctab[index] &= ~(1 << bitno);
|
||||
if ((devgen->alloctab[index] & (1ul << bitno)) != 0) {
|
||||
devgen->alloctab[index] &= ~(1ul << bitno);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (devaddr < devgen->next) {
|
||||
devgen->next = devaddr;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -91,7 +85,7 @@ static int usbh_free_devaddr(struct usbh_hubport *hport)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subclass, uint8_t protocol,
|
||||
static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subclass, uint8_t protocol, uint8_t intf,
|
||||
uint16_t vid, uint16_t pid)
|
||||
{
|
||||
struct usbh_class_info *index = NULL;
|
||||
@@ -106,6 +100,9 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin
|
||||
if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->bInterfaceProtocol == protocol)) {
|
||||
continue;
|
||||
}
|
||||
if ((index->match_flags & USB_CLASS_MATCH_INTF_NUM) && !(index->bInterfaceNumber == intf)) {
|
||||
continue;
|
||||
}
|
||||
if (index->match_flags & USB_CLASS_MATCH_VID_PID && index->id_table) {
|
||||
/* scan id table */
|
||||
uint32_t i;
|
||||
@@ -275,60 +272,6 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usbh_print_hubport_info(struct usbh_hubport *hport)
|
||||
{
|
||||
USB_LOG_RAW("Device Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->device_desc.bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->device_desc.bDescriptorType);
|
||||
USB_LOG_RAW("bcdUSB: 0x%04x \r\n", hport->device_desc.bcdUSB);
|
||||
USB_LOG_RAW("bDeviceClass: 0x%02x \r\n", hport->device_desc.bDeviceClass);
|
||||
USB_LOG_RAW("bDeviceSubClass: 0x%02x \r\n", hport->device_desc.bDeviceSubClass);
|
||||
USB_LOG_RAW("bDeviceProtocol: 0x%02x \r\n", hport->device_desc.bDeviceProtocol);
|
||||
USB_LOG_RAW("bMaxPacketSize0: 0x%02x \r\n", hport->device_desc.bMaxPacketSize0);
|
||||
USB_LOG_RAW("idVendor: 0x%04x \r\n", hport->device_desc.idVendor);
|
||||
USB_LOG_RAW("idProduct: 0x%04x \r\n", hport->device_desc.idProduct);
|
||||
USB_LOG_RAW("bcdDevice: 0x%04x \r\n", hport->device_desc.bcdDevice);
|
||||
USB_LOG_RAW("iManufacturer: 0x%02x \r\n", hport->device_desc.iManufacturer);
|
||||
USB_LOG_RAW("iProduct: 0x%02x \r\n", hport->device_desc.iProduct);
|
||||
USB_LOG_RAW("iSerialNumber: 0x%02x \r\n", hport->device_desc.iSerialNumber);
|
||||
USB_LOG_RAW("bNumConfigurations: 0x%02x\r\n", hport->device_desc.bNumConfigurations);
|
||||
|
||||
USB_LOG_RAW("Config Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.config_desc.bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.config_desc.bDescriptorType);
|
||||
USB_LOG_RAW("wTotalLength: 0x%04x \r\n", hport->config.config_desc.wTotalLength);
|
||||
USB_LOG_RAW("bNumInterfaces: 0x%02x \r\n", hport->config.config_desc.bNumInterfaces);
|
||||
USB_LOG_RAW("bConfigurationValue: 0x%02x \r\n", hport->config.config_desc.bConfigurationValue);
|
||||
USB_LOG_RAW("iConfiguration: 0x%02x \r\n", hport->config.config_desc.iConfiguration);
|
||||
USB_LOG_RAW("bmAttributes: 0x%02x \r\n", hport->config.config_desc.bmAttributes);
|
||||
USB_LOG_RAW("bMaxPower: 0x%02x \r\n", hport->config.config_desc.bMaxPower);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
|
||||
for (uint8_t j = 0; j < hport->config.intf[i].altsetting_num; j++) {
|
||||
USB_LOG_RAW("\tInterface Descriptor:\r\n");
|
||||
USB_LOG_RAW("\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
|
||||
USB_LOG_RAW("\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
|
||||
USB_LOG_RAW("\tbInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
|
||||
USB_LOG_RAW("\tbAlternateSetting: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
|
||||
USB_LOG_RAW("\tbNumEndpoints: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
|
||||
USB_LOG_RAW("\tbInterfaceClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
|
||||
USB_LOG_RAW("\tbInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
|
||||
USB_LOG_RAW("\tbInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
|
||||
USB_LOG_RAW("\tiInterface: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
|
||||
|
||||
for (uint8_t k = 0; k < hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints; k++) {
|
||||
USB_LOG_RAW("\t\tEndpoint Descriptor:\r\n");
|
||||
USB_LOG_RAW("\t\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
|
||||
USB_LOG_RAW("\t\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
|
||||
USB_LOG_RAW("\t\tbEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
|
||||
USB_LOG_RAW("\t\tbmAttributes: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
|
||||
USB_LOG_RAW("\t\twMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
|
||||
USB_LOG_RAW("\t\tbInterval: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_print_setup(struct usb_setup_packet *setup)
|
||||
{
|
||||
(void)setup;
|
||||
@@ -603,18 +546,25 @@ int usbh_enumerate(struct usbh_hubport *hport)
|
||||
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
|
||||
intf_desc = &hport->config.intf[i].altsetting[0].intf_desc;
|
||||
|
||||
struct usbh_class_driver *class_driver = (struct usbh_class_driver *)usbh_find_class_driver(intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol, hport->device_desc.idVendor, hport->device_desc.idProduct);
|
||||
USB_ASSERT_MSG(intf_desc->bInterfaceNumber == i, "Interface number mismatch, do not support non-standard device\r\n");
|
||||
|
||||
struct usbh_class_driver *class_driver = (struct usbh_class_driver *)usbh_find_class_driver(intf_desc->bInterfaceClass,
|
||||
intf_desc->bInterfaceSubClass,
|
||||
intf_desc->bInterfaceProtocol,
|
||||
intf_desc->bInterfaceNumber,
|
||||
hport->device_desc.idVendor,
|
||||
hport->device_desc.idProduct);
|
||||
|
||||
if (class_driver == NULL) {
|
||||
USB_LOG_ERR("do not support Class:0x%02x,Subclass:0x%02x,Protocl:0x%02x\r\n",
|
||||
USB_LOG_ERR("Do not support Class:0x%02x, Subclass:0x%02x, Protocl:0x%02x on interface %u\r\n",
|
||||
intf_desc->bInterfaceClass,
|
||||
intf_desc->bInterfaceSubClass,
|
||||
intf_desc->bInterfaceProtocol);
|
||||
|
||||
intf_desc->bInterfaceProtocol,
|
||||
i);
|
||||
continue;
|
||||
}
|
||||
hport->config.intf[i].class_driver = class_driver;
|
||||
USB_LOG_INFO("Loading %s class driver\r\n", class_driver->driver_name);
|
||||
USB_LOG_INFO("Loading %s class driver on interface %u\r\n", class_driver->driver_name, i);
|
||||
ret = CLASS_CONNECT(hport, i);
|
||||
}
|
||||
|
||||
@@ -630,6 +580,7 @@ void usbh_hubport_release(struct usbh_hubport *hport)
|
||||
{
|
||||
if (hport->connected) {
|
||||
hport->connected = false;
|
||||
usbh_kill_urb(&hport->ep0_urb);
|
||||
usbh_free_devaddr(hport);
|
||||
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
|
||||
if (hport->config.intf[i].class_driver && hport->config.intf[i].class_driver->disconnect) {
|
||||
@@ -637,7 +588,6 @@ void usbh_hubport_release(struct usbh_hubport *hport)
|
||||
}
|
||||
}
|
||||
hport->config.config_desc.bNumInterfaces = 0;
|
||||
usbh_kill_urb(&hport->ep0_urb);
|
||||
if (hport->mutex) {
|
||||
usb_osal_mutex_delete(hport->mutex);
|
||||
}
|
||||
@@ -652,7 +602,7 @@ static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uintptr_t reg_bas
|
||||
bus->hcd.reg_base = reg_base;
|
||||
|
||||
/* devaddr 1 is for roothub */
|
||||
bus->devgen.next = 2;
|
||||
bus->devgen.last = 0x7f;
|
||||
|
||||
usb_slist_add_tail(&g_bus_head, &bus->list);
|
||||
}
|
||||
@@ -661,11 +611,7 @@ int usbh_initialize(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
struct usbh_bus *bus;
|
||||
|
||||
if (busid >= CONFIG_USBHOST_MAX_BUS) {
|
||||
USB_LOG_ERR("bus overflow\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
USB_ASSERT_MSG(busid < CONFIG_USBHOST_MAX_BUS, "bus overflow\r\n");
|
||||
|
||||
bus = &g_usbhost_bus[busid];
|
||||
|
||||
@@ -693,11 +639,7 @@ int usbh_deinitialize(uint8_t busid)
|
||||
{
|
||||
struct usbh_bus *bus;
|
||||
|
||||
if (busid >= CONFIG_USBHOST_MAX_BUS) {
|
||||
USB_LOG_ERR("bus overflow\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
USB_ASSERT_MSG(busid < CONFIG_USBHOST_MAX_BUS, "bus overflow\r\n");
|
||||
|
||||
bus = &g_usbhost_bus[busid];
|
||||
|
||||
@@ -711,6 +653,7 @@ int usbh_deinitialize(uint8_t busid)
|
||||
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
|
||||
{
|
||||
struct usbh_urb *urb;
|
||||
volatile uint8_t retry = 3;
|
||||
int ret;
|
||||
|
||||
if (!hport || !setup) {
|
||||
@@ -723,12 +666,21 @@ int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *s
|
||||
|
||||
usbh_print_setup(setup);
|
||||
|
||||
resubmit:
|
||||
usbh_control_urb_fill(urb, hport, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
|
||||
if (ret < 0 && (ret != -USB_ERR_TIMEOUT)) {
|
||||
retry--;
|
||||
if (retry > 0) {
|
||||
USB_LOG_WRN("Control transfer failed, errorcode %d, retrying...\r\n", ret);
|
||||
goto resubmit;
|
||||
}
|
||||
}
|
||||
|
||||
usb_osal_mutex_give(hport->mutex);
|
||||
return ret;
|
||||
}
|
||||
@@ -816,73 +768,6 @@ static void *usbh_list_all_interface_name(struct usbh_hub *hub, const char *devn
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_list_all_interface_driver(struct usbh_hub *hub)
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_hub *hub_next;
|
||||
const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
|
||||
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hport = &hub->child[port];
|
||||
if (hport->connected) {
|
||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
|
||||
for (uint8_t j = 0; j < hub->index; j++) {
|
||||
USB_LOG_RAW("\t");
|
||||
}
|
||||
|
||||
USB_LOG_RAW("|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s, %s\r\n",
|
||||
hport->port,
|
||||
hport->dev_addr,
|
||||
itf,
|
||||
hport->config.intf[itf].class_driver->driver_name,
|
||||
speed_table[hport->speed]);
|
||||
|
||||
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
|
||||
hub_next = hport->config.intf[itf].priv;
|
||||
|
||||
if (hub_next && hub_next->connected) {
|
||||
usbh_list_all_interface_driver(hub_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub *hub)
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_hub *hub_next;
|
||||
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hport = &hub->child[port];
|
||||
if (hport->connected) {
|
||||
USB_LOG_RAW("\r\nBus %u, Hub %u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
|
||||
bus->busid,
|
||||
hub->index,
|
||||
hport->port,
|
||||
hport->dev_addr,
|
||||
hport->device_desc.idVendor,
|
||||
hport->device_desc.idProduct);
|
||||
usbh_print_hubport_info(hport);
|
||||
|
||||
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
|
||||
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
|
||||
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
|
||||
hub_next = hport->config.intf[itf].priv;
|
||||
|
||||
if (hub_next && hub_next->connected) {
|
||||
usbh_list_all_interface_desc(bus, hub_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct usbh_hubport *usbh_list_all_hubport(struct usbh_hub *hub, uint8_t hub_index, uint8_t hub_port)
|
||||
{
|
||||
struct usbh_hubport *hport;
|
||||
@@ -960,64 +845,341 @@ struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t
|
||||
return hport;
|
||||
}
|
||||
|
||||
static void usbh_print_hubport_info(struct usbh_hubport *hport)
|
||||
{
|
||||
USB_LOG_RAW("Device Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->device_desc.bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->device_desc.bDescriptorType);
|
||||
USB_LOG_RAW("bcdUSB: 0x%04x \r\n", hport->device_desc.bcdUSB);
|
||||
USB_LOG_RAW("bDeviceClass: 0x%02x \r\n", hport->device_desc.bDeviceClass);
|
||||
USB_LOG_RAW("bDeviceSubClass: 0x%02x \r\n", hport->device_desc.bDeviceSubClass);
|
||||
USB_LOG_RAW("bDeviceProtocol: 0x%02x \r\n", hport->device_desc.bDeviceProtocol);
|
||||
USB_LOG_RAW("bMaxPacketSize0: 0x%02x \r\n", hport->device_desc.bMaxPacketSize0);
|
||||
USB_LOG_RAW("idVendor: 0x%04x \r\n", hport->device_desc.idVendor);
|
||||
USB_LOG_RAW("idProduct: 0x%04x \r\n", hport->device_desc.idProduct);
|
||||
USB_LOG_RAW("bcdDevice: 0x%04x \r\n", hport->device_desc.bcdDevice);
|
||||
USB_LOG_RAW("iManufacturer: 0x%02x \r\n", hport->device_desc.iManufacturer);
|
||||
USB_LOG_RAW("iProduct: 0x%02x \r\n", hport->device_desc.iProduct);
|
||||
USB_LOG_RAW("iSerialNumber: 0x%02x \r\n", hport->device_desc.iSerialNumber);
|
||||
USB_LOG_RAW("bNumConfigurations: 0x%02x\r\n", hport->device_desc.bNumConfigurations);
|
||||
|
||||
USB_LOG_RAW("Config Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.config_desc.bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.config_desc.bDescriptorType);
|
||||
USB_LOG_RAW("wTotalLength: 0x%04x \r\n", hport->config.config_desc.wTotalLength);
|
||||
USB_LOG_RAW("bNumInterfaces: 0x%02x \r\n", hport->config.config_desc.bNumInterfaces);
|
||||
USB_LOG_RAW("bConfigurationValue: 0x%02x \r\n", hport->config.config_desc.bConfigurationValue);
|
||||
USB_LOG_RAW("iConfiguration: 0x%02x \r\n", hport->config.config_desc.iConfiguration);
|
||||
USB_LOG_RAW("bmAttributes: 0x%02x \r\n", hport->config.config_desc.bmAttributes);
|
||||
USB_LOG_RAW("bMaxPower: 0x%02x \r\n", hport->config.config_desc.bMaxPower);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
|
||||
for (uint8_t j = 0; j < hport->config.intf[i].altsetting_num; j++) {
|
||||
USB_LOG_RAW("\tInterface Descriptor:\r\n");
|
||||
USB_LOG_RAW("\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
|
||||
USB_LOG_RAW("\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
|
||||
USB_LOG_RAW("\tbInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
|
||||
USB_LOG_RAW("\tbAlternateSetting: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
|
||||
USB_LOG_RAW("\tbNumEndpoints: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
|
||||
USB_LOG_RAW("\tbInterfaceClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
|
||||
USB_LOG_RAW("\tbInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
|
||||
USB_LOG_RAW("\tbInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
|
||||
USB_LOG_RAW("\tiInterface: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
|
||||
|
||||
for (uint8_t k = 0; k < hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints; k++) {
|
||||
USB_LOG_RAW("\t\tEndpoint Descriptor:\r\n");
|
||||
USB_LOG_RAW("\t\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
|
||||
USB_LOG_RAW("\t\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
|
||||
USB_LOG_RAW("\t\tbEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
|
||||
USB_LOG_RAW("\t\tbmAttributes: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
|
||||
USB_LOG_RAW("\t\twMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
|
||||
USB_LOG_RAW("\t\tbInterval: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_list_device(struct usbh_hub *hub, bool astree, bool verbose, int dev_addr, int vid, int pid)
|
||||
{
|
||||
static const char *speed_table[] = {
|
||||
"UNKNOWN",
|
||||
"low-speed",
|
||||
"full-speed",
|
||||
"high-speed",
|
||||
"wireless",
|
||||
"super-speed",
|
||||
"super-speed-plus",
|
||||
};
|
||||
|
||||
static const char *root_speed_table[] = {
|
||||
"UNKNOWN",
|
||||
"1.1",
|
||||
"1.1",
|
||||
"2.0",
|
||||
"2.5",
|
||||
"3.0",
|
||||
"3.0",
|
||||
};
|
||||
|
||||
static const uint16_t speed_baud[] = {
|
||||
0,
|
||||
12,
|
||||
12,
|
||||
480,
|
||||
480,
|
||||
5000,
|
||||
10000,
|
||||
};
|
||||
|
||||
struct usbh_bus *bus;
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_hub *hub_next;
|
||||
|
||||
uint8_t imbuf[64];
|
||||
uint8_t ipbuf[64];
|
||||
|
||||
const char *pimstr;
|
||||
const char *pipstr;
|
||||
|
||||
bool imvalid = false;
|
||||
bool ipvalid = false;
|
||||
|
||||
int ret;
|
||||
|
||||
bus = hub->bus;
|
||||
|
||||
(void)speed_table;
|
||||
|
||||
if (hub->is_roothub) {
|
||||
if (astree) {
|
||||
USB_LOG_RAW("/: Bus %02u.Port 1: Dev %u, Class=root_hub, Driver=hcd, %uM\r\n",
|
||||
bus->busid, hub->hub_addr, speed_baud[hub->speed]);
|
||||
|
||||
} else {
|
||||
if ((dev_addr < 0) || (hub->hub_addr == dev_addr)) {
|
||||
if (((vid < 0) || (vid == 0xffff)) && ((pid < 0) || (pid == 0xffff))) {
|
||||
USB_LOG_RAW("Bus %03u Device %03u: ID %04x:%04x %s %s root hub\r\n",
|
||||
bus->busid, hub->hub_addr, 0xffff, 0xffff,
|
||||
"Cherry-Embedded", root_speed_table[hub->speed]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hport = &hub->child[port];
|
||||
if (hport->connected) {
|
||||
ret = 0;
|
||||
if (hport->device_desc.iManufacturer) {
|
||||
memset(imbuf, 0, sizeof(imbuf));
|
||||
ret = usbh_get_string_desc(hport, hport->device_desc.iManufacturer, imbuf, sizeof(imbuf));
|
||||
if (ret == 0) {
|
||||
imvalid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hport->device_desc.iProduct) {
|
||||
memset(ipbuf, 0, sizeof(ipbuf));
|
||||
ret = usbh_get_string_desc(hport, hport->device_desc.iProduct, ipbuf, sizeof(ipbuf));
|
||||
if (ret == 0) {
|
||||
ipvalid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (imvalid) {
|
||||
pimstr = (const char *)imbuf;
|
||||
} else {
|
||||
pimstr = "Not specified Manufacturer";
|
||||
}
|
||||
|
||||
if (ipvalid) {
|
||||
pipstr = (const char *)ipbuf;
|
||||
} else {
|
||||
pipstr = "Not specified Product";
|
||||
}
|
||||
|
||||
if (!astree) {
|
||||
if ((dev_addr < 0) || (hport->dev_addr == dev_addr)) {
|
||||
if (((vid < 0) || (vid == hport->device_desc.idVendor)) && ((pid < 0) || (pid == hport->device_desc.idProduct))) {
|
||||
USB_LOG_RAW("Bus %03u Device %03u: ID %04x:%04x %s %s\r\n",
|
||||
bus->busid, hport->dev_addr, hport->device_desc.idVendor, hport->device_desc.idProduct,
|
||||
pimstr, pipstr);
|
||||
|
||||
if (verbose) {
|
||||
usbh_print_hubport_info(hport);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t intf = 0; intf < hport->config.config_desc.bNumInterfaces; intf++) {
|
||||
if (hport->config.intf[intf].class_driver && hport->config.intf[intf].class_driver->driver_name) {
|
||||
if (astree) {
|
||||
for (uint8_t j = 0; j < hub->index; j++) {
|
||||
USB_LOG_RAW(" ");
|
||||
}
|
||||
|
||||
USB_LOG_RAW("|__ Port %u: Dev %u, If %u, ClassDriver=%s, %uM\r\n",
|
||||
hport->port, hport->dev_addr, intf, hport->config.intf[intf].class_driver->driver_name, speed_baud[hport->speed]);
|
||||
}
|
||||
|
||||
if (!strcmp(hport->config.intf[intf].class_driver->driver_name, "hub")) {
|
||||
hub_next = hport->config.intf[intf].priv;
|
||||
|
||||
if (hub_next && hub_next->connected) {
|
||||
usbh_list_device(hub_next, astree, verbose, dev_addr, vid, pid);
|
||||
}
|
||||
}
|
||||
} else if (astree) {
|
||||
for (uint8_t j = 0; j < hub->index; j++) {
|
||||
USB_LOG_RAW(" ");
|
||||
}
|
||||
|
||||
USB_LOG_RAW("|__ Port %u: Dev %u, If 0 ClassDriver=none, %uM\r\n",
|
||||
hport->port, hport->dev_addr, speed_baud[hport->speed]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lsusb_help(void)
|
||||
{
|
||||
USB_LOG_RAW("List USB Devices\r\n"
|
||||
"Usage: lsusb [options]...\r\n"
|
||||
"\r\n"
|
||||
"-v, --verbose\r\n"
|
||||
" - increase verbosity (show descriptors)\r\n"
|
||||
"-s [[bus]:][dev_addr]\r\n"
|
||||
" - show only devices with specified device and/or\r\n"
|
||||
" bus numbers (in decimal)\r\n"
|
||||
"-d vendor:[product]\r\n"
|
||||
" - show only devices with the specified vendor and\r\n"
|
||||
" product ID numbers (in hexadecimal)\r\n"
|
||||
"-t, --tree\r\n"
|
||||
" - dump the physical USB device hierarchy as a tree\r\n"
|
||||
"-V, --version\r\n"
|
||||
" - show version of the cherryusb\r\n"
|
||||
"-h, --help\r\n"
|
||||
" - show usage and help information\r\n");
|
||||
}
|
||||
|
||||
int lsusb(int argc, char **argv)
|
||||
{
|
||||
usb_slist_t *bus_list;
|
||||
struct usbh_hub *hub;
|
||||
struct usbh_bus *bus;
|
||||
size_t flags;
|
||||
|
||||
int busid = -1;
|
||||
int dev_addr = -1;
|
||||
int vid = -1;
|
||||
int pid = -1;
|
||||
bool astree = false;
|
||||
bool verbose = false;
|
||||
|
||||
if (argc < 2) {
|
||||
USB_LOG_RAW("Usage: lsusb [options]...\r\n");
|
||||
USB_LOG_RAW("List USB devices\r\n");
|
||||
USB_LOG_RAW(" -v, --verbose\r\n");
|
||||
USB_LOG_RAW(" Increase verbosity (show descriptors)\r\n");
|
||||
// USB_LOG_RAW(" -s [[bus]:[devnum]]\r\n");
|
||||
// USB_LOG_RAW(" Show only devices with specified device and/or bus numbers (in decimal)\r\n");
|
||||
// USB_LOG_RAW(" -d vendor:[product]\r\n");
|
||||
// USB_LOG_RAW(" Show only devices with the specified vendor and product ID numbers (in hexadecimal)\r\n");
|
||||
USB_LOG_RAW(" -t, --tree\r\n");
|
||||
USB_LOG_RAW(" Dump the physical USB device hierachy as a tree\r\n");
|
||||
USB_LOG_RAW(" -V, --version\r\n");
|
||||
USB_LOG_RAW(" Show version of program\r\n");
|
||||
USB_LOG_RAW(" -h, --help\r\n");
|
||||
USB_LOG_RAW(" Show usage and help\r\n");
|
||||
return 0;
|
||||
}
|
||||
if (argc > 3) {
|
||||
lsusb_help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
while (argc > 1) {
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (strcmp(argv[1], "-V") == 0) {
|
||||
USB_LOG_RAW("CherryUSB Version %s\r\n", CHERRYUSB_VERSION_STR);
|
||||
}
|
||||
if (!strcmp(*argv, "-V") || !strcmp(*argv, "--version")) {
|
||||
USB_LOG_RAW("CherryUSB version %s\r\n", CHERRYUSB_VERSION_STR);
|
||||
return 0;
|
||||
} else if (!strcmp(*argv, "-h") || !strcmp(*argv, "--help")) {
|
||||
lsusb_help();
|
||||
return 0;
|
||||
} else if (!strcmp(*argv, "-v") || !strcmp(*argv, "--verbose")) {
|
||||
verbose = true;
|
||||
} else if (!strcmp(*argv, "-t") || !strcmp(*argv, "--tree")) {
|
||||
astree = true;
|
||||
} else if (!strcmp(*argv, "-s")) {
|
||||
if (argc > 1) {
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (strcmp(argv[1], "-t") == 0) {
|
||||
usb_slist_for_each(bus_list, &g_bus_head)
|
||||
{
|
||||
bus = usb_slist_entry(bus_list, struct usbh_bus, list);
|
||||
hub = &bus->hcd.roothub;
|
||||
if (*argv[0] == '-') {
|
||||
continue;
|
||||
}
|
||||
|
||||
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
|
||||
bus->busid,
|
||||
hub->index,
|
||||
hub->nports);
|
||||
usbh_list_all_interface_driver(hub);
|
||||
char *endptr;
|
||||
const char *colon = strchr(*argv, ':');
|
||||
(void)endptr;
|
||||
|
||||
if (colon != NULL) {
|
||||
const char *str;
|
||||
if (colon > *argv) {
|
||||
busid = strtol(*argv, &endptr, 10);
|
||||
}
|
||||
str = colon + 1;
|
||||
if (*str != '\0') {
|
||||
dev_addr = strtol(str, &endptr, 10);
|
||||
if (dev_addr <= 0 || dev_addr >= 128) {
|
||||
dev_addr = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dev_addr = strtol(*argv, &endptr, 10);
|
||||
if (dev_addr <= 0 || dev_addr >= 128) {
|
||||
dev_addr = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(*argv, "-d")) {
|
||||
if (argc > 1) {
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (*argv[0] == '-') {
|
||||
continue;
|
||||
}
|
||||
|
||||
char *endptr;
|
||||
const char *colon = strchr(*argv, ':');
|
||||
(void)endptr;
|
||||
|
||||
if (colon == NULL) {
|
||||
continue;
|
||||
}
|
||||
const char *str;
|
||||
|
||||
vid = strtol(*argv, &endptr, 16);
|
||||
if (vid < 0 || vid > 0xffff) {
|
||||
vid = -1;
|
||||
continue;
|
||||
}
|
||||
str = colon + 1;
|
||||
if (*str != '\0') {
|
||||
pid = strtol(str, &endptr, 16);
|
||||
if (pid < 0 || pid > 0xffff) {
|
||||
pid = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "-v") == 0) {
|
||||
usb_slist_for_each(bus_list, &g_bus_head)
|
||||
{
|
||||
bus = usb_slist_entry(bus_list, struct usbh_bus, list);
|
||||
hub = &bus->hcd.roothub;
|
||||
|
||||
usbh_list_all_interface_desc(bus, hub);
|
||||
}
|
||||
if (astree) {
|
||||
busid = -1;
|
||||
dev_addr = -1;
|
||||
vid = -1;
|
||||
pid = -1;
|
||||
verbose = false;
|
||||
}
|
||||
|
||||
usb_slist_for_each(bus_list, &g_bus_head)
|
||||
{
|
||||
bus = usb_slist_entry(bus_list, struct usbh_bus, list);
|
||||
if (busid >= 0) {
|
||||
if (bus->busid != busid) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
usbh_list_device(&bus->hcd.roothub, astree, verbose, dev_addr, vid, pid);
|
||||
}
|
||||
|
||||
usb_osal_leave_critical_section(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ extern "C" {
|
||||
#define USB_CLASS_MATCH_INTF_CLASS 0x0004
|
||||
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
|
||||
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
|
||||
#define USB_CLASS_MATCH_INTF_NUM 0x0020
|
||||
#define USB_CLASS_MATCH_VID_PID (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT)
|
||||
|
||||
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
|
||||
@@ -65,6 +66,7 @@ struct usbh_class_info {
|
||||
uint8_t bInterfaceClass; /* Base device class code */
|
||||
uint8_t bInterfaceSubClass; /* Sub-class, depends on base class. Eg. */
|
||||
uint8_t bInterfaceProtocol; /* Protocol, depends on base class. Eg. */
|
||||
uint8_t bInterfaceNumber; /* Interface number */
|
||||
const uint16_t (*id_table)[2]; /* List of Vendor/Product ID pairs */
|
||||
const struct usbh_class_driver *class_driver;
|
||||
};
|
||||
@@ -150,7 +152,7 @@ struct usbh_devaddr_map {
|
||||
* alloctab[3]:addr from 96~127
|
||||
*
|
||||
*/
|
||||
uint8_t next; /* Next device address */
|
||||
uint8_t last; /* Last device address */
|
||||
uint32_t alloctab[4]; /* Bit allocation table */
|
||||
};
|
||||
|
||||
|
||||
@@ -5,39 +5,57 @@
|
||||
*/
|
||||
#include "usbotg_core.h"
|
||||
|
||||
#ifdef CONFIG_USB_OTG_ENABLE
|
||||
#undef USB_DBG_TAG
|
||||
#define USB_DBG_TAG "usbotg_core"
|
||||
#include "usb_log.h"
|
||||
|
||||
#define CONFIG_USB_OTG_MAX_BUS CONFIG_USBHOST_MAX_BUS
|
||||
|
||||
struct usbotg_core_priv {
|
||||
uint8_t busid;
|
||||
uint32_t reg_base;
|
||||
usb_osal_sem_t change_sem;
|
||||
usb_osal_thread_t change_thread;
|
||||
bool usbh_initialized;
|
||||
bool usbd_initialized;
|
||||
int (*usbh_initialize)(uint8_t busid, uint32_t reg_base);
|
||||
int (*usbd_initialize)(uint8_t busid, uint32_t reg_base);
|
||||
} g_usbotg_core[CONFIG_USBHOST_MAX_BUS];
|
||||
void *device_event_callback;
|
||||
void *host_event_callback;
|
||||
uint8_t current_mode;
|
||||
usb_osal_sem_t change_sem;
|
||||
usb_osal_thread_t change_thread;
|
||||
} g_usbotg_core[CONFIG_USB_OTG_MAX_BUS];
|
||||
|
||||
static void usbotg_host_initialize(uint8_t busid)
|
||||
{
|
||||
if (g_usbotg_core[busid].usbh_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_usbotg_core[busid].usbd_initialized) {
|
||||
g_usbotg_core[busid].usbd_initialized = false;
|
||||
usbd_deinitialize(busid);
|
||||
}
|
||||
if (g_usbotg_core[busid].usbh_initialize && !g_usbotg_core[busid].usbh_initialized) {
|
||||
g_usbotg_core[busid].usbh_initialized = true;
|
||||
g_usbotg_core[busid].usbh_initialize(g_usbotg_core[busid].busid, g_usbotg_core[busid].reg_base);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Switch to HOST mode\r\n");
|
||||
|
||||
usbh_initialize(busid, g_usbotg_core[busid].reg_base);
|
||||
g_usbotg_core[busid].usbh_initialized = true;
|
||||
}
|
||||
|
||||
static void usbotg_device_initialize(uint8_t busid)
|
||||
{
|
||||
if (g_usbotg_core[busid].usbd_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_usbotg_core[busid].usbh_initialized) {
|
||||
g_usbotg_core[busid].usbh_initialized = false;
|
||||
usbh_deinitialize(busid);
|
||||
}
|
||||
if (g_usbotg_core[busid].usbd_initialize && !g_usbotg_core[busid].usbd_initialize) {
|
||||
g_usbotg_core[busid].usbd_initialized = true;
|
||||
g_usbotg_core[busid].usbd_initialize(g_usbotg_core[busid].busid, g_usbotg_core[busid].reg_base);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Switch to DEVICE mode\r\n");
|
||||
|
||||
usbd_initialize(g_usbotg_core[busid].busid, g_usbotg_core[busid].reg_base, g_usbotg_core[busid].device_event_callback);
|
||||
g_usbotg_core[busid].usbd_initialized = true;
|
||||
}
|
||||
|
||||
static void usbotg_rolechange_thread(void *argument)
|
||||
@@ -48,58 +66,49 @@ static void usbotg_rolechange_thread(void *argument)
|
||||
|
||||
while (1) {
|
||||
if (usb_osal_sem_take(g_usbotg_core[busid].change_sem, USB_OSAL_WAITING_FOREVER) == 0) {
|
||||
if (usbotg_get_current_mode(busid) == USBOTG_MODE_HOST) {
|
||||
if (g_usbotg_core[busid].current_mode == USBOTG_MODE_HOST) {
|
||||
usbotg_host_initialize(busid);
|
||||
} else if (usbotg_get_current_mode(busid) == USBOTG_MODE_DEVICE) {
|
||||
} else if (g_usbotg_core[busid].current_mode == USBOTG_MODE_DEVICE) {
|
||||
usbotg_device_initialize(busid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int usbotg_initialize(uint8_t otg_mode, uint8_t busid, uint32_t reg_base,
|
||||
int (*usbh_initialize)(uint8_t busid, uint32_t reg_base),
|
||||
int (*usbd_initialize)(uint8_t busid, uint32_t reg_base))
|
||||
int usbotg_initialize(uint8_t busid, uint32_t reg_base, void *device_event_callback, void *host_event_callback, uint8_t default_role)
|
||||
{
|
||||
char thread_name[32] = { 0 };
|
||||
|
||||
if (busid >= CONFIG_USBHOST_MAX_BUS) {
|
||||
USB_LOG_ERR("bus overflow\r\n");
|
||||
USB_ASSERT_MSG(busid < CONFIG_USB_OTG_MAX_BUS, "bus overflow\r\n");
|
||||
|
||||
g_usbotg_core[busid].busid = busid;
|
||||
g_usbotg_core[busid].reg_base = reg_base;
|
||||
g_usbotg_core[busid].device_event_callback = device_event_callback;
|
||||
g_usbotg_core[busid].host_event_callback = host_event_callback;
|
||||
|
||||
g_usbotg_core[busid].change_sem = usb_osal_sem_create(0);
|
||||
if (g_usbotg_core[busid].change_sem == NULL) {
|
||||
USB_LOG_ERR("Failed to create change_sem\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
g_usbotg_core[busid].busid = busid;
|
||||
g_usbotg_core[busid].reg_base = reg_base;
|
||||
g_usbotg_core[busid].usbh_initialize = usbh_initialize;
|
||||
g_usbotg_core[busid].usbd_initialize = usbd_initialize;
|
||||
|
||||
if (otg_mode == USBOTG_MODE_OTG) {
|
||||
g_usbotg_core[busid].change_sem = usb_osal_sem_create(0);
|
||||
if (g_usbotg_core[busid].change_sem == NULL) {
|
||||
USB_LOG_ERR("Failed to create change_sem\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(thread_name, 32, "usbotg%u", busid);
|
||||
g_usbotg_core[busid].change_thread = usb_osal_thread_create(thread_name, CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbotg_rolechange_thread, (void *)(uintptr_t)busid);
|
||||
if (g_usbotg_core[busid].change_thread == NULL) {
|
||||
USB_LOG_ERR("Failed to create usbotg thread\r\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (otg_mode == USBOTG_MODE_HOST) {
|
||||
usbotg_host_initialize(busid);
|
||||
} else if (otg_mode == USBOTG_MODE_DEVICE) {
|
||||
usbotg_device_initialize(busid);
|
||||
snprintf(thread_name, 32, "usbotg%u", busid);
|
||||
g_usbotg_core[busid].change_thread = usb_osal_thread_create(thread_name, 2048, 10, usbotg_rolechange_thread, (void *)(uintptr_t)busid);
|
||||
if (g_usbotg_core[busid].change_thread == NULL) {
|
||||
USB_LOG_ERR("Failed to create usbotg thread\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
usbotg_trigger_role_change(busid, default_role);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbotg_deinitialize(uint8_t busid, uint32_t reg_base)
|
||||
int usbotg_deinitialize(uint8_t busid)
|
||||
{
|
||||
USB_ASSERT_MSG(busid < CONFIG_USB_OTG_MAX_BUS, "bus overflow\r\n");
|
||||
|
||||
if (g_usbotg_core[busid].usbd_initialized) {
|
||||
g_usbotg_core[busid].usbd_initialized = false;
|
||||
usbd_deinitialize(busid);
|
||||
@@ -110,28 +119,37 @@ int usbotg_deinitialize(uint8_t busid, uint32_t reg_base)
|
||||
usbh_deinitialize(busid);
|
||||
}
|
||||
|
||||
if (g_usbotg_core[busid].change_thread) {
|
||||
usb_osal_thread_delete(g_usbotg_core[busid].change_thread);
|
||||
}
|
||||
|
||||
if (g_usbotg_core[busid].change_sem) {
|
||||
usb_otg_deinit(busid);
|
||||
usb_osal_sem_delete(g_usbotg_core[busid].change_sem);
|
||||
}
|
||||
|
||||
if (g_usbotg_core[busid].change_thread) {
|
||||
usb_osal_thread_delete(g_usbotg_core[busid].change_thread);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usbotg_trigger_role_change(uint8_t busid)
|
||||
void usbotg_trigger_role_change(uint8_t busid, uint8_t mode)
|
||||
{
|
||||
usb_osal_sem_give(g_usbotg_core[busid].change_sem);
|
||||
USB_ASSERT_MSG(busid < CONFIG_USB_OTG_MAX_BUS, "bus overflow\r\n");
|
||||
|
||||
g_usbotg_core[busid].current_mode = mode;
|
||||
|
||||
if (g_usbotg_core[busid].change_sem) {
|
||||
usb_osal_sem_give(g_usbotg_core[busid].change_sem);
|
||||
}
|
||||
}
|
||||
|
||||
void USBOTG_IRQHandler(uint8_t busid)
|
||||
{
|
||||
if (usbotg_get_current_mode(busid) == USBOTG_MODE_HOST) {
|
||||
USB_ASSERT_MSG(busid < CONFIG_USB_OTG_MAX_BUS, "bus overflow\r\n");
|
||||
|
||||
if (g_usbotg_core[busid].current_mode == USBOTG_MODE_HOST && g_usbotg_core[busid].usbh_initialized) {
|
||||
USBH_IRQHandler(busid);
|
||||
} else if (usbotg_get_current_mode(busid) == USBOTG_MODE_DEVICE) {
|
||||
} else if (g_usbotg_core[busid].current_mode == USBOTG_MODE_DEVICE && g_usbotg_core[busid].usbd_initialized) {
|
||||
USBD_IRQHandler(busid);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_USB_OTG_ENABLE */
|
||||
@@ -10,22 +10,15 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define USBOTG_MODE_UNKNOWN 0
|
||||
#define USBOTG_MODE_OTG 1
|
||||
#define USBOTG_MODE_HOST 2
|
||||
#define USBOTG_MODE_DEVICE 3
|
||||
|
||||
#include "usbd_core.h"
|
||||
#include "usbh_core.h"
|
||||
#include "usb_otg.h"
|
||||
|
||||
int usbotg_initialize(uint8_t otg_mode, uint8_t busid, uint32_t reg_base,
|
||||
int (*usbh_initialize)(uint8_t busid, uint32_t reg_base),
|
||||
int (*usbd_initialize)(uint8_t busid, uint32_t reg_base));
|
||||
int usbotg_deinitialize(uint8_t busid, uint32_t reg_base);
|
||||
int usbotg_initialize(uint8_t busid, uint32_t reg_base, void *device_event_callback, void *host_event_callback, uint8_t default_role);
|
||||
int usbotg_deinitialize(uint8_t busid);
|
||||
|
||||
/* called by user */
|
||||
void usbotg_trigger_role_change(uint8_t busid);
|
||||
void usbotg_trigger_role_change(uint8_t busid, uint8_t mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ void cherryadb_init(uint8_t busid, uint32_t reg_base)
|
||||
/* shell_init() must be called in-task */
|
||||
if (0 != shell_init(false)) {
|
||||
/* shell failed to be initialized */
|
||||
printf("Failed to initialize shell\r\n");
|
||||
USB_LOG_RAW("Failed to initialize shell\r\n");
|
||||
for (;;) {
|
||||
;
|
||||
}
|
||||
|
||||
@@ -297,11 +297,11 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
|
||||
AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value); /* uac1 can only use 10.14 */
|
||||
usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
|
||||
#endif
|
||||
printf("OPEN1\r\n");
|
||||
USB_LOG_INFO("OPEN1\r\n");
|
||||
} else {
|
||||
tx_flag = 1;
|
||||
ep_tx_busy_flag = false;
|
||||
printf("OPEN2\r\n");
|
||||
USB_LOG_INFO("OPEN2\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,11 +309,11 @@ void usbd_audio_close(uint8_t busid, uint8_t intf)
|
||||
{
|
||||
if (intf == 1) {
|
||||
rx_flag = 0;
|
||||
printf("CLOSE1\r\n");
|
||||
USB_LOG_INFO("CLOSE1\r\n");
|
||||
} else {
|
||||
tx_flag = 0;
|
||||
ep_tx_busy_flag = false;
|
||||
printf("CLOSE2\r\n");
|
||||
USB_LOG_INFO("CLOSE2\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,4 +205,28 @@ void cdc_acm_chardev_init(uint8_t busid, uintptr_t reg_base)
|
||||
#endif
|
||||
usbd_cdc_acm_serial_init(busid, CDC_IN_EP, CDC_OUT_EP);
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
}
|
||||
|
||||
static int cdc_acm_enter(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
finsh_set_device("usb-acm0");
|
||||
rt_console_set_device("usb-acm0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
MSH_CMD_EXPORT(cdc_acm_enter, cdc_acm_enter);
|
||||
|
||||
static int cdc_acm_exit(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
finsh_set_device(RT_CONSOLE_DEVICE_NAME);
|
||||
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
MSH_CMD_EXPORT(cdc_acm_exit, cdc_acm_exit);
|
||||
@@ -68,6 +68,7 @@ static const char *string_descriptors[] = {
|
||||
"CherryUSB", /* Manufacturer */
|
||||
"CherryUSB CDC ECM DEMO", /* Product */
|
||||
"2022123456", /* Serial Number */
|
||||
"aabbccddeeff", /* ecm mac address */
|
||||
};
|
||||
|
||||
static const uint8_t *device_descriptor_callback(uint8_t speed)
|
||||
|
||||
@@ -189,14 +189,14 @@ void usbd_rndis_data_send_done(uint32_t len)
|
||||
#error rndis must enable RT_LWIP_DHCP
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_USING_DHCPD
|
||||
#error rndis must enable LWIP_USING_DHCPD
|
||||
#ifdef LWIP_USING_DHCPD
|
||||
#include <dhcp_server.h>
|
||||
#endif
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
#include <netif/ethernetif.h>
|
||||
#include <dhcp_server.h>
|
||||
#include <netdev.h>
|
||||
|
||||
struct eth_device rndis_dev;
|
||||
|
||||
@@ -250,7 +250,14 @@ void rndis_lwip_init(void)
|
||||
eth_device_init(&rndis_dev, "u0");
|
||||
|
||||
eth_device_linkchange(&rndis_dev, RT_TRUE);
|
||||
#ifdef LWIP_USING_DHCPD
|
||||
dhcpd_start("u0");
|
||||
#else
|
||||
struct netdev *netdev = netdev_get_by_name("u0");
|
||||
if (netdev) {
|
||||
netdev_dhcp_enabled(netdev, RT_TRUE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void usbd_rndis_data_recv_done(uint32_t len)
|
||||
|
||||
233
demo/mongoose/cdc_rndis_mongoose.c
Normal file
233
demo/mongoose/cdc_rndis_mongoose.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) 2025, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_rndis.h"
|
||||
#include "rndis_protocol.h"
|
||||
#include "mongoose.h"
|
||||
|
||||
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
#error Do not define CONFIG_USBDEV_RNDIS_USING_LWIP in this demo
|
||||
#endif
|
||||
|
||||
/*!< endpoint address */
|
||||
#define CDC_IN_EP 0x81
|
||||
#define CDC_OUT_EP 0x02
|
||||
#define CDC_INT_EP 0x83
|
||||
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + CDC_RNDIS_DESCRIPTOR_LEN)
|
||||
|
||||
static const uint8_t device_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
|
||||
};
|
||||
|
||||
static const uint8_t config_descriptor_hs[] = {
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_HS, 0x02),
|
||||
};
|
||||
|
||||
static const uint8_t config_descriptor_fs[] = {
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_FS, 0x02),
|
||||
};
|
||||
|
||||
static const uint8_t device_quality_descriptor[] = {
|
||||
USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, 0x01),
|
||||
};
|
||||
|
||||
static const uint8_t other_speed_config_descriptor_hs[] = {
|
||||
USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_FS, 0x02),
|
||||
};
|
||||
|
||||
static const uint8_t other_speed_config_descriptor_fs[] = {
|
||||
USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, USB_BULK_EP_MPS_HS, 0x02),
|
||||
};
|
||||
|
||||
static const char *string_descriptors[] = {
|
||||
(const char[]){ 0x09, 0x04 }, /* Langid */
|
||||
"CherryUSB", /* Manufacturer */
|
||||
"CherryUSB RNDIS MONGOOSE DEMO", /* Product */
|
||||
"2025123456", /* Serial Number */
|
||||
};
|
||||
|
||||
static const uint8_t *device_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
(void)speed;
|
||||
|
||||
return device_descriptor;
|
||||
}
|
||||
|
||||
static const uint8_t *config_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
if (speed == USB_SPEED_HIGH) {
|
||||
return config_descriptor_hs;
|
||||
} else if (speed == USB_SPEED_FULL) {
|
||||
return config_descriptor_fs;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
(void)speed;
|
||||
|
||||
return device_quality_descriptor;
|
||||
}
|
||||
|
||||
static const uint8_t *other_speed_config_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
if (speed == USB_SPEED_HIGH) {
|
||||
return other_speed_config_descriptor_hs;
|
||||
} else if (speed == USB_SPEED_FULL) {
|
||||
return other_speed_config_descriptor_fs;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
|
||||
{
|
||||
(void)speed;
|
||||
|
||||
if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
|
||||
return NULL;
|
||||
}
|
||||
return string_descriptors[index];
|
||||
}
|
||||
|
||||
const struct usb_descriptor cdc_descriptor = {
|
||||
.device_descriptor_callback = device_descriptor_callback,
|
||||
.config_descriptor_callback = config_descriptor_callback,
|
||||
.device_quality_descriptor_callback = device_quality_descriptor_callback,
|
||||
.other_speed_descriptor_callback = other_speed_config_descriptor_callback,
|
||||
.string_descriptor_callback = string_descriptor_callback,
|
||||
};
|
||||
|
||||
static uint8_t rndis_mac[6] = { 0x20, 0x89, 0x84, 0x6A, 0x96, 0xAA };
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[USB_ALIGN_UP(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[USB_ALIGN_UP(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
volatile bool g_rndis_tx_busy_flag = false;
|
||||
|
||||
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
g_rndis_tx_busy_flag = false;
|
||||
usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct mg_tcpip_if *s_ifp;
|
||||
|
||||
void usbd_rndis_data_recv_done(uint32_t len)
|
||||
{
|
||||
(void)len;
|
||||
|
||||
rndis_data_packet_t *hdr;
|
||||
uint8_t *buf;
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
|
||||
buf = (uint8_t *)hdr + hdr->DataOffset + sizeof(rndis_generic_msg_t);
|
||||
|
||||
mg_tcpip_qwrite((void *)buf, hdr->DataLength, s_ifp);
|
||||
|
||||
usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
}
|
||||
|
||||
void usbd_rndis_data_send_done(uint32_t len)
|
||||
{
|
||||
(void)len;
|
||||
|
||||
g_rndis_tx_busy_flag = false;
|
||||
}
|
||||
|
||||
static size_t usb_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp)
|
||||
{
|
||||
(void)ifp;
|
||||
rndis_data_packet_t *hdr;
|
||||
|
||||
if (!usb_device_is_configured(0))
|
||||
return 0;
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
|
||||
|
||||
memset(hdr, 0, sizeof(rndis_data_packet_t));
|
||||
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
hdr->MessageLength = sizeof(rndis_data_packet_t) + len;
|
||||
hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
|
||||
hdr->DataLength = len;
|
||||
|
||||
memcpy(g_rndis_tx_buffer + sizeof(rndis_data_packet_t), buf, len);
|
||||
|
||||
g_rndis_tx_busy_flag = true;
|
||||
usbd_rndis_start_write(g_rndis_tx_buffer, sizeof(rndis_data_packet_t) + len);
|
||||
while (g_rndis_tx_busy_flag) {
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool usb_poll(struct mg_tcpip_if *ifp, bool s1)
|
||||
{
|
||||
(void)ifp;
|
||||
|
||||
return s1 ? usb_device_is_configured(0) : false;
|
||||
}
|
||||
|
||||
struct mg_tcpip_driver driver = { .tx = usb_tx, .poll = usb_poll };
|
||||
|
||||
struct usbd_interface intf0;
|
||||
struct usbd_interface intf1;
|
||||
|
||||
struct mg_mgr mgr; // Initialise Mongoose event manager
|
||||
|
||||
void cdc_rndis_mongoose_init(uint8_t busid, uint32_t reg_base)
|
||||
{
|
||||
mg_mgr_init(&mgr); // and attach it to the interface
|
||||
|
||||
static struct mg_tcpip_if mif = { .mac = { 2, 0, 1, 2, 3, 0x77 },
|
||||
.enable_dhcp_server = true,
|
||||
.driver = &driver,
|
||||
.recv_queue.size = 4096 };
|
||||
s_ifp = &mif;
|
||||
|
||||
mif.ip = mg_htonl(MG_U32(192, 168, 7, 1));
|
||||
mif.mask = mg_htonl(MG_U32(255, 255, 255, 0));
|
||||
mg_tcpip_init(&mgr, &mif);
|
||||
|
||||
web_init(&mgr);
|
||||
|
||||
usbd_desc_register(busid, &cdc_descriptor);
|
||||
usbd_add_interface(busid, usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, rndis_mac));
|
||||
usbd_add_interface(busid, usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, rndis_mac));
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
// call mg_mgr_poll(&mgr, 0); in main loop
|
||||
BIN
demo/mongoose/mongoose.png
Normal file
BIN
demo/mongoose/mongoose.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 270 KiB |
22
demo/mongoose/mongoose_config.h
Normal file
22
demo/mongoose/mongoose_config.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
// See https://mongoose.ws/documentation/#build-options
|
||||
#define MG_ARCH MG_ARCH_CUSTOM
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#define MG_ENABLE_TCPIP 1
|
||||
#define MG_ENABLE_CUSTOM_MILLIS 1
|
||||
#define MG_ENABLE_CUSTOM_RANDOM 1
|
||||
#define MG_ENABLE_PACKED_FS 1
|
||||
#define MG_IO_SIZE 1460
|
||||
@@ -236,7 +236,7 @@ int usb_msc_fatfs_test()
|
||||
while (write_size > 0) {
|
||||
res_sd = f_write(&fnew, read_write_buffer, BUF_SIZE, (UINT*)&fnum);
|
||||
if (res_sd != FR_OK) {
|
||||
printf("Write file failed, cause: %s\n", res_sd);
|
||||
USB_LOG_RAW("Write file failed, cause: %s\n", res_sd);
|
||||
goto unmount;
|
||||
}
|
||||
write_size -= BUF_SIZE;
|
||||
@@ -262,7 +262,7 @@ int usb_msc_fatfs_test()
|
||||
while (write_size > 0) {
|
||||
res_sd = f_read(&fnew, read_write_buffer, BUF_SIZE, (UINT*)&fnum);
|
||||
if (res_sd != FR_OK) {
|
||||
printf("Read file failed, cause: %s\n", res_sd);
|
||||
USB_LOG_RAW("Read file failed, cause: %s\n", res_sd);
|
||||
goto unmount;
|
||||
}
|
||||
write_size -= BUF_SIZE;
|
||||
|
||||
@@ -469,11 +469,11 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
|
||||
audio_rx_flag = 1;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, AUDIO_OUT_EP, audio_read_buffer, AUDIO_OUT_PACKET);
|
||||
printf("OPEN1\r\n");
|
||||
USB_LOG_RAW("OPEN1\r\n");
|
||||
} else if (intf == 4) {
|
||||
audio_tx_flag = 1;
|
||||
audio_iso_tx_busy = false;
|
||||
printf("OPEN2\r\n");
|
||||
USB_LOG_RAW("OPEN2\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,11 +481,11 @@ void usbd_audio_close(uint8_t busid, uint8_t intf)
|
||||
{
|
||||
if (intf == 3) {
|
||||
audio_rx_flag = 0;
|
||||
printf("CLOSE1\r\n");
|
||||
USB_LOG_RAW("CLOSE1\r\n");
|
||||
} else if (intf == 4) {
|
||||
audio_tx_flag = 0;
|
||||
audio_iso_tx_busy = false;
|
||||
printf("CLOSE2\r\n");
|
||||
USB_LOG_RAW("CLOSE2\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ project = 'CherryUSB'
|
||||
copyright = '2022 ~ 2025, sakumisu'
|
||||
author = 'sakumisu'
|
||||
|
||||
release = '1.5.2'
|
||||
version = '1.5.2'
|
||||
release = '1.5.3'
|
||||
version = '1.5.3'
|
||||
|
||||
# -- General configuration
|
||||
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
usbd_audiov1
|
||||
===============
|
||||
|
||||
.. note:: 在使用windows 时,当修改描述符任意参数时,必须同步修改字符串描述符,并且卸载驱动,否则windows会认为设备未更改,继续使用旧的驱动,导致无法识别设备。Linux 不受此限制。
|
||||
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
usbd_audiov2
|
||||
===============
|
||||
|
||||
.. note:: 在使用windows 时,当修改描述符任意参数时,必须同步修改字符串描述符,并且卸载驱动,否则windows会认为设备未更改,继续使用旧的驱动,导致无法识别设备。Linux 不受此限制。
|
||||
|
||||
.. note:: windows 10 uac2.0 功能不完善,请使用 windows 11 测试uac2.0 功能。Linux 不受此限制。
|
||||
@@ -150,21 +150,6 @@ USB Device 移植要点
|
||||
|
||||
.. figure:: img/stm32_8.png
|
||||
|
||||
- 如果使用 dwc2 ip,需要增加 **dwc2/usb_glue_st.c** 文件,并在 `usb_config.h` 中实现以下宏:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
// 以下细节如有出入,请对照 stm32xxx.h 文件修改
|
||||
// 需要根据硬件实际的 fifo 深度进行修改,默认是最基础的配置
|
||||
#define CONFIG_USBDEV_EP_NUM 6
|
||||
#define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1012 - 16 * 6)
|
||||
#define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
|
||||
#define CONFIG_USB_DWC2_TX1_FIFO_SIZE (64 / 4)
|
||||
#define CONFIG_USB_DWC2_TX2_FIFO_SIZE (64 / 4)
|
||||
#define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
|
||||
#define CONFIG_USB_DWC2_TX4_FIFO_SIZE (64 / 4)
|
||||
#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (64 / 4)
|
||||
|
||||
- 如果使用 fsdev ip,(V1.5.0 开始需要增加 **fsdev/usb_glue_st.c**) 在 `usb_config.h` 中实现以下宏,具体数值不同芯片不一样:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 540 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 125 KiB |
@@ -88,6 +88,13 @@ USB Host ASIX 网卡
|
||||
.. figure:: img/usbhost_ax88772_1.png
|
||||
.. figure:: img/usbhost_ax88772_2.png
|
||||
|
||||
USB Host RNDIS 网卡
|
||||
-----------------------
|
||||
|
||||
演示 USB Host 驱动手机,手机开启 USB 共享网络即可使用 RNDIS 。
|
||||
|
||||
.. figure:: img/usbhost_rndis.png
|
||||
|
||||
USB Host WIFI
|
||||
-----------------------
|
||||
|
||||
|
||||
@@ -148,4 +148,18 @@ v1.5.2
|
||||
- musb 对于标准的 IP 结构采用独立 EP 控制寄存器组,不使用 EPIDX 寄存器去控制
|
||||
- 删除所有 CONFIG_USBDEV_EP_NUM & CONFIG_USBHOST_PIPE_NUM,不再使用,因为 IP 本身会携带这些信息,或者厂家 SDK 提供了对应的宏
|
||||
- CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 默认使用 2 减少内存,只有 UVC 和UAC 使用(商业收费),所以不需要开很大
|
||||
- urb interval 从 u8 改 u32,最大支持 2^15 * 125us
|
||||
- urb interval 从 u8 改 u32,最大支持 2^15 * 125us
|
||||
|
||||
v1.5.3
|
||||
----------------------
|
||||
|
||||
- 增加 mongoose demo
|
||||
- **从机支持自定义 ep0 mps,仅支持商业性 IP**
|
||||
- 主机增加 UVC bulk支持, **接口号匹配驱动功能**, **主机分配地址功能改成循环自增模式** ,重构 lsusb 命令
|
||||
- 主机控制传输增加 retry 机制,部分 device 通信不稳定,retry 次数参考 linux
|
||||
- **主机 rndis 驱动增加非标 02/02/ff 接口驱动匹配**
|
||||
- musb IP 关闭 multipoint feature 支持
|
||||
- hpmicro、chipidea dcache 支持
|
||||
- idf host msc 支持
|
||||
- otg 框架重构,当前 port 仅支持 hpmicro
|
||||
- CI 编译功能,支持 hpmicro/espressif/bouffalolab
|
||||
@@ -1,4 +1,4 @@
|
||||
version: "1.5.2"
|
||||
version: "1.5.3"
|
||||
description: CherryUSB is a tiny and portable USB Stack (device & host) for embedded system with USB IP
|
||||
tags:
|
||||
- usb
|
||||
|
||||
@@ -28,7 +28,12 @@
|
||||
|
||||
// #define CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
/* attribute data into no cache ram */
|
||||
/* attribute data into no cache ram
|
||||
* DRAM_DMA_ALIGNED_ATTR was introduced in IDF 5.3. If not defined, it falls back to DMA_ATTR
|
||||
*/
|
||||
#ifndef DRAM_DMA_ALIGNED_ATTR
|
||||
#define DRAM_DMA_ALIGNED_ATTR DMA_ATTR
|
||||
#endif
|
||||
#define USB_NOCACHE_RAM_SECTION DRAM_DMA_ALIGNED_ATTR
|
||||
|
||||
/* use usb_memcpy default for high performance but cost more flash memory.
|
||||
@@ -144,9 +149,6 @@
|
||||
#define CONFIG_USBDEV_RNDIS_VENDOR_DESC "CherryUSB"
|
||||
#endif
|
||||
|
||||
#define CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
|
||||
/* ================ USB HOST Stack Configuration ================== */
|
||||
|
||||
#define CONFIG_USBHOST_MAX_RHPORTS 1
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifdef __rtems__
|
||||
|
||||
#include "usb_osal.h"
|
||||
#include "usb_errno.h"
|
||||
#include <rtems.h>
|
||||
|
||||
#define SYS_USB_MBOX_SIZE (sizeof(void *))
|
||||
|
||||
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args)
|
||||
{
|
||||
rtems_id id = 0;
|
||||
rtems_status_code res;
|
||||
|
||||
res = rtems_task_create(
|
||||
rtems_build_name(name[0], name[1], name[2], name[3]),
|
||||
prio,
|
||||
stack_size,
|
||||
RTEMS_PREEMPT,
|
||||
0,
|
||||
&id);
|
||||
|
||||
if (res != RTEMS_SUCCESSFUL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = rtems_task_start(id, (rtems_task_entry)entry, (rtems_task_argument)args);
|
||||
|
||||
if (res != RTEMS_SUCCESSFUL) {
|
||||
rtems_task_delete(id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (usb_osal_thread_t)id;
|
||||
}
|
||||
|
||||
void usb_osal_thread_delete(usb_osal_thread_t thread)
|
||||
{
|
||||
rtems_task_delete(thread);
|
||||
}
|
||||
|
||||
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
|
||||
{
|
||||
rtems_id semaphore = 0;
|
||||
rtems_status_code ret = rtems_semaphore_create(
|
||||
rtems_build_name('U', 'S', 'B', 's'),
|
||||
initial_count,
|
||||
RTEMS_COUNTING_SEMAPHORE,
|
||||
0,
|
||||
&semaphore);
|
||||
|
||||
return semaphore;
|
||||
}
|
||||
|
||||
void usb_osal_sem_delete(usb_osal_sem_t sem)
|
||||
{
|
||||
rtems_semaphore_delete(sem);
|
||||
}
|
||||
|
||||
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
|
||||
{
|
||||
rtems_status_code status;
|
||||
status = rtems_semaphore_obtain(sem, RTEMS_WAIT, timeout);
|
||||
return status == RTEMS_SUCCESSFUL ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
int usb_osal_sem_give(usb_osal_sem_t sem)
|
||||
{
|
||||
rtems_status_code status = rtems_semaphore_release(sem);
|
||||
|
||||
return (status == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void)
|
||||
{
|
||||
rtems_id mutex;
|
||||
rtems_status_code ret = rtems_semaphore_create(
|
||||
rtems_build_name('U', 'S', 'B', 'm'),
|
||||
1,
|
||||
RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_LOCAL,
|
||||
0,
|
||||
&mutex);
|
||||
|
||||
return mutex;
|
||||
}
|
||||
|
||||
void usb_osal_mutex_delete(usb_osal_mutex_t mutex)
|
||||
{
|
||||
rtems_semaphore_delete(mutex);
|
||||
}
|
||||
|
||||
int usb_osal_mutex_take(usb_osal_mutex_t mutex)
|
||||
{
|
||||
return (rtems_semaphore_obtain(mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT) == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex)
|
||||
{
|
||||
return (rtems_semaphore_release(mutex) == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
|
||||
{
|
||||
rtems_status_code ret;
|
||||
rtems_id mailbox = 0;
|
||||
ret = rtems_message_queue_create(
|
||||
rtems_build_name('U', 'S', 'B', 'q'),
|
||||
max_msgs,
|
||||
SYS_USB_MBOX_SIZE,
|
||||
RTEMS_DEFAULT_ATTRIBUTES,
|
||||
&mailbox);
|
||||
return mailbox;
|
||||
}
|
||||
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr)
|
||||
{
|
||||
rtems_status_code ret;
|
||||
ret = rtems_message_queue_send(mq, &addr, SYS_USB_MBOX_SIZE);
|
||||
return (ret == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout)
|
||||
{
|
||||
size_t size;
|
||||
rtems_status_code sc;
|
||||
sc = rtems_message_queue_receive(
|
||||
mq,
|
||||
addr,
|
||||
&size,
|
||||
RTEMS_WAIT,
|
||||
timeout);
|
||||
return (sc == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
uint32_t usb_osal_enter_critical_section(void)
|
||||
{
|
||||
rtems_interrupt_level pval;
|
||||
|
||||
#if RTEMS_SMP
|
||||
rtems_recursive_mutex_lock(&sys_arch_lock);
|
||||
#else
|
||||
rtems_interrupt_disable(pval);
|
||||
#endif
|
||||
return pval;
|
||||
}
|
||||
|
||||
void usb_osal_leave_critical_section(size_t flag)
|
||||
{
|
||||
#if RTEMS_SMP
|
||||
rtems_recursive_mutex_unlock(&sys_arch_lock);
|
||||
#else
|
||||
rtems_interrupt_enable(flag);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usb_osal_msleep(uint32_t delay)
|
||||
{
|
||||
rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(delay));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -9,35 +9,23 @@
|
||||
#include "usb_log.h"
|
||||
#include "tx_api.h"
|
||||
|
||||
/* create bytepool in tx_application_define
|
||||
*
|
||||
* tx_byte_pool_create(&usb_byte_pool, "usb byte pool", memory_area, 65536);
|
||||
*/
|
||||
extern TX_BYTE_POOL usb_byte_pool; // define usb_byte_pool and call usb_osal_init first
|
||||
|
||||
extern TX_BYTE_POOL usb_byte_pool;
|
||||
usb_osal_mq_t usb_osal_mq;
|
||||
|
||||
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args)
|
||||
{
|
||||
CHAR *pointer = TX_NULL;
|
||||
TX_THREAD *thread_ptr = TX_NULL;
|
||||
|
||||
tx_byte_allocate(&usb_byte_pool, (VOID **)&thread_ptr, sizeof(TX_THREAD), TX_NO_WAIT);
|
||||
|
||||
tx_byte_allocate(&usb_byte_pool, (VOID **)&thread_ptr, USB_ALIGN_UP(sizeof(TX_THREAD), 4) + stack_size, TX_NO_WAIT);
|
||||
if (thread_ptr == TX_NULL) {
|
||||
USB_LOG_ERR("Create thread %s failed\r\n", name);
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
tx_byte_allocate(&usb_byte_pool, (VOID **)&pointer, stack_size, TX_NO_WAIT);
|
||||
if (pointer == TX_NULL) {
|
||||
USB_LOG_ERR("Create thread %s failed\r\n", name);
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
tx_thread_create(thread_ptr, (CHAR *)name, (VOID(*)(ULONG))entry, (uintptr_t)args,
|
||||
pointer, stack_size,
|
||||
((CHAR *)thread_ptr + USB_ALIGN_UP(sizeof(TX_THREAD), 4)), stack_size,
|
||||
prio, prio, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
return (usb_osal_thread_t)thread_ptr;
|
||||
@@ -45,27 +33,17 @@ usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size,
|
||||
|
||||
void usb_osal_thread_delete(usb_osal_thread_t thread)
|
||||
{
|
||||
TX_THREAD *thread_ptr = NULL;
|
||||
|
||||
if (thread == NULL) {
|
||||
/* Call the tx_thread_identify to get the control block pointer of the
|
||||
currently executing thread. */
|
||||
thread_ptr = tx_thread_identify();
|
||||
thread = tx_thread_identify();
|
||||
|
||||
/* Check if the current running thread pointer is not NULL */
|
||||
if (thread_ptr != NULL) {
|
||||
/* Call the tx_thread_terminate to terminates the specified application
|
||||
thread regardless of whether the thread is suspended or not. A thread
|
||||
may call this service to terminate itself. */
|
||||
tx_thread_terminate(thread_ptr);
|
||||
tx_byte_release(thread_ptr->tx_thread_stack_start);
|
||||
tx_byte_release(thread_ptr);
|
||||
}
|
||||
usb_osal_mq_send(usb_osal_mq, (uintptr_t)thread);
|
||||
|
||||
tx_thread_terminate(thread);
|
||||
return;
|
||||
}
|
||||
|
||||
tx_thread_terminate(thread);
|
||||
tx_byte_release(thread_ptr->tx_thread_stack_start);
|
||||
tx_thread_delete(thread);
|
||||
tx_byte_release(thread);
|
||||
}
|
||||
|
||||
@@ -86,7 +64,6 @@ usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
|
||||
TX_SEMAPHORE *sem_ptr = TX_NULL;
|
||||
|
||||
tx_byte_allocate(&usb_byte_pool, (VOID **)&sem_ptr, sizeof(TX_SEMAPHORE), TX_NO_WAIT);
|
||||
|
||||
if (sem_ptr == TX_NULL) {
|
||||
USB_LOG_ERR("Create semaphore failed\r\n");
|
||||
while (1) {
|
||||
@@ -121,7 +98,7 @@ int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
|
||||
|
||||
int usb_osal_sem_give(usb_osal_sem_t sem)
|
||||
{
|
||||
return (int)tx_semaphore_put((TX_SEMAPHORE *)sem);
|
||||
return (tx_semaphore_put((TX_SEMAPHORE *)sem) == TX_SUCCESS) ? 0 : -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
void usb_osal_sem_reset(usb_osal_sem_t sem)
|
||||
@@ -134,14 +111,13 @@ usb_osal_mutex_t usb_osal_mutex_create(void)
|
||||
TX_MUTEX *mutex_ptr = TX_NULL;
|
||||
|
||||
tx_byte_allocate(&usb_byte_pool, (VOID **)&mutex_ptr, sizeof(TX_MUTEX), TX_NO_WAIT);
|
||||
|
||||
if (mutex_ptr == TX_NULL) {
|
||||
USB_LOG_ERR("Create mutex failed\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
tx_mutex_create(mutex_ptr, "usbh_mutx", TX_INHERIT);
|
||||
tx_mutex_create(mutex_ptr, "usbh_mutex", TX_INHERIT);
|
||||
return (usb_osal_mutex_t)mutex_ptr;
|
||||
}
|
||||
|
||||
@@ -169,38 +145,27 @@ int usb_osal_mutex_take(usb_osal_mutex_t mutex)
|
||||
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex)
|
||||
{
|
||||
return (int)(tx_mutex_put((TX_MUTEX *)mutex) == TX_SUCCESS) ? 0 : -USB_ERR_INVAL;
|
||||
return (tx_mutex_put((TX_MUTEX *)mutex) == TX_SUCCESS) ? 0 : -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
|
||||
{
|
||||
CHAR *pointer = TX_NULL;
|
||||
TX_QUEUE *queue_ptr = TX_NULL;
|
||||
|
||||
tx_byte_allocate(&usb_byte_pool, (VOID **)&queue_ptr, sizeof(TX_QUEUE), TX_NO_WAIT);
|
||||
|
||||
tx_byte_allocate(&usb_byte_pool, (VOID **)&queue_ptr, USB_ALIGN_UP(sizeof(TX_QUEUE), 4) + sizeof(uintptr_t) * max_msgs, TX_NO_WAIT);
|
||||
if (queue_ptr == TX_NULL) {
|
||||
USB_LOG_ERR("Create TX_QUEUE failed\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
tx_byte_allocate(&usb_byte_pool, (VOID **)&pointer, sizeof(uintptr_t) * max_msgs, TX_NO_WAIT);
|
||||
|
||||
if (pointer == TX_NULL) {
|
||||
USB_LOG_ERR("Create mq failed\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
tx_queue_create(queue_ptr, "usbh_mq", sizeof(uintptr_t) / 4, pointer, sizeof(uintptr_t) * max_msgs);
|
||||
tx_queue_create(queue_ptr, "usbh_mq", sizeof(uintptr_t) / 4, (CHAR *)queue_ptr + USB_ALIGN_UP(sizeof(TX_QUEUE), 4), sizeof(uintptr_t) * max_msgs);
|
||||
return (usb_osal_mq_t)queue_ptr;
|
||||
}
|
||||
|
||||
void usb_osal_mq_delete(usb_osal_mq_t mq)
|
||||
{
|
||||
tx_queue_delete((TX_QUEUE *)mq);
|
||||
tx_byte_release(((TX_QUEUE *)mq)->tx_queue_start);
|
||||
tx_byte_release(mq);
|
||||
}
|
||||
|
||||
@@ -231,7 +196,6 @@ struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_
|
||||
struct usb_osal_timer *timer;
|
||||
|
||||
tx_byte_allocate(&usb_byte_pool, (VOID **)&timer, sizeof(struct usb_osal_timer), TX_NO_WAIT);
|
||||
|
||||
if (timer == TX_NULL) {
|
||||
USB_LOG_ERR("Create usb_osal_timer failed\r\n");
|
||||
while (1) {
|
||||
@@ -240,7 +204,6 @@ struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_
|
||||
memset(timer, 0, sizeof(struct usb_osal_timer));
|
||||
|
||||
tx_byte_allocate(&usb_byte_pool, (VOID **)&timer_ptr, sizeof(TX_TIMER), TX_NO_WAIT);
|
||||
|
||||
if (timer_ptr == TX_NULL) {
|
||||
USB_LOG_ERR("Create TX_TIMER failed\r\n");
|
||||
while (1) {
|
||||
@@ -269,8 +232,8 @@ void usb_osal_timer_start(struct usb_osal_timer *timer)
|
||||
{
|
||||
if (tx_timer_change((TX_TIMER *)timer->timer, timer->timeout_ms, timer->is_period ? timer->timeout_ms : 0) == TX_SUCCESS) {
|
||||
/* Call the tx_timer_activate to activates the specified application
|
||||
timer. The expiration routines of timers that expire at the same
|
||||
time are executed in the order they were activated. */
|
||||
timer. The expiration routines of timers that expire at the same
|
||||
time are executed in the order they were activated. */
|
||||
if (tx_timer_activate((TX_TIMER *)timer->timer) == TX_SUCCESS) {
|
||||
/* Return osOK for success */
|
||||
} else {
|
||||
@@ -296,7 +259,7 @@ size_t usb_osal_enter_critical_section(void)
|
||||
|
||||
void usb_osal_leave_critical_section(size_t flag)
|
||||
{
|
||||
int interrupt_save;
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
interrupt_save = flag;
|
||||
TX_RESTORE
|
||||
@@ -322,4 +285,40 @@ void *usb_osal_malloc(size_t size)
|
||||
void usb_osal_free(void *ptr)
|
||||
{
|
||||
tx_byte_release(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_osal_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
int ret;
|
||||
usb_osal_thread_t thread;
|
||||
|
||||
while (1) {
|
||||
ret = usb_osal_mq_recv(usb_osal_mq, (uintptr_t *)&thread, TX_WAIT_FOREVER);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
tx_thread_delete(thread);
|
||||
tx_byte_release(thread);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_osal_init(uint8_t *mem, uint32_t mem_size)
|
||||
{
|
||||
usb_osal_thread_t thread;
|
||||
|
||||
tx_byte_pool_create(&usb_byte_pool, "usb byte pool", mem, mem_size);
|
||||
|
||||
thread = usb_osal_thread_create("usb_osal", 2048, 10, usb_osal_thread, NULL);
|
||||
if (thread == NULL) {
|
||||
USB_LOG_ERR("Create usb_osal_thread failed\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
usb_osal_mq = usb_osal_mq_create(32);
|
||||
if (usb_osal_mq == NULL) {
|
||||
USB_LOG_ERR("Create usb_osal_mq failed\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usb_osal.h"
|
||||
#include "usb_errno.h"
|
||||
#include <aos/kernel.h>
|
||||
#include <csi_core.h>
|
||||
|
||||
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args)
|
||||
{
|
||||
aos_task_t task_handle = NULL;
|
||||
|
||||
aos_task_new_ext(&task_handle, name, entry, args, stack_size, prio + AOS_DEFAULT_APP_PRI - 4);
|
||||
|
||||
return task_handle;
|
||||
}
|
||||
|
||||
void usb_osal_thread_delete(usb_osal_thread_t thread)
|
||||
{
|
||||
aos_task_exit(0);
|
||||
}
|
||||
|
||||
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
|
||||
{
|
||||
aos_sem_t sem = NULL;
|
||||
|
||||
aos_sem_new(&sem, initial_count);
|
||||
|
||||
return sem;
|
||||
}
|
||||
|
||||
void usb_osal_sem_delete(usb_osal_sem_t sem)
|
||||
{
|
||||
aos_sem_free((aos_sem_t *)&sem);
|
||||
}
|
||||
|
||||
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
|
||||
{
|
||||
if (timeout == USB_OSAL_WAITING_FOREVER) {
|
||||
return aos_sem_wait((aos_sem_t *)&sem, AOS_WAIT_FOREVER);
|
||||
} else {
|
||||
return aos_sem_wait((aos_sem_t *)&sem, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
int usb_osal_sem_give(usb_osal_sem_t sem)
|
||||
{
|
||||
aos_sem_signal((aos_sem_t *)&sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usb_osal_sem_reset(usb_osal_sem_t sem)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void)
|
||||
{
|
||||
aos_mutex_t mutex = NULL;
|
||||
|
||||
aos_mutex_new(&mutex);
|
||||
|
||||
return (usb_osal_mutex_t)mutex;
|
||||
}
|
||||
|
||||
void usb_osal_mutex_delete(usb_osal_mutex_t mutex)
|
||||
{
|
||||
aos_mutex_free(((aos_mutex_t *)&mutex));
|
||||
}
|
||||
|
||||
int usb_osal_mutex_take(usb_osal_mutex_t mutex)
|
||||
{
|
||||
return aos_mutex_lock(((aos_mutex_t *)&mutex), AOS_WAIT_FOREVER);
|
||||
}
|
||||
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex)
|
||||
{
|
||||
return aos_mutex_unlock(((aos_mutex_t *)&mutex));
|
||||
}
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
|
||||
{
|
||||
aos_queue_t queue = NULL;
|
||||
|
||||
aos_queue_create(&queue, sizeof(uintptr_t), max_msgs, 0);
|
||||
|
||||
return (usb_osal_mq_t)queue;
|
||||
}
|
||||
|
||||
void usb_osal_mq_delete(usb_osal_mq_t mq)
|
||||
{
|
||||
aos_queue_free((aos_queue_t)mq);
|
||||
}
|
||||
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr)
|
||||
{
|
||||
return aos_queue_send((aos_queue_t *)&mq, &addr, sizeof(uintptr_t));
|
||||
}
|
||||
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout)
|
||||
{
|
||||
size_t recv_size;
|
||||
if (timeout == USB_OSAL_WAITING_FOREVER) {
|
||||
return aos_queue_recv((aos_queue_t *)&mq, AOS_WAIT_FOREVER, addr, &recv_size);
|
||||
} else {
|
||||
return aos_queue_recv((aos_queue_t *)&mq, timeout, addr, &recv_size);
|
||||
}
|
||||
}
|
||||
|
||||
size_t usb_osal_enter_critical_section(void)
|
||||
{
|
||||
return csi_irq_save();
|
||||
}
|
||||
|
||||
void usb_osal_leave_critical_section(size_t flag)
|
||||
{
|
||||
csi_irq_restore(flag);
|
||||
}
|
||||
|
||||
void usb_osal_msleep(uint32_t delay)
|
||||
{
|
||||
aos_msleep(delay);
|
||||
}
|
||||
|
||||
void *usb_osal_malloc(size_t size)
|
||||
{
|
||||
return aos_malloc(size);
|
||||
}
|
||||
|
||||
void usb_osal_free(void *ptr)
|
||||
{
|
||||
aos_free(ptr);
|
||||
}
|
||||
@@ -5,175 +5,313 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "dap_main.h"
|
||||
#include "DAP_config.h"
|
||||
#include "DAP.h"
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + CMSIS_DAP_INTERFACE_SIZE + CDC_ACM_DESCRIPTOR_LEN + CONFIG_MSC_DESCRIPTOR_LEN)
|
||||
#define INTF_NUM (2 + 1 + CONFIG_MSC_INTF_NUM)
|
||||
#define CMSIS_DAP_INTERFACE_SIZE (9 + 7 + 7)
|
||||
#define CUSTOM_HID_LEN (9 + 9 + 7 + 7)
|
||||
|
||||
#define HIDRAW_INTERVAL 4
|
||||
|
||||
#define HID_CUSTOM_REPORT_DESC_SIZE 53
|
||||
|
||||
#define USBD_WINUSB_VENDOR_CODE 0x20
|
||||
#define USBD_WEBUSB_VENDOR_CODE 0x21
|
||||
|
||||
#define USBD_WEBUSB_ENABLE 1
|
||||
#define USBD_BULK_ENABLE 1
|
||||
#define USBD_WINUSB_ENABLE 1
|
||||
|
||||
/* WinUSB Microsoft OS 2.0 descriptor sizes */
|
||||
#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE 10
|
||||
#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
|
||||
#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE 20
|
||||
|
||||
#define FUNCTION_SUBSET_LEN 160
|
||||
#define DEVICE_INTERFACE_GUIDS_FEATURE_LEN 132
|
||||
|
||||
#define USBD_WINUSB_DESC_SET_LEN (WINUSB_DESCRIPTOR_SET_HEADER_SIZE + USBD_WEBUSB_ENABLE * FUNCTION_SUBSET_LEN + USBD_BULK_ENABLE * FUNCTION_SUBSET_LEN)
|
||||
|
||||
#define USBD_NUM_DEV_CAPABILITIES (USBD_WEBUSB_ENABLE + USBD_WINUSB_ENABLE)
|
||||
|
||||
#define USBD_WEBUSB_DESC_LEN 24
|
||||
#define USBD_WINUSB_DESC_LEN 28
|
||||
|
||||
#define USBD_BOS_WTOTALLENGTH (0x05 + \
|
||||
USBD_WEBUSB_DESC_LEN * USBD_WEBUSB_ENABLE + \
|
||||
USBD_WINUSB_DESC_LEN * USBD_WINUSB_ENABLE)
|
||||
|
||||
#define USB_CONFIG_SIZE (9 + CMSIS_DAP_INTERFACE_SIZE + CDC_ACM_DESCRIPTOR_LEN + \
|
||||
CONFIG_CHERRYDAP_USE_CUSTOM_HID * CUSTOM_HID_LEN + \
|
||||
CONFIG_CHERRYDAP_USE_MSC * MSC_DESCRIPTOR_LEN + USBD_WEBUSB_ENABLE * 9)
|
||||
|
||||
#define INTF_NUM (1 + 2 + CONFIG_CHERRYDAP_USE_CUSTOM_HID + CONFIG_CHERRYDAP_USE_MSC + USBD_WEBUSB_ENABLE)
|
||||
|
||||
#define MSC_INTF_NUM (3 + CONFIG_CHERRYDAP_USE_CUSTOM_HID)
|
||||
|
||||
#define WEBUSB_INTF_NUM (3 + CONFIG_CHERRYDAP_USE_CUSTOM_HID + CONFIG_CHERRYDAP_USE_MSC)
|
||||
|
||||
#define WEBUSB_URL_STRINGS \
|
||||
'c', 'h', 'e', 'r', 'r', 'y', 'd', 'a', 'p', '.', 'c', 'h', 'e', 'r', 'r', 'y', '-', 'e', 'm', 'b', 'e', 'd', 'd', 'e', 'd', '.', 'o', 'r', 'g',
|
||||
|
||||
__ALIGN_BEGIN const uint8_t USBD_WinUSBDescriptorSetDescriptor[] = {
|
||||
WBVAL(WINUSB_DESCRIPTOR_SET_HEADER_SIZE), /* wLength */
|
||||
WBVAL(WINUSB_SET_HEADER_DESCRIPTOR_TYPE), /* wDescriptorType */
|
||||
0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
|
||||
WBVAL(USBD_WINUSB_DESC_SET_LEN), /* wDescriptorSetTotalLength */
|
||||
WBVAL(WINUSB_DESCRIPTOR_SET_HEADER_SIZE), /* wLength */
|
||||
WBVAL(WINUSB_SET_HEADER_DESCRIPTOR_TYPE), /* wDescriptorType */
|
||||
0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
|
||||
WBVAL(USBD_WINUSB_DESC_SET_LEN), /* wDescriptorSetTotalLength */
|
||||
#if (USBD_WEBUSB_ENABLE)
|
||||
WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), // wLength
|
||||
WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), // wDescriptorType
|
||||
0, // bFirstInterface USBD_WINUSB_IF_NUM
|
||||
0, // bReserved
|
||||
WBVAL(FUNCTION_SUBSET_LEN), // wSubsetLength
|
||||
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE), // wLength
|
||||
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE), // wDescriptorType
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0, 0, // CompatibleId
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // SubCompatibleId
|
||||
WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), // wLength
|
||||
WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), // wDescriptorType
|
||||
WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), // wPropertyDataType
|
||||
WBVAL(42), // wPropertyNameLength
|
||||
'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
|
||||
'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
|
||||
'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
|
||||
WBVAL(80), // wPropertyDataLength
|
||||
'{', 0,
|
||||
'9', 0, '2', 0, 'C', 0, 'E', 0, '6', 0, '4', 0, '6', 0, '2', 0, '-', 0,
|
||||
'9', 0, 'C', 0, '7', 0, '7', 0, '-', 0,
|
||||
'4', 0, '6', 0, 'F', 0, 'E', 0, '-', 0,
|
||||
'9', 0, '3', 0, '3', 0, 'B', 0, '-',
|
||||
0, '3', 0, '1', 0, 'C', 0, 'B', 0, '9', 0, 'C', 0, '5', 0, 'A', 0, 'A', 0, '3', 0, 'B', 0, '9', 0,
|
||||
'}', 0, 0, 0, 0, 0
|
||||
WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), // wLength
|
||||
WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), // wDescriptorType
|
||||
WEBUSB_INTF_NUM, // bFirstInterface USBD_WINUSB_IF_NUM
|
||||
0, // bReserved
|
||||
WBVAL(FUNCTION_SUBSET_LEN), // wSubsetLength
|
||||
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE), // wLength
|
||||
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE), // wDescriptorType
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0, 0, // CompatibleId
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // SubCompatibleId
|
||||
WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), // wLength
|
||||
WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), // wDescriptorType
|
||||
WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), // wPropertyDataType
|
||||
WBVAL(42), // wPropertyNameLength
|
||||
'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
|
||||
'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
|
||||
'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
|
||||
WBVAL(80), // wPropertyDataLength
|
||||
'{', 0,
|
||||
'9', 0, '2', 0, 'C', 0, 'E', 0, '6', 0, '4', 0, '6', 0, '2', 0, '-', 0,
|
||||
'9', 0, 'C', 0, '7', 0, '7', 0, '-', 0,
|
||||
'4', 0, '6', 0, 'F', 0, 'E', 0, '-', 0,
|
||||
'9', 0, '3', 0, '3', 0, 'B', 0, '-',
|
||||
0, '3', 0, '1', 0, 'C', 0, 'B', 0, '9', 0, 'C', 0, '5', 0, 'A', 0, 'A', 0, '3', 0, 'B', 0, '9', 0,
|
||||
'}', 0, 0, 0, 0, 0,
|
||||
#endif
|
||||
#if USBD_BULK_ENABLE
|
||||
WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), /* wLength */
|
||||
WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), /* wDescriptorType */
|
||||
0, /* bFirstInterface USBD_BULK_IF_NUM*/
|
||||
0, /* bReserved */
|
||||
WBVAL(FUNCTION_SUBSET_LEN), /* wSubsetLength */
|
||||
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE), /* wLength */
|
||||
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE), /* wDescriptorType */
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0, 0, /* CompatibleId*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* SubCompatibleId*/
|
||||
WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), /* wLength */
|
||||
WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), /* wDescriptorType */
|
||||
WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), /* wPropertyDataType */
|
||||
WBVAL(42), /* wPropertyNameLength */
|
||||
'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
|
||||
'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
|
||||
'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
|
||||
WBVAL(80), /* wPropertyDataLength */
|
||||
'{', 0,
|
||||
'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0, 'A', 0, 'D', 0, '-', 0,
|
||||
'2', 0, '9', 0, '3', 0, 'B', 0, '-', 0,
|
||||
'4', 0, '6', 0, '6', 0, '3', 0, '-', 0,
|
||||
'A', 0, 'A', 0, '3', 0, '6', 0, '-',
|
||||
0, '1', 0, 'A', 0, 'A', 0, 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0, '7', 0, '6', 0,
|
||||
'}', 0, 0, 0, 0, 0
|
||||
WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), /* wLength */
|
||||
WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), /* wDescriptorType */
|
||||
0, /* bFirstInterface USBD_BULK_IF_NUM*/
|
||||
0, /* bReserved */
|
||||
WBVAL(FUNCTION_SUBSET_LEN), /* wSubsetLength */
|
||||
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE), /* wLength */
|
||||
WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE), /* wDescriptorType */
|
||||
'W', 'I', 'N', 'U', 'S', 'B', 0, 0, /* CompatibleId*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* SubCompatibleId*/
|
||||
WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), /* wLength */
|
||||
WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), /* wDescriptorType */
|
||||
WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), /* wPropertyDataType */
|
||||
WBVAL(42), /* wPropertyNameLength */
|
||||
'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
|
||||
'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
|
||||
'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
|
||||
WBVAL(80), /* wPropertyDataLength */
|
||||
'{', 0,
|
||||
'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0, 'A', 0, 'D', 0, '-', 0,
|
||||
'2', 0, '9', 0, '3', 0, 'B', 0, '-', 0,
|
||||
'4', 0, '6', 0, '6', 0, '3', 0, '-', 0,
|
||||
'A', 0, 'A', 0, '3', 0, '6', 0, '-',
|
||||
0, '1', 0, 'A', 0, 'A', 0, 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0, '7', 0, '6', 0,
|
||||
'}', 0, 0, 0, 0, 0
|
||||
#endif
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
|
||||
0x05, /* bLength */
|
||||
0x0f, /* bDescriptorType */
|
||||
WBVAL(USBD_BOS_WTOTALLENGTH), /* wTotalLength */
|
||||
USBD_NUM_DEV_CAPABILITIES, /* bNumDeviceCaps */
|
||||
0x05, /* bLength */
|
||||
0x0f, /* bDescriptorType */
|
||||
WBVAL(USBD_BOS_WTOTALLENGTH), /* wTotalLength */
|
||||
USBD_NUM_DEV_CAPABILITIES, /* bNumDeviceCaps */
|
||||
#if (USBD_WEBUSB_ENABLE)
|
||||
USBD_WEBUSB_DESC_LEN, /* bLength */
|
||||
0x10, /* bDescriptorType */
|
||||
USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
|
||||
0x00, /* bReserved */
|
||||
0x38, 0xB6, 0x08, 0x34, /* PlatformCapabilityUUID */
|
||||
0xA9, 0x09, 0xA0, 0x47,
|
||||
0x8B, 0xFD, 0xA0, 0x76,
|
||||
0x88, 0x15, 0xB6, 0x65,
|
||||
WBVAL(0x0100), /* 1.00 */ /* bcdVersion */
|
||||
USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
|
||||
0, /* iLandingPage */
|
||||
USBD_WEBUSB_DESC_LEN, /* bLength */
|
||||
0x10, /* bDescriptorType */
|
||||
USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
|
||||
0x00, /* bReserved */
|
||||
0x38, 0xB6, 0x08, 0x34, /* PlatformCapabilityUUID */
|
||||
0xA9, 0x09, 0xA0, 0x47,
|
||||
0x8B, 0xFD, 0xA0, 0x76,
|
||||
0x88, 0x15, 0xB6, 0x65,
|
||||
WBVAL(0x0100), /* 1.00 */ /* bcdVersion */
|
||||
USBD_WEBUSB_VENDOR_CODE, /* bVendorCode */
|
||||
1, /* iLandingPage */
|
||||
#endif
|
||||
#if (USBD_WINUSB_ENABLE)
|
||||
USBD_WINUSB_DESC_LEN, /* bLength */
|
||||
0x10, /* bDescriptorType */
|
||||
USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
|
||||
0x00, /* bReserved */
|
||||
0xDF, 0x60, 0xDD, 0xD8, /* PlatformCapabilityUUID */
|
||||
0x89, 0x45, 0xC7, 0x4C,
|
||||
0x9C, 0xD2, 0x65, 0x9D,
|
||||
0x9E, 0x64, 0x8A, 0x9F,
|
||||
0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
|
||||
WBVAL(USBD_WINUSB_DESC_SET_LEN), /* wDescriptorSetTotalLength */
|
||||
USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
|
||||
0, /* bAltEnumCode */
|
||||
USBD_WINUSB_DESC_LEN, /* bLength */
|
||||
0x10, /* bDescriptorType */
|
||||
USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
|
||||
0x00, /* bReserved */
|
||||
0xDF, 0x60, 0xDD, 0xD8, /* PlatformCapabilityUUID */
|
||||
0x89, 0x45, 0xC7, 0x4C,
|
||||
0x9C, 0xD2, 0x65, 0x9D,
|
||||
0x9E, 0x64, 0x8A, 0x9F,
|
||||
0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
|
||||
WBVAL(USBD_WINUSB_DESC_SET_LEN), /* wDescriptorSetTotalLength */
|
||||
USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
|
||||
0, /* bAltEnumCode */
|
||||
#endif
|
||||
};
|
||||
|
||||
#define URL_DESCRIPTOR_LENGTH (3 + 29)
|
||||
|
||||
const uint8_t USBD_WebUSBURLDescriptor[URL_DESCRIPTOR_LENGTH] = {
|
||||
URL_DESCRIPTOR_LENGTH,
|
||||
WEBUSB_URL_TYPE,
|
||||
WEBUSB_URL_SCHEME_HTTPS,
|
||||
WEBUSB_URL_STRINGS
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
#define HID_DESC() \
|
||||
/************** Descriptor of Custom interface *****************/ \
|
||||
0x09, /* bLength: Interface Descriptor size */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ \
|
||||
0X03, /* bInterfaceNumber: Number of Interface */ \
|
||||
0x00, /* bAlternateSetting: Alternate setting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
0x03, /* bInterfaceClass: HID */ \
|
||||
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ \
|
||||
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ \
|
||||
0, /* iInterface: Index of string descriptor */ /******************** Descriptor of Custom HID ********************/ \
|
||||
0x09, /* bLength: HID Descriptor size */ \
|
||||
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */ \
|
||||
0x11, /* bcdHID: HID Class Spec release number */ \
|
||||
0x01, \
|
||||
0x00, /* bCountryCode: Hardware target country */ \
|
||||
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ \
|
||||
0x22, /* bDescriptorType */ \
|
||||
HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ \
|
||||
0x00, /******************** Descriptor of Custom in endpoint ********************/ \
|
||||
0x07, /* bLength: Endpoint Descriptor size */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ \
|
||||
HID_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */ \
|
||||
0x03, /* bmAttributes: Interrupt endpoint */ \
|
||||
WBVAL(HID_PACKET_SIZE), /* wMaxPacketSize: 4 Byte max */ \
|
||||
HIDRAW_INTERVAL, /* bInterval: Polling Interval */ /******************** Descriptor of Custom out endpoint ********************/ \
|
||||
0x07, /* bLength: Endpoint Descriptor size */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ \
|
||||
HID_OUT_EP, /* bEndpointAddress: Endpoint Address (IN) */ \
|
||||
0x03, /* bmAttributes: Interrupt endpoint */ \
|
||||
WBVAL(HID_PACKET_SIZE), /* wMaxPacketSize: 4 Byte max */ \
|
||||
HIDRAW_INTERVAL /* bInterval: Polling Interval */
|
||||
// clang-format on
|
||||
|
||||
static const uint8_t device_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
};
|
||||
|
||||
static const uint8_t config_descriptor[] = {
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
/* Interface 0 */
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
|
||||
/* Endpoint OUT 2 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_OUT_EP, USB_ENDPOINT_TYPE_BULK, DAP_PACKET_SIZE, 0x00),
|
||||
/* Endpoint IN 1 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_IN_EP, USB_ENDPOINT_TYPE_BULK, DAP_PACKET_SIZE, 0x00),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, DAP_PACKET_SIZE, 0x00),
|
||||
#ifdef CONFIG_CHERRYDAP_USE_MSC
|
||||
MSC_DESCRIPTOR_INIT(MSC_INTF_NUM, MSC_OUT_EP, MSC_IN_EP, DAP_PACKET_SIZE, 0x00),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
/* Interface 0 */
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
|
||||
/* Endpoint OUT 2 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_OUT_EP, USB_ENDPOINT_TYPE_BULK, DAP_PACKET_SIZE, 0x00),
|
||||
/* Endpoint IN 1 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_IN_EP, USB_ENDPOINT_TYPE_BULK, DAP_PACKET_SIZE, 0x00),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, DAP_PACKET_SIZE, 0x00),
|
||||
#if CONFIG_CHERRYDAP_USE_CUSTOM_HID
|
||||
HID_DESC(),
|
||||
#endif
|
||||
#if CONFIG_CHERRYDAP_USE_MSC
|
||||
MSC_DESCRIPTOR_INIT(MSC_INTF_NUM, MSC_OUT_EP, MSC_IN_EP, DAP_PACKET_SIZE, 0x00),
|
||||
#endif
|
||||
#if USBD_WEBUSB_ENABLE
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(WEBUSB_INTF_NUM, 0x00, 0x00, 0xff, 0x00, 0x00, 0x04),
|
||||
#endif
|
||||
};
|
||||
|
||||
static const uint8_t other_speed_config_descriptor[] = {
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
/* Interface 0 */
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
|
||||
/* Endpoint OUT 2 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_OUT_EP, USB_ENDPOINT_TYPE_BULK, DAP_PACKET_SIZE, 0x00),
|
||||
/* Endpoint IN 1 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_IN_EP, USB_ENDPOINT_TYPE_BULK, DAP_PACKET_SIZE, 0x00),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, DAP_PACKET_SIZE, 0x00),
|
||||
#ifdef CONFIG_CHERRYDAP_USE_MSC
|
||||
MSC_DESCRIPTOR_INIT(MSC_INTF_NUM, MSC_OUT_EP, MSC_IN_EP, DAP_PACKET_SIZE, 0x00),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
/* Interface 0 */
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
|
||||
/* Endpoint OUT 2 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_OUT_EP, USB_ENDPOINT_TYPE_BULK, DAP_PACKET_SIZE, 0x00),
|
||||
/* Endpoint IN 1 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_IN_EP, USB_ENDPOINT_TYPE_BULK, DAP_PACKET_SIZE, 0x00),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, DAP_PACKET_SIZE, 0x00),
|
||||
#if CONFIG_CHERRYDAP_USE_CUSTOM_HID
|
||||
HID_DESC(),
|
||||
#endif
|
||||
#if CONFIG_CHERRYDAP_USE_MSC
|
||||
MSC_DESCRIPTOR_INIT(0x04, MSC_OUT_EP, MSC_IN_EP, DAP_PACKET_SIZE, 0x00),
|
||||
#endif
|
||||
#if USBD_WEBUSB_ENABLE
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(WEBUSB_INTF_NUM, 0x00, 0x00, 0xff, 0x00, 0x00, 0x04),
|
||||
#endif
|
||||
};
|
||||
|
||||
/*!< custom hid report descriptor */
|
||||
const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
|
||||
/* USER CODE BEGIN 0 */
|
||||
0x06, 0x00, 0xff, /* USAGE_PAGE (Vendor Defined Page 1) */
|
||||
0x09, 0x01, /* USAGE (Vendor Usage 1) */
|
||||
0xa1, 0x01, /* COLLECTION (Application) */
|
||||
0x85, 0x02, /* REPORT ID (0x02) */
|
||||
0x09, 0x02, /* USAGE (Vendor Usage 1) */
|
||||
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
|
||||
0x25, 0xff, /*LOGICAL_MAXIMUM (255) */
|
||||
0x75, 0x08, /* REPORT_SIZE (8) */
|
||||
0x96, 0xff, 0x03, /* REPORT_COUNT (1023) */
|
||||
0x81, 0x02, /* INPUT (Data,Var,Abs) */
|
||||
/* <___________________________________________________> */
|
||||
0x85, 0x01, /* REPORT ID (0x01) */
|
||||
0x09, 0x03, /* USAGE (Vendor Usage 1) */
|
||||
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
|
||||
0x25, 0xff, /* LOGICAL_MAXIMUM (255) */
|
||||
0x75, 0x08, /* REPORT_SIZE (8) */
|
||||
0x96, 0xff, 0x03, /* REPORT_COUNT (1023) */
|
||||
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
|
||||
|
||||
/* <___________________________________________________> */
|
||||
0x85, 0x03, /* REPORT ID (0x03) */
|
||||
0x09, 0x04, /* USAGE (Vendor Usage 1) */
|
||||
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
|
||||
0x25, 0xff, /* LOGICAL_MAXIMUM (255) */
|
||||
0x75, 0x08, /* REPORT_SIZE (8) */
|
||||
0x96, 0xff, 0x03, /* REPORT_COUNT (1023) */
|
||||
0xb1, 0x02, /* FEATURE (Data,Var,Abs) */
|
||||
/* USER CODE END 0 */
|
||||
0xC0 /* END_COLLECTION */
|
||||
};
|
||||
|
||||
char serial_number_dynamic[36] = "00000000000000000123456789ABCDEF"; // Dynamic serial number
|
||||
|
||||
char *string_descriptors[] = {
|
||||
(char[]) {0x09, 0x04}, /* Langid */
|
||||
"CherryUSB", /* Manufacturer */
|
||||
"CherryUSB CMSIS-DAP", /* Product */
|
||||
"00000000000000000123456789ABCDEF", /* Serial Number */
|
||||
(char[]){ 0x09, 0x04 }, /* Langid */
|
||||
"CherryUSB", /* Manufacturer */
|
||||
"CherryUSB CMSIS-DAP", /* Product */
|
||||
"00000000000000000123456789ABCDEF", /* Serial Number */
|
||||
"CherryUSB WebUSB",
|
||||
};
|
||||
|
||||
static const uint8_t device_quality_descriptor[] = {
|
||||
USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, 0x01),
|
||||
USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, 0x01),
|
||||
};
|
||||
|
||||
__WEAK const uint8_t *device_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
(void) speed;
|
||||
(void)speed;
|
||||
return device_descriptor;
|
||||
}
|
||||
|
||||
__WEAK const uint8_t *config_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
(void) speed;
|
||||
(void)speed;
|
||||
return config_descriptor;
|
||||
}
|
||||
|
||||
__WEAK const uint8_t *device_quality_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
(void) speed;
|
||||
(void)speed;
|
||||
return device_quality_descriptor;
|
||||
}
|
||||
|
||||
__WEAK const uint8_t *other_speed_config_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
(void) speed;
|
||||
(void)speed;
|
||||
return other_speed_config_descriptor;
|
||||
}
|
||||
|
||||
__WEAK const char *string_descriptor_callback(uint8_t speed, uint8_t index)
|
||||
{
|
||||
(void) speed;
|
||||
(void)speed;
|
||||
|
||||
if (index == 3) {
|
||||
return serial_number_dynamic;
|
||||
}
|
||||
|
||||
if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
|
||||
return NULL;
|
||||
@@ -214,7 +352,7 @@ USB_NOCACHE_RAM_SECTION chry_ringbuffer_t g_usbrx;
|
||||
|
||||
void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
{
|
||||
(void) busid;
|
||||
(void)busid;
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
usbrx_idle_flag = 0;
|
||||
@@ -250,7 +388,7 @@ void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
|
||||
void dap_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void) busid;
|
||||
(void)busid;
|
||||
if (USB_Request[USB_RequestIndexI][0] == ID_DAP_TransferAbort) {
|
||||
DAP_TransferAbort = 1U;
|
||||
} else {
|
||||
@@ -262,7 +400,7 @@ void dap_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
}
|
||||
|
||||
// Start reception of next request packet
|
||||
if ((uint16_t) (USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
|
||||
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
|
||||
usbd_ep_start_read(0, DAP_OUT_EP, USB_Request[USB_RequestIndexI], DAP_PACKET_SIZE);
|
||||
} else {
|
||||
USB_RequestIdle = 1U;
|
||||
@@ -271,7 +409,7 @@ void dap_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
|
||||
void dap_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void) busid;
|
||||
(void)busid;
|
||||
if (USB_ResponseCountI != USB_ResponseCountO) {
|
||||
// Load data from response buffer to be sent back
|
||||
usbd_ep_start_write(0, DAP_IN_EP, USB_Response[USB_ResponseIndexO], USB_RespSize[USB_ResponseIndexO]);
|
||||
@@ -287,7 +425,7 @@ void dap_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void) busid;
|
||||
(void)busid;
|
||||
chry_ringbuffer_write(&g_usbrx, usb_tmpbuffer, nbytes);
|
||||
if (chry_ringbuffer_get_free(&g_usbrx) >= DAP_PACKET_SIZE) {
|
||||
usbd_ep_start_read(0, CDC_OUT_EP, usb_tmpbuffer, DAP_PACKET_SIZE);
|
||||
@@ -298,7 +436,7 @@ void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
|
||||
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void) busid;
|
||||
(void)busid;
|
||||
uint32_t size;
|
||||
uint8_t *buffer;
|
||||
|
||||
@@ -317,52 +455,110 @@ void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
}
|
||||
|
||||
struct usbd_endpoint dap_out_ep = {
|
||||
.ep_addr = DAP_OUT_EP,
|
||||
.ep_cb = dap_out_callback
|
||||
.ep_addr = DAP_OUT_EP,
|
||||
.ep_cb = dap_out_callback
|
||||
};
|
||||
|
||||
struct usbd_endpoint dap_in_ep = {
|
||||
.ep_addr = DAP_IN_EP,
|
||||
.ep_cb = dap_in_callback
|
||||
.ep_addr = DAP_IN_EP,
|
||||
.ep_cb = dap_in_callback
|
||||
};
|
||||
|
||||
struct usbd_endpoint cdc_out_ep = {
|
||||
.ep_addr = CDC_OUT_EP,
|
||||
.ep_cb = usbd_cdc_acm_bulk_out
|
||||
.ep_addr = CDC_OUT_EP,
|
||||
.ep_cb = usbd_cdc_acm_bulk_out
|
||||
};
|
||||
|
||||
struct usbd_endpoint cdc_in_ep = {
|
||||
.ep_addr = CDC_IN_EP,
|
||||
.ep_cb = usbd_cdc_acm_bulk_in
|
||||
.ep_addr = CDC_IN_EP,
|
||||
.ep_cb = usbd_cdc_acm_bulk_in
|
||||
};
|
||||
|
||||
#if CONFIG_CHERRYDAP_USE_CUSTOM_HID
|
||||
struct usbd_endpoint hid_custom_in_ep = {
|
||||
.ep_addr = HID_IN_EP,
|
||||
.ep_cb = usbd_hid_custom_in_callback,
|
||||
};
|
||||
|
||||
struct usbd_endpoint hid_custom_out_ep = {
|
||||
.ep_addr = HID_OUT_EP,
|
||||
.ep_cb = usbd_hid_custom_out_callback,
|
||||
};
|
||||
#endif
|
||||
|
||||
struct usbd_interface dap_intf;
|
||||
struct usbd_interface intf1;
|
||||
struct usbd_interface intf2;
|
||||
struct usbd_interface intf3;
|
||||
#if CONFIG_CHERRYDAP_USE_CUSTOM_HID
|
||||
struct usbd_interface hid_intf;
|
||||
#endif
|
||||
|
||||
#if CONFIG_CHERRYDAP_USE_MSC
|
||||
struct usbd_interface intf3;
|
||||
#endif
|
||||
|
||||
struct usb_msosv2_descriptor msosv2_desc = {
|
||||
.vendor_code = USBD_WINUSB_VENDOR_CODE,
|
||||
.compat_id = USBD_WinUSBDescriptorSetDescriptor,
|
||||
.compat_id_len = USBD_WINUSB_DESC_SET_LEN,
|
||||
.vendor_code = USBD_WINUSB_VENDOR_CODE,
|
||||
.compat_id = USBD_WinUSBDescriptorSetDescriptor,
|
||||
.compat_id_len = USBD_WINUSB_DESC_SET_LEN,
|
||||
};
|
||||
|
||||
struct usb_bos_descriptor bos_desc = {
|
||||
.string = USBD_BinaryObjectStoreDescriptor,
|
||||
.string_len = USBD_BOS_WTOTALLENGTH
|
||||
.string = USBD_BinaryObjectStoreDescriptor,
|
||||
.string_len = USBD_BOS_WTOTALLENGTH
|
||||
};
|
||||
|
||||
struct usb_webusb_descriptor webusb_url_desc = {
|
||||
.vendor_code = USBD_WEBUSB_VENDOR_CODE,
|
||||
.string = USBD_WebUSBURLDescriptor,
|
||||
.string_len = URL_DESCRIPTOR_LENGTH
|
||||
};
|
||||
|
||||
const struct usb_descriptor cmsisdap_descriptor = {
|
||||
.device_descriptor_callback = device_descriptor_callback,
|
||||
.config_descriptor_callback = config_descriptor_callback,
|
||||
.device_quality_descriptor_callback = device_quality_descriptor_callback,
|
||||
.other_speed_descriptor_callback = other_speed_config_descriptor_callback,
|
||||
.string_descriptor_callback = string_descriptor_callback,
|
||||
.bos_descriptor = &bos_desc,
|
||||
.msosv2_descriptor = &msosv2_desc,
|
||||
.device_descriptor_callback = device_descriptor_callback,
|
||||
.config_descriptor_callback = config_descriptor_callback,
|
||||
.device_quality_descriptor_callback = device_quality_descriptor_callback,
|
||||
.other_speed_descriptor_callback = other_speed_config_descriptor_callback,
|
||||
.string_descriptor_callback = string_descriptor_callback,
|
||||
.bos_descriptor = &bos_desc,
|
||||
.msosv2_descriptor = &msosv2_desc,
|
||||
.webusb_url_descriptor = &webusb_url_desc
|
||||
};
|
||||
|
||||
void chry_dap_init(uint8_t busid, uint32_t reg_base)
|
||||
{
|
||||
chry_ringbuffer_init(&g_uartrx, uartrx_ringbuffer, CONFIG_UARTRX_RINGBUF_SIZE);
|
||||
chry_ringbuffer_init(&g_usbrx, usbrx_ringbuffer, CONFIG_USBRX_RINGBUF_SIZE);
|
||||
|
||||
DAP_Setup();
|
||||
|
||||
usbd_desc_register(0, &cmsisdap_descriptor);
|
||||
|
||||
/*!< winusb */
|
||||
usbd_add_interface(0, &dap_intf);
|
||||
usbd_add_endpoint(0, &dap_out_ep);
|
||||
usbd_add_endpoint(0, &dap_in_ep);
|
||||
|
||||
/*!< cdc acm */
|
||||
usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf1));
|
||||
usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf2));
|
||||
usbd_add_endpoint(0, &cdc_out_ep);
|
||||
usbd_add_endpoint(0, &cdc_in_ep);
|
||||
|
||||
#if CONFIG_CHERRYDAP_USE_CUSTOM_HID
|
||||
/*!< hid */
|
||||
usbd_add_interface(0, usbd_hid_init_intf(0, &hid_intf, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE));
|
||||
hid_intf.notify_handler = hid_custom_notify_handler;
|
||||
usbd_add_endpoint(0, &hid_custom_in_ep);
|
||||
usbd_add_endpoint(0, &hid_custom_out_ep);
|
||||
#endif
|
||||
|
||||
#if CONFIG_CHERRYDAP_USE_MSC
|
||||
usbd_add_interface(0, usbd_msc_init_intf(0, &intf3, MSC_OUT_EP, MSC_IN_EP));
|
||||
#endif
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
|
||||
void chry_dap_handle(void)
|
||||
{
|
||||
uint32_t n;
|
||||
@@ -387,7 +583,7 @@ void chry_dap_handle(void)
|
||||
|
||||
// Execute DAP Command (process request and prepare response)
|
||||
USB_RespSize[USB_ResponseIndexI] =
|
||||
(uint16_t) DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);
|
||||
(uint16_t)DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]);
|
||||
|
||||
// Update Request Index and Count
|
||||
USB_RequestIndexO++;
|
||||
@@ -397,7 +593,7 @@ void chry_dap_handle(void)
|
||||
USB_RequestCountO++;
|
||||
|
||||
if (USB_RequestIdle) {
|
||||
if ((uint16_t) (USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
|
||||
if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) != DAP_PACKET_COUNT) {
|
||||
USB_RequestIdle = 0U;
|
||||
usbd_ep_start_read(0, DAP_OUT_EP, USB_Request[USB_RequestIndexI], DAP_PACKET_SIZE);
|
||||
}
|
||||
@@ -427,9 +623,9 @@ void chry_dap_handle(void)
|
||||
|
||||
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
(void) busid;
|
||||
if (memcmp(line_coding, (uint8_t *) &g_cdc_lincoding, sizeof(struct cdc_line_coding)) != 0) {
|
||||
memcpy((uint8_t *) &g_cdc_lincoding, line_coding, sizeof(struct cdc_line_coding));
|
||||
(void)busid;
|
||||
if (memcmp(line_coding, (uint8_t *)&g_cdc_lincoding, sizeof(struct cdc_line_coding)) != 0) {
|
||||
memcpy((uint8_t *)&g_cdc_lincoding, line_coding, sizeof(struct cdc_line_coding));
|
||||
config_uart = 1;
|
||||
config_uart_transfer = 0;
|
||||
}
|
||||
@@ -437,8 +633,8 @@ void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_c
|
||||
|
||||
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
(void) busid;
|
||||
memcpy(line_coding, (uint8_t *) &g_cdc_lincoding, sizeof(struct cdc_line_coding));
|
||||
(void)busid;
|
||||
memcpy(line_coding, (uint8_t *)&g_cdc_lincoding, sizeof(struct cdc_line_coding));
|
||||
}
|
||||
|
||||
void chry_dap_usb2uart_handle(void)
|
||||
@@ -450,7 +646,7 @@ void chry_dap_usb2uart_handle(void)
|
||||
/* disable irq here */
|
||||
config_uart = 0;
|
||||
/* config uart here */
|
||||
chry_dap_usb2uart_uart_config_callback((struct cdc_line_coding *) &g_cdc_lincoding);
|
||||
chry_dap_usb2uart_uart_config_callback((struct cdc_line_coding *)&g_cdc_lincoding);
|
||||
usbtx_idle_flag = 1;
|
||||
uarttx_idle_flag = 1;
|
||||
config_uart_transfer = 1;
|
||||
@@ -521,7 +717,7 @@ __WEAK void chry_dap_usb2uart_uart_send_bydma(uint8_t *data, uint16_t len)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CHERRYDAP_USE_MSC
|
||||
#if CONFIG_CHERRYDAP_USE_MSC
|
||||
#define BLOCK_SIZE 512
|
||||
#define BLOCK_COUNT 10
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "usbd_hid.h"
|
||||
#include "chry_ringbuffer.h"
|
||||
#include "DAP_config.h"
|
||||
#include "DAP.h"
|
||||
@@ -24,23 +25,14 @@
|
||||
#define MSC_IN_EP 0x86
|
||||
#define MSC_OUT_EP 0x07
|
||||
|
||||
#define HID_IN_EP 0x88
|
||||
#define HID_OUT_EP 0x09
|
||||
|
||||
#define USBD_VID 0x0D28
|
||||
#define USBD_PID 0x0204
|
||||
#define USBD_MAX_POWER 500
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
#define CMSIS_DAP_INTERFACE_SIZE (9 + 7 + 7)
|
||||
|
||||
#ifdef CONFIG_CHERRYDAP_USE_MSC
|
||||
#define CONFIG_MSC_DESCRIPTOR_LEN CDC_ACM_DESCRIPTOR_LEN
|
||||
#define CONFIG_MSC_INTF_NUM 1
|
||||
#define MSC_INTF_NUM (0x02 + 1)
|
||||
#else
|
||||
#define CONFIG_MSC_DESCRIPTOR_LEN 0
|
||||
#define CONFIG_MSC_INTF_NUM 0
|
||||
#define MSC_INTF_NUM (0x02)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#if DAP_PACKET_SIZE != 512
|
||||
#error "DAP_PACKET_SIZE must be 512 in hs"
|
||||
@@ -51,99 +43,57 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define USBD_WINUSB_VENDOR_CODE 0x20
|
||||
|
||||
#define USBD_WEBUSB_ENABLE 0
|
||||
#define USBD_BULK_ENABLE 1
|
||||
#define USBD_WINUSB_ENABLE 1
|
||||
|
||||
/* WinUSB Microsoft OS 2.0 descriptor sizes */
|
||||
#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE 10
|
||||
#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
|
||||
#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE 20
|
||||
|
||||
#define FUNCTION_SUBSET_LEN 160
|
||||
#define DEVICE_INTERFACE_GUIDS_FEATURE_LEN 132
|
||||
|
||||
#define USBD_WINUSB_DESC_SET_LEN (WINUSB_DESCRIPTOR_SET_HEADER_SIZE + USBD_WEBUSB_ENABLE * FUNCTION_SUBSET_LEN + USBD_BULK_ENABLE * FUNCTION_SUBSET_LEN)
|
||||
|
||||
#define USBD_NUM_DEV_CAPABILITIES (USBD_WEBUSB_ENABLE + USBD_WINUSB_ENABLE)
|
||||
|
||||
#define USBD_WEBUSB_DESC_LEN 24
|
||||
#define USBD_WINUSB_DESC_LEN 28
|
||||
|
||||
#define USBD_BOS_WTOTALLENGTH (0x05 + \
|
||||
USBD_WEBUSB_DESC_LEN * USBD_WEBUSB_ENABLE + \
|
||||
USBD_WINUSB_DESC_LEN * USBD_WINUSB_ENABLE)
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define HID_PACKET_SIZE 1024
|
||||
#else
|
||||
#define HID_PACKET_SIZE 64
|
||||
#endif
|
||||
|
||||
#define CONFIG_UARTRX_RINGBUF_SIZE (8 * 1024)
|
||||
#define CONFIG_USBRX_RINGBUF_SIZE (8 * 1024)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#ifndef CONFIG_CHERRYDAP_USE_MSC
|
||||
#define CONFIG_CHERRYDAP_USE_MSC 0
|
||||
#endif
|
||||
|
||||
extern USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t uartrx_ringbuffer[CONFIG_UARTRX_RINGBUF_SIZE];
|
||||
extern USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t usbrx_ringbuffer[CONFIG_USBRX_RINGBUF_SIZE];
|
||||
extern USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t usb_tmpbuffer[DAP_PACKET_SIZE];
|
||||
#ifndef CONFIG_CHERRYDAP_USE_CUSTOM_HID
|
||||
#define CONFIG_CHERRYDAP_USE_CUSTOM_HID 0
|
||||
#endif
|
||||
|
||||
extern const struct usb_descriptor cmsisdap_descriptor;
|
||||
extern __ALIGN_BEGIN const uint8_t USBD_WinUSBDescriptorSetDescriptor[];
|
||||
extern __ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[];
|
||||
extern char *string_descriptors[];
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern char serial_number_dynamic[36];
|
||||
|
||||
extern struct usbd_interface dap_intf;
|
||||
extern struct usbd_interface intf1;
|
||||
extern struct usbd_interface intf2;
|
||||
extern struct usbd_interface intf3;
|
||||
extern struct usbd_interface hid_intf;
|
||||
|
||||
extern struct usbd_endpoint dap_out_ep;
|
||||
extern struct usbd_endpoint dap_in_ep;
|
||||
extern struct usbd_endpoint cdc_out_ep;
|
||||
extern struct usbd_endpoint cdc_in_ep;
|
||||
|
||||
extern chry_ringbuffer_t g_uartrx;
|
||||
extern chry_ringbuffer_t g_usbrx;
|
||||
|
||||
__STATIC_INLINE void chry_dap_init(uint8_t busid, uint32_t reg_base)
|
||||
{
|
||||
chry_ringbuffer_init(&g_uartrx, uartrx_ringbuffer, CONFIG_UARTRX_RINGBUF_SIZE);
|
||||
chry_ringbuffer_init(&g_usbrx, usbrx_ringbuffer, CONFIG_USBRX_RINGBUF_SIZE);
|
||||
|
||||
DAP_Setup();
|
||||
|
||||
usbd_desc_register(0, &cmsisdap_descriptor);
|
||||
|
||||
/*!< winusb */
|
||||
usbd_add_interface(0, &dap_intf);
|
||||
usbd_add_endpoint(0, &dap_out_ep);
|
||||
usbd_add_endpoint(0, &dap_in_ep);
|
||||
|
||||
/*!< cdc acm */
|
||||
usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf1));
|
||||
usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf2));
|
||||
usbd_add_endpoint(0, &cdc_out_ep);
|
||||
usbd_add_endpoint(0, &cdc_in_ep);
|
||||
|
||||
#ifdef CONFIG_CHERRYDAP_USE_MSC
|
||||
usbd_add_interface(0, usbd_msc_init_intf(0, &intf3, MSC_OUT_EP, MSC_IN_EP));
|
||||
#endif
|
||||
extern void usbd_event_handler(uint8_t busid, uint8_t event);
|
||||
usbd_initialize(busid, reg_base, usbd_event_handler);
|
||||
}
|
||||
void chry_dap_init(uint8_t busid, uint32_t reg_base);
|
||||
|
||||
void chry_dap_handle(void);
|
||||
|
||||
void chry_dap_usb2uart_handle(void);
|
||||
|
||||
void chry_dap_usb2uart_uart_config_callback(struct cdc_line_coding *line_coding);
|
||||
/* implment by user */
|
||||
extern void chry_dap_usb2uart_uart_config_callback(struct cdc_line_coding *line_coding);
|
||||
|
||||
void chry_dap_usb2uart_uart_send_bydma(uint8_t *data, uint16_t len);
|
||||
/* implment by user */
|
||||
extern void chry_dap_usb2uart_uart_send_bydma(uint8_t *data, uint16_t len);
|
||||
|
||||
void chry_dap_usb2uart_uart_send_complete(uint32_t size);
|
||||
|
||||
/* implment by user */
|
||||
extern void hid_custom_notify_handler(uint8_t busid, uint8_t event, void *arg);
|
||||
|
||||
/* implment by user */
|
||||
extern void usbd_hid_custom_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes);
|
||||
|
||||
/* implment by user */
|
||||
extern void usbd_hid_custom_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,7 @@ int USB_disk_read(BYTE *buff, LBA_t sector, UINT count)
|
||||
uint8_t *align_buf;
|
||||
|
||||
align_buf = (uint8_t *)buff;
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
align_buf = (uint8_t *)aligned_alloc(CONFIG_USB_ALIGN_SIZE, count * active_msc_class->blocksize);
|
||||
if (!align_buf) {
|
||||
@@ -42,19 +42,19 @@ int USB_disk_read(BYTE *buff, LBA_t sector, UINT count)
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = usbh_msc_scsi_read10(active_msc_class, sector, align_buf, count);
|
||||
if (ret < 0) {
|
||||
ret = RES_ERROR;
|
||||
} else {
|
||||
ret = RES_OK;
|
||||
}
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
usb_memcpy(buff, align_buf, count * active_msc_class->blocksize);
|
||||
free(align_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ int USB_disk_write(const BYTE *buff, LBA_t sector, UINT count)
|
||||
uint8_t *align_buf;
|
||||
|
||||
align_buf = (uint8_t *)buff;
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
align_buf = (uint8_t *)aligned_alloc(CONFIG_USB_ALIGN_SIZE, count * active_msc_class->blocksize);
|
||||
if (!align_buf) {
|
||||
@@ -73,18 +73,18 @@ int USB_disk_write(const BYTE *buff, LBA_t sector, UINT count)
|
||||
}
|
||||
usb_memcpy(align_buf, buff, count * active_msc_class->blocksize);
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = usbh_msc_scsi_write10(active_msc_class, sector, align_buf, count);
|
||||
if (ret < 0) {
|
||||
ret = RES_ERROR;
|
||||
} else {
|
||||
ret = RES_OK;
|
||||
}
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
free(align_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
296
platform/idf/usbh_fatfs.c
Normal file
296
platform/idf/usbh_fatfs.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "diskio_impl.h"
|
||||
#include "ffconf.h"
|
||||
#include "ff.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_msc.h"
|
||||
|
||||
static char *TAG = "MSC";
|
||||
|
||||
#define DRIVE_STR_LEN 3
|
||||
|
||||
typedef struct msc_host_vfs {
|
||||
uint8_t pdrv;
|
||||
FATFS *fs;
|
||||
char base_path[0];
|
||||
} msc_host_vfs_t;
|
||||
|
||||
static struct usbh_msc *s_mscs[FF_VOLUMES] = { NULL };
|
||||
|
||||
static DSTATUS usb_disk_initialize(BYTE pdrv)
|
||||
{
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DSTATUS usb_disk_status(BYTE pdrv)
|
||||
{
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DRESULT usb_disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
|
||||
{
|
||||
struct usbh_msc *msc_class;
|
||||
assert(pdrv < FF_VOLUMES);
|
||||
|
||||
msc_class = s_mscs[pdrv];
|
||||
assert(msc_class);
|
||||
if (sector >= msc_class->blocknum - count) {
|
||||
ESP_LOGW(TAG, "%s: sector 0x%"PRIX32" out of range", __FUNCTION__, (uint32_t)sector);
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
uint8_t *dma_buff = buff;
|
||||
size_t len = msc_class->blocksize * count;
|
||||
|
||||
if (((uint32_t)dma_buff & (CONFIG_USB_ALIGN_SIZE - 1)) || (len & (CONFIG_USB_ALIGN_SIZE - 1))) {
|
||||
dma_buff = heap_caps_aligned_alloc(CONFIG_USB_ALIGN_SIZE, len, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
if (dma_buff == NULL) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int ret = usbh_msc_scsi_read10(msc_class, sector, dma_buff, count);
|
||||
if (dma_buff != buff) {
|
||||
if (ret == 0) {
|
||||
memcpy(buff, dma_buff, len);
|
||||
}
|
||||
heap_caps_free(dma_buff);
|
||||
}
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "usbh_msc_scsi_read10 failed (%d)", ret);
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DRESULT usb_disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
|
||||
{
|
||||
struct usbh_msc *msc_class;
|
||||
assert(pdrv < FF_VOLUMES);
|
||||
|
||||
msc_class = s_mscs[pdrv];
|
||||
assert(msc_class);
|
||||
if (sector >= msc_class->blocknum - count) {
|
||||
ESP_LOGW(TAG, "%s: sector 0x%"PRIX32" out of range", __FUNCTION__, (uint32_t)sector);
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
const uint8_t *dma_buff = buff;
|
||||
size_t len = msc_class->blocksize * count;
|
||||
|
||||
if (((uint32_t)dma_buff & (CONFIG_USB_ALIGN_SIZE - 1)) || (len & (CONFIG_USB_ALIGN_SIZE - 1))) {
|
||||
dma_buff = heap_caps_aligned_alloc(CONFIG_USB_ALIGN_SIZE, len, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
if (dma_buff == NULL) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
memcpy((uint8_t *)dma_buff, buff, len);
|
||||
}
|
||||
|
||||
int ret = usbh_msc_scsi_write10(msc_class, sector, dma_buff, count);
|
||||
if (dma_buff != buff) {
|
||||
heap_caps_free((uint8_t *)dma_buff);
|
||||
}
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "usbh_msc_scsi_write10 failed (%d)", ret);
|
||||
return RES_ERROR;
|
||||
}
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DRESULT usb_disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
|
||||
{
|
||||
struct usbh_msc *msc_class;
|
||||
assert(pdrv < FF_VOLUMES);
|
||||
|
||||
msc_class = s_mscs[pdrv];
|
||||
assert(msc_class);
|
||||
|
||||
switch (cmd) {
|
||||
case CTRL_SYNC:
|
||||
return RES_OK;
|
||||
case GET_SECTOR_COUNT:
|
||||
*((DWORD *) buff) = msc_class->blocknum;
|
||||
return RES_OK;
|
||||
case GET_SECTOR_SIZE:
|
||||
*((WORD *) buff) = msc_class->blocksize;
|
||||
return RES_OK;
|
||||
case GET_BLOCK_SIZE:
|
||||
return RES_ERROR;
|
||||
}
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
void ff_diskio_register_msc(BYTE pdrv, struct usbh_msc *msc_class)
|
||||
{
|
||||
assert(pdrv < FF_VOLUMES);
|
||||
|
||||
static const ff_diskio_impl_t usb_disk_impl = {
|
||||
.init = &usb_disk_initialize,
|
||||
.status = &usb_disk_status,
|
||||
.read = &usb_disk_read,
|
||||
.write = &usb_disk_write,
|
||||
.ioctl = &usb_disk_ioctl
|
||||
};
|
||||
s_mscs[pdrv] = msc_class;
|
||||
ff_diskio_register(pdrv, &usb_disk_impl);
|
||||
}
|
||||
|
||||
BYTE ff_diskio_get_pdrv_disk(const struct usbh_msc *msc_class)
|
||||
{
|
||||
for (int i = 0; i < FF_VOLUMES; i++) {
|
||||
if (msc_class == s_mscs[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
static esp_err_t msc_host_format(struct usbh_msc *msc_class, size_t allocation_size)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((msc_class != NULL && msc_class->user_data != NULL), ESP_ERR_INVALID_ARG, TAG, "");
|
||||
void *workbuf = NULL;
|
||||
const size_t workbuf_size = 4096;
|
||||
msc_host_vfs_t *vfs = (msc_host_vfs_t *)msc_class->user_data;
|
||||
|
||||
char drive[DRIVE_STR_LEN] = {(char)('0' + vfs->pdrv), ':', 0};
|
||||
ESP_RETURN_ON_FALSE((workbuf = ff_memalloc(workbuf_size)), ESP_ERR_NO_MEM, TAG, "");
|
||||
|
||||
// Valid value of cluster size is between sector_size and 128 * sector_size.
|
||||
size_t cluster_size = MIN(MAX(allocation_size, msc_class->blocksize), 128 * msc_class->blocksize);
|
||||
|
||||
ESP_LOGW(TAG, "Formatting card, allocation unit size=%d", cluster_size);
|
||||
f_mount(0, drive, 0);
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
FRESULT err = f_mkfs(drive, FM_ANY | FM_SFD, cluster_size, workbuf, workbuf_size);
|
||||
#else
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 0, cluster_size};
|
||||
FRESULT err = f_mkfs(drive, &opt, workbuf, workbuf_size);
|
||||
#endif
|
||||
|
||||
free(workbuf);
|
||||
if (err != FR_OK || (err = f_mount(vfs->fs, drive, 0)) != FR_OK) {
|
||||
ESP_LOGE(TAG, "Formatting failed with error: %d", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t msc_host_vfs_register(struct usbh_msc *msc_class,
|
||||
const char *base_path,
|
||||
const esp_vfs_fat_mount_config_t *mount_config)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((msc_class != NULL && msc_class->user_data == NULL && base_path != NULL && mount_config != NULL), ESP_ERR_INVALID_ARG, TAG, "");
|
||||
|
||||
FATFS *fs = NULL;
|
||||
BYTE pdrv;
|
||||
|
||||
if (ff_diskio_get_drive(&pdrv) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "the maximum count of volumes is already mounted");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
esp_err_t ret;
|
||||
|
||||
msc_host_vfs_t *vfs = malloc(sizeof(msc_host_vfs_t) + strlen(base_path) + 1);
|
||||
ESP_RETURN_ON_FALSE(vfs != NULL, ESP_ERR_NO_MEM, TAG, "");
|
||||
|
||||
ff_diskio_register_msc(pdrv, msc_class);
|
||||
char drive[DRIVE_STR_LEN] = {(char)('0' + pdrv), ':', 0};
|
||||
strcpy(vfs->base_path, base_path);
|
||||
vfs->pdrv = pdrv;
|
||||
|
||||
ret = esp_vfs_fat_register(base_path, drive, mount_config->max_files, &fs);
|
||||
ESP_GOTO_ON_ERROR(ret, fail, TAG, "Failed to register filesystem, error=%s", esp_err_to_name(ret));
|
||||
vfs->fs = fs;
|
||||
|
||||
msc_class->user_data = vfs;
|
||||
if (f_mount(fs, drive, 1) != FR_OK) {
|
||||
if ((!mount_config->format_if_mount_failed) || msc_host_format(msc_class, mount_config->allocation_unit_size) != ESP_OK) {
|
||||
ret = ESP_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
fail:
|
||||
msc_class->user_data = NULL;
|
||||
if (fs) {
|
||||
f_mount(NULL, drive, 0);
|
||||
}
|
||||
esp_vfs_fat_unregister_path(base_path);
|
||||
ff_diskio_unregister(pdrv);
|
||||
s_mscs[pdrv] = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t msc_host_vfs_unregister(struct usbh_msc *msc_class)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((msc_class != NULL && ff_diskio_get_pdrv_disk(msc_class) != 0XFF), ESP_ERR_INVALID_ARG, TAG, "");
|
||||
msc_host_vfs_t *vfs = (msc_host_vfs_t *)msc_class->user_data;
|
||||
msc_class->user_data = NULL;
|
||||
|
||||
char drive[DRIVE_STR_LEN] = {(char)('0' + vfs->pdrv), ':', 0};
|
||||
f_mount(NULL, drive, 0);
|
||||
ff_diskio_unregister(vfs->pdrv);
|
||||
s_mscs[vfs->pdrv] = NULL;
|
||||
esp_vfs_fat_unregister_path(vfs->base_path);
|
||||
heap_caps_free(vfs);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void usbh_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
struct usbh_msc *msc_class = (struct usbh_msc *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
|
||||
int ret;
|
||||
|
||||
ret = usbh_msc_scsi_init(msc_class);
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, "scsi_init error,ret:%d", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||
#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
|
||||
.format_if_mount_failed = true,
|
||||
#else
|
||||
.format_if_mount_failed = false,
|
||||
#endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
|
||||
.max_files = 5,
|
||||
.allocation_unit_size = 4 * 1024
|
||||
};
|
||||
ESP_LOGI(TAG, "Mounting msc host filesystem");
|
||||
|
||||
if (msc_host_vfs_register(msc_class, "/usb", &mount_config) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "msc_host_vfs_register fail");
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "MSC host filesystem mounted");
|
||||
|
||||
usb_osal_thread_delete(NULL);
|
||||
}
|
||||
|
||||
void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
{
|
||||
usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class);
|
||||
}
|
||||
|
||||
void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||
{
|
||||
msc_host_vfs_unregister(msc_class);
|
||||
}
|
||||
@@ -17,8 +17,11 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_ARM_CORTEX_M7) || \
|
||||
defined(SOC_HPM6000) || defined(SOC_HPM6E00) || defined(SOC_HPM6P00) || \
|
||||
#if defined(ARCH_ARM_CORTEX_M7) || \
|
||||
defined(ARCH_ARM_CORTEX_A) || \
|
||||
defined(ARCH_RISCV64) || \
|
||||
defined(SOC_HPM6200) || defined(SOC_HPM6300) || defined(SOC_HPM6700) || defined(SOC_HPM6800) || \
|
||||
defined(SOC_HPM6E00) || defined(SOC_HPM6P00) || \
|
||||
defined(BSP_USING_BL61X) || defined(BSP_USING_BL808)
|
||||
#ifndef RT_USING_CACHE
|
||||
#error RT_USING_CACHE must be enabled in this chip
|
||||
@@ -27,6 +30,6 @@
|
||||
|
||||
#ifdef RT_USING_CACHE
|
||||
#ifndef CONFIG_USB_DCACHE_ENABLE
|
||||
#warning CONFIG_USB_DCACHE_ENABLE must be enabled if you do not config nocache ram
|
||||
#error CONFIG_USB_DCACHE_ENABLE must be enabled if you do not config nocache ram
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -76,9 +76,8 @@ static rt_err_t usbd_serial_open(struct rt_device *dev, rt_uint16_t oflag)
|
||||
|
||||
serial = (struct usbd_serial *)dev;
|
||||
|
||||
if (!usb_device_is_configured(serial->busid)) {
|
||||
USB_LOG_ERR("USB device is not configured\n");
|
||||
return -RT_EPERM;
|
||||
while(!usb_device_is_configured(serial->busid)) {
|
||||
rt_thread_mdelay(10);
|
||||
}
|
||||
|
||||
usbd_ep_start_read(serial->busid, serial->out_ep,
|
||||
@@ -123,9 +122,8 @@ static rt_ssize_t usbd_serial_write(struct rt_device *dev,
|
||||
}
|
||||
align_buf = (rt_uint8_t *)buffer;
|
||||
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
align_buf = rt_malloc_align(size, CONFIG_USB_ALIGN_SIZE);
|
||||
align_buf = rt_malloc_align(USB_ALIGN_UP(size, CONFIG_USB_ALIGN_SIZE), CONFIG_USB_ALIGN_SIZE);
|
||||
if (!align_buf) {
|
||||
USB_LOG_ERR("serial get align buf failed\n");
|
||||
return 0;
|
||||
@@ -133,7 +131,7 @@ static rt_ssize_t usbd_serial_write(struct rt_device *dev,
|
||||
|
||||
usb_memcpy(align_buf, buffer, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
usb_osal_sem_reset(serial->tx_done);
|
||||
usbd_ep_start_write(serial->busid, serial->in_ep, align_buf, size);
|
||||
ret = usb_osal_sem_take(serial->tx_done, 3000);
|
||||
@@ -144,11 +142,9 @@ static rt_ssize_t usbd_serial_write(struct rt_device *dev,
|
||||
ret = size;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
rt_free_align(align_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ static rt_ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
|
||||
rt_uint8_t *align_buf;
|
||||
|
||||
align_buf = (rt_uint8_t *)buffer;
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE);
|
||||
if (!align_buf) {
|
||||
@@ -47,18 +47,18 @@ static rt_ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
|
||||
}
|
||||
} else {
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = usbh_msc_scsi_read10(msc_class, pos, (uint8_t *)align_buf, size);
|
||||
if (ret < 0) {
|
||||
rt_kprintf("usb mass_storage read failed\n");
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
usb_memcpy(buffer, align_buf, size * msc_class->blocksize);
|
||||
rt_free_align(align_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ static rt_ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buff
|
||||
rt_uint8_t *align_buf;
|
||||
|
||||
align_buf = (rt_uint8_t *)buffer;
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE);
|
||||
if (!align_buf) {
|
||||
@@ -80,17 +80,16 @@ static rt_ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buff
|
||||
|
||||
usb_memcpy(align_buf, buffer, size * msc_class->blocksize);
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = usbh_msc_scsi_write10(msc_class, pos, (uint8_t *)align_buf, size);
|
||||
if (ret < 0) {
|
||||
rt_kprintf("usb mass_storage write failed\n");
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
rt_free_align(align_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_NO_RX_THREAD
|
||||
#error must enable LWIP_NO_RX_THREAD, we do not use rtthread eth rx thread
|
||||
#warning suggest you to enable LWIP_NO_RX_THREAD, we do not use rtthread eth rx thread
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_NO_TX_THREAD
|
||||
@@ -33,7 +33,7 @@
|
||||
#endif
|
||||
|
||||
#if LWIP_TCPIP_CORE_LOCKING_INPUT != 1
|
||||
#warning suggest you to set LWIP_TCPIP_CORE_LOCKING_INPUT to 1, usb handles eth input with own thread
|
||||
#warning suggest you to set LWIP_TCPIP_CORE_LOCKING_INPUT to 1 for better performance, usb handles eth input with own thread
|
||||
#endif
|
||||
|
||||
#if LWIP_TCPIP_CORE_LOCKING != 1
|
||||
|
||||
@@ -193,9 +193,9 @@ static rt_ssize_t usbh_serial_write(struct rt_device *dev,
|
||||
serial = (struct usbh_serial *)dev;
|
||||
|
||||
align_buf = (rt_uint8_t *)buffer;
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
align_buf = rt_malloc_align(size, CONFIG_USB_ALIGN_SIZE);
|
||||
align_buf = rt_malloc_align(USB_ALIGN_UP(size, CONFIG_USB_ALIGN_SIZE), CONFIG_USB_ALIGN_SIZE);
|
||||
if (!align_buf) {
|
||||
USB_LOG_ERR("serial get align buf failed\n");
|
||||
return 0;
|
||||
@@ -203,7 +203,6 @@ static rt_ssize_t usbh_serial_write(struct rt_device *dev,
|
||||
|
||||
usb_memcpy(align_buf, buffer, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (serial->type) {
|
||||
#if defined(PKG_CHERRYUSB_HOST_CDC_ACM) || defined(RT_CHERRYUSB_HOST_CDC_ACM)
|
||||
@@ -211,10 +210,7 @@ static rt_ssize_t usbh_serial_write(struct rt_device *dev,
|
||||
ret = usbh_cdc_acm_bulk_out_transfer((struct usbh_cdc_acm *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("usbh_cdc_acm_bulk_out_transfer failed: %d\n", ret);
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
rt_free_align(align_buf);
|
||||
#endif
|
||||
return 0;
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -223,10 +219,7 @@ static rt_ssize_t usbh_serial_write(struct rt_device *dev,
|
||||
ret = usbh_ftdi_bulk_out_transfer((struct usbh_ftdi *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("usbh_ftdi_bulk_out_transfer failed: %d\n", ret);
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
rt_free_align(align_buf);
|
||||
#endif
|
||||
return 0;
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -235,10 +228,7 @@ static rt_ssize_t usbh_serial_write(struct rt_device *dev,
|
||||
ret = usbh_ch34x_bulk_out_transfer((struct usbh_ch34x *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("usbh_ch34x_bulk_out_transfer failed: %d\n", ret);
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
rt_free_align(align_buf);
|
||||
#endif
|
||||
return 0;
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -247,10 +237,7 @@ static rt_ssize_t usbh_serial_write(struct rt_device *dev,
|
||||
ret = usbh_pl2303_bulk_out_transfer((struct usbh_pl2303 *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("usbh_pl2303_bulk_out_transfer failed: %d\n", ret);
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
rt_free_align(align_buf);
|
||||
#endif
|
||||
return 0;
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -258,11 +245,9 @@ static rt_ssize_t usbh_serial_write(struct rt_device *dev,
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
|
||||
rt_free_align(align_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -202,7 +202,6 @@ VOID _fx_usbh_msc_driver(FX_MEDIA *media_ptr)
|
||||
media_ptr->fx_media_driver_status = FX_IO_ERROR;
|
||||
return;
|
||||
}
|
||||
printf("read success\r\n");
|
||||
/* Successful driver request. */
|
||||
media_ptr->fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
|
||||
@@ -594,10 +594,15 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
|
||||
return -2;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
USB_ASSERT_MSG(!((uintptr_t)data % CONFIG_USB_ALIGN_SIZE), "data is not aligned %d", CONFIG_USB_ALIGN_SIZE);
|
||||
#endif
|
||||
|
||||
g_chipidea_udc[busid].in_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_chipidea_udc[busid].in_ep[ep_idx].xfer_len = data_len;
|
||||
g_chipidea_udc[busid].in_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
usb_dcache_clean((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
|
||||
chipidea_start_xfer(busid, ep, (uint8_t *)data, data_len);
|
||||
|
||||
return 0;
|
||||
@@ -614,10 +619,15 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
|
||||
return -2;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
USB_ASSERT_MSG(!((uintptr_t)data % CONFIG_USB_ALIGN_SIZE), "data is not aligned %d", CONFIG_USB_ALIGN_SIZE);
|
||||
#endif
|
||||
|
||||
g_chipidea_udc[busid].out_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_chipidea_udc[busid].out_ep[ep_idx].xfer_len = data_len;
|
||||
g_chipidea_udc[busid].out_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
usb_dcache_invalidate((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
|
||||
chipidea_start_xfer(busid, ep, data, data_len);
|
||||
|
||||
return 0;
|
||||
@@ -649,7 +659,7 @@ void USBD_IRQHandler(uint8_t busid)
|
||||
memset(g_chipidea_udc[busid].in_ep, 0, sizeof(struct chipidea_ep_state) * CONFIG_USBDEV_EP_NUM);
|
||||
memset(g_chipidea_udc[busid].out_ep, 0, sizeof(struct chipidea_ep_state) * CONFIG_USBDEV_EP_NUM);
|
||||
usbd_event_reset_handler(busid);
|
||||
chipidea_bus_reset(busid, 64);
|
||||
chipidea_bus_reset(busid, g_chipidea_udc[busid].in_ep[0].ep_mps);
|
||||
}
|
||||
|
||||
if (int_status & intr_suspend) {
|
||||
@@ -712,6 +722,7 @@ void USBD_IRQHandler(uint8_t busid)
|
||||
if (ep_addr & 0x80) {
|
||||
usbd_event_ep_in_complete_handler(busid, ep_addr, transfer_len);
|
||||
} else {
|
||||
usb_dcache_invalidate((uintptr_t)g_chipidea_udc[busid].out_ep[ep_idx].xfer_buf, USB_ALIGN_UP(transfer_len, CONFIG_USB_ALIGN_SIZE));
|
||||
usbd_event_ep_out_complete_handler(busid, ep_addr, transfer_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,13 @@
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
#define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
|
||||
#endif
|
||||
#elif defined (__ICCARM__)
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
#define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
|
||||
#endif
|
||||
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
#pragma clang diagnostic push
|
||||
@@ -334,6 +341,8 @@ static void dwc2_ep0_start_read_setup(uint8_t busid, uint8_t *psetup)
|
||||
USB_OTG_OUTEP(0U)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT;
|
||||
|
||||
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
|
||||
usb_dcache_invalidate((uintptr_t)&g_dwc2_udc[busid].setup, USB_ALIGN_UP(8, CONFIG_USB_ALIGN_SIZE));
|
||||
|
||||
USB_OTG_OUTEP(0U)->DOEPDMA = (uint32_t)psetup;
|
||||
/* EP enable */
|
||||
USB_OTG_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_USBAEP;
|
||||
@@ -675,6 +684,7 @@ uint8_t usbd_get_port_speed(uint8_t busid)
|
||||
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
uint16_t ep_mps;
|
||||
|
||||
USB_ASSERT_MSG(ep_idx < (g_dwc2_udc[busid].hw_params.num_dev_ep + 1), "Ep addr %02x overflow", ep->bEndpointAddress);
|
||||
|
||||
@@ -682,14 +692,34 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_dwc2_udc[busid].out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
|
||||
ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
if (ep_idx == 0) {
|
||||
switch (ep_mps) {
|
||||
case 64:
|
||||
ep_mps = EP_MPS_64;
|
||||
break;
|
||||
case 32:
|
||||
ep_mps = EP_MPS_32;
|
||||
break;
|
||||
case 16:
|
||||
ep_mps = EP_MPS_16;
|
||||
break;
|
||||
case 8:
|
||||
ep_mps = EP_MPS_8;
|
||||
break;
|
||||
|
||||
default:
|
||||
ep_mps = EP_MPS_64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
USB_OTG_DEV->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & (uint32_t)(1UL << (16 + ep_idx));
|
||||
|
||||
if ((USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_USBAEP) == 0) {
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= (USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize) & USB_OTG_DOEPCTL_MPSIZ) |
|
||||
((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DOEPCTL_USBAEP;
|
||||
}
|
||||
USB_OTG_OUTEP(ep_idx)->DOEPCTL |= (ep_mps & USB_OTG_DOEPCTL_MPSIZ) |
|
||||
((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DOEPCTL_USBAEP;
|
||||
} else {
|
||||
uint16_t fifo_size;
|
||||
if (ep_idx == 0) {
|
||||
@@ -703,14 +733,34 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_dwc2_udc[busid].in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
|
||||
ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
if (ep_idx == 0) {
|
||||
switch (ep_mps) {
|
||||
case 64:
|
||||
ep_mps = EP_MPS_64;
|
||||
break;
|
||||
case 32:
|
||||
ep_mps = EP_MPS_32;
|
||||
break;
|
||||
case 16:
|
||||
ep_mps = EP_MPS_16;
|
||||
break;
|
||||
case 8:
|
||||
ep_mps = EP_MPS_8;
|
||||
break;
|
||||
|
||||
default:
|
||||
ep_mps = EP_MPS_64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
USB_OTG_DEV->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << ep_idx);
|
||||
|
||||
if ((USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_USBAEP) == 0) {
|
||||
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize) & USB_OTG_DIEPCTL_MPSIZ) |
|
||||
((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) | (ep_idx << 22) |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DIEPCTL_USBAEP;
|
||||
}
|
||||
USB_OTG_INEP(ep_idx)->DIEPCTL |= (ep_mps & USB_OTG_DIEPCTL_MPSIZ) |
|
||||
((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) | (ep_idx << 22) |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DIEPCTL_USBAEP;
|
||||
dwc2_flush_txfifo(busid, ep_idx);
|
||||
}
|
||||
return 0;
|
||||
@@ -782,7 +832,6 @@ int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
|
||||
}
|
||||
|
||||
if ((ep_idx == 0) && g_dwc2_udc[busid].user_params.device_dma_enable) {
|
||||
usb_dcache_invalidate((uintptr_t)&g_dwc2_udc[busid].setup, USB_ALIGN_UP(8, CONFIG_USB_ALIGN_SIZE));
|
||||
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
|
||||
}
|
||||
|
||||
@@ -1046,7 +1095,7 @@ void USBD_IRQHandler(uint8_t busid)
|
||||
usbd_event_ep_out_complete_handler(busid, ep_idx, g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len);
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
process_setup:
|
||||
// clang-format on
|
||||
if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) {
|
||||
|
||||
@@ -1,29 +1,296 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
* Copyright (c) 2022-2024, Xiaohua Semiconductor Co., Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2025-08-08 CDT first version
|
||||
*/
|
||||
#include "usb_config.h"
|
||||
#include "usb_dwc2_reg.h"
|
||||
|
||||
/* When using [GPIO_SetFunc(USBF_VBUS_PORT, USBF_VBUS_PIN, USBF_VBUS_FUNC);], there is no need to configure GOTGCTL */
|
||||
#include "usbd_core.h"
|
||||
#include "usbh_core.h"
|
||||
#include "usb_dwc2_param.h"
|
||||
|
||||
#define USB_OTG_GLB ((DWC2_GlobalTypeDef *)(reg_base))
|
||||
#include "board_config.h"
|
||||
|
||||
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
|
||||
#if defined(RT_CHERRYUSB_HOST) && defined(RT_CHERRYUSB_DEVICE)
|
||||
#if defined(HC32F460) || defined(HC32F472)
|
||||
#error "Only one USB role can be selected!"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const struct dwc2_user_params param_fs_core =
|
||||
{
|
||||
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
|
||||
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
|
||||
.device_dma_enable = true,
|
||||
#else
|
||||
.device_dma_enable = false,
|
||||
#endif
|
||||
.device_dma_desc_enable = false,
|
||||
.device_rx_fifo_size = CONFIG_USB_FS_CORE_DEVICE_RX_FIFO_SIZE,
|
||||
.device_tx_fifo_size = {
|
||||
[0] = CONFIG_USB_FS_CORE_DEVICE_TX0_FIFO_SIZE,
|
||||
[1] = CONFIG_USB_FS_CORE_DEVICE_TX1_FIFO_SIZE,
|
||||
[2] = CONFIG_USB_FS_CORE_DEVICE_TX2_FIFO_SIZE,
|
||||
[3] = CONFIG_USB_FS_CORE_DEVICE_TX3_FIFO_SIZE,
|
||||
[4] = CONFIG_USB_FS_CORE_DEVICE_TX4_FIFO_SIZE,
|
||||
[5] = CONFIG_USB_FS_CORE_DEVICE_TX5_FIFO_SIZE,
|
||||
#if defined(HC32F4A0) || defined(HC32F4A8)
|
||||
[6] = CONFIG_USB_FS_CORE_DEVICE_TX6_FIFO_SIZE,
|
||||
[7] = CONFIG_USB_FS_CORE_DEVICE_TX7_FIFO_SIZE,
|
||||
[8] = CONFIG_USB_FS_CORE_DEVICE_TX8_FIFO_SIZE,
|
||||
[9] = CONFIG_USB_FS_CORE_DEVICE_TX9_FIFO_SIZE,
|
||||
[10] = CONFIG_USB_FS_CORE_DEVICE_TX10_FIFO_SIZE,
|
||||
[11] = CONFIG_USB_FS_CORE_DEVICE_TX11_FIFO_SIZE,
|
||||
[12] = CONFIG_USB_FS_CORE_DEVICE_TX12_FIFO_SIZE,
|
||||
[13] = CONFIG_USB_FS_CORE_DEVICE_TX13_FIFO_SIZE,
|
||||
[14] = CONFIG_USB_FS_CORE_DEVICE_TX14_FIFO_SIZE,
|
||||
[15] = CONFIG_USB_FS_CORE_DEVICE_TX15_FIFO_SIZE
|
||||
#elif defined(HC32F460) || defined(HC32F472)
|
||||
[6] = 0,
|
||||
[7] = 0,
|
||||
[8] = 0,
|
||||
[9] = 0,
|
||||
[10] = 0,
|
||||
[11] = 0,
|
||||
[12] = 0,
|
||||
[13] = 0,
|
||||
[14] = 0,
|
||||
[15] = 0
|
||||
#endif
|
||||
},
|
||||
.total_fifo_size = CONFIG_USB_FS_CORE_TOTAL_FIFO_SIZE,
|
||||
|
||||
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
|
||||
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
|
||||
return 0;
|
||||
.host_dma_desc_enable = false,
|
||||
.host_rx_fifo_size = CONFIG_USB_FS_CORE_HOST_RX_FIFO_SIZE,
|
||||
.host_nperio_tx_fifo_size = CONFIG_USB_FS_CORE_HOST_NP_FIFO_SIZE,
|
||||
.host_perio_tx_fifo_size = CONFIG_USB_FS_CORE_HOST_PE_FIFO_SIZE,
|
||||
.device_gccfg = 0,
|
||||
.host_gccfg = 0,
|
||||
#if defined(HC32F4A0) || defined(HC32F4A8) || defined(HC32F460)
|
||||
.b_session_valid_override = false,
|
||||
#elif defined(HC32F472)
|
||||
.b_session_valid_override = true,
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(HC32F4A0) || defined(HC32F4A8)
|
||||
const struct dwc2_user_params param_hs_core =
|
||||
{
|
||||
#ifdef CONFIG_USB_HS
|
||||
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
|
||||
#else
|
||||
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
|
||||
#endif
|
||||
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
|
||||
.device_dma_enable = true,
|
||||
#else
|
||||
.device_dma_enable = false,
|
||||
#endif
|
||||
.device_dma_desc_enable = false,
|
||||
.device_rx_fifo_size = CONFIG_USB_HS_CORE_DEVICE_RX_FIFO_SIZE,
|
||||
.device_tx_fifo_size = {
|
||||
[0] = CONFIG_USB_HS_CORE_DEVICE_TX0_FIFO_SIZE,
|
||||
[1] = CONFIG_USB_HS_CORE_DEVICE_TX1_FIFO_SIZE,
|
||||
[2] = CONFIG_USB_HS_CORE_DEVICE_TX2_FIFO_SIZE,
|
||||
[3] = CONFIG_USB_HS_CORE_DEVICE_TX3_FIFO_SIZE,
|
||||
[4] = CONFIG_USB_HS_CORE_DEVICE_TX4_FIFO_SIZE,
|
||||
[5] = CONFIG_USB_HS_CORE_DEVICE_TX5_FIFO_SIZE,
|
||||
[6] = CONFIG_USB_HS_CORE_DEVICE_TX6_FIFO_SIZE,
|
||||
[7] = CONFIG_USB_HS_CORE_DEVICE_TX7_FIFO_SIZE,
|
||||
[8] = CONFIG_USB_HS_CORE_DEVICE_TX8_FIFO_SIZE,
|
||||
[9] = CONFIG_USB_HS_CORE_DEVICE_TX9_FIFO_SIZE,
|
||||
[10] = CONFIG_USB_HS_CORE_DEVICE_TX10_FIFO_SIZE,
|
||||
[11] = CONFIG_USB_HS_CORE_DEVICE_TX11_FIFO_SIZE,
|
||||
[12] = CONFIG_USB_HS_CORE_DEVICE_TX12_FIFO_SIZE,
|
||||
[13] = CONFIG_USB_HS_CORE_DEVICE_TX13_FIFO_SIZE,
|
||||
[14] = CONFIG_USB_HS_CORE_DEVICE_TX14_FIFO_SIZE,
|
||||
[15] = CONFIG_USB_HS_CORE_DEVICE_TX15_FIFO_SIZE
|
||||
},
|
||||
.total_fifo_size = CONFIG_USB_HS_CORE_TOTAL_FIFO_SIZE,
|
||||
|
||||
.host_dma_desc_enable = false,
|
||||
.host_rx_fifo_size = CONFIG_USB_HS_CORE_HOST_RX_FIFO_SIZE,
|
||||
.host_nperio_tx_fifo_size = CONFIG_USB_HS_CORE_HOST_NP_FIFO_SIZE,
|
||||
.host_perio_tx_fifo_size = CONFIG_USB_HS_CORE_HOST_PE_FIFO_SIZE,
|
||||
.device_gccfg = 0,
|
||||
.host_gccfg = 0,
|
||||
.b_session_valid_override = false,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
|
||||
void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
|
||||
{
|
||||
#if defined(HC32F4A0) || defined(HC32F4A8)
|
||||
if (reg_base == CM_USBHS_BASE)
|
||||
{
|
||||
memcpy(params, ¶m_hs_core, sizeof(struct dwc2_user_params));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
memcpy(params, ¶m_fs_core, sizeof(struct dwc2_user_params));
|
||||
}
|
||||
#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
|
||||
struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
|
||||
|
||||
dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
|
||||
|
||||
params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
|
||||
for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++)
|
||||
{
|
||||
params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#define BOARD_INIT_USB_HOST_MODE (0U)
|
||||
#define BOARD_INIT_USB_DEVICE_MODE (1U)
|
||||
extern rt_err_t rt_hw_usbfs_board_init(uint8_t devmode);
|
||||
static uint8_t g_usb_fs_busid = 0U;
|
||||
#if defined(HC32F4A0) || defined(HC32F4A8)
|
||||
extern rt_err_t rt_hw_usbhs_board_init(uint8_t devmode);
|
||||
static uint8_t g_usb_hs_busid = 0U;
|
||||
#endif
|
||||
|
||||
#if defined(RT_CHERRYUSB_HOST)
|
||||
static void usbh_fs_irq_handler(void)
|
||||
{
|
||||
USBH_IRQHandler(g_usb_fs_busid);
|
||||
}
|
||||
|
||||
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
|
||||
#if defined(HC32F4A0) || defined(HC32F4A8)
|
||||
static void usbh_hs_irq_handler(void)
|
||||
{
|
||||
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOEN;
|
||||
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOVAL;
|
||||
return 0;
|
||||
USBH_IRQHandler(g_usb_hs_busid);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HC32F472)
|
||||
void USBFS_Handler(void)
|
||||
{
|
||||
usbh_fs_irq_handler();
|
||||
}
|
||||
#endif
|
||||
|
||||
void usb_hc_low_level_init(struct usbh_bus *bus)
|
||||
{
|
||||
struct hc32_irq_config irq_config;
|
||||
|
||||
#if defined(HC32F4A0) || defined(HC32F4A8)
|
||||
if (bus->hcd.reg_base == CM_USBHS_BASE)
|
||||
{
|
||||
g_usb_hs_busid = bus->hcd.hcd_id;
|
||||
|
||||
rt_hw_usbhs_board_init(BOARD_INIT_USB_HOST_MODE);
|
||||
FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_USBHS, ENABLE);
|
||||
#ifndef CONFIG_USB_HS
|
||||
/* enable the embedded PHY in USBHS mode */
|
||||
CM_PERIC->USB_SYCTLREG |= PERIC_USB_SYCTLREG_USBHS_FSPHYE;
|
||||
#endif
|
||||
|
||||
irq_config.irq_num = BSP_USBHS_GLB_IRQ_NUM;
|
||||
irq_config.int_src = INT_SRC_USBHS_GLB;
|
||||
irq_config.irq_prio = BSP_USBHS_GLB_IRQ_PRIO;
|
||||
/* register interrupt */
|
||||
hc32_install_irq_handler(&irq_config,
|
||||
usbh_hs_irq_handler,
|
||||
RT_TRUE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
g_usb_fs_busid = bus->hcd.hcd_id;
|
||||
|
||||
rt_hw_usbfs_board_init(BOARD_INIT_USB_HOST_MODE);
|
||||
FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_USBFS, ENABLE);
|
||||
|
||||
irq_config.irq_num = BSP_USBFS_GLB_IRQ_NUM;
|
||||
irq_config.int_src = INT_SRC_USBFS_GLB;
|
||||
irq_config.irq_prio = BSP_USBFS_GLB_IRQ_PRIO;
|
||||
/* register interrupt */
|
||||
hc32_install_irq_handler(&irq_config,
|
||||
usbh_fs_irq_handler,
|
||||
RT_TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RT_CHERRYUSB_DEVICE)
|
||||
static void usbd_fs_irq_handler(void)
|
||||
{
|
||||
USBD_IRQHandler(g_usb_fs_busid);
|
||||
}
|
||||
|
||||
#if defined(HC32F4A0) || defined(HC32F4A8)
|
||||
static void usbd_hs_irq_handler(void)
|
||||
{
|
||||
USBD_IRQHandler(g_usb_hs_busid);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HC32F472)
|
||||
void USBFS_Handler(void)
|
||||
{
|
||||
usbd_fs_irq_handler();
|
||||
}
|
||||
#endif
|
||||
|
||||
void usb_dc_low_level_init(uint8_t busid)
|
||||
{
|
||||
struct hc32_irq_config irq_config;
|
||||
|
||||
#if defined(HC32F4A0) || defined(HC32F4A8)
|
||||
if (g_usbdev_bus[busid].reg_base == CM_USBHS_BASE)
|
||||
{
|
||||
g_usb_hs_busid = busid;
|
||||
|
||||
rt_hw_usbhs_board_init(BOARD_INIT_USB_DEVICE_MODE);
|
||||
FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_USBHS, ENABLE);
|
||||
|
||||
#ifndef CONFIG_USB_HS
|
||||
/* enable the embedded PHY in USBHS mode */
|
||||
CM_PERIC->USB_SYCTLREG |= PERIC_USB_SYCTLREG_USBHS_FSPHYE;
|
||||
#endif
|
||||
|
||||
irq_config.irq_num = BSP_USBHS_GLB_IRQ_NUM;
|
||||
irq_config.int_src = INT_SRC_USBHS_GLB;
|
||||
irq_config.irq_prio = BSP_USBHS_GLB_IRQ_PRIO;
|
||||
/* register interrupt */
|
||||
hc32_install_irq_handler(&irq_config,
|
||||
usbd_hs_irq_handler,
|
||||
RT_TRUE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
g_usb_fs_busid = busid;
|
||||
|
||||
rt_hw_usbfs_board_init(BOARD_INIT_USB_DEVICE_MODE);
|
||||
FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_USBFS, ENABLE);
|
||||
|
||||
irq_config.irq_num = BSP_USBFS_GLB_IRQ_NUM;
|
||||
irq_config.int_src = INT_SRC_USBFS_GLB;
|
||||
irq_config.irq_prio = BSP_USBFS_GLB_IRQ_PRIO;
|
||||
/* register interrupt */
|
||||
hc32_install_irq_handler(&irq_config,
|
||||
usbd_fs_irq_handler,
|
||||
RT_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_dc_low_level_deinit(uint8_t busid)
|
||||
{
|
||||
(void)busid;
|
||||
/* reserved */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ const struct dwc2_user_params param_pa11_pa12 = {
|
||||
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
|
||||
.device_dma_enable = false,
|
||||
.device_dma_desc_enable = false,
|
||||
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
|
||||
.device_rx_fifo_size = (320 - 16 - 64 - 16 - 16),
|
||||
.device_tx_fifo_size = {
|
||||
[0] = 16, // 64 byte
|
||||
[1] = 16, // 64 byte
|
||||
[1] = 64, // 256 byte
|
||||
[2] = 16, // 64 byte
|
||||
[3] = 16, // 64 byte
|
||||
[4] = 0,
|
||||
@@ -50,10 +50,10 @@ const struct dwc2_user_params param_pa11_pa12 = {
|
||||
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
|
||||
.device_dma_enable = false,
|
||||
.device_dma_desc_enable = false,
|
||||
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
|
||||
.device_rx_fifo_size = (320 - 16 - 64 - 16 - 16),
|
||||
.device_tx_fifo_size = {
|
||||
[0] = 16, // 64 byte
|
||||
[1] = 16, // 64 byte
|
||||
[1] = 64, // 256 byte
|
||||
[2] = 16, // 64 byte
|
||||
[3] = 16, // 64 byte
|
||||
[4] = 0,
|
||||
@@ -124,10 +124,10 @@ const struct dwc2_user_params param_pa11_pa12 = {
|
||||
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
|
||||
.device_dma_enable = false,
|
||||
.device_dma_desc_enable = false,
|
||||
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
|
||||
.device_rx_fifo_size = (320 - 16 - 64 - 16 - 16),
|
||||
.device_tx_fifo_size = {
|
||||
[0] = 16, // 64 byte
|
||||
[1] = 16, // 64 byte
|
||||
[1] = 64, // 256 byte
|
||||
[2] = 16, // 64 byte
|
||||
[3] = 16, // 64 byte
|
||||
[4] = 0,
|
||||
@@ -212,10 +212,10 @@ const struct dwc2_user_params param_pa11_pa12 = {
|
||||
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
|
||||
.device_dma_enable = false,
|
||||
.device_dma_desc_enable = false,
|
||||
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
|
||||
.device_rx_fifo_size = (320 - 16 - 64 - 16 - 16),
|
||||
.device_tx_fifo_size = {
|
||||
[0] = 16, // 64 byte
|
||||
[1] = 16, // 64 byte
|
||||
[1] = 64, // 256 byte
|
||||
[2] = 16, // 64 byte
|
||||
[3] = 16, // 64 byte
|
||||
[4] = 0,
|
||||
@@ -380,10 +380,10 @@ const struct dwc2_user_params param_pa11_pa12 = {
|
||||
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
|
||||
.device_dma_enable = false,
|
||||
.device_dma_desc_enable = false,
|
||||
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
|
||||
.device_rx_fifo_size = (320 - 16 - 64 - 16 - 16),
|
||||
.device_tx_fifo_size = {
|
||||
[0] = 16, // 64 byte
|
||||
[1] = 16, // 64 byte
|
||||
[1] = 64, // 256 byte
|
||||
[2] = 16, // 64 byte
|
||||
[3] = 16, // 64 byte
|
||||
[4] = 0,
|
||||
@@ -446,10 +446,10 @@ const struct dwc2_user_params param_pa11_pa12 = {
|
||||
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
|
||||
.device_dma_enable = false,
|
||||
.device_dma_desc_enable = false,
|
||||
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
|
||||
.device_rx_fifo_size = (320 - 16 - 64 - 16 - 16),
|
||||
.device_tx_fifo_size = {
|
||||
[0] = 16, // 64 byte
|
||||
[1] = 16, // 64 byte
|
||||
[1] = 64, // 256 byte
|
||||
[2] = 16, // 64 byte
|
||||
[3] = 16, // 64 byte
|
||||
[4] = 0,
|
||||
@@ -481,10 +481,10 @@ const struct dwc2_user_params param_pa11_pa12 = {
|
||||
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
|
||||
.device_dma_enable = false,
|
||||
.device_dma_desc_enable = false,
|
||||
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
|
||||
.device_rx_fifo_size = (320 - 16 - 64 - 16 - 16),
|
||||
.device_tx_fifo_size = {
|
||||
[0] = 16, // 64 byte
|
||||
[1] = 16, // 64 byte
|
||||
[1] = 64, // 256 byte
|
||||
[2] = 16, // 64 byte
|
||||
[3] = 16, // 64 byte
|
||||
[4] = 0,
|
||||
|
||||
@@ -1337,6 +1337,7 @@ int usbh_kill_urb(struct usbh_urb *urb)
|
||||
EHCI_HCOR->usbcmd |= (EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN);
|
||||
|
||||
qh = (struct ehci_qh_hw *)urb->hcpriv;
|
||||
qh->remove_in_iaad = 0;
|
||||
urb->errorcode = -USB_ERR_SHUTDOWN;
|
||||
|
||||
if (urb->timeout) {
|
||||
@@ -1347,6 +1348,7 @@ int usbh_kill_urb(struct usbh_urb *urb)
|
||||
|
||||
if (remove_in_iaad) {
|
||||
volatile uint32_t timeout = 0;
|
||||
EHCI_HCOR->usbsts = EHCI_USBSTS_IAA;
|
||||
EHCI_HCOR->usbcmd |= EHCI_USBCMD_IAAD;
|
||||
while (!(EHCI_HCOR->usbsts & EHCI_USBSTS_IAA)) {
|
||||
timeout++;
|
||||
|
||||
@@ -102,7 +102,9 @@ int usb_dc_init(uint8_t busid)
|
||||
#endif
|
||||
|
||||
usb_device_init(g_hpm_udc[busid].handle, int_mask);
|
||||
|
||||
#ifdef CONFIG_USB_OTG_ENABLE
|
||||
usb_otgsc_enable_id_chg_int(g_hpm_udc[busid].handle->regs);
|
||||
#endif
|
||||
usb_dc_isr_connect(busid);
|
||||
|
||||
return 0;
|
||||
@@ -240,10 +242,15 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
|
||||
return -2;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
USB_ASSERT_MSG(!((uintptr_t)data % CONFIG_USB_ALIGN_SIZE), "data is not aligned %d", CONFIG_USB_ALIGN_SIZE);
|
||||
#endif
|
||||
|
||||
g_hpm_udc[busid].in_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_hpm_udc[busid].in_ep[ep_idx].xfer_len = data_len;
|
||||
g_hpm_udc[busid].in_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
usb_dcache_clean((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
|
||||
usb_device_edpt_xfer(handle, ep, (uint8_t *)data, data_len);
|
||||
|
||||
return 0;
|
||||
@@ -261,10 +268,15 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
|
||||
return -2;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
USB_ASSERT_MSG(!((uintptr_t)data % CONFIG_USB_ALIGN_SIZE), "data is not aligned %d", CONFIG_USB_ALIGN_SIZE);
|
||||
#endif
|
||||
|
||||
g_hpm_udc[busid].out_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_hpm_udc[busid].out_ep[ep_idx].xfer_len = data_len;
|
||||
g_hpm_udc[busid].out_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
usb_dcache_invalidate((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
|
||||
usb_device_edpt_xfer(handle, ep, data, data_len);
|
||||
|
||||
return 0;
|
||||
@@ -297,7 +309,7 @@ void USBD_IRQHandler(uint8_t busid)
|
||||
memset(g_hpm_udc[busid].in_ep, 0, sizeof(struct hpm_ep_state) * USB_NUM_BIDIR_ENDPOINTS);
|
||||
memset(g_hpm_udc[busid].out_ep, 0, sizeof(struct hpm_ep_state) * USB_NUM_BIDIR_ENDPOINTS);
|
||||
usbd_event_reset_handler(busid);
|
||||
usb_device_bus_reset(handle, 64);
|
||||
usb_device_bus_reset(handle, g_hpm_udc[busid].in_ep[0].ep_mps);
|
||||
}
|
||||
|
||||
if (int_status & intr_suspend) {
|
||||
@@ -362,6 +374,7 @@ void USBD_IRQHandler(uint8_t busid)
|
||||
if (ep_addr & 0x80) {
|
||||
usbd_event_ep_in_complete_handler(busid, ep_addr, transfer_len);
|
||||
} else {
|
||||
usb_dcache_invalidate((uintptr_t)g_hpm_udc[busid].out_ep[ep_idx].xfer_buf, USB_ALIGN_UP(transfer_len, CONFIG_USB_ALIGN_SIZE));
|
||||
usbd_event_ep_out_complete_handler(busid, ep_addr, transfer_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,73 @@
|
||||
#include "hpm_common.h"
|
||||
#include "hpm_soc.h"
|
||||
#include "hpm_l1c_drv.h"
|
||||
#include "hpm_usb_drv.h"
|
||||
#include "usb_config.h"
|
||||
|
||||
void (*g_usb_hpm_irq[2])(uint8_t busid);
|
||||
uint8_t g_usb_hpm_busid[2];
|
||||
|
||||
#ifndef CONFIG_CHERRYUSB_CUSTOM_IRQ_HANDLER
|
||||
SDK_DECLARE_EXT_ISR_M(IRQn_USB0, hpm_isr_usb0)
|
||||
#ifdef HPM_USB1_BASE
|
||||
SDK_DECLARE_EXT_ISR_M(IRQn_USB1, hpm_isr_usb1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_OTG_ENABLE
|
||||
#include "usbotg_core.h"
|
||||
int usb_otg_init(uint8_t busid)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_otg_deinit(uint8_t busid)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hpm_isr_usb0(void)
|
||||
{
|
||||
if (usb_otgsc_get_id_chg_flag(HPM_USB0)) {
|
||||
usb_otgsc_clear_id_chg_flag(HPM_USB0);
|
||||
usbotg_trigger_role_change(g_usb_hpm_busid[0], usb_otgsc_get_id_status(HPM_USB0) ? USBOTG_MODE_DEVICE : USBOTG_MODE_HOST);
|
||||
}
|
||||
|
||||
USBOTG_IRQHandler(g_usb_hpm_busid[0]);
|
||||
}
|
||||
|
||||
#ifdef HPM_USB1_BASE
|
||||
void hpm_isr_usb1(void)
|
||||
{
|
||||
if (usb_otgsc_get_id_chg_flag(HPM_USB1)) {
|
||||
usb_otgsc_clear_id_chg_flag(HPM_USB1);
|
||||
usbotg_trigger_role_change(g_usb_hpm_busid[1], usb_otgsc_get_id_status(HPM_USB1) ? USBOTG_MODE_DEVICE : USBOTG_MODE_HOST);
|
||||
}
|
||||
|
||||
USBOTG_IRQHandler(g_usb_hpm_busid[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
void hpm_isr_usb0(void)
|
||||
{
|
||||
g_usb_hpm_irq[0](g_usb_hpm_busid[0]);
|
||||
}
|
||||
|
||||
#ifdef HPM_USB1_BASE
|
||||
void hpm_isr_usb1(void)
|
||||
{
|
||||
g_usb_hpm_irq[1](g_usb_hpm_busid[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
ATTR_WEAK void hpm_usb_isr_enable(uint32_t base)
|
||||
{
|
||||
if (base == HPM_USB0_BASE) {
|
||||
@@ -34,24 +96,6 @@ ATTR_WEAK void hpm_usb_isr_disable(uint32_t base)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CHERRYUSB_CUSTOM_IRQ_HANDLER
|
||||
SDK_DECLARE_EXT_ISR_M(IRQn_USB0, hpm_isr_usb0)
|
||||
#endif
|
||||
void hpm_isr_usb0(void)
|
||||
{
|
||||
g_usb_hpm_irq[0](g_usb_hpm_busid[0]);
|
||||
}
|
||||
|
||||
#ifdef HPM_USB1_BASE
|
||||
#ifndef CONFIG_CHERRYUSB_CUSTOM_IRQ_HANDLER
|
||||
SDK_DECLARE_EXT_ISR_M(IRQn_USB1, hpm_isr_usb1)
|
||||
#endif
|
||||
void hpm_isr_usb1(void)
|
||||
{
|
||||
g_usb_hpm_irq[1](g_usb_hpm_busid[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
void usb_dcache_clean(uintptr_t addr, size_t size)
|
||||
{
|
||||
@@ -67,4 +111,4 @@ void usb_dcache_flush(uintptr_t addr, size_t size)
|
||||
{
|
||||
l1c_dc_flush(addr, size);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -57,31 +57,29 @@ void usb_hc_low_level2_init(struct usbh_bus *bus)
|
||||
if (bus->hcd.reg_base == HPM_USB0_BASE) {
|
||||
g_usb_hpm_busid[0] = bus->hcd.hcd_id;
|
||||
g_usb_hpm_irq[0] = USBH_IRQHandler;
|
||||
|
||||
hpm_usb_isr_enable(HPM_USB0_BASE);
|
||||
} else {
|
||||
#ifdef HPM_USB1_BASE
|
||||
g_usb_hpm_busid[1] = bus->hcd.hcd_id;
|
||||
g_usb_hpm_irq[1] = USBH_IRQHandler;
|
||||
|
||||
hpm_usb_isr_enable(HPM_USB1_BASE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_OTG_ENABLE
|
||||
usb_otgsc_enable_id_chg_int((USB_Type *)(bus->hcd.reg_base));
|
||||
#endif
|
||||
hpm_usb_isr_enable(bus->hcd.reg_base);
|
||||
}
|
||||
|
||||
void usb_hc_low_level_deinit(struct usbh_bus *bus)
|
||||
{
|
||||
usb_phy_deinit((USB_Type *)(bus->hcd.reg_base));
|
||||
hpm_usb_isr_disable(bus->hcd.reg_base);
|
||||
|
||||
if (bus->hcd.reg_base == HPM_USB0_BASE) {
|
||||
hpm_usb_isr_disable(HPM_USB0_BASE);
|
||||
|
||||
g_usb_hpm_busid[0] = 0;
|
||||
g_usb_hpm_irq[0] = NULL;
|
||||
} else {
|
||||
#ifdef HPM_USB1_BASE
|
||||
hpm_usb_isr_disable(HPM_USB1_BASE);
|
||||
|
||||
g_usb_hpm_busid[1] = 0;
|
||||
g_usb_hpm_irq[1] = NULL;
|
||||
#endif
|
||||
|
||||
@@ -82,4 +82,12 @@ void usb_dc_low_level_deinit(uint8_t busid)
|
||||
|
||||
void usbd_kinetis_delay_ms(uint8_t ms)
|
||||
{
|
||||
#ifdef __RTTHREAD__
|
||||
rt_thread_mdelay(ms);
|
||||
#else
|
||||
for (uint32_t i = 0; i < ms; i++)
|
||||
{
|
||||
for (volatile uint32_t j = 0; j < 10000; j++);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -328,10 +328,16 @@ void musb_control_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb
|
||||
speed = USB_TYPE0_SPEED_LOW;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_MUSB_WITHOUT_MULTIPOINT
|
||||
/* Without multipoint, use FADDR for host target addressing and do not access Hub/FuncAddr regs */
|
||||
HWREGB(USB_BASE + MUSB_FADDR_OFFSET) = (urb->hport->dev_addr & 0x7F);
|
||||
HWREGB(USB_TXTYPE_BASE(chidx)) = speed;
|
||||
#else
|
||||
HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr;
|
||||
HWREGB(USB_TXTYPE_BASE(chidx)) = speed;
|
||||
HWREGB(USB_TXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_TXHUBPORT_BASE(chidx)) = 0;
|
||||
#endif
|
||||
|
||||
musb_write_packet(bus, chidx, (uint8_t *)setup, 8);
|
||||
HWREGB(USB_TXCSRL_BASE(chidx)) = USB_CSRL0_TXRDY | USB_CSRL0_SETUP;
|
||||
@@ -360,12 +366,19 @@ int musb_bulk_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_MUSB_WITHOUT_MULTIPOINT
|
||||
HWREGB(USB_BASE + MUSB_FADDR_OFFSET) = (urb->hport->dev_addr & 0x7F);
|
||||
HWREGB(USB_RXTYPE_BASE(chidx)) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_BULK;
|
||||
HWREGH(USB_RXMAP_BASE(chidx)) = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
HWREGB(USB_RXINTERVAL_BASE(chidx)) = 0;
|
||||
#else
|
||||
HWREGB(USB_RXADDR_BASE(chidx)) = urb->hport->dev_addr;
|
||||
HWREGB(USB_RXTYPE_BASE(chidx)) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_BULK;
|
||||
HWREGH(USB_RXMAP_BASE(chidx)) = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
HWREGB(USB_RXINTERVAL_BASE(chidx)) = 0;
|
||||
HWREGB(USB_RXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_RXHUBPORT_BASE(chidx)) = 0;
|
||||
#endif
|
||||
HWREGB(USB_TXCSRH_BASE(chidx)) &= ~USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_RXCSRL_BASE(chidx)) = USB_RXCSRL1_REQPKT;
|
||||
|
||||
@@ -376,12 +389,19 @@ int musb_bulk_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_MUSB_WITHOUT_MULTIPOINT
|
||||
HWREGB(USB_BASE + MUSB_FADDR_OFFSET) = (urb->hport->dev_addr & 0x7F);
|
||||
HWREGB(USB_TXTYPE_BASE(chidx)) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_BULK;
|
||||
HWREGH(USB_TXMAP_BASE(chidx)) = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
HWREGB(USB_TXINTERVAL_BASE(chidx)) = 0;
|
||||
#else
|
||||
HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr;
|
||||
HWREGB(USB_TXTYPE_BASE(chidx)) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_BULK;
|
||||
HWREGH(USB_TXMAP_BASE(chidx)) = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
HWREGB(USB_TXINTERVAL_BASE(chidx)) = 0;
|
||||
HWREGB(USB_TXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_TXHUBPORT_BASE(chidx)) = 0;
|
||||
#endif
|
||||
|
||||
if (buflen > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
|
||||
buflen = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
@@ -419,12 +439,19 @@ int musb_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_MUSB_WITHOUT_MULTIPOINT
|
||||
HWREGB(USB_BASE + MUSB_FADDR_OFFSET) = (urb->hport->dev_addr & 0x7F);
|
||||
HWREGB(USB_RXTYPE_BASE(chidx)) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_INT;
|
||||
HWREGH(USB_RXMAP_BASE(chidx)) = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
HWREGB(USB_RXINTERVAL_BASE(chidx)) = urb->ep->bInterval;
|
||||
#else
|
||||
HWREGB(USB_RXADDR_BASE(chidx)) = urb->hport->dev_addr;
|
||||
HWREGB(USB_RXTYPE_BASE(chidx)) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_INT;
|
||||
HWREGH(USB_RXMAP_BASE(chidx)) = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
HWREGB(USB_RXINTERVAL_BASE(chidx)) = urb->ep->bInterval;
|
||||
HWREGB(USB_RXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_RXHUBPORT_BASE(chidx)) = 0;
|
||||
#endif
|
||||
HWREGB(USB_TXCSRH_BASE(chidx)) &= ~USB_TXCSRH1_MODE;
|
||||
HWREGB(USB_RXCSRL_BASE(chidx)) = USB_RXCSRL1_REQPKT;
|
||||
|
||||
@@ -435,12 +462,19 @@ int musb_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_MUSB_WITHOUT_MULTIPOINT
|
||||
HWREGB(USB_BASE + MUSB_FADDR_OFFSET) = (urb->hport->dev_addr & 0x7F);
|
||||
HWREGB(USB_TXTYPE_BASE(chidx)) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_INT;
|
||||
HWREGH(USB_TXMAP_BASE(chidx)) = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
HWREGB(USB_TXINTERVAL_BASE(chidx)) = urb->ep->bInterval;
|
||||
#else
|
||||
HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr;
|
||||
HWREGB(USB_TXTYPE_BASE(chidx)) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_INT;
|
||||
HWREGH(USB_TXMAP_BASE(chidx)) = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
HWREGB(USB_TXINTERVAL_BASE(chidx)) = urb->ep->bInterval;
|
||||
HWREGB(USB_TXHUBADDR_BASE(chidx)) = 0;
|
||||
HWREGB(USB_TXHUBPORT_BASE(chidx)) = 0;
|
||||
#endif
|
||||
|
||||
if (buflen > USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
|
||||
buflen = USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize);
|
||||
|
||||
46
tests/bouffalolab/CMakeLists.txt
Normal file
46
tests/bouffalolab/CMakeLists.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
include(proj.conf)
|
||||
|
||||
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
|
||||
|
||||
sdk_add_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_ECM)
|
||||
sdk_add_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_NCM)
|
||||
sdk_add_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_RNDIS)
|
||||
sdk_add_compile_definitions(-DCONFIG_USBHOST_PLATFORM_ASIX)
|
||||
sdk_add_compile_definitions(-DCONFIG_USBHOST_PLATFORM_RTL8152)
|
||||
sdk_add_include_directories(inc)
|
||||
|
||||
target_sources(app PRIVATE ../../demo/usb_host.c)
|
||||
|
||||
set(CONFIG_CHERRYMP 1)
|
||||
set(CONFIG_CHERRYUSB 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE 1)
|
||||
set(CONFIG_CHERRYUSB_HOST 1)
|
||||
|
||||
set(CONFIG_CHERRYUSB_DEVICE_CDC_RNDIS 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE_CDC_ECM 1)
|
||||
|
||||
# add_subdirectory(src/cherryusb_hostuvcuac)
|
||||
add_subdirectory(../.. cherryusb)
|
||||
|
||||
# sdk_add_link_options(-uusbd_cdc_acm_init_intf)
|
||||
# sdk_add_link_options(-uusbd_hid_init_intf)
|
||||
# sdk_add_link_options(-uusbd_msc_init_intf)
|
||||
# sdk_add_link_options(-uusbd_video_init_intf)
|
||||
# sdk_add_link_options(-uusbd_audio_init_intf)
|
||||
# sdk_add_link_options(-uusbd_cdc_ecm_init_intf)
|
||||
# sdk_add_link_options(-uusbd_rndis_init_intf)
|
||||
# sdk_add_link_options(-uusbd_initialize)
|
||||
# sdk_add_link_options(-uusbd_desc_register)
|
||||
# sdk_add_link_options(-uusbd_add_interface)
|
||||
# sdk_add_link_options(-uusbd_add_endpoint)
|
||||
# sdk_add_link_options(-uusbd_rndis_start_write)
|
||||
# sdk_add_link_options(-uusbd_rndis_start_read)
|
||||
# sdk_add_link_options(-uusbd_cdc_ecm_start_write)
|
||||
# sdk_add_link_options(-uusbd_cdc_ecm_start_read)
|
||||
# sdk_add_link_options(-uusbd_video_stream_start_write)
|
||||
# sdk_add_link_options(-uusbd_video_stream_split_transfer)
|
||||
|
||||
sdk_set_main_file(src/main.c)
|
||||
project(cherryusb)
|
||||
13
tests/bouffalolab/Makefile
Normal file
13
tests/bouffalolab/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
SDK_DEMO_PATH ?= .
|
||||
BL_SDK_BASE ?= /home/sakumisu/repo/bouffalolab/bouffalo_sdk_github
|
||||
|
||||
export BL_SDK_BASE
|
||||
|
||||
CHIP ?= bl616
|
||||
BOARD ?= bl616dk
|
||||
CROSS_COMPILE = riscv64-unknown-elf-
|
||||
|
||||
# add custom cmake definition
|
||||
#cmake_definition+=-Dxxx=sss
|
||||
|
||||
include $(BL_SDK_BASE)/project.build
|
||||
14
tests/bouffalolab/flash_prog_cfg.ini
Normal file
14
tests/bouffalolab/flash_prog_cfg.ini
Normal file
@@ -0,0 +1,14 @@
|
||||
[cfg]
|
||||
# 0: no erase, 1:programmed section erase, 2: chip erase
|
||||
erase = 1
|
||||
# skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
|
||||
skip_mode = 0x0, 0x0
|
||||
# 0: not use isp mode, #1: isp mode
|
||||
boot2_isp_mode = 0
|
||||
pre_program =
|
||||
pre_program_args =
|
||||
|
||||
[FW]
|
||||
filedir = ./build/build_out/cherryusb*_$(CHIPNAME).bin
|
||||
address = 0x000000
|
||||
|
||||
128
tests/bouffalolab/inc/FreeRTOSConfig.h
Normal file
128
tests/bouffalolab/inc/FreeRTOSConfig.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.
|
||||
*----------------------------------------------------------*/
|
||||
#if defined(BL602) || defined(BL702) || defined(BL702L)
|
||||
#define configMTIME_BASE_ADDRESS (0x02000000UL + 0xBFF8UL)
|
||||
#define configMTIMECMP_BASE_ADDRESS (0x02000000UL + 0x4000UL)
|
||||
#else
|
||||
#if __riscv_xlen == 64
|
||||
#define configMTIME_BASE_ADDRESS (0)
|
||||
#define configMTIMECMP_BASE_ADDRESS ((0xE4000000UL) + 0x4000UL)
|
||||
#else
|
||||
#define configMTIME_BASE_ADDRESS ((0xE0000000UL) + 0xBFF8UL)
|
||||
#define configMTIMECMP_BASE_ADDRESS ((0xE0000000UL) + 0x4000UL)
|
||||
#endif
|
||||
#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 (32)
|
||||
#define configMINIMAL_STACK_SIZE ((unsigned short)128) /* 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)24 * 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 1
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#define configUSE_TICKLESS_IDLE 0
|
||||
#define configUSE_POSIX_ERRNO 1
|
||||
|
||||
#define configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS 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 (512)
|
||||
/* 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);
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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 */
|
||||
270
tests/bouffalolab/inc/fatfs_conf_user.h
Normal file
270
tests/bouffalolab/inc/fatfs_conf_user.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Configurations of FatFs Module
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
/* User external configuration, User need to use this file as a template.
|
||||
All configuration items must be included in the file */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_FS_CONTINUOUS 1
|
||||
/* Read and write as much data as possible at one time, regardless of the cluster size */
|
||||
|
||||
#define FF_FS_READONLY 0
|
||||
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
||||
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
|
||||
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
|
||||
/ and optional writing functions as well. */
|
||||
|
||||
#define FF_FS_MINIMIZE 0
|
||||
/* This option defines minimization level to remove some basic API functions.
|
||||
/
|
||||
/ 0: Basic functions are fully enabled.
|
||||
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
|
||||
/ are removed.
|
||||
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
|
||||
/ 3: f_lseek() function is removed in addition to 2. */
|
||||
|
||||
#define FF_USE_FIND 1
|
||||
/* This option switches filtered directory read functions, f_findfirst() and
|
||||
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
||||
|
||||
#define FF_USE_MKFS 1
|
||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||
|
||||
#define FF_USE_FASTSEEK 1
|
||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||
|
||||
#define FF_USE_EXPAND 0
|
||||
/* This option switches f_expand function. (0:Disable or 1:Enable) */
|
||||
|
||||
#define FF_USE_CHMOD 0
|
||||
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
||||
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
|
||||
|
||||
#define FF_USE_LABEL 0
|
||||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||
/ (0:Disable or 1:Enable) */
|
||||
|
||||
#define FF_USE_FORWARD 0
|
||||
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
|
||||
|
||||
#define FF_USE_STRFUNC 0
|
||||
#define FF_PRINT_LLI 1
|
||||
#define FF_PRINT_FLOAT 1
|
||||
#define FF_STRF_ENCODE 3
|
||||
/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and
|
||||
/ f_printf().
|
||||
/
|
||||
/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
|
||||
/ 1: Enable without LF-CRLF conversion.
|
||||
/ 2: Enable with LF-CRLF conversion.
|
||||
/
|
||||
/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
|
||||
/ makes f_printf() support floating point argument. These features want C99 or later.
|
||||
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character
|
||||
/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
|
||||
/ to be read/written via those functions.
|
||||
/
|
||||
/ 0: ANSI/OEM in current CP
|
||||
/ 1: Unicode in UTF-16LE
|
||||
/ 2: Unicode in UTF-16BE
|
||||
/ 3: Unicode in UTF-8
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Locale and Namespace Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_CODE_PAGE 437
|
||||
/* This option specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect code page setting can cause a file open failure.
|
||||
/
|
||||
/ 437 - U.S.
|
||||
/ 720 - Arabic
|
||||
/ 737 - Greek
|
||||
/ 771 - KBL
|
||||
/ 775 - Baltic
|
||||
/ 850 - Latin 1
|
||||
/ 852 - Latin 2
|
||||
/ 855 - Cyrillic
|
||||
/ 857 - Turkish
|
||||
/ 860 - Portuguese
|
||||
/ 861 - Icelandic
|
||||
/ 862 - Hebrew
|
||||
/ 863 - Canadian French
|
||||
/ 864 - Arabic
|
||||
/ 865 - Nordic
|
||||
/ 866 - Russian
|
||||
/ 869 - Greek 2
|
||||
/ 932 - Japanese (DBCS)
|
||||
/ 936 - Simplified Chinese (DBCS)
|
||||
/ 949 - Korean (DBCS)
|
||||
/ 950 - Traditional Chinese (DBCS)
|
||||
/ 0 - Include all code pages above and configured by f_setcp()
|
||||
*/
|
||||
|
||||
#define FF_USE_LFN 2
|
||||
#define FF_MAX_LFN 255
|
||||
/* The FF_USE_LFN switches the support for LFN (long file name).
|
||||
/
|
||||
/ 0: Disable LFN. FF_MAX_LFN has no effect.
|
||||
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||
/
|
||||
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
|
||||
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
|
||||
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
|
||||
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
|
||||
/ be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN
|
||||
/ specification.
|
||||
/ When use stack for the working buffer, take care on stack overflow. When use heap
|
||||
/ memory for the working buffer, memory management functions, ff_memalloc() and
|
||||
/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */
|
||||
|
||||
#define FF_LFN_UNICODE 0
|
||||
/* This option switches the character encoding on the API when LFN is enabled.
|
||||
/
|
||||
/ 0: ANSI/OEM in current CP (TCHAR = char)
|
||||
/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
|
||||
/ 2: Unicode in UTF-8 (TCHAR = char)
|
||||
/ 3: Unicode in UTF-32 (TCHAR = DWORD)
|
||||
/
|
||||
/ Also behavior of string I/O functions will be affected by this option.
|
||||
/ When LFN is not enabled, this option has no effect. */
|
||||
|
||||
#define FF_LFN_BUF 255
|
||||
#define FF_SFN_BUF 12
|
||||
/* This set of options defines size of file name members in the FILINFO structure
|
||||
/ which is used to read out directory items. These values should be suffcient for
|
||||
/ the file names to read. The maximum possible length of the read file name depends
|
||||
/ on character encoding. When LFN is not enabled, these options have no effect. */
|
||||
|
||||
#define FF_FS_RPATH 0
|
||||
/* This option configures support for relative path.
|
||||
/
|
||||
/ 0: Disable relative path and remove related functions.
|
||||
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
|
||||
/ 2: f_getcwd() function is available in addition to 1.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Drive/Volume Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_VOLUMES 5
|
||||
/* Number of volumes (logical drives) to be used. (1-10) */
|
||||
|
||||
#define FF_STR_VOLUME_ID 2
|
||||
#define FF_VOLUME_STRS "ram", "flash", "sd", "sd2", "usb"
|
||||
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
||||
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
||||
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
||||
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
|
||||
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
|
||||
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
|
||||
/ not defined, a user defined volume string table is needed as:
|
||||
/
|
||||
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
|
||||
*/
|
||||
|
||||
#define FF_MULTI_PARTITION 0
|
||||
/* This option switches support for multiple volumes on the physical drive.
|
||||
/ By default (0), each logical drive number is bound to the same physical drive
|
||||
/ number and only an FAT volume found on the physical drive will be mounted.
|
||||
/ When this function is enabled (1), each logical drive number can be bound to
|
||||
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
|
||||
/ function will be available. */
|
||||
|
||||
#define FF_MIN_SS 512
|
||||
#define FF_MAX_SS 512
|
||||
/* This set of options configures the range of sector size to be supported. (512,
|
||||
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
|
||||
/ harddisk, but a larger value may be required for on-board flash memory and some
|
||||
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
|
||||
/ for variable sector size mode and disk_ioctl() function needs to implement
|
||||
/ GET_SECTOR_SIZE command. */
|
||||
|
||||
#define FF_LBA64 0
|
||||
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
|
||||
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
|
||||
|
||||
#define FF_MIN_GPT 0x10000000
|
||||
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
|
||||
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
|
||||
|
||||
#define FF_USE_TRIM 0
|
||||
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
|
||||
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ System Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_FS_TINY 0
|
||||
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
||||
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
|
||||
/ Instead of private sector buffer eliminated from the file object, common sector
|
||||
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
|
||||
|
||||
#define FF_FS_EXFAT 0
|
||||
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
||||
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
|
||||
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
||||
|
||||
#define FF_FS_NORTC 1
|
||||
#define FF_NORTC_MON 1
|
||||
#define FF_NORTC_MDAY 1
|
||||
#define FF_NORTC_YEAR 2022
|
||||
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
|
||||
/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
|
||||
/ timestamp feature. Every object modified by FatFs will have a fixed timestamp
|
||||
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
|
||||
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
|
||||
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
|
||||
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
|
||||
/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
|
||||
|
||||
#define FF_FS_NOFSINFO 0
|
||||
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
||||
/ option, and f_getfree() function at the first time after volume mount will force
|
||||
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
||||
/
|
||||
/ bit0=0: Use free cluster count in the FSINFO if available.
|
||||
/ bit0=1: Do not trust free cluster count in the FSINFO.
|
||||
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
|
||||
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
|
||||
*/
|
||||
|
||||
#define FF_FS_LOCK 0
|
||||
/* The option FF_FS_LOCK switches file lock function to control duplicated file open
|
||||
/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
|
||||
/ is 1.
|
||||
/
|
||||
/ 0: Disable file lock function. To avoid volume corruption, application program
|
||||
/ should avoid illegal open, remove and rename to the open objects.
|
||||
/ >0: Enable file lock function. The value defines how many files/sub-directories
|
||||
/ can be opened simultaneously under file lock control. Note that the file
|
||||
/ lock control is independent of re-entrancy. */
|
||||
|
||||
#define FF_FS_REENTRANT 0
|
||||
#define FF_FS_TIMEOUT 1000
|
||||
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
|
||||
/ module itself. Note that regardless of this option, file access to different
|
||||
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
||||
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
|
||||
/ to the same volume is under control of this featuer.
|
||||
/
|
||||
/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
|
||||
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
||||
/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give()
|
||||
/ function, must be added to the project. Samples are available in ffsystem.c.
|
||||
/
|
||||
/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
|
||||
*/
|
||||
|
||||
/*--- End of configuration options ---*/
|
||||
442
tests/bouffalolab/inc/lwipopts_user.h
Normal file
442
tests/bouffalolab/inc/lwipopts_user.h
Normal file
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
* Copyright (c) 2025, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef LWIPOPTS_H
|
||||
#define LWIPOPTS_H
|
||||
|
||||
#ifdef USE_LWIPOPTS_APP_H
|
||||
#include "lwipopts_app.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
|
||||
* critical regions during buffer allocation, deallocation and memory
|
||||
* allocation and deallocation.
|
||||
*/
|
||||
#define SYS_LIGHTWEIGHT_PROT 1
|
||||
#define IP_REASSEMBLY 0
|
||||
#define IP_FRAG 0
|
||||
#define ARP_QUEUEING 0
|
||||
#define NO_SYS 0
|
||||
#define LWIP_RAND rand
|
||||
|
||||
#define LWIP_NETIF_HOSTNAME 0
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
#define LWIP_TIMERS 1
|
||||
#define LWIP_RAW 1
|
||||
#define LWIP_IPV4 1
|
||||
#define LWIP_IGMP 1
|
||||
#define LWIP_ICMP 1
|
||||
#define ICMP_TTL 64
|
||||
#define LWIP_TCP 1
|
||||
#define TCP_TTL 255
|
||||
#define LWIP_UDP 1
|
||||
#define UDP_TTL 255
|
||||
#define LWIP_DNS 1
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_API==1: Support netif api (in netifapi.c)
|
||||
*/
|
||||
#define LWIP_NETIF_API 1
|
||||
/**
|
||||
* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
|
||||
*/
|
||||
#define LWIP_NETCONN 1
|
||||
/**
|
||||
* LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
|
||||
*/
|
||||
#define LWIP_SOCKET 1
|
||||
|
||||
/* ---------- Memory options ---------- */
|
||||
#define MEMP_MEM_MALLOC 0
|
||||
|
||||
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
|
||||
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
|
||||
byte alignment -> define MEM_ALIGNMENT to 2. */
|
||||
#ifndef MEM_ALIGNMENT
|
||||
#define MEM_ALIGNMENT 64
|
||||
#endif
|
||||
|
||||
/* MEM_SIZE: the size of the heap memory. If the application will send
|
||||
a lot of data that needs to be copied, this should be set high. */
|
||||
#ifndef MEM_SIZE
|
||||
#define MEM_SIZE (32 * 1024)
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
|
||||
sends a lot of data out of ROM (or other static memory), this
|
||||
should be set high. */
|
||||
#ifndef MEMP_NUM_PBUF
|
||||
#define MEMP_NUM_PBUF 100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_RAW_PCB: Number of raw connection PCBs
|
||||
* (requires the LWIP_RAW option)
|
||||
*/
|
||||
#ifndef MEMP_NUM_RAW_PCB
|
||||
#define MEMP_NUM_RAW_PCB 4
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
|
||||
per active UDP "connection". */
|
||||
#ifndef MEMP_NUM_UDP_PCB
|
||||
#define MEMP_NUM_UDP_PCB 4
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
|
||||
connections. */
|
||||
#ifndef MEMP_NUM_TCP_PCB
|
||||
#define MEMP_NUM_TCP_PCB 4
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
|
||||
connections. */
|
||||
#ifndef MEMP_NUM_TCP_PCB_LISTEN
|
||||
#define MEMP_NUM_TCP_PCB_LISTEN 5
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
|
||||
segments. */
|
||||
#ifndef MEMP_NUM_TCP_SEG
|
||||
#define MEMP_NUM_TCP_SEG 40
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
|
||||
timeouts. */
|
||||
#ifndef MEMP_NUM_SYS_TIMEOUT
|
||||
#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_NETCONN: the number of struct netconns.
|
||||
* (only needed if you use the sequential API, like api_lib.c)
|
||||
*/
|
||||
#ifndef MEMP_NUM_NETCONN
|
||||
#define MEMP_NUM_NETCONN 4
|
||||
#endif
|
||||
|
||||
/* ---------- Pbuf options ---------- */
|
||||
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
|
||||
#ifndef PBUF_POOL_SIZE
|
||||
#define PBUF_POOL_SIZE 20
|
||||
#endif
|
||||
|
||||
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
|
||||
#ifndef PBUF_POOL_BUFSIZE
|
||||
#define PBUF_POOL_BUFSIZE 1600
|
||||
#endif
|
||||
|
||||
/* ---------- TCP options ---------- */
|
||||
/* Controls if TCP should queue segments that arrive out of
|
||||
order. Define to 0 if your device is low on memory. */
|
||||
#ifndef TCP_QUEUE_OOSEQ
|
||||
#define TCP_QUEUE_OOSEQ 0
|
||||
#endif
|
||||
|
||||
/* TCP Maximum segment size. */
|
||||
#ifndef TCP_MSS
|
||||
#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
|
||||
#endif
|
||||
|
||||
/* TCP sender buffer space (bytes). */
|
||||
#ifndef TCP_SND_BUF
|
||||
#define TCP_SND_BUF (8 * TCP_MSS)
|
||||
#endif
|
||||
|
||||
/* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
|
||||
as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */
|
||||
#ifndef TCP_SND_QUEUELEN
|
||||
#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF / TCP_MSS)
|
||||
#endif
|
||||
|
||||
/* TCP receive window. */
|
||||
#ifndef TCP_WND
|
||||
#define TCP_WND (16 * TCP_MSS)
|
||||
#endif
|
||||
|
||||
/* ---------- DHCP options ---------- */
|
||||
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
|
||||
interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
|
||||
turning this on does currently not work. */
|
||||
#ifndef LWIP_DHCP
|
||||
#define LWIP_DHCP 1
|
||||
#endif
|
||||
|
||||
/* ---------- Statistics options ---------- */
|
||||
#ifndef LWIP_STATS
|
||||
#define LWIP_STATS 0
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_PROVIDE_ERRNO
|
||||
#define LWIP_PROVIDE_ERRNO 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
------------------------------------------------
|
||||
---------- Network Interfaces options ----------
|
||||
------------------------------------------------
|
||||
*/
|
||||
/**
|
||||
* LWIP_SINGLE_NETIF==1: use a single netif only. This is the common case for
|
||||
* small real-life targets. Some code like routing etc. can be left out.
|
||||
*/
|
||||
#ifndef LWIP_SINGLE_NETIF
|
||||
#define LWIP_SINGLE_NETIF 1
|
||||
#endif
|
||||
|
||||
/* ---------- link callback options ---------- */
|
||||
/* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface
|
||||
* whenever the link changes (i.e., link down)
|
||||
*/
|
||||
#ifndef LWIP_NETIF_LINK_CALLBACK
|
||||
#define LWIP_NETIF_LINK_CALLBACK 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP *tries* to put all data
|
||||
* to be sent into one single pbuf. This is for compatibility with DMA-enabled
|
||||
* MACs that do not support scatter-gather.
|
||||
* Beware that this might involve CPU-memcpy before transmitting that would not
|
||||
* be needed without this flag! Use this only if you need to!
|
||||
*
|
||||
* ATTENTION: a driver should *NOT* rely on getting single pbufs but check TX
|
||||
* pbufs for being in one piece. If not, @ref pbuf_clone can be used to get
|
||||
* a single pbuf:
|
||||
* if (p->next != NULL) {
|
||||
* struct pbuf *q = pbuf_clone(PBUF_RAW, PBUF_RAM, p);
|
||||
* if (q == NULL) {
|
||||
* return ERR_MEM;
|
||||
* }
|
||||
* p = q; ATTENTION: do NOT free the old 'p' as the ref belongs to the caller!
|
||||
* }
|
||||
*/
|
||||
#ifndef LWIP_NETIF_TX_SINGLE_PBUF
|
||||
#define LWIP_NETIF_TX_SINGLE_PBUF 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
--------------------------------------
|
||||
---------- Checksum options ----------
|
||||
--------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some MCUs allow computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
|
||||
* To use this feature let the following define uncommented.
|
||||
* To disable it and process by CPU comment the the checksum.
|
||||
*/
|
||||
#ifdef CHECKSUM_BY_HARDWARE
|
||||
/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
|
||||
#define CHECKSUM_GEN_IP 0
|
||||
/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
|
||||
#define CHECKSUM_GEN_UDP 0
|
||||
/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
|
||||
#define CHECKSUM_GEN_TCP 0
|
||||
/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
|
||||
#define CHECKSUM_CHECK_IP 0
|
||||
/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
|
||||
#define CHECKSUM_CHECK_UDP 0
|
||||
/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
|
||||
#define CHECKSUM_CHECK_TCP 0
|
||||
/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/
|
||||
#define CHECKSUM_GEN_ICMP 0
|
||||
#else
|
||||
/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
|
||||
#define CHECKSUM_GEN_IP 1
|
||||
/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
|
||||
#define CHECKSUM_GEN_UDP 1
|
||||
/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
|
||||
#define CHECKSUM_GEN_TCP 1
|
||||
/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
|
||||
#define CHECKSUM_CHECK_IP 1
|
||||
/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
|
||||
#define CHECKSUM_CHECK_UDP 1
|
||||
/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
|
||||
#define CHECKSUM_CHECK_TCP 1
|
||||
/* CHECKSUM_CHECK_ICMP==1: Check checksums by software for incoming ICMP packets.*/
|
||||
#define CHECKSUM_GEN_ICMP 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
-----------------------------------
|
||||
---------- DEBUG options ----------
|
||||
-----------------------------------
|
||||
*/
|
||||
#ifdef LWIP_DEBUG
|
||||
|
||||
#ifndef LWIP_DBG_MIN_LEVEL
|
||||
#define LWIP_DBG_MIN_LEVEL 0
|
||||
#endif
|
||||
|
||||
#ifndef PPP_DEBUG
|
||||
#define PPP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef MEM_DEBUG
|
||||
#define MEM_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_DEBUG
|
||||
#define MEMP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef PBUF_DEBUG
|
||||
#define PBUF_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef API_LIB_DEBUG
|
||||
#define API_LIB_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef API_MSG_DEBUG
|
||||
#define API_MSG_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCPIP_DEBUG
|
||||
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef NETIF_DEBUG
|
||||
#define NETIF_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef SOCKETS_DEBUG
|
||||
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef DNS_DEBUG
|
||||
#define DNS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef AUTOIP_DEBUG
|
||||
#define AUTOIP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef DHCP_DEBUG
|
||||
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef IP_DEBUG
|
||||
#define IP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef IP_REASS_DEBUG
|
||||
#define IP_REASS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef ICMP_DEBUG
|
||||
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef IGMP_DEBUG
|
||||
#define IGMP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef UDP_DEBUG
|
||||
#define UDP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_DEBUG
|
||||
#define TCP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_INPUT_DEBUG
|
||||
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_OUTPUT_DEBUG
|
||||
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_RTO_DEBUG
|
||||
#define TCP_RTO_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_CWND_DEBUG
|
||||
#define TCP_CWND_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_WND_DEBUG
|
||||
#define TCP_WND_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_FR_DEBUG
|
||||
#define TCP_FR_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_QLEN_DEBUG
|
||||
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_RST_DEBUG
|
||||
#define TCP_RST_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef ETHARP_DEBUG
|
||||
#define ETHARP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
---------------------------------
|
||||
---------- OS options ----------
|
||||
---------------------------------
|
||||
*/
|
||||
#ifndef TCPIP_THREAD_NAME
|
||||
#define TCPIP_THREAD_NAME "tcpip"
|
||||
#endif
|
||||
|
||||
#ifndef TCPIP_THREAD_STACKSIZE
|
||||
#define TCPIP_THREAD_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef TCPIP_MBOX_SIZE
|
||||
#define TCPIP_MBOX_SIZE 8
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_RAW_RECVMBOX_SIZE
|
||||
#define DEFAULT_RAW_RECVMBOX_SIZE 50
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_UDP_RECVMBOX_SIZE
|
||||
#define DEFAULT_UDP_RECVMBOX_SIZE 50
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_TCP_RECVMBOX_SIZE
|
||||
#define DEFAULT_TCP_RECVMBOX_SIZE 50
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_ACCEPTMBOX_SIZE
|
||||
#define DEFAULT_ACCEPTMBOX_SIZE 50
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_THREAD_STACKSIZE
|
||||
#define DEFAULT_THREAD_STACKSIZE 500
|
||||
#endif
|
||||
|
||||
#ifndef TCPIP_THREAD_PRIO
|
||||
#define TCPIP_THREAD_PRIO 10
|
||||
#endif
|
||||
|
||||
#define LWIP_COMPAT_MUTEX 0
|
||||
#define LWIP_TCPIP_CORE_LOCKING 1
|
||||
|
||||
#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT
|
||||
#define LWIP_TCPIP_CORE_LOCKING_INPUT 1
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_MEM_SECTION
|
||||
#define LWIP_MEM_SECTION ".bss"
|
||||
#endif
|
||||
|
||||
// bouffalo patch
|
||||
#define LWIP_DNS_SERVER 0
|
||||
#define LWIP_SUPPORT_CUSTOM_PBUF 1
|
||||
|
||||
#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)] __attribute__((section(LWIP_MEM_SECTION)))
|
||||
|
||||
#endif /* __LWIPOPTS_H__ */
|
||||
325
tests/bouffalolab/inc/usb_config.h
Normal file
325
tests/bouffalolab/inc/usb_config.h
Normal file
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef CHERRYUSB_CONFIG_H
|
||||
#define CHERRYUSB_CONFIG_H
|
||||
|
||||
/* ================ USB common Configuration ================ */
|
||||
#include "bflb_core.h"
|
||||
|
||||
#ifdef __RTTHREAD__
|
||||
#include <rtthread.h>
|
||||
|
||||
#define CONFIG_USB_PRINTF(...) rt_kprintf(__VA_ARGS__)
|
||||
#else
|
||||
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USB_DBG_LEVEL
|
||||
#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
|
||||
#endif
|
||||
|
||||
/* Enable print with color */
|
||||
#define CONFIG_USB_PRINTF_COLOR_ENABLE
|
||||
|
||||
// #define CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
/* data align size when use dma or use dcache */
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
#define CONFIG_USB_ALIGN_SIZE 32 // 32 or 64
|
||||
#else
|
||||
#define CONFIG_USB_ALIGN_SIZE 4
|
||||
#endif
|
||||
|
||||
/* attribute data into no cache ram */
|
||||
#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable")))
|
||||
|
||||
/* use usb_memcpy default for high performance but cost more flash memory.
|
||||
* And, arm libc has a bug that memcpy() may cause data misalignment when the size is not a multiple of 4.
|
||||
*/
|
||||
// #define CONFIG_USB_MEMCPY_DISABLE
|
||||
|
||||
/* ================= USB Device Stack Configuration ================ */
|
||||
|
||||
/* Ep0 in and out transfer buffer */
|
||||
#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN
|
||||
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 512
|
||||
#endif
|
||||
|
||||
/* Send ep0 in data from user buffer instead of copying into ep0 reqdata
|
||||
* Please note that user buffer must be aligned with CONFIG_USB_ALIGN_SIZE
|
||||
*/
|
||||
// #define CONFIG_USBDEV_EP0_INDATA_NO_COPY
|
||||
|
||||
/* Check if the input descriptor is correct */
|
||||
// #define CONFIG_USBDEV_DESC_CHECK
|
||||
|
||||
/* Enable test mode */
|
||||
// #define CONFIG_USBDEV_TEST_MODE
|
||||
|
||||
/* enable advance desc register api */
|
||||
#define CONFIG_USBDEV_ADVANCE_DESC
|
||||
|
||||
/* move ep0 setup handler from isr to thread */
|
||||
// #define CONFIG_USBDEV_EP0_THREAD
|
||||
|
||||
#ifndef CONFIG_USBDEV_EP0_PRIO
|
||||
#define CONFIG_USBDEV_EP0_PRIO 4
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_EP0_STACKSIZE
|
||||
#define CONFIG_USBDEV_EP0_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_MAX_LUN
|
||||
#define CONFIG_USBDEV_MSC_MAX_LUN 1
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_MAX_BUFSIZE
|
||||
#define CONFIG_USBDEV_MSC_MAX_BUFSIZE 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
|
||||
|
||||
/* move msc read & write from isr to while(1), you should call usbd_msc_polling in while(1) */
|
||||
// #define CONFIG_USBDEV_MSC_POLLING
|
||||
|
||||
/* move msc read & write from isr to thread */
|
||||
// #define CONFIG_USBDEV_MSC_THREAD
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_PRIO
|
||||
#define CONFIG_USBDEV_MSC_PRIO 4
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_STACKSIZE
|
||||
#define CONFIG_USBDEV_MSC_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MTP_MAX_BUFSIZE
|
||||
#define CONFIG_USBDEV_MTP_MAX_BUFSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MTP_MAX_OBJECTS
|
||||
#define CONFIG_USBDEV_MTP_MAX_OBJECTS 256
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MTP_MAX_PATHNAME
|
||||
#define CONFIG_USBDEV_MTP_MAX_PATHNAME 256
|
||||
#endif
|
||||
|
||||
#define CONFIG_USBDEV_MTP_THREAD
|
||||
|
||||
#ifndef CONFIG_USBDEV_MTP_PRIO
|
||||
#define CONFIG_USBDEV_MTP_PRIO 4
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MTP_STACKSIZE
|
||||
#define CONFIG_USBDEV_MTP_STACKSIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
|
||||
#endif
|
||||
|
||||
/* rndis transfer buffer size, must be a multiple of (1536 + 44)*/
|
||||
#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID
|
||||
#define CONFIG_USBDEV_RNDIS_VENDOR_ID 0x0000ffff
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_VENDOR_DESC
|
||||
#define CONFIG_USBDEV_RNDIS_VENDOR_DESC "CherryUSB"
|
||||
#endif
|
||||
|
||||
#define CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
|
||||
/* ================ 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 8
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 2
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_HID_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
|
||||
#define CONFIG_USBHOST_DEV_NAMELEN 16
|
||||
|
||||
#ifndef CONFIG_USBHOST_PSC_PRIO
|
||||
#define CONFIG_USBHOST_PSC_PRIO 0
|
||||
#endif
|
||||
#ifndef CONFIG_USBHOST_PSC_STACKSIZE
|
||||
#define CONFIG_USBHOST_PSC_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
//#define CONFIG_USBHOST_GET_STRING_DESC
|
||||
|
||||
// #define CONFIG_USBHOST_MSOS_ENABLE
|
||||
#ifndef CONFIG_USBHOST_MSOS_VENDOR_CODE
|
||||
#define CONFIG_USBHOST_MSOS_VENDOR_CODE 0x00
|
||||
#endif
|
||||
|
||||
/* Ep0 max transfer buffer */
|
||||
#ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN
|
||||
#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 4096
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
#define CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
// #define CONFIG_USBHOST_BLUETOOTH_HCI_LOG
|
||||
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_TX_SIZE
|
||||
#define CONFIG_USBHOST_BLUETOOTH_TX_SIZE 2048
|
||||
#endif
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_RX_SIZE
|
||||
#define CONFIG_USBHOST_BLUETOOTH_RX_SIZE 2048
|
||||
#endif
|
||||
|
||||
/* ================ USB Device Port Configuration ================*/
|
||||
|
||||
#ifndef CONFIG_USBDEV_MAX_BUS
|
||||
#define CONFIG_USBDEV_MAX_BUS 1
|
||||
#endif
|
||||
|
||||
// #define CONFIG_USBDEV_SOF_ENABLE
|
||||
|
||||
/* ---------------- FSDEV Configuration ---------------- */
|
||||
//#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2 // maybe 1 or 2, many chips may have a difference
|
||||
|
||||
/* ---------------- DWC2 Configuration ---------------- */
|
||||
/* enable dwc2 buffer dma mode for device
|
||||
* in xxx32 chips, only pb14/pb15 can support dma mode, pa11/pa12 is not supported(only a few supports, but we ignore them)
|
||||
*/
|
||||
// #define CONFIG_USB_DWC2_DMA_ENABLE
|
||||
|
||||
/* ---------------- MUSB Configuration ---------------- */
|
||||
#define CONFIG_USB_MUSB_EP_NUM 8
|
||||
// #define CONFIG_USB_MUSB_SUNXI
|
||||
|
||||
/* ================ USB Host Port Configuration ==================*/
|
||||
#ifndef CONFIG_USBHOST_MAX_BUS
|
||||
#define CONFIG_USBHOST_MAX_BUS 1
|
||||
#endif
|
||||
|
||||
/* ---------------- EHCI Configuration ---------------- */
|
||||
|
||||
#define CONFIG_USB_EHCI_HCCR_OFFSET (0x0)
|
||||
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
|
||||
#define CONFIG_USB_EHCI_QH_NUM 10
|
||||
#define CONFIG_USB_EHCI_QTD_NUM (CONFIG_USB_EHCI_QH_NUM * 3)
|
||||
#define CONFIG_USB_EHCI_ITD_NUM 4
|
||||
#define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
|
||||
// #define CONFIG_USB_EHCI_CONFIGFLAG
|
||||
// #define CONFIG_USB_EHCI_ISO
|
||||
// #define CONFIG_USB_EHCI_WITH_OHCI
|
||||
// #define CONFIG_USB_EHCI_DESC_DCACHE_ENABLE
|
||||
|
||||
/* ---------------- OHCI Configuration ---------------- */
|
||||
#define CONFIG_USB_OHCI_HCOR_OFFSET (0x0)
|
||||
#define CONFIG_USB_OHCI_ED_NUM 10
|
||||
#define CONFIG_USB_OHCI_TD_NUM 3
|
||||
// #define CONFIG_USB_OHCI_DESC_DCACHE_ENABLE
|
||||
|
||||
/* ---------------- XHCI Configuration ---------------- */
|
||||
#define CONFIG_USB_XHCI_HCCR_OFFSET (0x0)
|
||||
|
||||
/* ---------------- DWC2 Configuration ---------------- */
|
||||
// nothing to define
|
||||
|
||||
/* ---------------- MUSB Configuration ---------------- */
|
||||
#define CONFIG_USB_MUSB_PIPE_NUM 8
|
||||
// #define CONFIG_USB_MUSB_SUNXI
|
||||
// #define CONFIG_USB_MUSB_WITHOUT_MULTIPOINT
|
||||
|
||||
/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode,
|
||||
* the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS.
|
||||
*
|
||||
* in xxx32 chips, only pb14/pb15 can support hs mode, pa11/pa12 is not supported(only a few supports, but we ignore them).
|
||||
*/
|
||||
// #define CONFIG_USB_HS
|
||||
|
||||
#ifndef usb_phyaddr2ramaddr
|
||||
#define usb_phyaddr2ramaddr(addr) (addr)
|
||||
#endif
|
||||
|
||||
#ifndef usb_ramaddr2phyaddr
|
||||
#define usb_ramaddr2phyaddr(addr) (addr)
|
||||
#endif
|
||||
|
||||
#define ATTR_FAST_RAM_SECTION ATTR_TCM_SECTION
|
||||
#define CONFIG_USB_HS
|
||||
|
||||
#endif
|
||||
16
tests/bouffalolab/proj.conf
Normal file
16
tests/bouffalolab/proj.conf
Normal file
@@ -0,0 +1,16 @@
|
||||
set(CONFIG_FREERTOS 1)
|
||||
|
||||
# do not use sdk cherryusb because its version is lower than master.
|
||||
|
||||
#set(CONFIG_CHERRYUSB 1)
|
||||
#set(CONFIG_CHERRYUSB_HOST 1)
|
||||
#set(CONFIG_CHERRYUSB_HOST_ECM 1)
|
||||
|
||||
set(CONFIG_PSRAM 1)
|
||||
set(CONFIG_FATFS 1)
|
||||
set(CONFIG_FATFS_USBH 1)
|
||||
|
||||
set(CONFIG_LWIP 1)
|
||||
set(CONFIG_PING 1)
|
||||
set(CONFIG_IPERF 1)
|
||||
set(CONFIG_SHELL 1)
|
||||
158
tests/bouffalolab/src/main.c
Normal file
158
tests/bouffalolab/src/main.c
Normal file
@@ -0,0 +1,158 @@
|
||||
#include <FreeRTOS.h>
|
||||
#include "semphr.h"
|
||||
#include "usbh_core.h"
|
||||
#include "bflb_uart.h"
|
||||
#include "board.h"
|
||||
#include "shell.h"
|
||||
#ifdef CONFIG_USB_EHCI_ISO
|
||||
#include "usbh_uvc_stream.h"
|
||||
#include "usbh_uac_stream.h"
|
||||
#endif
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
static struct bflb_device_s *uart0;
|
||||
|
||||
extern void shell_init_with_task(struct bflb_device_s *shell);
|
||||
|
||||
#ifdef CONFIG_USB_EHCI_ISO
|
||||
static ATTR_NOINIT_PSRAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer1[640 * 480 * 2];
|
||||
static ATTR_NOINIT_PSRAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer2[640 * 480 * 2];
|
||||
static struct usbh_videoframe frame_pool[2];
|
||||
|
||||
static ATTR_NOINIT_PSRAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer[AUDIO_MIC_EP_MPS * 8];
|
||||
static struct usbh_audioframe frame_pool2[8];
|
||||
|
||||
void usbh_video_run(struct usbh_video *video_class)
|
||||
{
|
||||
usbh_video_stream_start(640, 480, USBH_VIDEO_FORMAT_MJPEG);
|
||||
}
|
||||
|
||||
void usbh_video_stop(struct usbh_video *video_class)
|
||||
{
|
||||
usbh_video_stream_stop();
|
||||
}
|
||||
|
||||
void usbh_video_frame_callback(struct usbh_videoframe *frame)
|
||||
{
|
||||
USB_LOG_RAW("frame buf:%p,frame len:%d\r\n", frame->frame_buf, frame->frame_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
|
||||
uart0 = bflb_device_get_by_name("uart0");
|
||||
shell_init_with_task(uart0);
|
||||
|
||||
/* Initialize the LwIP stack */
|
||||
tcpip_init(NULL, NULL);
|
||||
|
||||
printf("Starting usb host task...\r\n");
|
||||
#ifdef CONFIG_USB_EHCI_ISO
|
||||
extern void usbh_video_fps_init(void);
|
||||
usbh_video_fps_init();
|
||||
frame_pool[0].frame_buf = frame_buffer1;
|
||||
frame_pool[0].frame_bufsize = 640 * 480 * 2;
|
||||
frame_pool[1].frame_buf = frame_buffer2;
|
||||
frame_pool[1].frame_bufsize = 640 * 480 * 2;
|
||||
|
||||
usbh_video_stream_init(5, frame_pool, 2);
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
frame_pool2[i].frame_buf = frame_buffer + i * AUDIO_MIC_EP_MPS;
|
||||
frame_pool2[i].frame_bufsize = AUDIO_MIC_EP_MPS;
|
||||
}
|
||||
|
||||
usbh_audio_mic_stream_init(5, frame_pool2, 8);
|
||||
#endif
|
||||
vTaskStartScheduler();
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
int usbh_deinit(int argc, char **argv)
|
||||
{
|
||||
printf("usbh_deinit\r\n");
|
||||
usbh_deinitialize(0);
|
||||
return 0;
|
||||
}
|
||||
SHELL_CMD_EXPORT_ALIAS(usbh_deinit, usbh_deinit, usbh deinit);
|
||||
|
||||
int usbh_init(int argc, char **argv)
|
||||
{
|
||||
printf("usbh_init\r\n");
|
||||
usbh_initialize(0, 0x20072000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_CMD_EXPORT_ALIAS(usbh_init, usbh_init, usbh init);
|
||||
|
||||
SHELL_CMD_EXPORT_ALIAS(lsusb, lsusb, ls usb);
|
||||
|
||||
// int uvcinit(int argc, char **argv)
|
||||
// {
|
||||
// video_init(0, 0x20072000);
|
||||
// return 0;
|
||||
// }
|
||||
// SHELL_CMD_EXPORT_ALIAS(uvcinit, uvcinit, usbh init);
|
||||
|
||||
// int uvcsend(int argc, char **argv)
|
||||
// {
|
||||
// extern void video_test(uint8_t busid);
|
||||
// video_test(0);
|
||||
// return 0;
|
||||
// }
|
||||
// SHELL_CMD_EXPORT_ALIAS(uvcsend, uvcsend, usbh init);
|
||||
|
||||
#ifdef CONFIG_USB_EHCI_ISO
|
||||
int usbh_uvc_start(int argc, char **argv)
|
||||
{
|
||||
uint8_t type;
|
||||
|
||||
if (argc < 2) {
|
||||
USB_LOG_ERR("please input correct command: usbh_uvc_start type\r\n");
|
||||
USB_LOG_ERR("type 0:yuyv, type 1:mjpeg\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
type = atoi(argv[1]);
|
||||
usbh_video_stream_start(640, 480, type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_CMD_EXPORT_ALIAS(usbh_uvc_start, usbh_uvc_start, usbh_uvc_start);
|
||||
|
||||
int usbh_uvc_stop(int argc, char **argv)
|
||||
{
|
||||
usbh_video_stream_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_CMD_EXPORT_ALIAS(usbh_uvc_stop, usbh_uvc_stop, usbh_uvc_stop);
|
||||
|
||||
int usbh_uac_start(int argc, char **argv)
|
||||
{
|
||||
uint32_t freq;
|
||||
|
||||
if (argc < 2) {
|
||||
USB_LOG_ERR("please input correct command: usbh_uac_start freq\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
freq = atoi(argv[1]);
|
||||
usbh_audio_mic_stream_start(freq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_CMD_EXPORT_ALIAS(usbh_uac_start, usbh_uac_start, usbh_uac_start);
|
||||
|
||||
int usbh_uac_stop(int argc, char **argv)
|
||||
{
|
||||
usbh_audio_mic_stream_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_CMD_EXPORT_ALIAS(usbh_uac_stop, usbh_uac_stop, usbh_uac_stop);
|
||||
#endif
|
||||
9
tests/espressif/device/CMakeLists.txt
Normal file
9
tests/espressif/device/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "../../../../CherryUSB")
|
||||
|
||||
project(cherryusb)
|
||||
4
tests/espressif/device/main/CMakeLists.txt
Normal file
4
tests/espressif/device/main/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS "."
|
||||
WHOLE_ARCHIVE)
|
||||
27
tests/espressif/device/main/main.c
Normal file
27
tests/espressif/device/main/main.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "usbd_core.h"
|
||||
#include "usbh_core.h"
|
||||
#include "demo/cdc_acm_msc_template.c"
|
||||
|
||||
extern void cdc_acm_msc_init(uint8_t busid, uintptr_t reg_base);
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
USB_LOG_INFO("Hello CherryUSB!\n");
|
||||
|
||||
cdc_acm_msc_init(0, 0x60080000);
|
||||
while(1)
|
||||
{
|
||||
vTaskDelay(10);
|
||||
}
|
||||
}
|
||||
7
tests/espressif/device/sdkconfig.defaults
Normal file
7
tests/espressif/device/sdkconfig.defaults
Normal file
@@ -0,0 +1,7 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
#
|
||||
CONFIG_CHERRYUSB=y
|
||||
CONFIG_CHERRYUSB_DEVICE=y
|
||||
CONFIG_CHERRYUSB_DEVICE_CDC_ACM=y
|
||||
CONFIG_CHERRYUSB_DEVICE_HID=y
|
||||
CONFIG_CHERRYUSB_DEVICE_MSC=y
|
||||
9
tests/espressif/host/CMakeLists.txt
Normal file
9
tests/espressif/host/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "../../../../CherryUSB")
|
||||
|
||||
project(cherryusb)
|
||||
4
tests/espressif/host/main/CMakeLists.txt
Normal file
4
tests/espressif/host/main/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS "."
|
||||
WHOLE_ARCHIVE)
|
||||
33
tests/espressif/host/main/main.c
Normal file
33
tests/espressif/host/main/main.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "usbd_core.h"
|
||||
#include "usbh_core.h"
|
||||
#include "demo/usb_host.c"
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
USB_LOG_INFO("Hello CherryUSB!\n");
|
||||
|
||||
// Initialize TCP/IP network interface aka the esp-netif (should be called only once in application)
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
// Create default event loop that running in background
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
usbh_initialize(0, 0x60080000);
|
||||
while(1)
|
||||
{
|
||||
vTaskDelay(10);
|
||||
}
|
||||
}
|
||||
19
tests/espressif/host/sdkconfig.defaults
Normal file
19
tests/espressif/host/sdkconfig.defaults
Normal file
@@ -0,0 +1,19 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
#
|
||||
CONFIG_CHERRYUSB=y
|
||||
CONFIG_CHERRYUSB_HOST=y
|
||||
CONFIG_CHERRYUSB_HOST_CUSTOM=y
|
||||
CONFIG_CHERRYUSB_HOST_CDC_ACM=y
|
||||
CONFIG_CHERRYUSB_HOST_HID=y
|
||||
CONFIG_CHERRYUSB_HOST_MSC=y
|
||||
CONFIG_CHERRYUSB_HOST_CDC_ECM=y
|
||||
CONFIG_CHERRYUSB_HOST_CDC_NCM=y
|
||||
CONFIG_CHERRYUSB_HOST_CDC_RNDIS=y
|
||||
CONFIG_CHERRYUSB_HOST_ASIX=y
|
||||
CONFIG_CHERRYUSB_HOST_RTL8152=y
|
||||
CONFIG_CHERRYUSB_HOST_CH34X=y
|
||||
CONFIG_CHERRYUSB_HOST_CP210X=y
|
||||
CONFIG_CHERRYUSB_HOST_FTDI=y
|
||||
CONFIG_CHERRYUSB_HOST_PL2303=y
|
||||
CONFIG_CHERRYUSB_HOST_VIDEO=y
|
||||
CONFIG_CHERRYUSB_HOST_AUDIO=y
|
||||
57
tests/hpmicro/CMakeLists.txt
Normal file
57
tests/hpmicro/CMakeLists.txt
Normal file
@@ -0,0 +1,57 @@
|
||||
# Copyright (c) 2021 HPMicro
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(CONFIG_CHERRYSH 1)
|
||||
set(CONFIG_CHERRYSH_INTERFACE "uart")
|
||||
set(CONFIG_USB_DEVICE 1)
|
||||
|
||||
set(CONFIG_FREERTOS 1)
|
||||
set(CONFIG_LWIP 1)
|
||||
set(CONFIG_LWIP_IPERF 1)
|
||||
set(CONFIG_LWIP_STRERR 1)
|
||||
set(CONFIG_LWIP_NETDB 1)
|
||||
set(CONFIG_LWIP_SOCKET_API 1)
|
||||
|
||||
set(CONFIG_HPM_PANEL 1)
|
||||
|
||||
find_package(hpm-sdk REQUIRED HINTS $ENV{HPM_SDK_BASE})
|
||||
project(cherryusb)
|
||||
|
||||
sdk_compile_definitions(-D__freertos_irq_stack_top=_stack)
|
||||
sdk_compile_definitions(-DCONFIG_FREERTOS=1)
|
||||
sdk_compile_definitions(-DUSE_NONVECTOR_MODE=1)
|
||||
sdk_compile_definitions(-DDISABLE_IRQ_PREEMPTIVE=1)
|
||||
sdk_compile_definitions(-DLWIP_TIMEVAL_PRIVATE=0)
|
||||
|
||||
sdk_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_ECM)
|
||||
sdk_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_NCM)
|
||||
sdk_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_RNDIS)
|
||||
sdk_compile_definitions(-DCONFIG_USBHOST_PLATFORM_ASIX)
|
||||
sdk_compile_definitions(-DCONFIG_USBHOST_PLATFORM_RTL8152)
|
||||
|
||||
# sdk_compile_definitions(-DCONFIG_USB_OTG_ENABLE)
|
||||
|
||||
sdk_compile_options("-O2")
|
||||
|
||||
sdk_inc(inc)
|
||||
sdk_app_src(inc/arch/sys_arch.c)
|
||||
sdk_app_src(src/main.c)
|
||||
sdk_app_src(../../demo/usb_host.c)
|
||||
|
||||
sdk_inc(src/iperf)
|
||||
sdk_app_src(src/iperf/iperf.c src/iperf/iperf_cli.c src/iperf/utils_getopt.c src/ping.c)
|
||||
sdk_app_src(src/cdc_acm_otg_template.c)
|
||||
|
||||
set(CONFIG_CHERRYMP 1)
|
||||
set(CONFIG_CHERRYUSB 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE 1)
|
||||
set(CONFIG_CHERRYUSB_HOST 1)
|
||||
|
||||
# sdk_app_src(src/uvc2lcd.c)
|
||||
# sdk_app_src(src/font24x48.c)
|
||||
# add_subdirectory(src/cherryusb_hostuvcuac)
|
||||
add_subdirectory(../.. cherryusb)
|
||||
|
||||
generate_ses_project()
|
||||
162
tests/hpmicro/inc/FreeRTOSConfig.h
Normal file
162
tests/hpmicro/inc/FreeRTOSConfig.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2022 HPMicro
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#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 "board.h"
|
||||
#if (portasmHAS_MTIME == 0)
|
||||
#define configMTIME_BASE_ADDRESS (0)
|
||||
#define configMTIMECMP_BASE_ADDRESS (0)
|
||||
#else
|
||||
#define configMTIME_BASE_ADDRESS (HPM_MCHTMR_BASE)
|
||||
#define configMTIMECMP_BASE_ADDRESS (HPM_MCHTMR_BASE + 8UL)
|
||||
#endif
|
||||
|
||||
/* When USE_SYSCALL_INTERRUPT_PRIORITY is set, interrupts whose priority is higher than configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
will not be delayed by anything FreeRTOS do. */
|
||||
#if defined (USE_SYSCALL_INTERRUPT_PRIORITY) && USE_SYSCALL_INTERRUPT_PRIORITY
|
||||
#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configCPU_CLOCK_HZ ((uint32_t) 24000000)
|
||||
#define configTICK_RATE_HZ ((TickType_t) 1000)
|
||||
#define configMAX_PRIORITIES (32)
|
||||
#define configMINIMAL_STACK_SIZE (256)
|
||||
#define configMAX_TASK_NAME_LEN 16
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configIDLE_SHOULD_YIELD 0
|
||||
#define configUSE_APPLICATION_TASK_TAG 0
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configUSE_MUTEXES 1
|
||||
|
||||
/* Memory allocation definitions. */
|
||||
#define configSUPPORT_STATIC_ALLOCATION 1
|
||||
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||
#ifndef configTOTAL_HEAP_SIZE
|
||||
#define configTOTAL_HEAP_SIZE ((size_t) (64 * 1024))
|
||||
#endif
|
||||
|
||||
/* Hook function definitions. */
|
||||
#define configUSE_IDLE_HOOK 0
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 0
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_MALLOC_FAILED_HOOK 0
|
||||
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
|
||||
|
||||
/* Run time and task stats gathering definitions. */
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
#define configUSE_TRACE_FACILITY 1
|
||||
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
|
||||
|
||||
/* 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_xTaskGetCurrentTaskHandle 1
|
||||
#define INCLUDE_xTimerPendFunctionCall 1
|
||||
#define INCLUDE_eTaskGetState 1
|
||||
#define INCLUDE_xTaskAbortDelay 1
|
||||
#define INCLUDE_xTaskGetHandle 1
|
||||
#define INCLUDE_xSemaphoreGetMutexHolder 1
|
||||
|
||||
/* 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.*/
|
||||
#ifndef uartPRIMARY_PRIORITY
|
||||
#define uartPRIMARY_PRIORITY (configMAX_PRIORITIES - 3)
|
||||
#endif
|
||||
|
||||
/* Normal assert() semantics without relying on the provision of an assert.h header file. */
|
||||
#define configASSERT(x) if ((x) == 0) { taskDISABLE_INTERRUPTS(); __asm volatile("ebreak"); for (;;); }
|
||||
|
||||
/*
|
||||
* The size of the global output buffer that is available for use when there
|
||||
* are multiple command interpreters running at once (for example, one on a UART
|
||||
* and one on TCP/IP). This is done to prevent an output buffer being defined by
|
||||
* each implementation - which would waste RAM. In this case, there is only one
|
||||
* command interpreter running.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The buffer into which output generated by FreeRTOS+CLI is placed. This must
|
||||
* be at least big enough to contain the output of the task-stats command, as the
|
||||
* example implementation does not include buffer overlow checking.
|
||||
*/
|
||||
#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096
|
||||
#define configINCLUDE_QUERY_HEAP_COMMAND 1
|
||||
|
||||
/* This file is included from assembler files - make sure C code is not included in assembler files. */
|
||||
#ifndef __ASSEMBLER__
|
||||
void vAssertCalled(const char *pcFile, unsigned long ulLine);
|
||||
void vConfigureTickInterrupt(void);
|
||||
void vClearTickInterrupt(void);
|
||||
void vPreSleepProcessing(unsigned long uxExpectedIdleTime);
|
||||
void vPostSleepProcessing(unsigned long uxExpectedIdleTime);
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
/****** Hardware/compiler specific settings. *******/
|
||||
/*
|
||||
* The application must provide a function that configures a peripheral to
|
||||
* create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT()
|
||||
* in FreeRTOSConfig.h to call the function.
|
||||
*/
|
||||
#define configSETUP_TICK_INTERRUPT() vConfigureTickInterrupt()
|
||||
#define configCLEAR_TICK_INTERRUPT() vClearTickInterrupt()
|
||||
|
||||
/*
|
||||
* The configPRE_SLEEP_PROCESSING() and configPOST_SLEEP_PROCESSING() macros
|
||||
* allow the application writer to add additional code before and after the MCU is
|
||||
* placed into the low power state respectively. The empty implementations
|
||||
* provided in this demo can be extended to save even more power.
|
||||
*/
|
||||
#define configPRE_SLEEP_PROCESSING(uxExpectedIdleTime) vPreSleepProcessing(uxExpectedIdleTime);
|
||||
#define configPOST_SLEEP_PROCESSING(uxExpectedIdleTime) vPostSleepProcessing(uxExpectedIdleTime);
|
||||
|
||||
|
||||
/* Compiler specifics. */
|
||||
#define fabs(x) __builtin_fabs(x)
|
||||
|
||||
/* Enable Hardware Stack Protection and Recording mechanism. */
|
||||
#define configHSP_ENABLE 0
|
||||
|
||||
/* Record the highest address of stack. */
|
||||
#if (configHSP_ENABLE == 1 && configRECORD_STACK_HIGH_ADDRESS != 1)
|
||||
#define configRECORD_STACK_HIGH_ADDRESS 1
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
99
tests/hpmicro/inc/arch/cc.h
Normal file
99
tests/hpmicro/inc/arch/cc.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021-2024 HPMicro
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CC_H__
|
||||
#define __CC_H__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define U16_F "hu"
|
||||
#define S16_F "d"
|
||||
#define X16_F "hx"
|
||||
#define U32_F "u"
|
||||
#define S32_F "d"
|
||||
#define X32_F "x"
|
||||
#define SZT_F "uz"
|
||||
|
||||
/* define compiler specific symbols */
|
||||
#if defined (__ICCARM__)
|
||||
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_STRUCT
|
||||
#define PACK_STRUCT_END
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
#define PACK_STRUCT_USE_INCLUDES
|
||||
|
||||
#elif defined (__CC_ARM)
|
||||
|
||||
#define PACK_STRUCT_BEGIN __packed
|
||||
#define PACK_STRUCT_STRUCT
|
||||
#define PACK_STRUCT_END
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
|
||||
#elif defined (__GNUC__)
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
|
||||
#define PACK_STRUCT_END
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
|
||||
#elif defined(__ICCRISCV__)
|
||||
|
||||
#include <time.h>
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
|
||||
#define PACK_STRUCT_END
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
typedef unsigned long clockid_t;
|
||||
|
||||
#elif defined (__TASKING__)
|
||||
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_STRUCT
|
||||
#define PACK_STRUCT_END
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
|
||||
#endif
|
||||
|
||||
#define LWIP_PLATFORM_ASSERT(x) printf(x)
|
||||
|
||||
#endif /* __CC_H__ */
|
||||
618
tests/hpmicro/inc/arch/sys_arch.c
Normal file
618
tests/hpmicro/inc/arch/sys_arch.c
Normal file
@@ -0,0 +1,618 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Simon Goldschmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Simon Goldschmidt <goldsimon@gmx.de>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021-2022 HPMicro
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
/* lwIP includes. */
|
||||
#include "lwip/debug.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#if !NO_SYS
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#endif
|
||||
|
||||
#if !NO_SYS
|
||||
#include "sys_arch.h"
|
||||
#endif
|
||||
|
||||
int errno;
|
||||
#if !NO_SYS
|
||||
/** Set this to 1 if you want the stack size passed to sys_thread_new() to be
|
||||
* interpreted as number of stack words (FreeRTOS-like).
|
||||
* Default is that they are interpreted as byte count (lwIP-like).
|
||||
*/
|
||||
#ifndef LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS
|
||||
#define LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS 0
|
||||
#endif
|
||||
|
||||
/** Set this to 1 to use a mutex for SYS_ARCH_PROTECT() critical regions.
|
||||
* Default is 0 and locks interrupts/scheduler for SYS_ARCH_PROTECT().
|
||||
*/
|
||||
#ifndef LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
|
||||
#define LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX 0
|
||||
#endif
|
||||
|
||||
/** Set this to 1 to include a sanity check that SYS_ARCH_PROTECT() and
|
||||
* SYS_ARCH_UNPROTECT() are called matching.
|
||||
*/
|
||||
#ifndef LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
|
||||
#define LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK 0
|
||||
#endif
|
||||
|
||||
/** Set this to 1 to let sys_mbox_free check that queues are empty when freed */
|
||||
#ifndef LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE
|
||||
#define LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE 0
|
||||
#endif
|
||||
|
||||
/** Set this to 1 to enable core locking check functions in this port.
|
||||
* For this to work, you'll have to define LWIP_ASSERT_CORE_LOCKED()
|
||||
* and LWIP_MARK_TCPIP_THREAD() correctly in your lwipopts.h! */
|
||||
#ifndef LWIP_FREERTOS_CHECK_CORE_LOCKING
|
||||
#define LWIP_FREERTOS_CHECK_CORE_LOCKING 1
|
||||
#endif
|
||||
|
||||
/** Set this to 0 to implement sys_now() yourself, e.g. using a hw timer.
|
||||
* Default is 1, where FreeRTOS ticks are used to calculate back to ms.
|
||||
*/
|
||||
#ifndef LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS
|
||||
#define LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS 1
|
||||
#endif
|
||||
|
||||
#if !configSUPPORT_DYNAMIC_ALLOCATION
|
||||
# error "lwIP FreeRTOS port requires configSUPPORT_DYNAMIC_ALLOCATION"
|
||||
#endif
|
||||
#if !INCLUDE_vTaskDelay
|
||||
# error "lwIP FreeRTOS port requires INCLUDE_vTaskDelay"
|
||||
#endif
|
||||
#if !INCLUDE_vTaskSuspend
|
||||
# error "lwIP FreeRTOS port requires INCLUDE_vTaskSuspend"
|
||||
#endif
|
||||
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX || !LWIP_COMPAT_MUTEX
|
||||
#if !configUSE_MUTEXES
|
||||
# error "lwIP FreeRTOS port requires configUSE_MUTEXES"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
|
||||
static SemaphoreHandle_t sys_arch_protect_mutex;
|
||||
#endif
|
||||
#if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
|
||||
static sys_prot_t sys_arch_protect_nesting;
|
||||
#endif
|
||||
|
||||
/* Initialize this module (see description in sys.h) */
|
||||
void
|
||||
sys_init(void)
|
||||
{
|
||||
#if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
|
||||
/* initialize sys_arch_protect global mutex */
|
||||
sys_arch_protect_mutex = xSemaphoreCreateRecursiveMutex();
|
||||
LWIP_ASSERT("failed to create sys_arch_protect mutex",
|
||||
sys_arch_protect_mutex != NULL);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
|
||||
}
|
||||
|
||||
#if configUSE_16_BIT_TICKS == 1
|
||||
#error This port requires 32 bit ticks or timer overflow will fail
|
||||
#endif
|
||||
|
||||
#if LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS
|
||||
u32_t sys_now(void)
|
||||
{
|
||||
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
||||
}
|
||||
#else
|
||||
u32_t sys_now(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
u32_t sys_jiffies(void)
|
||||
{
|
||||
return xTaskGetTickCount();
|
||||
}
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
|
||||
sys_prot_t sys_arch_protect(void)
|
||||
{
|
||||
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
|
||||
BaseType_t ret;
|
||||
LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL);
|
||||
|
||||
ret = xSemaphoreTakeRecursive(sys_arch_protect_mutex, portMAX_DELAY);
|
||||
LWIP_ASSERT("sys_arch_protect failed to take the mutex", ret == pdTRUE);
|
||||
#else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
|
||||
taskENTER_CRITICAL();
|
||||
#endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
|
||||
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
|
||||
{
|
||||
/* every nested call to sys_arch_protect() returns an increased number */
|
||||
sys_prot_t ret = sys_arch_protect_nesting;
|
||||
sys_arch_protect_nesting++;
|
||||
LWIP_ASSERT("sys_arch_protect overflow", sys_arch_protect_nesting > ret);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void sys_arch_unprotect(sys_prot_t pval)
|
||||
{
|
||||
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
|
||||
BaseType_t ret;
|
||||
#endif
|
||||
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
|
||||
LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting > 0);
|
||||
sys_arch_protect_nesting--;
|
||||
LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting == pval);
|
||||
#endif
|
||||
|
||||
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
|
||||
LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL);
|
||||
|
||||
ret = xSemaphoreGiveRecursive(sys_arch_protect_mutex);
|
||||
LWIP_ASSERT("sys_arch_unprotect failed to give the mutex", ret == pdTRUE);
|
||||
#else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
|
||||
taskEXIT_CRITICAL();
|
||||
#endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
|
||||
LWIP_UNUSED_ARG(pval);
|
||||
}
|
||||
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
void sys_arch_msleep(u32_t delay_ms)
|
||||
{
|
||||
TickType_t delay_ticks = delay_ms / portTICK_RATE_MS;
|
||||
vTaskDelay(delay_ticks);
|
||||
}
|
||||
|
||||
#if !LWIP_COMPAT_MUTEX
|
||||
|
||||
/* Create a new mutex*/
|
||||
err_t sys_mutex_new(sys_mutex_t *mutex)
|
||||
{
|
||||
LWIP_ASSERT("mutex != NULL", mutex != NULL);
|
||||
|
||||
mutex->mut = xSemaphoreCreateRecursiveMutex();
|
||||
if (mutex->mut == NULL) {
|
||||
SYS_STATS_INC(mutex.err);
|
||||
return ERR_MEM;
|
||||
}
|
||||
SYS_STATS_INC_USED(mutex);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void sys_mutex_lock(sys_mutex_t *mutex)
|
||||
{
|
||||
BaseType_t ret;
|
||||
LWIP_ASSERT("mutex != NULL", mutex != NULL);
|
||||
LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); /* NOLINT */
|
||||
|
||||
ret = xSemaphoreTakeRecursive(mutex->mut, portMAX_DELAY);
|
||||
LWIP_ASSERT("failed to take the mutex", ret == pdTRUE);
|
||||
}
|
||||
|
||||
void sys_mutex_unlock(sys_mutex_t *mutex)
|
||||
{
|
||||
BaseType_t ret;
|
||||
LWIP_ASSERT("mutex != NULL", mutex != NULL);
|
||||
LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); /* NOLINT */
|
||||
|
||||
ret = xSemaphoreGiveRecursive(mutex->mut);
|
||||
LWIP_ASSERT("failed to give the mutex", ret == pdTRUE);
|
||||
}
|
||||
|
||||
void sys_mutex_free(sys_mutex_t *mutex)
|
||||
{
|
||||
LWIP_ASSERT("mutex != NULL", mutex != NULL);
|
||||
LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); /* NOLINT */
|
||||
|
||||
SYS_STATS_DEC(mutex.used);
|
||||
vSemaphoreDelete(mutex->mut);
|
||||
mutex->mut = NULL;
|
||||
}
|
||||
|
||||
#endif /* !LWIP_COMPAT_MUTEX */
|
||||
|
||||
err_t sys_sem_new(sys_sem_t *sem, u8_t initial_count)
|
||||
{
|
||||
LWIP_ASSERT("sem != NULL", sem != NULL);
|
||||
LWIP_ASSERT("initial_count invalid (not 0 or 1)",
|
||||
(initial_count == 0) || (initial_count == 1));
|
||||
|
||||
sem->sem = xSemaphoreCreateBinary();
|
||||
if (sem->sem == NULL) {
|
||||
SYS_STATS_INC(sem.err);
|
||||
return ERR_MEM;
|
||||
}
|
||||
SYS_STATS_INC_USED(sem);
|
||||
|
||||
if (initial_count == 1) {
|
||||
BaseType_t ret = xSemaphoreGive(sem->sem);
|
||||
LWIP_ASSERT("sys_sem_new: initial give failed", ret == pdTRUE);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void sys_sem_signal(sys_sem_t *sem)
|
||||
{
|
||||
BaseType_t ret;
|
||||
LWIP_ASSERT("sem != NULL", sem != NULL);
|
||||
LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); /* NOLINT */
|
||||
|
||||
ret = xSemaphoreGive(sem->sem);
|
||||
/* queue full is OK, this is a signal only... */
|
||||
LWIP_ASSERT("sys_sem_signal: sane return value",
|
||||
(ret == pdTRUE) || (ret == errQUEUE_FULL));
|
||||
}
|
||||
|
||||
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout_ms)
|
||||
{
|
||||
BaseType_t ret;
|
||||
LWIP_ASSERT("sem != NULL", sem != NULL);
|
||||
LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); /* NOLINT */
|
||||
|
||||
if (!timeout_ms) {
|
||||
/* wait infinite */
|
||||
ret = xSemaphoreTake(sem->sem, portMAX_DELAY);
|
||||
LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
|
||||
} else {
|
||||
TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS;
|
||||
ret = xSemaphoreTake(sem->sem, timeout_ticks);
|
||||
if (ret == errQUEUE_EMPTY) {
|
||||
/* timed out */
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
|
||||
}
|
||||
|
||||
/* Old versions of lwIP required us to return the time waited.
|
||||
This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
|
||||
here is enough. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sys_sem_free(sys_sem_t *sem)
|
||||
{
|
||||
LWIP_ASSERT("sem != NULL", sem != NULL);
|
||||
LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); /* NOLINT */
|
||||
|
||||
SYS_STATS_DEC(sem.used);
|
||||
vSemaphoreDelete(sem->sem);
|
||||
sem->sem = NULL;
|
||||
}
|
||||
|
||||
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
|
||||
{
|
||||
LWIP_ASSERT("mbox != NULL", mbox != NULL); /* NOLINT */
|
||||
LWIP_ASSERT("size > 0", size > 0);
|
||||
|
||||
mbox->mbx = xQueueCreate((UBaseType_t)size, sizeof(void *));
|
||||
if (mbox->mbx == NULL) {
|
||||
SYS_STATS_INC(mbox.err);
|
||||
return ERR_MEM;
|
||||
}
|
||||
SYS_STATS_INC_USED(mbox);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void sys_mbox_post(sys_mbox_t *mbox, void *msg)
|
||||
{
|
||||
BaseType_t ret;
|
||||
LWIP_ASSERT("mbox != NULL", mbox != NULL);
|
||||
LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
|
||||
|
||||
ret = xQueueSendToBack(mbox->mbx, &msg, portMAX_DELAY);
|
||||
LWIP_ASSERT("mbox post failed", ret == pdTRUE);
|
||||
}
|
||||
|
||||
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
|
||||
{
|
||||
BaseType_t ret;
|
||||
LWIP_ASSERT("mbox != NULL", mbox != NULL);
|
||||
LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
|
||||
|
||||
ret = xQueueSendToBack(mbox->mbx, &msg, 0);
|
||||
if (ret == pdTRUE) {
|
||||
return ERR_OK;
|
||||
} else {
|
||||
LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
|
||||
SYS_STATS_INC(mbox.err);
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg)
|
||||
{
|
||||
BaseType_t ret;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
LWIP_ASSERT("mbox != NULL", mbox != NULL);
|
||||
LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
|
||||
|
||||
ret = xQueueSendToBackFromISR(mbox->mbx, &msg, &xHigherPriorityTaskWoken);
|
||||
if (ret == pdTRUE) {
|
||||
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||
return ERR_NEED_SCHED;
|
||||
}
|
||||
return ERR_OK;
|
||||
} else {
|
||||
LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
|
||||
SYS_STATS_INC(mbox.err);
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout_ms)
|
||||
{
|
||||
BaseType_t ret;
|
||||
void *msg_dummy;
|
||||
LWIP_ASSERT("mbox != NULL", mbox != NULL);
|
||||
LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
|
||||
|
||||
if (!msg) {
|
||||
msg = &msg_dummy;
|
||||
}
|
||||
|
||||
if (!timeout_ms) {
|
||||
/* wait infinite */
|
||||
ret = xQueueReceive(mbox->mbx, &(*msg), portMAX_DELAY);
|
||||
LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
|
||||
} else {
|
||||
TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS;
|
||||
ret = xQueueReceive(mbox->mbx, &(*msg), timeout_ticks);
|
||||
if (ret == errQUEUE_EMPTY) {
|
||||
/* timed out */
|
||||
*msg = NULL;
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
|
||||
}
|
||||
|
||||
/* Old versions of lwIP required us to return the time waited.
|
||||
This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
|
||||
here is enough. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
|
||||
{
|
||||
BaseType_t ret;
|
||||
void *msg_dummy;
|
||||
LWIP_ASSERT("mbox != NULL", mbox != NULL);
|
||||
LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
|
||||
|
||||
if (!msg) {
|
||||
msg = &msg_dummy;
|
||||
}
|
||||
|
||||
ret = xQueueReceive(mbox->mbx, &(*msg), 0);
|
||||
if (ret == errQUEUE_EMPTY) {
|
||||
*msg = NULL;
|
||||
return SYS_MBOX_EMPTY;
|
||||
}
|
||||
LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
|
||||
|
||||
/* Old versions of lwIP required us to return the time waited.
|
||||
This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
|
||||
here is enough. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sys_mbox_free(sys_mbox_t *mbox)
|
||||
{
|
||||
LWIP_ASSERT("mbox != NULL", mbox != NULL);
|
||||
LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
|
||||
|
||||
#if LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE
|
||||
{
|
||||
UBaseType_t msgs_waiting = uxQueueMessagesWaiting(mbox->mbx);
|
||||
LWIP_ASSERT("mbox quence not empty", msgs_waiting == 0);
|
||||
|
||||
if (msgs_waiting != 0) {
|
||||
SYS_STATS_INC(mbox.err);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vQueueDelete(mbox->mbx);
|
||||
|
||||
SYS_STATS_DEC(mbox.used);
|
||||
}
|
||||
|
||||
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
|
||||
{
|
||||
TaskHandle_t rtos_task;
|
||||
BaseType_t ret;
|
||||
sys_thread_t lwip_thread;
|
||||
size_t rtos_stacksize;
|
||||
|
||||
LWIP_ASSERT("invalid stacksize", stacksize > 0);
|
||||
#if LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS
|
||||
rtos_stacksize = (size_t)stacksize;
|
||||
#else
|
||||
rtos_stacksize = (size_t)stacksize / sizeof(StackType_t);
|
||||
#endif
|
||||
|
||||
/* lwIP's lwip_thread_fn matches FreeRTOS' TaskFunction_t, so we can pass the
|
||||
thread function without adaption here. */
|
||||
ret = xTaskCreate(thread, name, (configSTACK_DEPTH_TYPE)rtos_stacksize, arg, prio, &rtos_task);
|
||||
LWIP_ASSERT("task creation failed", ret == pdTRUE);
|
||||
|
||||
lwip_thread.thread_handle = rtos_task;
|
||||
return lwip_thread;
|
||||
}
|
||||
|
||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
||||
#if configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0
|
||||
|
||||
sys_sem_t *sys_arch_netconn_sem_get(void)
|
||||
{
|
||||
void *ret;
|
||||
TaskHandle_t task = xTaskGetCurrentTaskHandle();
|
||||
LWIP_ASSERT("task != NULL", task != NULL);
|
||||
|
||||
ret = pvTaskGetThreadLocalStoragePointer(task, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sys_arch_netconn_sem_alloc(void)
|
||||
{
|
||||
void *ret;
|
||||
TaskHandle_t task = xTaskGetCurrentTaskHandle();
|
||||
LWIP_ASSERT("task != NULL", task != NULL);
|
||||
|
||||
ret = pvTaskGetThreadLocalStoragePointer(task, 0);
|
||||
if (ret == NULL) {
|
||||
sys_sem_t *sem;
|
||||
err_t err;
|
||||
/* need to allocate the memory for this semaphore */
|
||||
sem = mem_malloc(sizeof(sys_sem_t));
|
||||
LWIP_ASSERT("sem != NULL", sem != NULL);
|
||||
err = sys_sem_new(sem, 0);
|
||||
LWIP_ASSERT("err == ERR_OK", err == ERR_OK);
|
||||
LWIP_ASSERT("sem invalid", sys_sem_valid(sem));
|
||||
vTaskSetThreadLocalStoragePointer(task, 0, sem);
|
||||
}
|
||||
}
|
||||
|
||||
void sys_arch_netconn_sem_free(void)
|
||||
{
|
||||
void *ret;
|
||||
TaskHandle_t task = xTaskGetCurrentTaskHandle();
|
||||
LWIP_ASSERT("task != NULL", task != NULL);
|
||||
|
||||
ret = pvTaskGetThreadLocalStoragePointer(task, 0);
|
||||
if (ret != NULL) {
|
||||
sys_sem_t *sem = ret;
|
||||
sys_sem_free(sem);
|
||||
mem_free(sem);
|
||||
vTaskSetThreadLocalStoragePointer(task, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */
|
||||
#error LWIP_NETCONN_SEM_PER_THREAD needs configNUM_THREAD_LOCAL_STORAGE_POINTERS
|
||||
#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */
|
||||
|
||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
||||
|
||||
#if LWIP_FREERTOS_CHECK_CORE_LOCKING
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
|
||||
/** Flag the core lock held. A counter for recursive locks. */
|
||||
static u8_t lwip_core_lock_count;
|
||||
static TaskHandle_t lwip_core_lock_holder_thread;
|
||||
|
||||
void sys_lock_tcpip_core(void)
|
||||
{
|
||||
sys_mutex_lock(&lock_tcpip_core);
|
||||
if (lwip_core_lock_count == 0) {
|
||||
lwip_core_lock_holder_thread = xTaskGetCurrentTaskHandle();
|
||||
}
|
||||
lwip_core_lock_count++;
|
||||
}
|
||||
|
||||
void sys_unlock_tcpip_core(void)
|
||||
{
|
||||
lwip_core_lock_count--;
|
||||
if (lwip_core_lock_count == 0) {
|
||||
lwip_core_lock_holder_thread = 0;
|
||||
}
|
||||
sys_mutex_unlock(&lock_tcpip_core);
|
||||
}
|
||||
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
|
||||
#if !NO_SYS
|
||||
static TaskHandle_t lwip_tcpip_thread;
|
||||
#endif
|
||||
|
||||
void sys_mark_tcpip_thread(void)
|
||||
{
|
||||
#if !NO_SYS
|
||||
lwip_tcpip_thread = xTaskGetCurrentTaskHandle();
|
||||
#endif
|
||||
}
|
||||
|
||||
void sys_check_core_locking(void)
|
||||
{
|
||||
/* Embedded systems should check we are NOT in an interrupt context here */
|
||||
/* E.g. core Cortex-M3/M4 ports:
|
||||
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||
|
||||
Instead, we use more generic FreeRTOS functions here, which should fail from ISR: */
|
||||
taskENTER_CRITICAL();
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
#if !NO_SYS
|
||||
if (lwip_tcpip_thread != 0) {
|
||||
TaskHandle_t current_thread = xTaskGetCurrentTaskHandle();
|
||||
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
LWIP_ASSERT("Function called without core lock",
|
||||
current_thread == lwip_core_lock_holder_thread && lwip_core_lock_count > 0);
|
||||
#else /* LWIP_TCPIP_CORE_LOCKING */
|
||||
LWIP_ASSERT("Function called from wrong thread", current_thread == lwip_tcpip_thread);
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
}
|
||||
#endif /* !NO_SYS */
|
||||
}
|
||||
|
||||
#endif /* LWIP_FREERTOS_CHECK_CORE_LOCKING*/
|
||||
|
||||
#else
|
||||
static uint32_t sys_tick = 0;
|
||||
|
||||
void sys_timer_callback(void)
|
||||
{
|
||||
sys_tick++;
|
||||
}
|
||||
|
||||
u32_t sys_now(void)
|
||||
{
|
||||
return (u32_t)sys_tick;
|
||||
}
|
||||
|
||||
#endif
|
||||
108
tests/hpmicro/inc/arch/sys_arch.h
Normal file
108
tests/hpmicro/inc/arch/sys_arch.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Simon Goldschmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Simon Goldschmdit <goldsimon@gmx.de>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021-2023 HPMicro
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LWIP_ARCH_SYS_ARCH_H
|
||||
#define LWIP_ARCH_SYS_ARCH_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/arch.h"
|
||||
|
||||
|
||||
#if !NO_SYS
|
||||
/** This is returned by _fromisr() sys functions to tell the outermost function
|
||||
* that a higher priority task was woken and the scheduler needs to be invoked.
|
||||
*/
|
||||
#define ERR_NEED_SCHED 123
|
||||
|
||||
/* This port includes FreeRTOS headers in sys_arch.c only.
|
||||
* FreeRTOS uses pointers as object types. We use wrapper structs instead of
|
||||
* void pointers directly to get a tiny bit of type safety.
|
||||
*/
|
||||
|
||||
void sys_arch_msleep(u32_t delay_ms);
|
||||
#define sys_msleep(ms) sys_arch_msleep(ms)
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
typedef u32_t sys_prot_t;
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
|
||||
#if !LWIP_COMPAT_MUTEX
|
||||
struct _sys_mut {
|
||||
void *mut;
|
||||
};
|
||||
typedef struct _sys_mut sys_mutex_t;
|
||||
#define sys_mutex_valid_val(mutex) ((mutex).mut != NULL)
|
||||
#define sys_mutex_valid(mutex) (((mutex) != NULL) && sys_mutex_valid_val(*(mutex)))
|
||||
#define sys_mutex_set_invalid(mutex) ((mutex)->mut = NULL)
|
||||
#endif /* !LWIP_COMPAT_MUTEX */
|
||||
|
||||
struct _sys_sem {
|
||||
void *sem;
|
||||
};
|
||||
typedef struct _sys_sem sys_sem_t;
|
||||
#define sys_sem_valid_val(sema) ((sema).sem != NULL)
|
||||
#define sys_sem_valid(sema) (((sema) != NULL) && sys_sem_valid_val(*(sema)))
|
||||
#define sys_sem_set_invalid(sema) ((sema)->sem = NULL)
|
||||
|
||||
struct _sys_mbox {
|
||||
void *mbx;
|
||||
};
|
||||
typedef struct _sys_mbox sys_mbox_t;
|
||||
#define sys_mbox_valid_val(mbox) ((mbox).mbx != NULL)
|
||||
#define sys_mbox_valid(mbox) (((mbox) != NULL) && sys_mbox_valid_val(*(mbox)))
|
||||
#define sys_mbox_set_invalid(mbox) ((mbox)->mbx = NULL)
|
||||
|
||||
struct _sys_thread {
|
||||
void *thread_handle;
|
||||
};
|
||||
typedef struct _sys_thread sys_thread_t;
|
||||
|
||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
||||
sys_sem_t *sys_arch_netconn_sem_get(void);
|
||||
void sys_arch_netconn_sem_alloc(void);
|
||||
void sys_arch_netconn_sem_free(void);
|
||||
#define LWIP_NETCONN_THREAD_SEM_GET() sys_arch_netconn_sem_get()
|
||||
#define LWIP_NETCONN_THREAD_SEM_ALLOC() sys_arch_netconn_sem_alloc()
|
||||
#define LWIP_NETCONN_THREAD_SEM_FREE() sys_arch_netconn_sem_free()
|
||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
||||
#else
|
||||
void sys_timer_callback(void);
|
||||
#endif /* !NO_SYS */
|
||||
#endif /* LWIP_ARCH_SYS_ARCH_H */
|
||||
436
tests/hpmicro/inc/lwipopts.h
Normal file
436
tests/hpmicro/inc/lwipopts.h
Normal file
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
* Copyright (c) 2025, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef LWIPOPTS_H
|
||||
#define LWIPOPTS_H
|
||||
|
||||
#ifdef USE_LWIPOPTS_APP_H
|
||||
#include "lwipopts_app.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
|
||||
* critical regions during buffer allocation, deallocation and memory
|
||||
* allocation and deallocation.
|
||||
*/
|
||||
#define SYS_LIGHTWEIGHT_PROT 1
|
||||
#define IP_REASSEMBLY 0
|
||||
#define IP_FRAG 0
|
||||
#define ARP_QUEUEING 0
|
||||
#define NO_SYS 0
|
||||
#define LWIP_RAND rand
|
||||
|
||||
#define LWIP_NETIF_HOSTNAME 0
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
#define LWIP_TIMERS 1
|
||||
#define LWIP_RAW 1
|
||||
#define LWIP_IPV4 1
|
||||
#define LWIP_IGMP 1
|
||||
#define LWIP_ICMP 1
|
||||
#define ICMP_TTL 64
|
||||
#define LWIP_TCP 1
|
||||
#define TCP_TTL 255
|
||||
#define LWIP_UDP 1
|
||||
#define UDP_TTL 255
|
||||
#define LWIP_DNS 1
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_API==1: Support netif api (in netifapi.c)
|
||||
*/
|
||||
#define LWIP_NETIF_API 1
|
||||
/**
|
||||
* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
|
||||
*/
|
||||
#define LWIP_NETCONN 1
|
||||
/**
|
||||
* LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
|
||||
*/
|
||||
#define LWIP_SOCKET 1
|
||||
|
||||
/* ---------- Memory options ---------- */
|
||||
#define MEMP_MEM_MALLOC 0
|
||||
|
||||
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
|
||||
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
|
||||
byte alignment -> define MEM_ALIGNMENT to 2. */
|
||||
#ifndef MEM_ALIGNMENT
|
||||
#define MEM_ALIGNMENT 64
|
||||
#endif
|
||||
|
||||
/* MEM_SIZE: the size of the heap memory. If the application will send
|
||||
a lot of data that needs to be copied, this should be set high. */
|
||||
#ifndef MEM_SIZE
|
||||
#define MEM_SIZE (32 * 1024)
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
|
||||
sends a lot of data out of ROM (or other static memory), this
|
||||
should be set high. */
|
||||
#ifndef MEMP_NUM_PBUF
|
||||
#define MEMP_NUM_PBUF 100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_RAW_PCB: Number of raw connection PCBs
|
||||
* (requires the LWIP_RAW option)
|
||||
*/
|
||||
#ifndef MEMP_NUM_RAW_PCB
|
||||
#define MEMP_NUM_RAW_PCB 4
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
|
||||
per active UDP "connection". */
|
||||
#ifndef MEMP_NUM_UDP_PCB
|
||||
#define MEMP_NUM_UDP_PCB 4
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
|
||||
connections. */
|
||||
#ifndef MEMP_NUM_TCP_PCB
|
||||
#define MEMP_NUM_TCP_PCB 4
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
|
||||
connections. */
|
||||
#ifndef MEMP_NUM_TCP_PCB_LISTEN
|
||||
#define MEMP_NUM_TCP_PCB_LISTEN 5
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
|
||||
segments. */
|
||||
#ifndef MEMP_NUM_TCP_SEG
|
||||
#define MEMP_NUM_TCP_SEG 40
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
|
||||
timeouts. */
|
||||
#ifndef MEMP_NUM_SYS_TIMEOUT
|
||||
#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_NETCONN: the number of struct netconns.
|
||||
* (only needed if you use the sequential API, like api_lib.c)
|
||||
*/
|
||||
#ifndef MEMP_NUM_NETCONN
|
||||
#define MEMP_NUM_NETCONN 4
|
||||
#endif
|
||||
|
||||
/* ---------- Pbuf options ---------- */
|
||||
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
|
||||
#ifndef PBUF_POOL_SIZE
|
||||
#define PBUF_POOL_SIZE 20
|
||||
#endif
|
||||
|
||||
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
|
||||
#ifndef PBUF_POOL_BUFSIZE
|
||||
#define PBUF_POOL_BUFSIZE 1600
|
||||
#endif
|
||||
|
||||
/* ---------- TCP options ---------- */
|
||||
/* Controls if TCP should queue segments that arrive out of
|
||||
order. Define to 0 if your device is low on memory. */
|
||||
#ifndef TCP_QUEUE_OOSEQ
|
||||
#define TCP_QUEUE_OOSEQ 0
|
||||
#endif
|
||||
|
||||
/* TCP Maximum segment size. */
|
||||
#ifndef TCP_MSS
|
||||
#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
|
||||
#endif
|
||||
|
||||
/* TCP sender buffer space (bytes). */
|
||||
#ifndef TCP_SND_BUF
|
||||
#define TCP_SND_BUF (8 * TCP_MSS)
|
||||
#endif
|
||||
|
||||
/* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
|
||||
as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */
|
||||
#ifndef TCP_SND_QUEUELEN
|
||||
#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF / TCP_MSS)
|
||||
#endif
|
||||
|
||||
/* TCP receive window. */
|
||||
#ifndef TCP_WND
|
||||
#define TCP_WND (16 * TCP_MSS)
|
||||
#endif
|
||||
|
||||
/* ---------- DHCP options ---------- */
|
||||
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
|
||||
interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
|
||||
turning this on does currently not work. */
|
||||
#ifndef LWIP_DHCP
|
||||
#define LWIP_DHCP 1
|
||||
#endif
|
||||
|
||||
/* ---------- Statistics options ---------- */
|
||||
#ifndef LWIP_STATS
|
||||
#define LWIP_STATS 0
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_PROVIDE_ERRNO
|
||||
#define LWIP_PROVIDE_ERRNO 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
------------------------------------------------
|
||||
---------- Network Interfaces options ----------
|
||||
------------------------------------------------
|
||||
*/
|
||||
/**
|
||||
* LWIP_SINGLE_NETIF==1: use a single netif only. This is the common case for
|
||||
* small real-life targets. Some code like routing etc. can be left out.
|
||||
*/
|
||||
#ifndef LWIP_SINGLE_NETIF
|
||||
#define LWIP_SINGLE_NETIF 1
|
||||
#endif
|
||||
|
||||
/* ---------- link callback options ---------- */
|
||||
/* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface
|
||||
* whenever the link changes (i.e., link down)
|
||||
*/
|
||||
#ifndef LWIP_NETIF_LINK_CALLBACK
|
||||
#define LWIP_NETIF_LINK_CALLBACK 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP *tries* to put all data
|
||||
* to be sent into one single pbuf. This is for compatibility with DMA-enabled
|
||||
* MACs that do not support scatter-gather.
|
||||
* Beware that this might involve CPU-memcpy before transmitting that would not
|
||||
* be needed without this flag! Use this only if you need to!
|
||||
*
|
||||
* ATTENTION: a driver should *NOT* rely on getting single pbufs but check TX
|
||||
* pbufs for being in one piece. If not, @ref pbuf_clone can be used to get
|
||||
* a single pbuf:
|
||||
* if (p->next != NULL) {
|
||||
* struct pbuf *q = pbuf_clone(PBUF_RAW, PBUF_RAM, p);
|
||||
* if (q == NULL) {
|
||||
* return ERR_MEM;
|
||||
* }
|
||||
* p = q; ATTENTION: do NOT free the old 'p' as the ref belongs to the caller!
|
||||
* }
|
||||
*/
|
||||
#ifndef LWIP_NETIF_TX_SINGLE_PBUF
|
||||
#define LWIP_NETIF_TX_SINGLE_PBUF 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
--------------------------------------
|
||||
---------- Checksum options ----------
|
||||
--------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some MCUs allow computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
|
||||
* To use this feature let the following define uncommented.
|
||||
* To disable it and process by CPU comment the the checksum.
|
||||
*/
|
||||
#ifdef CHECKSUM_BY_HARDWARE
|
||||
/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
|
||||
#define CHECKSUM_GEN_IP 0
|
||||
/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
|
||||
#define CHECKSUM_GEN_UDP 0
|
||||
/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
|
||||
#define CHECKSUM_GEN_TCP 0
|
||||
/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
|
||||
#define CHECKSUM_CHECK_IP 0
|
||||
/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
|
||||
#define CHECKSUM_CHECK_UDP 0
|
||||
/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
|
||||
#define CHECKSUM_CHECK_TCP 0
|
||||
/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/
|
||||
#define CHECKSUM_GEN_ICMP 0
|
||||
#else
|
||||
/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
|
||||
#define CHECKSUM_GEN_IP 1
|
||||
/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
|
||||
#define CHECKSUM_GEN_UDP 1
|
||||
/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
|
||||
#define CHECKSUM_GEN_TCP 1
|
||||
/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
|
||||
#define CHECKSUM_CHECK_IP 1
|
||||
/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
|
||||
#define CHECKSUM_CHECK_UDP 1
|
||||
/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
|
||||
#define CHECKSUM_CHECK_TCP 1
|
||||
/* CHECKSUM_CHECK_ICMP==1: Check checksums by software for incoming ICMP packets.*/
|
||||
#define CHECKSUM_GEN_ICMP 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
-----------------------------------
|
||||
---------- DEBUG options ----------
|
||||
-----------------------------------
|
||||
*/
|
||||
#ifdef LWIP_DEBUG
|
||||
|
||||
#ifndef LWIP_DBG_MIN_LEVEL
|
||||
#define LWIP_DBG_MIN_LEVEL 0
|
||||
#endif
|
||||
|
||||
#ifndef PPP_DEBUG
|
||||
#define PPP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef MEM_DEBUG
|
||||
#define MEM_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_DEBUG
|
||||
#define MEMP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef PBUF_DEBUG
|
||||
#define PBUF_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef API_LIB_DEBUG
|
||||
#define API_LIB_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef API_MSG_DEBUG
|
||||
#define API_MSG_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCPIP_DEBUG
|
||||
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef NETIF_DEBUG
|
||||
#define NETIF_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef SOCKETS_DEBUG
|
||||
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef DNS_DEBUG
|
||||
#define DNS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef AUTOIP_DEBUG
|
||||
#define AUTOIP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef DHCP_DEBUG
|
||||
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef IP_DEBUG
|
||||
#define IP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef IP_REASS_DEBUG
|
||||
#define IP_REASS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef ICMP_DEBUG
|
||||
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef IGMP_DEBUG
|
||||
#define IGMP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef UDP_DEBUG
|
||||
#define UDP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_DEBUG
|
||||
#define TCP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_INPUT_DEBUG
|
||||
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_OUTPUT_DEBUG
|
||||
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_RTO_DEBUG
|
||||
#define TCP_RTO_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_CWND_DEBUG
|
||||
#define TCP_CWND_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_WND_DEBUG
|
||||
#define TCP_WND_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_FR_DEBUG
|
||||
#define TCP_FR_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_QLEN_DEBUG
|
||||
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_RST_DEBUG
|
||||
#define TCP_RST_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef ETHARP_DEBUG
|
||||
#define ETHARP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
---------------------------------
|
||||
---------- OS options ----------
|
||||
---------------------------------
|
||||
*/
|
||||
#ifndef TCPIP_THREAD_NAME
|
||||
#define TCPIP_THREAD_NAME "tcpip"
|
||||
#endif
|
||||
|
||||
#ifndef TCPIP_THREAD_STACKSIZE
|
||||
#define TCPIP_THREAD_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef TCPIP_MBOX_SIZE
|
||||
#define TCPIP_MBOX_SIZE 8
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_RAW_RECVMBOX_SIZE
|
||||
#define DEFAULT_RAW_RECVMBOX_SIZE 50
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_UDP_RECVMBOX_SIZE
|
||||
#define DEFAULT_UDP_RECVMBOX_SIZE 50
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_TCP_RECVMBOX_SIZE
|
||||
#define DEFAULT_TCP_RECVMBOX_SIZE 50
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_ACCEPTMBOX_SIZE
|
||||
#define DEFAULT_ACCEPTMBOX_SIZE 50
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_THREAD_STACKSIZE
|
||||
#define DEFAULT_THREAD_STACKSIZE 500
|
||||
#endif
|
||||
|
||||
#ifndef TCPIP_THREAD_PRIO
|
||||
#define TCPIP_THREAD_PRIO 10
|
||||
#endif
|
||||
|
||||
#define LWIP_COMPAT_MUTEX 0
|
||||
#define LWIP_TCPIP_CORE_LOCKING 1
|
||||
|
||||
#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT
|
||||
#define LWIP_TCPIP_CORE_LOCKING_INPUT 1
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_MEM_SECTION
|
||||
#define LWIP_MEM_SECTION ".bss"
|
||||
#endif
|
||||
|
||||
#endif /* __LWIPOPTS_H__ */
|
||||
308
tests/hpmicro/inc/usb_config.h
Normal file
308
tests/hpmicro/inc/usb_config.h
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
* Copyright (c) 2022-2025, HPMicro
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef CHERRYUSB_CONFIG_H
|
||||
#define CHERRYUSB_CONFIG_H
|
||||
|
||||
#include "board.h"
|
||||
|
||||
/* ================ USB common Configuration ================ */
|
||||
|
||||
#ifdef __RTTHREAD__
|
||||
#include <rtthread.h>
|
||||
|
||||
#define CONFIG_USB_PRINTF(...) rt_kprintf(__VA_ARGS__)
|
||||
#else
|
||||
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USB_DBG_LEVEL
|
||||
#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USB_DEVICE_FS) || defined(CONFIG_USB_DEVICE_FORCE_FULL_SPEED)
|
||||
#undef CONFIG_USB_HS
|
||||
#else
|
||||
#define CONFIG_USB_HS
|
||||
#endif
|
||||
|
||||
/* Enable print with color */
|
||||
#define CONFIG_USB_PRINTF_COLOR_ENABLE
|
||||
|
||||
/* #define CONFIG_USB_DCACHE_ENABLE */
|
||||
|
||||
/* data align size when use dma or use dcache */
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
#define CONFIG_USB_ALIGN_SIZE HPM_L1C_CACHELINE_SIZE
|
||||
#else
|
||||
#define CONFIG_USB_ALIGN_SIZE 4
|
||||
#endif
|
||||
|
||||
/* descriptor common define */
|
||||
#define USBD_VID 0x34B7 /* HPMicro VID */
|
||||
#define USBD_PID 0xFFFF
|
||||
#define USBD_MAX_POWER 200
|
||||
|
||||
/* attribute data into no cache ram */
|
||||
#define USB_NOCACHE_RAM_SECTION __attribute__((section(".fast_ram.non_init")))
|
||||
|
||||
/* use usb_memcpy default for high performance but cost more flash memory.
|
||||
* And, arm libc has a bug that memcpy() may cause data misalignment when the size is not a multiple of 4.
|
||||
*/
|
||||
/* #define CONFIG_USB_MEMCPY_DISABLE */
|
||||
|
||||
/* ================= USB Device Stack Configuration ================ */
|
||||
|
||||
/* Ep0 in and out transfer buffer */
|
||||
#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN
|
||||
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 512
|
||||
#endif
|
||||
|
||||
/* Setup packet log for debug */
|
||||
/* #define CONFIG_USBDEV_SETUP_LOG_PRINT */
|
||||
|
||||
/* Send ep0 in data from user buffer instead of copying into ep0 reqdata
|
||||
* Please note that user buffer must be aligned with CONFIG_USB_ALIGN_SIZE
|
||||
*/
|
||||
/* #define CONFIG_USBDEV_EP0_INDATA_NO_COPY */
|
||||
|
||||
/* Check if the input descriptor is correct */
|
||||
/* #define CONFIG_USBDEV_DESC_CHECK */
|
||||
|
||||
/* Enable test mode */
|
||||
#define CONFIG_USBDEV_TEST_MODE
|
||||
|
||||
/* enable advance desc register api */
|
||||
#define CONFIG_USBDEV_ADVANCE_DESC
|
||||
|
||||
/* move ep0 setup handler from isr to thread */
|
||||
/* #define CONFIG_USBDEV_EP0_THREAD */
|
||||
|
||||
#ifndef CONFIG_USBDEV_EP0_PRIO
|
||||
#define CONFIG_USBDEV_EP0_PRIO 4
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_EP0_STACKSIZE
|
||||
#define CONFIG_USBDEV_EP0_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_MAX_LUN
|
||||
#define CONFIG_USBDEV_MSC_MAX_LUN 1
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_MAX_BUFSIZE
|
||||
#define CONFIG_USBDEV_MSC_MAX_BUFSIZE 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
|
||||
|
||||
/* move msc read & write from isr to while(1), you should call usbd_msc_polling in while(1) */
|
||||
/* #define CONFIG_USBDEV_MSC_POLLING */
|
||||
|
||||
/* move msc read & write from isr to thread */
|
||||
/* #define CONFIG_USBDEV_MSC_THREAD */
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_PRIO
|
||||
#define CONFIG_USBDEV_MSC_PRIO 4
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_STACKSIZE
|
||||
#define CONFIG_USBDEV_MSC_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MTP_MAX_BUFSIZE
|
||||
#define CONFIG_USBDEV_MTP_MAX_BUFSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MTP_MAX_OBJECTS
|
||||
#define CONFIG_USBDEV_MTP_MAX_OBJECTS 256
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MTP_MAX_PATHNAME
|
||||
#define CONFIG_USBDEV_MTP_MAX_PATHNAME 256
|
||||
#endif
|
||||
|
||||
#define CONFIG_USBDEV_MTP_THREAD
|
||||
|
||||
#ifndef CONFIG_USBDEV_MTP_PRIO
|
||||
#define CONFIG_USBDEV_MTP_PRIO 4
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MTP_STACKSIZE
|
||||
#define CONFIG_USBDEV_MTP_STACKSIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
|
||||
#endif
|
||||
|
||||
/* rndis transfer buffer size, must be a multiple of (1536 + 44)*/
|
||||
#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID
|
||||
#define CONFIG_USBDEV_RNDIS_VENDOR_ID 0x0000ffff
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_VENDOR_DESC
|
||||
#define CONFIG_USBDEV_RNDIS_VENDOR_DESC "HPMicro"
|
||||
#endif
|
||||
|
||||
#define CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
|
||||
/* ================ 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 8
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 2
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_HID_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
|
||||
#define CONFIG_USBHOST_DEV_NAMELEN 16
|
||||
|
||||
#ifndef CONFIG_USBHOST_PSC_PRIO
|
||||
#define CONFIG_USBHOST_PSC_PRIO 0
|
||||
#endif
|
||||
#ifndef CONFIG_USBHOST_PSC_STACKSIZE
|
||||
#define CONFIG_USBHOST_PSC_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
/* #define CONFIG_USBHOST_GET_STRING_DESC */
|
||||
|
||||
/* #define CONFIG_USBHOST_MSOS_ENABLE */
|
||||
#ifndef CONFIG_USBHOST_MSOS_VENDOR_CODE
|
||||
#define CONFIG_USBHOST_MSOS_VENDOR_CODE 0x00
|
||||
#endif
|
||||
|
||||
/* Ep0 max transfer buffer */
|
||||
#ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN
|
||||
#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 4096
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (16 * 1024)
|
||||
#endif
|
||||
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
#define CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
/* #define CONFIG_USBHOST_BLUETOOTH_HCI_LOG */
|
||||
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_TX_SIZE
|
||||
#define CONFIG_USBHOST_BLUETOOTH_TX_SIZE 2048
|
||||
#endif
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_RX_SIZE
|
||||
#define CONFIG_USBHOST_BLUETOOTH_RX_SIZE 2048
|
||||
#endif
|
||||
|
||||
/* ================ USB Device Port Configuration ================*/
|
||||
|
||||
#define CONFIG_USBDEV_MAX_BUS USB_SOC_MAX_COUNT
|
||||
|
||||
#ifndef CONFIG_HPM_USBD_BASE
|
||||
#define CONFIG_HPM_USBD_BASE HPM_USB0_BASE
|
||||
#endif
|
||||
#ifndef CONFIG_HPM_USBD_IRQn
|
||||
#define CONFIG_HPM_USBD_IRQn IRQn_USB0
|
||||
#endif
|
||||
|
||||
/* ================ USB Host Port Configuration ==================*/
|
||||
#define CONFIG_USBHOST_MAX_BUS USB_SOC_MAX_COUNT
|
||||
|
||||
#ifndef CONFIG_HPM_USBH_BASE
|
||||
#define CONFIG_HPM_USBH_BASE HPM_USB0_BASE
|
||||
#endif
|
||||
#ifndef CONFIG_HPM_USBH_IRQn
|
||||
#define CONFIG_HPM_USBH_IRQn IRQn_USB0
|
||||
#endif
|
||||
|
||||
/* ================ EHCI Configuration ================ */
|
||||
|
||||
#define CONFIG_USB_EHCI_HPMICRO (1)
|
||||
#define CONFIG_USB_EHCI_HCCR_OFFSET (0x100u)
|
||||
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
|
||||
#define CONFIG_USB_EHCI_QH_NUM 10
|
||||
#define CONFIG_USB_EHCI_QTD_NUM 64
|
||||
|
||||
/* ================ Addr Convert Configuration ==================*/
|
||||
#ifndef usb_phyaddr2ramaddr
|
||||
#define usb_phyaddr2ramaddr(addr) core_local_mem_to_sys_address(BOARD_RUNNING_CORE, addr)
|
||||
#endif
|
||||
|
||||
#ifndef usb_ramaddr2phyaddr
|
||||
#define usb_ramaddr2phyaddr(addr) sys_address_to_core_local_mem(BOARD_RUNNING_CORE, addr)
|
||||
#endif
|
||||
|
||||
#define ATTR_FAST_RAM_SECTION __attribute__((section(".fast")))
|
||||
// #define CONFIG_USB_EHCI_ISO
|
||||
|
||||
#endif
|
||||
277
tests/hpmicro/src/cdc_acm_otg_template.c
Normal file
277
tests/hpmicro/src/cdc_acm_otg_template.c
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbotg_core.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
/*!< endpoint address */
|
||||
#define CDC_IN_EP 0x81
|
||||
#define CDC_OUT_EP 0x02
|
||||
#define CDC_INT_EP 0x83
|
||||
|
||||
#define USBD_LANGID_STRING 1033
|
||||
|
||||
/*!< config descriptor size */
|
||||
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN)
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_MAX_MPS 512
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
static const uint8_t device_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
|
||||
};
|
||||
|
||||
static const uint8_t config_descriptor[] = {
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02)
|
||||
};
|
||||
|
||||
static const uint8_t device_quality_descriptor[] = {
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
|
||||
static const char *string_descriptors[] = {
|
||||
(const char[]){ 0x09, 0x04 }, /* Langid */
|
||||
"CherryUSB", /* Manufacturer */
|
||||
"CherryUSB CDC DEMO", /* Product */
|
||||
"2022123456", /* Serial Number */
|
||||
};
|
||||
|
||||
static const uint8_t *device_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
return device_descriptor;
|
||||
}
|
||||
|
||||
static const uint8_t *config_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
return config_descriptor;
|
||||
}
|
||||
|
||||
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
|
||||
{
|
||||
return device_quality_descriptor;
|
||||
}
|
||||
|
||||
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
|
||||
{
|
||||
if (index > 3) {
|
||||
return NULL;
|
||||
}
|
||||
return string_descriptors[index];
|
||||
}
|
||||
|
||||
const struct usb_descriptor cdc_descriptor = {
|
||||
.device_descriptor_callback = device_descriptor_callback,
|
||||
.config_descriptor_callback = config_descriptor_callback,
|
||||
.device_quality_descriptor_callback = device_quality_descriptor_callback,
|
||||
.string_descriptor_callback = string_descriptor_callback
|
||||
};
|
||||
#else
|
||||
/*!< global descriptor */
|
||||
static const uint8_t cdc_descriptor[] = {
|
||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
|
||||
///////////////////////////////////////
|
||||
/// string0 descriptor
|
||||
///////////////////////////////////////
|
||||
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||
///////////////////////////////////////
|
||||
/// string1 descriptor
|
||||
///////////////////////////////////////
|
||||
0x14, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
///////////////////////////////////////
|
||||
/// string2 descriptor
|
||||
///////////////////////////////////////
|
||||
0x26, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'C', 0x00, /* wcChar0 */
|
||||
'h', 0x00, /* wcChar1 */
|
||||
'e', 0x00, /* wcChar2 */
|
||||
'r', 0x00, /* wcChar3 */
|
||||
'r', 0x00, /* wcChar4 */
|
||||
'y', 0x00, /* wcChar5 */
|
||||
'U', 0x00, /* wcChar6 */
|
||||
'S', 0x00, /* wcChar7 */
|
||||
'B', 0x00, /* wcChar8 */
|
||||
' ', 0x00, /* wcChar9 */
|
||||
'C', 0x00, /* wcChar10 */
|
||||
'D', 0x00, /* wcChar11 */
|
||||
'C', 0x00, /* wcChar12 */
|
||||
' ', 0x00, /* wcChar13 */
|
||||
'D', 0x00, /* wcChar14 */
|
||||
'E', 0x00, /* wcChar15 */
|
||||
'M', 0x00, /* wcChar16 */
|
||||
'O', 0x00, /* wcChar17 */
|
||||
///////////////////////////////////////
|
||||
/// string3 descriptor
|
||||
///////////////////////////////////////
|
||||
0x16, /* bLength */
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||
'2', 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 */
|
||||
#ifdef CONFIG_USB_HS
|
||||
///////////////////////////////////////
|
||||
/// device qualifier descriptor
|
||||
///////////////////////////////////////
|
||||
0x0a,
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
0x00
|
||||
};
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048]; /* 2048 is only for test speed , please use CDC_MAX_MPS for common*/
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
|
||||
|
||||
volatile bool ep_tx_busy_flag = false;
|
||||
|
||||
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
ep_tx_busy_flag = false;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
|
||||
// for (int i = 0; i < 100; i++) {
|
||||
// printf("%02x ", read_buffer[i]);
|
||||
// }
|
||||
// printf("\r\n");
|
||||
/* setup next out ep read transfer */
|
||||
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
|
||||
|
||||
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
|
||||
} else {
|
||||
ep_tx_busy_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*!< endpoint call back */
|
||||
struct usbd_endpoint cdc_out_ep = {
|
||||
.ep_addr = CDC_OUT_EP,
|
||||
.ep_cb = usbd_cdc_acm_bulk_out
|
||||
};
|
||||
|
||||
struct usbd_endpoint cdc_in_ep = {
|
||||
.ep_addr = CDC_IN_EP,
|
||||
.ep_cb = usbd_cdc_acm_bulk_in
|
||||
};
|
||||
|
||||
static struct usbd_interface intf0;
|
||||
static struct usbd_interface intf1;
|
||||
|
||||
void cdc_acm_otg_init(uint8_t busid, uintptr_t reg_base)
|
||||
{
|
||||
const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
||||
|
||||
memcpy(&write_buffer[0], data, 10);
|
||||
memset(&write_buffer[10], 'a', 2038);
|
||||
|
||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
||||
usbd_desc_register(busid, &cdc_descriptor);
|
||||
#else
|
||||
usbd_desc_register(busid, cdc_descriptor);
|
||||
#endif
|
||||
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
|
||||
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
|
||||
usbd_add_endpoint(busid, &cdc_out_ep);
|
||||
usbd_add_endpoint(busid, &cdc_in_ep);
|
||||
|
||||
usbotg_initialize(busid, reg_base, usbd_event_handler, NULL, USBOTG_MODE_DEVICE);
|
||||
}
|
||||
|
||||
volatile uint8_t dtr_enable = 0;
|
||||
|
||||
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
|
||||
{
|
||||
if (dtr) {
|
||||
dtr_enable = 1;
|
||||
} else {
|
||||
dtr_enable = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
|
||||
{
|
||||
if (dtr_enable) {
|
||||
ep_tx_busy_flag = true;
|
||||
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
|
||||
while (ep_tx_busy_flag) {
|
||||
}
|
||||
}
|
||||
}
|
||||
1066
tests/hpmicro/src/font24x48.c
Normal file
1066
tests/hpmicro/src/font24x48.c
Normal file
File diff suppressed because it is too large
Load Diff
763
tests/hpmicro/src/iperf/iperf.c
Normal file
763
tests/hpmicro/src/iperf/iperf.c
Normal file
@@ -0,0 +1,763 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
#include "iperf.h"
|
||||
|
||||
#include "hpm_clock_drv.h"
|
||||
#include "hpm_csr_drv.h"
|
||||
#include "board.h"
|
||||
|
||||
// TODO move to common
|
||||
#define xTaskCreatePinnedToCore(pvTaskCode, pcName, usStackDepth, \
|
||||
pvParameters, uxPriority, \
|
||||
pvCreatedTask, xCoreID_) \
|
||||
xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, \
|
||||
uxPriority, pvCreatedTask)
|
||||
|
||||
int64_t iperf_timer_get_time()
|
||||
{
|
||||
return (hpm_csr_get_core_mcycle() / (clock_get_frequency(clock_cpu0) / 1000000));
|
||||
}
|
||||
|
||||
#define iperf_delay_us board_delay_us
|
||||
#define IRAM_ATTR __attribute__((section(".fast"))) // on tcm run
|
||||
#define IPERF_V6 0 // TODO sync with lwip config
|
||||
#define iperf_err_t int
|
||||
#define IPERF_OK 0 /*!< iperf_err_t value indicating success (no error) */
|
||||
#define IPERF_FAIL -1 /*!< Generic iperf_err_t code indicating failure */
|
||||
|
||||
#define IPERF_LOGE(tag, format, ...) \
|
||||
do { \
|
||||
(void)tag; \
|
||||
printf("[%s] " format "\r\n", tag, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define IPERF_LOGW(tag, format, ...) \
|
||||
do { \
|
||||
(void)tag; \
|
||||
printf("[%s] " format "\r\n", tag, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define IPERF_LOGI(tag, format, ...) \
|
||||
do { \
|
||||
(void)tag; \
|
||||
printf("[%s] " format "\r\n", tag, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define IPERF_LOGD(tag, format, ...) \
|
||||
do { \
|
||||
(void)tag; \
|
||||
printf("[%s] " format "\r\n", tag, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define IPERF_LOGV(tag, format, ...) \
|
||||
do { \
|
||||
(void)tag; \
|
||||
printf("[%s] " format "\r\n", tag, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define IPERF_GOTO_ON_FALSE(a, err_code, goto_tag, log_tag, format, ...) \
|
||||
do { \
|
||||
(void)log_tag; \
|
||||
if ((!(a))) { \
|
||||
ret = err_code; \
|
||||
goto goto_tag; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NL "\r\n"
|
||||
|
||||
typedef struct {
|
||||
iperf_cfg_t cfg;
|
||||
bool finish;
|
||||
uint32_t actual_len;
|
||||
uint32_t tot_len;
|
||||
uint32_t buffer_len;
|
||||
uint8_t *buffer;
|
||||
uint32_t sockfd;
|
||||
} iperf_ctrl_t;
|
||||
|
||||
static bool s_iperf_is_running = false;
|
||||
static iperf_ctrl_t s_iperf_ctrl;
|
||||
static const char *TAG = "iperf";
|
||||
|
||||
inline static bool iperf_is_udp_client(void)
|
||||
{
|
||||
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP));
|
||||
}
|
||||
|
||||
inline static bool iperf_is_udp_server(void)
|
||||
{
|
||||
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_SERVER) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP));
|
||||
}
|
||||
|
||||
inline static bool iperf_is_tcp_client(void)
|
||||
{
|
||||
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP));
|
||||
}
|
||||
|
||||
inline static bool iperf_is_tcp_dual_client(void)
|
||||
{
|
||||
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_DUAL));
|
||||
}
|
||||
|
||||
inline static bool iperf_is_tcp_server(void)
|
||||
{
|
||||
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_SERVER) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP));
|
||||
}
|
||||
|
||||
static int iperf_get_socket_error_code(int sockfd)
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
static int iperf_show_socket_error_reason(const char *str, int sockfd)
|
||||
{
|
||||
int err = errno;
|
||||
if (err != 0) {
|
||||
IPERF_LOGW(TAG, "%s error, error code: %d, reason: %s", str, err, strerror(err));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void iperf_report_task(void *arg)
|
||||
{
|
||||
uint32_t interval = s_iperf_ctrl.cfg.interval;
|
||||
uint32_t time = s_iperf_ctrl.cfg.time;
|
||||
TickType_t delay_interval = (interval * 1000) / portTICK_PERIOD_MS;
|
||||
uint32_t cur = 0;
|
||||
double average = 0;
|
||||
double actual_bandwidth = 0;
|
||||
double actual_transfer = 0;
|
||||
int k = 1;
|
||||
|
||||
printf("[ ID] Interval Transfer Bandwidth\r\n");
|
||||
while (!s_iperf_ctrl.finish) {
|
||||
vTaskDelay(delay_interval);
|
||||
actual_bandwidth = (s_iperf_ctrl.actual_len / 1e6 * 8) / interval;
|
||||
actual_transfer = s_iperf_ctrl.actual_len / 1e6;
|
||||
printf("[%3d] %2d.0-%2d.0 sec %.2f MByte %.2f Mbits/sec\r\n",
|
||||
s_iperf_ctrl.sockfd, cur, cur + interval, actual_transfer, actual_bandwidth);
|
||||
cur += interval;
|
||||
average = ((average * (k - 1) / k) + (actual_bandwidth / k));
|
||||
k++;
|
||||
s_iperf_ctrl.actual_len = 0;
|
||||
if (cur >= time) {
|
||||
actual_transfer = s_iperf_ctrl.tot_len / 1e6;
|
||||
printf("[%3d] %2d.0-%2d.0 sec %.2f MByte %.2f Mbits/sec\r\n",
|
||||
s_iperf_ctrl.sockfd, 0, time, actual_transfer, average);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s_iperf_ctrl.finish = true;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static iperf_err_t iperf_start_report(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = xTaskCreatePinnedToCore(iperf_report_task, IPERF_REPORT_TASK_NAME, IPERF_REPORT_TASK_STACK, NULL, s_iperf_ctrl.cfg.traffic_task_priority, NULL, portNUM_PROCESSORS - 1);
|
||||
|
||||
if (ret != pdPASS) {
|
||||
IPERF_LOGE(TAG, "create task %s failed", IPERF_REPORT_TASK_NAME);
|
||||
return IPERF_FAIL;
|
||||
}
|
||||
|
||||
return IPERF_OK;
|
||||
}
|
||||
|
||||
static void socket_recv(int recv_socket, struct sockaddr_storage listen_addr, uint8_t type)
|
||||
{
|
||||
bool iperf_recv_start = true;
|
||||
uint8_t *buffer;
|
||||
int want_recv = 0;
|
||||
int actual_recv = 0;
|
||||
#if IPERF_V6
|
||||
socklen_t socklen = (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
|
||||
#else
|
||||
socklen_t socklen = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
const char *error_log = (type == IPERF_TRANS_TYPE_TCP) ? "tcp server recv" : "udp server recv";
|
||||
|
||||
buffer = s_iperf_ctrl.buffer;
|
||||
want_recv = s_iperf_ctrl.buffer_len;
|
||||
while (!s_iperf_ctrl.finish) {
|
||||
actual_recv = recvfrom(recv_socket, buffer, want_recv, 0, (struct sockaddr *)&listen_addr, &socklen);
|
||||
if (actual_recv < 0) {
|
||||
iperf_show_socket_error_reason(error_log, recv_socket);
|
||||
s_iperf_ctrl.finish = true;
|
||||
break;
|
||||
} else {
|
||||
if (iperf_recv_start) {
|
||||
iperf_start_report();
|
||||
iperf_recv_start = false;
|
||||
}
|
||||
s_iperf_ctrl.actual_len += actual_recv;
|
||||
s_iperf_ctrl.tot_len += actual_recv;
|
||||
if (s_iperf_ctrl.cfg.num_bytes > 0 && s_iperf_ctrl.tot_len > s_iperf_ctrl.cfg.num_bytes) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void socket_recv_dual(int recv_socket, struct sockaddr_storage listen_addr, uint8_t type)
|
||||
{
|
||||
uint8_t *buffer;
|
||||
int want_recv = 0;
|
||||
int actual_recv = 0;
|
||||
socklen_t socklen = sizeof(struct sockaddr_in);
|
||||
|
||||
#define RECV_DUAL_BUF_LEN (16 * 1024)
|
||||
buffer = pvPortMalloc(RECV_DUAL_BUF_LEN);
|
||||
want_recv = RECV_DUAL_BUF_LEN;
|
||||
if (!buffer) {
|
||||
return;
|
||||
}
|
||||
while (1) {
|
||||
actual_recv = recvfrom(recv_socket, buffer, want_recv, 0, (struct sockaddr *)&listen_addr, &socklen);
|
||||
if (actual_recv <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
vPortFree(buffer);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int32_t flags;
|
||||
int32_t numThreads;
|
||||
int32_t mPort;
|
||||
int32_t bufferlen;
|
||||
int32_t mWindowSize;
|
||||
int32_t mAmount;
|
||||
int32_t mRate;
|
||||
int32_t mUDPRateUnits;
|
||||
int32_t mRealtime;
|
||||
} iperf_client_hdr_t;
|
||||
#define HEADER_VERSION1 0x80000000
|
||||
#define RUN_NOW 0x00000001
|
||||
#define UNITS_PPS 0x00000002
|
||||
|
||||
static void send_dual_header(int sock, struct sockaddr *addr, socklen_t socklen)
|
||||
{
|
||||
iperf_client_hdr_t hdr = {};
|
||||
iperf_cfg_t *cfg = &s_iperf_ctrl.cfg;
|
||||
|
||||
hdr.flags = htonl(HEADER_VERSION1 | RUN_NOW);
|
||||
hdr.numThreads = htonl(1);
|
||||
hdr.mPort = htonl(cfg->sport);
|
||||
hdr.mAmount = htonl(-(cfg->time * 100));
|
||||
|
||||
sendto(sock, &hdr, sizeof(hdr), 0, addr, socklen);
|
||||
}
|
||||
|
||||
static void socket_send(int send_socket, struct sockaddr_storage dest_addr, uint8_t type, int bw_lim)
|
||||
{
|
||||
uint8_t *buffer;
|
||||
int32_t *pkt_id_p;
|
||||
int32_t pkt_cnt = 0;
|
||||
int actual_send = 0;
|
||||
int want_send = 0;
|
||||
int period_us = -1;
|
||||
int delay_us = 0;
|
||||
int64_t prev_time = 0;
|
||||
int64_t send_time = 0;
|
||||
int err = 0;
|
||||
#if IPERF_V6
|
||||
const socklen_t socklen = (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
|
||||
#else
|
||||
const socklen_t socklen = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
const char *error_log = (type == IPERF_TRANS_TYPE_TCP) ? "tcp client send" : "udp client send";
|
||||
|
||||
buffer = s_iperf_ctrl.buffer;
|
||||
pkt_id_p = (int32_t *)s_iperf_ctrl.buffer;
|
||||
want_send = s_iperf_ctrl.buffer_len;
|
||||
iperf_start_report();
|
||||
|
||||
if (bw_lim > 0) {
|
||||
period_us = want_send * 8 / bw_lim;
|
||||
}
|
||||
|
||||
if (iperf_is_tcp_dual_client()) {
|
||||
send_dual_header(send_socket, (struct sockaddr *)&dest_addr, socklen);
|
||||
}
|
||||
|
||||
while (!s_iperf_ctrl.finish) {
|
||||
if (period_us > 0) {
|
||||
send_time = iperf_timer_get_time();
|
||||
if (actual_send > 0) {
|
||||
// Last packet "send" was successful, check how much off the previous loop duration was to the ideal send period. Result will adjust the
|
||||
// next send delay.
|
||||
delay_us += period_us + (int32_t)(prev_time - send_time);
|
||||
} else {
|
||||
// Last packet "send" was not successful. Ideally we should try to catch up the whole previous loop duration (e.g. prev_time - send_time).
|
||||
// However, that's not possible since the most probable reason why the send was unsuccessful is the HW was not able to process the packet.
|
||||
// Hence, we cannot queue more packets with shorter (or no) delay to catch up since we are already at the performance edge. The best we
|
||||
// can do is to reset the send delay (which is probably big negative number) and start all over again.
|
||||
delay_us = 0;
|
||||
}
|
||||
prev_time = send_time;
|
||||
}
|
||||
*pkt_id_p = htonl(pkt_cnt); // datagrams need to be sequentially numbered
|
||||
if (pkt_cnt >= INT32_MAX) {
|
||||
pkt_cnt = 0;
|
||||
} else {
|
||||
pkt_cnt++;
|
||||
}
|
||||
actual_send = sendto(send_socket, buffer, want_send, 0, (struct sockaddr *)&dest_addr, socklen);
|
||||
if (actual_send != want_send) {
|
||||
if (type == IPERF_TRANS_TYPE_UDP) {
|
||||
err = iperf_get_socket_error_code(send_socket);
|
||||
// ENOMEM is expected under heavy load => do not print it
|
||||
if (err != ENOMEM) {
|
||||
iperf_show_socket_error_reason(error_log, send_socket);
|
||||
}
|
||||
} else if (type == IPERF_TRANS_TYPE_TCP) {
|
||||
iperf_show_socket_error_reason(error_log, send_socket);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
s_iperf_ctrl.actual_len += actual_send;
|
||||
s_iperf_ctrl.tot_len += actual_send;
|
||||
if (s_iperf_ctrl.cfg.num_bytes > 0 && s_iperf_ctrl.tot_len >= s_iperf_ctrl.cfg.num_bytes) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// The send delay may be negative, it indicates we are trying to catch up and hence to not delay the loop at all.
|
||||
if (delay_us > 0) {
|
||||
iperf_delay_us(delay_us);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static iperf_err_t IRAM_ATTR iperf_run_tcp_server(void)
|
||||
{
|
||||
int listen_socket = -1;
|
||||
int client_socket = -1;
|
||||
int opt = 1;
|
||||
int err = 0;
|
||||
iperf_err_t ret = IPERF_OK;
|
||||
struct sockaddr_in remote_addr;
|
||||
struct timeval timeout = { 0 };
|
||||
socklen_t addr_len = sizeof(struct sockaddr);
|
||||
struct sockaddr_storage listen_addr = { 0 };
|
||||
#if IPERF_V6
|
||||
struct sockaddr_in6 listen_addr6 = { 0 };
|
||||
#endif
|
||||
struct sockaddr_in listen_addr4 = { 0 };
|
||||
|
||||
IPERF_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), IPERF_FAIL, exit, TAG, "Ivalid AF types");
|
||||
|
||||
#if IPERF_V6
|
||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
||||
// The TCP server listen at the address "::", which means all addresses can be listened to.
|
||||
inet6_aton("::", &listen_addr6.sin6_addr);
|
||||
listen_addr6.sin6_family = AF_INET6;
|
||||
listen_addr6.sin6_port = htons(s_iperf_ctrl.cfg.sport);
|
||||
|
||||
listen_socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_IPV6);
|
||||
IPERF_GOTO_ON_FALSE((listen_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||
|
||||
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
setsockopt(listen_socket, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
|
||||
|
||||
IPERF_LOGI(TAG, "Socket created");
|
||||
|
||||
err = bind(listen_socket, (struct sockaddr *)&listen_addr6, sizeof(listen_addr6));
|
||||
IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET6);
|
||||
err = listen(listen_socket, 1);
|
||||
IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Error occurred during listen: errno %d", errno);
|
||||
|
||||
timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
|
||||
setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
|
||||
memcpy(&listen_addr, &listen_addr6, sizeof(listen_addr6));
|
||||
} else
|
||||
#endif
|
||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
||||
listen_addr4.sin_family = AF_INET;
|
||||
listen_addr4.sin_port = htons(s_iperf_ctrl.cfg.sport);
|
||||
listen_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.source_ip4;
|
||||
|
||||
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
IPERF_GOTO_ON_FALSE((listen_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||
|
||||
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
|
||||
IPERF_LOGI(TAG, "Socket created");
|
||||
|
||||
err = bind(listen_socket, (struct sockaddr *)&listen_addr4, sizeof(listen_addr4));
|
||||
IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET);
|
||||
|
||||
err = listen(listen_socket, 5);
|
||||
IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Error occurred during listen: errno %d", errno);
|
||||
memcpy(&listen_addr, &listen_addr4, sizeof(listen_addr4));
|
||||
}
|
||||
|
||||
client_socket = accept(listen_socket, (struct sockaddr *)&remote_addr, &addr_len);
|
||||
IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to accept connection: errno %d", errno);
|
||||
IPERF_LOGI(TAG, "accept: %s,%d\n", inet_ntoa(remote_addr.sin_addr), htons(remote_addr.sin_port));
|
||||
|
||||
timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
|
||||
setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
|
||||
socket_recv(client_socket, listen_addr, IPERF_TRANS_TYPE_TCP);
|
||||
exit:
|
||||
if (client_socket != -1) {
|
||||
close(client_socket);
|
||||
}
|
||||
|
||||
if (listen_socket != -1) {
|
||||
shutdown(listen_socket, 0);
|
||||
close(listen_socket);
|
||||
IPERF_LOGI(TAG, "TCP Socket server is closed.");
|
||||
}
|
||||
s_iperf_ctrl.finish = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR iperf_tcp_dual_server_task(void *pvParameters)
|
||||
{
|
||||
int listen_socket = -1;
|
||||
int client_socket = -1;
|
||||
int opt = 1;
|
||||
int err = 0;
|
||||
iperf_err_t ret = IPERF_OK;
|
||||
struct sockaddr_in remote_addr;
|
||||
struct timeval timeout = { 0 };
|
||||
socklen_t addr_len = sizeof(struct sockaddr);
|
||||
struct sockaddr_storage listen_addr = { 0 };
|
||||
struct sockaddr_in listen_addr4 = { 0 };
|
||||
|
||||
(void)ret;
|
||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
||||
listen_addr4.sin_family = AF_INET;
|
||||
listen_addr4.sin_port = htons(s_iperf_ctrl.cfg.sport);
|
||||
listen_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.source_ip4;
|
||||
|
||||
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
IPERF_GOTO_ON_FALSE((listen_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||
|
||||
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
|
||||
IPERF_LOGI(TAG, "Socket created");
|
||||
|
||||
err = bind(listen_socket, (struct sockaddr *)&listen_addr4, sizeof(listen_addr4));
|
||||
IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET);
|
||||
|
||||
err = listen(listen_socket, 5);
|
||||
IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Error occurred during listen: errno %d", errno);
|
||||
memcpy(&listen_addr, &listen_addr4, sizeof(listen_addr4));
|
||||
}
|
||||
|
||||
client_socket = accept(listen_socket, (struct sockaddr *)&remote_addr, &addr_len);
|
||||
IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to accept connection: errno %d", errno);
|
||||
IPERF_LOGI(TAG, "accept: %s,%d\n", inet_ntoa(remote_addr.sin_addr), htons(remote_addr.sin_port));
|
||||
|
||||
timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
|
||||
setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
|
||||
socket_recv_dual(client_socket, listen_addr, IPERF_TRANS_TYPE_TCP);
|
||||
exit:
|
||||
if (client_socket != -1) {
|
||||
close(client_socket);
|
||||
}
|
||||
|
||||
if (listen_socket != -1) {
|
||||
shutdown(listen_socket, 0);
|
||||
close(listen_socket);
|
||||
IPERF_LOGI(TAG, "TCP Socket server is closed.");
|
||||
}
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static iperf_err_t iperf_run_tcp_client(void)
|
||||
{
|
||||
int client_socket = -1;
|
||||
int err = 0;
|
||||
iperf_err_t ret = IPERF_OK;
|
||||
struct sockaddr_storage dest_addr = { 0 };
|
||||
#if IPERF_V6
|
||||
struct sockaddr_in6 dest_addr6 = { 0 };
|
||||
#endif
|
||||
struct sockaddr_in dest_addr4 = { 0 };
|
||||
int opt = s_iperf_ctrl.cfg.tos;
|
||||
|
||||
IPERF_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), IPERF_FAIL, exit, TAG, "Ivalid AF types");
|
||||
|
||||
if (iperf_is_tcp_dual_client()) {
|
||||
xTaskCreate(iperf_tcp_dual_server_task, "dual_rx", IPERF_TRAFFIC_TASK_STACK, NULL, s_iperf_ctrl.cfg.traffic_task_priority, NULL);
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
#if IPERF_V6
|
||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
||||
client_socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_IPV6);
|
||||
IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||
setsockopt(client_socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt));
|
||||
|
||||
inet6_aton(s_iperf_ctrl.cfg.destination_ip6, &dest_addr6.sin6_addr);
|
||||
dest_addr6.sin6_family = AF_INET6;
|
||||
dest_addr6.sin6_port = htons(s_iperf_ctrl.cfg.dport);
|
||||
|
||||
err = connect(client_socket, (struct sockaddr *)&dest_addr6, sizeof(struct sockaddr_in6));
|
||||
IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to connect: errno %d", errno);
|
||||
IPERF_LOGI(TAG, "Successfully connected");
|
||||
memcpy(&dest_addr, &dest_addr6, sizeof(dest_addr6));
|
||||
} else
|
||||
#endif
|
||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
||||
client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||
setsockopt(client_socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt));
|
||||
|
||||
dest_addr4.sin_family = AF_INET;
|
||||
dest_addr4.sin_port = htons(s_iperf_ctrl.cfg.dport);
|
||||
dest_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.destination_ip4;
|
||||
err = connect(client_socket, (struct sockaddr *)&dest_addr4, sizeof(struct sockaddr_in));
|
||||
IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to connect: errno %d", errno);
|
||||
IPERF_LOGI(TAG, "Successfully connected");
|
||||
memcpy(&dest_addr, &dest_addr4, sizeof(dest_addr4));
|
||||
}
|
||||
|
||||
socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_TCP, s_iperf_ctrl.cfg.bw_lim);
|
||||
exit:
|
||||
if (client_socket != -1) {
|
||||
shutdown(client_socket, 0);
|
||||
close(client_socket);
|
||||
IPERF_LOGI(TAG, "TCP Socket client is closed.");
|
||||
}
|
||||
s_iperf_ctrl.finish = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static iperf_err_t IRAM_ATTR iperf_run_udp_server(void)
|
||||
{
|
||||
int listen_socket = -1;
|
||||
int opt = 1;
|
||||
int err = 0;
|
||||
iperf_err_t ret = IPERF_OK;
|
||||
struct timeval timeout = { 0 };
|
||||
struct sockaddr_storage listen_addr = { 0 };
|
||||
#if IPERF_V6
|
||||
struct sockaddr_in6 listen_addr6 = { 0 };
|
||||
#endif
|
||||
struct sockaddr_in listen_addr4 = { 0 };
|
||||
|
||||
IPERF_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), IPERF_FAIL, exit, TAG, "Ivalid AF types");
|
||||
|
||||
#if IPERF_V6
|
||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
||||
// The UDP server listen at the address "::", which means all addresses can be listened to.
|
||||
inet6_aton("::", &listen_addr6.sin6_addr);
|
||||
listen_addr6.sin6_family = AF_INET6;
|
||||
listen_addr6.sin6_port = htons(s_iperf_ctrl.cfg.sport);
|
||||
|
||||
listen_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
IPERF_GOTO_ON_FALSE((listen_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||
IPERF_LOGI(TAG, "Socket created");
|
||||
|
||||
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
|
||||
err = bind(listen_socket, (struct sockaddr *)&listen_addr6, sizeof(struct sockaddr_in6));
|
||||
IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to bind: errno %d", errno);
|
||||
IPERF_LOGI(TAG, "Socket bound, port %d", listen_addr6.sin6_port);
|
||||
|
||||
memcpy(&listen_addr, &listen_addr6, sizeof(listen_addr6));
|
||||
} else
|
||||
#endif
|
||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
||||
listen_addr4.sin_family = AF_INET;
|
||||
listen_addr4.sin_port = htons(s_iperf_ctrl.cfg.sport);
|
||||
listen_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.source_ip4;
|
||||
|
||||
listen_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
IPERF_GOTO_ON_FALSE((listen_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||
IPERF_LOGI(TAG, "Socket created");
|
||||
|
||||
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
|
||||
err = bind(listen_socket, (struct sockaddr *)&listen_addr4, sizeof(struct sockaddr_in));
|
||||
IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to bind: errno %d", errno);
|
||||
IPERF_LOGI(TAG, "Socket bound, port %d", listen_addr4.sin_port);
|
||||
memcpy(&listen_addr, &listen_addr4, sizeof(listen_addr4));
|
||||
}
|
||||
|
||||
timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
|
||||
setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
|
||||
socket_recv(listen_socket, listen_addr, IPERF_TRANS_TYPE_UDP);
|
||||
exit:
|
||||
if (listen_socket != -1) {
|
||||
shutdown(listen_socket, 0);
|
||||
close(listen_socket);
|
||||
}
|
||||
IPERF_LOGI(TAG, "Udp socket server is closed.");
|
||||
s_iperf_ctrl.finish = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static iperf_err_t iperf_run_udp_client(void)
|
||||
{
|
||||
int client_socket = -1;
|
||||
int opt = 1;
|
||||
iperf_err_t ret = IPERF_OK;
|
||||
struct sockaddr_storage dest_addr = { 0 };
|
||||
#if IPERF_V6
|
||||
struct sockaddr_in6 dest_addr6 = { 0 };
|
||||
#endif
|
||||
struct sockaddr_in dest_addr4 = { 0 };
|
||||
|
||||
IPERF_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), IPERF_FAIL, exit, TAG, "Ivalid AF types");
|
||||
|
||||
#if IPERF_V6
|
||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
||||
inet6_aton(s_iperf_ctrl.cfg.destination_ip6, &dest_addr6.sin6_addr);
|
||||
dest_addr6.sin6_family = AF_INET6;
|
||||
dest_addr6.sin6_port = htons(s_iperf_ctrl.cfg.dport);
|
||||
|
||||
client_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6);
|
||||
IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||
IPERF_LOGI(TAG, "Socket created, sending to %s:%d", s_iperf_ctrl.cfg.destination_ip6, s_iperf_ctrl.cfg.dport);
|
||||
|
||||
setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
opt = s_iperf_ctrl.cfg.tos;
|
||||
setsockopt(client_socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt));
|
||||
memcpy(&dest_addr, &dest_addr6, sizeof(dest_addr6));
|
||||
} else
|
||||
#endif
|
||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
||||
dest_addr4.sin_family = AF_INET;
|
||||
dest_addr4.sin_port = htons(s_iperf_ctrl.cfg.dport);
|
||||
dest_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.destination_ip4;
|
||||
|
||||
client_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||
IPERF_LOGI(TAG, "Socket created, sending to %d:%d", s_iperf_ctrl.cfg.destination_ip4, s_iperf_ctrl.cfg.dport);
|
||||
|
||||
setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
opt = s_iperf_ctrl.cfg.tos;
|
||||
setsockopt(client_socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt));
|
||||
memcpy(&dest_addr, &dest_addr4, sizeof(dest_addr4));
|
||||
}
|
||||
|
||||
socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_UDP, s_iperf_ctrl.cfg.bw_lim);
|
||||
exit:
|
||||
if (client_socket != -1) {
|
||||
shutdown(client_socket, 0);
|
||||
close(client_socket);
|
||||
}
|
||||
s_iperf_ctrl.finish = true;
|
||||
IPERF_LOGI(TAG, "UDP Socket client is closed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iperf_task_traffic(void *arg)
|
||||
{
|
||||
if (iperf_is_udp_client()) {
|
||||
iperf_run_udp_client();
|
||||
} else if (iperf_is_udp_server()) {
|
||||
iperf_run_udp_server();
|
||||
} else if (iperf_is_tcp_client()) {
|
||||
iperf_run_tcp_client();
|
||||
} else {
|
||||
iperf_run_tcp_server();
|
||||
}
|
||||
|
||||
if (s_iperf_ctrl.buffer) {
|
||||
vPortFree(s_iperf_ctrl.buffer);
|
||||
s_iperf_ctrl.buffer = NULL;
|
||||
}
|
||||
printf("iperf exit\r\n");
|
||||
s_iperf_is_running = false;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static uint32_t iperf_get_buffer_len(void)
|
||||
{
|
||||
if (iperf_is_udp_client()) {
|
||||
return (s_iperf_ctrl.cfg.len_buf == 0 ? IPERF_UDP_TX_LEN : s_iperf_ctrl.cfg.len_buf);
|
||||
} else if (iperf_is_udp_server()) {
|
||||
return IPERF_UDP_RX_LEN;
|
||||
} else if (iperf_is_tcp_client()) {
|
||||
return (s_iperf_ctrl.cfg.len_buf == 0 ? IPERF_TCP_TX_LEN : s_iperf_ctrl.cfg.len_buf);
|
||||
} else {
|
||||
return (s_iperf_ctrl.cfg.len_buf == 0 ? IPERF_TCP_RX_LEN : s_iperf_ctrl.cfg.len_buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void net_iperf_print_header(iperf_cfg_t *cfg)
|
||||
{
|
||||
printf("------------------------------------------------------------\r\n");
|
||||
if (iperf_is_udp_server()) {
|
||||
printf("Server listening on UDP port %d\r\n",
|
||||
cfg->sport);
|
||||
} else if (iperf_is_tcp_server()) {
|
||||
printf("Server listening on TCP port %d\r\n",
|
||||
cfg->sport);
|
||||
} else if (iperf_is_udp_client()) {
|
||||
printf("Client connecting to %s, UDP port %d\r\n"
|
||||
"Sending %d byte datagrams\r\n",
|
||||
inet_ntoa(cfg->destination_ip4),
|
||||
cfg->dport, cfg->num_bytes);
|
||||
} else if (iperf_is_tcp_client()) {
|
||||
printf("Client connecting to %s, TCP port %d\r\n",
|
||||
inet_ntoa(cfg->destination_ip4), cfg->dport);
|
||||
}
|
||||
printf("------------------------------------------------------------\r\n");
|
||||
}
|
||||
|
||||
iperf_err_t iperf_start(iperf_cfg_t *cfg)
|
||||
{
|
||||
BaseType_t ret;
|
||||
|
||||
if (!cfg) {
|
||||
return IPERF_FAIL;
|
||||
}
|
||||
|
||||
if (s_iperf_is_running) {
|
||||
IPERF_LOGW(TAG, "iperf is running");
|
||||
printf("iperf is running\r\n");
|
||||
return IPERF_FAIL;
|
||||
}
|
||||
|
||||
memset(&s_iperf_ctrl, 0, sizeof(s_iperf_ctrl));
|
||||
memcpy(&s_iperf_ctrl.cfg, cfg, sizeof(*cfg));
|
||||
s_iperf_is_running = true;
|
||||
s_iperf_ctrl.finish = false;
|
||||
s_iperf_ctrl.buffer_len = iperf_get_buffer_len();
|
||||
s_iperf_ctrl.buffer = (uint8_t *)pvPortMalloc(s_iperf_ctrl.buffer_len);
|
||||
if (!s_iperf_ctrl.buffer) {
|
||||
IPERF_LOGE(TAG, "create buffer: not enough memory");
|
||||
return IPERF_FAIL;
|
||||
}
|
||||
memset(s_iperf_ctrl.buffer, 0, s_iperf_ctrl.buffer_len);
|
||||
ret = xTaskCreatePinnedToCore(iperf_task_traffic, IPERF_TRAFFIC_TASK_NAME, IPERF_TRAFFIC_TASK_STACK, NULL, s_iperf_ctrl.cfg.traffic_task_priority, NULL, portNUM_PROCESSORS - 1);
|
||||
if (ret != pdPASS) {
|
||||
IPERF_LOGE(TAG, "create task %s failed", IPERF_TRAFFIC_TASK_NAME);
|
||||
vPortFree(s_iperf_ctrl.buffer);
|
||||
s_iperf_ctrl.buffer = NULL;
|
||||
return IPERF_FAIL;
|
||||
}
|
||||
net_iperf_print_header(cfg);
|
||||
return IPERF_OK;
|
||||
}
|
||||
|
||||
iperf_err_t iperf_stop(void)
|
||||
{
|
||||
if (s_iperf_is_running) {
|
||||
s_iperf_ctrl.finish = true;
|
||||
}
|
||||
|
||||
return IPERF_OK;
|
||||
}
|
||||
82
tests/hpmicro/src/iperf/iperf.h
Normal file
82
tests/hpmicro/src/iperf/iperf.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* Iperf Example - iperf declaration
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#ifndef __IPERF_H_
|
||||
#define __IPERF_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define IPERF_IP_TYPE_IPV4 0
|
||||
#define IPERF_IP_TYPE_IPV6 1
|
||||
#define IPERF_TRANS_TYPE_TCP 0
|
||||
#define IPERF_TRANS_TYPE_UDP 1
|
||||
|
||||
#define IPERF_FLAG_SET(cfg, flag) ((cfg) |= (flag))
|
||||
#define IPERF_FLAG_CLR(cfg, flag) ((cfg) &= (~(flag)))
|
||||
|
||||
#define IPERF_FLAG_CLIENT (1)
|
||||
#define IPERF_FLAG_SERVER (1 << 1)
|
||||
#define IPERF_FLAG_TCP (1 << 2)
|
||||
#define IPERF_FLAG_UDP (1 << 3)
|
||||
#define IPERF_FLAG_DUAL (1 << 4)
|
||||
|
||||
#define IPERF_DEFAULT_PORT 5001
|
||||
#define IPERF_DEFAULT_INTERVAL 1
|
||||
#define IPERF_DEFAULT_TIME 10
|
||||
#define IPERF_DEFAULT_NO_BW_LIMIT -1
|
||||
|
||||
#define IPERF_TRAFFIC_TASK_NAME "iperf_traffic"
|
||||
#define IPERF_TRAFFIC_TASK_PRIORITY 10
|
||||
#define IPERF_TRAFFIC_TASK_STACK 2048
|
||||
#define IPERF_REPORT_TASK_NAME "iperf_report"
|
||||
#define IPERF_REPORT_TASK_STACK 2048
|
||||
|
||||
#define IPERF_UDP_TX_LEN (1470)
|
||||
#define IPERF_UDP_RX_LEN (1470)
|
||||
#define IPERF_TCP_TX_LEN (8 << 10)
|
||||
#define IPERF_TCP_RX_LEN (8 << 10)
|
||||
|
||||
#define IPERF_MAX_DELAY 64
|
||||
|
||||
#define IPERF_SOCKET_RX_TIMEOUT 10
|
||||
#define IPERF_SOCKET_ACCEPT_TIMEOUT 5
|
||||
|
||||
typedef struct {
|
||||
uint32_t flag;
|
||||
union {
|
||||
uint32_t destination_ip4;
|
||||
char *destination_ip6;
|
||||
};
|
||||
union {
|
||||
uint32_t source_ip4;
|
||||
char *source_ip6;
|
||||
};
|
||||
uint8_t type;
|
||||
uint16_t dport;
|
||||
uint16_t sport;
|
||||
uint32_t interval;
|
||||
uint32_t time;
|
||||
uint16_t len_buf;
|
||||
int32_t bw_lim;
|
||||
uint8_t tos;
|
||||
uint8_t traffic_task_priority;
|
||||
uint32_t num_bytes;
|
||||
} iperf_cfg_t;
|
||||
|
||||
int iperf_start(iperf_cfg_t *cfg);
|
||||
|
||||
int iperf_stop(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
115
tests/hpmicro/src/iperf/iperf_cli.c
Normal file
115
tests/hpmicro/src/iperf/iperf_cli.c
Normal file
@@ -0,0 +1,115 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <utils_getopt.h>
|
||||
#include <iperf.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
|
||||
#define NL "\r\n"
|
||||
|
||||
static void iperf_cmd(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
getopt_env_t opt_env;
|
||||
int o_c = 0, o_s = 0, o_u = 0, o_a = 0;
|
||||
int o_p = IPERF_DEFAULT_PORT, o_l = 0, o_i = IPERF_DEFAULT_INTERVAL, o_t = IPERF_DEFAULT_TIME, o_b = IPERF_DEFAULT_NO_BW_LIMIT, o_S = 0, o_n = 0;
|
||||
int o_d = 0;
|
||||
int o_P = IPERF_TRAFFIC_TASK_PRIORITY;
|
||||
uint32_t dst_addr = 0;
|
||||
|
||||
iperf_cfg_t cfg;
|
||||
|
||||
utils_getopt_init(&opt_env, 0);
|
||||
while ((opt = utils_getopt(&opt_env, argc, argv, ":c:sup:l:i:t:b:S:n:P:ad")) != -1) {
|
||||
#define ARG_READ(v) v = atoi(opt_env.optarg)
|
||||
switch (opt) {
|
||||
case 'c':
|
||||
++o_c;
|
||||
dst_addr = ipaddr_addr(opt_env.optarg);
|
||||
break;
|
||||
case 's': ++o_s; break;
|
||||
case 'u': ++o_u; break;
|
||||
case 'p': ARG_READ(o_p); break;
|
||||
case 'l': ARG_READ(o_l); break;
|
||||
case 'i': ARG_READ(o_i); break;
|
||||
case 't': ARG_READ(o_t); break;
|
||||
case 'b': ARG_READ(o_b); break;
|
||||
case 'S': ARG_READ(o_S); break;
|
||||
case 'n': ARG_READ(o_n); break;
|
||||
case 'P': ARG_READ(o_P); break;
|
||||
case 'd': ++o_d; break;
|
||||
case 'a': ++o_a; break;
|
||||
}
|
||||
#undef ARG_READ
|
||||
}
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.type = IPERF_IP_TYPE_IPV4;
|
||||
|
||||
if (o_a) {
|
||||
iperf_stop();
|
||||
return;
|
||||
}
|
||||
if (!((o_c && !o_s) || (!o_c && o_s))) {
|
||||
printf("client/server required" NL);
|
||||
return;
|
||||
}
|
||||
if (o_c) {
|
||||
cfg.destination_ip4 = dst_addr;
|
||||
cfg.flag |= IPERF_FLAG_CLIENT;
|
||||
} else {
|
||||
cfg.flag |= IPERF_FLAG_SERVER;
|
||||
}
|
||||
if (o_u) {
|
||||
cfg.flag |= IPERF_FLAG_UDP;
|
||||
} else {
|
||||
cfg.flag |= IPERF_FLAG_TCP;
|
||||
}
|
||||
|
||||
if (o_c && !o_u && o_d) {
|
||||
cfg.flag |= IPERF_FLAG_DUAL;
|
||||
}
|
||||
|
||||
cfg.len_buf = o_l;
|
||||
cfg.sport = o_p;
|
||||
cfg.dport = o_p;
|
||||
cfg.interval = o_i;
|
||||
cfg.time = o_t;
|
||||
if (cfg.time < cfg.interval) {
|
||||
cfg.time = cfg.interval;
|
||||
}
|
||||
cfg.bw_lim = o_b;
|
||||
cfg.tos = o_S;
|
||||
cfg.num_bytes = o_n * 1000 * 1000;
|
||||
if (cfg.bw_lim <= 0) {
|
||||
cfg.bw_lim = IPERF_DEFAULT_NO_BW_LIMIT;
|
||||
}
|
||||
cfg.traffic_task_priority = o_P;
|
||||
|
||||
iperf_start(&cfg);
|
||||
}
|
||||
|
||||
#include <shell.h>
|
||||
#define ML(s) s NL
|
||||
#define IPERF_USAGE \
|
||||
ML("iperf") \
|
||||
ML(" -c server_addr: run in client mode") \
|
||||
ML(" -s: run in server mode") \
|
||||
ML(" -u: UDP") \
|
||||
ML(" -p port: specify port") \
|
||||
ML(" -l length: set read/write buffer size") \
|
||||
ML(" -i interval: seconds between bandwidth reports") \
|
||||
ML(" -t time: time in seconds to run") \
|
||||
ML(" -b bandwith: bandwidth to send in Mbps") \
|
||||
ML(" -S tos: TOS") \
|
||||
ML(" -n MB: number of MB to send/recv") \
|
||||
ML(" -P priority: traffic task priority") \
|
||||
ML(" -d: dual mode") \
|
||||
ML(" -a: abort running iperf") \
|
||||
|
||||
#if 0
|
||||
const static struct cli_command iperf_cmds[] STATIC_CLI_CMD_ATTRIBUTE = {
|
||||
{"iperf", IPERF_USAGE, iperf_cmd},
|
||||
};
|
||||
#endif
|
||||
CSH_CMD_EXPORT_ALIAS(iperf_cmd, iperf, iperf command);
|
||||
|
||||
377
tests/hpmicro/src/iperf/utils_getopt.c
Normal file
377
tests/hpmicro/src/iperf/utils_getopt.c
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* This file is derived from musl v1.2.0.
|
||||
* Modifications are applied.
|
||||
* Copyright (C) Bouffalo Lab 2016-2020
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright © 2005-2020 Rich Felker, et al.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <utils_getopt.h>
|
||||
|
||||
int utils_getopt_init(getopt_env_t *env, int opterr)
|
||||
{
|
||||
if (!env) {
|
||||
return -1;
|
||||
}
|
||||
env->optarg = NULL;
|
||||
env->optind = 1;
|
||||
env->opterr = opterr;
|
||||
env->optopt = 0;
|
||||
env->__optpos = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NEWLINE "\r\n"
|
||||
|
||||
int utils_getopt(getopt_env_t *env, int argc, char *const argv[], const char *optstring)
|
||||
{
|
||||
int i;
|
||||
char c, d;
|
||||
char *optchar;
|
||||
|
||||
if (!env) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (env->optind >= argc || !argv[env->optind])
|
||||
return -1;
|
||||
|
||||
if (argv[env->optind][0] != '-') {
|
||||
if (optstring[0] == '-') {
|
||||
env->optarg = argv[env->optind++];
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!argv[env->optind][1])
|
||||
return -1;
|
||||
|
||||
if (argv[env->optind][1] == '-' && !argv[env->optind][2])
|
||||
return env->optind++, -1;
|
||||
|
||||
if (!env->__optpos)
|
||||
env->__optpos++;
|
||||
c = argv[env->optind][env->__optpos];
|
||||
optchar = argv[env->optind] + env->__optpos;
|
||||
env->__optpos += !!c;
|
||||
|
||||
if (!argv[env->optind][env->__optpos]) {
|
||||
env->optind++;
|
||||
env->__optpos = 0;
|
||||
}
|
||||
|
||||
if (optstring[0] == '-' || optstring[0] == '+')
|
||||
optstring++;
|
||||
|
||||
i = 0;
|
||||
do
|
||||
d = optstring[i++];
|
||||
while (d && d != c);
|
||||
|
||||
if (d != c || c == ':') {
|
||||
env->optopt = c;
|
||||
if (optstring[0] != ':' && env->opterr)
|
||||
printf("%s: unrecognized option: %c" NEWLINE, argv[0], *optchar);
|
||||
return '?';
|
||||
}
|
||||
if (optstring[i] == ':') {
|
||||
env->optarg = 0;
|
||||
if (optstring[i + 1] != ':' || env->__optpos) {
|
||||
env->optarg = argv[env->optind++] + env->__optpos;
|
||||
env->__optpos = 0;
|
||||
}
|
||||
if (env->optind > argc) {
|
||||
env->optopt = c;
|
||||
if (optstring[0] == ':')
|
||||
return ':';
|
||||
if (env->opterr) {
|
||||
printf("%s: option requires an argument: %c" NEWLINE, argv[0], *optchar);
|
||||
}
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static int params_filter(char **params, uint32_t *r)
|
||||
{
|
||||
char *p;
|
||||
uint32_t result = 0;
|
||||
uint8_t base = 0;
|
||||
|
||||
p = *params;
|
||||
|
||||
if ((*p == '0') && ((*(p + 1) == 'x') || (*(p + 1) == 'X'))) {
|
||||
p = p + 2;
|
||||
base = 16;
|
||||
|
||||
} else {
|
||||
base = 10;
|
||||
}
|
||||
|
||||
while (*p) {
|
||||
result *= base;
|
||||
if (*p >= '0' && *p <= '9')
|
||||
result += *p - '0';
|
||||
else if (base == 10)
|
||||
return -1;
|
||||
|
||||
if (base == 16) {
|
||||
if (*p >= 'a' && *p <= 'f')
|
||||
result += *p - 'a' + 10;
|
||||
else if (*p >= 'A' && *p <= 'F')
|
||||
result += *p - 'A' + 10;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
*r = result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_bytearray_from_string(char **params, uint8_t *result, int array_size)
|
||||
{
|
||||
int i = 0;
|
||||
char rand[3];
|
||||
|
||||
for (i = 0; i < array_size; i++) {
|
||||
memcpy(rand, *params, 2);
|
||||
rand[2] = '\0';
|
||||
result[i] = strtol(rand, NULL, 16);
|
||||
*params = *params + 2;
|
||||
}
|
||||
}
|
||||
|
||||
void get_uint8_from_string(char **params, uint8_t *result)
|
||||
{
|
||||
uint32_t p = 0;
|
||||
int state = 0;
|
||||
|
||||
state = params_filter(params, &p);
|
||||
if (!state) {
|
||||
*result = p & 0xff;
|
||||
} else
|
||||
*result = 0;
|
||||
}
|
||||
|
||||
void get_uint16_from_string(char **params, uint16_t *result)
|
||||
{
|
||||
uint32_t p = 0;
|
||||
int state = 0;
|
||||
|
||||
state = params_filter(params, &p);
|
||||
if (!state) {
|
||||
*result = p & 0xffff;
|
||||
} else
|
||||
*result = 0;
|
||||
}
|
||||
|
||||
void get_uint32_from_string(char **params, uint32_t *result)
|
||||
{
|
||||
uint32_t p = 0;
|
||||
int state = 0;
|
||||
|
||||
state = params_filter(params, &p);
|
||||
if (!state) {
|
||||
*result = p;
|
||||
} else
|
||||
*result = 0;
|
||||
}
|
||||
|
||||
void utils_parse_number(const char *str, char sep, uint8_t *buf, int buflen, int base)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < buflen; i++) {
|
||||
buf[i] = (uint8_t)strtol(str, NULL, base);
|
||||
str = strchr(str, sep);
|
||||
if (str == NULL || *str == '\0') {
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
void utils_parse_number_adv(const char *str, char sep, uint8_t *buf, int buflen, int base, int *count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < buflen; i++) {
|
||||
buf[i] = (uint8_t)strtol(str, NULL, base);
|
||||
str = strchr(str, sep);
|
||||
if (str == NULL || *str == '\0') {
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
*count = (i + 1);
|
||||
}
|
||||
|
||||
unsigned long long convert_arrayToU64(uint8_t *inputArray)
|
||||
{
|
||||
unsigned long long result = 0;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
result <<= 8;
|
||||
result |= (unsigned long long)inputArray[7 - i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void convert_u64ToArray(unsigned long long inputU64, uint8_t result[8])
|
||||
{
|
||||
for (int i = 0; i < 8; i++) {
|
||||
result[i] = inputU64 >> (i * 8);
|
||||
}
|
||||
}
|
||||
|
||||
void utils_memdrain8(void *src, size_t len)
|
||||
{
|
||||
volatile uint8_t *s = (uint8_t *)src;
|
||||
uint8_t tmp;
|
||||
|
||||
while (len--) {
|
||||
tmp = *s++;
|
||||
}
|
||||
|
||||
(void)tmp;
|
||||
}
|
||||
|
||||
void utils_memdrain16(void *src, size_t len)
|
||||
{
|
||||
volatile uint16_t *s = (uint16_t *)src;
|
||||
uint16_t tmp;
|
||||
|
||||
len >>= 1; //convert to half words
|
||||
|
||||
while (len--) {
|
||||
tmp = *s++;
|
||||
}
|
||||
|
||||
(void)tmp;
|
||||
}
|
||||
|
||||
void utils_memdrain32(void *src, size_t len)
|
||||
{
|
||||
volatile uint32_t *s = (uint32_t *)src;
|
||||
uint32_t tmp;
|
||||
|
||||
len >>= 2; //convert to words
|
||||
|
||||
while (len--) {
|
||||
tmp = *s++;
|
||||
}
|
||||
|
||||
(void)tmp;
|
||||
}
|
||||
|
||||
void utils_memdrain64(void *src, size_t len)
|
||||
{
|
||||
volatile uint64_t *s = (uint64_t *)src;
|
||||
uint64_t tmp;
|
||||
|
||||
len >>= 3; //convert to two words
|
||||
|
||||
while (len--) {
|
||||
tmp = *s++;
|
||||
}
|
||||
|
||||
(void)tmp;
|
||||
}
|
||||
|
||||
void *utils_memdrain8_with_check(void *src, size_t len, uint8_t seq)
|
||||
{
|
||||
volatile uint8_t *s = (uint8_t *)src;
|
||||
uint8_t tmp;
|
||||
|
||||
(void)tmp;
|
||||
|
||||
while (len--) {
|
||||
tmp = *s++;
|
||||
if ((seq++) != tmp) {
|
||||
return (uint8_t *)s - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *utils_memdrain16_with_check(void *src, size_t len, uint16_t seq)
|
||||
{
|
||||
volatile uint16_t *s = (uint16_t *)src;
|
||||
uint16_t tmp;
|
||||
(void)tmp;
|
||||
|
||||
len >>= 1; //convert to half words
|
||||
|
||||
while (len--) {
|
||||
tmp = *s++;
|
||||
if ((seq++) != tmp) {
|
||||
return (uint16_t *)s - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *utils_memdrain32_with_check(void *src, size_t len, uint32_t seq)
|
||||
{
|
||||
volatile uint32_t *s = (uint32_t *)src;
|
||||
uint32_t tmp;
|
||||
(void)tmp;
|
||||
|
||||
len >>= 2; //convert to words
|
||||
|
||||
while (len--) {
|
||||
tmp = *s++;
|
||||
if ((seq++) != tmp) {
|
||||
return (uint32_t *)s - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *utils_memdrain64_with_check(void *src, size_t len, uint64_t seq)
|
||||
{
|
||||
volatile uint64_t *s = (uint64_t *)src;
|
||||
uint64_t tmp;
|
||||
(void)tmp;
|
||||
|
||||
len >>= 3; //convert to two words
|
||||
|
||||
while (len--) {
|
||||
tmp = *s++;
|
||||
if ((seq++) != tmp) {
|
||||
return (uint64_t *)s - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
107
tests/hpmicro/src/iperf/utils_getopt.h
Normal file
107
tests/hpmicro/src/iperf/utils_getopt.h
Normal file
@@ -0,0 +1,107 @@
|
||||
#ifndef __GETOPT_H__
|
||||
#define __GETOPT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Parameters needed to parse the command line
|
||||
*
|
||||
*/
|
||||
typedef struct getopt_env {
|
||||
char *optarg; /*!< if the option accepts parameters, then optarg point to the option parameter*/
|
||||
int optind; /*!< current index of argv*/
|
||||
int opterr; /*!< non-zero enable error message output, while 0,no error message output*/
|
||||
int optopt; /*!< contain unrecognized option character*/
|
||||
int __optpos;
|
||||
} getopt_env_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize struct getopt_env
|
||||
*
|
||||
* @param env pointer to struct getopt_env
|
||||
* @param opterr set error message output method
|
||||
*
|
||||
* @return
|
||||
* - 0: success
|
||||
* - -1: fail
|
||||
*/
|
||||
int utils_getopt_init(getopt_env_t *env, int opterr);
|
||||
|
||||
/**
|
||||
* @brief Parses the command-line arguments
|
||||
*
|
||||
* @param env pointer to struct getopt_env
|
||||
* @param argc the argument count
|
||||
* @param argv the argument array
|
||||
*
|
||||
* @return
|
||||
* - option character : an option was successfully found
|
||||
* - -1 : all command-line options have been parsed
|
||||
* - '?' : option character was not in optstring
|
||||
* - ':' or '?' : If utils_getopt() encounters an option with a missing argument, then the return value depends on the first character in optstring: if it is ':', then ':' is returned; otherwise '?' is returned
|
||||
*
|
||||
* @note Example
|
||||
* @code
|
||||
*
|
||||
* #include <utils_getopt.h>
|
||||
* #include <stdio.h>
|
||||
*
|
||||
* void cmd(char *buf, int len, int argc, char **argv)
|
||||
* {
|
||||
* int opt;
|
||||
getopt_env_t getopt_env;
|
||||
utils_getopt_init(&getopt_env, 0);
|
||||
* //put ':' in the starting of the string so that program can distinguish between '?' and ':'
|
||||
* while ((opt = utils_getopt(&getopt_env, argc, argv, ":if:lr")) != -1) {
|
||||
* switch(opt)
|
||||
* {
|
||||
* case 'i':
|
||||
* case 'l':
|
||||
* case 'r':
|
||||
* printf("option: %c\r\n", opt);
|
||||
* break;
|
||||
* case 'f':
|
||||
* printf("filename: %s\r\n", getopt_env.optarg);
|
||||
* break;
|
||||
* case ':':
|
||||
printf("%s: %c requires an argument\r\n", *argv, getopt_env.optopt);
|
||||
* break;
|
||||
* case '?':
|
||||
* printf("unknow option: %c\r\n", getopt_env.optopt);
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
* //optind is for the extra arguments which are not parsed
|
||||
* for(; getopt_env.optind < argc; getopt_env.optind++){
|
||||
* printf("extra arguments: %s\r\n", argv[getopt_env.optind]);
|
||||
* }
|
||||
*
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
int utils_getopt(getopt_env_t *env, int argc, char *const argv[], const char *optstring);
|
||||
|
||||
void get_bytearray_from_string(char **params, uint8_t *result, int array_size);
|
||||
void get_uint8_from_string(char **params, uint8_t *result);
|
||||
void get_uint16_from_string(char **params, uint16_t *result);
|
||||
void get_uint32_from_string(char **params, uint32_t *result);
|
||||
void utils_parse_number(const char *str, char sep, uint8_t *buf, int buflen, int base);
|
||||
void utils_parse_number_adv(const char *str, char sep, uint8_t *buf, int buflen, int base, int *count);
|
||||
unsigned long long convert_arrayToU64(uint8_t *inputArray);
|
||||
void convert_u64ToArray(unsigned long long inputU64, uint8_t result[8]);
|
||||
void utils_memdrain8(void *src, size_t len);
|
||||
void utils_memdrain16(void *src, size_t len);
|
||||
void utils_memdrain32(void *src, size_t len);
|
||||
void utils_memdrain64(void *src, size_t len);
|
||||
void *utils_memdrain8_with_check(void *src, size_t len, uint8_t seq);
|
||||
void *utils_memdrain16_with_check(void *src, size_t len, uint16_t seq);
|
||||
void *utils_memdrain32_with_check(void *src, size_t len, uint32_t seq);
|
||||
void *utils_memdrain64_with_check(void *src, size_t len, uint64_t seq);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GETOPT_H__ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user