Merge pull request #143 from qmk/fix_kinesis_usb_data_sync

Fix Kinetis usb databank synchronization problems
This commit is contained in:
Fabien Poussin 2018-03-08 17:09:26 +01:00 committed by GitHub
commit 11066ebbd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 17 deletions

View File

@ -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 */

View File

@ -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);
}