TheLegace

STM32F4

Feb 2nd, 2013
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.21 KB | None | 0 0
  1. /*
  2.  * This file is part of the libopencm3 project.
  3.  *
  4.  * Copyright (C) 2010 Gareth McMullin <[email protected]>
  5.  *
  6.  * This library is free software: you can redistribute it and/or modify
  7.  * it under the terms of the GNU Lesser General Public License as published by
  8.  * the Free Software Foundation, either version 3 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public License
  17.  * along with this library.  If not, see <http://www.gnu.org/licenses/>.
  18.  */
  19.  
  20. #include <stdlib.h>
  21. #include <libopencm3/stm32/f4/rcc.h>
  22. #include <libopencm3/stm32/f4/gpio.h>
  23. #include <libopencm3/usb/usbd.h>
  24. #include <libopencm3/usb/cdc.h>
  25. #include <libopencm3/cm3/scb.h>
  26. #include <libopencm3/stm32/timer.h>
  27. #include <libopencm3/cm3/nvic.h>
  28. #include "ring.h"
  29. #include "fourbyte.h"
  30.  
  31. #define RX_BUFFER_SIZE    128
  32. static struct ring rx_ring;
  33. static u8 rx_buffer[RX_BUFFER_SIZE];
  34. static usbd_device *usbd_dev;
  35.  
  36. static const struct usb_device_descriptor dev = {
  37.     .bLength = USB_DT_DEVICE_SIZE,
  38.     .bDescriptorType = USB_DT_DEVICE,
  39.     .bcdUSB = 0x0200,
  40.     .bDeviceClass = USB_CLASS_CDC,
  41.     .bDeviceSubClass = 0,
  42.     .bDeviceProtocol = 0,
  43.     .bMaxPacketSize0 = 64,
  44.     .idVendor = 0x0483,
  45.     .idProduct = 0x5740,
  46.     .bcdDevice = 0x0200,
  47.     .iManufacturer = 1,
  48.     .iProduct = 2,
  49.     .iSerialNumber = 3,
  50.     .bNumConfigurations = 1,
  51. };
  52.  
  53. /*
  54.  * This notification endpoint isn't implemented. According to CDC spec it's
  55.  * optional, but its absence causes a NULL pointer dereference in the
  56.  * Linux cdc_acm driver.
  57.  */
  58. static const struct usb_endpoint_descriptor comm_endp[] = {{
  59.     .bLength = USB_DT_ENDPOINT_SIZE,
  60.     .bDescriptorType = USB_DT_ENDPOINT,
  61.     .bEndpointAddress = 0x83,
  62.     .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
  63.     .wMaxPacketSize = 16,
  64.     .bInterval = 255,
  65. }};
  66.  
  67. static const struct usb_endpoint_descriptor data_endp[] = {{
  68.     .bLength = USB_DT_ENDPOINT_SIZE,
  69.     .bDescriptorType = USB_DT_ENDPOINT,
  70.     .bEndpointAddress = 0x01,
  71.     .bmAttributes = USB_ENDPOINT_ATTR_BULK,
  72.     .wMaxPacketSize = 64,
  73.     .bInterval = 1,
  74. }, {
  75.     .bLength = USB_DT_ENDPOINT_SIZE,
  76.     .bDescriptorType = USB_DT_ENDPOINT,
  77.     .bEndpointAddress = 0x82,
  78.     .bmAttributes = USB_ENDPOINT_ATTR_BULK,
  79.     .wMaxPacketSize = 64,
  80.     .bInterval = 1,
  81. }};
  82.  
  83. static const struct {
  84.     struct usb_cdc_header_descriptor header;
  85.     struct usb_cdc_call_management_descriptor call_mgmt;
  86.     struct usb_cdc_acm_descriptor acm;
  87.     struct usb_cdc_union_descriptor cdc_union;
  88. } __attribute__((packed)) cdcacm_functional_descriptors = {
  89.     .header = {
  90.         .bFunctionLength = sizeof(struct usb_cdc_header_descriptor),
  91.         .bDescriptorType = CS_INTERFACE,
  92.         .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
  93.         .bcdCDC = 0x0110,
  94.     },
  95.     .call_mgmt = {
  96.         .bFunctionLength =
  97.             sizeof(struct usb_cdc_call_management_descriptor),
  98.         .bDescriptorType = CS_INTERFACE,
  99.         .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
  100.         .bmCapabilities = 0,
  101.         .bDataInterface = 1,
  102.     },
  103.     .acm = {
  104.         .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
  105.         .bDescriptorType = CS_INTERFACE,
  106.         .bDescriptorSubtype = USB_CDC_TYPE_ACM,
  107.         .bmCapabilities = 0,
  108.     },
  109.     .cdc_union = {
  110.         .bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
  111.         .bDescriptorType = CS_INTERFACE,
  112.         .bDescriptorSubtype = USB_CDC_TYPE_UNION,
  113.         .bControlInterface = 0,
  114.         .bSubordinateInterface0 = 1,
  115.      }
  116. };
  117.  
  118. static const struct usb_interface_descriptor comm_iface[] = {{
  119.     .bLength = USB_DT_INTERFACE_SIZE,
  120.     .bDescriptorType = USB_DT_INTERFACE,
  121.     .bInterfaceNumber = 0,
  122.     .bAlternateSetting = 0,
  123.     .bNumEndpoints = 1,
  124.     .bInterfaceClass = USB_CLASS_CDC,
  125.     .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  126.     .bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
  127.     .iInterface = 0,
  128.  
  129.     .endpoint = comm_endp,
  130.  
  131.     .extra = &cdcacm_functional_descriptors,
  132.     .extralen = sizeof(cdcacm_functional_descriptors)
  133. }};
  134.  
  135. static const struct usb_interface_descriptor data_iface[] = {{
  136.     .bLength = USB_DT_INTERFACE_SIZE,
  137.     .bDescriptorType = USB_DT_INTERFACE,
  138.     .bInterfaceNumber = 1,
  139.     .bAlternateSetting = 0,
  140.     .bNumEndpoints = 2,
  141.     .bInterfaceClass = USB_CLASS_DATA,
  142.     .bInterfaceSubClass = 0,
  143.     .bInterfaceProtocol = 0,
  144.     .iInterface = 0,
  145.  
  146.     .endpoint = data_endp,
  147. }};
  148.  
  149. static const struct usb_interface ifaces[] = {{
  150.     .num_altsetting = 1,
  151.     .altsetting = comm_iface,
  152. }, {
  153.     .num_altsetting = 1,
  154.     .altsetting = data_iface,
  155. }};
  156.  
  157. static const struct usb_config_descriptor config = {
  158.     .bLength = USB_DT_CONFIGURATION_SIZE,
  159.     .bDescriptorType = USB_DT_CONFIGURATION,
  160.     .wTotalLength = 0,
  161.     .bNumInterfaces = 2,
  162.     .bConfigurationValue = 1,
  163.     .iConfiguration = 0,
  164.     .bmAttributes = 0x80,
  165.     .bMaxPower = 0x32,
  166.  
  167.     .interface = ifaces,
  168. };
  169.  
  170. static const char *usb_strings[] = {
  171.     "Black Sphere Technologies",
  172.     "CDC-ACM Demo",
  173.     "DEMO",
  174. };
  175.  
  176. static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
  177.         u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
  178. {
  179.     (void)complete;
  180.     (void)buf;
  181.     (void)usbd_dev;
  182.  
  183.     switch (req->bRequest) {
  184.     case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
  185.         /*
  186.          * This Linux cdc_acm driver requires this to be implemented
  187.          * even though it's optional in the CDC spec, and we don't
  188.          * advertise it in the ACM functional descriptor.
  189.          */
  190.         return 1;
  191.         }
  192.     case USB_CDC_REQ_SET_LINE_CODING:
  193.         if (*len < sizeof(struct usb_cdc_line_coding))
  194.             return 0;
  195.  
  196.         return 1;
  197.     }
  198.     return 0;
  199. }
  200.  
  201. static void cdcacm_data_rx_cb(usbd_device *usbd_dev, u8 ep)
  202. {
  203.     (void)ep;
  204.  
  205.     char buf[64];
  206.     int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
  207.  
  208.     if (len) {
  209.         ring_write(&rx_ring, (u8 *) buf, (u32) len);
  210.     }
  211.  
  212.     gpio_toggle(GPIOC, GPIO5);
  213. }
  214.  
  215. static void cdcacm_set_config(usbd_device *usbd_dev, u16 wValue)
  216. {
  217.     (void)wValue;
  218.  
  219.     usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
  220.     usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
  221.     usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
  222.  
  223.     usbd_register_control_callback(
  224.                 usbd_dev,
  225.                 USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
  226.                 USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
  227.                 cdcacm_control_request);
  228. }
  229.  
  230. void nvic_setup(void)
  231. {
  232.         /* Without this the timer interrupt routine will never be called. */
  233.         nvic_enable_irq(NVIC_TIM2_IRQ);
  234.         nvic_set_priority(NVIC_TIM2_IRQ, 1);
  235. }
  236.  
  237. void tim2_init(void){
  238.                 rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM2EN);    
  239.         /* Set timer start value. */
  240.         TIM_CNT(TIM2) = 1;
  241.  
  242.         /* Set timer prescaler. 120MHz/120000 => 1000 counts per second. */
  243.         TIM_PSC(TIM2) = 120000;
  244.  
  245.         /* End timer value. If this is reached an interrupt is generated. */
  246.         TIM_ARR(TIM2) = 1000;
  247.  
  248.         /* Update interrupt enable. */
  249.         TIM_DIER(TIM2) |= TIM_DIER_UIE;
  250.  
  251.         /* Start timer. */
  252.         TIM_CR1(TIM2) |= TIM_CR1_CEN;
  253. }
  254.  
  255. void tim2_isr(void)
  256. {
  257.         //gpio_toggle(GPIOB, GPIO6);   /* LED2 on/off. */
  258.         TIM_SR(TIM2) &= ~TIM_SR_UIF; /* Clear interrrupt flag. */
  259.         ring_init(&rx_ring, rx_buffer, RX_BUFFER_SIZE);    
  260. }
  261.  
  262. char parse_bytes(u8 *command){
  263.     switch(command[0]){
  264.         case SET_SPEED:
  265.             while (usbd_ep_write_packet(usbd_dev, 0x82, "SPEED", 5) == 0)
  266.                     ;
  267.             break;
  268.     }
  269.     return 0;
  270. }
  271.  
  272. int main(void)
  273. {
  274.     rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_120MHZ]);
  275.  
  276.     rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN);
  277.     rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN);
  278.  
  279.     gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE,
  280.             GPIO9 | GPIO11 | GPIO12);
  281.     gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12);
  282.  
  283.     usbd_dev = usbd_init(&otgfs_usb_driver, &dev, &config, usb_strings, 3);
  284.     usbd_register_set_config_callback(usbd_dev, cdcacm_set_config);
  285.    
  286.     u8 command[4];
  287.     u32 len;
  288.     ring_init(&rx_ring, rx_buffer, RX_BUFFER_SIZE);
  289.    
  290.     nvic_setup();
  291.     tim2_init();
  292.    
  293.     while (1){
  294.         usbd_poll(usbd_dev);
  295.         if (rx_ring.count >= 4){
  296.             len = ring_read(&rx_ring, command, 4);
  297.             if(len){
  298.                 parse_bytes(command);
  299.             }          
  300.         }
  301.     }
  302. }
Advertisement
Add Comment
Please, Sign In to add comment