Merge pull request #243 from Codetector1374/LPC_Port

[HAL/LPC] Update USB HAL Driver to resolve an issue where sometimes it causes control EP to stall
This commit is contained in:
Fabien Poussin 2020-12-18 01:58:12 +01:00 committed by GitHub
commit 11478d784b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 368 additions and 201 deletions

View File

@ -41,10 +41,6 @@ static void jump_to_application(void) {
while (1) {}
}
#define IAP_LOCATION 0x1fff1ff1
typedef void (*IAP)(uint32_t [], uint32_t []);
const IAP iap_entry = (IAP)IAP_LOCATION;
/*
* Application entry point.
*/
@ -57,66 +53,16 @@ int main(void) {
*/
chSysInit();
memset(fw_buffer, 0, FW_BUFFER_SIZE);
dfu_need_flush = 0;
/*
* Normal main() thread activity, in this demo it does nothing except
* increasing the minutes counter.
*/
while (true) {
uint32_t iap_command[5];
uint32_t iap_result[4];
usbDisconnectBus(&USBD1);
chThdSleepMilliseconds(1500);
usbStart(&USBD1, &usbcfg);
usbConnectBus(&USBD1);
usbDisconnectBus(&USBD1);
chThdSleepMilliseconds(1500);
usbStart(&USBD1, &usbcfg);
usbConnectBus(&USBD1);
while(1){
if (dfu_need_flush) {
if (global_offset == APP_BASE) {
do {
iap_command[0] = 50; // Prep Sector
iap_command[1] = 3; // Start Sec
iap_command[2] = 15; // Stop Sec
iap_entry(iap_command, iap_result);
} while(iap_result[0]);
// Erase All Flash (3-15)
do {
iap_command[0] = 52; // Erase Sector
iap_command[1] = 3; // Start Sec
iap_command[2] = 15; // Stop Sec
iap_command[3] = 48000; // 48MHz
iap_entry(iap_command, iap_result);
} while(iap_result[0]);
}
uint32_t start_sector = global_offset / 4096;
uint32_t end_sector = (global_offset + FW_BUFFER_SIZE) / 4096;
iap_command[0] = 50; // Prep Sector
iap_command[1] = start_sector; // Start Sec
iap_command[2] = end_sector; // Stop Sec
iap_entry(iap_command, iap_result);
// Copy the buffer
iap_command[0] = 51;
iap_command[1] = global_offset;
iap_command[2] = (uint32_t)fw_buffer;
iap_command[3] = FW_BUFFER_SIZE;
iap_command[4] = 48000;
iap_entry(iap_command, iap_result);
global_offset += FW_BUFFER_SIZE;
dfu_need_flush = 0;
memset(fw_buffer, 0, FW_BUFFER_SIZE);
buffer_fill = 0;
if (currentState == STATE_DFU_DNLOAD_SYNC || currentState == STATE_DFU_DNBUSY)
currentState = STATE_DFU_DNLOAD_IDLE;
if (currentState == STATE_DFU_MANIFEST_SYNC) {
currentState = STATE_DFU_MANIFEST_WAIT_RESET;
chThdSleepMilliseconds(2000);
jump_to_application();
}
}
}
while(1){
chThdSleepSeconds(600);
}
}

View File

@ -0,0 +1,115 @@
#include "dfu_target.h"
#include "usbdfu.h"
#include "ch.h"
#include "hal.h"
#include <string.h>
#define IAP_LOCATION 0x1fff1ff1
typedef void (*IAP)(uint32_t [], uint32_t []);
const IAP iap_entry = (IAP)IAP_LOCATION;
#define INTERNAL_CHUNK_SIZE 1024
static uint8_t iap_buffer[INTERNAL_CHUNK_SIZE];
static size_t buffer_size = 0;
static size_t buffer_base = 0;
static size_t last_chunk_size = 0;
static size_t preped_flash = 0;
size_t target_get_max_fw_size(void) {
return (0x10000 - 0x2000);
}
uint16_t target_get_timeout(void) {
if (last_chunk_size != 0 && (buffer_size + last_chunk_size) < INTERNAL_CHUNK_SIZE) {
return 5;
}
if (preped_flash == 0) {
return 50;
}
return 0;
}
void target_flash_unlock(void) {
chSysLock();
}
static inline bool write_buffer(void) {
uint32_t iap_command[5] = {0,0,0,0,0};
uint32_t iap_result[4] = {0,0,0,0};
if (((size_t)buffer_base % INTERNAL_CHUNK_SIZE) != 0) {
return false;
}
uint32_t sector = (size_t)buffer_base / 4096;
iap_command[0] = 50; // Prep Sector
iap_command[1] = sector; // Start Sec
iap_command[2] = sector; // Stop Sec
iap_entry(iap_command, iap_result);
// Copy the buffer
iap_command[0] = 51; // Copy RAM -> Flash
iap_command[1] = (size_t) buffer_base;
iap_command[2] = (size_t) iap_buffer;
iap_command[3] = INTERNAL_CHUNK_SIZE;
iap_command[4] = 48000;
iap_entry(iap_command, iap_result);
return iap_result[0] == 0;
}
bool target_flash_write(uint8_t* dst, uint8_t* src, size_t len) {
last_chunk_size = len;
size_t copied = 0;
while(copied < len) { // Stuff remain in the thing
if (buffer_size == 0) { // If buffer is empty, then we update base
buffer_base = (size_t)dst + copied;
}
size_t copy_size = len - copied;
if (copy_size > (INTERNAL_CHUNK_SIZE - buffer_size)) {
copy_size = INTERNAL_CHUNK_SIZE - buffer_size;
}
memcpy(&iap_buffer[buffer_size], (src + copied), copy_size);
buffer_size += copy_size;
copied += copy_size;
if (buffer_size == INTERNAL_CHUNK_SIZE) {
if (!write_buffer())
return false;
buffer_size = 0;
}
}
return true;
}
bool target_prepare_flash(void) {
uint32_t iap_command[5] = {0,0,0,0,0};
uint32_t iap_result[4] = {0,0,0,0};
iap_command[0] = 50; // Prep Sector
iap_command[1] = APP_BASE / 0x1000; // Start Sec
iap_command[2] = 15; // Stop Sec
iap_entry(iap_command, iap_result);
if (iap_result[0] != 0) {
return false;
}
iap_command[0] = 52; // Erase Sector
iap_command[1] = APP_BASE / 0x1000; // Start Sec
iap_command[2] = 15; // Stop Sec
iap_command[3] = 48000; // 48MHz
iap_entry(iap_command, iap_result);
preped_flash = 1;
return iap_result[0] == 0;
}
void target_flash_lock(void) {
chSysUnlock();
}
void target_complete_programming(void) {
if (buffer_size > 0) {
memset(&iap_buffer[buffer_size], 0, INTERNAL_CHUNK_SIZE - buffer_size);
write_buffer();
}
}

View File

@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
size_t target_get_max_fw_size(void);
uint16_t target_get_timeout(void);
void target_flash_unlock(void);
bool target_flash_write(uint8_t* dst, uint8_t* src, size_t len);
bool target_prepare_flash(void);
void target_flash_lock(void);
void target_complete_programming(void);

View File

@ -1,11 +1,8 @@
#include "hal.h"
#include "usbdfu.h"
#include "dfu_target.h"
uint8_t fw_buffer[FW_BUFFER_SIZE];
volatile uint8_t dfu_need_flush = 0;
volatile uint32_t buffer_fill = 0;
volatile uint32_t global_offset = APP_BASE;
/*
* USB Device Descriptor.
*/
@ -52,8 +49,8 @@ static const uint8_t dfu_configuration_descriptor_data[27] = {
USB_DESC_BYTE (9), /* bLength. */
USB_DESC_BYTE (0x21), /* bDescriptorType (DFU_FCUNTION). */
USB_DESC_BYTE (0b1011), /* bmAttributes (DETACH | DOWNLOAD) */
USB_DESC_WORD ( 1500), /* Timeout. */
USB_DESC_WORD (64 ),
USB_DESC_WORD ( 1000), /* DetachTimeout. */
USB_DESC_WORD ( 64),
USB_DESC_BCD (0x0110)
};
@ -79,9 +76,9 @@ static const uint8_t dfu_string1[] = {
* Device Description string.
*/
static const uint8_t dfu_string2[] = {
USB_DESC_BYTE(8), /* bLength. */
USB_DESC_BYTE(12), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'D', 0, 'F', 0, 'U', 0
'S', 0, 'F', 0, 'D', 0, 'F', 0, 'U', 0
};
/*
@ -114,7 +111,6 @@ static const USBDescriptor *get_descriptor(USBDriver *usbp,
uint8_t dtype,
uint8_t dindex,
uint16_t lang) {
(void)usbp;
(void)lang;
switch (dtype) {
@ -129,87 +125,171 @@ static const USBDescriptor *get_descriptor(USBDriver *usbp,
return NULL;
}
static void usb_event(USBDriver *usbp, usbevent_t event) {
}
static void sof_handler(USBDriver *usbp) {
(void)usbp;
}
volatile enum dfu_state currentState = STATE_DFU_IDLE;
size_t currentAddress = 0;
static enum {
LASTOP_IDLE,
LASTOP_DNLOAD,
LASTOP_UPLOAD
} lastOperation;
volatile enum dfu_status currentStatus = DFU_STATUS_OK;
size_t current_dfu_offset = 0;
size_t dfu_download_size = 0;
static uint8_t status_response_buffer[6] = {
DFU_STATUS_OK, // Status (0)
100, 0x00, 0x00,
0x00, // Next State (4)
0
};
static void dfu_on_download_request(USBDriver *usbp) {
(void)usbp;
uint8_t *dest = (uint8_t*)(APP_BASE + current_dfu_offset);
bool ok = true;
target_flash_unlock();
if (current_dfu_offset == 0) {
ok = target_prepare_flash();
}
if (ok) {
ok = target_flash_write(dest, fw_buffer, dfu_download_size);
}
target_flash_lock();
if (ok) {
current_dfu_offset += dfu_download_size;
currentState = STATE_DFU_DNLOAD_IDLE;
} else {
currentState = STATE_DFU_ERROR;
currentStatus = DFU_STATUS_ERR_VERIFY;
}
}
static void dfu_on_download_complete(USBDriver *usbp) {
(void)usbp;
currentState = STATE_DFU_MANIFEST_SYNC;
}
static void dfu_on_manifest_request(USBDriver *usbp) {
(void)usbp;
target_complete_programming();
currentState = STATE_DFU_MANIFEST_WAIT_RESET;
}
static void dfu_on_detach_complete(USBDriver *usbp) {
(void)usbp;
__asm__ __volatile__("dsb");
SCB->AIRCR = 0x05FA0004; // System Reset
__asm__ __volatile__("dsb");
while(1){};
}
static inline void dfu_status_req(USBDriver *usbp) {
static uint8_t status_response_buffer[6] = {};
uint32_t pollTime = 10;
usbcallback_t cb = NULL;
switch(currentState) {
case STATE_DFU_DNLOAD_SYNC: {
currentState = STATE_DFU_DNBUSY;
pollTime = target_get_timeout();
cb = &dfu_on_download_request;
break;
}
case STATE_DFU_MANIFEST_SYNC: {
currentState = STATE_DFU_MANIFEST;
cb = &dfu_on_manifest_request;
break;
}
case STATE_DFU_MANIFEST_WAIT_RESET: {
cb = &dfu_on_detach_complete;
break;
}
default:
break;
}
// Response Construction
status_response_buffer[0] = (uint8_t) currentStatus;
status_response_buffer[1] = (uint8_t) (pollTime & 0xFFU);
status_response_buffer[2] = (uint8_t) ((pollTime >> 8U) & 0xFFU);
status_response_buffer[3] = (uint8_t) ((pollTime >> 16U) & 0xFFU);
status_response_buffer[4] = (uint8_t) currentState;
status_response_buffer[5] = 0; // No Index
usbSetupTransfer(usbp, status_response_buffer, 6, cb);
}
static bool request_handler(USBDriver *usbp) {
if((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) {
uint16_t transfer_size = (((uint16_t)usbp->setup[7]) << 8) | usbp->setup[6];
uint16_t block_cnt = (((uint16_t)usbp->setup[4]) << 8) | usbp->setup[3];
switch (usbp->setup[1]) {
case DFU_GETSTATUS:
if (currentState == STATE_DFU_DNLOAD_SYNC) {
currentState = STATE_DFU_DNBUSY;
}
status_response_buffer[4] = currentState;
usbSetupTransfer(usbp, (uint8_t *)status_response_buffer, 6, NULL);
return true;
case DFU_GETSTATE:
usbSetupTransfer(usbp, (uint8_t *)&currentState, 1, NULL);
return true;
case DFU_UPLOAD:
if (lastOperation != LASTOP_UPLOAD) {
lastOperation = LASTOP_UPLOAD;
currentAddress = APP_BASE;
}
if ((currentAddress + transfer_size) > MAX_FLASH_ADDR) {
transfer_size = MAX_FLASH_ADDR - currentAddress;
usbSetupTransfer(usbp, (uint8_t *)currentAddress, transfer_size, NULL);
lastOperation = LASTOP_IDLE;
currentState = STATE_DFU_IDLE;
} else {
usbSetupTransfer(usbp, (uint8_t *)currentAddress, transfer_size, NULL);
currentAddress += transfer_size;
currentState = STATE_DFU_UPLOAD_IDLE;
}
return true;
case DFU_ABORT:
lastOperation = LASTOP_IDLE;
currentState = STATE_DFU_IDLE;
return true;
case DFU_DNLOAD:
if (lastOperation != LASTOP_DNLOAD) {
lastOperation = LASTOP_DNLOAD;
global_offset = APP_BASE;
buffer_fill = 0;
dfu_need_flush = 0;
}
if (transfer_size) {
usbSetupTransfer(usbp, &fw_buffer[buffer_fill], transfer_size, NULL);
buffer_fill += transfer_size;
if (buffer_fill < FW_BUFFER_SIZE) {
currentState = STATE_DFU_DNLOAD_IDLE;
} else {
currentState = STATE_DFU_DNLOAD_SYNC;
dfu_need_flush = 1;
}
} else {
if (buffer_fill > 0)
dfu_need_flush = 1;
currentState = STATE_DFU_MANIFEST_SYNC;
lastOperation = LASTOP_IDLE;
}
return true;
struct usb_setup* setup = (struct usb_setup*) usbp->setup;
if((setup->bmRequestType & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) {
switch (setup->bRequest) {
case DFU_GETSTATUS: {
dfu_status_req(usbp);
return true;
}
case DFU_GETSTATE: {
usbSetupTransfer(usbp, (uint8_t *)&currentState, 1, NULL);
return true;
}
case DFU_UPLOAD: {
switch (currentState) {
case STATE_DFU_IDLE: {
current_dfu_offset = 0;
__attribute__((fallthrough));
}
case STATE_DFU_UPLOAD_IDLE: {
uint16_t copy_len = setup->wLength;
size_t fw_size = target_get_max_fw_size();
if (current_dfu_offset + setup->wLength > fw_size) {
copy_len = fw_size - current_dfu_offset;
currentState = STATE_DFU_IDLE;
} else {
currentState = STATE_DFU_UPLOAD_IDLE;
}
usbSetupTransfer(usbp, (uint8_t *)(APP_BASE + current_dfu_offset), copy_len, NULL );
current_dfu_offset += copy_len;
break;
}
default:
usbSetupTransfer(usbp, NULL, 0, NULL);
break;
}
return true;
}
case DFU_CLRSTATUS: {
currentStatus = DFU_STATUS_OK;
if (currentState != STATE_DFU_ERROR) {
usbSetupTransfer(usbp, NULL, 0, NULL);
break;
}
__attribute__((fallthrough));
}
case DFU_ABORT: {
currentState = STATE_DFU_IDLE;
usbSetupTransfer(usbp, NULL, 0, NULL);
return true;
}
case DFU_DETACH: {
usbSetupTransfer(usbp, NULL, 0, &dfu_on_detach_complete);
return true;
}
case DFU_DNLOAD: {
switch (currentState) {
case STATE_DFU_IDLE: {
current_dfu_offset = 0;
dfu_download_size = setup->wLength;
currentState = STATE_DFU_DNLOAD_SYNC;
usbSetupTransfer(usbp, &fw_buffer[0], dfu_download_size, NULL);
break;
}
case STATE_DFU_DNLOAD_IDLE: {
if (setup->wLength > 0) {
dfu_download_size = setup->wLength;
usbSetupTransfer(usbp, &fw_buffer[0], dfu_download_size, NULL);
currentState = STATE_DFU_DNLOAD_SYNC;
} else {
usbSetupTransfer(usbp, NULL, 0, &dfu_on_download_complete);
}
break;
}
default: {
usbSetupTransfer(usbp, NULL, 0, NULL);
break;
}
}
return true;
}
}
}
return false;
}
@ -218,8 +298,8 @@ static bool request_handler(USBDriver *usbp) {
* USB driver configuration.
*/
const USBConfig usbcfg = {
usb_event,
NULL,
get_descriptor,
request_handler,
sof_handler
NULL
};

View File

@ -1,23 +1,18 @@
#pragma once
#include "stdint.h"
#include "hal.h"
extern const USBConfig usbcfg;
#define MAX_FLASH_ADDR 0x10000
#define FLASH_BASE 0x0
#define BL_SIZE 0x3000
#define BL_SIZE 0x2000
#define APP_BASE (FLASH_BASE + BL_SIZE)
#define FLASH_PAGE_SIZE 4096
#define FW_BUFFER_SIZE 1024
extern uint8_t fw_buffer[FW_BUFFER_SIZE];
extern volatile uint8_t dfu_need_flush;
extern volatile uint32_t buffer_fill;
extern volatile uint32_t global_offset;
extern size_t currentAddress;
extern volatile enum dfu_state currentState;
#define FW_BUFFER_SIZE 256
enum dfu_req {
DFU_DETACH,
@ -63,3 +58,10 @@ enum dfu_status {
DFU_STATUS_ERR_STALLEDPKT,
};
struct usb_setup {
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} __attribute__((packed));

View File

@ -132,7 +132,7 @@ static void usb_packet_transmit(USBDriver *usbp, usbep_t ep, size_t n)
}
/* Get EP command/status List, update the length field and data pointer. */
USB_EPLIST->entry[ep * 4 + 2] &= ~0x3FFFFFF;
USB_EPLIST->entry[ep * 4 + 2] &= ~(0x3FFFFFF | EPLIST_ENTRY_STALL | EPLIST_ENTRY_ACTIVE);
USB_EPLIST->entry[ep * 4 + 2] |= EPLIST_ENTRY_NBYTES(n) |
EPLIST_ADDR(usbp->epn_buffer[ep * 2 + 1]);
if (n > 0)
@ -145,21 +145,28 @@ static size_t usb_packet_receive(USBDriver *usbp, usbep_t ep) {
const USBEndpointConfig *epcp = usbp->epc[ep];
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
uint32_t n = (USB_EPLIST->entry[4 * ep] & EPLIST_ENTRY_NBYTES_MASK) >> EPLIST_ENTRY_NBYTES_POS;
n = epcp->out_maxsize - n;
const size_t xfer_size = (osp->rxsize > epcp->out_maxsize) ? epcp->out_maxsize : osp->rxsize;
n = xfer_size - n;
if (osp->rxbuf != NULL && n > 0) {
memcpy(osp->rxbuf, usbp->epn_buffer[ep * 2], n);
osp->rxbuf += n;
}
// ReSetup for recieve
USB_EPLIST->entry[4 * ep] &= ~0x3FFFFFF;
USB_EPLIST->entry[4 * ep] |= EPLIST_ENTRY_NBYTES(epcp->out_maxsize) |
EPLIST_ADDR(usbp->epn_buffer[ep * 2]);
if (osp->rxpkts > 0)
osp->rxpkts -= 1;
osp->rxcnt += n;
osp->rxsize -= n;
size_t next_xfer = (osp->rxsize > epcp->out_maxsize) ? epcp->out_maxsize : osp->rxsize;
USB_EPLIST->entry[4 * ep] &= ~(0x3FFFFFF | EPLIST_ENTRY_STALL | EPLIST_ENTRY_ACTIVE);
if (next_xfer > 0) {
// ReSetup for recieve
USB_EPLIST->entry[4 * ep] |= EPLIST_ENTRY_NBYTES(next_xfer) |
EPLIST_ADDR(usbp->epn_buffer[ep * 2]) | EPLIST_ENTRY_ACTIVE;
} else {
USB_EPLIST->entry[4 * ep] |= EPLIST_ENTRY_STALL;
}
return n;
}
@ -174,10 +181,9 @@ OSAL_IRQ_HANDLER(LPC_USB_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
USBDriver *usbp = &USBD1;
uint32_t isr = LPC_USB->INTSTAT;
#define devstat (LPC_USB->DEVCMDSTAT)
uint32_t isr = (LPC_USB->INTSTAT & LPC_USB->INTEN);
LPC_USB->INTSTAT &= 0xFFFFFFFF; // Clear Flags
#define devstat (LPC_USB->DEVCMDSTAT)
// SOF
if (isr & USB_INT_FRAME_INT) {
@ -212,13 +218,13 @@ OSAL_IRQ_HANDLER(LPC_USB_IRQ_VECTOR) {
} else {
// OUT endpoint, receive
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
osalSysLockFromISR();
size_t n = usb_packet_receive(usbp, ep);
osalSysUnlockFromISR();
if ((n < usbp->epc[0]->out_maxsize) || (osp->rxpkts == 0)) {
if (osp->rxsize > 0) {
osalSysLockFromISR();
usb_packet_receive(usbp, ep);
osalSysUnlockFromISR();
}
if (osp->rxsize == 0) { // TODO: Check if this is correct
_usb_isr_invoke_out_cb(usbp, ep);
} else {
USB_EPLIST->entry[4 * ep] |= EPLIST_ENTRY_ACTIVE;
}
}
}
@ -356,9 +362,9 @@ void usb_lld_reset(USBDriver *usbp) {
LPC_USB->DATABUFSTART = LPC_USB_SRAM_START & USB_DATABUFSTART_MASK;
// Clear Existing Interrupts
LPC_USB->INTSTAT = USB_INT_DEV_INT | USB_INT_FRAME_INT | USB_INT_EP_ALL_INT;
LPC_USB->INTSTAT |= USB_INT_DEV_INT | USB_INT_FRAME_INT | USB_INT_EP_ALL_INT;
// Setup Interrupt Masks
LPC_USB->INTEN = USB_INT_DEV_INT | USB_INT_EP_ALL_INT;
LPC_USB->INTEN = USB_INT_DEV_INT | 0b11;
// SOF only if there is a handler registered.
if ((usbp)->config->sof_cb != NULL) {
LPC_USB->INTEN |= USB_INT_FRAME_INT;
@ -425,32 +431,31 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
case USB_EP_MODE_TYPE_INTR:
break;
default:
while(1) {}
break;
}
if (epcp->out_state != NULL) {
while(epcp->out_maxsize > 1023);
if (epcp->out_state != NULL || ep == 0) {
uint32_t ep_mem = usb_ep_malloc(usbp, epcp->out_maxsize, 64);
usbp->epn_buffer[(2 * ep)] = (void *)ep_mem;
USB_EPLIST->entry[(4 * ep)] = usbep_cfg | EPLIST_ADDR(ep_mem)
| EPLIST_ENTRY_NBYTES(epcp->out_maxsize);
LPC_USB->INTEN |= USB_INT_EP((ep * 2));
}
if (ep == 0) {
while(usbp->setup_buffer != NULL){}
// Allocate Setup Bytes
uint32_t ep_mem = usb_ep_malloc(usbp, 8, 64);
usbp->setup_buffer = (void *)ep_mem;
USB_EPLIST->entry[1] = EPLIST_ADDR(ep_mem);
LPC_USB->INTEN |= USB_INT_EP(ep * 2);
}
if (epcp->in_state != NULL) {
while(epcp->in_maxsize > 1023);
if (epcp->in_state != NULL || ep == 0) {
uint32_t ep_mem = usb_ep_malloc(usbp, epcp->in_maxsize, 64);
usbp->epn_buffer[(2 * ep) + 1] = (void *)ep_mem;
USB_EPLIST->entry[(4 * ep) + 2] = usbep_cfg | EPLIST_ADDR(ep_mem)
| EPLIST_ENTRY_NBYTES(epcp->in_maxsize);
LPC_USB->INTEN |= USB_INT_EP((ep * 2) + 1);
LPC_USB->INTEN |= USB_INT_EP(((ep * 2) + 1));
}
}
@ -469,10 +474,10 @@ void usb_lld_disable_endpoints(USBDriver *usbp) {
while (LPC_USB->EPSKIP) {}
for (int i = 1; i < 5; ++i) // 4 EPs needs to be disabled, EP0 can't
{
USB_EPLIST->entry[i * 2] &= ~EP_STATUS_ACTIVE;
USB_EPLIST->entry[i * 2] |= EP_STATUS_DISABLED;
USB_EPLIST->entry[i * 2 + 2] &= ~EP_STATUS_ACTIVE;
USB_EPLIST->entry[i * 2 + 2] |= EP_STATUS_DISABLED;
USB_EPLIST->entry[i * 4] &= ~EP_STATUS_ACTIVE;
USB_EPLIST->entry[i * 4] |= EP_STATUS_DISABLED;
USB_EPLIST->entry[i * 4 + 2] &= ~EP_STATUS_ACTIVE;
USB_EPLIST->entry[i * 4 + 2] |= EP_STATUS_DISABLED;
}
}
@ -491,9 +496,9 @@ void usb_lld_disable_endpoints(USBDriver *usbp) {
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return EP_STATUS_DISABLED;
if (USB_EPLIST->entry[ep * 2] & EPLIST_ENTRY_DISABLE) {
if (USB_EPLIST->entry[ep * 4] & EPLIST_ENTRY_DISABLE) {
return EP_STATUS_DISABLED;
} else if (USB_EPLIST->entry[ep * 2] & EPLIST_ENTRY_STALL) {
} else if (USB_EPLIST->entry[ep * 4] & EPLIST_ENTRY_STALL) {
return EP_STATUS_STALLED;
} else {
return EP_STATUS_ACTIVE;
@ -515,9 +520,9 @@ usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) {
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return EP_STATUS_DISABLED;
if (USB_EPLIST->entry[ep * 2 + 2] & EPLIST_ENTRY_DISABLE) {
if (USB_EPLIST->entry[ep * 4 + 2] & EPLIST_ENTRY_DISABLE) {
return EP_STATUS_DISABLED;
} else if (USB_EPLIST->entry[ep * 2 + 2] & EPLIST_ENTRY_STALL) {
} else if (USB_EPLIST->entry[ep * 4 + 2] & EPLIST_ENTRY_STALL) {
return EP_STATUS_STALLED;
} else {
return EP_STATUS_ACTIVE;
@ -546,11 +551,8 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
USB_EPLIST->entry[0] &= ~(EPLIST_ENTRY_STALL | EPLIST_ENTRY_ACTIVE); // EP0OUT
USB_EPLIST->entry[2] &= ~(EPLIST_ENTRY_STALL | EPLIST_ENTRY_ACTIVE); // EP0IN
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_SETUP; // Clear SETUP
LPC_USB->DEVCMDSTAT &= ~(USB_DEVCMDSTAT_INTONNAK_CO | USB_DEVCMDSTAT_INTONNAK_CI);
memcpy(buf, usbp->setup_buffer, 8);
USB_EPLIST->entry[1] = EPLIST_ADDR(usbp->setup_buffer);
} else {
while(1){}
}
}
}
@ -567,19 +569,28 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
const USBEndpointConfig *epcp = usbp->epc[ep];
if (osp->rxsize == 0) /* Special case for zero sized packets.*/
osp->rxpkts = 1;
else
osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
usbp->epc[ep]->out_maxsize);
size_t rx_size = 0;
USB_EPLIST->entry[ep * 4] &= ~0x3FFFFFF;
if (osp->rxsize == 0) { /* Special case for zero sized packets.*/
osp->rxpkts = 1;
rx_size = 0;
} else {
osp->rxpkts = (uint16_t)((osp->rxsize + epcp->out_maxsize - 1) /
epcp->out_maxsize);
if (osp->rxsize > epcp->out_maxsize) {
rx_size = epcp->out_maxsize;
} else {
rx_size = osp->rxsize;
}
}
USB_EPLIST->entry[ep * 4] &= ~(0x3FFFFFF | EPLIST_ENTRY_STALL | EPLIST_ENTRY_ACTIVE);
USB_EPLIST->entry[ep * 4] |= EPLIST_ENTRY_ACTIVE |
EPLIST_ENTRY_NBYTES(epcp->out_maxsize) |
EPLIST_ENTRY_NBYTES(rx_size) |
EPLIST_ADDR(usbp->epn_buffer[ep * 2]);
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_INTONNAK_CO;
LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_INTONNAK_CI;
if (ep == 0)
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_INTONNAK_CO;
}
/**