diff options
author | Fabien Poussin <fabien.poussin@gmail.com> | 2018-03-08 17:09:26 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-08 17:09:26 +0100 |
commit | 11066ebbd353a4a4c0e1add129b9d60202a9803e (patch) | |
tree | 62e67ed9ddb904d94ee1aa2d286b9c4441a01896 /os | |
parent | 14c851fdabae5799830103c208c6a900b1fb4159 (diff) | |
parent | b7f761313c11d94b89b605f81a89ced34a57c603 (diff) | |
download | ChibiOS-Contrib-11066ebbd353a4a4c0e1add129b9d60202a9803e.tar.gz ChibiOS-Contrib-11066ebbd353a4a4c0e1add129b9d60202a9803e.tar.bz2 ChibiOS-Contrib-11066ebbd353a4a4c0e1add129b9d60202a9803e.zip |
Merge pull request #143 from qmk/fix_kinesis_usb_data_sync
Fix Kinetis usb databank synchronization problems
Diffstat (limited to 'os')
-rw-r--r-- | os/common/ext/CMSIS/KINETIS/k20xx.h | 2 | ||||
-rw-r--r-- | os/hal/ports/KINETIS/LLD/hal_usb_lld.c | 57 |
2 files changed, 42 insertions, 17 deletions
diff --git a/os/common/ext/CMSIS/KINETIS/k20xx.h b/os/common/ext/CMSIS/KINETIS/k20xx.h index 38855aa..8218b3c 100644 --- a/os/common/ext/CMSIS/KINETIS/k20xx.h +++ b/os/common/ext/CMSIS/KINETIS/k20xx.h @@ -2242,7 +2242,7 @@ typedef struct /******** Bits definition for USBx_CTL register *****************/ #define USBx_CTL_JSTATE ((uint8_t)0x80) /*!< Live USB differential receiver JSTATE signal */ #define USBx_CTL_SE0 ((uint8_t)0x40) /*!< Live USB single ended zero signal */ -#define USBx_CTL_TXSUSPENDTOKENBUS ((uint8_t)0x20) /*!< */ +#define USBx_CTL_TXSUSPENDTOKENBUSY ((uint8_t)0x20) /*!< */ #define USBx_CTL_RESET ((uint8_t)0x10) /*!< Generates an USB reset signal (host mode) */ #define USBx_CTL_HOSTMODEEN ((uint8_t)0x08) /*!< Operate in Host mode */ #define USBx_CTL_RESUME ((uint8_t)0x04) /*!< Executes resume signaling */ diff --git a/os/hal/ports/KINETIS/LLD/hal_usb_lld.c b/os/hal/ports/KINETIS/LLD/hal_usb_lld.c index e8d9778..ba91d24 100644 --- a/os/hal/ports/KINETIS/LLD/hal_usb_lld.c +++ b/os/hal/ports/KINETIS/LLD/hal_usb_lld.c @@ -158,7 +158,7 @@ void usb_packet_transmit(USBDriver *usbp, usbep_t ep, size_t n) USBInEndpointState *isp = epc->in_state;
bd_t *bd = (bd_t *)&_bdt[BDT_INDEX(ep, TX, isp->odd_even)];
-
+
if (n > (size_t)epc->in_maxsize)
n = (size_t)epc->in_maxsize;
@@ -244,19 +244,16 @@ OSAL_IRQ_HANDLER(KINETIS_USB_IRQ_VECTOR) { {
case BDT_PID_SETUP: // SETUP
{
- /* Clear any pending IN stuff */
- _bdt[BDT_INDEX(ep, TX, EVEN)].desc = 0;
- _bdt[BDT_INDEX(ep, TX, ODD)].desc = 0;
- /* Also in the chibios state machine */
+ /* Clear receiving in the chibios state machine */
(usbp)->receiving &= ~1;
- /* After a SETUP, IN is always DATA1 */
- usbp->epc[ep]->in_state->data_bank = DATA1;
-
- /* Call SETUP function (ChibiOS core), which sends back stuff */
+ /* Call SETUP function (ChibiOS core), which prepares
+ * for send or receive and releases the buffer
+ */
_usb_isr_invoke_setup_cb(usbp, ep);
- /* Buffer is released by the above callback. */
- /* from Paul: "unfreeze the USB, now that we're ready" */
- USB0->CTL = USBx_CTL_USBENSOFEN;
+ /* When a setup packet is received, tx is suspended,
+ * so it needs to be resumed here.
+ */
+ USB0->CTL &= ~USBx_CTL_TXSUSPENDTOKENBUSY;
} break;
case BDT_PID_IN: // IN
{
@@ -728,9 +725,23 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { }
/* Release the buffer
* Setup packet is always DATA0
- * Initialize buffers so current expects DATA0 & opposite DATA1 */
+ * Release the current DATA0 buffer
+ */
bd->desc = BDT_DESC(usbp->epc[ep]->out_maxsize,DATA0);
- _bdt[BDT_INDEX(ep, RX, os->odd_even^ODD)].desc = BDT_DESC(usbp->epc[ep]->out_maxsize,DATA1);
+ /* If DATA1 was expected, then the states are out of sync.
+ * So reset the other buffer too, and set it as DATA1.
+ * This should not happen in normal cases, but is possible in
+ * error situations. NOTE: it's possible that this is too late
+ * and the next packet has already been received and dropped, but
+ * there's nothing that we can do about that anymore at this point.
+ */
+ if (os->data_bank == DATA1)
+ {
+ bd_t *bd_next = (bd_t*)&_bdt[BDT_INDEX(ep, RX, os->odd_even^ODD)];
+ bd_next->desc = BDT_DESC(usbp->epc[ep]->out_maxsize,DATA1);
+ }
+ /* After a SETUP, both in and out are always DATA1 */
+ usbp->epc[ep]->in_state->data_bank = DATA1;
os->data_bank = DATA1;
}
@@ -762,8 +773,22 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { * @notapi
*/
void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
- (void)usbp;
- (void)ep;
+ if (ep == 0 && usbp->ep0state == USB_EP0_IN_SENDING_STS) {
+ /* When a status packet is about to be sent on endpoint 0 the
+ * next packet will be a setup packet, which means that the
+ * buffer we expect after this should be DATA0, and the following
+ * DATA1. Since no out packets should be in flight at this time
+ * it's safe to initialize the buffers according to the expectations
+ * here.
+ */
+ const USBEndpointConfig* epc = usbp->epc[ep];
+ bd_t * bd = (bd_t*)&_bdt[BDT_INDEX(ep, RX, epc->out_state->odd_even)];
+ bd_t *bd_next = (bd_t*)&_bdt[BDT_INDEX(ep, RX, epc->out_state->odd_even^ODD)];
+
+ bd->desc = BDT_DESC(usbp->epc[ep]->out_maxsize,DATA1);
+ bd_next->desc = BDT_DESC(usbp->epc[ep]->out_maxsize,DATA0);
+ epc->out_state->data_bank = DATA0;
+ }
usb_packet_transmit(usbp,ep,usbp->epc[ep]->in_state->txsize);
}
|