blackmagic/lib/stm32/st_usbfs_v2.c
Karl Palsson f5eb96caf3 usb: Add st_usbfs_v2 for f0/l0 devices
Based on previous work, add a new driver for the v2 usb peripheral found on
stm32f0 and l0 devices.

Correspondingly, add a usb gadget zero test suite for the f0.  L0 device level
code isn't yet ready, but will add the test case when it moves in.

Work by Frantisek Burian, Kuldeep
Singh Dhaka, Robin Kreis, fenugrec and zyp on irc, and all those forgotten.
2015-10-03 02:03:58 +00:00

94 lines
2.8 KiB
C

/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2014 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/cm3/common.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/tools.h>
#include <libopencm3/stm32/st_usbfs.h>
#include <libopencm3/usb/usbd.h>
#include "../usb/usb_private.h"
#include "common/st_usbfs_core.h"
static usbd_device *st_usbfs_v2_usbd_init(void);
const struct _usbd_driver st_usbfs_v2_usb_driver = {
.init = st_usbfs_v2_usbd_init,
.set_address = st_usbfs_set_address,
.ep_setup = st_usbfs_ep_setup,
.ep_reset = st_usbfs_endpoints_reset,
.ep_stall_set = st_usbfs_ep_stall_set,
.ep_stall_get = st_usbfs_ep_stall_get,
.ep_nak_set = st_usbfs_ep_nak_set,
.ep_write_packet = st_usbfs_ep_write_packet,
.ep_read_packet = st_usbfs_ep_read_packet,
.poll = st_usbfs_poll,
};
/** Initialize the USB device controller hardware of the STM32. */
static usbd_device *st_usbfs_v2_usbd_init(void)
{
rcc_periph_clock_enable(RCC_USB);
SET_REG(USB_CNTR_REG, 0);
SET_REG(USB_BTABLE_REG, 0);
SET_REG(USB_ISTR_REG, 0);
/* Enable RESET, SUSPEND, RESUME and CTR interrupts. */
SET_REG(USB_CNTR_REG, USB_CNTR_RESETM | USB_CNTR_CTRM |
USB_CNTR_SUSPM | USB_CNTR_WKUPM);
SET_REG(USB_BCDR_REG, USB_BCDR_DPPU);
return &st_usbfs_dev;
}
void st_usbfs_copy_to_pm(volatile void *vPM, const void *buf, uint16_t len)
{
/*
* This is a bytewise copy, so it always works, even on CM0(+)
* that don't support unaligned accesses.
*/
const uint8_t *lbuf = buf;
volatile uint16_t *PM = vPM;
uint32_t i;
for (i = 0; i < len; i += 2) {
*PM++ = (uint16_t)lbuf[i+1] << 8 | lbuf[i];
}
}
/**
* Copy a data buffer from packet memory.
*
* @param buf Source pointer to data buffer.
* @param vPM Destination pointer into packet memory.
* @param len Number of bytes to copy.
*/
void st_usbfs_copy_from_pm(void *buf, const volatile void *vPM, uint16_t len)
{
uint16_t *lbuf = buf;
const volatile uint16_t *PM = vPM;
uint8_t odd = len & 1;
for (len >>= 1; len; PM++, lbuf++, len--) {
*lbuf = *PM;
}
if (odd) {
*(uint8_t *) lbuf = *(uint8_t *) PM;
}
}