Going to suspend states disable reception on non-0 RX endpoints.
Now when USB resume condition is detected, all RX endpoints
with pending transfers are resumed.
Bit mask enabling/disabling over-run/unde-run was shifted
by one nibble, so interrupt was never enabled.
It did not force any issue as this situation could only
happen on ISO endpoints without DMA.
So far tud_vendor_n_write() always flushed data.
It requires to have whole vendor packed constructed
before in one buffer.
With this change data do get flushed when endpoint size
is filled on write, when there is no enough data to
fill endpoint data is not sent and subsequent calls to
write functions can add more bytes.
Vendor code needs to call tud_vendor_n_flush() when packet is
ready to be sent.
When two tasks entered dcd_edpt_xfer() it was possible that
first disabled interrupt to setup total_len and actual_len
but second task for another endpoint enabled interrupt
between total_len and actual_len resulting in race
condition with interrupt, hence mutex is added on top of interrupt being blocked.
In multi-thread mode starting DMA in thread mode was
prone to race condition resulting in infinite loop.
It may happen on single core CPU with strict priority based
tasks scheduler where ready high prio task never yields to
ready low prio task (Mynewt).
Sequence that failed (T1 - low priority task, T2 - high priority task)
- T1 called start_dma()
- T1 set _dcd.dma_running (DMA not started yet, context switch happens)
- T2 took CPU and saw that _dcd.dma_running is set, so waits for _dcd.dma_running to be 0
- T1 never gets CPU again, DMA is not started T2 waits forever
OSAL mutex resolves problem of DMA starting from thread-context.
Mynewt (similar to Soft Device) has its own reference counting for
HFXO oscillator.
So far TinyUSB requested HFXO when VBUS was detected and stopped when
VBUS was removed.
But with Mynewt running HFXO can be stopped when other interested parties
don't require HFXO anymore. This results in very difficult to track
USB transmission errors.
This change enables Mynewt specific HFXO management in Soft Device fashion.
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.
When dcd_edpt_xfer() starts new transfer two separate problems were observed.
For both problems stream of OUT packets was pouring from host.
First problem was that total_len and actual_len were not atomic.
In case where incoming OUT packets are less (63) than MPS (64), actual_len and total_len
are set 63.
Then transfer complete from USBD is called that will schedule next 64 bytes transfer.
At that point incoming packet would start DMA if there is place in RAM, normally
it does not happen since actual_len == total_len.
If packets arrives and interrupt is raised after total_len is set (64) but actual_len is still 63 from
previous transfer, interrupt code sees that there is place in ram (1 byte) and transfer this 1 byte
to buffer that was already filled with previous packet.
To remedy this USB interrupt is blocked during transfer setup.
Second problem can happen when dcd_edpt_xfer setups xfer->total_len and actual_len correctly
but then context switch happens before xfer->data_received is checked.
If during this time two packets arrive one will be copied to RAM second will stay in endpoint with
data_received set to 1.
Then when xfer_edpt_xfer() checks data_receive flag it starts DMA again overwriting data.
To remedy this, data_received is checked together with check if data was already transferred.
If transfer was complete, there is no need to start DMA yet.
In such case data_received will be handled in same place by next xfer_edpt_xfer() correctly.
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).