There were two problems:
- dma_running flag could be checked in USB interrupt (not set yet) then higher priority
interrupt could start transfer, check dma_running (not set yet) set it to true start
DMA; then when USB interrupt continues it starts another DMA that is not allowed
- when DMA is started some registers can't be safely accessed, read can yield invalid
values (SIZE.EPOUT, SIZE.EPISO)
current implementation could start DMA for one OUT endpoint then check that another
endpoint also has data and while DMA was not started right away, SIZE.EPOUT was copied
already to MAXCNT register. Later on when DMA was started not all data was read from
endpoint due to incorrect DMA size previously set.
To prevent both cases dma_running is changed in atomic way.
Only code that actually set this value to true starts DMA, code that tried and
had dma_running flag already set simply defers DMA start to USB task.
This eliminates also need to have mutex that was there to limit access to dma_running flag
to one task only.
transfer also now has started flag that is set only after dcd_edpt_xfer() sets up total_len
and actua_len. Previously USB interrupt was disabled when total_len and actual_len were
setup to prevent race condition when data arrived to ednpoint before transfer was setup
was finished.
When transfer was finished rx_fifo_read() read all that
was to read RXPKTRDY was cleared allowing next packet to
be received.
Then xfer_complete was called.
Interrupt for OUT endpoint was left enable, that would not
be a problem if data was handled fast and new transfer was
scheduled.
For MSC when host sends a lot of data this interrupt that was
enabled could cause epn_handle_rx_int() to be called after
transfer was completed and next was not scheduled yet.
Without TU_ASSERT that was added to detect this, incoming
data was written past buffer provided by user code resulting
in random memory corruption.
This just blocks RX interrupt when transfer is finished,
and also only unmasked rx interrupts are handled.
Remote wakeup requires 10ms of delay when RESUME bit
is toggled.
It was covered for OS build.
For non-OS build simple delay based on board_millis() is
used to wait required amount of time.
Without this remote wakup may not work.
Two boards from Olimex are added:
olimex_hmz144 with PIC32MZ2048EFM144
olimex_emz64.c with PIC32MZ2048EFH064
Both can be programmed with Segger JLINK probe using ICSP
interface. (JTAG not tested but could also work but header
is not mounted).
definition of DEBUG breaks Microchip pic32 builds for Mynewt.
When MCU is not VALENTYUSB_EPTRI there is no need to have any
preprocessor definitions.
It may not look like a big deal but for xc32 builds, compiler
automatically force-includes some file that have structure with field name
DEBUG that result in build error in dcd_eptri.c when this file
is not really needed.
Moving DEBUG and LOG_USB few lines down should not break eptri builds.
Three changes are needed to accommodate xc32 compiler build:
- optimized build flag other than -Os
added CFLAGS_OPTIMIZED that defaults to -Os but can be overridden in boards
- build without -lnosys
added LIBS_GCC with default libraries that can be changed in boards
- build without LD_FILE specification
if LD_FILE is empty -Wl,-T options is not added to LDFLAGS
dcd_synopsys.c included broadcom/interrupts.h before
preprocessor check whether file should be used.
Since mynewt build does not include all folders it resulted in build
error.
Now offending include is moved few lines after preprocessor check.
dcd_da1469x can work with broader range of MCUs that
share same USB core.
Specific header file that was used DA1469xAB.h now it is changed
to mcu/mcu.h which includes actual MCU specific register file.