TheLegace

STM32F42

Feb 6th, 2013
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.11 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/stm32/f4/timer.h>
  24. #include <libopencm3/usb/usbd.h>
  25. #include <libopencm3/usb/cdc.h>
  26. #include <libopencm3/cm3/scb.h>
  27. #include <libopencm3/cm3/nvic.h>
  28. #include "ring.h"
  29. #include "fourbyte.h"
  30. #include "timer.h"
  31.  
  32. #define RX_BUFFER_SIZE    128
  33. static struct ring rx_ring;
  34. static u8 rx_buffer[RX_BUFFER_SIZE];
  35. static usbd_device *usbd_dev;
  36.  
  37. static const struct usb_device_descriptor dev = {
  38.     .bLength = USB_DT_DEVICE_SIZE,
  39.     .bDescriptorType = USB_DT_DEVICE,
  40.     .bcdUSB = 0x0200,
  41.     .bDeviceClass = USB_CLASS_CDC,
  42.     .bDeviceSubClass = 0,
  43.     .bDeviceProtocol = 0,
  44.     .bMaxPacketSize0 = 64,
  45.     .idVendor = 0x0483,
  46.     .idProduct = 0x5740,
  47.     .bcdDevice = 0x0200,
  48.     .iManufacturer = 1,
  49.     .iProduct = 2,
  50.     .iSerialNumber = 3,
  51.     .bNumConfigurations = 1,
  52. };
  53.  
  54. /*
  55.  * This notification endpoint isn't implemented. According to CDC spec it's
  56.  * optional, but its absence causes a NULL pointer dereference in the
  57.  * Linux cdc_acm driver.
  58.  */
  59. static const struct usb_endpoint_descriptor comm_endp[] = {{
  60.     .bLength = USB_DT_ENDPOINT_SIZE,
  61.     .bDescriptorType = USB_DT_ENDPOINT,
  62.     .bEndpointAddress = 0x83,
  63.     .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
  64.     .wMaxPacketSize = 16,
  65.     .bInterval = 255,
  66. }};
  67.  
  68. static const struct usb_endpoint_descriptor data_endp[] = {{
  69.     .bLength = USB_DT_ENDPOINT_SIZE,
  70.     .bDescriptorType = USB_DT_ENDPOINT,
  71.     .bEndpointAddress = 0x01,
  72.     .bmAttributes = USB_ENDPOINT_ATTR_BULK,
  73.     .wMaxPacketSize = 64,
  74.     .bInterval = 1,
  75. }, {
  76.     .bLength = USB_DT_ENDPOINT_SIZE,
  77.     .bDescriptorType = USB_DT_ENDPOINT,
  78.     .bEndpointAddress = 0x82,
  79.     .bmAttributes = USB_ENDPOINT_ATTR_BULK,
  80.     .wMaxPacketSize = 64,
  81.     .bInterval = 1,
  82. }};
  83.  
  84. static const struct {
  85.     struct usb_cdc_header_descriptor header;
  86.     struct usb_cdc_call_management_descriptor call_mgmt;
  87.     struct usb_cdc_acm_descriptor acm;
  88.     struct usb_cdc_union_descriptor cdc_union;
  89. } __attribute__((packed)) cdcacm_functional_descriptors = {
  90.     .header = {
  91.         .bFunctionLength = sizeof(struct usb_cdc_header_descriptor),
  92.         .bDescriptorType = CS_INTERFACE,
  93.         .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
  94.         .bcdCDC = 0x0110,
  95.     },
  96.     .call_mgmt = {
  97.         .bFunctionLength =
  98.             sizeof(struct usb_cdc_call_management_descriptor),
  99.         .bDescriptorType = CS_INTERFACE,
  100.         .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
  101.         .bmCapabilities = 0,
  102.         .bDataInterface = 1,
  103.     },
  104.     .acm = {
  105.         .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
  106.         .bDescriptorType = CS_INTERFACE,
  107.         .bDescriptorSubtype = USB_CDC_TYPE_ACM,
  108.         .bmCapabilities = 0,
  109.     },
  110.     .cdc_union = {
  111.         .bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
  112.         .bDescriptorType = CS_INTERFACE,
  113.         .bDescriptorSubtype = USB_CDC_TYPE_UNION,
  114.         .bControlInterface = 0,
  115.         .bSubordinateInterface0 = 1,
  116.      }
  117. };
  118.  
  119. static const struct usb_interface_descriptor comm_iface[] = {{
  120.     .bLength = USB_DT_INTERFACE_SIZE,
  121.     .bDescriptorType = USB_DT_INTERFACE,
  122.     .bInterfaceNumber = 0,
  123.     .bAlternateSetting = 0,
  124.     .bNumEndpoints = 1,
  125.     .bInterfaceClass = USB_CLASS_CDC,
  126.     .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  127.     .bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
  128.     .iInterface = 0,
  129.  
  130.     .endpoint = comm_endp,
  131.  
  132.     .extra = &cdcacm_functional_descriptors,
  133.     .extralen = sizeof(cdcacm_functional_descriptors)
  134. }};
  135.  
  136. static const struct usb_interface_descriptor data_iface[] = {{
  137.     .bLength = USB_DT_INTERFACE_SIZE,
  138.     .bDescriptorType = USB_DT_INTERFACE,
  139.     .bInterfaceNumber = 1,
  140.     .bAlternateSetting = 0,
  141.     .bNumEndpoints = 2,
  142.     .bInterfaceClass = USB_CLASS_DATA,
  143.     .bInterfaceSubClass = 0,
  144.     .bInterfaceProtocol = 0,
  145.     .iInterface = 0,
  146.  
  147.     .endpoint = data_endp,
  148. }};
  149.  
  150. static const struct usb_interface ifaces[] = {{
  151.     .num_altsetting = 1,
  152.     .altsetting = comm_iface,
  153. }, {
  154.     .num_altsetting = 1,
  155.     .altsetting = data_iface,
  156. }};
  157.  
  158. static const struct usb_config_descriptor config = {
  159.     .bLength = USB_DT_CONFIGURATION_SIZE,
  160.     .bDescriptorType = USB_DT_CONFIGURATION,
  161.     .wTotalLength = 0,
  162.     .bNumInterfaces = 2,
  163.     .bConfigurationValue = 1,
  164.     .iConfiguration = 0,
  165.     .bmAttributes = 0x80,
  166.     .bMaxPower = 0x32,
  167.  
  168.     .interface = ifaces,
  169. };
  170.  
  171. static const char *usb_strings[] = {
  172.     "Black Sphere Technologies",
  173.     "CDC-ACM Demo",
  174.     "DEMO",
  175. };
  176.  
  177. static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
  178.         u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
  179. {
  180.     (void)complete;
  181.     (void)buf;
  182.     (void)usbd_dev;
  183.  
  184.     switch (req->bRequest) {
  185.     case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
  186.         /*
  187.          * This Linux cdc_acm driver requires this to be implemented
  188.          * even though it's optional in the CDC spec, and we don't
  189.          * advertise it in the ACM functional descriptor.
  190.          */
  191.         return 1;
  192.         }
  193.     case USB_CDC_REQ_SET_LINE_CODING:
  194.         if (*len < sizeof(struct usb_cdc_line_coding))
  195.             return 0;
  196.  
  197.         return 1;
  198.     }
  199.     return 0;
  200. }
  201.  
  202. static void cdcacm_data_rx_cb(usbd_device *usbd_dev, u8 ep)
  203. {
  204.     (void)ep;
  205.  
  206.     char buf[64];
  207.     int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
  208.  
  209.     if (len) {
  210.         ring_write(&rx_ring, (u8 *) buf, (u32) len);
  211.     }
  212.  
  213.     gpio_toggle(GPIOC, GPIO5);
  214. }
  215.  
  216. static void cdcacm_set_config(usbd_device *usbd_dev, u16 wValue)
  217. {
  218.     (void)wValue;
  219.  
  220.     usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
  221.     usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
  222.     usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
  223.  
  224.     usbd_register_control_callback(
  225.                 usbd_dev,
  226.                 USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
  227.                 USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
  228.                 cdcacm_control_request);
  229. }
  230.  
  231. void nvic_setup(void)
  232. {
  233.         /* Without this the timer interrupt routine will never be called. */
  234.         nvic_enable_irq(NVIC_TIM2_IRQ);
  235.         nvic_set_priority(NVIC_TIM2_IRQ, 1);
  236. }
  237.  
  238. void tim2_init(void){
  239.                 rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM2EN);    
  240.         /* Set timer start value. */
  241.         TIM_CNT(TIM2) = 1;
  242.  
  243.         /* Set timer prescaler. 120MHz/120000 => 1000 counts per second. */
  244.         TIM_PSC(TIM2) = 120000;
  245.  
  246.         /* End timer value. If this is reached an interrupt is generated. */
  247.         TIM_ARR(TIM2) = 1000;
  248.  
  249.         /* Update interrupt enable. */
  250.         TIM_DIER(TIM2) |= TIM_DIER_UIE;
  251.  
  252.         /* Start timer. */
  253.         TIM_CR1(TIM2) |= TIM_CR1_CEN;
  254. }
  255.  
  256. void tim2_isr(void)
  257. {
  258.         //gpio_toggle(GPIOB, GPIO6);   /* LED2 on/off. */
  259.         TIM_SR(TIM2) &= ~TIM_SR_UIF; /* Clear interrrupt flag. */
  260.         ring_init(&rx_ring, rx_buffer, RX_BUFFER_SIZE);    
  261. }
  262.  
  263. void setup_periodic_timer(uint32_t timer, unsigned int freq_in_hz)
  264. {
  265.     unsigned int prescaler = 1;
  266.     while (rcc_ppre1_frequency / prescaler / freq_in_hz > 0xffff)
  267.         prescaler *= 2;
  268.     timer_reset(timer);
  269.     timer_set_prescaler(timer, prescaler-1);
  270.     timer_set_period(timer, rcc_ppre1_frequency / prescaler / freq_in_hz);
  271.     timer_direction_down(timer);
  272.     timer_enable_preload(timer);
  273. }
  274.  
  275. void gpio_setup(void){
  276.    
  277.     /* Enable GPIOD clock. */
  278.     rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);
  279.     /* Set GPIO12 (in GPIO port D) to 'output push-pull'. */
  280.     gpio_mode_setup(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO13);
  281. }
  282.  
  283.  
  284. void tim_setup(void){
  285.     rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN);
  286.     gpio_mode_setup(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO12);
  287.     gpio_set_af(GPIOD, GPIO_AF2, GPIO12);
  288.     //~ timer_reset(TIM4);
  289.     //~ timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
  290.     //~ timer_set_prescaler(TIM4, 0);
  291.     //~ timer_set_repetition_counter(TIM4, 0);
  292.     //~ timer_enable_preload(TIM4);
  293.     //~ timer_continuous_mode(TIM4);
  294.     //~ timer_set_period(TIM4, 168000000 / 32000);
  295.     //~ timer_disable_oc_output(TIM4, TIM_OC1);
  296.     //~ timer_disable_oc_clear(TIM4, TIM_OC1);
  297.     //~ timer_enable_oc_preload(TIM4, TIM_OC1);
  298.     //~ timer_set_oc_mode(TIM4, TIM_OC1, TIM_OCM_PWM1);
  299.     //~ timer_set_oc_value(TIM4, TIM_OC1, 5260);
  300.     //~ timer_enable_oc_output(TIM4, TIM_OC1);
  301.     //~ timer_enable_preload(TIM4);
  302.     //~ timer_enable_counter(TIM4);
  303.    
  304.     rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN);
  305.     nvic_enable_irq(NVIC_TIM4_IRQ);
  306.     timer_reset(TIM4);
  307.     timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
  308.     timer_set_prescaler(TIM4, 0);
  309.     timer_enable_preload(TIM4);
  310.     timer_continuous_mode(TIM4);
  311.     timer_set_period(TIM4, 168000000 / 32000);
  312.    
  313.     timer_disable_oc_output(TIM4, TIM_OC1);
  314.     timer_disable_oc_clear(TIM4, TIM_OC1);
  315.     timer_enable_oc_preload(TIM4, TIM_OC1);
  316.     timer_set_oc_mode(TIM4, TIM_OC1, TIM_OCM_PWM1);
  317.     timer_set_oc_value(TIM4, TIM_OC1, 1000);
  318.      
  319.     timer_enable_oc_output(TIM4, TIM_OC1);
  320.     timer_enable_preload(TIM4);
  321.     timer_enable_irq(TIM4, TIM_DIER_CC4IE);
  322.     timer_enable_counter(TIM4);
  323. }
  324.  
  325. void tim4_isr(){
  326.     timer_clear_flag(TIM4, 0xffffffff);
  327. }
  328.  
  329.  
  330.  
  331. char parse_bytes(u8 *command){
  332.     switch(command[0]){
  333.         case SET_SPEED:
  334.             switch(command[1]){
  335.                 case ID_FL:
  336.                     gpio_toggle(GPIOD, GPIO13);
  337.                     while (usbd_ep_write_packet(usbd_dev, 0x82, "SPEED", 5) == 0)
  338.                         ;
  339.                     break;
  340.             }
  341.         case GET_SPEED:
  342.             break;
  343.     }
  344.     return 0;
  345. }
  346.  
  347. int main(void)
  348. {
  349.     rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_120MHZ]);
  350.  
  351.     rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN);
  352.     rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);
  353.     rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN);
  354.     rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN);
  355.    
  356.     gpio_mode_setup(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO12|GPIO13);
  357.     gpio_set_af(GPIOD, GPIO_AF2, GPIO12|GPIO13);
  358.  
  359.     gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE,
  360.             GPIO9 | GPIO11 | GPIO12);
  361.     gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12);
  362.  
  363.     usbd_dev = usbd_init(&otgfs_usb_driver, &dev, &config, usb_strings, 3);
  364.     usbd_register_set_config_callback(usbd_dev, cdcacm_set_config);
  365.    
  366.     u8 command[4];
  367.     u32 len;
  368.     ring_init(&rx_ring, rx_buffer, RX_BUFFER_SIZE);
  369.    
  370.     nvic_setup();
  371.     tim2_init();
  372.     //gpio_setup();
  373.     //tim_setup();
  374.     uint32_t mode[3] = {TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP};
  375.     enum tim_oc_id *oc_id = {TIM_OC1,TIM_OC2};
  376.     timer_init(TIM4, 168000000 / 32000, 2, mode, oc_id);
  377.    
  378.     while (1){
  379.         usbd_poll(usbd_dev);
  380.         if (rx_ring.count >= 4){
  381.             len = ring_read(&rx_ring, command, 4);
  382.             if(len){
  383.                 parse_bytes(command);
  384.             }          
  385.         }
  386.     }
  387. }
Advertisement
Add Comment
Please, Sign In to add comment