parent
dc6365c7f8
commit
ebd770b957
@ -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 |
@ -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
|
@ -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) |
||||||
|
{ |
||||||
|
} |
@ -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) |
||||||
|
{ |
||||||
|
} |
@ -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; |
||||||
|
} |
@ -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; |
||||||
|
} |
@ -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; |
||||||
|
} |
@ -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)); |
||||||
|
|
@ -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…
Reference in new issue