stm32f1: initial support
This commit is contained in:
parent
dc6365c7f8
commit
ebd770b957
10 changed files with 696 additions and 1 deletions
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
|||
TARGET ?= host
|
||||
TARGET := $(filter host stm32f0,${TARGET})
|
||||
TARGET := $(filter host stm32f0 stm32f1,${TARGET})
|
||||
|
||||
ifeq (${TARGET},)
|
||||
$(error No support available for the target)
|
||||
|
|
52
scripts/Makefile.stm32f1
Normal file
52
scripts/Makefile.stm32f1
Normal file
|
@ -0,0 +1,52 @@
|
|||
PREFIX ?= arm-none-eabi-
|
||||
|
||||
LDSCRIPT = support/stm32vl-discovery.ld
|
||||
|
||||
CFLAGS += -Os
|
||||
LDFLAGS += -Os
|
||||
|
||||
CFLAGS += -fno-common --function-sections -fdata-sections
|
||||
LDFLAGS += -static -nostartfiles
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
LDFLAGS += -T ${LDSCRIPT}
|
||||
LIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
|
||||
|
||||
# Set up libopencm3.
|
||||
OPENCM3_DIR ?= libopencm3
|
||||
OPENCM3_LIBNAME = opencm3_stm32f1
|
||||
CFLAGS += -I$(OPENCM3_DIR)/include
|
||||
CFLAGS += -DSTM32F1 -msoft-float -mthumb -mcpu=cortex-m3 -mfix-cortex-m3-ldrd
|
||||
LDFLAGS += -L$(OPENCM3_DIR)/lib
|
||||
LIBS += -l$(OPENCM3_LIBNAME)
|
||||
|
||||
STLINK_PORT ?= :4242
|
||||
|
||||
obj-y += source/core/spi.o
|
||||
obj-y += source/drivers/spi_flash.o
|
||||
|
||||
$(OPENCM3_DIR)/lib/lib$(OPENCM3_LIBNAME).a:
|
||||
@if [ ! -e libopencm3/.git ]; then \
|
||||
git submodule init; \
|
||||
git submodule update; \
|
||||
fi
|
||||
@$(MAKE) -C $(OPENCM3_DIR)
|
||||
|
||||
$(BUILD)/tbm: $(OPENCM3_DIR)/lib/lib$(OPENCM3_LIBNAME).a
|
||||
|
||||
$(BUILD)/tbm.bin: $(BUILD)/tbm
|
||||
$(PREFIX)objcopy -Obinary $< $@
|
||||
|
||||
$(BUILD)/tbm.hex: $(BUILD)/tbm
|
||||
$(PREFIX)objcopy -Oihex $< $@
|
||||
|
||||
run: $(BUILD)/tbm
|
||||
@echo "GDB $<"
|
||||
@$(GDB) --batch \
|
||||
-ex 'target extended-remote $(STLINK_PORT)' \
|
||||
-x flash.scr \
|
||||
$<
|
||||
|
||||
flash: $(BUILD)/tbm.bin
|
||||
stm32flash -g 0x8000000 -w $< $(STM32_PORT)
|
||||
|
||||
.PHONY: run
|
5
source/platform/stm32f1/Makefile
Normal file
5
source/platform/stm32f1/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
obj-y += source/platform/stm32f1/gpio.o
|
||||
obj-y += source/platform/stm32f1/rcc.o
|
||||
obj-y += source/platform/stm32f1/rtc.o
|
||||
obj-y += source/platform/stm32f1/spi.o
|
||||
obj-y += source/platform/stm32f1/usart.o
|
41
source/platform/stm32f1/gpio.c
Normal file
41
source/platform/stm32f1/gpio.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include <libopencm3/stm32/gpio.h>
|
||||
|
||||
#include <gpio.h>
|
||||
|
||||
int gpio_init(void)
|
||||
{
|
||||
/* Set up GPIOs for SPI 1 */
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, GPIO_SPI1_NSS);
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_SPI1_SCK |
|
||||
GPIO_SPI1_MOSI);
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
|
||||
GPIO_SPI1_MISO);
|
||||
/*gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4);
|
||||
gpio_set(GPIOA, GPIO4);
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO5 | GPIO6 | GPIO7);
|
||||
gpio_set_af(GPIOA, GPIO_AF0, GPIO5 | GPIO6 | GPIO7);*/
|
||||
|
||||
/* Set up GPIOs for user console (USART 1) */
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
|
||||
GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX);
|
||||
/*gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO10);
|
||||
gpio_set_af(GPIOA, GPIO_AF1, GPIO9 | GPIO10);*/
|
||||
|
||||
/* Set up GPIOs for admin console (USART 2) */
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
|
||||
GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);
|
||||
/*gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2 | GPIO3);
|
||||
gpio_set_af(GPIOA, GPIO_AF1, GPIO2 | GPIO3);*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpio_cleanup(void)
|
||||
{
|
||||
}
|
19
source/platform/stm32f1/rcc.c
Normal file
19
source/platform/stm32f1/rcc.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include <libopencm3/stm32/rcc.h>
|
||||
|
||||
#include <rcc.h>
|
||||
|
||||
int rcc_init(void)
|
||||
{
|
||||
rcc_periph_clock_enable(RCC_AFIO);
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
rcc_periph_clock_enable(RCC_GPIOB);
|
||||
rcc_periph_clock_enable(RCC_SPI1);
|
||||
rcc_periph_clock_enable(RCC_USART1);
|
||||
rcc_periph_clock_enable(RCC_USART2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rcc_cleanup(void)
|
||||
{
|
||||
}
|
42
source/platform/stm32f1/rtc.c
Normal file
42
source/platform/stm32f1/rtc.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include <libopencm3/stm32/pwr.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/rtc.h>
|
||||
|
||||
#include <macros.h>
|
||||
#include <rtc.h>
|
||||
|
||||
int rtc_get_time(struct tm *time)
|
||||
{
|
||||
time_t unix_time;
|
||||
|
||||
if (!time)
|
||||
return -1;
|
||||
|
||||
unix_time = rtc_get_counter_val();
|
||||
|
||||
if (!gmtime_r(&unix_time, time))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtc_set_time(struct tm *time)
|
||||
{
|
||||
time_t unix_time;
|
||||
|
||||
if (!time)
|
||||
return -1;
|
||||
|
||||
unix_time = mktime(time);
|
||||
rtc_set_counter_val((uint32_t)unix_time);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_init(struct tm *time)
|
||||
{
|
||||
rtc_auto_awake(RCC_LSI, 0x7fff);
|
||||
rtc_set_time(time);
|
||||
|
||||
return 0;
|
||||
}
|
78
source/platform/stm32f1/spi.c
Normal file
78
source/platform/stm32f1/spi.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/spi.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
|
||||
#include <spi.h>
|
||||
|
||||
static int stm32f1_spi_tx_rx(struct spi_dev *dev, void *rx_buf, size_t rx_len,
|
||||
const void *tx_buf, size_t tx_len);
|
||||
|
||||
static struct spi_ops stm32f1_spi_ops = {
|
||||
.tx_rx = stm32f1_spi_tx_rx,
|
||||
};
|
||||
|
||||
static void stm32f1_spi_init(void)
|
||||
{
|
||||
spi_reset(SPI1);
|
||||
spi_init_master(SPI1,
|
||||
SPI_CR1_BAUDRATE_FPCLK_DIV_64,
|
||||
SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
|
||||
SPI_CR1_CPHA_CLK_TRANSITION_2,
|
||||
SPI_CR1_DFF_8BIT,
|
||||
SPI_CR1_MSBFIRST);
|
||||
spi_enable_software_slave_management(SPI1);
|
||||
spi_set_nss_high(SPI1);
|
||||
spi_enable(SPI1);
|
||||
|
||||
gpio_set(GPIOA, GPIO_SPI1_NSS);
|
||||
}
|
||||
|
||||
struct spi_dev *spi_probe(void)
|
||||
{
|
||||
struct spi_dev *dev;
|
||||
|
||||
if (!(dev = malloc(sizeof *dev)))
|
||||
return NULL;
|
||||
|
||||
dev->ops = &stm32f1_spi_ops;
|
||||
dev->dev_id = SPI1;
|
||||
|
||||
stm32f1_spi_init();
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void spi_release(struct spi_dev *dev)
|
||||
{
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static int stm32f1_spi_tx_rx(struct spi_dev *dev, void *rx_buf, size_t rx_len,
|
||||
const void *tx_buf, size_t tx_len)
|
||||
{
|
||||
char *rx = rx_buf;
|
||||
const char *tx = tx_buf;
|
||||
size_t i;
|
||||
|
||||
gpio_clear(GPIOA, GPIO_SPI1_NSS);
|
||||
|
||||
for (i = 0; i < tx_len; ++i) {
|
||||
spi_send(dev->dev_id, *tx++);
|
||||
(void)spi_read(dev->dev_id);
|
||||
}
|
||||
|
||||
if (rx_buf) {
|
||||
for (i = 0; i < rx_len; ++i) {
|
||||
spi_send(dev->dev_id, 0);
|
||||
*rx++ = spi_read(dev->dev_id);
|
||||
}
|
||||
}
|
||||
|
||||
gpio_set(GPIOA, GPIO_SPI1_NSS);
|
||||
|
||||
return 0;
|
||||
}
|
321
source/platform/stm32f1/usart.c
Normal file
321
source/platform/stm32f1/usart.c
Normal file
|
@ -0,0 +1,321 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/cm3/scb.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <console.h>
|
||||
#include <macros.h>
|
||||
|
||||
#define RECV_BUF_LEN 128
|
||||
|
||||
struct usart_console {
|
||||
struct console console;
|
||||
char recv_buf[RECV_BUF_LEN];
|
||||
volatile size_t cur;
|
||||
volatile size_t next;
|
||||
unsigned irq_no;
|
||||
uint32_t dev;
|
||||
};
|
||||
|
||||
static struct usart_console usart[2];
|
||||
|
||||
static void usart_isr(struct usart_console *console)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!console)
|
||||
return;
|
||||
|
||||
while (usart_get_flag(console->dev, USART_SR_RXNE)) {
|
||||
console->recv_buf[console->next] = usart_recv(console->dev);
|
||||
|
||||
if (console->recv_buf[console->next] == '\003')
|
||||
scb_reset_system();
|
||||
|
||||
i = (console->next + 1) % RECV_BUF_LEN;
|
||||
|
||||
if (i != console->cur)
|
||||
console->next = i;
|
||||
}
|
||||
}
|
||||
|
||||
void usart1_isr(void)
|
||||
{
|
||||
usart_isr(usart + 0);
|
||||
}
|
||||
|
||||
void usart2_isr(void)
|
||||
{
|
||||
usart_isr(usart + 1);
|
||||
}
|
||||
|
||||
static char usart_getc(struct usart_console *console, int block)
|
||||
{
|
||||
char c = 0;
|
||||
|
||||
while (block && (console->cur == console->next));
|
||||
|
||||
if (console->cur != console->next) {
|
||||
c = console->recv_buf[console->cur];
|
||||
console->cur = (console->cur + 1) % RECV_BUF_LEN;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int console_peek(char *c, struct console *console_, int block)
|
||||
{
|
||||
struct usart_console *console = container_of(console_,
|
||||
struct usart_console, console);
|
||||
|
||||
while (block && console->cur == console->next);
|
||||
|
||||
if (console->cur != console->next) {
|
||||
*c = console->recv_buf[console->cur];
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
int console_getc(char *c, struct console *console_)
|
||||
{
|
||||
struct usart_console *console = container_of(console_,
|
||||
struct usart_console, console);
|
||||
|
||||
if (console->cur == console->next)
|
||||
return -1;
|
||||
|
||||
if (console->cur != console->next) {
|
||||
*c = console->recv_buf[console->cur];
|
||||
console->cur = (console->cur + 1) % RECV_BUF_LEN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int console_getline(struct console *console_, char *buf, size_t n)
|
||||
{
|
||||
struct usart_console *console = container_of(console_,
|
||||
struct usart_console, console);
|
||||
char *p = buf + strlen(buf);
|
||||
char c;
|
||||
|
||||
*p = '\0';
|
||||
|
||||
while (console_getc(&c, console_) == 0) {
|
||||
switch (c) {
|
||||
case '\r':
|
||||
usart_send_blocking(console->dev, '\r');
|
||||
usart_send_blocking(console->dev, '\n');
|
||||
return 0;
|
||||
case 10:
|
||||
case 127:
|
||||
if (buf < p) {
|
||||
usart_send_blocking(console->dev, '\010');
|
||||
usart_send_blocking(console->dev, ' ');
|
||||
usart_send_blocking(console->dev, '\010');
|
||||
--p;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
*p = c;
|
||||
usart_send_blocking(console->dev, c);
|
||||
|
||||
if (((size_t)p - (size_t)buf) < n) {
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ssize_t console_read(struct console *console_, char *buf, size_t n)
|
||||
{
|
||||
struct usart_console *console = container_of(console_,
|
||||
struct usart_console, console);
|
||||
char *p = buf;
|
||||
char c;
|
||||
|
||||
*buf = '\0';
|
||||
|
||||
while (console_peek(&c, console_, 1) == 0) {
|
||||
switch (c) {
|
||||
case '\004':
|
||||
if (buf < p)
|
||||
goto out;
|
||||
|
||||
console_getc(&c, console_);
|
||||
return 0;
|
||||
case 10:
|
||||
case 127:
|
||||
if (buf < p) {
|
||||
usart_send_blocking(console->dev, '\010');
|
||||
usart_send_blocking(console->dev, ' ');
|
||||
usart_send_blocking(console->dev, '\010');
|
||||
--p;
|
||||
}
|
||||
|
||||
console_getc(&c, console_);
|
||||
|
||||
break;
|
||||
case '\r':
|
||||
if (((size_t)p - (size_t)buf) >= n)
|
||||
goto out;
|
||||
|
||||
*p++ = '\n';
|
||||
usart_send_blocking(console->dev, '\r');
|
||||
console_getc(&c, console_);
|
||||
goto out;
|
||||
default:
|
||||
if (((size_t)p - (size_t)buf) >= n)
|
||||
goto out;
|
||||
|
||||
*p++ = c;
|
||||
usart_send_blocking(console->dev, c);
|
||||
console_getc(&c, console_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
*p = '\0';
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
static ssize_t usart_read(void *cookie, char *buf, size_t n)
|
||||
{
|
||||
struct usart_console *console = cookie;
|
||||
char *p = buf;
|
||||
char c;
|
||||
|
||||
*buf = '\0';
|
||||
|
||||
while ((c = usart_getc(console, 1)) != '\r') {
|
||||
switch (c) {
|
||||
case 10:
|
||||
case 127:
|
||||
if (buf < p) {
|
||||
usart_send_blocking(console->dev, '\010');
|
||||
usart_send_blocking(console->dev, ' ');
|
||||
usart_send_blocking(console->dev, '\010');
|
||||
--p;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
*p = c;
|
||||
usart_send_blocking(console->dev, c);
|
||||
|
||||
if (((size_t)p - (size_t)buf) < n) {
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
*p = '\n';
|
||||
|
||||
if (((size_t)p - (size_t)buf) < n) {
|
||||
++p;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
static ssize_t usart_write(void *cookie, const char *buf, size_t n)
|
||||
{
|
||||
struct usart_console *console = cookie;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (buf[i] == '\n')
|
||||
usart_send_blocking(console->dev, '\r');
|
||||
|
||||
usart_send_blocking(console->dev, buf[i]);
|
||||
};
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int usart_get_irq_no(unsigned *irq_no, unsigned dev)
|
||||
{
|
||||
if (!irq_no)
|
||||
return -1;
|
||||
|
||||
switch (dev) {
|
||||
case USART1: *irq_no = NVIC_USART1_IRQ; break;
|
||||
case USART2: *irq_no = NVIC_USART2_IRQ; break;
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usart_init(struct usart_console *console)
|
||||
{
|
||||
if (usart_get_irq_no(&console->irq_no, console->dev) < 0)
|
||||
return -1;
|
||||
|
||||
usart_set_baudrate(console->dev, 115200);
|
||||
usart_set_databits(console->dev, 8);
|
||||
usart_set_parity(console->dev, USART_PARITY_NONE);
|
||||
usart_set_stopbits(console->dev, USART_STOPBITS_1);
|
||||
usart_set_mode(console->dev, USART_MODE_TX_RX);
|
||||
usart_set_flow_control(console->dev, USART_FLOWCONTROL_NONE);
|
||||
|
||||
nvic_enable_irq(console->irq_no);
|
||||
usart_enable(console->dev);
|
||||
usart_enable_rx_interrupt(console->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct console *console_init(unsigned dev_id)
|
||||
{
|
||||
cookie_io_functions_t fops = {
|
||||
.read = usart_read,
|
||||
.write = usart_write,
|
||||
.seek = NULL,
|
||||
.close = NULL,
|
||||
};
|
||||
struct usart_console *console;
|
||||
|
||||
console = usart + dev_id;
|
||||
|
||||
switch (dev_id) {
|
||||
case 0: console->dev = USART1; break;
|
||||
case 1: console->dev = USART2; break;
|
||||
default: return NULL;
|
||||
}
|
||||
|
||||
console->cur = 0;
|
||||
console->next = 0;
|
||||
|
||||
usart_init(console);
|
||||
|
||||
console->console.fp = fopencookie(console, "r+w", fops);
|
||||
setvbuf(console->console.fp, NULL, _IONBF, 0);
|
||||
|
||||
return &console->console;
|
||||
}
|
106
support/libopencm3_stm32f1.ld
Normal file
106
support/libopencm3_stm32f1.ld
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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
|
||||
{
|
||||
.text : {
|
||||
*(.vectors) /* Vector table */
|
||||
*(.text*) /* Program code */
|
||||
. = ALIGN(4);
|
||||
*(.rodata*) /* Read-only data */
|
||||
. = ALIGN(4);
|
||||
} >rom
|
||||
|
||||
/* 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
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
|
||||
.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
|
||||
|
||||
/*
|
||||
* 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) }
|
||||
|
||||
. = ALIGN(4);
|
||||
end = .;
|
||||
}
|
||||
|
||||
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
|
||||
|
31
support/stm32vl-discovery.ld
Normal file
31
support/stm32vl-discovery.ld
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Linker script for ST STM32VLDISCOVERY (STM32F100RB, 128K flash, 8K RAM). */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
Loading…
Add table
Reference in a new issue