Reviewing functions. Added critical sections to some functions that access state information.

pull/10689/head
George Beckstein 2019-01-09 23:29:35 -05:00 committed by aglass0fmilk
parent f00053820b
commit c006888557
1 changed files with 52 additions and 18 deletions

View File

@ -16,8 +16,31 @@
#include "USBPhyHw.h" #include "USBPhyHw.h"
#include "platform/mbed_critical.h"
#include "nrf_clock.h" #include "nrf_clock.h"
/*
* TODO list for nRF52840 USBD driver
*
* 1.) Properly enable/disable start-of-frame interrupt.
*
* Description: Currently, start-of-frame interrupts are masked by a flag at this layer
* but still cause the processor to be interrupted for no purpose.
*
* The Nordic driver requires you to call nrf_drv_start(bool)
* with a boolean flag indicating whether it should enable start-of-frame
* interrupts or not. From the datasheet it seems to be possible to
* enable/disable SoF interrupts on the fly, but the fact that they
* force you to make the SoF decision during "start" makes me suspicious
* the underlying driver may manage/use the SoF flag in other ways.
*
* Next steps: Investigate how the SoF flag is used during "nrf_drv_start" and
* determine if enabling/disabling this interrupt would cause internal problems
* with the Nordic USBD driver
*
*
*/
#define MAX_PACKET_SIZE_SETUP NRF_DRV_USBD_EPSIZE #define MAX_PACKET_SIZE_SETUP NRF_DRV_USBD_EPSIZE
#define MAX_PACKET_NON_ISO NRF_DRV_USBD_EPSIZE #define MAX_PACKET_NON_ISO NRF_DRV_USBD_EPSIZE
#define MAX_PACKET_ISO NRF_DRV_USBD_ISOSIZE #define MAX_PACKET_ISO NRF_DRV_USBD_ISOSIZE
@ -79,11 +102,6 @@ void USBPhyHw::init(USBPhyEvents *events) {
ret = nrf_drv_power_init(NULL); ret = nrf_drv_power_init(NULL);
APP_ERROR_CHECK(ret); APP_ERROR_CHECK(ret);
/* Configure selected size of the packed on EP0 */
nrf_drv_usbd_ep_max_packet_size_set(NRF_DRV_USBD_EPOUT0, MAX_PACKET_SIZE_SETUP);
nrf_drv_usbd_ep_max_packet_size_set(NRF_DRV_USBD_EPIN0, MAX_PACKET_SIZE_SETUP);
// Register callback for USB Power events // Register callback for USB Power events
static const nrf_drv_power_usbevt_config_t config = { .handler = static const nrf_drv_power_usbevt_config_t config = { .handler =
power_usb_event_handler }; power_usb_event_handler };
@ -94,13 +112,17 @@ void USBPhyHw::init(USBPhyEvents *events) {
ret = nrf_drv_usbd_init(usbd_event_handler); ret = nrf_drv_usbd_init(usbd_event_handler);
APP_ERROR_CHECK(ret); APP_ERROR_CHECK(ret);
/* Configure selected size of the packed on EP0 */
nrf_drv_usbd_ep_max_packet_size_set(NRF_DRV_USBD_EPOUT0, MAX_PACKET_SIZE_SETUP);
nrf_drv_usbd_ep_max_packet_size_set(NRF_DRV_USBD_EPIN0, MAX_PACKET_SIZE_SETUP);
// Store a reference to this instance // Store a reference to this instance
instance = this; instance = this;
// Enable IRQ // Enable IRQ
NVIC_SetVector(USBD_IRQn, (uint32_t)USBD_IRQHandler); NVIC_SetVector(USBD_IRQn, (uint32_t)USBD_IRQHandler);
NVIC_SetPriority(USBD_IRQn, 7); //NVIC_SetPriority(USBD_IRQn, 7);
NVIC_EnableIRQ(USBD_IRQn); //NVIC_EnableIRQ(USBD_IRQn); // This is handled by the Nordic driver
} }
void USBPhyHw::deinit() { void USBPhyHw::deinit() {
@ -109,10 +131,13 @@ void USBPhyHw::deinit() {
// Disable the USB Device driver // Disable the USB Device driver
ret_code_t ret = nrf_drv_usbd_uninit(); ret_code_t ret = nrf_drv_usbd_uninit();
APP_ERROR_CHECK(ret); APP_ERROR_CHECK(ret);
NVIC_DisableIRQ(USBD_IRQn); //NVIC_DisableIRQ(USBD_IRQn); // This is handled by the Nordic driver
// Clear the instance pointer? // Disable the power peripheral driver
//instance = 0; nrf_drv_power_uninit();
// Clear the instance pointer
instance = 0;
} }
bool USBPhyHw::powered() { bool USBPhyHw::powered() {
@ -142,7 +167,7 @@ void USBPhyHw::connect() {
if(nrf_drv_power_usbstatus_get() == NRF_DRV_POWER_USB_STATE_READY if(nrf_drv_power_usbstatus_get() == NRF_DRV_POWER_USB_STATE_READY
&& !nrf_drv_usbd_is_started()) && !nrf_drv_usbd_is_started())
nrf_drv_usbd_start(false);//nrf_drv_usbd_start(true); nrf_drv_usbd_start(true);
} }
} }
@ -152,8 +177,8 @@ void USBPhyHw::disconnect() {
if(nrf_drv_usbd_is_started()) if(nrf_drv_usbd_is_started())
nrf_drv_usbd_stop(); nrf_drv_usbd_stop();
// if(nrf_drv_usbd_is_enabled()) if(nrf_drv_usbd_is_enabled())
// nrf_drv_usbd_disable(); nrf_drv_usbd_disable();
} }
void USBPhyHw::configure() { void USBPhyHw::configure() {
@ -214,20 +239,30 @@ const usb_ep_table_t *USBPhyHw::endpoint_table() {
} }
uint32_t USBPhyHw::ep0_set_max_packet(uint32_t max_packet) { uint32_t USBPhyHw::ep0_set_max_packet(uint32_t max_packet) {
disable_usb_interrupts();
if (max_packet > MAX_PACKET_SIZE_SETUP) if (max_packet > MAX_PACKET_SIZE_SETUP)
max_packet = MAX_PACKET_SIZE_SETUP; max_packet = MAX_PACKET_SIZE_SETUP;
nrf_drv_usbd_ep_max_packet_size_set(NRF_DRV_USBD_EPOUT0, max_packet); nrf_drv_usbd_ep_max_packet_size_set(NRF_DRV_USBD_EPOUT0, max_packet);
nrf_drv_usbd_ep_max_packet_size_set(NRF_DRV_USBD_EPIN0, max_packet); nrf_drv_usbd_ep_max_packet_size_set(NRF_DRV_USBD_EPIN0, max_packet);
enable_usb_interrupts();
return max_packet; return max_packet;
} }
// read setup packet // read setup packet
void USBPhyHw::ep0_setup_read_result(uint8_t *buffer, uint32_t size) { void USBPhyHw::ep0_setup_read_result(uint8_t *buffer, uint32_t size) {
disable_usb_interrupts();
if (size > sizeof(this->setup_buf)) { if (size > sizeof(this->setup_buf)) {
size = sizeof(this->setup_buf); size = sizeof(this->setup_buf);
} }
memcpy(buffer, &this->setup_buf, size); memcpy(buffer, &this->setup_buf, size);
enable_usb_interrupts();
} }
void USBPhyHw::ep0_read(uint8_t *data, uint32_t size) { void USBPhyHw::ep0_read(uint8_t *data, uint32_t size) {
@ -454,10 +489,10 @@ void USBPhyHw::process() {
events->power(false); events->power(false);
break; break;
case NRF_DRV_POWER_USB_EVT_READY: case NRF_DRV_POWER_USB_EVT_READY:
if(this->connect_enabled) { //if(this->connect_enabled) { // Not really necessary (only happens after enabled)
if(!nrf_drv_usbd_is_started()) if(!nrf_drv_usbd_is_started())
nrf_drv_usbd_start(false);//nrf_drv_usbd_start(true); nrf_drv_usbd_start(true);
} //}
break; break;
default: default:
ASSERT(false); ASSERT(false);
@ -468,7 +503,7 @@ void USBPhyHw::process() {
usb_event_type = USB_HW_EVENT_NONE; usb_event_type = USB_HW_EVENT_NONE;
// Re-enable interrupt // Re-enable interrupt
NVIC_ClearPendingIRQ(USBD_IRQn); //NVIC_ClearPendingIRQ(USBD_IRQn);
enable_usb_interrupts(); enable_usb_interrupts();
} }
@ -541,7 +576,6 @@ static void power_usb_event_handler(nrf_drv_power_usb_evt_t event) {
static void usbd_event_handler(nrf_drv_usbd_evt_t const * const p_event) { static void usbd_event_handler(nrf_drv_usbd_evt_t const * const p_event) {
if(instance) { if(instance) {
NVIC_DisableIRQ(USBD_IRQn);
// Pass the event on to the USBPhyHW instance // Pass the event on to the USBPhyHW instance
instance->_usb_event_handler(p_event); instance->_usb_event_handler(p_event);
} }