diff --git a/hal/usb/TARGET_Templates/USBPhyHw.h b/hal/usb/TARGET_Templates/USBPhyHw.h new file mode 100644 index 0000000..1476fa7 --- /dev/null +++ b/hal/usb/TARGET_Templates/USBPhyHw.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018-2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef USBPHYHW_H +#define USBPHYHW_H + +#include "mbed.h" +#include "USBPhy.h" + + +class USBPhyHw : public USBPhy { +public: + USBPhyHw(); + virtual ~USBPhyHw(); + virtual void init(USBPhyEvents *events); + virtual void deinit(); + virtual bool powered(); + virtual void connect(); + virtual void disconnect(); + virtual void configure(); + virtual void unconfigure(); + virtual void sof_enable(); + virtual void sof_disable(); + virtual void set_address(uint8_t address); + virtual void remote_wakeup(); + virtual const usb_ep_table_t *endpoint_table(); + + virtual uint32_t ep0_set_max_packet(uint32_t max_packet); + virtual void ep0_setup_read_result(uint8_t *buffer, uint32_t size); + virtual void ep0_read(uint8_t *data, uint32_t size); + virtual uint32_t ep0_read_result(); + virtual void ep0_write(uint8_t *buffer, uint32_t size); + virtual void ep0_stall(); + + virtual bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type); + virtual void endpoint_remove(usb_ep_t endpoint); + virtual void endpoint_stall(usb_ep_t endpoint); + virtual void endpoint_unstall(usb_ep_t endpoint); + + virtual bool endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size); + virtual uint32_t endpoint_read_result(usb_ep_t endpoint); + virtual bool endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size); + virtual void endpoint_abort(usb_ep_t endpoint); + + virtual void process(); + +private: + USBPhyEvents *events; + + static void _usbisr(void); +}; + +#endif diff --git a/hal/usb/TARGET_Templates/USBPhy_template.cpp b/hal/usb/TARGET_Templates/USBPhy_template.cpp new file mode 100644 index 0000000..fe0d559 --- /dev/null +++ b/hal/usb/TARGET_Templates/USBPhy_template.cpp @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2018-2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "USBPhyHw.h" + +static USBPhyHw *instance; + +USBPhy *get_usb_phy() +{ + static USBPhyHw usbphy; + return &usbphy; +} + +USBPhyHw::USBPhyHw(): events(NULL) +{ + +} + +USBPhyHw::~USBPhyHw() +{ + +} + +void USBPhyHw::init(USBPhyEvents *events) +{ + this->events = events; + + // Disable IRQ + NVIC_DisableIRQ(USB_IRQn); + + // TODO - Setup clocks + + // TODO - Enable USB module + + // Enable IRQ + NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr); + NVIC_EnableIRQ(USB_IRQn); +} + +void USBPhyHw::deinit() +{ + // Disconnect and disable interrupt + disconnect(); + NVIC_DisableIRQ(USB_IRQn); +} + +bool USBPhyHw::powered() +{ + // TODO - return true if powered false otherwise. Devices which don't support + // this should always return true + return true; +} + +void USBPhyHw::connect() +{ + // TODO - Enable endpoint interrupts + + // TODO - Enable pullup on D+ +} + +void USBPhyHw::disconnect() +{ + // TODO - Disable all endpoints + + // TODO - Clear all endpoint interrupts + + // TODO - Disable pullup on D+ +} + +void USBPhyHw::configure() +{ + // TODO - set device to configured. Most device will not need this +} + +void USBPhyHw::unconfigure() +{ + // TODO - set device to unconfigured. Most device will not need this +} + +void USBPhyHw::sof_enable() +{ + // TODO - Enable SOF interrupt +} + +void USBPhyHw::sof_disable() +{ + // TODO - Disable SOF interrupt +} + +void USBPhyHw::set_address(uint8_t address) +{ + // TODO - set the device address. Address must take effect + // after the status phase of the current transfer +} + +void USBPhyHw::remote_wakeup() +{ + // TODO - Sent remote wakeup over USB lines (if supported) +} + +const usb_ep_table_t *USBPhyHw::endpoint_table() +{ + // TODO - Update the endpoint table for what your device supports + + static const usb_ep_table_t template_table = { + 4096 - 32 * 4, // 32 words for endpoint buffers + // +3 based added to interrupt and isochronous to ensure enough + // space for 4 byte alignment + { + {USB_EP_ATTR_ALLOW_CTRL | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 0}, + {USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, + {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}, + {USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, + {USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, + {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}, + {USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, + {USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, + {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}, + {USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, + {USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, + {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}, + {USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, + {USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, + {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}, + {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0} + } + }; + return &lpc_table; +} + +uint32_t USBPhyHw::ep0_set_max_packet(uint32_t max_packet) +{ + // TODO - set endpoint 0 size and return this size + return 64; +} + +// read setup packet +void USBPhyHw::ep0_setup_read_result(uint8_t *buffer, uint32_t size) +{ + // TODO - read up to size bytes of the setup packet +} + +void USBPhyHw::ep0_read(uint8_t *data, uint32_t size) +{ + // TODO - setup data buffer to receive next endpoint 0 OUT packet +} + +uint32_t USBPhyHw::ep0_read_result() +{ + // TODO - return the size of the last OUT packet received on endpoint 0 + return 0; +} + +void USBPhyHw::ep0_write(uint8_t *buffer, uint32_t size) +{ + // TODO - start transferring buffer on endpoint 0 IN +} + +void USBPhyHw::ep0_stall() +{ + // TODO - protocol stall endpoint 0. This stall must be automatically + // cleared by the next setup packet +} + +bool USBPhyHw::endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type) +{ + // TODO - enable this endpoint + + return true; +} + +void USBPhyHw::endpoint_remove(usb_ep_t endpoint) +{ + // TODO - disable and remove this endpoint +} + +void USBPhyHw::endpoint_stall(usb_ep_t endpoint) +{ + // TODO - stall this endpoint until it is explicitly cleared +} + +void USBPhyHw::endpoint_unstall(usb_ep_t endpoint) +{ + // TODO - unstall this endpoint +} + +bool USBPhyHw::endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size) +{ + // TODO - setup data buffer to receive next endpoint OUT packet and return true if successful + return true; +} + +uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint) +{ + // TODO - return the size of the last OUT packet received on endpoint +} + +bool USBPhyHw::endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size) +{ + // TODO - start transferring buffer on endpoint IN + + return true; +} + +void USBPhyHw::endpoint_abort(usb_ep_t endpoint) +{ + // TODO - stop the current transfer on this endpoint and don't call the IN or OUT callback +} + +void USBPhyHw::process() +{ + // TODO - update register for your mcu + + uint8_t stat = USB0->STAT; + + USB0->STAT = stat; // Clear pending interrupts + + // reset interrupt + if (stat & USB_STAT_RESET_MASK) { + + // TODO - disable all endpoints + + // TODO - clear all endpoint interrupts + + // TODO - enable control endpoint + + // reset bus for USBDevice layer + events->reset(); + + // Re-enable interrupt + NVIC_ClearPendingIRQ(USB_IRQn); + NVIC_EnableIRQ(USB_IRQn); + return; + } + + // power applied + if (stat & USB_STAT_POWERED) { + events->powered(true); + } + + // power lost + if (stat & USB_STAT_UNPOWERED) { + events->powered(false); + } + + // sleep interrupt + if (stat & USB_STAT_SUSPEND_MASK) { + events->suspend(true); + } + + // resume interrupt + if (stat & USB_STAT_RESUME_MASK) { + events->suspend(false); + } + + // sof interrupt + if (stat & USB_STAT_SOF_MASK) { + // SOF event, read frame number + events->sof(USB0->FRAME); + } + + // endpoint interrupt + if (stat & USB_STAT_EP_MASK) { + uint32_t ep_pending = USB->EP; + + // TODO - call endpoint 0 IN callback if pending + events->ep0_in(); + + // TODO - call endpoint 0 OUT callback if pending + events->ep0_out(); + + // TODO - call endpoint 0 SETUP callback if pending + events->ep0_setup(); + + for (int i = 0; i < 16; i++) { + // TODO - call endpoint i IN callback if pending + events->in(0x80 | i); + } + + for (int i = 0; i < 16; i++) { + // TODO - call endpoint i OUT callback if pending + events->out(); + } + + USB->EP = ep_pending; // clear pending + } + + // Re-enable interrupt + NVIC_ClearPendingIRQ(USB_IRQn); + NVIC_EnableIRQ(USB_IRQn); +} + +void USBPhyHw::_usbisr(void) +{ + NVIC_DisableIRQ(USB_IRQn); + instance->events->start_process(); +} diff --git a/targets/TARGET_Templates/USBPhyHw.h b/targets/TARGET_Templates/USBPhyHw.h deleted file mode 100644 index 1476fa7..0000000 --- a/targets/TARGET_Templates/USBPhyHw.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited and affiliates. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef USBPHYHW_H -#define USBPHYHW_H - -#include "mbed.h" -#include "USBPhy.h" - - -class USBPhyHw : public USBPhy { -public: - USBPhyHw(); - virtual ~USBPhyHw(); - virtual void init(USBPhyEvents *events); - virtual void deinit(); - virtual bool powered(); - virtual void connect(); - virtual void disconnect(); - virtual void configure(); - virtual void unconfigure(); - virtual void sof_enable(); - virtual void sof_disable(); - virtual void set_address(uint8_t address); - virtual void remote_wakeup(); - virtual const usb_ep_table_t *endpoint_table(); - - virtual uint32_t ep0_set_max_packet(uint32_t max_packet); - virtual void ep0_setup_read_result(uint8_t *buffer, uint32_t size); - virtual void ep0_read(uint8_t *data, uint32_t size); - virtual uint32_t ep0_read_result(); - virtual void ep0_write(uint8_t *buffer, uint32_t size); - virtual void ep0_stall(); - - virtual bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type); - virtual void endpoint_remove(usb_ep_t endpoint); - virtual void endpoint_stall(usb_ep_t endpoint); - virtual void endpoint_unstall(usb_ep_t endpoint); - - virtual bool endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size); - virtual uint32_t endpoint_read_result(usb_ep_t endpoint); - virtual bool endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size); - virtual void endpoint_abort(usb_ep_t endpoint); - - virtual void process(); - -private: - USBPhyEvents *events; - - static void _usbisr(void); -}; - -#endif diff --git a/targets/TARGET_Templates/USBPhy_template.cpp b/targets/TARGET_Templates/USBPhy_template.cpp deleted file mode 100644 index fe0d559..0000000 --- a/targets/TARGET_Templates/USBPhy_template.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited and affiliates. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "USBPhyHw.h" - -static USBPhyHw *instance; - -USBPhy *get_usb_phy() -{ - static USBPhyHw usbphy; - return &usbphy; -} - -USBPhyHw::USBPhyHw(): events(NULL) -{ - -} - -USBPhyHw::~USBPhyHw() -{ - -} - -void USBPhyHw::init(USBPhyEvents *events) -{ - this->events = events; - - // Disable IRQ - NVIC_DisableIRQ(USB_IRQn); - - // TODO - Setup clocks - - // TODO - Enable USB module - - // Enable IRQ - NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr); - NVIC_EnableIRQ(USB_IRQn); -} - -void USBPhyHw::deinit() -{ - // Disconnect and disable interrupt - disconnect(); - NVIC_DisableIRQ(USB_IRQn); -} - -bool USBPhyHw::powered() -{ - // TODO - return true if powered false otherwise. Devices which don't support - // this should always return true - return true; -} - -void USBPhyHw::connect() -{ - // TODO - Enable endpoint interrupts - - // TODO - Enable pullup on D+ -} - -void USBPhyHw::disconnect() -{ - // TODO - Disable all endpoints - - // TODO - Clear all endpoint interrupts - - // TODO - Disable pullup on D+ -} - -void USBPhyHw::configure() -{ - // TODO - set device to configured. Most device will not need this -} - -void USBPhyHw::unconfigure() -{ - // TODO - set device to unconfigured. Most device will not need this -} - -void USBPhyHw::sof_enable() -{ - // TODO - Enable SOF interrupt -} - -void USBPhyHw::sof_disable() -{ - // TODO - Disable SOF interrupt -} - -void USBPhyHw::set_address(uint8_t address) -{ - // TODO - set the device address. Address must take effect - // after the status phase of the current transfer -} - -void USBPhyHw::remote_wakeup() -{ - // TODO - Sent remote wakeup over USB lines (if supported) -} - -const usb_ep_table_t *USBPhyHw::endpoint_table() -{ - // TODO - Update the endpoint table for what your device supports - - static const usb_ep_table_t template_table = { - 4096 - 32 * 4, // 32 words for endpoint buffers - // +3 based added to interrupt and isochronous to ensure enough - // space for 4 byte alignment - { - {USB_EP_ATTR_ALLOW_CTRL | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 0}, - {USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, - {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}, - {USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, - {USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, - {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}, - {USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, - {USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, - {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}, - {USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, - {USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, - {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}, - {USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, - {USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3}, - {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}, - {USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0} - } - }; - return &lpc_table; -} - -uint32_t USBPhyHw::ep0_set_max_packet(uint32_t max_packet) -{ - // TODO - set endpoint 0 size and return this size - return 64; -} - -// read setup packet -void USBPhyHw::ep0_setup_read_result(uint8_t *buffer, uint32_t size) -{ - // TODO - read up to size bytes of the setup packet -} - -void USBPhyHw::ep0_read(uint8_t *data, uint32_t size) -{ - // TODO - setup data buffer to receive next endpoint 0 OUT packet -} - -uint32_t USBPhyHw::ep0_read_result() -{ - // TODO - return the size of the last OUT packet received on endpoint 0 - return 0; -} - -void USBPhyHw::ep0_write(uint8_t *buffer, uint32_t size) -{ - // TODO - start transferring buffer on endpoint 0 IN -} - -void USBPhyHw::ep0_stall() -{ - // TODO - protocol stall endpoint 0. This stall must be automatically - // cleared by the next setup packet -} - -bool USBPhyHw::endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type) -{ - // TODO - enable this endpoint - - return true; -} - -void USBPhyHw::endpoint_remove(usb_ep_t endpoint) -{ - // TODO - disable and remove this endpoint -} - -void USBPhyHw::endpoint_stall(usb_ep_t endpoint) -{ - // TODO - stall this endpoint until it is explicitly cleared -} - -void USBPhyHw::endpoint_unstall(usb_ep_t endpoint) -{ - // TODO - unstall this endpoint -} - -bool USBPhyHw::endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size) -{ - // TODO - setup data buffer to receive next endpoint OUT packet and return true if successful - return true; -} - -uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint) -{ - // TODO - return the size of the last OUT packet received on endpoint -} - -bool USBPhyHw::endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size) -{ - // TODO - start transferring buffer on endpoint IN - - return true; -} - -void USBPhyHw::endpoint_abort(usb_ep_t endpoint) -{ - // TODO - stop the current transfer on this endpoint and don't call the IN or OUT callback -} - -void USBPhyHw::process() -{ - // TODO - update register for your mcu - - uint8_t stat = USB0->STAT; - - USB0->STAT = stat; // Clear pending interrupts - - // reset interrupt - if (stat & USB_STAT_RESET_MASK) { - - // TODO - disable all endpoints - - // TODO - clear all endpoint interrupts - - // TODO - enable control endpoint - - // reset bus for USBDevice layer - events->reset(); - - // Re-enable interrupt - NVIC_ClearPendingIRQ(USB_IRQn); - NVIC_EnableIRQ(USB_IRQn); - return; - } - - // power applied - if (stat & USB_STAT_POWERED) { - events->powered(true); - } - - // power lost - if (stat & USB_STAT_UNPOWERED) { - events->powered(false); - } - - // sleep interrupt - if (stat & USB_STAT_SUSPEND_MASK) { - events->suspend(true); - } - - // resume interrupt - if (stat & USB_STAT_RESUME_MASK) { - events->suspend(false); - } - - // sof interrupt - if (stat & USB_STAT_SOF_MASK) { - // SOF event, read frame number - events->sof(USB0->FRAME); - } - - // endpoint interrupt - if (stat & USB_STAT_EP_MASK) { - uint32_t ep_pending = USB->EP; - - // TODO - call endpoint 0 IN callback if pending - events->ep0_in(); - - // TODO - call endpoint 0 OUT callback if pending - events->ep0_out(); - - // TODO - call endpoint 0 SETUP callback if pending - events->ep0_setup(); - - for (int i = 0; i < 16; i++) { - // TODO - call endpoint i IN callback if pending - events->in(0x80 | i); - } - - for (int i = 0; i < 16; i++) { - // TODO - call endpoint i OUT callback if pending - events->out(); - } - - USB->EP = ep_pending; // clear pending - } - - // Re-enable interrupt - NVIC_ClearPendingIRQ(USB_IRQn); - NVIC_EnableIRQ(USB_IRQn); -} - -void USBPhyHw::_usbisr(void) -{ - NVIC_DisableIRQ(USB_IRQn); - instance->events->start_process(); -}