diff options
-rw-r--r-- | rules.mk | 169 | ||||
-rw-r--r-- | shared/trace.c | 54 | ||||
-rw-r--r-- | shared/trace.h | 30 | ||||
-rw-r--r-- | shared/trace_stdio.c | 34 | ||||
-rw-r--r-- | tests/adc-power/Makefile.stm32f4-disco | 44 | ||||
-rw-r--r-- | tests/adc-power/adc-power.c | 94 | ||||
-rw-r--r-- | tests/adc-power/adc-power.h | 25 | ||||
-rw-r--r-- | tests/adc-power/main-stm32f4-disco.c | 52 |
8 files changed, 502 insertions, 0 deletions
diff --git a/rules.mk b/rules.mk new file mode 100644 index 0000000..e10dd79 --- /dev/null +++ b/rules.mk @@ -0,0 +1,169 @@ +## +## This file is part of the libopencm3 project. +## +## 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/>. +## + +# This version of rules.mk expects the following to be defined before +# inclusion.. +### REQUIRED ### +# OPENCM3_DIR - duh +# OPENCM3_LIB - the basename, eg: opencm3_stm32f4 +# OPENCM3_DEFS - the target define eg: -DSTM32F4 +# ARCH_FLAGS - eg, -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 +# (ie, the full set of cpu arch flags, _none_ are defined in this file) +# PROJECT - will be the basename of the output elf, eg usb-gadget0-stm32f4disco +# CFILES - basenames only, eg main.c blah.c +# LDSCRIPT - full path, eg ../../examples/stm32/f4/stm32f4-discovery/stm32f4-discovery.ld +# +### OPTIONAL ### +# INCLUDES - fully formed -I paths, if you want extra, eg -I../shared +# BUILD_DIR - defaults to bin, should set this if you are building multiarch +# OPT - full -O flag, defaults to -Os +# CSTD - defaults -std=c99 +# CXXSTD - no default. +# OOCD_INTERFACE - eg stlink-v2 +# OOCD_TARGET - eg stm32f4x +# both only used if you use the "make flash" target. +# OOCD_FILE - eg my.openocd.cfg +# This overrides interface/target above, and is used as just -f FILE +### TODO/FIXME/notes ### +# No support for stylecheck. +# No support for BMP/texane/random flash methods, no plans either +# No support for magically finding the library. +# C++ hasn't been actually tested with this..... sorry bout that. ;) +# Second expansion/secondary not set, add this if you need them. + +BUILD_DIR ?= bin +OPT ?= -Os +CSTD ?= -std=c99 + +# Be silent per default, but 'make V=1' will show all compiler calls. +# If you're insane, V=99 will print out all sorts of things. +V?=0 +ifeq ($(V),0) +Q := @ +NULL := 2>/dev/null +endif + +# Tool paths. +PREFIX ?= arm-none-eabi- +CC = $(PREFIX)gcc +LD = $(PREFIX)gcc +OBJCOPY = $(PREFIX)objcopy +OBJDUMP = $(PREFIX)objdump +OOCD ?= openocd + +OPENCM3_INC = $(OPENCM3_DIR)/include + +# Inclusion of library header files +INCLUDES += $(patsubst %,-I%, . $(OPENCM3_INC) ) + +OBJS = $(CFILES:%.c=$(BUILD_DIR)/%.o) + +TGT_CPPFLAGS += -MD +TGT_CPPFLAGS += -Wall -Wundef $(INCLUDES) +TGT_CPPFLAGS += $(INCLUDES) $(OPENCM3_DEFS) + +TGT_CFLAGS += $(OPT) $(CSTD) -ggdb3 +TGT_CFLAGS += $(ARCH_FLAGS) +TGT_CFLAGS += -fno-common +TGT_CFLAGS += -ffunction-sections -fdata-sections +TGT_CFLAGS += -Wextra -Wshadow -Wno-unused-variable -Wimplicit-function-declaration +TGT_CFLAGS += -Wredundant-decls -Wstrict-prototypes -Wmissing-prototypes + +TGT_CXXFLAGS += $(OPT) $(CXXSTD) -ggdb3 +TGT_CXXFLAGS += $(ARCH_FLAGS) +TGT_CXXFLAGS += -fno-common +TGT_CXXFLAGS += -ffunction-sections -fdata-sections +TGT_CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++ + +TGT_LDFLAGS += -T$(LDSCRIPT) -L$(OPENCM3_DIR)/lib -nostartfiles +TGT_LDFLAGS += $(ARCH_FLAGS) +TGT_LDFLAGS += -specs=nano.specs +TGT_LDFLAGS += -Wl,--gc-sections +# OPTIONAL +#TGT_LDFLAGS += -Wl,-Map=$(PROJECT).map +ifeq ($(V),99) +TGT_LDFLAGS += -Wl,--print-gc-sections +endif + +LDLIBS += -l$(OPENCM3_LIB) +# nosys is only in newer gcc-arm-embedded... +LDLIBS += -specs=nosys.specs +#LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group + +# Burn in legacy hell fortran modula pascal yacc idontevenwat +.SUFFIXES: +.SUFFIXES: .c .h .o .cxx .elf .bin .list .lss + +# Bad make, never *ever* try to get a file out of source control by yourself. +%: %,v +%: RCS/%,v +%: RCS/% +%: s.% +%: SCCS/s.% + +all: $(PROJECT).elf $(PROJECT).bin +flash: $(PROJECT).flash + +$(LDSCRIPT): +ifeq (,$(wildcard $(LDSCRIPT))) + $(error Unable to find specified linker script: $(LDSCRIPT)) +endif + +# Need a special rule to have a bin dir +$(BUILD_DIR)/%.o: %.c + @printf " CC\t$<\n" + @mkdir -p $(dir $@) + $(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $@ -c $< + +$(BUILD_DIR)/%.o: %.cxx + @printf " CXX\t$<\n" + @mkdir -p $(dir $@) + $(Q)$(CC) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $@ -c $< + +$(PROJECT).elf: $(OBJS) $(LDSCRIPT) + @printf " LD\t$@\n" + $(Q)$(LD) $(TGT_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@ + +%.bin: %.elf + @printf " OBJCOPY\t$@\n" + $(Q)$(OBJCOPY) -O binary $< $@ + +%.lss: %.elf + $(OBJDUMP) -h -S $< > $@ + +%.list: %.elf + $(OBJDUMP) -S $< > $@ + +%.flash: %.elf + @printf " FLASH\t$<\n" +ifeq (,$(OOCD_FILE)) + $(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \ + -f target/$(OOCD_TARGET).cfg \ + -c "program $(*).elf verify reset exit" \ + $(NULL) +else + $(Q)$(OOCD) -f $(OOCD_FILE) \ + -c "program $(*).elf verify reset exit" \ + $(NULL) +endif + +clean: + rm -rf $(BUILD_DIR) $(PROJECT).{elf,bin} $(PROJECT).{list,lss,map} + +.PHONY: all clean flash +-include $(OBJS:.o=.d) + diff --git a/shared/trace.c b/shared/trace.c new file mode 100644 index 0000000..9e05d9a --- /dev/null +++ b/shared/trace.c @@ -0,0 +1,54 @@ +#include <stdint.h> +#include <libopencm3/cm3/common.h> +#include <libopencm3/cm3/memorymap.h> +#include <libopencm3/cm3/itm.h> +#include "trace.h" + +void trace_send_blocking8(int stimulus_port, char c) { + if (!(ITM_TER[0] & (1<<stimulus_port))) { + return; + } + while (!(ITM_STIM8(stimulus_port) & ITM_STIM_FIFOREADY)) + ; + ITM_STIM8(stimulus_port) = c; +} + +void trace_send8(int stimulus_port, char val) { + if (!(ITM_TER[0] & (1<<stimulus_port))) { + return; + } + ITM_STIM8(stimulus_port) = val; +} + +void trace_send_blocking16(int stimulus_port, uint16_t val) { + if (!(ITM_TER[0] & (1<<stimulus_port))) { + return; + } + while (!(ITM_STIM16(stimulus_port) & ITM_STIM_FIFOREADY)) + ; + ITM_STIM16(stimulus_port) = val; +} + +void trace_send16(int stimulus_port, uint16_t val) { + if (!(ITM_TER[0] & (1<<stimulus_port))) { + return; + } + ITM_STIM16(stimulus_port) = val; +} + + +void trace_send_blocking32(int stimulus_port, uint32_t val) { + if (!(ITM_TER[0] & (1<<stimulus_port))) { + return; + } + while (!(ITM_STIM32(stimulus_port) & ITM_STIM_FIFOREADY)) + ; + ITM_STIM32(stimulus_port) = val; +} + +void trace_send32(int stimulus_port, uint32_t val) { + if (!(ITM_TER[0] & (1<<stimulus_port))) { + return; + } + ITM_STIM32(stimulus_port) = val; +} diff --git a/shared/trace.h b/shared/trace.h new file mode 100644 index 0000000..b18cc11 --- /dev/null +++ b/shared/trace.h @@ -0,0 +1,30 @@ +/* + * trace support + * Karl Palsson <karlp@tweak.net.au> + */ + +#ifndef TRACE_H +#define TRACE_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +void trace_send_blocking8(int stimulus_port, char c); +void trace_send8(int stimulus_port, char c); + +void trace_send_blocking16(int stimulus_port, uint16_t val); +void trace_send16(int stimulus_port, uint16_t val); + +void trace_send_blocking32(int stimulus_port, uint32_t val); +void trace_send32(int stimulus_port, uint32_t val); + + +#ifdef __cplusplus +} +#endif + +#endif /* TRACE_H */ + diff --git a/shared/trace_stdio.c b/shared/trace_stdio.c new file mode 100644 index 0000000..2710942 --- /dev/null +++ b/shared/trace_stdio.c @@ -0,0 +1,34 @@ +/* + * support for stdio output to a trace port + * Karl Palsson, 2014 <karlp@remake.is> + */ + +#include <errno.h> +#include <stdio.h> +#include <unistd.h> + +#include "trace.h" + +#ifndef STIMULUS_STDIO +#define STIMULUS_STDIO 0 +#endif + +int _write(int file, char *ptr, int len); +int _write(int file, char *ptr, int len) +{ + int i; + + if (file == STDOUT_FILENO || file == STDERR_FILENO) { + for (i = 0; i < len; i++) { + if (ptr[i] == '\n') { + trace_send_blocking8(STIMULUS_STDIO, '\r'); + } + trace_send_blocking8(STIMULUS_STDIO, ptr[i]); + } + return i; + } + errno = EIO; + return -1; +} + + diff --git a/tests/adc-power/Makefile.stm32f4-disco b/tests/adc-power/Makefile.stm32f4-disco new file mode 100644 index 0000000..b592384 --- /dev/null +++ b/tests/adc-power/Makefile.stm32f4-disco @@ -0,0 +1,44 @@ +## +## This file is part of the libopencm3 project. +## +## 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/>. +## + +BOARD = stm32f4-disco +PROJECT = adc-power-$(BOARD) +BUILD_DIR = bin-$(BOARD) + +SHARED_DIR = ../../shared + +CFILES = main-$(BOARD).c +CFILES += adc-power.c +CFILES += trace.c trace_stdio.c + +VPATH += $(SHARED_DIR) + +INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR)) + +OPENCM3_DIR=../../libopencm3/ + +### This section can go to an arch shared rules eventually... +LDSCRIPT = ../../../libopencm3/lib/stm32/f4/stm32f405x6.ld +OPENCM3_LIB = opencm3_stm32f4 +OPENCM3_DEFS = -DSTM32F4 +FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 +ARCH_FLAGS = -mthumb -mcpu=cortex-m4 $(FP_FLAGS) +#OOCD_INTERFACE = stlink-v2 +#OOCD_TARGET = stm32f4x +OOCD_FILE = ../../openocd/openocd.stm32f4-disco.cfg + +include ../../rules.mk diff --git a/tests/adc-power/adc-power.c b/tests/adc-power/adc-power.c new file mode 100644 index 0000000..817671c --- /dev/null +++ b/tests/adc-power/adc-power.c @@ -0,0 +1,94 @@ +/** + * Testing ADC power up and power down, for timing and actual on/off + * Uses TIM6, because DWT_CYCCNT not available on cm0(+) :( + * (And with no DWT, no ITM timestamping either, get a real mcu!) + */ + +#include <stdio.h> +#include <stdint.h> +#include <libopencm3/stm32/adc.h> +#include <libopencm3/stm32/rcc.h> +#include <libopencm3/stm32/timer.h> + +#include "adc-power.h" + +/* Everyone has tim6 right? */ +#define TIMER TIM6 +#define TIMER_RCC RCC_TIM6 + +// TODO - stick this in libopencm3? +#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) + + +void adc_power_init(void) +{ + /* Some basic ADC config, that we won't touch again */ + rcc_periph_clock_enable(RCC_ADC1); + adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28CYC); +#if 0 + // DANGER DANGER! doing this without DMA is dum. + // but... we're busy polling, we should be right... right? + // (dma across platforms is teh suck) + adc_enable_scan_mode(ADC1); + ADC_CR2 |= ADC_CR2_EOCS; // FIXME +#else + adc_disable_scan_mode(ADC1); +#endif + + /* + * We're going to setup a timer to run at top speed, so... "fast" + * but we don't actually care about the rate itself. We just + * want to collect how many ticks it takes to enable and disable + * the adc. + */ + rcc_periph_clock_enable(TIMER_RCC); + timer_reset(TIMER); + timer_set_prescaler(TIMER, 0); + timer_enable_counter(TIMER); +} + +static uint16_t read_adc_naiive(uint8_t channel) +{ + uint8_t channel_array[16]; + channel_array[0] = channel; + adc_set_regular_sequence(ADC1, 1, channel_array); + adc_start_conversion_regular(ADC1); + while (!adc_eoc(ADC1)); + return adc_read_regular(ADC1); +} + +void adc_power_task_up(void) { + TIM_CNT(TIMER) = 0; + adc_power_on(ADC1); + unsigned int td = TIM_CNT(TIMER); + + /* just for kicks, let's time some sequences too.... + * I mean, we're going to do some conversions right? */ + adc_set_single_conversion_mode(ADC1); +#if 0 + uint8_t channels[2] = { 0, 1 }; + adc_set_regular_sequence(ADC1, ARRAY_SIZE(channels), channels); + TIM_CNT(TIMER) = 0; + adc_start_conversion_regular(ADC1); + while (!adc_eoc(ADC1)); + unsigned int v1 = adc_read_regular(ADC1); + while (!adc_eoc(ADC1)); + unsigned int v2 = adc_read_regular(ADC1); + unsigned int tconv = TIM_CNT(TIMER); +#else + TIM_CNT(TIMER) = 0; + unsigned int v1 = read_adc_naiive(0); + unsigned int v2 = read_adc_naiive(1); + unsigned int tconv = TIM_CNT(TIMER); +#endif + + printf("ton: %u, tconv: %u, v1: %u, v2: %u\n", td, tconv, v1, v2); +} + +void adc_power_task_down() +{ + TIM_CNT(TIMER) = 0; + adc_power_off(ADC1); + unsigned int td = TIM_CNT(TIMER); + printf("toff in: %u\n", td); +}
\ No newline at end of file diff --git a/tests/adc-power/adc-power.h b/tests/adc-power/adc-power.h new file mode 100644 index 0000000..2775d1a --- /dev/null +++ b/tests/adc-power/adc-power.h @@ -0,0 +1,25 @@ +/* + * File: adc-power.h + * Author: karlp + * + * Created on October 17, 2015, 12:19 AM + */ + +#ifndef ADC_POWER_H +#define ADC_POWER_H + +#ifdef __cplusplus +extern "C" { +#endif + + void adc_power_init(void); + void adc_power_task_up(void); + void adc_power_task_down(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* ADC_POWER_H */ + diff --git a/tests/adc-power/main-stm32f4-disco.c b/tests/adc-power/main-stm32f4-disco.c new file mode 100644 index 0000000..f02e610 --- /dev/null +++ b/tests/adc-power/main-stm32f4-disco.c @@ -0,0 +1,52 @@ +/* + * Oct 2015 Karl Palsson <karlp@tweak.net.au> + */ + +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <libopencm3/cm3/nvic.h> +#include <libopencm3/stm32/adc.h> +#include <libopencm3/stm32/dac.h> +#include <libopencm3/stm32/gpio.h> +#include <libopencm3/stm32/rcc.h> +#include <libopencm3/stm32/usart.h> + +#include "trace.h" +#include "adc-power.h" + +#define LED_DISCO_GREEN_PORT GPIOD +#define LED_DISCO_GREEN_PIN GPIO12 + +int main(void) +{ + int i; + int j = 0; + rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); + rcc_periph_clock_enable(RCC_GPIOD); + printf("hi guys!\n"); + /* green led for ticking */ + gpio_mode_setup(LED_DISCO_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, + LED_DISCO_GREEN_PIN); + + rcc_periph_clock_enable(RCC_GPIOA); + gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO0); + gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1); + + adc_power_init(); + while (1) { + adc_power_task_up(); + gpio_toggle(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN); + + for (i = 0; i < 0x1000000; i++) { /* Wait a bit. */ + __asm__("NOP"); + } + adc_power_task_down(); + gpio_toggle(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN); + for (i = 0; i < 0x1000000; i++) { /* Wait a bit. */ + __asm__("NOP"); + } + } + + return 0; +} |