mirror of
https://github.com/hathach/tinyusb.git
synced 2026-03-04 06:37:15 +00:00
Merge pull request #3348 from hathach/fix-more-warnings
fix more alerts
This commit is contained in:
@ -11,7 +11,8 @@
|
||||
//-V:memcpy:2547 [MISRA-C-17.7] The return value of non-void function 'memcpy' should be used.
|
||||
//-V:memmove:2547 [MISRA-C-17.7] The return value of non-void function 'memmove' should be used.
|
||||
//-V:printf:2547 [MISRA-C-17.7]
|
||||
//-V::2584::{gintsts} dwc2
|
||||
//-V::2584::{gintsts} dwc2 interrupt handler
|
||||
//-V::2584::{hcint} dwc2 interrupt handler
|
||||
//-V::2600 [MISRA-C-21.6] The function with the 'printf' name should not be used.
|
||||
//+V2614 DISABLE_LENGHT_LIMIT_CHECK:YES
|
||||
//-V:memcpy:2628 Pointer arguments to the 'memcpy' function should be pointers to qualified or unqualified versions of compatible types.
|
||||
|
||||
219
AGENTS.md
219
AGENTS.md
@ -21,11 +21,220 @@
|
||||
3. Run unit tests relevant to touched modules; add fuzz/HIL coverage when modifying parsers or protocol state machines.
|
||||
|
||||
## Copilot Agent Notes (`.github/copilot-instructions.md`)
|
||||
- Treat this handbook as authoritative before searching or executing speculative shell commands; unexpected conflicts justify additional probing.
|
||||
- Respect build timing guidance: allow ≥5 minutes for single example builds and ≥30 minutes for bulk runs; never cancel dependency fetches or builds mid-flight.
|
||||
- Support optional switches: `-DRHPORT_DEVICE[_SPEED]`, logging toggles (`LOG=2`, `LOGGER=rtt`), and board selection helpers from `tools/get_deps.py`.
|
||||
- Flashing shortcuts: `ninja <target>-jlink|openocd|uf2` or `make BOARD=<board> flash-{jlink,openocd}`; list Ninja targets with `ninja -t targets`.
|
||||
- Keep Ceedling installed (`sudo gem install ceedling`) and available for per-test or full suite runs triggered from `test/unit-test`.
|
||||
# TinyUSB
|
||||
TinyUSB is an open-source cross-platform USB Host/Device stack for embedded systems, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events deferred to non-ISR task functions.
|
||||
|
||||
Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.
|
||||
|
||||
### Working Effectively
|
||||
|
||||
#### Bootstrap and Build Setup
|
||||
- Install ARM GCC toolchain: `sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi`
|
||||
- Fetch core dependencies: `python3 tools/get_deps.py` -- takes <1 second. NEVER CANCEL.
|
||||
- For specific board families: `python3 tools/get_deps.py FAMILY_NAME` (e.g., rp2040, stm32f4)
|
||||
- Dependencies are cached in `lib/` and `hw/mcu/` directories
|
||||
|
||||
#### Build Examples
|
||||
Choose ONE of these approaches:
|
||||
|
||||
**Option 1: Individual Example with CMake (RECOMMENDED)**
|
||||
```bash
|
||||
cd examples/device/cdc_msc
|
||||
mkdir -p build && cd build
|
||||
cmake -DBOARD=raspberry_pi_pico -DCMAKE_BUILD_TYPE=MinSizeRel ..
|
||||
cmake --build . -j4
|
||||
```
|
||||
-- takes 1-2 seconds. NEVER CANCEL. Set timeout to 5+ minutes.
|
||||
|
||||
**CMake with Ninja (Alternative)**
|
||||
```bash
|
||||
cd examples/device/cdc_msc
|
||||
mkdir build && cd build
|
||||
cmake -G Ninja -DBOARD=raspberry_pi_pico ..
|
||||
ninja
|
||||
```
|
||||
|
||||
**Option 2: Individual Example with Make**
|
||||
```bash
|
||||
cd examples/device/cdc_msc
|
||||
make BOARD=raspberry_pi_pico all
|
||||
```
|
||||
-- takes 2-3 seconds. NEVER CANCEL. Set timeout to 5+ minutes.
|
||||
|
||||
**Option 3: All Examples for a Board**
|
||||
```bash
|
||||
python3 tools/build.py -b BOARD_NAME
|
||||
```
|
||||
-- takes 15-20 seconds, may have some objcopy failures that are non-critical. NEVER CANCEL. Set timeout to 30+ minutes.
|
||||
|
||||
#### Build Options
|
||||
- **Debug build**:
|
||||
- CMake: `-DCMAKE_BUILD_TYPE=Debug`
|
||||
- Make: `DEBUG=1`
|
||||
- **With logging**:
|
||||
- CMake: `-DLOG=2`
|
||||
- Make: `LOG=2`
|
||||
- **With RTT logger**:
|
||||
- CMake: `-DLOG=2 -DLOGGER=rtt`
|
||||
- Make: `LOG=2 LOGGER=rtt`
|
||||
- **RootHub port selection**:
|
||||
- CMake: `-DRHPORT_DEVICE=1`
|
||||
- Make: `RHPORT_DEVICE=1`
|
||||
- **Port speed**:
|
||||
- CMake: `-DRHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED`
|
||||
- Make: `RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED`
|
||||
|
||||
#### Flashing and Deployment
|
||||
- **Flash with JLink**:
|
||||
- CMake: `ninja cdc_msc-jlink`
|
||||
- Make: `make BOARD=raspberry_pi_pico flash-jlink`
|
||||
- **Flash with OpenOCD**:
|
||||
- CMake: `ninja cdc_msc-openocd`
|
||||
- Make: `make BOARD=raspberry_pi_pico flash-openocd`
|
||||
- **Generate UF2**:
|
||||
- CMake: `ninja cdc_msc-uf2`
|
||||
- Make: `make BOARD=raspberry_pi_pico all uf2`
|
||||
- **List all targets** (CMake/Ninja): `ninja -t targets`
|
||||
|
||||
#### Unit Testing
|
||||
- Install Ceedling: `sudo gem install ceedling`
|
||||
- Run all unit tests: `cd test/unit-test && ceedling` or `cd test/unit-test && ceedling test:all` -- takes 4 seconds. NEVER CANCEL. Set timeout to 10+ minutes.
|
||||
- Run specific test: `cd test/unit-test && ceedling test:test_fifo`
|
||||
- Tests use Unity framework with CMock for mocking
|
||||
|
||||
#### Documentation
|
||||
- Install requirements: `pip install -r docs/requirements.txt`
|
||||
- Build docs: `cd docs && sphinx-build -b html . _build` -- takes 2-3 seconds. NEVER CANCEL. Set timeout to 10+ minutes.
|
||||
|
||||
#### Code Quality and Validation
|
||||
- Format code: `clang-format -i path/to/file.c` (uses `.clang-format` config)
|
||||
- Check spelling: `pip install codespell && codespell` (uses `.codespellrc` config)
|
||||
- Pre-commit hooks validate unit tests and code quality automatically
|
||||
|
||||
#### Static Analysis with PVS-Studio
|
||||
- **Analyze whole project**:
|
||||
```bash
|
||||
pvs-studio-analyzer analyze -f examples/cmake-build-raspberry_pi_pico/compile_commands.json -R .PVS-Studio/.pvsconfig -o pvs-report.log -j12 --dump-files --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser
|
||||
```
|
||||
- **Analyze specific source files**:
|
||||
```bash
|
||||
pvs-studio-analyzer analyze -f examples/cmake-build-raspberry_pi_pico/compile_commands.json -R .PVS-Studio/.pvsconfig -S path/to/file.c -o pvs-report.log -j12 --dump-files --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser
|
||||
```
|
||||
- **Multiple specific files**:
|
||||
```bash
|
||||
pvs-studio-analyzer analyze -f examples/cmake-build-raspberry_pi_pico/compile_commands.json -R .PVS-Studio/.pvsconfig -S src/file1.c -S src/file2.c -o pvs-report.log -j12 --dump-files --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser
|
||||
```
|
||||
- Requires `compile_commands.json` in the build directory (generated by CMake with `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON`)
|
||||
- Use `-f` option to specify path to `compile_commands.json`
|
||||
- Use `-R .PVS-Studio/.pvsconfig` to specify rule configuration file
|
||||
- Use `-j12` for parallel analysis with 12 threads
|
||||
- `--dump-files` saves preprocessed files for debugging
|
||||
- `--misra-c-version 2023` enables MISRA C:2023 checks
|
||||
- `--misra-cpp-version 2008` enables MISRA C++:2008 checks
|
||||
- `--use-old-parser` uses legacy parser for compatibility
|
||||
- Analysis takes ~10-30 seconds depending on project size. Set timeout to 5+ minutes.
|
||||
- View results: `plog-converter -a GA:1,2 -t errorfile pvs-report.log` or open in PVS-Studio GUI
|
||||
|
||||
### Validation
|
||||
|
||||
#### ALWAYS Run These After Making Changes
|
||||
1. **Pre-commit validation** (RECOMMENDED): `pre-commit run --all-files`
|
||||
- Install pre-commit: `pip install pre-commit && pre-commit install`
|
||||
- Runs all quality checks, unit tests, spell checking, and formatting
|
||||
- Takes 10-15 seconds. NEVER CANCEL. Set timeout to 15+ minutes.
|
||||
2. **Build validation**: Build at least one example that exercises your changes
|
||||
```bash
|
||||
cd examples/device/cdc_msc
|
||||
make BOARD=raspberry_pi_pico all
|
||||
```
|
||||
|
||||
#### Manual Testing Scenarios
|
||||
- **Device examples**: Cannot be fully tested without real hardware, but must build successfully
|
||||
- **Unit tests**: Exercise core stack functionality - ALL tests must pass
|
||||
- **Build system**: Must be able to build examples for multiple board families
|
||||
|
||||
#### Board Selection for Testing
|
||||
- **STM32F4**: `stm32f407disco` - no external SDK required, good for testing
|
||||
- **RP2040**: `raspberry_pi_pico` - requires Pico SDK, commonly used
|
||||
- **Other families**: Check `hw/bsp/FAMILY/boards/` for available boards
|
||||
|
||||
### Common Tasks and Time Expectations
|
||||
|
||||
#### Repository Structure Quick Reference
|
||||
```
|
||||
├── src/ # Core TinyUSB stack
|
||||
│ ├── class/ # USB device classes (CDC, HID, MSC, Audio, etc.)
|
||||
│ ├── portable/ # MCU-specific drivers (organized by vendor)
|
||||
│ ├── device/ # USB device stack core
|
||||
│ ├── host/ # USB host stack core
|
||||
│ └── common/ # Shared utilities (FIFO, etc.)
|
||||
├── examples/ # Example applications
|
||||
│ ├── device/ # Device examples (cdc_msc, hid_generic, etc.)
|
||||
│ ├── host/ # Host examples
|
||||
│ └── dual/ # Dual-role examples
|
||||
├── hw/bsp/ # Board Support Packages
|
||||
│ └── FAMILY/boards/ # Board-specific configurations
|
||||
├── test/unit-test/ # Unit tests using Ceedling
|
||||
├── tools/ # Build and utility scripts
|
||||
└── docs/ # Sphinx documentation
|
||||
```
|
||||
|
||||
#### Build Time Reference
|
||||
- **Dependency fetch**: <1 second
|
||||
- **Single example build**: 1-3 seconds
|
||||
- **Unit tests**: ~4 seconds
|
||||
- **Documentation build**: ~2.5 seconds
|
||||
- **Full board examples**: 15-20 seconds
|
||||
- **Toolchain installation**: 2-5 minutes (one-time)
|
||||
|
||||
#### Key Files to Know
|
||||
- `tools/get_deps.py`: Manages dependencies for MCU families
|
||||
- `tools/build.py`: Builds multiple examples, supports make/cmake
|
||||
- `src/tusb.h`: Main TinyUSB header file
|
||||
- `src/tusb_config.h`: Configuration template
|
||||
- `examples/device/cdc_msc/`: Most commonly used example for testing
|
||||
- `test/unit-test/project.yml`: Ceedling test configuration
|
||||
|
||||
#### Debugging Build Issues
|
||||
- **Missing compiler**: Install `gcc-arm-none-eabi` package
|
||||
- **Missing dependencies**: Run `python3 tools/get_deps.py FAMILY`
|
||||
- **Board not found**: Check `hw/bsp/FAMILY/boards/` for valid board names
|
||||
- **objcopy errors**: Often non-critical in full builds, try individual example builds
|
||||
|
||||
#### Working with USB Device Classes
|
||||
- **CDC (Serial)**: `src/class/cdc/` - Virtual serial port
|
||||
- **HID**: `src/class/hid/` - Human Interface Device (keyboard, mouse, etc.)
|
||||
- **MSC**: `src/class/msc/` - Mass Storage Class (USB drive)
|
||||
- **Audio**: `src/class/audio/` - USB Audio Class
|
||||
- Each class has device (`*_device.c`) and host (`*_host.c`) implementations
|
||||
|
||||
#### MCU Family Support
|
||||
- **STM32**: Largest support (F0, F1, F2, F3, F4, F7, G0, G4, H7, L4, U5, etc.)
|
||||
- **Raspberry Pi**: RP2040, RP2350 with PIO-USB host support
|
||||
- **NXP**: iMXRT, Kinetis, LPC families
|
||||
- **Microchip**: SAM D/E/G/L families
|
||||
- Check `hw/bsp/` for complete list and `docs/reference/boards.rst` for details
|
||||
|
||||
### Code Style Guidelines
|
||||
|
||||
#### General Coding Standards
|
||||
- Use C99 standard
|
||||
- Memory-safe: no dynamic allocation
|
||||
- Thread-safe: defer all interrupt events to non-ISR task functions
|
||||
- 2-space indentation, no tabs
|
||||
- Use snake_case for variables/functions
|
||||
- Use UPPER_CASE for macros and constants
|
||||
- Follow existing variable naming patterns in files you're modifying
|
||||
- Include proper header comments with MIT license
|
||||
- Add descriptive comments for non-obvious functions
|
||||
|
||||
#### Best Practices
|
||||
- When including headers, group in order: C stdlib, tusb common, drivers, classes
|
||||
- Always check return values from functions that can fail
|
||||
- Use TU_ASSERT() for error checking with return statements
|
||||
- Follow the existing code patterns in the files you're modifying
|
||||
|
||||
Remember: TinyUSB is designed for embedded systems - builds are fast, tests are focused, and the codebase is optimized for resource-constrained environments.
|
||||
|
||||
## Claude Agent Notes (`CLAUDE.md`)
|
||||
- Default to CMake+Ninja for builds, but align with Make workflows when users rely on legacy scripts; provide DEBUG/LOG/LOGGER knobs consistently.
|
||||
|
||||
@ -94,13 +94,13 @@ void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr);
|
||||
TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_tx(dwc2_regs_t* dwc2, uint8_t fnum) {
|
||||
// flush TX fifo and wait for it cleared
|
||||
dwc2->grstctl = GRSTCTL_TXFFLSH | (fnum << GRSTCTL_TXFNUM_Pos);
|
||||
while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {}
|
||||
while (0 != (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk)) {}
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) {
|
||||
// flush RX fifo and wait for it cleared
|
||||
dwc2->grstctl = GRSTCTL_RXFFLSH;
|
||||
while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {}
|
||||
while (0 != (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk)) {}
|
||||
}
|
||||
|
||||
void dfifo_read_packet(dwc2_regs_t* dwc2, uint8_t* dst, uint16_t len);
|
||||
|
||||
@ -91,6 +91,16 @@ enum {
|
||||
GOTGCTL_OTG_VERSION_2_0 = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
GUSBCFG_PHYSEL_HIGHSPEED = 0,
|
||||
GUSBCFG_PHYSEL_FULLSPEED = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
GUSBCFG_PHYHS_UTMI = 0,
|
||||
GUSBCFG_PHYHS_ULPI = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
GHWCFG2_OPMODE_HNP_SRP = 0,
|
||||
GHWCFG2_OPMODE_SRP = 1,
|
||||
|
||||
@ -300,8 +300,8 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t cal_packet_count(uint16_t len, uint
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t cal_next_pid(uint8_t pid, uint8_t packet_count) {
|
||||
if (packet_count & 0x01) {
|
||||
return pid ^ 0x02; // toggle DATA0 and DATA1
|
||||
if (packet_count & 0x01u) {
|
||||
return pid ^ 0x02u; // toggle DATA0 and DATA1
|
||||
} else {
|
||||
return pid;
|
||||
}
|
||||
@ -544,17 +544,24 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t*
|
||||
|
||||
edpt->speed = bus_info.speed;
|
||||
edpt->next_pid = HCTSIZ_PID_DATA0;
|
||||
if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
|
||||
edpt->uframe_interval = 1 << (desc_ep->bInterval - 1);
|
||||
if (bus_info.speed == TUSB_SPEED_FULL) {
|
||||
edpt->uframe_interval <<= 3;
|
||||
}
|
||||
} else if (desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT) {
|
||||
if (bus_info.speed == TUSB_SPEED_HIGH) {
|
||||
switch (desc_ep->bmAttributes.xfer) {
|
||||
case TUSB_XFER_ISOCHRONOUS:
|
||||
edpt->uframe_interval = 1 << (desc_ep->bInterval - 1);
|
||||
} else {
|
||||
edpt->uframe_interval = desc_ep->bInterval << 3;
|
||||
}
|
||||
if (bus_info.speed == TUSB_SPEED_FULL) {
|
||||
edpt->uframe_interval <<= 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case TUSB_XFER_INTERRUPT:
|
||||
if (bus_info.speed == TUSB_SPEED_HIGH) {
|
||||
edpt->uframe_interval = 1 << (desc_ep->bInterval - 1);
|
||||
} else {
|
||||
edpt->uframe_interval = desc_ep->bInterval << 3;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -801,7 +808,7 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci
|
||||
edpt->next_pid = hctsiz.pid; // save PID
|
||||
edpt->uframe_countdown = edpt->uframe_interval - ucount;
|
||||
// enable SOF interrupt if not already enabled
|
||||
if (!(dwc2->gintmsk & GINTMSK_SOFM)) {
|
||||
if (0 == (dwc2->gintmsk & GINTMSK_SOFM)) {
|
||||
dwc2->gintsts = GINTSTS_SOF;
|
||||
dwc2->gintmsk |= GINTMSK_SOFM;
|
||||
}
|
||||
@ -848,7 +855,7 @@ static void handle_rxflvl_irq(uint8_t rhport) {
|
||||
TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,);
|
||||
hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id];
|
||||
|
||||
if (byte_count) {
|
||||
if (byte_count > 0) {
|
||||
dfifo_read_packet(dwc2, edpt->buffer + xfer->xferred_bytes, byte_count);
|
||||
xfer->xferred_bytes += byte_count;
|
||||
xfer->fifo_bytes = byte_count;
|
||||
@ -884,8 +891,8 @@ static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) {
|
||||
dwc2_channel_t* channel = &dwc2->channel[ch_id];
|
||||
const dwc2_channel_char_t hcchar = {.value = channel->hcchar};
|
||||
// skip writing to FIFO if channel is expecting halted.
|
||||
if (!(channel->hcintmsk & HCINT_HALTED) && (hcchar.ep_dir == TUSB_DIR_OUT)) {
|
||||
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
|
||||
if (0 == (channel->hcintmsk & HCINT_HALTED) && (hcchar.ep_dir == TUSB_DIR_OUT)) {
|
||||
hcd_xfer_t *xfer = &_hcd_data.xfer[ch_id];
|
||||
TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX);
|
||||
hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id];
|
||||
const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz};
|
||||
@ -946,6 +953,8 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h
|
||||
} else if (hcint & HCINT_XACT_ERR) {
|
||||
xfer->err_count++;
|
||||
channel->hcintmsk |= HCINT_ACK;
|
||||
} else {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
channel_disable(dwc2, channel);
|
||||
@ -957,7 +966,7 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h
|
||||
channel_disable(dwc2, channel);
|
||||
} else if (hcint & HCINT_NAK) {
|
||||
// NAK received, disable channel to flush all posted request and try again
|
||||
if (hcsplt.split_en) {
|
||||
if (hcsplt.split_en == 1u) {
|
||||
hcsplt.split_compl = 0; // restart with start-split
|
||||
channel->hcsplt = hcsplt.value;
|
||||
}
|
||||
@ -966,8 +975,8 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h
|
||||
} else if (hcint & HCINT_ACK) {
|
||||
xfer->err_count = 0;
|
||||
|
||||
if (hcsplt.split_en) {
|
||||
if (!hcsplt.split_compl) {
|
||||
if (hcsplt.split_en == 1u) {
|
||||
if (hcsplt.split_compl == 0) {
|
||||
// start split is ACK --> do complete split
|
||||
channel->hcintmsk |= HCINT_NYET;
|
||||
hcsplt.split_compl = 1;
|
||||
@ -979,7 +988,7 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h
|
||||
} else {
|
||||
// ACK with data
|
||||
const uint16_t remain_packets = hctsiz.packet_count;
|
||||
if (remain_packets) {
|
||||
if (remain_packets > 0) {
|
||||
// still more packet to receive, also reset to start split
|
||||
hcsplt.split_compl = 0;
|
||||
channel->hcsplt = hcsplt.value;
|
||||
@ -993,7 +1002,7 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h
|
||||
} else if (xfer->err_count == HCD_XFER_ERROR_MAX) {
|
||||
xfer->result = XFER_RESULT_FAILED;
|
||||
is_done = true;
|
||||
} else if (xfer->closing) {
|
||||
} else if (xfer->closing == 1) {
|
||||
is_done = true;
|
||||
} else {
|
||||
// got here due to NAK or NYET
|
||||
@ -1002,6 +1011,8 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h
|
||||
} else if (hcint & HCINT_DATATOGGLE_ERR) {
|
||||
xfer->err_count = 0;
|
||||
TU_ASSERT(false);
|
||||
} else {
|
||||
// nothing to do
|
||||
}
|
||||
return is_done;
|
||||
}
|
||||
@ -1026,7 +1037,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t
|
||||
channel_disable(dwc2, channel);
|
||||
} else if (hcint & HCINT_NYET) {
|
||||
xfer->err_count = 0;
|
||||
if (hcsplt.split_en) {
|
||||
if (hcsplt.split_en == 1u) {
|
||||
// retry complete split
|
||||
hcsplt.split_compl = 1;
|
||||
channel->hcsplt = hcsplt.value;
|
||||
@ -1054,8 +1065,8 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t
|
||||
is_done = true;
|
||||
} else if (xfer->err_count == HCD_XFER_ERROR_MAX) {
|
||||
xfer->result = XFER_RESULT_FAILED;
|
||||
is_done = true;
|
||||
} else if (xfer->closing) {
|
||||
is_done = true;
|
||||
} else if (xfer->closing == 1) {
|
||||
is_done = true;
|
||||
} else {
|
||||
// Got here due to NAK or NYET
|
||||
@ -1064,8 +1075,8 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t
|
||||
} else if (hcint & HCINT_ACK) {
|
||||
xfer->err_count = 0;
|
||||
channel->hcintmsk &= ~HCINT_ACK;
|
||||
if (hcsplt.split_en) {
|
||||
if (!hcsplt.split_compl) {
|
||||
if (hcsplt.split_en == 1u) {
|
||||
if (hcsplt.split_compl == 0) {
|
||||
// ACK for start split --> do complete split
|
||||
hcsplt.split_compl = 1;
|
||||
channel->hcsplt = hcsplt.value;
|
||||
@ -1077,6 +1088,8 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t
|
||||
channel->hctsiz &= ~HCTSIZ_DOPING; // HC already cleared PING bit, but we clear anyway
|
||||
channel->hcchar |= HCCHAR_CHENA;
|
||||
}
|
||||
} else {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
if (is_done) {
|
||||
@ -1174,7 +1187,7 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci
|
||||
channel_xfer_in_retry(dwc2, ch_id, hcint);
|
||||
}
|
||||
|
||||
if (xfer->closing) {
|
||||
if (xfer->closing == 1) {
|
||||
is_done = true;
|
||||
}
|
||||
}
|
||||
@ -1238,7 +1251,7 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc
|
||||
}
|
||||
}
|
||||
|
||||
if (xfer->closing) {
|
||||
if (xfer->closing == 1) {
|
||||
is_done = true;
|
||||
}
|
||||
} else if (hcint & HCINT_ACK) {
|
||||
@ -1289,7 +1302,7 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) {
|
||||
}
|
||||
|
||||
if (is_done) {
|
||||
if (xfer->closing) {
|
||||
if (xfer->closing == 1) {
|
||||
hcd_endpoint_t *edpt = &_hcd_data.edpt[xfer->ep_id];
|
||||
edpt_dealloc(edpt);
|
||||
} else {
|
||||
@ -1337,9 +1350,9 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) {
|
||||
uint32_t hcfg = dwc2->hcfg & ~HCFG_FSLS_PHYCLK_SEL;
|
||||
|
||||
const dwc2_gusbcfg_t gusbcfg = {.value = dwc2->gusbcfg};
|
||||
uint32_t phy_clock;
|
||||
uint32_t phy_clock;
|
||||
|
||||
if (gusbcfg.phy_sel) {
|
||||
if (gusbcfg.phy_sel == GUSBCFG_PHYSEL_FULLSPEED) {
|
||||
phy_clock = 48; // dedicated FS is 48Mhz
|
||||
if (speed == TUSB_SPEED_LOW) {
|
||||
hcfg |= HCFG_FSLS_PHYCLK_SEL_6MHZ;
|
||||
@ -1347,7 +1360,7 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) {
|
||||
hcfg |= HCFG_FSLS_PHYCLK_SEL_48MHZ;
|
||||
}
|
||||
} else {
|
||||
if (gusbcfg.ulpi_utmi_sel) {
|
||||
if (gusbcfg.ulpi_utmi_sel == GUSBCFG_PHYHS_ULPI) {
|
||||
phy_clock = 60; // ULPI 8-bit is 60Mhz
|
||||
} else {
|
||||
// UTMI+ 16-bit is 30Mhz, 8-bit is 60Mhz
|
||||
@ -1386,20 +1399,20 @@ static void handle_hprt_irq(uint8_t rhport, bool in_isr) {
|
||||
const dwc2_hprt_t hprt_bm = {.value = dwc2->hprt};
|
||||
uint32_t hprt = hprt_bm.value & ~HPRT_W1_MASK;
|
||||
|
||||
if (hprt_bm.conn_detected) {
|
||||
if (hprt_bm.conn_detected == 1u) {
|
||||
// Port Connect Detect
|
||||
hprt |= HPRT_CONN_DETECT;
|
||||
|
||||
if (hprt_bm.conn_status) {
|
||||
if (hprt_bm.conn_status == 1u) {
|
||||
hcd_event_device_attach(rhport, in_isr);
|
||||
}
|
||||
}
|
||||
|
||||
if (hprt_bm.enable_change) {
|
||||
if (hprt_bm.enable_change == 1u) {
|
||||
// Port enable change
|
||||
hprt |= HPRT_ENABLE_CHANGE;
|
||||
|
||||
if (hprt_bm.enable) {
|
||||
if (hprt_bm.enable == 1u) {
|
||||
// Port enable
|
||||
const tusb_speed_t speed = hprt_speed_get(dwc2);
|
||||
port0_enable(dwc2, speed);
|
||||
@ -1458,7 +1471,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) {
|
||||
// Device disconnected
|
||||
dwc2->gintsts = GINTSTS_DISCINT;
|
||||
|
||||
if (!(dwc2->hprt & HPRT_CONN_STATUS)) {
|
||||
if (0 == (dwc2->hprt & HPRT_CONN_STATUS)) {
|
||||
hcd_event_device_remove(rhport, in_isr);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user