mirror of
https://github.com/rene-dev/stmbl.git
synced 2024-12-24 17:42:10 +00:00
initial port to libopencm3
This commit is contained in:
parent
b3e5f42439
commit
3643b09c8d
68
Makefile
68
Makefile
@ -1,8 +1,8 @@
|
||||
# Optimization level, can be [0, 1, 2, 3, s].
|
||||
# 0 = turn off optimization. s = optimize for size.
|
||||
#
|
||||
OPT = -O1 -flto
|
||||
# OPT = -O1 # for debugging
|
||||
#OPT = -O1 -flto
|
||||
OPT = -ggdb3 # for debugging
|
||||
|
||||
# Object files directory
|
||||
# Warning: this will be removed by make clean!
|
||||
@ -17,72 +17,24 @@ INCDIRS += inc
|
||||
INCDIRS += shared
|
||||
|
||||
SOURCES += src/main.c
|
||||
SOURCES += src/stm32f4xx_it.c
|
||||
SOURCES += src/system_stm32f4xx.c
|
||||
SOURCES += src/scanf.c
|
||||
SOURCES += src/setup.c
|
||||
SOURCES += src/usb_cdc.c
|
||||
SOURCES += src/cdc.c
|
||||
SOURCES += src/hal.c
|
||||
SOURCES += src/misc.c
|
||||
SOURCES += src/eeprom.c
|
||||
#SOURCES += src/eeprom.c
|
||||
SOURCES += src/link.c
|
||||
SOURCES += src/version.c
|
||||
SOURCES += src/syscalls.c
|
||||
|
||||
SOURCES += shared/crc8.c
|
||||
SOURCES += shared/common.c
|
||||
SOURCES += shared/ringbuf.c
|
||||
|
||||
USB_VCP_DIR = lib/STM32_USB_Device_VCP-1.2.0
|
||||
LDFLAGS += -lopencm3_stm32f4 -Llibopencm3/lib/ -nostartfiles
|
||||
CFLAGS += -DSTM32F4
|
||||
INCDIRS += libopencm3/include
|
||||
|
||||
CPPFLAGS += -DUSBD_PRODUCT_STRING='"STMBL Virtual ComPort"'
|
||||
CPPFLAGS += -DCDC_IN_FRAME_INTERVAL=1
|
||||
CPPFLAGS += -DAPP_RX_DATA_SIZE=4096
|
||||
|
||||
INCDIRS += $(USB_VCP_DIR)/inc
|
||||
SOURCES += $(USB_VCP_DIR)/src/usbd_desc.c
|
||||
|
||||
USB_DEVICE_DIR = lib/STM32_USB_Device_Library-1.2.0
|
||||
|
||||
INCDIRS += $(USB_DEVICE_DIR)/Class/cdc/inc
|
||||
SOURCES += $(USB_DEVICE_DIR)/Class/cdc/src/usbd_cdc_core.c
|
||||
|
||||
INCDIRS += $(USB_DEVICE_DIR)/Core/inc
|
||||
SOURCES += $(USB_DEVICE_DIR)/Core/src/usbd_core.c
|
||||
SOURCES += $(USB_DEVICE_DIR)/Core/src/usbd_ioreq.c
|
||||
SOURCES += $(USB_DEVICE_DIR)/Core/src/usbd_req.c
|
||||
|
||||
USB_DRIVER_DIR = lib/STM32_USB_OTG_Driver-2.2.0
|
||||
|
||||
INCDIRS += $(USB_DRIVER_DIR)/inc
|
||||
SOURCES += $(USB_DRIVER_DIR)/src/usb_core.c
|
||||
SOURCES += $(USB_DRIVER_DIR)/src/usb_dcd.c
|
||||
SOURCES += $(USB_DRIVER_DIR)/src/usb_dcd_int.c
|
||||
|
||||
# Standard peripheral library
|
||||
CPPFLAGS += -DUSE_STDPERIPH_DRIVER
|
||||
#CPPFLAGS += -DUSE_FULL_ASSERT
|
||||
|
||||
PERIPH_DRV_DIR = lib/STM32F4xx_StdPeriph_Driver-V1.6.0
|
||||
|
||||
INCDIRS += $(PERIPH_DRV_DIR)/inc
|
||||
INCDIRS += lib/CMSIS/Include
|
||||
INCDIRS += lib/CMSIS/Device/ST/STM32F4xx/Include
|
||||
|
||||
SOURCES += $(PERIPH_DRV_DIR)/src/stm32f4xx_adc.c
|
||||
SOURCES += $(PERIPH_DRV_DIR)/src/stm32f4xx_crc.c
|
||||
SOURCES += $(PERIPH_DRV_DIR)/src/stm32f4xx_dma.c
|
||||
SOURCES += $(PERIPH_DRV_DIR)/src/stm32f4xx_flash.c
|
||||
SOURCES += $(PERIPH_DRV_DIR)/src/stm32f4xx_gpio.c
|
||||
SOURCES += $(PERIPH_DRV_DIR)/src/stm32f4xx_pwr.c
|
||||
SOURCES += $(PERIPH_DRV_DIR)/src/stm32f4xx_rcc.c
|
||||
SOURCES += $(PERIPH_DRV_DIR)/src/stm32f4xx_tim.c
|
||||
SOURCES += $(PERIPH_DRV_DIR)/src/stm32f4xx_usart.c
|
||||
SOURCES += $(PERIPH_DRV_DIR)/src/misc.c
|
||||
|
||||
SOURCES += lib/CMSIS/Device/ST/STM32F4xx/Source/startup_stm32f40_41xxx.s
|
||||
|
||||
CPPFLAGS += -DSTM32F40_41xxx
|
||||
CPPFLAGS += -DHSE_VALUE=8000000
|
||||
LDSCRIPT = stm32_flash.ld
|
||||
|
||||
#============================================================================
|
||||
@ -96,7 +48,6 @@ CPPFLAGS += $(addprefix -I,$(INCDIRS))
|
||||
# -save-temps preserve .s and .i-files
|
||||
#
|
||||
CPPFLAGS += -fsingle-precision-constant
|
||||
CPPFLAGS += -g
|
||||
# CPPFLAGS += -save-temps=obj
|
||||
|
||||
#---------------- C Compiler Options ----------------
|
||||
@ -194,6 +145,9 @@ boot_clean:
|
||||
|
||||
boot_flash: boot
|
||||
$(MAKE) -f bootloader/Makefile flash
|
||||
|
||||
flash:
|
||||
st-flash --reset write $(TARGET).bin 0x08000000
|
||||
|
||||
hv_flash: boot
|
||||
$(MAKE) -f stm32f103/Makefile flash
|
||||
|
96
shared/ringbuf.c
Normal file
96
shared/ringbuf.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include "ringbuf.h"
|
||||
|
||||
/**
|
||||
* Read a single byte from a buffer
|
||||
*
|
||||
* \param rb pointer to ringbuffer struct
|
||||
* \param data pointer to data byte
|
||||
* \return number of bytes read (0 if buffer was empty)
|
||||
*/
|
||||
int rb_getc(struct ringbuf *rb, char *data)
|
||||
{
|
||||
if (!rb->len)
|
||||
return 0;
|
||||
|
||||
*data = rb->buf[rb->pos++];
|
||||
if (rb->pos >= rb->bufsize)
|
||||
rb->pos -= rb->bufsize;
|
||||
rb->len--;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write a single byte to a buffer
|
||||
*
|
||||
* \param rb pointer to ringbuffer struct
|
||||
* \param data pointer to data byte
|
||||
* \return number of bytes written (0 if buffer was full)
|
||||
*/
|
||||
int rb_putc(struct ringbuf *rb, const char data)
|
||||
{
|
||||
if (rb->len >= rb->bufsize)
|
||||
return 0;
|
||||
|
||||
unsigned i = rb->pos + rb->len;
|
||||
if (i >= rb->bufsize)
|
||||
i -= rb->bufsize;
|
||||
|
||||
rb->buf[i] = data;
|
||||
rb->len++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from a buffer
|
||||
*
|
||||
*/
|
||||
int rb_read(struct ringbuf *rb, void *data, int len)
|
||||
{
|
||||
if (len > rb->len)
|
||||
len = rb->len;
|
||||
|
||||
int len1 = len;
|
||||
if (rb->pos + len1 >= rb->bufsize) {
|
||||
int len2 = (rb->pos + len1) - rb->bufsize;
|
||||
len1 -= len2;
|
||||
memcpy((char*)data + len1, rb->buf, len2);
|
||||
}
|
||||
memcpy(data, rb->buf + rb->pos, len1);
|
||||
|
||||
rb->len -= len;
|
||||
rb->pos += len;
|
||||
if (rb->pos > rb->bufsize)
|
||||
rb->pos -= rb->bufsize;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write to a buffer
|
||||
*
|
||||
* \param rb pointer to ringbuffer struct
|
||||
* \param data pointer to data byte
|
||||
* \return number of bytes written (0 if buffer was full)
|
||||
*
|
||||
*/
|
||||
int rb_write(struct ringbuf *rb, const void *data, int len)
|
||||
{
|
||||
if (len > rb->bufsize - rb->len)
|
||||
len = rb->bufsize - rb->len;
|
||||
|
||||
int len1 = len;
|
||||
if (rb->pos + rb->len + len1 >= rb->bufsize) {
|
||||
int len2 = (rb->pos + rb->len + len1) - rb->bufsize;
|
||||
len1 -= len2;
|
||||
memcpy(rb->buf, (char*)data + len1, len2);
|
||||
}
|
||||
|
||||
memcpy(rb->buf + rb->pos + rb->len, data, len1);
|
||||
|
||||
rb->len += len;
|
||||
return len;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Ringbuffer structure
|
||||
@ -21,18 +21,7 @@ struct ringbuf {
|
||||
* \param data pointer to data byte
|
||||
* \return number of bytes read (0 if buffer was empty)
|
||||
*/
|
||||
static inline int rb_getc(struct ringbuf *rb, char *data)
|
||||
{
|
||||
if (!rb->len)
|
||||
return 0;
|
||||
|
||||
*data = rb->buf[rb->pos++];
|
||||
if (rb->pos >= rb->bufsize)
|
||||
rb->pos -= rb->bufsize;
|
||||
rb->len--;
|
||||
|
||||
return 1;
|
||||
}
|
||||
int rb_getc(struct ringbuf *rb, char *data);
|
||||
|
||||
|
||||
/**
|
||||
@ -42,47 +31,12 @@ static inline int rb_getc(struct ringbuf *rb, char *data)
|
||||
* \param data pointer to data byte
|
||||
* \return number of bytes written (0 if buffer was full)
|
||||
*/
|
||||
static inline int rb_putc(struct ringbuf *rb, const char data)
|
||||
{
|
||||
if (rb->len >= rb->bufsize)
|
||||
return 0;
|
||||
|
||||
unsigned i = rb->pos + rb->len;
|
||||
if (i >= rb->bufsize)
|
||||
i -= rb->bufsize;
|
||||
|
||||
rb->buf[i] = data;
|
||||
rb->len++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
int rb_putc(struct ringbuf *rb, const char data);
|
||||
/**
|
||||
* Read from a buffer
|
||||
*
|
||||
*/
|
||||
int rb_read(struct ringbuf *rb, void *data, int len)
|
||||
{
|
||||
if (len > rb->len)
|
||||
len = rb->len;
|
||||
|
||||
int len1 = len;
|
||||
if (rb->pos + len1 >= rb->bufsize) {
|
||||
int len2 = (rb->pos + len1) - rb->bufsize;
|
||||
len1 -= len2;
|
||||
memcpy((char*)data + len1, rb->buf, len2);
|
||||
}
|
||||
memcpy(data, rb->buf + rb->pos, len1);
|
||||
|
||||
rb->len -= len;
|
||||
rb->pos += len;
|
||||
if (rb->pos > rb->bufsize)
|
||||
rb->pos -= rb->bufsize;
|
||||
|
||||
return len;
|
||||
}
|
||||
int rb_read(struct ringbuf *rb, void *data, int len);
|
||||
|
||||
|
||||
/**
|
||||
@ -93,22 +47,4 @@ int rb_read(struct ringbuf *rb, void *data, int len)
|
||||
* \return number of bytes written (0 if buffer was full)
|
||||
*
|
||||
*/
|
||||
int rb_write(struct ringbuf *rb, const void *data, int len)
|
||||
{
|
||||
if (len > rb->bufsize - rb->len)
|
||||
len = rb->bufsize - rb->len;
|
||||
|
||||
int len1 = len;
|
||||
if (rb->pos + rb->len + len1 >= rb->bufsize) {
|
||||
int len2 = (rb->pos + rb->len + len1) - rb->bufsize;
|
||||
len1 -= len2;
|
||||
memcpy(rb->buf, (char*)data + len1, len2);
|
||||
}
|
||||
|
||||
memcpy(rb->buf + rb->pos + rb->len, data, len1);
|
||||
|
||||
rb->len += len;
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
int rb_write(struct ringbuf *rb, const void *data, int len);
|
314
src/cdc.c
Normal file
314
src/cdc.c
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/cm3/scb.h>
|
||||
|
||||
#include "cdc.h"
|
||||
|
||||
struct ringbuf rx_buf = { .buf = (char[RX_QUEUE_SIZE]) {0}, .bufsize = RX_QUEUE_SIZE };
|
||||
struct ringbuf tx_buf = { .buf = (char[TX_QUEUE_SIZE]) {0}, .bufsize = TX_QUEUE_SIZE };
|
||||
|
||||
static const struct usb_device_descriptor dev = {
|
||||
.bLength = USB_DT_DEVICE_SIZE,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = USB_CLASS_CDC,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
.bMaxPacketSize0 = 64,
|
||||
.idVendor = 0x0483,
|
||||
.idProduct = 0x5740,
|
||||
.bcdDevice = 0x0200,
|
||||
.iManufacturer = 1,
|
||||
.iProduct = 2,
|
||||
.iSerialNumber = 3,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* This notification endpoint isn't implemented. According to CDC spec it's
|
||||
* optional, but its absence causes a NULL pointer dereference in the
|
||||
* Linux cdc_acm driver.
|
||||
*/
|
||||
static const struct usb_endpoint_descriptor comm_endp[] = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x83,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
||||
.wMaxPacketSize = 16,
|
||||
.bInterval = 255,
|
||||
} };
|
||||
|
||||
static const struct usb_endpoint_descriptor data_endp[] = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x01,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
}, {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x82,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
} };
|
||||
|
||||
static const struct {
|
||||
struct usb_cdc_header_descriptor header;
|
||||
struct usb_cdc_call_management_descriptor call_mgmt;
|
||||
struct usb_cdc_acm_descriptor acm;
|
||||
struct usb_cdc_union_descriptor cdc_union;
|
||||
} __attribute__((packed)) cdcacm_functional_descriptors = {
|
||||
.header = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_header_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_HEADER,
|
||||
.bcdCDC = 0x0110,
|
||||
},
|
||||
.call_mgmt = {
|
||||
.bFunctionLength =
|
||||
sizeof(struct usb_cdc_call_management_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
|
||||
.bmCapabilities = 0,
|
||||
.bDataInterface = 1,
|
||||
},
|
||||
.acm = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_ACM,
|
||||
.bmCapabilities = 0,
|
||||
},
|
||||
.cdc_union = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_UNION,
|
||||
.bControlInterface = 0,
|
||||
.bSubordinateInterface0 = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct usb_interface_descriptor comm_iface[] = {{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = USB_CLASS_CDC,
|
||||
.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
|
||||
.bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
|
||||
.iInterface = 0,
|
||||
|
||||
.endpoint = comm_endp,
|
||||
|
||||
.extra = &cdcacm_functional_descriptors,
|
||||
.extralen = sizeof(cdcacm_functional_descriptors)
|
||||
} };
|
||||
|
||||
static const struct usb_interface_descriptor data_iface[] = {{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 1,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_CLASS_DATA,
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
.iInterface = 0,
|
||||
|
||||
.endpoint = data_endp,
|
||||
} };
|
||||
|
||||
static const struct usb_interface ifaces[] = {{
|
||||
.num_altsetting = 1,
|
||||
.altsetting = comm_iface,
|
||||
}, {
|
||||
.num_altsetting = 1,
|
||||
.altsetting = data_iface,
|
||||
} };
|
||||
|
||||
static const struct usb_config_descriptor config = {
|
||||
.bLength = USB_DT_CONFIGURATION_SIZE,
|
||||
.bDescriptorType = USB_DT_CONFIGURATION,
|
||||
.wTotalLength = 0,
|
||||
.bNumInterfaces = 2,
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = 0,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 0x32,
|
||||
|
||||
.interface = ifaces,
|
||||
};
|
||||
|
||||
//TODO: serial number
|
||||
//https://github.com/rene-dev/stmbl/blob/master/lib/STM32_USB_Device_VCP-1.2.0/src/usbd_desc.c#L302-L314
|
||||
//https://github.com/paparazzi/paparazzi/blob/master/sw/airborne/arch/stm32/usb_ser_hw.c#L516
|
||||
static const char * usb_strings[] = {
|
||||
"Black Sphere Technologies",
|
||||
"STMBL Virtual ComPort",
|
||||
"DEMO",//serial
|
||||
};
|
||||
|
||||
/* Buffer to be used for control requests. */
|
||||
uint8_t usbd_control_buffer[128];
|
||||
|
||||
static int cdcacm_control_request(usbd_device *usbd_dev,
|
||||
struct usb_setup_data *req, uint8_t **buf, uint16_t *len,
|
||||
void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
|
||||
{
|
||||
(void)complete;
|
||||
(void)buf;
|
||||
(void)usbd_dev;
|
||||
|
||||
switch (req->bRequest) {
|
||||
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
|
||||
/*
|
||||
* This Linux cdc_acm driver requires this to be implemented
|
||||
* even though it's optional in the CDC spec, and we don't
|
||||
* advertise it in the ACM functional descriptor.
|
||||
*/
|
||||
char local_buf[10];
|
||||
struct usb_cdc_notification *notif = (void *)local_buf;
|
||||
/* We echo signals back to host as notification. */
|
||||
notif->bmRequestType = 0xA1;
|
||||
notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE;
|
||||
notif->wValue = 0;
|
||||
notif->wIndex = 0;
|
||||
notif->wLength = 2;
|
||||
local_buf[8] = req->wValue & 3;
|
||||
local_buf[9] = 0;
|
||||
usbd_ep_write_packet(usbd_dev, 0x83, local_buf, 10);
|
||||
return 1;
|
||||
}
|
||||
case USB_CDC_REQ_SET_LINE_CODING:
|
||||
if (*len < sizeof(struct usb_cdc_line_coding)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
|
||||
{
|
||||
//gpio_toggle(GPIOB,GPIO8);
|
||||
(void)ep;
|
||||
|
||||
char buf[64];
|
||||
int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
|
||||
rb_write(&rx_buf, buf, len);
|
||||
}
|
||||
|
||||
void cdcacm_flush(){
|
||||
|
||||
}
|
||||
|
||||
int cdcacm_tx(void* data, uint32_t len){
|
||||
if(usb_connected == 0){
|
||||
return 0;
|
||||
}
|
||||
int ret, len2;
|
||||
char buf[64];
|
||||
ret = rb_write(&tx_buf, data, len);
|
||||
if(!usbd_ep_stall_get(usbd_dev, 0.82) && tx_buf.len > 0){
|
||||
len2 = rb_read(&tx_buf,buf,64);
|
||||
usbd_ep_write_packet(usbd_dev, 0x82, buf,len2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cdcacm_data_tx_cb(usbd_device *usbd_dev, uint8_t ep)
|
||||
{
|
||||
if(usb_connected == 0){
|
||||
return;
|
||||
}
|
||||
char buf[64];
|
||||
int len;
|
||||
if(tx_buf.len > 0){
|
||||
len = rb_read(&tx_buf,buf,64);
|
||||
usbd_ep_write_packet(usbd_dev, 0x82, buf,len);
|
||||
}
|
||||
}
|
||||
|
||||
int cdcacm_is_connected(){
|
||||
return usb_connected;
|
||||
}
|
||||
|
||||
//TODO: ptr overflow
|
||||
int cdcacm_getstring(char *ptr){
|
||||
int len = 0;
|
||||
char c;
|
||||
if (rx_buf.len == 0) return 0;
|
||||
|
||||
while(rb_getc(&rx_buf, &c)){
|
||||
len++;
|
||||
*ptr++ = c;
|
||||
if(c == 0x0D){
|
||||
*--ptr = 0x00;
|
||||
return len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// use suspend callback to detect disconnect
|
||||
static void suspend_cb(void)
|
||||
{
|
||||
usb_connected = 0;
|
||||
gpio_clear(GPIOC, GPIO10);
|
||||
}
|
||||
|
||||
static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue)
|
||||
{
|
||||
(void)wValue;
|
||||
|
||||
usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
|
||||
usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_tx_cb);
|
||||
usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
|
||||
|
||||
usbd_register_control_callback(
|
||||
usbd_dev,
|
||||
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
|
||||
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
|
||||
cdcacm_control_request);
|
||||
usb_connected = 1;
|
||||
tx_buf.len = 0;
|
||||
rx_buf.len = 0;
|
||||
gpio_set(GPIOC, GPIO10);
|
||||
usbd_register_suspend_callback(usbd_dev, suspend_cb);
|
||||
}
|
||||
|
||||
void cdc_init(void)
|
||||
{
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
rcc_periph_clock_enable(RCC_OTGFS);
|
||||
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11 | GPIO12);
|
||||
gpio_set_af(GPIOA, GPIO_AF10, GPIO11 | GPIO12);
|
||||
|
||||
usbd_dev = usbd_init(&otgfs_usb_driver, &dev, &config, usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer));
|
||||
|
||||
usbd_register_set_config_callback(usbd_dev, cdcacm_set_config);
|
||||
usb_connected = 0;
|
||||
}
|
20
src/cdc.h
Normal file
20
src/cdc.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
#include <libopencm3/usb/cdc.h>
|
||||
#include "ringbuf.h"
|
||||
|
||||
#define RX_QUEUE_SIZE 512
|
||||
#define TX_QUEUE_SIZE 512
|
||||
|
||||
void cdc_init(void);
|
||||
int cdcacm_tx(void* data, uint32_t len);
|
||||
int cdcacm_getstring(char *ptr);
|
||||
int cdcacm_is_connected();
|
||||
void cdcacm_flush();
|
||||
|
||||
usbd_device *usbd_dev;
|
||||
int usb_connected;
|
||||
|
||||
extern struct ringbuf rx_buf;
|
||||
extern struct ringbuf tx_buf;
|
@ -60,7 +60,7 @@ MEM(unsigned int last_fault_sent) = 0; //save last error message
|
||||
MEM(uint32_t last_hal_state) = HAL_OK;
|
||||
MEM(uint16_t ee_error);
|
||||
|
||||
|
||||
/*
|
||||
int load(){
|
||||
if(hal.rt_state != RT_STOP || hal.frt_state != FRT_STOP){
|
||||
return(-4);
|
||||
@ -104,9 +104,10 @@ int load(){
|
||||
update_fb();
|
||||
return 0;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
INIT(
|
||||
/*
|
||||
FLASH_Unlock();
|
||||
ee_error = EE_Init();
|
||||
FLASH_Lock();
|
||||
@ -114,10 +115,11 @@ INIT(
|
||||
if(ret){//flash load error
|
||||
hal.hal_state = CONFIG_LOAD_ERROR;
|
||||
}
|
||||
*/
|
||||
);
|
||||
|
||||
RT(
|
||||
TIM2->ARR = (int)CLAMP(PIN(tim2_rv), 1, 1500);
|
||||
TIM2_ARR = (int)CLAMP(PIN(tim2_rv), 1, 1500);
|
||||
if(send_counter++ >= PIN(send_step) - 1){
|
||||
w0[write_pos] = PIN(wave0);
|
||||
w1[write_pos] = PIN(wave1);
|
||||
@ -138,11 +140,11 @@ NRT(
|
||||
|
||||
void bootloader(){
|
||||
*((unsigned long *)0x2001C000) = 0xDEADBEEF;
|
||||
NVIC_SystemReset();
|
||||
scb_reset_system();
|
||||
}
|
||||
|
||||
void reset(){
|
||||
NVIC_SystemReset();
|
||||
scb_reset_system();
|
||||
}
|
||||
|
||||
void hal_info(){
|
||||
@ -298,16 +300,15 @@ NRT(
|
||||
printf("by %s on %s\n",version_info.build_user, version_info.build_host);
|
||||
printf("GCC %s\n",__VERSION__);
|
||||
printf("newlib %s\n",_NEWLIB_VERSION);
|
||||
printf("CMSIS %i.%i\n",__CM4_CMSIS_VERSION_MAIN,__CM4_CMSIS_VERSION_SUB);
|
||||
printf("StdPeriph %i.%i.%i\n",__STM32F4XX_STDPERIPH_VERSION_MAIN,__STM32F4XX_STDPERIPH_VERSION_SUB1,__STM32F4XX_STDPERIPH_VERSION_SUB2);
|
||||
printf("CPU ID %lx %lx %lx\n",U_ID[0], U_ID[1], U_ID[2]);
|
||||
CRC_ResetDR();
|
||||
uint32_t crc = CRC_CalcBlockCRC((uint32_t *) 0x08010000, version_info.image_size / 4);
|
||||
//TODO
|
||||
//CRC_ResetDR();
|
||||
//uint32_t crc = CRC_CalcBlockCRC((uint32_t *) 0x08010000, version_info.image_size / 4);
|
||||
printf("size: %lu crc:%lx\n", version_info.image_size, version_info.image_crc);
|
||||
if(crc == 0)
|
||||
printf("crc ok!\n");
|
||||
else
|
||||
printf("crc error!:%lx\n", crc);
|
||||
//if(crc == 0)
|
||||
// printf("crc ok!\n");
|
||||
//else
|
||||
// printf("crc error!:%lx\n", crc);
|
||||
|
||||
printf("######## Bootloader info ########\n");
|
||||
printf(
|
||||
@ -339,43 +340,43 @@ NRT(
|
||||
|
||||
void sysinfo(){
|
||||
printf("######## sysinfo ########\n");
|
||||
extern char _etext; // end address of the .text section
|
||||
extern char _sidata; // start address of the initialization values of the .data section
|
||||
extern char _sdata; // start address of the .data section
|
||||
extern char _edata; // end address of the .data section
|
||||
extern char _sbss; // start address of the .bss section
|
||||
extern char _ebss; // end address of the .bss section
|
||||
// extern char _etext; // end address of the .text section
|
||||
// extern char _sidata; // start address of the initialization values of the .data section
|
||||
// extern char _sdata; // start address of the .data section
|
||||
// extern char _edata; // end address of the .data section
|
||||
// extern char _sbss; // start address of the .bss section
|
||||
// extern char _ebss; // end address of the .bss section
|
||||
//extern char _snoinit; // start address of the .noinit section
|
||||
//extern char _enoinit; // end address of the .noinit section
|
||||
extern char _end; // end address of the .bss section
|
||||
extern char _estack; // initial value of the stack pointer
|
||||
// extern char _end; // end address of the .bss section
|
||||
// extern char _estack; // initial value of the stack pointer
|
||||
//
|
||||
// extern char *__brkval;
|
||||
|
||||
extern char *__brkval;
|
||||
//RCC_ClocksTypeDef RCC_ClocksStatus;
|
||||
//RCC_GetClocksFreq(&RCC_ClocksStatus);
|
||||
|
||||
RCC_ClocksTypeDef RCC_ClocksStatus;
|
||||
RCC_GetClocksFreq(&RCC_ClocksStatus);
|
||||
|
||||
printf("HSE_VALUE = %uHz\n", HSE_VALUE);
|
||||
printf("SYSCLK_Frequency = %luHz\n", RCC_ClocksStatus.SYSCLK_Frequency );
|
||||
printf("HCLK_Frequency = %luHz\n", RCC_ClocksStatus.HCLK_Frequency );
|
||||
printf("PCLK1_Frequency = %luHz\n", RCC_ClocksStatus.PCLK1_Frequency );
|
||||
printf("PCLK2_Frequency = %luHz\n", RCC_ClocksStatus.PCLK2_Frequency );
|
||||
extern void *g_pfnVectors;
|
||||
printf("vtor %lu\n",(uint32_t)&g_pfnVectors);
|
||||
// printf("HSE_VALUE = %uHz\n", HSE_VALUE);
|
||||
// printf("SYSCLK_Frequency = %luHz\n", RCC_ClocksStatus.SYSCLK_Frequency );
|
||||
// printf("HCLK_Frequency = %luHz\n", RCC_ClocksStatus.HCLK_Frequency );
|
||||
// printf("PCLK1_Frequency = %luHz\n", RCC_ClocksStatus.PCLK1_Frequency );
|
||||
// printf("PCLK2_Frequency = %luHz\n", RCC_ClocksStatus.PCLK2_Frequency );
|
||||
//extern void *g_pfnVectors;
|
||||
//printf("vtor %lu\n",(uint32_t)&g_pfnVectors);
|
||||
//*****************************************************************
|
||||
printf("RCC->CSR = %x\n", (unsigned int)RCC->CSR);
|
||||
printf("_etext = %p\n", &_etext );
|
||||
printf("_sidata = %p\n", &_sidata );
|
||||
printf("_sdata = %p\n", &_sdata );
|
||||
printf("_edata = %p\n", &_edata );
|
||||
printf("_sbss = %p\n", &_sbss );
|
||||
printf("_ebss = %p\n", &_ebss );
|
||||
//printf("RCC->CSR = %x\n", (unsigned int)RCC_CSR);
|
||||
// printf("_etext = %p\n", &_etext );
|
||||
// printf("_sidata = %p\n", &_sidata );
|
||||
// printf("_sdata = %p\n", &_sdata );
|
||||
// printf("_edata = %p\n", &_edata );
|
||||
// printf("_sbss = %p\n", &_sbss );
|
||||
// printf("_ebss = %p\n", &_ebss );
|
||||
// printf("_snoinit = %p\n", &_snoinit);
|
||||
// printf("_enoinit = %p\n", &_enoinit);
|
||||
printf("_end = %p\n", &_end );
|
||||
printf("_estack = %p\n", &_estack );
|
||||
// printf("_end = %p\n", &_end );
|
||||
// printf("_estack = %p\n", &_estack );
|
||||
|
||||
printf("heap avail = %luB\n", (uint32_t)((char*)__get_MSP() - __brkval));
|
||||
// printf("heap avail = %luB\n", (uint32_t)((char*)__get_MSP() - __brkval));
|
||||
}
|
||||
|
||||
void listhal(){
|
||||
@ -384,7 +385,7 @@ NRT(
|
||||
Wait(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void save(){
|
||||
if(ee_error != FLASH_COMPLETE){
|
||||
printf("flash error:%i\n",ee_error);
|
||||
@ -423,6 +424,7 @@ NRT(
|
||||
FLASH_Lock();
|
||||
printf("done\n");
|
||||
}
|
||||
*/
|
||||
|
||||
void conf(){
|
||||
for(int i = 0; i < hal.hal_pin_count; i++){
|
||||
@ -434,7 +436,7 @@ NRT(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void load_cmd(){
|
||||
int ret = load();
|
||||
if(ret == -1){
|
||||
@ -451,7 +453,7 @@ NRT(
|
||||
printf("done\n");
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
void help(){
|
||||
printf("######## HAL cheat sheet ########\n");
|
||||
printf("pin name: <comp name><comp instance number>.<pin name> (e.g. pid0.enable)\n");
|
||||
@ -503,16 +505,20 @@ NRT(
|
||||
help();
|
||||
}
|
||||
else if(!strcmp(s, "save")){
|
||||
save();
|
||||
//TODO:
|
||||
//save();
|
||||
printf("not implemented\n");
|
||||
}
|
||||
else if(!strcmp(s, "load")){
|
||||
load_cmd();
|
||||
//TODO:
|
||||
//load_cmd();
|
||||
printf("not implemented\n");
|
||||
}
|
||||
else if(!strcmp(s, "conf")){
|
||||
conf();
|
||||
}
|
||||
else{
|
||||
printf("not found: %s\n",s);
|
||||
printf("cmd not found: %s\n",s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -657,9 +663,9 @@ NRT(
|
||||
|
||||
buf[8 + 1] = 0;
|
||||
|
||||
if (USB_CDC_is_connected()) {
|
||||
if (cdcacm_is_connected()) {
|
||||
PIN(con) = 1.0;
|
||||
USB_VCP_send_string(buf);
|
||||
cdcacm_tx(buf,9);
|
||||
}else{
|
||||
PIN(con) = 0.0;
|
||||
}
|
||||
@ -669,16 +675,16 @@ NRT(
|
||||
|
||||
|
||||
|
||||
if (USB_CDC_is_connected() && systime >= 1000) {
|
||||
char source[APP_TX_BUF_SIZE];
|
||||
char sink[APP_TX_BUF_SIZE];
|
||||
if (cdcacm_is_connected()) {
|
||||
char source[MAX_HPNAME];
|
||||
char sink[MAX_HPNAME];
|
||||
|
||||
fault_sender();
|
||||
hal_error_sender();
|
||||
|
||||
int i = -1;
|
||||
char rx_buf[APP_TX_BUF_SIZE];
|
||||
if (USB_VCP_get_string(rx_buf)) {
|
||||
char rx_buf[65];
|
||||
if (cdcacm_getstring(rx_buf)) {
|
||||
i = sscanf_(rx_buf, "%N = %N", sink, source);
|
||||
}
|
||||
if(i == 2){ // read hal pin
|
||||
|
16
src/hal.h
16
src/hal.h
@ -198,24 +198,24 @@ extern void disable_frt();
|
||||
|
||||
#define RT(func) \
|
||||
self.rt = ({ void function(float period){ \
|
||||
unsigned int __start_time__ = SysTick->VAL; \
|
||||
unsigned int __start_time__ = systick_get_value(); \
|
||||
func \
|
||||
unsigned int __end_time__ = SysTick->VAL; \
|
||||
unsigned int __end_time__ = systick_get_value(); \
|
||||
if(__start_time__ < __end_time__){ \
|
||||
__start_time__ += SysTick->LOAD; \
|
||||
__start_time__ += systick_get_reload(); \
|
||||
} \
|
||||
PIN(rt_calc_time) = ((float)(__start_time__ - __end_time__)) / RCC_Clocks.HCLK_Frequency; \
|
||||
PIN(rt_calc_time) = ((float)(__start_time__ - __end_time__)) / rcc_ahb_frequency; \
|
||||
} function;});
|
||||
|
||||
#define FRT(func) \
|
||||
self.frt = ({ void function(float period){ \
|
||||
unsigned int __start_time__ = SysTick->VAL; \
|
||||
unsigned int __start_time__ = systick_get_value(); \
|
||||
func \
|
||||
unsigned int __end_time__ = SysTick->VAL; \
|
||||
unsigned int __end_time__ = systick_get_value(); \
|
||||
if(__start_time__ < __end_time__){ \
|
||||
__start_time__ += SysTick->LOAD; \
|
||||
__start_time__ += systick_get_reload(); \
|
||||
} \
|
||||
PIN(frt_calc_time) = ((float)(__start_time__ - __end_time__)) / RCC_Clocks.HCLK_Frequency; \
|
||||
PIN(frt_calc_time) = ((float)(__start_time__ - __end_time__)) / rcc_ahb_frequency; \
|
||||
} function;});
|
||||
|
||||
#define NRT(func) \
|
||||
|
94
src/main.c
94
src/main.c
@ -18,18 +18,16 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "stm32f4xx_conf.h"
|
||||
#include "scanf.h"
|
||||
#include "hal.h"
|
||||
#include "setup.h"
|
||||
#include "eeprom.h"
|
||||
//#include "eeprom.h"
|
||||
#include "link.h"
|
||||
#include "crc8.h"
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "usb_cdc.h"
|
||||
|
||||
|
||||
GLOBAL_HAL_PIN(rt_time);
|
||||
@ -41,16 +39,16 @@ void Wait(uint32_t ms);
|
||||
|
||||
//hal interface
|
||||
void enable_rt(){
|
||||
TIM_Cmd(TIM2, ENABLE);
|
||||
timer_enable_counter(TIM2);
|
||||
}
|
||||
void enable_frt(){
|
||||
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
|
||||
timer_enable_irq(TIM2,TIM_DIER_UIE);
|
||||
}
|
||||
void disable_rt(){
|
||||
TIM_Cmd(TIM2, DISABLE);
|
||||
timer_disable_counter(TIM2);
|
||||
}
|
||||
void disable_frt(){
|
||||
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
|
||||
timer_disable_irq(TIM2,TIM_DIER_UIE);
|
||||
}
|
||||
|
||||
extern char _binary_obj_hv_hv_bin_start;
|
||||
@ -65,8 +63,8 @@ void SysTick_Handler(void)
|
||||
}
|
||||
|
||||
//20kHz
|
||||
void TIM2_IRQHandler(void){
|
||||
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
|
||||
void tim2_isr(void){
|
||||
timer_clear_flag(TIM2,TIM_SR_UIF);
|
||||
switch(hal.frt_state){
|
||||
case FRT_STOP:
|
||||
return;
|
||||
@ -85,16 +83,16 @@ void TIM2_IRQHandler(void){
|
||||
hal.frt_state = FRT_CALC;
|
||||
}
|
||||
|
||||
GPIO_SetBits(GPIOB,GPIO_Pin_9);
|
||||
gpio_set(GPIOB,GPIO9);
|
||||
|
||||
static unsigned int last_start = 0;
|
||||
unsigned int start = SysTick->VAL;
|
||||
unsigned int start = systick_get_value();
|
||||
|
||||
if(last_start < start){
|
||||
last_start += SysTick->LOAD;
|
||||
last_start += systick_get_reload();
|
||||
}
|
||||
|
||||
float period = ((float)(last_start - start)) / RCC_Clocks.HCLK_Frequency;
|
||||
float period = ((float)(last_start - start)) / rcc_ahb_frequency;
|
||||
last_start = start;
|
||||
|
||||
for(hal.active_frt_func = 0; hal.active_frt_func < hal.frt_func_count; hal.active_frt_func++){//run all fast realtime hal functions
|
||||
@ -102,21 +100,21 @@ void TIM2_IRQHandler(void){
|
||||
}
|
||||
hal.active_frt_func = -1;
|
||||
|
||||
unsigned int end = SysTick->VAL;
|
||||
unsigned int end = systick_get_value();
|
||||
if(start < end){
|
||||
start += SysTick->LOAD;
|
||||
start += systick_get_reload();
|
||||
}
|
||||
PIN(frt_time) = ((float)(start - end)) / RCC_Clocks.HCLK_Frequency;
|
||||
PIN(frt_time) = ((float)(start - end)) / rcc_ahb_frequency;
|
||||
PIN(frt_period_time) = period;
|
||||
|
||||
hal.frt_state = FRT_SLEEP;
|
||||
GPIO_ResetBits(GPIOB,GPIO_Pin_9);
|
||||
gpio_clear(GPIOB,GPIO9);
|
||||
}
|
||||
|
||||
//5 kHz interrupt for hal. at this point all ADCs have been sampled,
|
||||
//see setup_res() in setup.c if you are interested in the magic behind this.
|
||||
void DMA2_Stream0_IRQHandler(void){
|
||||
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
|
||||
void dma2_stream0_isr(void){
|
||||
dma_clear_interrupt_flags(DMA2, DMA_STREAM0, DMA_TCIF);
|
||||
switch(hal.rt_state){
|
||||
case RT_STOP:
|
||||
return;
|
||||
@ -135,16 +133,16 @@ void DMA2_Stream0_IRQHandler(void){
|
||||
hal.rt_state = RT_CALC;
|
||||
}
|
||||
|
||||
GPIO_SetBits(GPIOB,GPIO_Pin_8);
|
||||
gpio_set(GPIOB,GPIO8);
|
||||
|
||||
static unsigned int last_start = 0;
|
||||
unsigned int start = SysTick->VAL;
|
||||
unsigned int start = systick_get_value();
|
||||
|
||||
if(last_start < start){
|
||||
last_start += SysTick->LOAD;
|
||||
last_start += systick_get_reload();
|
||||
}
|
||||
|
||||
float period = ((float)(last_start - start)) / RCC_Clocks.HCLK_Frequency;
|
||||
float period = ((float)(last_start - start)) / rcc_ahb_frequency;
|
||||
last_start = start;
|
||||
|
||||
for(hal.active_rt_func = 0; hal.active_rt_func < hal.rt_func_count; hal.active_rt_func++){//run all realtime hal functions
|
||||
@ -152,23 +150,24 @@ void DMA2_Stream0_IRQHandler(void){
|
||||
}
|
||||
hal.active_rt_func = -1;
|
||||
|
||||
unsigned int end = SysTick->VAL;
|
||||
unsigned int end = systick_get_value();
|
||||
if(start < end){
|
||||
start += SysTick->LOAD;
|
||||
start += systick_get_reload();
|
||||
}
|
||||
PIN(rt_time) = ((float)(start - end)) / RCC_Clocks.HCLK_Frequency;
|
||||
PIN(rt_time) = ((float)(start - end)) / rcc_ahb_frequency;
|
||||
PIN(rt_period_time) = period;
|
||||
|
||||
hal.rt_state = RT_SLEEP;
|
||||
GPIO_ResetBits(GPIOB,GPIO_Pin_8);
|
||||
gpio_clear(GPIOB,GPIO8);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
|
||||
// Relocate interrupt vectors
|
||||
//
|
||||
extern void *g_pfnVectors;
|
||||
SCB->VTOR = (uint32_t)&g_pfnVectors;
|
||||
//extern void *vector_table;
|
||||
//SCB_VTOR = (uint32_t)&vector_table;
|
||||
|
||||
float period = 0.0;
|
||||
int last_start = 0;
|
||||
@ -182,19 +181,19 @@ int main(void)
|
||||
HAL_PIN(bar) = 0.0;
|
||||
|
||||
//feedback comps
|
||||
#include "comps/adc.comp"
|
||||
#include "comps/res.comp"
|
||||
#include "comps/enc_fb.comp"
|
||||
#include "comps/encm.comp"
|
||||
#include "comps/encs.comp"
|
||||
#include "comps/yaskawa.comp"
|
||||
// #include "comps/adc.comp"
|
||||
// #include "comps/res.comp"
|
||||
// #include "comps/enc_fb.comp"
|
||||
// #include "comps/encm.comp"
|
||||
// #include "comps/encs.comp"
|
||||
// #include "comps/yaskawa.comp"
|
||||
//TODO: hyperface
|
||||
|
||||
//command comps
|
||||
#include "comps/sserial.comp"
|
||||
// #include "comps/sserial.comp"
|
||||
#include "comps/sim.comp"
|
||||
#include "comps/enc_cmd.comp"
|
||||
#include "comps/en.comp"
|
||||
// #include "comps/enc_cmd.comp"
|
||||
// #include "comps/en.comp"
|
||||
|
||||
//PID
|
||||
#include "comps/stp.comp"
|
||||
@ -210,12 +209,12 @@ int main(void)
|
||||
#include "comps/pmsm_limits.comp"
|
||||
#include "comps/idq.comp"
|
||||
#include "comps/dq.comp"
|
||||
#include "comps/hv.comp"
|
||||
// #include "comps/hv.comp"
|
||||
|
||||
//other comps
|
||||
#include "comps/fault.comp"
|
||||
#include "comps/term.comp"
|
||||
#include "comps/io.comp"
|
||||
// #include "comps/io.comp"
|
||||
|
||||
|
||||
set_comp_type("net");
|
||||
@ -316,13 +315,14 @@ int main(void)
|
||||
|
||||
while(1)//run non realtime stuff
|
||||
{
|
||||
start = SysTick->VAL;
|
||||
usbd_poll(usbd_dev);
|
||||
start = systick_get_value();
|
||||
|
||||
if(last_start < start){
|
||||
last_start += SysTick->LOAD;
|
||||
last_start += systick_get_reload();
|
||||
}
|
||||
|
||||
period = ((float)(last_start - start)) / RCC_Clocks.HCLK_Frequency;
|
||||
period = ((float)(last_start - start)) / rcc_ahb_frequency;
|
||||
last_start = start;
|
||||
|
||||
for(hal.active_nrt_func = 0; hal.active_nrt_func < hal.nrt_func_count; hal.active_nrt_func++){//run all non realtime hal functions
|
||||
@ -330,13 +330,13 @@ int main(void)
|
||||
}
|
||||
hal.active_nrt_func = -1;
|
||||
|
||||
end = SysTick->VAL;
|
||||
end = systick_get_value();
|
||||
if(start < end){
|
||||
start += SysTick->LOAD;
|
||||
start += systick_get_reload();
|
||||
}
|
||||
PIN(nrt_calc_time) = ((float)(start - end)) / RCC_Clocks.HCLK_Frequency;
|
||||
PIN(nrt_calc_time) = ((float)(start - end)) / rcc_ahb_frequency;
|
||||
PIN(nrt_period) = period;
|
||||
Wait(2);
|
||||
//Wait(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
32
src/scanf.c
32
src/scanf.c
@ -7,23 +7,23 @@
|
||||
//
|
||||
|
||||
#include "scanf.h"
|
||||
#include "usb_cdc.h"
|
||||
//#include "usb_cdc.h"
|
||||
|
||||
int scanf_(const char *format, ...){
|
||||
int ret = 0;
|
||||
char rx_buf[APP_TX_BUF_SIZE];
|
||||
va_list arg;
|
||||
if (USB_CDC_is_connected()) {
|
||||
if (USB_VCP_get_string(rx_buf)) {
|
||||
va_start(arg, format);
|
||||
ret = vfsscanf_(rx_buf, format, arg);
|
||||
va_end(arg);
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
// int scanf_(const char *format, ...){
|
||||
// int ret = 0;
|
||||
// char rx_buf[10];
|
||||
// va_list arg;
|
||||
// if (USB_CDC_is_connected()) {
|
||||
// if (USB_VCP_get_string(rx_buf)) {
|
||||
// va_start(arg, format);
|
||||
// ret = vfsscanf_(rx_buf, format, arg);
|
||||
// va_end(arg);
|
||||
// } else {
|
||||
// ret = -1;
|
||||
// }
|
||||
// }
|
||||
// return(ret);
|
||||
// }
|
||||
|
||||
int sscanf_(const char *buf, const char *format, ...){
|
||||
int ret = 0;
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
int scanf_(const char *format, ...);
|
||||
//int scanf_(const char *format, ...);
|
||||
int sscanf_(const char* buf, const char *format, ...);
|
||||
int vfsscanf_(const char *buf, const char *format, va_list arg);
|
||||
int isDecDigit(char c);
|
||||
|
278
src/setup.c
278
src/setup.c
@ -7,130 +7,218 @@
|
||||
//
|
||||
|
||||
#include "setup.h"
|
||||
#include "usb_cdc.h"
|
||||
//#include "usb_cdc.h"
|
||||
|
||||
void setup(){
|
||||
//Enable clocks
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA1 | RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_CRC, ENABLE);
|
||||
//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA1 | RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_CRC, ENABLE);
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
rcc_periph_clock_enable(RCC_GPIOB);
|
||||
rcc_periph_clock_enable(RCC_GPIOC);
|
||||
rcc_periph_clock_enable(RCC_GPIOD);
|
||||
rcc_periph_clock_enable(RCC_DMA1);
|
||||
rcc_periph_clock_enable(RCC_DMA2);
|
||||
rcc_periph_clock_enable(RCC_CRC);
|
||||
|
||||
//messpin
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9;
|
||||
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
// GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
// GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO3 | GPIO4 | GPIO5 | GPIO8 | GPIO9);
|
||||
//gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO3 | GPIO4 | GPIO5 | GPIO8 | GPIO9);
|
||||
|
||||
//foo leds
|
||||
gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT,GPIO_PUPD_NONE, GPIO10 | GPIO11);
|
||||
gpio_set(GPIOC, GPIO11);
|
||||
gpio_clear(GPIOC, GPIO10);
|
||||
//foo
|
||||
|
||||
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
|
||||
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
|
||||
//scb_set_priority_grouping();//TODO
|
||||
|
||||
setup_res();
|
||||
usb_init();
|
||||
|
||||
//usb_init();
|
||||
cdc_init();
|
||||
// systick timer
|
||||
RCC_GetClocksFreq(&RCC_Clocks);
|
||||
SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);
|
||||
//RCC_GetClocksFreq(&RCC_Clocks);
|
||||
//SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);
|
||||
systick_set_reload(rcc_ahb_frequency / 1000);
|
||||
systick_interrupt_enable();
|
||||
systick_counter_enable();//??
|
||||
//systick prio
|
||||
|
||||
NVIC_SetPriority(SysTick_IRQn, 14);
|
||||
//NVIC_SetPriority(SysTick_IRQn, 14);
|
||||
nvic_set_priority(NVIC_SYSTICK_IRQ,14);
|
||||
nvic_enable_irq(NVIC_SYSTICK_IRQ);
|
||||
}
|
||||
|
||||
// Setup Resolver Interface
|
||||
// TIM2 triggers ADC1 and 2 at 20kHz
|
||||
// TIM2 OC1 generates resolver reference signal at 10kHz
|
||||
// DMA2 moves 4 samples to memory, generates transfer complete interrupt at 5kHz
|
||||
|
||||
void setup_res(){
|
||||
//resolver timer
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
||||
//RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
||||
rcc_periph_clock_enable(RCC_TIM2);
|
||||
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseStructure.TIM_Period = 420;//20kHz
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = 9;
|
||||
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
|
||||
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
|
||||
TIM_ARRPreloadConfig(TIM2,ENABLE);
|
||||
// TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
// TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
// TIM_TimeBaseStructure.TIM_Period = 420;//20kHz
|
||||
// TIM_TimeBaseStructure.TIM_Prescaler = 9;
|
||||
// TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
|
||||
// TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
|
||||
//TIM_ARRPreloadConfig(TIM2,ENABLE);
|
||||
|
||||
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);//trigger ADC
|
||||
//timer_set_mode(TIM2,TIM_CR1_CKD_CK_INT,TIM_CR1_CMS_EDGE,TIM_CR1_DIR_UP);
|
||||
timer_reset(TIM2);
|
||||
timer_set_mode(TIM2,TIM_CR1_CKD_CK_INT,TIM_CR1_CMS_EDGE,TIM_CR1_DIR_UP);
|
||||
timer_set_clock_division(TIM2,TIM_CR1_CKD_CK_INT);
|
||||
timer_direction_up(TIM2);
|
||||
timer_set_repetition_counter(TIM2,0);
|
||||
//timer_enable_preload(TIM2);
|
||||
timer_set_period(TIM2,420);
|
||||
timer_set_prescaler(TIM2,9);
|
||||
timer_enable_update_event(TIM2);
|
||||
//hal does this:
|
||||
//timer_enable_irq(TIM2,TIM_DIER_UIE);
|
||||
//timer_enable_counter(TIM2);
|
||||
|
||||
//TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);//trigger ADC
|
||||
timer_set_master_mode(TIM2,TIM_CR2_MMS_UPDATE);
|
||||
|
||||
/* ADC clock enable */
|
||||
RCC_APB2PeriphClockCmd(SIN_ADC_RCC | COS_ADC_RCC, ENABLE);
|
||||
//RCC_APB2PeriphClockCmd(SIN_ADC_RCC | COS_ADC_RCC, ENABLE);
|
||||
rcc_periph_clock_enable(RCC_ADC1);
|
||||
rcc_periph_clock_enable(RCC_ADC2);
|
||||
|
||||
//Analog pin configuration
|
||||
GPIO_InitStructure.GPIO_Pin = SIN_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(SIN_PORT,&GPIO_InitStructure);
|
||||
// GPIO_InitStructure.GPIO_Pin = SIN_PIN;
|
||||
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
|
||||
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
// GPIO_Init(SIN_PORT,&GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = COS_PIN;
|
||||
GPIO_Init(COS_PORT,&GPIO_InitStructure);
|
||||
// GPIO_InitStructure.GPIO_Pin = COS_PIN;
|
||||
// GPIO_Init(COS_PORT,&GPIO_InitStructure);
|
||||
gpio_mode_setup(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4);
|
||||
gpio_mode_setup(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO5);
|
||||
|
||||
//ADC structure configuration
|
||||
ADC_DeInit();
|
||||
//ADC_DeInit();
|
||||
adc_off(ADC1);
|
||||
adc_off(ADC2);
|
||||
|
||||
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//data converted will be shifted to right
|
||||
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//Input voltage is converted into a 12bit number giving a maximum value of 4096
|
||||
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //the conversion is continuous, the input data is converted more than once
|
||||
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;//trigger on rising edge of TIM8
|
||||
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
|
||||
ADC_InitStructure.ADC_NbrOfConversion = ADC_ANZ;//I think this one is clear :p
|
||||
ADC_InitStructure.ADC_ScanConvMode = ENABLE;//The scan is configured in one channel
|
||||
ADC_Init(SIN_ADC, &ADC_InitStructure);//Initialize ADC with the previous configuration
|
||||
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
|
||||
ADC_Init(COS_ADC, &ADC_InitStructure);//Initialize ADC with the previous configuration
|
||||
// ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//data converted will be shifted to right
|
||||
adc_set_right_aligned(ADC1);
|
||||
adc_set_right_aligned(ADC2);
|
||||
// ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//Input voltage is converted into a 12bit number giving a maximum value of 4096
|
||||
adc_set_resolution(ADC1,ADC_CR1_RES_12BIT);
|
||||
adc_set_resolution(ADC2,ADC_CR1_RES_12BIT);
|
||||
// ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //the conversion is continuous, the input data is converted more than once
|
||||
adc_enable_discontinuous_mode_regular(ADC1,ADC_ANZ);
|
||||
adc_enable_discontinuous_mode_regular(ADC2,ADC_ANZ);
|
||||
adc_disable_external_trigger_injected(ADC1);
|
||||
adc_disable_external_trigger_injected(ADC2);
|
||||
// ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;//trigger on rising edge of TIM8
|
||||
// ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
|
||||
adc_enable_external_trigger_regular(ADC1,ADC_CR2_EXTSEL_TIM2_TRGO,ADC_CR2_EXTEN_RISING_EDGE);//ADC2 trigger via dual mode
|
||||
// ADC_InitStructure.ADC_NbrOfConversion = ADC_ANZ;//I think this one is clear :p
|
||||
// ADC_InitStructure.ADC_ScanConvMode = ENABLE;//The scan is configured in one channel
|
||||
adc_enable_scan_mode(ADC1);
|
||||
adc_enable_scan_mode(ADC2);
|
||||
// ADC_Init(SIN_ADC, &ADC_InitStructure);//Initialize ADC with the previous configuration
|
||||
// ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
|
||||
// ADC_Init(COS_ADC, &ADC_InitStructure);//Initialize ADC with the previous configuration
|
||||
//
|
||||
// ADC_CommonInitTypeDef ADC_CommonInitStructure;
|
||||
// ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;
|
||||
// ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
|
||||
adc_set_clk_prescale(ADC_CCR_ADCPRE_BY4);
|
||||
// ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2;
|
||||
//TODO: set this bit: ADC_CCR_DMA_MODE_2
|
||||
ADC_CCR |= ADC_CCR_DMA_MODE_2;
|
||||
ADC_CCR |= ADC_CCR_DDS;
|
||||
// ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
|
||||
// ADC_CommonInit(&ADC_CommonInitStructure);
|
||||
// for(int i = 1;i<=ADC_ANZ;i++){16
|
||||
// ADC_RegularChannelConfig(SIN_ADC, SIN_ADC_CHAN, i, RES_SampleTime);14
|
||||
// ADC_RegularChannelConfig(COS_ADC, COS_ADC_CHAN, i, RES_SampleTime);15
|
||||
// }
|
||||
//TODO: sample time?
|
||||
adc_set_sample_time_on_all_channels(ADC1,ADC_SMPR_SMP_28CYC);
|
||||
adc_set_sample_time_on_all_channels(ADC2,ADC_SMPR_SMP_28CYC);
|
||||
uint8_t sin_ch[] = {14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14};
|
||||
uint8_t cos_ch[] = {15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15};
|
||||
adc_set_regular_sequence(ADC1, 16, sin_ch);
|
||||
adc_set_regular_sequence(ADC2, 16, cos_ch);
|
||||
|
||||
adc_enable_dma(ADC1);
|
||||
adc_enable_dma(ADC2);
|
||||
//
|
||||
// ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
|
||||
adc_set_multi_mode(ADC_CCR_MULTI_DUAL_REGULAR_SIMUL);
|
||||
|
||||
ADC_CommonInitTypeDef ADC_CommonInitStructure;
|
||||
ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;
|
||||
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
|
||||
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2;
|
||||
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
|
||||
ADC_CommonInit(&ADC_CommonInitStructure);
|
||||
// //Enable ADC conversion
|
||||
// ADC_Cmd(SIN_ADC,ENABLE);
|
||||
adc_power_on(ADC1);
|
||||
// ADC_Cmd(COS_ADC,ENABLE);
|
||||
adc_power_on(ADC2);
|
||||
//
|
||||
// // DMA-Disable
|
||||
// DMA_Cmd(DMA2_Stream0, DISABLE);
|
||||
// DMA_DeInit(DMA2_Stream0);
|
||||
dma_stream_reset(DMA2, DMA_STREAM0);
|
||||
//
|
||||
// // DMA2-Config
|
||||
// DMA_InitStructure.DMA_Channel = DMA_Channel_0;
|
||||
dma_channel_select(DMA2, DMA_STREAM0, DMA_SxCR_CHSEL_0);
|
||||
// DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC->CDR;
|
||||
dma_set_peripheral_address(DMA2, DMA_STREAM0, (uint32_t)&ADC_CDR);
|
||||
// DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_DMA_Buffer;
|
||||
dma_set_memory_address(DMA2, DMA_STREAM0, (uint32_t)&ADC_DMA_Buffer);
|
||||
// DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
dma_set_transfer_mode(DMA2, DMA_STREAM0, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
|
||||
// DMA_InitStructure.DMA_BufferSize = ADC_ANZ * PID_WAVES;
|
||||
dma_set_number_of_data(DMA2, DMA_STREAM0, ADC_ANZ * PID_WAVES);
|
||||
// DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
// DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
dma_enable_memory_increment_mode(DMA2, DMA_STREAM0);
|
||||
// DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
|
||||
dma_set_peripheral_size(DMA2, DMA_STREAM0, DMA_SxCR_PSIZE_32BIT);
|
||||
// DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
|
||||
dma_set_memory_size(DMA2, DMA_STREAM0, DMA_SxCR_MSIZE_32BIT);
|
||||
// DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
dma_enable_circular_mode(DMA2, DMA_STREAM0);
|
||||
// DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
||||
dma_set_priority(DMA2, DMA_STREAM0, DMA_SxCR_PL_HIGH);
|
||||
// DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
// DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
|
||||
// DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
// DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
// DMA_Init(DMA2_Stream0, &DMA_InitStructure);
|
||||
|
||||
for(int i = 1;i<=ADC_ANZ;i++){
|
||||
ADC_RegularChannelConfig(SIN_ADC, SIN_ADC_CHAN, i, RES_SampleTime);
|
||||
ADC_RegularChannelConfig(COS_ADC, COS_ADC_CHAN, i, RES_SampleTime);
|
||||
}
|
||||
|
||||
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
|
||||
|
||||
//Enable ADC conversion
|
||||
ADC_Cmd(SIN_ADC,ENABLE);
|
||||
ADC_Cmd(COS_ADC,ENABLE);
|
||||
|
||||
// DMA-Disable
|
||||
DMA_Cmd(DMA2_Stream0, DISABLE);
|
||||
DMA_DeInit(DMA2_Stream0);
|
||||
|
||||
// DMA2-Config
|
||||
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC->CDR;
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_DMA_Buffer;
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
DMA_InitStructure.DMA_BufferSize = ADC_ANZ * PID_WAVES;
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
DMA_Cmd(DMA2_Stream0, ENABLE);
|
||||
|
||||
DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
|
||||
// NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
|
||||
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
||||
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
// NVIC_Init(&NVIC_InitStructure);
|
||||
nvic_enable_irq(NVIC_TIM2_IRQ);
|
||||
nvic_set_priority(NVIC_TIM2_IRQ,0);
|
||||
//
|
||||
// NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
|
||||
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
|
||||
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
// NVIC_Init(&NVIC_InitStructure);
|
||||
nvic_enable_irq(NVIC_DMA2_STREAM0_IRQ);
|
||||
nvic_set_priority(NVIC_DMA2_STREAM0_IRQ,2);
|
||||
//
|
||||
// DMA_Cmd(DMA2_Stream0, ENABLE);
|
||||
dma_enable_stream(DMA2, DMA_STREAM0);
|
||||
//
|
||||
// DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
|
||||
dma_enable_transfer_complete_interrupt(DMA2, DMA_STREAM0);
|
||||
}
|
||||
|
26
src/setup.h
26
src/setup.h
@ -8,19 +8,31 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stm32f4xx_conf.h"
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/timer.h>
|
||||
#include <libopencm3/stm32/dma.h>
|
||||
#include <libopencm3/stm32/adc.h>
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
#include <libopencm3/usb/cdc.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/cm3/scb.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "version.h"
|
||||
#include "common.h"
|
||||
#include "defines_res.h"
|
||||
#define U_ID ((__IO uint32_t *)0x1FFF7A10)
|
||||
#include "cdc.h"
|
||||
|
||||
#define U_ID ((volatile uint32_t *)0x1FFF7A10)//TODO: should be in opencm3
|
||||
|
||||
|
||||
//#define mag_res 5250
|
||||
#define mag_res 8400
|
||||
|
||||
//sample times for F4: 3,15,28,56,84,112,144,480
|
||||
#define RES_SampleTime ADC_SampleTime_28Cycles
|
||||
//#define RES_SampleTime ADC_SampleTime_28Cycles
|
||||
|
||||
#define ADC_ANZ 16
|
||||
#define PID_WAVES 4
|
||||
@ -29,11 +41,3 @@ void setup(void);
|
||||
void setup_res(void);
|
||||
|
||||
volatile uint32_t ADC_DMA_Buffer[ADC_ANZ * PID_WAVES];
|
||||
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_OCInitTypeDef TIM_OCInitStructure;
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
ADC_InitTypeDef ADC_InitStructure;
|
||||
RCC_ClocksTypeDef RCC_Clocks;
|
||||
|
@ -2,12 +2,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include "stm32f4xx.h"
|
||||
#include "usb_cdc.h"
|
||||
#include "cdc.h"
|
||||
|
||||
//int __errno;
|
||||
size_t __malloc_margin = 256;
|
||||
char *__brkval;
|
||||
|
||||
@ -34,6 +33,14 @@ int _open(const char *name, int flags, int mode) {
|
||||
/* Register name faking - works in collusion with the linker. */
|
||||
register char * stack_ptr asm ("sp");
|
||||
|
||||
uint32_t __get_MSP(void)
|
||||
{
|
||||
register uint32_t result;
|
||||
|
||||
asm volatile ("MRS %0, msp\n" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
void *_sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||
{
|
||||
extern char end; // provided by the linker script
|
||||
@ -50,40 +57,29 @@ void *_sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||
__brkval += incr;
|
||||
|
||||
return ret;
|
||||
return (void*)-1;
|
||||
}
|
||||
|
||||
ssize_t _read(int fd, void *ptr, size_t len)
|
||||
{
|
||||
(void) fd;
|
||||
while (!usb_rx_buf.len);
|
||||
//while (!usb_rx_buf.len);
|
||||
|
||||
if (len > usb_rx_buf.len)
|
||||
len = usb_rx_buf.len;
|
||||
//if (len > usb_rx_buf.len)
|
||||
// len = usb_rx_buf.len;
|
||||
|
||||
char *c = (char *) ptr;
|
||||
for (uint16_t i = 0; i < len; i++)
|
||||
rb_getc(&usb_rx_buf, c++);
|
||||
for (uint16_t i = 0; i < len; i++){}
|
||||
//rb_getc(&usb_rx_buf, c++);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int _write(int fd, const char *ptr, int len)
|
||||
int _write(int file, char *ptr, int len)
|
||||
{
|
||||
char *c = (char *) ptr;
|
||||
(void) fd;
|
||||
int sent = 0;
|
||||
|
||||
while (len--) {
|
||||
// send a queued byte - copy to usb stack buffer
|
||||
APP_Rx_Buffer[APP_Rx_ptr_in++] = *c;
|
||||
c++;
|
||||
|
||||
// To avoid buffer overflow
|
||||
if (APP_Rx_ptr_in >= APP_RX_DATA_SIZE) {
|
||||
APP_Rx_ptr_in = 0;
|
||||
}
|
||||
sent++;
|
||||
if (file == STDOUT_FILENO || file == STDERR_FILENO) {
|
||||
return cdcacm_tx(ptr,len);
|
||||
}
|
||||
return sent;
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
309
stm32_flash.ld
309
stm32_flash.ld
@ -1,193 +1,152 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
**
|
||||
** File : stm32_flash.ld
|
||||
**
|
||||
** Abstract : Linker script for STM32F407VG Device with
|
||||
** 1024KByte FLASH, 192KByte RAM
|
||||
**
|
||||
** Set heap size, stack size and stack location according
|
||||
** to application requirements.
|
||||
**
|
||||
** Set memory bank area and size if external memory is used.
|
||||
**
|
||||
** Target : STMicroelectronics STM32
|
||||
**
|
||||
** Environment : Atollic TrueSTUDIO(R)
|
||||
**
|
||||
** Distribution: The file is distributed “as is,” without any warranty
|
||||
** of any kind.
|
||||
**
|
||||
** (c)Copyright Atollic AB.
|
||||
** You may use this file as-is or modify it according to the needs of your
|
||||
** project. Distribution of this file (unmodified or modified) is not
|
||||
** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the
|
||||
** rights to distribute the assembled, compiled & linked contents of this
|
||||
** file as part of an application binary file, provided that it is built
|
||||
** using the Atollic TrueSTUDIO(R) toolchain.
|
||||
**
|
||||
*****************************************************************************
|
||||
*/
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.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/>.
|
||||
*/
|
||||
|
||||
/* Entry Point */
|
||||
ENTRY(Reset_Handler)
|
||||
/* Linker script for ST STM32F4DISCOVERY (STM32F407VG, 1024K flash, 128K RAM). */
|
||||
|
||||
/* Highest address of the user mode stack */
|
||||
_estack = 0x20020000; /* end of 128K RAM on AHB bus*/
|
||||
|
||||
/* Generate a link error if heap and stack don't fit into RAM */
|
||||
_Min_Heap_Size = 0; /* required amount of heap */
|
||||
_Min_Stack_Size = 0x400; /* required amount of stack */
|
||||
|
||||
/* Specify the memory areas */
|
||||
/* flash layout: 4*16+1*64+7*128=1024 */
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
BOOT (rx) : ORIGIN = 0x08000000, LENGTH = 32K/* sector 0-1 */
|
||||
PARAM0 (rx) : ORIGIN = 0x08008000, LENGTH = 16K/* sector 2 */
|
||||
PARAM1 (rx) : ORIGIN = 0x0800C000, LENGTH = 16K/* sector 3 */
|
||||
FLASH (rx) : ORIGIN = 0x08010000, LENGTH = 960K/* sector 4-11 */
|
||||
CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 64k
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 112K/*SRAM1*/
|
||||
RAM2(xrw) : ORIGIN = 0x2001C000, LENGTH = 16K/*SRAM2*/
|
||||
BKP(xrw) : ORIGIN = 0x40024000, LENGTH = 4K/*backup bkp sram*/
|
||||
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 960K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
/* Define output sections */
|
||||
/* Include the common ld script. */
|
||||
/*INCLUDE libopencm3_stm32f4.ld*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Generic linker script for STM32 targets using libopencm3. */
|
||||
|
||||
/* Memory regions must be defined in the ld script which includes this one. */
|
||||
|
||||
/* Enforce emmition of the vector table. */
|
||||
EXTERN (vector_table)
|
||||
|
||||
/* Define the entry point of the output file. */
|
||||
ENTRY(reset_handler)
|
||||
|
||||
/* Define sections. */
|
||||
SECTIONS
|
||||
{
|
||||
/* The startup code goes first into FLASH */
|
||||
.isr_vector :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
.text : {
|
||||
*(.vectors) /* Vector table */
|
||||
*(.text*) /* Program code */
|
||||
. = ALIGN(4);
|
||||
*(.rodata*) /* Read-only data */
|
||||
. = ALIGN(4);
|
||||
} >rom
|
||||
|
||||
/* version info needs to have a section, so the bootloader and python script can find it */
|
||||
.version_info :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.version_info))
|
||||
. = ALIGN(4);
|
||||
} >rom
|
||||
|
||||
/* version info needs to have a section, so the bootloader and python script can find it */
|
||||
.version_info :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.version_info))
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
.hv_firmware :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.hv_firmware))
|
||||
. = ALIGN(4);
|
||||
} >rom
|
||||
|
||||
.hv_firmware :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.hv_firmware))
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
/* C++ Static constructors/destructors, also used for __attribute__
|
||||
* ((constructor)) and the likes */
|
||||
.preinit_array : {
|
||||
. = ALIGN(4);
|
||||
__preinit_array_start = .;
|
||||
KEEP (*(.preinit_array))
|
||||
__preinit_array_end = .;
|
||||
} >rom
|
||||
.init_array : {
|
||||
. = ALIGN(4);
|
||||
__init_array_start = .;
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
__init_array_end = .;
|
||||
} >rom
|
||||
.fini_array : {
|
||||
. = ALIGN(4);
|
||||
__fini_array_start = .;
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
__fini_array_end = .;
|
||||
} >rom
|
||||
|
||||
/* The program code and other data goes into FLASH */
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text) /* .text sections (code) */
|
||||
*(.text*) /* .text* sections (code) */
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
*(.glue_7) /* glue arm to thumb code */
|
||||
*(.glue_7t) /* glue thumb to arm code */
|
||||
*(.eh_frame)
|
||||
/*
|
||||
* Another section used by C++ stuff, appears when using newlib with
|
||||
* 64bit (long long) printf support
|
||||
*/
|
||||
.ARM.extab : {
|
||||
*(.ARM.extab*)
|
||||
} >rom
|
||||
.ARM.exidx : {
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
} >rom
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .; /* define a global symbols at end of code */
|
||||
_exit = .;
|
||||
} >FLASH
|
||||
.data : {
|
||||
_data = .;
|
||||
*(.data*) /* Read-write initialized data */
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} >ram AT >rom
|
||||
_data_loadaddr = LOADADDR(.data);
|
||||
|
||||
.bss : {
|
||||
*(.bss*) /* Read-write zero initialized data */
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
} >ram
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
|
||||
.ARM : {
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
} >FLASH
|
||||
/*
|
||||
* The .eh_frame section appears to be used for C++ exception handling.
|
||||
* You may need to fix this if you're using C++.
|
||||
*/
|
||||
/DISCARD/ : { *(.eh_frame) }
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array*))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >FLASH
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array*))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} >FLASH
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(.fini_array*))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} >FLASH
|
||||
|
||||
/* used by the startup to initialize data */
|
||||
_sidata = .;
|
||||
|
||||
/* Initialized data sections goes into RAM, load LMA copy after code */
|
||||
.data : AT ( _sidata )
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .; /* create a global symbol at data start */
|
||||
*(.data) /* .data sections */
|
||||
*(.data*) /* .data* sections */
|
||||
|
||||
. = ALIGN(4);
|
||||
_edata = .; /* define a global symbol at data end */
|
||||
} >RAM
|
||||
|
||||
/* Uninitialized data section */
|
||||
. = ALIGN(4);
|
||||
.bss :
|
||||
{
|
||||
/* This is used by the startup in order to initialize the .bss secion */
|
||||
_sbss = .; /* define a global symbol at bss start */
|
||||
__bss_start__ = _sbss;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4);
|
||||
_ebss = .; /* define a global symbol at bss end */
|
||||
__bss_end__ = _ebss;
|
||||
} >RAM
|
||||
|
||||
/* User_heap_stack section, used to check that there is enough RAM left */
|
||||
._user_heap_stack :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE ( end = . );
|
||||
PROVIDE ( _end = . );
|
||||
. = . + _Min_Heap_Size;
|
||||
. = . + _Min_Stack_Size;
|
||||
. = ALIGN(4);
|
||||
} >RAM
|
||||
|
||||
/* MEMORY_bank1 section, code must be located here explicitly */
|
||||
/* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */
|
||||
.memory_b1_text :
|
||||
{
|
||||
*(.mb1text) /* .mb1text sections (code) */
|
||||
*(.mb1text*) /* .mb1text* sections (code) */
|
||||
*(.mb1rodata) /* read-only data (constants) */
|
||||
*(.mb1rodata*)
|
||||
} >MEMORY_B1
|
||||
|
||||
/* Remove information from the standard libraries */
|
||||
/DISCARD/ :
|
||||
{
|
||||
libc.a ( * )
|
||||
libm.a ( * )
|
||||
libgcc.a ( * )
|
||||
}
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
. = ALIGN(4);
|
||||
end = .;
|
||||
}
|
||||
|
||||
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
|
||||
|
Loading…
Reference in New Issue
Block a user