aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2010-08-31 17:39:46 -0400
committerbnewbold <bnewbold@robocracy.org>2010-08-31 17:39:46 -0400
commit02d7b08f0497096f21e41922e0efb54c4ef33bab (patch)
treea7e04293efcba70f37cffcd03c0fcc4c0be7858a
parentb2dd49c3141d8a21a4e7c7ef51dee7329f847c30 (diff)
parente03d58f4dab4176514924baa3a1ff430bf5819b8 (diff)
downloadlibrambutan-02d7b08f0497096f21e41922e0efb54c4ef33bab.tar.gz
librambutan-02d7b08f0497096f21e41922e0efb54c4ef33bab.zip
Merge maple-native changes into portable
This compiles for both maple and maple_native but is untested.
-rw-r--r--LICENSE7
-rw-r--r--Makefile44
-rw-r--r--examples/blinky.cpp28
-rw-r--r--examples/test-session.cpp29
-rw-r--r--libmaple/adc.c6
-rw-r--r--libmaple/adc.h37
-rw-r--r--libmaple/dac.c2
-rw-r--r--libmaple/exti.h8
-rw-r--r--libmaple/flash.c8
-rw-r--r--libmaple/fsmc.c2
-rw-r--r--libmaple/gpio.c18
-rw-r--r--libmaple/gpio.h14
-rw-r--r--libmaple/libmaple.h110
-rw-r--r--libmaple/nvic.c34
-rw-r--r--libmaple/nvic.h34
-rw-r--r--libmaple/rcc.c148
-rw-r--r--libmaple/rcc.h221
-rw-r--r--libmaple/ring_buffer.h57
-rw-r--r--libmaple/spi.c4
-rw-r--r--libmaple/spi.h1
-rw-r--r--libmaple/syscalls.c7
-rw-r--r--libmaple/systick.c18
-rw-r--r--libmaple/systick.h25
-rw-r--r--libmaple/timers.c55
-rw-r--r--libmaple/timers.h16
-rw-r--r--libmaple/usart.c316
-rw-r--r--libmaple/usart.h91
-rw-r--r--libmaple/usb/descriptors.h2
-rw-r--r--libmaple/usb/usb_config.h6
-rw-r--r--libmaple/usb/usb_hardware.h1
-rw-r--r--libmaple/util.c11
-rw-r--r--libmaple/util.h11
-rw-r--r--notes/pin-mapping.txt5
-rw-r--r--notes/portable.txt100
-rw-r--r--support/ld/flash.ld2
-rw-r--r--support/ld/jtag.ld2
-rw-r--r--support/ld/ram.ld2
-rw-r--r--support/make/build-targets.mk4
-rwxr-xr-xsupport/stm32loader.py435
-rw-r--r--wirish/HardwareTimer.cpp39
-rw-r--r--wirish/HardwareTimer.h14
-rw-r--r--wirish/boards.h219
-rw-r--r--wirish/comm/HardwareSerial.cpp89
-rw-r--r--wirish/comm/HardwareSerial.h18
-rw-r--r--wirish/ext_interrupts.c29
-rw-r--r--wirish/ext_interrupts.h8
-rw-r--r--wirish/io.h51
-rw-r--r--wirish/pwm.c4
-rw-r--r--wirish/time.c54
-rw-r--r--wirish/time.h50
-rw-r--r--wirish/wirish.c60
-rw-r--r--wirish/wirish.h12
-rw-r--r--wirish/wirish_analog.c5
-rw-r--r--wirish/wirish_digital.c68
54 files changed, 1703 insertions, 938 deletions
diff --git a/LICENSE b/LICENSE
index 00044f8..fcbfcc6 100644
--- a/LICENSE
+++ b/LICENSE
@@ -57,3 +57,10 @@ the new terms are clearly indicated on the first page of each file where
they apply.
-------------------------------------------------------------------------------
+The ./support/stm32loader.py python script is GPL (see
+http://www.gnu.org/licenses/ for a copy) and comes with the following info:
+
+ Author: Ivan A-R <ivan@tuxotronic.org>
+ Project page: http://tuxotronic.org/wiki/projects/stm32loader
+
+-------------------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index b1858c7..28cd4f3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,22 @@
.DEFAULT_GOAL := sketch
+# Valid BOARDs: maple, maple_native, ...
BOARD ?= maple
-MAPLE_TARGET ?= flash
+MEMORY_TARGET ?= flash
+
+# USB ID for DFU upload
+VENDOR_ID := 1EAF
+PRODUCT_ID := 0003
+
+# Guess the MCU based on the BOARD (can be overridden )
+ifeq ($(BOARD), maple)
+ MCU := STM32F103RB
+ PRODUCT_ID := 0003
+endif
+ifeq ($(BOARD), maple_native)
+ MCU := STM32F103ZE
+ PRODUCT_ID := 0003
+endif
# Useful paths
SRCROOT := $(dir)
@@ -10,8 +25,9 @@ LIBMAPLE_PATH := libmaple
# Useful variables
GLOBAL_CFLAGS := -Os -g -mcpu=cortex-m3 -mthumb -march=armv7-m -nostdlib \
- -ffunction-sections -fdata-sections -Wl,--gc-sections
-GLOBAL_CXXFLAGS := -fno-rtti -fno-exceptions -Wall
+ -ffunction-sections -fdata-sections -Wl,--gc-sections \
+ -DBOARD_$(BOARD) -DMCU_$(MCU)
+GLOBAL_CXXFLAGS := -fno-rtti -fno-exceptions -Wall -DBOARD_$(BOARD) -DMCU_$(MCU)
LDDIR := support/ld
@@ -23,20 +39,16 @@ LDFLAGS = -T$(LDDIR)/$(LDSCRIPT) -L$(LDDIR) \
include support/make/build-rules.mk
include support/make/build-templates.mk
-# Maple USB id
-VENDOR_ID := 1EAF
-PRODUCT_ID := 0003
-
# Some target specific things
-ifeq ($(MAPLE_TARGET), ram)
+ifeq ($(MEMORY_TARGET), ram)
VECT_BASE_ADDR := VECT_TAB_RAM
LDSCRIPT := ram.ld
endif
-ifeq ($(MAPLE_TARGET), flash)
+ifeq ($(MEMORY_TARGET), flash)
LDSCRIPT := flash.ld
VECT_BASE_ADDR := VECT_TAB_FLASH
endif
-ifeq ($(MAPLE_TARGET), jtag)
+ifeq ($(MEMORY_TARGET), jtag)
LDSCRIPT := jtag.ld
VECT_BASE_ADDR := VECT_TAB_BASE
endif
@@ -71,7 +83,7 @@ install: $(BUILD_PATH)/$(BOARD).bin
# Force a rebuild if the maple target changed
PREV_BUILD_TYPE = $(shell cat $(BUILD_PATH)/build-type 2>/dev/null)
build-check:
-ifneq ($(PREV_BUILD_TYPE), $(MAPLE_TARGET))
+ifneq ($(PREV_BUILD_TYPE), $(MEMORY_TARGET))
$(shell rm -rf $(BUILD_PATH))
endif
@@ -84,11 +96,11 @@ help:
@echo ""
@echo " libmaple Makefile help"
@echo " ----------------------"
- @echo " Compile targets (default MAPLE_TARGET=flash):"
+ @echo " Compile targets (default MEMORY_TARGET=flash):"
@echo " ram: Compile sketch code to ram"
@echo " flash: Compile sketch code to flash"
@echo " jtag: Compile sketch code to jtag"
- @echo " sketch: Compile sketch code to target MAPLE_TARGET"
+ @echo " sketch: Compile sketch code to target MEMORY_TARGET"
@echo " "
@echo " Programming targets:"
@echo " install: Upload code to target"
@@ -115,10 +127,10 @@ ctags:
@echo "Made tags file for VIM code browsing"
ram:
- @$(MAKE) MAPLE_TARGET=ram --no-print-directory sketch
+ @$(MAKE) MEMORY_TARGET=ram --no-print-directory sketch
flash:
- @$(MAKE) MAPLE_TARGET=flash --no-print-directory sketch
+ @$(MAKE) MEMORY_TARGET=flash --no-print-directory sketch
jtag:
- @$(MAKE) MAPLE_TARGET=jtag --no-print-directory sketch
+ @$(MAKE) MEMORY_TARGET=jtag --no-print-directory sketch
diff --git a/examples/blinky.cpp b/examples/blinky.cpp
index b037a1f..45c4528 100644
--- a/examples/blinky.cpp
+++ b/examples/blinky.cpp
@@ -1,30 +1,4 @@
-/* *****************************************************************************
- * The MIT License
- *
- * Copyright (c) 2010 LeafLabs LLC.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- * ****************************************************************************/
-
-/**
- * @brief blinky.cpp. Blinks the LED, pin 13
- */
+// Blinks the LED, pin 13
#include "wirish.h"
diff --git a/examples/test-session.cpp b/examples/test-session.cpp
index 9885ab3..cfb81d0 100644
--- a/examples/test-session.cpp
+++ b/examples/test-session.cpp
@@ -1,26 +1,9 @@
-/* *****************************************************************************
- * The MIT License
- *
- * Copyright (c) 2010 LeafLabs LLC.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- * ****************************************************************************/
+// Interactive Test Session for LeafLabs Maple
+// Copyright (c) 2010 LeafLabs LLC.
+//
+// Useful for testing Maple features and troubleshooting. Select a COMM port
+// (SerialUSB or Serial2) before compiling and then enter 'h' at the prompt
+// for a list of commands.
#include "wirish.h"
diff --git a/libmaple/adc.c b/libmaple/adc.c
index 317a5ff..021758c 100644
--- a/libmaple/adc.c
+++ b/libmaple/adc.c
@@ -63,9 +63,9 @@
* At 55.5 cycles/sample, the external input impedance < 50kOhms*/
void adc_init(void) {
- rcc_set_adc_prescaler(PCLK2_DIV_2);
- rcc_enable_clk_adc1();
- rcc_reset_adc1();
+ rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_6);
+ rcc_clk_enable(RCC_ADC1);
+ rcc_reset_dev(RCC_ADC1);
ADC_CR1 = 0;
ADC_CR2 = CR2_EXTSEL_SWSTART | CR2_EXTTRIG; // Software triggers conversions
diff --git a/libmaple/adc.h b/libmaple/adc.h
index 11aa5f6..f98a5f2 100644
--- a/libmaple/adc.h
+++ b/libmaple/adc.h
@@ -43,29 +43,32 @@ extern "C"{
*
* Need to up the sample time if otherwise... see datasheet */
-/* We'll only use ADC1 for now... */
-#define ADC_BASE 0x40012400
-#define ADC_SR *(volatile uint32*)(ADC_BASE + 0)
-#define ADC_CR1 *(volatile uint32*)(ADC_BASE + 0x4)
-#define ADC_CR2 *(volatile uint32*)(ADC_BASE + 0x8)
-#define ADC_SMPR1 *(volatile uint32*)(ADC_BASE + 0xC)
-#define ADC_SMPR2 *(volatile uint32*)(ADC_BASE + 0x10)
-#define ADC_SQR1 *(volatile uint32*)(ADC_BASE + 0x2C)
-#define ADC_SQR3 *(volatile uint32*)(ADC_BASE + 0x34)
-#define ADC_DR *(volatile uint32*)(ADC_BASE + 0x4C)
+/* TODO: We'll only use ADC1 for now... */
+#define ADC1_BASE 0x40012400
+#define ADC2_BASE 0x40012400
+#define ADC3_BASE 0x40012400
+
+#define ADC_SR *(volatile uint32*)(ADC1_BASE + 0)
+#define ADC_CR1 *(volatile uint32*)(ADC1_BASE + 0x4)
+#define ADC_CR2 *(volatile uint32*)(ADC1_BASE + 0x8)
+#define ADC_SMPR1 *(volatile uint32*)(ADC1_BASE + 0xC)
+#define ADC_SMPR2 *(volatile uint32*)(ADC1_BASE + 0x10)
+#define ADC_SQR1 *(volatile uint32*)(ADC1_BASE + 0x2C)
+#define ADC_SQR3 *(volatile uint32*)(ADC1_BASE + 0x34)
+#define ADC_DR *(volatile uint32*)(ADC1_BASE + 0x4C)
#define CR2_EXTSEL_SWSTART (0xE << 16)
#define CR2_RSTCAL (BIT(3))
#define CR2_EXTTRIG (BIT(20))
/* Bit banded bits */
-#define CR2_ADON_BIT *(volatile uint32*)(BITBAND_PERI(ADC_BASE+0x8, 0))
-#define CR2_CAL_BIT *(volatile uint32*)(BITBAND_PERI(ADC_BASE+0x8, 2))
-#define CR2_RSTCAL_BIT *(volatile uint32*)(BITBAND_PERI(ADC_BASE+0x8, 3))
-#define CR2_SWSTART_BIT *(volatile uint32*)(BITBAND_PERI(ADC_BASE+0x8 + 2, 6))
-#define SR_EOC_BIT *(volatile uint32*)(BITBAND_PERI(ADC_BASE+0, 1))
+#define CR2_ADON_BIT *(volatile uint32*)(BITBAND_PERI(ADC1_BASE+0x8, 0))
+#define CR2_CAL_BIT *(volatile uint32*)(BITBAND_PERI(ADC1_BASE+0x8, 2))
+#define CR2_RSTCAL_BIT *(volatile uint32*)(BITBAND_PERI(ADC1_BASE+0x8, 3))
+#define CR2_SWSTART_BIT *(volatile uint32*)(BITBAND_PERI(ADC1_BASE+0x8 + 2, 6))
+#define SR_EOC_BIT *(volatile uint32*)(BITBAND_PERI(ADC1_BASE+0, 1))
-#define NR_ANALOG_PINS 29
+// NR_ANALOG_PINS is board specific
/* Initialize ADC1 to do one-shot conversions */
void adc_init(void);
@@ -88,8 +91,6 @@ static inline int adc_read(int channel) {
return ADC_DR;
}
-
-
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/libmaple/dac.c b/libmaple/dac.c
index b9c7d63..ffc34f8 100644
--- a/libmaple/dac.c
+++ b/libmaple/dac.c
@@ -39,7 +39,7 @@ DAC_Map *dac = (DAC_Map*)(DAC_BASE);
void dac_init(void) {
// First turn on the clock
- rcc_enable_clk_dac();
+ rcc_clk_enable(RCC_DAC);
// Then setup ANALOG mode on PA4 and PA5
gpio_set_mode(GPIOA_BASE, 4, CNF_INPUT_ANALOG);
diff --git a/libmaple/exti.h b/libmaple/exti.h
index fdba184..2832e24 100644
--- a/libmaple/exti.h
+++ b/libmaple/exti.h
@@ -94,12 +94,11 @@
* EXTI[5-9] -> EXT9_5
* EXTI[10-15] -> EXT15_10
*
- *
* */
-#define NR_EXTI_CHANNELS 16
-#define NR_EXTI_PORTS 4
#define NR_EXTI_MODES 3
+#define NR_EXTI_CHANNELS 16
+#define NR_EXTI_PORTS NR_GPIO_PORTS // board specific
#define EXTI_IMR 0x40010400 // Interrupt mask register
#define EXTI_EMR (EXTI_IMR + 0x04) // Event mask register
@@ -139,6 +138,9 @@
#define EXTI_CONFIG_PORTB 1
#define EXTI_CONFIG_PORTC 2
#define EXTI_CONFIG_PORTD 3
+#define EXTI_CONFIG_PORTE 4 // Native only
+#define EXTI_CONFIG_PORTF 5 // Native only
+#define EXTI_CONFIG_PORTG 6 // Native only
#ifdef __cplusplus
diff --git a/libmaple/flash.c b/libmaple/flash.c
index 3fd35d6..828f938 100644
--- a/libmaple/flash.c
+++ b/libmaple/flash.c
@@ -22,12 +22,19 @@
* THE SOFTWARE.
* ****************************************************************************/
+/**
+ * @brief flash peripheral management functions
+ */
+
+
#include "libmaple.h"
#include "flash.h"
+/* flash registers */
#define FLASH_BASE 0x40022000
#define FLASH_ACR FLASH_BASE
+/* flash prefetcher */
#define ACR_PRFTBE BIT(4)
#define ACR_PRFTBE_ENABLE BIT(4)
@@ -37,7 +44,6 @@
#define FLASH_WRITE_ACR(val) __write(FLASH_ACR, val)
#define FLASH_READ_ACR() __read(FLASH_ACR)
-
/**
* @brief turn on the hardware prefetcher
*/
diff --git a/libmaple/fsmc.c b/libmaple/fsmc.c
index a8df2e1..502b7b4 100644
--- a/libmaple/fsmc.c
+++ b/libmaple/fsmc.c
@@ -90,7 +90,7 @@ void fsmc_native_sram_init(void) {
gpio_set_mode(GPIOE_BASE, 1, MODE_AF_OUTPUT_PP); // NBL1
// Next enable the clock
- rcc_enable_clk_fsmc();
+ rcc_clk_enable(RCC_FSMC);
// Then we configure channel 1 the FSMC SRAM peripheral
// (all SRAM channels are in "Bank 1" of the FSMC)
diff --git a/libmaple/gpio.c b/libmaple/gpio.c
index a47e623..c5bb450 100644
--- a/libmaple/gpio.c
+++ b/libmaple/gpio.c
@@ -33,14 +33,16 @@
#include "gpio.h"
void gpio_init(void) {
- rcc_enable_clk_gpioa();
- rcc_enable_clk_gpiob();
- rcc_enable_clk_gpioc();
- rcc_enable_clk_gpiod();
- rcc_enable_clk_gpioe();
- rcc_enable_clk_gpiof();
- rcc_enable_clk_gpiog();
- rcc_enable_clk_afio();
+ rcc_clk_enable(RCC_GPIOA);
+ rcc_clk_enable(RCC_GPIOB);
+ rcc_clk_enable(RCC_GPIOC);
+ rcc_clk_enable(RCC_GPIOD);
+ #if NR_GPIO_PORTS >= 7
+ rcc_clk_enable(RCC_GPIOE);
+ rcc_clk_enable(RCC_GPIOF);
+ rcc_clk_enable(RCC_GPIOG);
+ #endif
+ rcc_clk_enable(RCC_AFIO);
}
void gpio_set_mode(GPIO_Port* port, uint8 gpio_pin, GPIOPinMode mode) {
diff --git a/libmaple/gpio.h b/libmaple/gpio.h
index edbd4f0..9099c9b 100644
--- a/libmaple/gpio.h
+++ b/libmaple/gpio.h
@@ -44,13 +44,13 @@
* - After reset, the alternate functions are not active and IO prts
* are set to Input Floating mode */
-#define GPIOA_BASE (GPIO_Port*)0x40010800
-#define GPIOB_BASE (GPIO_Port*)0x40010C00
-#define GPIOC_BASE (GPIO_Port*)0x40011000
-#define GPIOD_BASE (GPIO_Port*)0x40011400
-#define GPIOE_BASE (GPIO_Port*)0x40011800
-#define GPIOF_BASE (GPIO_Port*)0x40011C00
-#define GPIOG_BASE (GPIO_Port*)0x40012000
+#define GPIOA_BASE (GPIO_Port*)0x40010800
+#define GPIOB_BASE (GPIO_Port*)0x40010C00
+#define GPIOC_BASE (GPIO_Port*)0x40011000
+#define GPIOD_BASE (GPIO_Port*)0x40011400
+#define GPIOE_BASE (GPIO_Port*)0x40011800 // High-density devices only
+#define GPIOF_BASE (GPIO_Port*)0x40011C00 // High-density devices only
+#define GPIOG_BASE (GPIO_Port*)0x40012000 // High-density devices only
#define GPIO_SPEED_50MHZ (0x3)
diff --git a/libmaple/libmaple.h b/libmaple/libmaple.h
index 5360b51..8e072c3 100644
--- a/libmaple/libmaple.h
+++ b/libmaple/libmaple.h
@@ -32,6 +32,116 @@
#define _LIBMAPLE_H_
#include "libmaple_types.h"
+
+// General configuration
+#define MAPLE_DEBUG 0
+
+// MCU-specific configuration
+#ifdef MCU_STM32F103RB // eg, LeafLabs Maple
+
+ // Number of GPIO ports (GPIOA, GPIOB, etc), definately used
+ #define NR_GPIO_PORTS 4
+
+ // Total number of GPIO pins
+ #define NR_GPIO_PINS 39
+
+ // Number of timer devices ports, definately used
+ #define NR_TIMERS 4
+
+ // Has an FSMC bus?
+ #define NR_FSMC 1
+
+ // Has an FSMC bus?
+ #define NR_DAC_PINS 2
+
+ // USB Identifier numbers
+ // Descriptor strings must be modified by hand in usb/descriptors.c for now
+ #define VCOM_ID_VENDOR 0x1EAF
+ #define VCOM_ID_PRODUCT 0x0004
+ #define USB_CONFIG_MAX_POWER (100 >> 1)
+ #define RESET_DELAY (100)
+
+ // Where to put usercode (based on space reserved for bootloader)
+ #define USER_ADDR_ROM 0x08005000
+ #define USER_ADDR_RAM 0x20000C00
+ #define STACK_TOP 0x20000800
+
+ // Debug port settings (from ASSERT)
+ #define ERROR_LED_PORT GPIOA_BASE
+ #define ERROR_LED_PIN 5
+ #define ERROR_USART_NUM 2
+ #define ERROR_USART_BAUD 9600
+ #define ERROR_TX_PIN 2
+ #define ERROR_TX_PORT GPIOA_BASE
+
+ // Just in case, most boards have at least some memory
+ #ifndef RAMSIZE
+ # define RAMSIZE (caddr_t)0x50000
+ #endif
+
+ // Bitbanded Memory sections
+ #define BITBAND_SRAM_REF 0x20000000
+ #define BITBAND_SRAM_BASE 0x22000000
+ #define BITBAND_PERI_REF 0x40000000
+ #define BITBAND_PERI_BASE 0x42000000
+#endif
+
+#ifdef MCU_STM32F103ZE // eg, LeafLabs Maple Native
+
+ // Number of GPIO ports (GPIOA, GPIOB, etc), definately used
+ #define NR_GPIO_PORTS 7
+
+ // Total number of GPIO pins
+ #define NR_GPIO_PINS 63
+
+ // Number of timer devices ports, definately used
+ #define NR_TIMERS 8
+
+ // Has an FSMC bus?
+ #define NR_FSMC 1
+
+ // Has an FSMC bus?
+ #define NR_DAC_PINS 2
+
+ // USB Identifier numbers
+ // Descriptor strings must be modified by hand in usb/descriptors.c for now
+ #define VCOM_ID_VENDOR 0x1EAF
+ #define VCOM_ID_PRODUCT 0x0004
+ #define USB_CONFIG_MAX_POWER (100 >> 1)
+ #define RESET_DELAY (100)
+
+ // Where to put usercode (based on space reserved for bootloader)
+ #define USER_ADDR_ROM 0x08005000
+ #define USER_ADDR_RAM 0x20000C00
+ #define STACK_TOP 0x20000800
+
+ // Debug port settings (from ASSERT)
+ #define ERROR_LED_PORT GPIOC_BASE
+ #define ERROR_LED_PIN 15
+ #define ERROR_USART_NUM 1
+ #define ERROR_USART_BAUD 9600
+ #define ERROR_TX_PIN 10
+ #define ERROR_TX_PORT GPIOA_BASE
+
+ // Just in case, most boards have at least some memory
+ #ifndef RAMSIZE
+ # define RAMSIZE (caddr_t)0x50000
+ #endif
+
+ // Bitbanded Memory sections
+ #define BITBAND_SRAM_REF 0x20000000
+ #define BITBAND_SRAM_BASE 0x22000000
+ #define BITBAND_PERI_REF 0x40000000
+ #define BITBAND_PERI_BASE 0x42000000
+#endif
+
+// Make sure MCU-specific settings were defined
+#ifndef NR_GPIO_PORTS
+#error Error: No MCU type specified. Add something like -DMCU_STM32F103RB \
+ to your compiler arguments (probably in a Makefile).
+#endif
+
+// Requires board configuration info
#include "util.h"
#endif
diff --git a/libmaple/nvic.c b/libmaple/nvic.c
index d8745a4..7aef26d 100644
--- a/libmaple/nvic.c
+++ b/libmaple/nvic.c
@@ -32,16 +32,6 @@
#include "nvic.h"
#include "systick.h"
-void nvic_disable_interrupts(void) {
- /* Turn off all interrupts */
- REG_SET(NVIC_ICER0, 0xFFFFFFFF);
- REG_SET(NVIC_ICER1, 0xFFFFFFFF);
-
- /* Turn off systick exception */
- REG_CLEAR_BIT(SYSTICK_CSR, 0);
-}
-
-
void nvic_set_vector_table(uint32 addr, uint32 offset) {
__write(SCB_VTOR, (uint32)addr | (offset & 0x1FFFFF80));
}
@@ -49,33 +39,29 @@ void nvic_set_vector_table(uint32 addr, uint32 offset) {
/**
* @brief turn on interrupt number n
- * @param[in] n interrupt number
+ * @param n interrupt number
*/
-void nvic_enable_interrupt(uint32 n) {
- if (n >= NVIC_NR_INTERRUPTS) {
- return;
- }
-
+void nvic_irq_enable(uint32 n) {
if (n < 32) {
REG_SET_BIT(NVIC_ISER0, n);
- } else {
+ } else if(n < 64) {
REG_SET_BIT(NVIC_ISER1, n - 32);
+ } else {
+ REG_SET_BIT(NVIC_ISER2, n - 64);
}
}
/**
* @brief turn off interrupt number n
- * @param[in] n interrupt number
+ * @param n interrupt number
*/
-void nvic_disable_interrupt(uint32 n) {
- if (n >= NVIC_NR_INTERRUPTS) {
- return;
- }
-
+void nvic_irq_disable(uint32 n) {
if (n < 32) {
REG_SET_BIT(NVIC_ICER0, n);
- } else {
+ } else if(n < 64) {
REG_SET_BIT(NVIC_ICER1, n - 32);
+ } else {
+ REG_SET_BIT(NVIC_ICER2, n - 64);
}
}
diff --git a/libmaple/nvic.h b/libmaple/nvic.h
index 8f18e4d..a24086a 100644
--- a/libmaple/nvic.h
+++ b/libmaple/nvic.h
@@ -38,13 +38,13 @@
#define NVIC_ISER0 0xE000E100
#define NVIC_ISER1 0xE000E104
#define NVIC_ISER2 0xE000E108
-#define NVIC_ISER3 0xE000E10C
+#define NVIC_ISER3 0xE000E10C // Non existant?
/* NVIC Interrupt Clear registers */
#define NVIC_ICER0 0xE000E180
#define NVIC_ICER1 0xE000E184
#define NVIC_ICER2 0xE000E188
-#define NVIC_ICER3 0xE000E18C
+#define NVIC_ICER3 0xE000E18C // Non existant?
/* System control registers */
#define SCB_VTOR 0xE000ED08 // Vector table offset register
@@ -52,20 +52,32 @@
#define NVIC_VectTab_RAM ((u32)0x20000000)
#define NVIC_VectTab_FLASH ((u32)0x08000000)
-#define NVIC_NR_INTERRUPTS 60
-
-/* Where to put code */
-#define USER_ADDR_ROM 0x08005000
-#define USER_ADDR_RAM 0x20000C00
-
#ifdef __cplusplus
extern "C"{
#endif
+enum {
+ NVIC_TIMER1 = 27,
+ NVIC_TIMER2 = 28,
+ NVIC_TIMER3 = 29,
+ NVIC_TIMER4 = 30,
+ NVIC_TIMER5 = 50, // high density only (Maple Native)
+ NVIC_TIMER6 = 54, // high density only (Maple Native)
+ NVIC_TIMER7 = 55, // high density only (Maple Native)
+ NVIC_USART1 = 37,
+ NVIC_USART2 = 38,
+ NVIC_USART3 = 39,
+ NVIC_USART4 = 52, // high density only (Maple Native)
+ NVIC_USART5 = 53, // high density only (Maple Native)
+};
+
+
+#define nvic_globalirq_enable() asm volatile("cpsid i")
+#define nvic_globalirq_disable() asm volatile("cpsie i")
+
void nvic_init(void);
-void nvic_disable_interrupts(void);
-void nvic_enable_interrupt(uint32);
-void nvic_disable_interrupt(uint32);
+void nvic_irq_enable(uint32 device);
+void nvic_irq_disable(uint32 device);
#ifdef __cplusplus
}
diff --git a/libmaple/rcc.c b/libmaple/rcc.c
index fbf9160..9bd2663 100644
--- a/libmaple/rcc.c
+++ b/libmaple/rcc.c
@@ -23,66 +23,73 @@
* ****************************************************************************/
/**
- * @file rcc.c
- *
* @brief Implements pretty much only the basic clock setup on the stm32,
- * exposes a handful of clock enable/disable and peripheral reset commands.
+ * clock enable/disable and peripheral reset commands.
*/
#include "libmaple.h"
#include "flash.h"
#include "rcc.h"
-#define RCC_CFGR_PPRE1 (0x7 << 8)
-#define RCC_CFGR_PPRE2 (0x7 << 11)
-#define RCC_CFGR_HPRE (0xF << 4)
-#define RCC_CFGR_PLLSRC (0x1 << 16)
-
-#define RCC_CFGR_SWS (0x3 << 2)
-#define RCC_CFGR_SWS_PLL (0x2 << 2)
-#define RCC_CFGR_SWS_HSE (0x1 << 2)
-
-#define RCC_CFGR_SW (0x3 << 0)
-#define RCC_CFGR_SW_PLL (0x2 << 0)
-#define RCC_CFGR_SW_HSE (0x1 << 0)
-
-/* CR status bits */
-#define RCC_CR_HSEON (0x1 << 16)
-#define RCC_CR_HSERDY (0x1 << 17)
-#define RCC_CR_PLLON (0x1 << 24)
-#define RCC_CR_PLLRDY (0x1 << 25)
+enum {
+ APB1,
+ APB2,
+ AHB
+};
-#define RCC_WRITE_CFGR(val) __write(RCC_CFGR, val)
-#define RCC_READ_CFGR() __read(RCC_CFGR)
+struct rcc_dev_info {
+ const uint8 clk_domain;
+ const uint8 line_num;
+};
-#define RCC_WRITE_CR(val) __write(RCC_CR, val)
-#define RCC_READ_CR() __read(RCC_CR)
+/* device descriptor tables */
+static const struct rcc_dev_info rcc_dev_table[] = {
+ [RCC_GPIOA] = { .clk_domain = APB2, .line_num = 2 },
+ [RCC_GPIOB] = { .clk_domain = APB2, .line_num = 3 },
+ [RCC_GPIOC] = { .clk_domain = APB2, .line_num = 4 },
+ [RCC_GPIOD] = { .clk_domain = APB2, .line_num = 5 },
+ [RCC_GPIOE] = { .clk_domain = APB2, .line_num = 6 }, // High-density devices only
+ [RCC_GPIOF] = { .clk_domain = APB2, .line_num = 7 }, // High-density devices only
+ [RCC_GPIOG] = { .clk_domain = APB2, .line_num = 8 }, // High-density devices only
+ [RCC_AFIO] = { .clk_domain = APB2, .line_num = 0 },
+ [RCC_ADC1] = { .clk_domain = APB2, .line_num = 9 },
+ [RCC_ADC2] = { .clk_domain = APB2, .line_num = 10 },
+ [RCC_USART1] = { .clk_domain = APB2, .line_num = 14 },
+ [RCC_USART2] = { .clk_domain = APB1, .line_num = 17 },
+ [RCC_USART3] = { .clk_domain = APB1, .line_num = 18 },
+ [RCC_USART4] = { .clk_domain = APB1, .line_num = 19 }, // High-density devices only
+ [RCC_USART5] = { .clk_domain = APB1, .line_num = 20 }, // High-density devices only
+ [RCC_TIMER1] = { .clk_domain = APB2, .line_num = 11 },
+ [RCC_TIMER2] = { .clk_domain = APB1, .line_num = 0 },
+ [RCC_TIMER3] = { .clk_domain = APB1, .line_num = 1 },
+ [RCC_TIMER4] = { .clk_domain = APB1, .line_num = 2 },
+ [RCC_TIMER5] = { .clk_domain = APB1, .line_num = 3 }, // High-density devices only
+ [RCC_TIMER6] = { .clk_domain = APB1, .line_num = 4 }, // High-density devices only
+ [RCC_TIMER7] = { .clk_domain = APB1, .line_num = 5 }, // High-density devices only
+ [RCC_TIMER8] = { .clk_domain = APB2, .line_num = 13 }, // High-density devices only
+ [RCC_SPI1] = { .clk_domain = APB2, .line_num = 12 },
+ [RCC_SPI2] = { .clk_domain = APB1, .line_num = 14 },
+ [RCC_FSMC] = { .clk_domain = AHB, .line_num = 8 }, // High-density devices only
+ [RCC_DAC] = { .clk_domain = APB1, .line_num = 9 }, // High-density devices only
+};
/**
- * @brief Initialize the clock control system. Sets up only the basics:
- * APB1 clock prescaler
- * APB2 clock prescaler
- * AHB clock prescaler
- * System clock source (Must be PLL)
- * PLL clock source (Must be high-speed external clock)
- * PLL Multiplier
- * @param dev initialization struct
- * @sideeffect Switches clock source to PLL, clock speed to HSE_CLK*PLLMUL
+ * @brief Initialize the clock control system. Initializes the system
+ * clock source to use the PLL driven by an external oscillator
+ * @param sysclk_src system clock source, must be PLL
+ * @param pll_src pll clock source, must be HSE
+ * @param pll_mul pll multiplier
*/
-void rcc_init(struct rcc_device *dev) {
+void rcc_clk_init(uint32 sysclk_src, uint32 pll_src, uint32 pll_mul) {
/* Assume that we're going to clock the chip off the PLL, fed by
* the HSE */
- ASSERT(dev->sysclk_src == RCC_CLKSRC_PLL &&
- dev->pll_src == RCC_PLLSRC_HSE);
+ ASSERT(sysclk_src == RCC_CLKSRC_PLL &&
+ pll_src == RCC_PLLSRC_HSE);
uint32 cfgr = 0;
uint32 cr = RCC_READ_CR();
- cfgr = (dev->apb1_prescale |
- dev->apb2_prescale |
- dev->ahb_prescale |
- dev->pll_src |
- dev->pll_mul);
+ cfgr = (pll_src | pll_mul);
RCC_WRITE_CFGR(cfgr);
/* Turn on the HSE */
@@ -104,3 +111,60 @@ void rcc_init(struct rcc_device *dev) {
while ((RCC_READ_CFGR() & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
;
}
+
+
+
+/**
+ * @brief Turn on the clock line on a device
+ * @param dev_num device to turn on
+ */
+void rcc_clk_enable(uint32 dev_num) {
+ static const uint32 enable_regs[] = {
+ [APB1] = RCC_APB1ENR,
+ [APB2] = RCC_APB2ENR,
+ [AHB] = RCC_AHBENR,
+ };
+
+ uint8 clk_domain = rcc_dev_table[dev_num].clk_domain;
+
+ __set_bits(enable_regs[clk_domain], BIT(rcc_dev_table[dev_num].line_num));
+}
+
+
+/**
+ * @brief Set the divider on a device prescaler
+ * @param prescaler prescaler to set
+ * @param divider prescaler divider
+ */
+void rcc_set_prescaler(uint32 prescaler, uint32 divider) {
+ static const uint32 masks[] = {
+ [RCC_PRESCALER_AHB] = RCC_CFGR_HPRE,
+ [RCC_PRESCALER_APB1] = RCC_CFGR_PPRE1,
+ [RCC_PRESCALER_APB2] = RCC_CFGR_PPRE2,
+ [RCC_PRESCALER_USB] = RCC_CFGR_USBPRE,
+ [RCC_PRESCALER_ADC] = RCC_CFGR_ADCPRE,
+ };
+
+ uint32 cfgr = RCC_READ_CFGR();
+
+ cfgr &= ~masks[prescaler];
+ cfgr |= divider;
+ RCC_WRITE_CFGR(cfgr);
+}
+
+
+/**
+ * @brief reset a device
+ * @param dev_num device to reset
+ */
+void rcc_reset_dev(uint32 dev_num) {
+ static const uint32 reset_regs[] = {
+ [APB1] = RCC_APB1RSTR,
+ [APB2] = RCC_APB2RSTR,
+ };
+
+ uint8 clk_domain = rcc_dev_table[dev_num].clk_domain;
+
+ __set_bits(reset_regs[clk_domain], BIT(rcc_dev_table[dev_num].line_num));
+ __clear_bits(reset_regs[clk_domain], BIT(rcc_dev_table[dev_num].line_num));
+}
diff --git a/libmaple/rcc.h b/libmaple/rcc.h
index 2dca151..3651945 100644
--- a/libmaple/rcc.h
+++ b/libmaple/rcc.h
@@ -23,42 +23,84 @@
* ****************************************************************************/
/**
- * @file rcc.h
- *
- * @brief
+ * @brief reset and clock control definitions and prototypes
*/
#ifndef _RCC_H_
#define _RCC_H_
-struct rcc_device {
- uint32 apb1_prescale;
- uint32 apb2_prescale;
- uint32 ahb_prescale;
- uint32 sysclk_src;
- uint32 pll_src;
- uint32 pll_mul;
-};
+/* registers */
+#define RCC_BASE 0x40021000
+#define RCC_CR (RCC_BASE + 0x0)
+#define RCC_CFGR (RCC_BASE + 0x4)
+#define RCC_CIR (RCC_BASE + 0x8)
+#define RCC_APB2RSTR (RCC_BASE + 0xC)
+#define RCC_APB1RSTR (RCC_BASE + 0x10)
+#define RCC_AHBENR (RCC_BASE + 0x14)
+#define RCC_APB2ENR (RCC_BASE + 0x18)
+#define RCC_APB1ENR (RCC_BASE + 0x1C)
+#define RCC_BDCR (RCC_BASE + 0x20)
+#define RCC_CSR (RCC_BASE + 0x24)
+#define RCC_AHBSTR (RCC_BASE + 0x28)
+#define RCC_CFGR2 (RCC_BASE + 0x2C)
+
+#define RCC_CFGR_USBPRE (0x1 << 22)
+#define RCC_CFGR_ADCPRE (0x3 << 14)
+#define RCC_CFGR_PPRE1 (0x7 << 8)
+#define RCC_CFGR_PPRE2 (0x7 << 11)
+#define RCC_CFGR_HPRE (0xF << 4)
+#define RCC_CFGR_PLLSRC (0x1 << 16)
+
+#define RCC_CFGR_SWS (0x3 << 2)
+#define RCC_CFGR_SWS_PLL (0x2 << 2)
+#define RCC_CFGR_SWS_HSE (0x1 << 2)
+
+#define RCC_CFGR_SW (0x3 << 0)
+#define RCC_CFGR_SW_PLL (0x2 << 0)
+#define RCC_CFGR_SW_HSE (0x1 << 0)
+
+/* CR status bits */
+#define RCC_CR_HSEON (0x1 << 16)
+#define RCC_CR_HSERDY (0x1 << 17)
+#define RCC_CR_PLLON (0x1 << 24)
+#define RCC_CR_PLLRDY (0x1 << 25)
+
+#define RCC_WRITE_CFGR(val) __write(RCC_CFGR, val)
+#define RCC_READ_CFGR() __read(RCC_CFGR)
+
+#define RCC_WRITE_CR(val) __write(RCC_CR, val)
+#define RCC_READ_CR() __read(RCC_CR)
+/* sysclk source */
#define RCC_CLKSRC_HSI (0x0)
#define RCC_CLKSRC_HSE (0x1)
#define RCC_CLKSRC_PLL (0x2)
-#define RCC_PLLSRC_HSI_DIV_2 (0x0 << 16)
-#define RCC_PLLSRC_HSE (0x1 << 16)
+/* pll entry clock source */
+#define RCC_PLLSRC_HSE (0x1 << 16)
+#define RCC_PLLSRC_HSI_DIV_2 (0x0 << 16)
+/* adc prescaler dividers */
+#define RCC_ADCPRE_PCLK_DIV_2 (0x0 << 14)
+#define RCC_ADCPRE_PCLK_DIV_4 (0x1 << 14)
+#define RCC_ADCPRE_PCLK_DIV_6 (0x2 << 14)
+#define RCC_ADCPRE_PCLK_DIV_8 (0x3 << 14)
+
+/* apb1 prescaler dividers */
#define RCC_APB1_HCLK_DIV_1 (0x0 << 8)
#define RCC_APB1_HCLK_DIV_2 (0x4 << 8)
#define RCC_APB1_HCLK_DIV_4 (0x5 << 8)
#define RCC_APB1_HCLK_DIV_8 (0x6 << 8)
#define RCC_APB1_HCLK_DIV_16 (0x7 << 8)
+/* apb2 prescaler dividers */
#define RCC_APB2_HCLK_DIV_1 (0x0 << 11)
#define RCC_APB2_HCLK_DIV_2 (0x4 << 11)
#define RCC_APB2_HCLK_DIV_4 (0x5 << 11)
#define RCC_APB2_HCLK_DIV_8 (0x6 << 11)
#define RCC_APB2_HCLK_DIV_16 (0x7 << 11)
+/* ahb prescaler dividers */
#define RCC_AHB_SYSCLK_DIV_1 (0x0 << 4)
#define RCC_AHB_SYSCLK_DIV_2 (0x8 << 4)
#define RCC_AHB_SYSCLK_DIV_4 (0x9 << 4)
@@ -70,6 +112,7 @@ struct rcc_device {
#define RCC_AHB_SYSCLK_DIV_256 (0xE << 4)
#define RCC_AHB_SYSCLK_DIV_512 (0xF << 4)
+/* pll multipliers */
#define RCC_PLLMUL_2 (0x0 << 18)
#define RCC_PLLMUL_3 (0x1 << 18)
#define RCC_PLLMUL_4 (0x2 << 18)
@@ -86,118 +129,52 @@ struct rcc_device {
#define RCC_PLLMUL_15 (0xD << 18)
#define RCC_PLLMUL_16 (0xE << 18)
-/* remove!! */
-#define RCC_BASE 0x40021000
-#define RCC_CR (RCC_BASE + 0x0)
-#define RCC_CFGR (RCC_BASE + 0x4)
-#define RCC_CIR (RCC_BASE + 0x8)
-#define RCC_APB2RSTR (RCC_BASE + 0xC)
-#define RCC_APB1RSTR (RCC_BASE + 0x10)
-#define RCC_AHBENR (RCC_BASE + 0x14)
-#define RCC_APB2ENR (RCC_BASE + 0x18)
-#define RCC_APB1ENR (RCC_BASE + 0x1C)
-#define RCC_BDCR (RCC_BASE + 0x20)
-#define RCC_CSR (RCC_BASE + 0x24)
-#define RCC_AHBSTR (RCC_BASE + 0x28)
-#define RCC_CFGR2 (RCC_BASE + 0x2C)
-/* APB2 reset bits */
-#define RCC_APB2RSTR_USART1RST BIT(14)
-#define RCC_APB2RSTR_SPI1RST BIT(12)
-#define RCC_APB2RSTR_TIM1RST BIT(11)
-#define RCC_APB2RSTR_ADC2RST BIT(10)
-#define RCC_APB2RSTR_ADC1RST BIT(9)
-#define RCC_APB2RSTR_IOERST BIT(6)
-#define RCC_APB2RSTR_IODRST BIT(5)
-#define RCC_APB2RSTR_IOCRST BIT(4)
-#define RCC_APB2RSTR_IOBRST BIT(3)
-#define RCC_APB2RSTR_IOARST BIT(2)
-#define RCC_APB2RSTR_AFIORST BIT(0)
-
-#define RCC_APB1RSTR_USB BIT(23)
-
-/* APB2 peripheral clock enable bits */
-#define RCC_APB2ENR_USART1EN BIT(14)
-#define RCC_APB2ENR_SPI1EN BIT(12)
-#define RCC_APB2ENR_TIM1EN BIT(11)
-#define RCC_APB2ENR_ADC2EN BIT(10)
-#define RCC_APB2ENR_ADC1EN BIT(9)
-#define RCC_APB2ENR_IOPGEN BIT(8)
-#define RCC_APB2ENR_IOPFEN BIT(7)
-#define RCC_APB2ENR_IOPEEN BIT(6)
-#define RCC_APB2ENR_IOPDEN BIT(5)
-#define RCC_APB2ENR_IOPCEN BIT(4)
-#define RCC_APB2ENR_IOPBEN BIT(3)
-#define RCC_APB2ENR_IOPAEN BIT(2)
-#define RCC_APB2ENR_AFIOEN BIT(0)
-
-/* APB1 peripheral clock enable bits */
-#define RCC_APB1ENR_TIM2EN BIT(0)
-#define RCC_APB1ENR_TIM3EN BIT(1)
-#define RCC_APB1ENR_TIM4EN BIT(2)
-#define RCC_APB1ENR_USART2EN BIT(17)
-#define RCC_APB1ENR_USART3EN BIT(18)
-#define RCC_APB1ENR_SPI2EN BIT(14)
-#define RCC_APB1ENR_USB BIT(23)
-#define RCC_APB1ENR_DACEN BIT(29)
-
-/* AHB peripheral clock enable bits */
-#define RCC_AHBENR_DMA1EN BIT(0)
-#define RCC_AHBENR_DMA2EN BIT(1)
-#define RCC_AHBENR_SRAMEN BIT(2)
-#define RCC_AHBENR_FLITFEN BIT(4)
-#define RCC_AHBENR_CRCEN BIT(6)
-#define RCC_AHBENR_FSMCEN BIT(8)
-#define RCC_AHBENR_SDIOEN BIT(10)
-
-#define rcc_enable_clk_fsmc() __set_bits(RCC_AHBENR, RCC_AHBENR_FSMCEN)
-
-#define rcc_enable_clk_spi1() __set_bits(RCC_APB2ENR, RCC_APB2ENR_SPI1EN)
-#define rcc_enable_clk_spi2() __set_bits(RCC_APB1ENR, RCC_APB1ENR_SPI2EN)
-
-#define rcc_enable_clk_timer1() __set_bits(RCC_APB2ENR, RCC_APB2ENR_TIM1EN)
-#define rcc_enable_clk_timer2() __set_bits(RCC_APB1ENR, RCC_APB1ENR_TIM2EN)
-#define rcc_enable_clk_timer3() __set_bits(RCC_APB1ENR, RCC_APB1ENR_TIM3EN)
-#define rcc_enable_clk_timer4() __set_bits(RCC_APB1ENR, RCC_APB1ENR_TIM4EN)
-
-#define rcc_enable_clk_gpioa() __set_bits(RCC_APB2ENR, RCC_APB2ENR_IOPAEN)
-#define rcc_enable_clk_gpiob() __set_bits(RCC_APB2ENR, RCC_APB2ENR_IOPBEN)
-#define rcc_enable_clk_gpioc() __set_bits(RCC_APB2ENR, RCC_APB2ENR_IOPCEN)
-#define rcc_enable_clk_gpiod() __set_bits(RCC_APB2ENR, RCC_APB2ENR_IOPDEN)
-#define rcc_enable_clk_gpioe() __set_bits(RCC_APB2ENR, RCC_APB2ENR_IOPEEN)
-#define rcc_enable_clk_gpiof() __set_bits(RCC_APB2ENR, RCC_APB2ENR_IOPFEN)
-#define rcc_enable_clk_gpiog() __set_bits(RCC_APB2ENR, RCC_APB2ENR_IOPGEN)
-#define rcc_enable_clk_afio() __set_bits(RCC_APB2ENR, RCC_APB2ENR_AFIOEN)
-
-#define rcc_enable_clk_usart1() __set_bits(RCC_APB2ENR, RCC_APB2ENR_USART1EN)
-#define rcc_enable_clk_usart2() __set_bits(RCC_APB1ENR, RCC_APB1ENR_USART2EN)
-#define rcc_enable_clk_usart3() __set_bits(RCC_APB1ENR, RCC_APB1ENR_USART3EN)
-
-#define rcc_enable_clk_adc1() __set_bits(RCC_APB2ENR, RCC_APB2ENR_ADC1EN)
-
-#define rcc_enable_clk_dac() __set_bits(RCC_APB1ENR, RCC_APB1ENR_DACEN)
-
-#define rcc_reset_adc1() { __set_bits(RCC_APB2RSTR, RCC_APB2RSTR_ADC1RST); \
- __clear_bits(RCC_APB2RSTR, RCC_APB2RSTR_ADC1RST); \
- }
-
-#define rcc_reset_usb() { __set_bits(RCC_APB1RSTR, RCC_APB1RSTR_USB); \
- __clear_bits(RCC_APB1RSTR, RCC_APB1RSTR_USB); \
- }
-
-
-#define PCLK2_DIV_2 0x00008000
-
-#ifdef __cplusplus
-extern "C"{
-#endif
+/* prescalers */
+enum {
+ RCC_PRESCALER_AHB,
+ RCC_PRESCALER_APB1,
+ RCC_PRESCALER_APB2,
+ RCC_PRESCALER_USB,
+ RCC_PRESCALER_ADC
+};
-void rcc_init(struct rcc_device *dev);
+// RCC Devices
+enum {
+ RCC_GPIOA,
+ RCC_GPIOB,
+ RCC_GPIOC,
+ RCC_GPIOD,
+ RCC_GPIOE, // High-density devices only (Maple Native)
+ RCC_GPIOF, // High-density devices only (Maple Native)
+ RCC_GPIOG, // High-density devices only (Maple Native)
+ RCC_AFIO,
+ RCC_ADC1,
+ RCC_ADC2,
+ RCC_USART1,
+ RCC_USART2,
+ RCC_USART3,
+ RCC_USART4, // High-density devices only (Maple Native)
+ RCC_USART5, // High-density devices only (Maple Native)
+ RCC_TIMER1,
+ RCC_TIMER2,
+ RCC_TIMER3,
+ RCC_TIMER4,
+ RCC_TIMER5, // High-density devices only (Maple Native)
+ RCC_TIMER6, // High-density devices only (Maple Native)
+ RCC_TIMER7, // High-density devices only (Maple Native)
+ RCC_TIMER8, // High-density devices only (Maple Native)
+ RCC_SPI1,
+ RCC_SPI2,
+ RCC_FSMC, // High-density devices only (Maple Native)
+ RCC_DAC, // High-density devices only (Maple Native)
+};
-#ifdef __cplusplus
-}
-#endif
-#endif
+void rcc_clk_init(uint32 sysclk_src, uint32 pll_src, uint32 pll_mul);
+void rcc_clk_enable(uint32 dev);
+void rcc_reset_dev(uint32 dev);
+void rcc_set_prescaler(uint32 prescaler, uint32 divider);
+#endif
diff --git a/libmaple/ring_buffer.h b/libmaple/ring_buffer.h
new file mode 100644
index 0000000..95b9dd8
--- /dev/null
+++ b/libmaple/ring_buffer.h
@@ -0,0 +1,57 @@
+/**
+ * @brief simple circular buffer
+ */
+
+#ifndef _RING_BUFFER_H_
+#define _RING_BUFFER_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* The buffer is empty when head == tail.
+ * The buffer is full when the head is one byte in front of the tail
+ * The total buffer size must be a power of two
+ * One byte is left free to distinguish empty from full */
+typedef struct ring_buffer {
+ uint32 head;
+ uint32 tail;
+ uint8 size;
+ uint8 *buf;
+} ring_buffer;
+
+static inline void rb_init(ring_buffer *rb, uint8 size, uint8 *buf) {
+ ASSERT(IS_POWER_OF_TWO(size));
+ rb->head = 0;
+ rb->tail = 0;
+ rb->size = size;
+ rb->buf = buf;
+}
+
+static inline void rb_insert(ring_buffer *rb, uint8 element) {
+ rb->buf[(rb->tail)++] = element;
+ rb->tail &= (rb->size - 1);
+}
+
+static inline uint8 rb_remove(ring_buffer *rb) {
+ uint8 ch = rb->buf[rb->head++];
+ rb->head &= (rb->size - 1);
+ return ch;
+}
+
+static inline uint32 rb_full_count(ring_buffer *rb) {
+ return rb->tail - rb->head;
+}
+
+static inline void rb_reset(ring_buffer *rb) {
+ rb->tail = rb->head;
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+
+#endif
+
diff --git a/libmaple/spi.c b/libmaple/spi.c
index aa75c5f..68855a5 100644
--- a/libmaple/spi.c
+++ b/libmaple/spi.c
@@ -89,12 +89,12 @@ void spi_init(uint32 spi_num,
/* limit to 18 mhz max speed */
ASSERT(prescale != CR1_BR_PRESCALE_2);
spi = (SPI*)SPI1_BASE;
- rcc_enable_clk_spi1();
+ rcc_clk_enable(RCC_SPI1);
spi_gpio_cfg(&spi_dev1);
break;
case 2:
spi = (SPI*)SPI2_BASE;
- rcc_enable_clk_spi2();
+ rcc_clk_enable(RCC_SPI2);
spi_gpio_cfg(&spi_dev2);
break;
}
diff --git a/libmaple/spi.h b/libmaple/spi.h
index 25c2c6b..742c1d0 100644
--- a/libmaple/spi.h
+++ b/libmaple/spi.h
@@ -36,6 +36,7 @@ extern "C" {
/* peripheral addresses */
#define SPI1_BASE 0x40013000
#define SPI2_BASE 0x40003800
+#define SPI3_BASE 0x40003C00
/* baud rate prescaler bits */
#define CR1_BR 0x00000038
diff --git a/libmaple/syscalls.c b/libmaple/syscalls.c
index 63ebb1e..ec271a2 100644
--- a/libmaple/syscalls.c
+++ b/libmaple/syscalls.c
@@ -28,13 +28,6 @@
/* _end is set in the linker command file */
extern caddr_t _end;
-/* just in case, most boards have at least some memory */
-#ifndef RAMSIZE
-# define RAMSIZE (caddr_t)0x50000
-#endif
-
-#define STACK_TOP 0x20000800
-
void uart_send(const char*str);
/*
diff --git a/libmaple/systick.c b/libmaple/systick.c
index a333528..8b0d92a 100644
--- a/libmaple/systick.c
+++ b/libmaple/systick.c
@@ -31,23 +31,25 @@
#include "libmaple.h"
#include "systick.h"
-#define MILLIS_INC 1
+#define SYSTICK_RELOAD 0xE000E014 // Reload value register
+#define SYSTICK_CNT 0xE000E018 // Current value register
+#define SYSTICK_CALIB 0xE000E01C // Calibration value register
+
+#define SYSTICK_SRC_HCLK BIT(2) // Use core clock
+#define SYSTICK_TICKINT BIT(1) // Interrupt on systick countdown
+#define SYSTICK_ENABLE BIT(0) // Turn on the counter
volatile uint32 systick_timer_millis = 0;
-void systick_init(void) {
+void systick_init(uint32 reload_val) {
/* Set the reload counter to tick every 1ms */
- REG_SET_MASK(SYSTICK_RELOAD, MAPLE_RELOAD_VAL);
-// SYSTICK_RELOAD = MAPLE_RELOAD_VAL;
+ __write(SYSTICK_RELOAD, reload_val);
/* Clock the system timer with the core clock
* and turn it on, interrrupt every 1ms to keep track of millis()*/
- REG_SET(SYSTICK_CSR, SYSTICK_SRC_HCLK |
+ __write(SYSTICK_CSR, SYSTICK_SRC_HCLK |
SYSTICK_ENABLE |
SYSTICK_TICKINT);
-// SYSTICK_CSR = SYSTICK_SRC_HCLK |
-// SYSTICK_ENABLE |
-// SYSTICK_TICKINT;
}
void SysTickHandler(void) {
diff --git a/libmaple/systick.h b/libmaple/systick.h
index d0a623f..57b724a 100644
--- a/libmaple/systick.h
+++ b/libmaple/systick.h
@@ -33,30 +33,23 @@
#include "libmaple.h"
-/* To the ARM technical manual... there's nearly nothing on the systick
- * timer in the stm32 manual */
+#define SYSTICK_CSR 0xE000E010 // Control and status register
+#define SYSTICK_CNT 0xE000E018 // Current value register
-#define SYSTICK_CSR 0xE000E010 // Control and status register
-#define SYSTICK_RELOAD 0xE000E014 // Reload value register
-#define SYSTICK_CNT 0xE000E018 // Current value register
-#define SYSTICK_CALIB 0xE000E01C // Calibration value register
-
-#define SYSTICK_SRC_HCLK BIT(2) // Use core clock
-#define SYSTICK_TICKINT BIT(1) // Interrupt on systick countdown
-#define SYSTICK_ENABLE BIT(0) // Turn on the counter
-
-/* We use the systick timer to tick once
- * every millisecond */
-#define MAPLE_RELOAD_VAL 72000
+#define SYSTICK_CSR_COUNTFLAG BIT(16)
#ifdef __cplusplus
extern "C"{
#endif
-void systick_init(void);
+void systick_init(uint32 reload_val);
static inline uint32 systick_get_count(void) {
- return (uint32)*(volatile uint32*)SYSTICK_CNT;
+ return __read(SYSTICK_CNT);
+}
+
+static inline uint32 systick_check_underflow(void) {
+ return (__read(SYSTICK_CSR) & SYSTICK_CSR_COUNTFLAG);
}
#ifdef __cplusplus
diff --git a/libmaple/timers.c b/libmaple/timers.c
index da85680..6fa2848 100644
--- a/libmaple/timers.c
+++ b/libmaple/timers.c
@@ -28,8 +28,11 @@
* @brief General timer routines
*/
+// TODO: actually support timer5 and timer8
+
#include "libmaple.h"
#include "rcc.h"
+#include "nvic.h"
#include "timers.h"
typedef struct {
@@ -81,6 +84,10 @@ volatile static voidFuncPtr timer1_handlers[4];
volatile static voidFuncPtr timer2_handlers[4];
volatile static voidFuncPtr timer3_handlers[4];
volatile static voidFuncPtr timer4_handlers[4];
+#if NR_TIMERS >= 8
+volatile static voidFuncPtr timer5_handlers[4]; // High-density devices only
+volatile static voidFuncPtr timer8_handlers[4]; // High-density devices only
+#endif
// This function should probably be rewriten to take (timer_num, mode) and have
// prescaler set elsewhere. The mode can be passed through to set_mode at the
@@ -94,21 +101,35 @@ void timer_init(uint8 timer_num, uint16 prescale) {
switch(timer_num) {
case 1:
timer = (Timer*)TIMER1_BASE;
- rcc_enable_clk_timer1();
+ rcc_clk_enable(RCC_TIMER1);
is_advanced = 1;
break;
case 2:
timer = (Timer*)TIMER2_BASE;
- rcc_enable_clk_timer2();
+ rcc_clk_enable(RCC_TIMER2);
break;
case 3:
timer = (Timer*)TIMER3_BASE;
- rcc_enable_clk_timer3();
+ rcc_clk_enable(RCC_TIMER3);
break;
case 4:
timer = (Timer*)TIMER4_BASE;
- rcc_enable_clk_timer4();
+ rcc_clk_enable(RCC_TIMER4);
+ break;
+ #if NR_TIMERS >= 8
+ case 5:
+ timer = (Timer*)TIMER5_BASE;
+ rcc_clk_enable(RCC_TIMER5);
break;
+ case 8:
+ timer = (Timer*)TIMER8_BASE;
+ rcc_clk_enable(RCC_TIMER8);
+ is_advanced = 1;
+ break;
+ #endif
+ default:
+ ASSERT(0);
+ return;
}
timer->CR1 = ARPE; // No clock division
@@ -171,6 +192,9 @@ void timer_pause(uint8 timer_num) {
case 4:
timer = (Timer*)TIMER4_BASE;
break;
+ default:
+ ASSERT(0);
+ return;
}
timer->CR1 &= ~(0x0001); // CEN
}
@@ -193,6 +217,9 @@ void timer_resume(uint8 timer_num) {
case 4:
timer = (Timer*)TIMER4_BASE;
break;
+ default:
+ ASSERT(0);
+ return;
}
timer->CR1 |= 0x0001; // CEN
}
@@ -217,6 +244,9 @@ ASSERT(timer_num > 0 && timer_num <= 4);
case 4:
timer = (Timer*)TIMER4_BASE;
break;
+ default:
+ ASSERT(0);
+ return;
}
timer->CNT = value;
}
@@ -240,6 +270,9 @@ uint16 timer_get_count(uint8 timer_num) {
case 4:
timer = (Timer*)TIMER4_BASE;
break;
+ default:
+ ASSERT(0);
+ return;
}
return timer->CNT;
}
@@ -262,6 +295,9 @@ void timer_set_prescaler(uint8 timer_num, uint16 prescale) {
case 4:
timer = (Timer*)TIMER4_BASE;
break;
+ default:
+ ASSERT(0);
+ return;
}
timer->PSC = prescale;
}
@@ -285,6 +321,9 @@ void timer_set_reload(uint8 timer_num, uint16 max_reload) {
case 4:
timer = (Timer*)TIMER4_BASE;
break;
+ default:
+ ASSERT(0);
+ return;
}
timer->ARR = max_reload;
}
@@ -476,25 +515,25 @@ void timer_attach_interrupt(uint8 timer_num, uint8 compare_num, voidFuncPtr hand
case 1:
timer = (Timer*)TIMER1_BASE;
timer1_handlers[compare_num-1] = handler;
- nvic_enable_interrupt(27);
+ nvic_irq_enable(NVIC_TIMER1);
timer->DIER |= (1 << compare_num); // 1-indexed compare nums
break;
case 2:
timer = (Timer*)TIMER2_BASE;
timer2_handlers[compare_num-1] = handler;
- nvic_enable_interrupt(28);
+ nvic_irq_enable(NVIC_TIMER2);
timer->DIER |= (1 << compare_num); // 1-indexed compare nums
break;
case 3:
timer = (Timer*)TIMER3_BASE;
timer3_handlers[compare_num-1] = handler;
- nvic_enable_interrupt(29);
+ nvic_irq_enable(NVIC_TIMER3);
timer->DIER |= (1 << compare_num); // 1-indexed compare nums
break;
case 4:
timer = (Timer*)TIMER4_BASE;
timer4_handlers[compare_num-1] = handler;
- nvic_enable_interrupt(30);
+ nvic_irq_enable(NVIC_TIMER4);
timer->DIER |= (1 << compare_num); // 1-indexed compare nums
break;
}
diff --git a/libmaple/timers.h b/libmaple/timers.h
index c48ef42..c49a00e 100644
--- a/libmaple/timers.h
+++ b/libmaple/timers.h
@@ -89,6 +89,10 @@ typedef volatile uint32* TimerCCR;
#define TIMER2_BASE 0x40000000
#define TIMER3_BASE 0x40000400
#define TIMER4_BASE 0x40000800
+#define TIMER5_BASE 0x40000C00 // High-density devices only (Maple Native)
+#define TIMER6_BASE 0x40001000 // High-density devices only (Maple Native)
+#define TIMER7_BASE 0x40001400 // High-density devices only (Maple Native)
+#define TIMER8_BASE 0x40013400 // High-density devices only (Maple Native)
#define ARPE BIT(7) // Auto-reload preload enable
#define NOT_A_TIMER 0
@@ -116,6 +120,18 @@ typedef volatile uint32* TimerCCR;
#define TIMER4_CH3_CCR (TimerCCR)(TIMER4_BASE + 0x3C)
#define TIMER4_CH4_CCR (TimerCCR)(TIMER4_BASE + 0x40)
+// Timer5 and Timer8 are in high-density devices only (such as Maple Native).
+// Timer6 and Timer7 in these devices have no output compare pins.
+
+#define TIMER5_CH1_CCR (TimerCCR)(TIMER5_BASE + 0x34)
+#define TIMER5_CH2_CCR (TimerCCR)(TIMER5_BASE + 0x38)
+#define TIMER5_CH3_CCR (TimerCCR)(TIMER5_BASE + 0x3C)
+#define TIMER5_CH4_CCR (TimerCCR)(TIMER5_BASE + 0x40)
+
+#define TIMER8_CH1_CCR (TimerCCR)(TIMER8_BASE + 0x34)
+#define TIMER8_CH2_CCR (TimerCCR)(TIMER8_BASE + 0x38)
+#define TIMER8_CH3_CCR (TimerCCR)(TIMER8_BASE + 0x3C)
+#define TIMER8_CH4_CCR (TimerCCR)(TIMER8_BASE + 0x40)
#define TIMER_DISABLED 0
#define TIMER_PWM 1
diff --git a/libmaple/usart.c b/libmaple/usart.c
index 282fc5d..d08d3cf 100644
--- a/libmaple/usart.c
+++ b/libmaple/usart.c
@@ -36,123 +36,95 @@
#define USART1_BASE 0x40013800
#define USART2_BASE 0x40004400
#define USART3_BASE 0x40004800
+#define UART4_BASE 0x40004C00 // High-density devices only (Maple Native)
+#define UART5_BASE 0x40005000 // High-density devices only (Maple Native)
#define USART_UE BIT(13)
#define USART_M BIT(12)
#define USART_TE BIT(3)
#define USART_RE BIT(2)
#define USART_RXNEIE BIT(5) // read data register not empty interrupt enable
-#define USART_TXE BIT(7)
#define USART_TC BIT(6)
-#define USART_STOP_BITS_1 BIT_MASK_SHIFT(0b0, 12)
-#define USART_STOP_BITS_05 BIT_MASK_SHIFT(0b01, 12)
-#define USART_STOP_BITS_2 BIT_MASK_SHIFT(0b02, 12)
-#define USART_STOP_BITS_15 BIT_MASK_SHIFT(0b02, 12)
-
-#define USART1_CLK 72000000UL
-#define USART2_CLK 36000000UL
-#define USART3_CLK 36000000UL
-
-#define USART_RECV_BUF_SIZE 64
-
-/* Ring buffer notes:
- * The buffer is empty when head == tail.
- * The buffer is full when the head is one byte in front of the tail
- * The total buffer size must be a power of two
- * Note, one byte is necessarily left free with this scheme */
-typedef struct usart_ring_buf {
- uint32 head;
- uint32 tail;
- uint8 buf[USART_RECV_BUF_SIZE];
-} usart_ring_buf;
-
-static usart_ring_buf ring_buf1;
-static usart_ring_buf ring_buf2;
-static usart_ring_buf ring_buf3;
-
-typedef struct usart_port {
- volatile uint32 SR; // Status register
- volatile uint32 DR; // Data register
- volatile uint32 BRR; // Baud rate register
- volatile uint32 CR1; // Control register 1
- volatile uint32 CR2; // Control register 2
- volatile uint32 CR3; // Control register 3
- volatile uint32 GTPR; // Guard time and prescaler register
-} usart_port;
-
+/* usart descriptor table */
+struct usart_dev usart_dev_table[] = {
+ [USART1] = {
+ .base = (usart_port*)USART1_BASE,
+ .rcc_dev_num = RCC_USART1,
+ .nvic_dev_num = NVIC_USART1
+ },
+ [USART2] = {
+ .base = (usart_port*)USART2_BASE,
+ .rcc_dev_num = RCC_USART2,
+ .nvic_dev_num = NVIC_USART2
+ },
+ [USART3] = {
+ .base = (usart_port*)USART3_BASE,
+ .rcc_dev_num = RCC_USART3,
+ .nvic_dev_num = NVIC_USART3
+ },
+ #if NR_USART >= 5
+ [UART4] = {
+ .base = (usart_port*)UART4_BASE,
+ .rcc_dev_num = RCC_UART4,
+ .nvic_dev_num = NVIC_UART4
+ },
+ [UART5] = {
+ .base = (usart_port*)UART5_BASE,
+ .rcc_dev_num = RCC_UART5,
+ .nvic_dev_num = NVIC_UART5
+ },
+ #endif
+};
+
+/* usart interrupt handlers */
void USART1_IRQHandler(void) {
- /* Read the data */
- ring_buf1.buf[ring_buf1.tail++] = (uint8)(((usart_port*)(USART1_BASE))->DR);
- ring_buf1.tail %= USART_RECV_BUF_SIZE;
+ rb_insert(&(usart_dev_table[USART1].rb), (uint8)(((usart_port*)(USART1_BASE))->DR));
}
-/* Don't overrun your buffer, seriously */
void USART2_IRQHandler(void) {
- /* Read the data */
- ring_buf2.buf[ring_buf2.tail++] = (uint8)(((usart_port*)(USART2_BASE))->DR);
- ring_buf2.tail %= USART_RECV_BUF_SIZE;
+ rb_insert(&(usart_dev_table[USART2].rb), (uint8)(((usart_port*)(USART2_BASE))->DR));
}
-/* Don't overrun your buffer, seriously */
+
void USART3_IRQHandler(void) {
- /* Read the data */
- ring_buf3.buf[ring_buf3.tail++] = (uint8)(((usart_port*)(USART3_BASE))->DR);
- ring_buf3.tail %= USART_RECV_BUF_SIZE;
+ rb_insert(&usart_dev_table[USART3].rb, (uint8)(((usart_port*)(USART3_BASE))->DR));
+}
+#if NR_USART >= 5
+void UART4_IRQHandler(void) {
+ rb_insert(&usart_dev_table[UART4].rb, (uint8)(((usart_port*)(UART4_BASE))->DR));
}
+void UART5_IRQHandler(void) {
+ rb_insert(&usart_dev_table[UART5].rb, (uint8)(((usart_port*)(UART5_BASE))->DR));
+}
+#endif
/**
* @brief Enable a USART in single buffer transmission mode, multibuffer
- * receiver mode.
- *
+ * receiver mode.
* @param usart_num USART to be initialized
* @param baud Baud rate to be set at
- * @param recvBuf buf buffer for receiver
- * @param len size of recvBuf
- *
- * @sideeffect Turns on the specified USART
*/
void usart_init(uint8 usart_num, uint32 baud) {
- ASSERT((usart_num <= NR_USARTS) && (usart_num > 0));
- ASSERT(baud && (baud < USART_MAX_BAUD));
-
+ ASSERT(usart_num <= NR_USART);
usart_port *port;
- usart_ring_buf *ring_buf;
+ ring_buffer *ring_buf;
uint32 clk_speed;
uint32 integer_part;
uint32 fractional_part;
uint32 tmp;
- switch (usart_num) {
- case 1:
- port = (usart_port*)USART1_BASE;
- ring_buf = &ring_buf1;
- clk_speed = USART1_CLK;
- rcc_enable_clk_usart1();
- REG_SET(NVIC_ISER1, BIT(5));
- break;
- case 2:
- port = (usart_port*)USART2_BASE;
- ring_buf = &ring_buf2;
- clk_speed = USART2_CLK;
- rcc_enable_clk_usart2();
- REG_SET(NVIC_ISER1, BIT(6));
- break;
- case 3:
- port = (usart_port*)USART3_BASE;
- ring_buf = &ring_buf3;
- clk_speed = USART3_CLK;
- rcc_enable_clk_usart3();
- REG_SET(NVIC_ISER1, BIT(7));
- break;
- default:
- /* should never get here */
- ASSERT(0);
- }
+ port = usart_dev_table[usart_num].base;
+ rcc_clk_enable(usart_dev_table[usart_num].rcc_dev_num);
+ nvic_irq_enable(usart_dev_table[usart_num].nvic_dev_num);
+
+ /* usart1 is mad fast */
+ clk_speed = (usart_num == USART1) ? 72000000UL : 36000000UL;
- /* Initialize ring buffer */
- ring_buf->head = 0;
- ring_buf->tail = 0;
+ /* Initialize rx ring buffer */
+ rb_init(&usart_dev_table[usart_num].rb,
+ sizeof (usart_dev_table[usart_num].rx_buf),
+ usart_dev_table[usart_num].rx_buf);
/* Set baud rate */
integer_part = ((25 * clk_speed) / (4 * baud));
@@ -172,36 +144,25 @@ void usart_init(uint8 usart_num, uint32 baud) {
port->CR1 |= USART_UE;
}
+/**
+ * @brief Turn off all USARTs.
+ */
+void usart_disable_all() {
+ usart_disable(1);
+ usart_disable(2);
+ usart_disable(3);
+ #if NR_USART >= 5
+ usart_disable(4);
+ usart_disable(5);
+ #endif
+}
/**
* @brief Turn off a USART.
- *
* @param USART to be disabled
- *
- * @sideeffect Turns off the specified USART
*/
void usart_disable(uint8 usart_num) {
- ASSERT((usart_num <= NR_USARTS) && (usart_num > 0));
- usart_port *port;
-
- switch (usart_num) {
- case 1:
- port = (usart_port*)USART1_BASE;
- break;
- case 2:
- port = (usart_port*)USART2_BASE;
- break;
- case 3:
- port = (usart_port*)USART3_BASE;
- break;
- default:
- /* should never get here */
- ASSERT(0);
- }
-
- /* Is this usart enabled? */
- if (!(port->SR & USART_UE))
- return;
+ usart_port *port = usart_dev_table[usart_num].base;
/* TC bit must be high before disabling the usart */
while ((port->SR & USART_TC) == 0)
@@ -211,18 +172,17 @@ void usart_disable(uint8 usart_num) {
port->CR1 = 0;
/* Clean up buffer */
- usart_clear_buffer(usart_num);
+ usart_reset_rx(usart_num);
}
/**
* @brief Print a null terminated string to the specified USART
*
- * @param[in] usart_num USART to send on
- * @param[in] str String to send
+ * @param usart_num usart to send on
+ * @param str string to send
*/
void usart_putstr(uint8 usart_num, const char* str) {
- ASSERT((usart_num <= NR_USARTS) && (usart_num > 0));
char ch;
while((ch = *(str++)) != '\0') {
@@ -233,11 +193,10 @@ void usart_putstr(uint8 usart_num, const char* str) {
/**
* @brief Print an unsigned integer to the specified usart
*
- * @param[in] usart_num usart to send on
- * @param[in] val number to print
+ * @param usart_num usart to send on
+ * @param val number to print
*/
void usart_putudec(uint8 usart_num, uint32 val) {
- ASSERT((usart_num <= NR_USARTS) && (usart_num > 0));
char digits[12];
int i;
@@ -249,125 +208,4 @@ void usart_putudec(uint8 usart_num, uint32 val) {
while (--i >= 0) {
usart_putc(usart_num, digits[i]);
}
-
-}
-
-
-/**
- * @brief Return one character from the receive buffer. Assumes
- * that there is data available.
- *
- * @param[in] usart_num number of the usart to read from
- *
- * @return character from ring buffer
- *
- * @sideeffect may update the head pointer of the recv buffer
- */
-uint8 usart_getc(uint8 usart_num) {
- uint8 ch;
- usart_ring_buf *rb;
-
- switch (usart_num) {
- case 1:
- rb = &ring_buf1;
- break;
- case 2:
- rb = &ring_buf2;
- break;
- case 3:
- rb = &ring_buf3;
- break;
- default:
- ASSERT(0);
- }
-
- /* Make sure there's actually data to be read */
- ASSERT(rb->head != rb->tail);
-
- /* Read the data and check for wraparound */
- ch = rb->buf[rb->head++];
- rb->head %= USART_RECV_BUF_SIZE;
-
- return ch;
-}
-
-uint32 usart_data_available(uint8 usart_num) {
- usart_ring_buf *rb;
-
- switch (usart_num) {
- case 1:
- rb = &ring_buf1;
- break;
- case 2:
- rb = &ring_buf2;
- break;
- case 3:
- rb = &ring_buf3;
- break;
- default:
- ASSERT(0);
- }
-
- return rb->tail - rb->head;
-}
-
-void usart_clear_buffer(uint8 usart_num) {
- usart_ring_buf *rb;
-
- switch (usart_num) {
- case 1:
- rb = &ring_buf1;
- break;
- case 2:
- rb = &ring_buf2;
- break;
- case 3:
- rb = &ring_buf3;
- break;
- default:
- ASSERT(0);
- }
-
- rb->tail = rb->head;
-}
-
-
-
-/**
- * @brief Output a byte out the uart
- *
- * @param[in] usart_num usart number to output on
- * @param[in] byte byte to send
- *
- */
-void usart_putc(uint8 usart_num, uint8 byte) {
- ASSERT((usart_num <= NR_USARTS) && (usart_num > 0));
- usart_port *port;
-
- switch (usart_num) {
- case 1:
- port = (usart_port*)USART1_BASE;
- break;
- case 2:
- port = (usart_port*)USART2_BASE;
- break;
- case 3:
- port = (usart_port*)USART3_BASE;
- break;
- default:
- /* Should never get here */
- ASSERT(0);
- }
-
-// if (ch == '\n') {
-// usart_putc(usart_num, '\r');
-// }
-
- port->DR = byte;
-
- /* Wait for transmission to complete */
- while ((port->SR & USART_TXE) == 0)
- ;
}
-
-
diff --git a/libmaple/usart.h b/libmaple/usart.h
index 02fb6e0..2bc472f 100644
--- a/libmaple/usart.h
+++ b/libmaple/usart.h
@@ -23,32 +23,101 @@
* ****************************************************************************/
/**
- * @file usart.h
- *
- * @brief USART Definitions
+ * @brief USART definitions and prototypes
*/
#ifndef _USART_H_
#define _USART_H_
-#define NR_USARTS 0x3
+#include "ring_buffer.h"
#ifdef __cplusplus
extern "C"{
#endif
-#define USART_MAX_BAUD 225000
+#define USART_TXE BIT(7)
+
+/* usart device numbers */
+enum {
+ USART1,
+ USART2,
+ USART3,
+ UART4,
+ UART5,
+};
+
+/* peripheral register struct */
+typedef struct usart_port {
+ volatile uint32 SR; // Status register
+ volatile uint32 DR; // Data register
+ volatile uint32 BRR; // Baud rate register
+ volatile uint32 CR1; // Control register 1
+ volatile uint32 CR2; // Control register 2
+ volatile uint32 CR3; // Control register 3
+ volatile uint32 GTPR; // Guard time and prescaler register
+} usart_port;
+
+/* usart descriptor */
+struct usart_dev {
+ usart_port *base;
+ ring_buffer rb;
+ uint8 rx_buf[64];
+ const uint8 rcc_dev_num;
+ const uint8 nvic_dev_num;
+};
+
+extern struct usart_dev usart_dev_table[];
+
+
+/**
+ * @brief send one character on a usart
+ * @param usart_num usart to send on
+ * @param byte byte to send
+ */
+static inline void usart_putc(uint8 usart_num, uint8 byte) {
+ usart_port *port = usart_dev_table[usart_num].base;
+
+ port->DR = byte;
+
+ /* Wait for transmission to complete */
+ while ((port->SR & USART_TXE) == 0)
+ ;
+}
+
+
+/**
+ * @brief read one character from a usart
+ * @param usart_num usart to read from
+ * @return byte read
+ */
+static inline uint8 usart_getc(uint8 usart_num) {
+ return rb_remove(&usart_dev_table[usart_num].rb);
+}
+
+
+/**
+ * @brief return the amount of data available in the rx buffer
+ * @param usart_num which usart to check
+ * @return number of bytes in the rx buffer
+ */
+static inline uint32 usart_data_available(uint8 usart_num) {
+ return rb_full_count(&usart_dev_table[usart_num].rb);
+}
+
+
+/**
+ * @brief removes the contents of the rx fifo
+ * @param usart_num which usart to reset
+ */
+static inline void usart_reset_rx(uint8 usart_num) {
+ rb_reset(&usart_dev_table[usart_num].rb);
+}
void usart_init(uint8 usart_num, uint32 baud);
void usart_disable(uint8 usart_num);
-
+void usart_disable_all();
void usart_putstr(uint8 usart_num, const char*);
void usart_putudec(uint8 usart_num, uint32 val);
-void usart_putc(uint8 usart_num, uint8 ch);
-
-uint32 usart_data_available(uint8 usart_num);
-uint8 usart_getc(uint8 usart_num);
-void usart_clear_buffer(uint8 usart_num);
#ifdef __cplusplus
} // extern "C"
diff --git a/libmaple/usb/descriptors.h b/libmaple/usb/descriptors.h
index 1efe8c1..6652942 100644
--- a/libmaple/usb/descriptors.h
+++ b/libmaple/usb/descriptors.h
@@ -16,7 +16,7 @@
#define USB_DEVICE_SUBCLASS_CDC 0x00
#define USB_CONFIG_ATTR_BUSPOWERED 0b10000000
-#define USB_CONFIG_ATTR_SELF_POWERED 0b11000000
+#define USB_CONFIG_ATTR_SELF_POWERED 0b11000000
#define EP_TYPE_INTERRUPT 0x03
#define EP_TYPE_BULK 0x02
diff --git a/libmaple/usb/usb_config.h b/libmaple/usb/usb_config.h
index 9f6b600..27294dc 100644
--- a/libmaple/usb/usb_config.h
+++ b/libmaple/usb/usb_config.h
@@ -5,12 +5,6 @@
#include "usb_lib.h"
-#define VCOM_ID_VENDOR 0x1EAF
-#define VCOM_ID_PRODUCT 0x0004
-
-#define USB_CONFIG_MAX_POWER (100 >> 1)
-#define RESET_DELAY (100)
-
/* choose addresses to give endpoints the max 64 byte buffers */
#define USB_BTABLE_ADDRESS 0x00
#define VCOM_CTRL_EPNUM 0x00
diff --git a/libmaple/usb/usb_hardware.h b/libmaple/usb/usb_hardware.h
index 208fa3a..e4a26b4 100644
--- a/libmaple/usb/usb_hardware.h
+++ b/libmaple/usb/usb_hardware.h
@@ -30,7 +30,6 @@
/* macro'd register and peripheral definitions */
#define EXC_RETURN 0xFFFFFFF9
#define DEFAULT_CPSR 0x61000000
-#define STACK_TOP 0x20005000
#define RCC ((u32)0x40021000)
#define FLASH ((u32)0x40022000)
diff --git a/libmaple/util.c b/libmaple/util.c
index 8c25257..61beab8 100644
--- a/libmaple/util.c
+++ b/libmaple/util.c
@@ -36,13 +36,6 @@
#include "adc.h"
#include "timers.h"
-#define ERROR_LED_PORT GPIOC_BASE
-#define ERROR_LED_PIN 15
-#define ERROR_USART_NUM 1
-#define ERROR_USART_BAUD 9600
-#define ERROR_TX_PIN 10
-#define ERROR_TX_PORT GPIOA_BASE
-
/* Error assert + fade */
void _fail(const char* file, int line, const char* exp) {
int32 slope = 1;
@@ -60,9 +53,7 @@ void _fail(const char* file, int line, const char* exp) {
adc_disable();
/* Turn off all usarts */
- usart_disable(1);
- usart_disable(2);
- usart_disable(3);
+ usart_disable_all();
/* Initialize the error usart */
gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_MODE_AF_OUTPUT_PP);
diff --git a/libmaple/util.h b/libmaple/util.h
index 1aae7bd..053731a 100644
--- a/libmaple/util.h
+++ b/libmaple/util.h
@@ -32,8 +32,6 @@
#ifndef _UTIL_H_
#define _UTIL_H_
-#define MAPLE_DEBUG 1
-
#define BIT(shift) (1 << (shift))
#define BIT_MASK_SHIFT(mask, shift) ((mask) << (shift))
@@ -41,16 +39,9 @@
#define GET_BITS(x, m, n) ((((uint32)x) << (31 - (n))) >> ((31 - (n)) + (m)))
/* Bit-banding macros */
-#define BITBAND_SRAM_REF 0x20000000
-#define BITBAND_SRAM_BASE 0x22000000
#define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE + (a-BITBAND_SRAM_REF)*32 + (b*4))) // Convert SRAM address
-#define BITBAND_PERI_REF 0x40000000
-#define BITBAND_PERI_BASE 0x42000000
#define BITBAND_PERI(a,b) ((BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 + (b*4))) // Convert PERI address
-
-#define COUNTFLAG *((volatile unsigned char*) (BITBAND_PERI(SYSTICK_CSR,2)))
-
#define REG_SET(reg, val) (*(volatile uint32*)(reg) = (val))
#define REG_SET_BIT(reg, bit) (*(volatile uint32*)(reg) |= BIT(bit))
#define REG_CLEAR_BIT(reg, bit) (*(volatile uint32*)(reg) &= ~BIT(bit))
@@ -66,6 +57,8 @@
#define __read(reg) *(volatile uint32*)(reg)
#define __write(reg, value) *(volatile uint32*)(reg) = (value)
+#define IS_POWER_OF_TWO(v) (v && !(v & (v - 1)))
+
#ifdef __cplusplus
extern "C"{
#endif
diff --git a/notes/pin-mapping.txt b/notes/pin-mapping.txt
index e6debf7..67a675c 100644
--- a/notes/pin-mapping.txt
+++ b/notes/pin-mapping.txt
@@ -7,6 +7,7 @@ PA15 JTDI
PB2 BOOT1
PB3 JTDO
PB4 JTRST
+PC9 BUT button
PC11 USB_P
PC12 DISC
PD0 OSC_IN
@@ -59,9 +60,9 @@ D34 PB15 - TIM1_CH3N - - SPI2_MOSI Y
D35 PC6 - - - - - Y
D36 PC7 - - - - - Y
D37 PC8 - - - - - Y
-D38 PC9 - - - - - Y
-------------------------------------------------------------------------------
-
+Note: former pin D38 (PC9) is now attached to the BUT button and there is a
+GND connection where D38 was.
todo:
adc pin check
diff --git a/notes/portable.txt b/notes/portable.txt
new file mode 100644
index 0000000..69952d7
--- /dev/null
+++ b/notes/portable.txt
@@ -0,0 +1,100 @@
+
+Disclaimer text: // High-density devices only (Maple Native)
+
+
+Board portability is implemented by adding a header file to ./libmaple with the
+name of the BOARD target, and then editing libmaple.h to add this file as an
+option.
+
+A pin maple file should be added to ./notes describing the pin numbering
+
+Files to check by hand:
+# adc.c
+# adc.h
+# exc.c
+# exti.c
+# exti.h
+# flash.c
+# flash.h
+# gpio.c
+# gpio.h
+# libmaple_types.h
+# nvic.c
+# nvic.h
+# rcc.c
+# rcc.h
+# ring_buffer.h
+# rules.mk
+# spi.c
+- spi.h
+# syscalls.c
+# systick.c
+# systick.h
+# timers.c
+# timers.h
+# usart.c
+# usart.h
+# util.c
+# util.h
+# libmaple.h
+# usb/*
+
+wirish/:
+# bits.h
+# boards.h
+# cxxabi-compat.cpp
+# ext_interrupts.c
+# ext_interrupts.h
+# HardwareTimer.cpp
+# HardwareTimer.h
+# io.h
+# main.cxx
+# Print.cpp
+# Print.h
+# pwm.c
+# pwm.h
+# rules.mk
+# time.c
+# time.h
+# usb_serial.cpp
+# usb_serial.h
+# wirish_analog.c
+# wirish.c
+# wirish_digital.c
+# wirish.h
+# wirish_math.cpp
+# wirish_math.h
+# wirish_shift.c
+# WProgram.h
+- comm/
+
+
+
+ADC Notes:
+ only using ADC1?
+ untested
+
+EXTI Notes:
+ need to update huge table in comments?
+ untested
+
+NVIC Notes:
+ I don't think NVIC_ISER3 and NVIC_ICER3 actually exist?
+ Only CANBUS and USB OTG use interrupts above #63, but I updated the nvic code anyways
+
+RCC Notes:
+ Added some clock stuff to all boards even though they aren't usable... blah.
+
+SPI Notes:
+ SPI3 is only in XL chips so didn't really handle that
+
+TIMER Notes:
+ High-density devices add an advanced timer (TIMER8) and another normal one (TIMER5).
+ TIMER6 and TIMER7 are much less useful.
+ There is some partial progress towards adding timer5/timer8 functionality,
+ but not much. This should probably all be rewritten.
+ The wirish timer implementation should be refactored to use pin numbers.
+
+USART Notes:
+ The USART/UART nomeclature is a little mixed up.
+ TODO: portability of HardwareSerial, HardwareSPI
diff --git a/support/ld/flash.ld b/support/ld/flash.ld
index 473f5a1..7e1e453 100644
--- a/support/ld/flash.ld
+++ b/support/ld/flash.ld
@@ -33,7 +33,7 @@ OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
ENTRY(_start)
SEARCH_DIR(.)
/* GROUP(-lgcc -lc -lcs3 -lcs3unhosted -lcs3-lanchon-stm32) */
-GROUP(libgcc.a libc.a libcs3-lanchon-stm32.a)
+GROUP(libgcc.a libc.a libm.a libcs3-lanchon-stm32.a)
/* These force the linker to search for particular symbols from
* the start of the link process and thus ensure the user's
diff --git a/support/ld/jtag.ld b/support/ld/jtag.ld
index 64d049d..890f18a 100644
--- a/support/ld/jtag.ld
+++ b/support/ld/jtag.ld
@@ -16,7 +16,7 @@ OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
ENTRY(_start)
SEARCH_DIR(.)
/* GROUP(-lgcc -lc -lcs3 -lcs3unhosted -lcs3-lanchon-stm32) */
-GROUP(libgcc.a libc.a libcs3-lanchon-stm32.a)
+GROUP(libgcc.a libc.a libm.a libcs3-lanchon-stm32.a)
/* These force the linker to search for particular symbols from
* the start of the link process and thus ensure the user's
diff --git a/support/ld/ram.ld b/support/ld/ram.ld
index d2c05c0..168c1da 100644
--- a/support/ld/ram.ld
+++ b/support/ld/ram.ld
@@ -34,7 +34,7 @@ OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
ENTRY(_start)
SEARCH_DIR(.)
/* GROUP(-lgcc -lc -lcs3 -lcs3unhosted -lcs3-lanchon-stm32) */
-GROUP(libgcc.a libc.a libcs3-lanchon-stm32.a)
+GROUP(libgcc.a libc.a libm.a libcs3-lanchon-stm32.a)
/* These force the linker to search for particular symbols from
* the start of the link process and thus ensure the user's
diff --git a/support/make/build-targets.mk b/support/make/build-targets.mk
index 01097a7..083976a 100644
--- a/support/make/build-targets.mk
+++ b/support/make/build-targets.mk
@@ -15,7 +15,7 @@ $(BUILD_PATH)/$(BOARD).bin: $(BUILD_PATH)/$(BOARD).elf
@echo " "
@echo "Final Size:"
@$(SIZE) $<
- @echo $(MAPLE_TARGET) > $(BUILD_PATH)/build-type
+ @echo $(MEMORY_TARGET) > $(BUILD_PATH)/build-type
$(BUILDDIRS):
@mkdir -p $@
@@ -25,7 +25,7 @@ MSG_INFO:
@echo ""
@echo " Build info:"
@echo " BOARD:" $(BOARD)
- @echo " MAPLE_TARGET:" $(MAPLE_TARGET)
+ @echo " MEMORY_TARGET:" $(MEMORY_TARGET)
@echo ""
@echo " See 'make help' for all possible targets"
@echo ""
diff --git a/support/stm32loader.py b/support/stm32loader.py
new file mode 100755
index 0000000..f717c9a
--- /dev/null
+++ b/support/stm32loader.py
@@ -0,0 +1,435 @@
+#!/usr/bin/env python
+
+# -*- coding: utf-8 -*-
+# vim: sw=4:ts=4:si:et:enc=utf-8
+
+# Author: Ivan A-R <ivan@tuxotronic.org>
+# Project page: http://tuxotronic.org/wiki/projects/stm32loader
+#
+# This file is part of stm32loader.
+#
+# stm32loader is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 3, or (at your option) any later
+# version.
+#
+# stm32loader 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 General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with stm32loader; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+import sys, getopt
+import serial
+import time
+
+try:
+ from progressbar import *
+ usepbar = 1
+except:
+ usepbar = 0
+
+# Verbose level
+QUIET = 20
+
+def mdebug(level, message):
+ if(QUIET >= level):
+ print >> sys.stderr , message
+
+
+class CmdException(Exception):
+ pass
+
+class CommandInterface:
+ def open(self, aport='/dev/tty.usbserial-FTD3TMCH', abaudrate=115200) :
+ self.sp = serial.Serial(
+ port=aport,
+ baudrate=abaudrate, # baudrate
+ bytesize=8, # number of databits
+ parity=serial.PARITY_EVEN,
+ stopbits=1,
+ xonxoff=0, # enable software flow control
+ rtscts=0, # disable RTS/CTS flow control
+ timeout=5 # set a timeout value, None for waiting forever
+ )
+
+
+ def _wait_for_ask(self, info = ""):
+ # wait for ask
+ try:
+ ask = ord(self.sp.read())
+ except:
+ raise CmdException("Can't read port or timeout")
+ else:
+ if ask == 0x79:
+ # ACK
+ return 1
+ else:
+ if ask == 0x1F:
+ # NACK
+ raise CmdException("NACK "+info)
+ else:
+ # Unknow responce
+ raise CmdException("Unknow response. "+info+": "+hex(ask))
+
+
+ def reset(self):
+ self.sp.setDTR(0)
+ time.sleep(0.1)
+ self.sp.setDTR(1)
+ time.sleep(0.5)
+
+ def initChip(self):
+ # Set boot
+ self.sp.setRTS(0)
+ self.reset()
+
+ self.sp.write("\x7F") # Syncro
+ return self._wait_for_ask("Syncro")
+
+ def releaseChip(self):
+ self.sp.setRTS(1)
+ self.reset()
+
+ def cmdGeneric(self, cmd):
+ self.sp.write(chr(cmd))
+ self.sp.write(chr(cmd ^ 0xFF)) # Control byte
+ return self._wait_for_ask(hex(cmd))
+
+ def cmdGet(self):
+ if self.cmdGeneric(0x00):
+ mdebug(10, "*** Get command");
+ len = ord(self.sp.read())
+ version = ord(self.sp.read())
+ mdebug(10, " Bootloader version: "+hex(version))
+ dat = map(lambda c: hex(ord(c)), self.sp.read(len))
+ mdebug(10, " Available commands: "+str(dat))
+ self._wait_for_ask("0x00 end")
+ return version
+ else:
+ raise CmdException("Get (0x00) failed")
+
+ def cmdGetVersion(self):
+ if self.cmdGeneric(0x01):
+ mdebug(10, "*** GetVersion command")
+ version = ord(self.sp.read())
+ self.sp.read(2)
+ self._wait_for_ask("0x01 end")
+ mdebug(10, " Bootloader version: "+hex(version))
+ return version
+ else:
+ raise CmdException("GetVersion (0x01) failed")
+
+ def cmdGetID(self):
+ if self.cmdGeneric(0x02):
+ mdebug(10, "*** GetID command")
+ len = ord(self.sp.read())
+ id = self.sp.read(len+1)
+ self._wait_for_ask("0x02 end")
+ return id
+ else:
+ raise CmdException("GetID (0x02) failed")
+
+
+ def _encode_addr(self, addr):
+ byte3 = (addr >> 0) & 0xFF
+ byte2 = (addr >> 8) & 0xFF
+ byte1 = (addr >> 16) & 0xFF
+ byte0 = (addr >> 24) & 0xFF
+ crc = byte0 ^ byte1 ^ byte2 ^ byte3
+ return (chr(byte0) + chr(byte1) + chr(byte2) + chr(byte3) + chr(crc))
+
+
+ def cmdReadMemory(self, addr, lng):
+ assert(lng <= 256)
+ if self.cmdGeneric(0x11):
+ mdebug(10, "*** ReadMemory command")
+ self.sp.write(self._encode_addr(addr))
+ self._wait_for_ask("0x11 address failed")
+ N = (lng - 1) & 0xFF
+ crc = N ^ 0xFF
+ self.sp.write(chr(N) + chr(crc))
+ self._wait_for_ask("0x11 length failed")
+ return map(lambda c: ord(c), self.sp.read(lng))
+ else:
+ raise CmdException("ReadMemory (0x11) failed")
+
+
+ def cmdGo(self, addr):
+ if self.cmdGeneric(0x21):
+ mdebug(10, "*** Go command")
+ self.sp.write(self._encode_addr(addr))
+ self._wait_for_ask("0x21 go failed")
+ else:
+ raise CmdException("Go (0x21) failed")
+
+
+ def cmdWriteMemory(self, addr, data):
+ assert(len(data) <= 256)
+ if self.cmdGeneric(0x31):
+ mdebug(10, "*** Write memory command")
+ self.sp.write(self._encode_addr(addr))
+ self._wait_for_ask("0x31 address failed")
+ #map(lambda c: hex(ord(c)), data)
+ lng = (len(data)-1) & 0xFF
+ mdebug(10, " %s bytes to write" % [lng+1]);
+ self.sp.write(chr(lng)) # len really
+ crc = 0xFF
+ for c in data:
+ crc = crc ^ c
+ self.sp.write(chr(c))
+ self.sp.write(chr(crc))
+ self._wait_for_ask("0x31 programming failed")
+ mdebug(10, " Write memory done")
+ else:
+ raise CmdException("Write memory (0x31) failed")
+
+
+ def cmdEraseMemory(self, sectors = None):
+ if self.cmdGeneric(0x43):
+ mdebug(10, "*** Erase memory command")
+ if sectors is None:
+ # Global erase
+ self.sp.write(chr(0xFF))
+ self.sp.write(chr(0x00))
+ else:
+ # Sectors erase
+ self.sp.write(chr((len(sectors)-1) & 0xFF))
+ crc = 0xFF
+ for c in sectors:
+ crc = crc ^ c
+ self.sp.write(chr(c))
+ self.sp.write(chr(crc))
+ self._wait_for_ask("0x43 erasing failed")
+ mdebug(10, " Erase memory done")
+ else:
+ raise CmdException("Erase memory (0x43) failed")
+
+ def cmdWriteProtect(self, sectors):
+ if self.cmdGeneric(0x63):
+ mdebug(10, "*** Write protect command")
+ self.sp.write(chr((len(sectors)-1) & 0xFF))
+ crc = 0xFF
+ for c in sectors:
+ crc = crc ^ c
+ self.sp.write(chr(c))
+ self.sp.write(chr(crc))
+ self._wait_for_ask("0x63 write protect failed")
+ mdebug(10, " Write protect done")
+ else:
+ raise CmdException("Write Protect memory (0x63) failed")
+
+ def cmdWriteUnprotect(self):
+ if self.cmdGeneric(0x73):
+ mdebug(10, "*** Write Unprotect command")
+ self._wait_for_ask("0x73 write unprotect failed")
+ self._wait_for_ask("0x73 write unprotect 2 failed")
+ mdebug(10, " Write Unprotect done")
+ else:
+ raise CmdException("Write Unprotect (0x73) failed")
+
+ def cmdReadoutProtect(self):
+ if self.cmdGeneric(0x82):
+ mdebug(10, "*** Readout protect command")
+ self._wait_for_ask("0x82 readout protect failed")
+ self._wait_for_ask("0x82 readout protect 2 failed")
+ mdebug(10, " Read protect done")
+ else:
+ raise CmdException("Readout protect (0x82) failed")
+
+ def cmdReadoutUnprotect(self):
+ if self.cmdGeneric(0x92):
+ mdebug(10, "*** Readout Unprotect command")
+ self._wait_for_ask("0x92 readout unprotect failed")
+ self._wait_for_ask("0x92 readout unprotect 2 failed")
+ mdebug(10, " Read Unprotect done")
+ else:
+ raise CmdException("Readout unprotect (0x92) failed")
+
+
+# Complex commands section
+
+ def readMemory(self, addr, lng):
+ data = []
+ if usepbar:
+ widgets = ['Reading: ', Percentage(),', ', ETA(), ' ', Bar()]
+ pbar = ProgressBar(widgets=widgets,maxval=lng, term_width=79).start()
+
+ while lng > 256:
+ if usepbar:
+ pbar.update(pbar.maxval-lng)
+ else:
+ mdebug(5, "Read %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256})
+ data = data + self.cmdReadMemory(addr, 256)
+ addr = addr + 256
+ lng = lng - 256
+ if usepbar:
+ pbar.update(pbar.maxval-lng)
+ pbar.finish()
+ else:
+ mdebug(5, "Read %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256})
+ data = data + self.cmdReadMemory(addr, lng)
+ return data
+
+ def writeMemory(self, addr, data):
+ lng = len(data)
+ if usepbar:
+ widgets = ['Writing: ', Percentage(),' ', ETA(), ' ', Bar()]
+ pbar = ProgressBar(widgets=widgets, maxval=lng, term_width=79).start()
+
+ offs = 0
+ while lng > 256:
+ if usepbar:
+ pbar.update(pbar.maxval-lng)
+ else:
+ mdebug(5, "Write %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256})
+ self.cmdWriteMemory(addr, data[offs:offs+256])
+ offs = offs + 256
+ addr = addr + 256
+ lng = lng - 256
+ if usepbar:
+ pbar.update(pbar.maxval-lng)
+ pbar.finish()
+ else:
+ mdebug(5, "Write %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256})
+ self.cmdWriteMemory(addr, data[offs:offs+lng] + ([0xFF] * (256-lng)) )
+
+
+
+
+ def __init__(self) :
+ pass
+
+
+def usage():
+ print """Usage: %s [-hqVewvr] [-l length] [-p port] [-b baud] [-a addr] [file.bin]
+ -h This help
+ -q Quiet
+ -V Verbose
+ -e Erase
+ -w Write
+ -v Verify
+ -r Read
+ -l length Length of read
+ -p port Serial port (default: /dev/tty.usbserial-ftCYPMYJ)
+ -b baud Baud speed (default: 115200)
+ -a addr Target address
+
+ ./stm32loader.py -e -w -v example/main.bin
+
+ """ % sys.argv[0]
+
+
+if __name__ == "__main__":
+
+ # Import Psyco if available
+ try:
+ import psyco
+ psyco.full()
+ print "Using Psyco..."
+ except ImportError:
+ pass
+
+ conf = {
+ 'port': '/dev/tty.usbserial-FTD3TMCH',
+ 'baud': 115200,
+ 'address': 0x08000000,
+ 'erase': 0,
+ 'write': 0,
+ 'verify': 0,
+ 'read': 0,
+ 'len': 1000,
+ 'fname':'',
+ }
+
+# http://www.python.org/doc/2.5.2/lib/module-getopt.html
+
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "hqVewvrp:b:a:l:")
+ except getopt.GetoptError, err:
+ # print help information and exit:
+ print str(err) # will print something like "option -a not recognized"
+ usage()
+ sys.exit(2)
+
+ QUIET = 5
+
+ for o, a in opts:
+ if o == '-V':
+ QUIET = 10
+ elif o == '-q':
+ QUIET = 0
+ elif o == '-h':
+ usage()
+ sys.exit(0)
+ elif o == '-e':
+ conf['erase'] = 1
+ elif o == '-w':
+ conf['write'] = 1
+ elif o == '-v':
+ conf['verify'] = 1
+ elif o == '-r':
+ conf['read'] = 1
+ elif o == '-p':
+ conf['port'] = a
+ elif o == '-b':
+ conf['baud'] = eval(a)
+ elif o == '-a':
+ conf['address'] = eval(a)
+ elif o == '-l':
+ conf['len'] = eval(a)
+# elif o == '-f':
+# conf['fname'] = a
+ else:
+ assert False, "unhandled option"
+
+ cmd = CommandInterface()
+ cmd.open(conf['port'], conf['baud'])
+ mdebug(10, "Open port %(port)s, baud %(baud)d" % {'port':conf['port'], 'baud':conf['baud']})
+ try:
+ try:
+ cmd.initChip()
+ except:
+ print "Can't init. Ensure that BOOT0 is enabled and reset device"
+
+ bootversion = cmd.cmdGet()
+ mdebug(0, "Bootloader version %X" % bootversion)
+ mdebug(0, "Chip id `%s'" % str(map(lambda c: hex(ord(c)), cmd.cmdGetID())))
+# cmd.cmdGetVersion()
+# cmd.cmdGetID()
+# cmd.cmdReadoutUnprotect()
+# cmd.cmdWriteUnprotect()
+# cmd.cmdWriteProtect([0, 1])
+
+ if (conf['write'] or conf['verify']):
+ data = map(lambda c: ord(c), file(args[0]).read())
+
+ if conf['erase']:
+ cmd.cmdEraseMemory()
+
+ if conf['write']:
+ cmd.writeMemory(conf['address'], data)
+
+ if conf['verify']:
+ verify = cmd.readMemory(conf['address'], len(data))
+ if(data == verify):
+ print "Verification OK"
+ else:
+ print "Verification FAILED"
+ print str(len(data)) + ' vs ' + str(len(verify))
+ for i in xrange(0, len(data)):
+ if data[i] != verify[i]:
+ print hex(i) + ': ' + hex(data[i]) + ' vs ' + hex(verify[i])
+
+ if not conf['write'] and conf['read']:
+ rdata = cmd.readMemory(conf['address'], conf['len'])
+# file(conf['fname'], 'wb').write(rdata)
+ file(args[0], 'wb').write(''.join(map(chr,rdata)))
+
+# cmd.cmdGo(addr + 0x04)
+ finally:
+ cmd.releaseChip()
+
diff --git a/wirish/HardwareTimer.cpp b/wirish/HardwareTimer.cpp
index 3c8e9f4..5675948 100644
--- a/wirish/HardwareTimer.cpp
+++ b/wirish/HardwareTimer.cpp
@@ -32,10 +32,7 @@
#include "HardwareTimer.h"
HardwareTimer::HardwareTimer(uint8 timerNum) {
- ASSERT(timerNum == 1 ||
- timerNum == 2 ||
- timerNum == 3 ||
- timerNum == 4);
+ ASSERT(timerNum < NR_TIMERS);
this->timerNum = timerNum;
// Need to remember over flow for bounds checking
this->overflow = 0xFFFF;
@@ -141,9 +138,43 @@ void HardwareTimer::detachCompare3Interrupt(void) {
void HardwareTimer::detachCompare4Interrupt(void) {
timer_detach_interrupt(this->timerNum,4);
}
+#if NR_TIMERS >= 8
+void HardwareTimer::setChannel5Mode(uint8 mode) {
+ timer_set_mode(this->timerNum,5,mode);
+}
+void HardwareTimer::setChannel8Mode(uint8 mode) {
+ timer_set_mode(this->timerNum,8,mode);
+}
+void HardwareTimer::setCompare5(uint16 val) {
+ if(val > this->overflow)
+ val = this->overflow;
+ timer_set_compare_value(this->timerNum,5,val);
+}
+void HardwareTimer::setCompare8(uint16 val) {
+ if(val > this->overflow)
+ val = this->overflow;
+ timer_set_compare_value(this->timerNum,8,val);
+}
+void HardwareTimer::attachCompare5Interrupt(voidFuncPtr handler) {
+ timer_attach_interrupt(this->timerNum,5,handler);
+}
+void HardwareTimer::attachCompare8Interrupt(voidFuncPtr handler) {
+ timer_attach_interrupt(this->timerNum,8,handler);
+}
+void HardwareTimer::detachCompare5Interrupt(void) {
+ timer_detach_interrupt(this->timerNum,5);
+}
+void HardwareTimer::detachCompare8Interrupt(void) {
+ timer_detach_interrupt(this->timerNum,8);
+}
+#endif
HardwareTimer Timer1(1);
HardwareTimer Timer2(2);
HardwareTimer Timer3(3);
HardwareTimer Timer4(4);
+#if NR_TIMERS >= 8
+HardwareTimer Timer5(5); // High-density devices only
+HardwareTimer Timer8(8); // High-density devices only
+#endif
diff --git a/wirish/HardwareTimer.h b/wirish/HardwareTimer.h
index c79f54f..3f986e4 100644
--- a/wirish/HardwareTimer.h
+++ b/wirish/HardwareTimer.h
@@ -62,12 +62,26 @@ class HardwareTimer {
void detachCompare2Interrupt(void);
void detachCompare3Interrupt(void);
void detachCompare4Interrupt(void);
+ #if NR_TIMERS >= 8
+ void setChannel5Mode(uint8 mode);
+ void setChannel8Mode(uint8 mode);
+ void setCompare5(uint16 val); // truncates to overflow
+ void setCompare8(uint16 val); // truncates to overflow
+ void attachCompare5Interrupt(voidFuncPtr handler);
+ void attachCompare8Interrupt(voidFuncPtr handler);
+ void detachCompare5Interrupt(void);
+ void detachCompare8Interrupt(void);
+ #endif
};
extern HardwareTimer Timer1;
extern HardwareTimer Timer2;
extern HardwareTimer Timer3;
extern HardwareTimer Timer4;
+#if NR_TIMERS >= 8
+extern HardwareTimer Timer5;
+extern HardwareTimer Timer8;
+#endif
#endif
diff --git a/wirish/boards.h b/wirish/boards.h
new file mode 100644
index 0000000..035868a
--- /dev/null
+++ b/wirish/boards.h
@@ -0,0 +1,219 @@
+/* *****************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 Bryan Newbold.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ * ****************************************************************************/
+
+// This file contains BOARD-specific pin mapping tables. To add a new board
+// type, copy the "BOARD_maple" section below and edit it as needed, then
+// update your build toolchain with a new "BOARD" type. This must match the
+// seperate MCU type (which determines the ../libmaple configuration).
+
+#ifndef _BOARDS_H_
+#define _BOARDS_H_
+
+#include "libmaple.h"
+#include "gpio.h"
+#include "timers.h"
+#include "exti.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+// Set of all possible digital pin names; not all boards have all these
+enum {
+ D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, D16,
+ D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31,
+ D32, D33, D34, D35, D36, D37, D38, D39, D40, D41, D42, D43, D44, D45, D46,
+ D47, D48, D49, D50, D51, D52, D53, D54, D55, D56, D57, D58, D59, D60, D61,
+ D62, D63, D64, D65, D66, D67, D68, D69, D70, D71, D72, D73, D74, D75, D76,
+ D77, D78, D79, D80, D81, D82, D83, D84, D85, D86, D87, D88, D89, D90, D91,
+ D92, D93, D94, D95, D96, D97, D98, D99, D100, D101, D102, D103, D104, D105,
+ D106, D107, D108, D109, D110, D111, };
+
+// Set of all possible analog pin names; not all boards have all these
+enum {
+ ADC0, ADC1, ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, ADC10, ADC11,
+ ADC12, ADC13, ADC14, ADC15, ADC16, ADC17, ADC18, ADC19, ADC20, };
+
+#define ADC_INVALID 0xFFFFFFFF
+#define TIMER_INVALID (TimerCCR)0xFFFFFFFF
+
+// Types used for the tables below
+typedef struct PinMapping {
+ GPIO_Port *port;
+ uint32 pin;
+ uint32 adc;
+ TimerCCR timer_channel;
+} PinMapping;
+
+typedef struct ExtiInfo {
+ uint8 channel;
+ uint8 port;
+} ExtiInfo;
+
+// LeafLabs Maple rev3, rev4
+#ifdef BOARD_maple
+
+ #define CYCLES_PER_MICROSECOND 72
+
+ static PinMapping PIN_MAP[NR_GPIO_PINS] = {
+ {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR}, // D0/PA3
+ {GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR}, // D1/PA2
+ {GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR}, // D2/PA0
+ {GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR}, // D3/PA1
+ {GPIOB_BASE, 5, ADC_INVALID, TIMER_INVALID}, // D4/PB5
+ {GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR}, // D5/PB6
+ {GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR}, // D6/PA8
+ {GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR}, // D7/PA9
+ {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR}, // D8/PA10
+ {GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR}, // D9/PB7
+ {GPIOA_BASE, 4, ADC4, TIMER_INVALID}, // D10/PA4
+ {GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR}, // D11/PA7
+ {GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR}, // D12/PA6
+ {GPIOA_BASE, 5, ADC5, TIMER_INVALID}, // D13/PA5
+ {GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR}, // D14/PB8
+ /* Little header */
+ {GPIOC_BASE, 0, ADC10, TIMER_INVALID}, // D15/PC0
+ {GPIOC_BASE, 1, ADC11, TIMER_INVALID}, // D16/PC1
+ {GPIOC_BASE, 2, ADC12, TIMER_INVALID}, // D17/PC2
+ {GPIOC_BASE, 3, ADC13, TIMER_INVALID}, // D18/PC3
+ {GPIOC_BASE, 4, ADC14, TIMER_INVALID}, // D19/PC4
+ {GPIOC_BASE, 5, ADC15, TIMER_INVALID}, // D20/PC5
+ /* External header */
+ {GPIOC_BASE, 13, ADC_INVALID, TIMER_INVALID}, // D21/PC13
+ {GPIOC_BASE, 14, ADC_INVALID, TIMER_INVALID}, // D22/PC14
+ {GPIOC_BASE, 15, ADC_INVALID, TIMER_INVALID}, // D23/PC15
+ {GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR}, // D24/PB9
+ {GPIOD_BASE, 2, ADC_INVALID, TIMER_INVALID}, // D25/PD2
+ {GPIOC_BASE, 10, ADC_INVALID, TIMER_INVALID}, // D26/PC10
+ {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR}, // D27/PB0
+ {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR}, // D28/PB1
+ {GPIOB_BASE, 10, ADC_INVALID, TIMER_INVALID}, // D29/PB10
+ {GPIOB_BASE, 11, ADC_INVALID, TIMER_INVALID}, // D30/PB11
+ {GPIOB_BASE, 12, ADC_INVALID, TIMER_INVALID}, // D31/PB12
+ {GPIOB_BASE, 13, ADC_INVALID, TIMER_INVALID}, // D32/PB13
+ {GPIOB_BASE, 14, ADC_INVALID, TIMER_INVALID}, // D33/PB14
+ {GPIOB_BASE, 15, ADC_INVALID, TIMER_INVALID}, // D34/PB15
+ {GPIOC_BASE, 6, ADC_INVALID, TIMER_INVALID}, // D35/PC6
+ {GPIOC_BASE, 7, ADC_INVALID, TIMER_INVALID}, // D36/PC7
+ {GPIOC_BASE, 8, ADC_INVALID, TIMER_INVALID}, // D37/PC8
+ {GPIOC_BASE, 9, ADC_INVALID, TIMER_INVALID} // D38/PC9 (BUT)
+ };
+
+ static ExtiInfo PIN_TO_EXTI_CHANNEL[NR_GPIO_PINS] = {
+ {EXTI3, EXTI_CONFIG_PORTA}, // D0/PA3
+ {EXTI2, EXTI_CONFIG_PORTA}, // D1/PA2
+ {EXTI0, EXTI_CONFIG_PORTA}, // D2/PA0
+ {EXTI1, EXTI_CONFIG_PORTA}, // D3/PA1
+ {EXTI5, EXTI_CONFIG_PORTB}, // D4/PB5
+ {EXTI6, EXTI_CONFIG_PORTB}, // D5/PB6
+ {EXTI8, EXTI_CONFIG_PORTA}, // D6/PA8
+ {EXTI9, EXTI_CONFIG_PORTA}, // D7/PA9
+ {EXTI10, EXTI_CONFIG_PORTA}, // D8/PA10
+ {EXTI7, EXTI_CONFIG_PORTB}, // D9/PB7
+ {EXTI4, EXTI_CONFIG_PORTA}, // D10/PA4
+ {EXTI7, EXTI_CONFIG_PORTA}, // D11/PA7
+ {EXTI6, EXTI_CONFIG_PORTA}, // D12/PA6
+ {EXTI5, EXTI_CONFIG_PORTA}, // D13/PA5
+ };
+
+#endif
+
+// LeafLabs Maple Native (prototype)
+#ifdef BOARD_maple_native
+
+ #define CYCLES_PER_MICROSECOND 72
+
+ // TODO:
+ static PinMapping PIN_MAP[NR_GPIO_PINS] = {
+ {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR}, // D0/PA3
+ {GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR}, // D1/PA2
+ {GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR}, // D2/PA0
+ {GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR}, // D3/PA1
+ {GPIOB_BASE, 5, ADC_INVALID, TIMER_INVALID}, // D4/PB5
+ {GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR}, // D5/PB6
+ {GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR}, // D6/PA8
+ {GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR}, // D7/PA9
+ {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR}, // D8/PA10
+ {GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR}, // D9/PB7
+ {GPIOA_BASE, 4, ADC4, TIMER_INVALID}, // D10/PA4
+ {GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR}, // D11/PA7
+ {GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR}, // D12/PA6
+ {GPIOA_BASE, 5, ADC5, TIMER_INVALID}, // D13/PA5
+ {GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR}, // D14/PB8
+ /* Little header */
+ {GPIOC_BASE, 0, ADC10, TIMER_INVALID}, // D15/PC0
+ {GPIOC_BASE, 1, ADC11, TIMER_INVALID}, // D16/PC1
+ {GPIOC_BASE, 2, ADC12, TIMER_INVALID}, // D17/PC2
+ {GPIOC_BASE, 3, ADC13, TIMER_INVALID}, // D18/PC3
+ {GPIOC_BASE, 4, ADC14, TIMER_INVALID}, // D19/PC4
+ {GPIOC_BASE, 5, ADC15, TIMER_INVALID}, // D20/PC5
+ /* External header */
+ {GPIOC_BASE, 13, ADC_INVALID, TIMER_INVALID}, // D21/PC13
+ {GPIOC_BASE, 14, ADC_INVALID, TIMER_INVALID}, // D22/PC14
+ {GPIOC_BASE, 15, ADC_INVALID, TIMER_INVALID}, // D23/PC15
+ {GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR}, // D24/PB9
+ {GPIOD_BASE, 2, ADC_INVALID, TIMER_INVALID}, // D25/PD2
+ {GPIOC_BASE, 10, ADC_INVALID, TIMER_INVALID}, // D26/PC10
+ {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR}, // D27/PB0
+ {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR}, // D28/PB1
+ {GPIOB_BASE, 10, ADC_INVALID, TIMER_INVALID}, // D29/PB10
+ {GPIOB_BASE, 11, ADC_INVALID, TIMER_INVALID}, // D30/PB11
+ {GPIOB_BASE, 12, ADC_INVALID, TIMER_INVALID}, // D31/PB12
+ {GPIOB_BASE, 13, ADC_INVALID, TIMER_INVALID}, // D32/PB13
+ {GPIOB_BASE, 14, ADC_INVALID, TIMER_INVALID}, // D33/PB14
+ {GPIOB_BASE, 15, ADC_INVALID, TIMER_INVALID}, // D34/PB15
+ {GPIOC_BASE, 6, ADC_INVALID, TIMER_INVALID}, // D35/PC6
+ {GPIOC_BASE, 7, ADC_INVALID, TIMER_INVALID}, // D36/PC7
+ {GPIOC_BASE, 8, ADC_INVALID, TIMER_INVALID}, // D37/PC8
+ {GPIOC_BASE, 9, ADC_INVALID, TIMER_INVALID} // D38/PC9 (BUT)
+ };
+
+ static ExtiInfo PIN_TO_EXTI_CHANNEL[NR_GPIO_PINS] = {
+ {EXTI3, EXTI_CONFIG_PORTA}, // D0/PA3
+ {EXTI2, EXTI_CONFIG_PORTA}, // D1/PA2
+ {EXTI0, EXTI_CONFIG_PORTA}, // D2/PA0
+ {EXTI1, EXTI_CONFIG_PORTA}, // D3/PA1
+ {EXTI5, EXTI_CONFIG_PORTB}, // D4/PB5
+ {EXTI6, EXTI_CONFIG_PORTB}, // D5/PB6
+ {EXTI8, EXTI_CONFIG_PORTA}, // D6/PA8
+ {EXTI9, EXTI_CONFIG_PORTA}, // D7/PA9
+ {EXTI10, EXTI_CONFIG_PORTA}, // D8/PA10
+ {EXTI7, EXTI_CONFIG_PORTB}, // D9/PB7
+ {EXTI4, EXTI_CONFIG_PORTA}, // D10/PA4
+ {EXTI7, EXTI_CONFIG_PORTA}, // D11/PA7
+ {EXTI6, EXTI_CONFIG_PORTA}, // D12/PA6
+ {EXTI5, EXTI_CONFIG_PORTA}, // D13/PA5
+ };
+#endif
+
+#ifndef CYCLES_PER_MICROSECOND
+#error Board type has not been selected correctly.
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
+
diff --git a/wirish/comm/HardwareSerial.cpp b/wirish/comm/HardwareSerial.cpp
index 7157e74..6399ad5 100644
--- a/wirish/comm/HardwareSerial.cpp
+++ b/wirish/comm/HardwareSerial.cpp
@@ -34,77 +34,60 @@
#include "gpio.h"
#include "timers.h"
-#define USART1_TX_PORT GPIOA_BASE
-#define USART1_TX_PIN 9
-#define USART1_RX_PORT GPIOA_BASE
-#define USART1_RX_PIN 10
-
-#define USART2_TX_PORT GPIOA_BASE
-#define USART2_TX_PIN 2
-#define USART2_RX_PORT GPIOA_BASE
-#define USART2_RX_PIN 3
-
-#define USART3_TX_PORT GPIOB_BASE
-#define USART3_TX_PIN 10
-#define USART3_RX_PORT GPIOB_BASE
-#define USART3_RX_PIN 11
-
-HardwareSerial::HardwareSerial(uint8 usartNum) {
- ASSERT(usartNum == 1 ||
- usartNum == 2 ||
- usartNum == 3);
- this->usartNum = usartNum;
+HardwareSerial Serial1(USART1, 4500000UL, GPIOA_BASE, 9, 10, 1, 2);
+HardwareSerial Serial2(USART2, 2250000UL, GPIOA_BASE, 2, 3, 2, 3);
+HardwareSerial Serial3(USART3, 2250000UL, GPIOB_BASE, 10, 11, 0, 0);
+// TODO: High density device ports
+
+HardwareSerial::HardwareSerial(uint8 usart_num,
+ uint32 max_baud,
+ GPIO_Port *gpio_port,
+ uint8 tx_pin,
+ uint8 rx_pin,
+ uint8 timer_num,
+ uint8 compare_num) {
+ this->usart_num = usart_num;
+ this->max_baud = max_baud;
+ this->gpio_port = gpio_port;
+ this->tx_pin = tx_pin;
+ this->rx_pin = rx_pin;
+ this->timer_num = timer_num;
+ this->compare_num = compare_num;
}
uint8 HardwareSerial::read(void) {
- return usart_getc(usartNum);
+ return usart_getc(usart_num);
}
uint32 HardwareSerial::available(void) {
-
- return usart_data_available(usartNum);
+ return usart_data_available(usart_num);
}
void HardwareSerial::write(unsigned char ch) {
- usart_putc(usartNum, ch);
+ usart_putc(usart_num, ch);
}
void HardwareSerial::begin(uint32 baud) {
- ASSERT(!(baud > USART_MAX_BAUD));
+ if (baud > max_baud) {
+ return;
+ }
+
+ gpio_set_mode(gpio_port, tx_pin, GPIO_MODE_AF_OUTPUT_PP);
+ gpio_set_mode(gpio_port, rx_pin, GPIO_MODE_INPUT_FLOATING);
- /* Set appropriate pin modes */
- switch (usartNum) {
- case 1:
- gpio_set_mode(USART1_TX_PORT, USART1_TX_PIN, GPIO_MODE_AF_OUTPUT_PP);
- gpio_set_mode(USART1_RX_PORT, USART1_RX_PIN, GPIO_MODE_INPUT_FLOATING);
- /* Turn off any pwm */
- timer_set_mode(1, 2, TIMER_DISABLED);
- break;
- case 2:
- gpio_set_mode(USART2_TX_PORT, USART2_TX_PIN, GPIO_MODE_AF_OUTPUT_PP);
- gpio_set_mode(USART2_RX_PORT, USART2_RX_PIN, GPIO_MODE_INPUT_FLOATING);
- /* Turn off any pwm */
- timer_set_mode(2, 3, TIMER_DISABLED);
- break;
- case 3:
- gpio_set_mode(USART3_TX_PORT, USART3_TX_PIN, GPIO_MODE_AF_OUTPUT_PP);
- gpio_set_mode(USART3_RX_PORT, USART3_RX_PIN, GPIO_MODE_INPUT_FLOATING);
- break;
- default:
- ASSERT(0);
- }
+ if ((usart_num == USART1) ||
+ (usart_num == USART2)) {
+ /* turn off any pwm if there's a conflict on this usart */
+ timer_set_mode(timer_num, compare_num, TIMER_DISABLED);
+ }
- usart_init(usartNum, baud);
+ usart_init(usart_num, baud);
}
void HardwareSerial::end(void) {
- usart_disable(usartNum);
+ usart_disable(usart_num);
}
void HardwareSerial::flush(void) {
- usart_clear_buffer(usartNum);
+ usart_reset_rx(usart_num);
}
-
-HardwareSerial Serial1(1);
-HardwareSerial Serial2(2);
-HardwareSerial Serial3(3);
diff --git a/wirish/comm/HardwareSerial.h b/wirish/comm/HardwareSerial.h
index 5ed81cd..df8d7bf 100644
--- a/wirish/comm/HardwareSerial.h
+++ b/wirish/comm/HardwareSerial.h
@@ -35,9 +35,21 @@
class HardwareSerial : public Print {
private:
- uint8 usartNum;
+ uint8 usart_num;
+ uint32 max_baud;
+ GPIO_Port *gpio_port;
+ uint8 tx_pin;
+ uint8 rx_pin;
+ uint8 timer_num;
+ uint8 compare_num;
public:
- HardwareSerial(uint8);
+ HardwareSerial(uint8 usart_num,
+ uint32 max_baud,
+ GPIO_Port *gpio_port,
+ uint8 tx_pin,
+ uint8 rx_pin,
+ uint8 timer_num,
+ uint8 compare_num);
void begin(uint32);
void end(void);
uint32 available(void);
@@ -46,9 +58,9 @@ class HardwareSerial : public Print {
virtual void write(unsigned char);
using Print::write;
};
-
extern HardwareSerial Serial1;
extern HardwareSerial Serial2;
extern HardwareSerial Serial3;
+// TODO: high density device ports
#endif
diff --git a/wirish/ext_interrupts.c b/wirish/ext_interrupts.c
index 54b8be9..6ba1d05 100644
--- a/wirish/ext_interrupts.c
+++ b/wirish/ext_interrupts.c
@@ -32,29 +32,6 @@
#include "exti.h"
#include "ext_interrupts.h"
-typedef struct ExtiInfo {
- uint8 channel;
- uint8 port;
-} ExtiInfo;
-
-static ExtiInfo PIN_TO_EXTI_CHANNEL[NR_MAPLE_PINS] = {
- {EXTI3, EXTI_CONFIG_PORTA}, // D0/PA3
- {EXTI2, EXTI_CONFIG_PORTA}, // D1/PA2
- {EXTI0, EXTI_CONFIG_PORTA}, // D2/PA0
- {EXTI1, EXTI_CONFIG_PORTA}, // D3/PA1
- {EXTI5, EXTI_CONFIG_PORTB}, // D4/PB5
- {EXTI6, EXTI_CONFIG_PORTB}, // D5/PB6
- {EXTI8, EXTI_CONFIG_PORTA}, // D6/PA8
- {EXTI9, EXTI_CONFIG_PORTA}, // D7/PA9
- {EXTI10, EXTI_CONFIG_PORTA}, // D8/PA10
- {EXTI7, EXTI_CONFIG_PORTB}, // D9/PB7
- {EXTI4, EXTI_CONFIG_PORTA}, // D10/PA4
- {EXTI7, EXTI_CONFIG_PORTA}, // D11/PA7
- {EXTI6, EXTI_CONFIG_PORTA}, // D12/PA6
- {EXTI5, EXTI_CONFIG_PORTA}, // D13/PA5
-};
-
-
/**
* @brief Attach an interrupt handler to be triggered on a given
* transition on the pin. Runs in interrupt context
@@ -65,10 +42,10 @@ static ExtiInfo PIN_TO_EXTI_CHANNEL[NR_MAPLE_PINS] = {
*
* @sideeffect Registers a handler
*/
-int attachInterrupt(uint8 pin, voidFuncPtr handler, ExtInterruptTriggerMode mode) {
+int attachInterrupt(uint8 pin, voidFuncPtr handler, uint32 mode) {
uint8 outMode;
/* Parameter checking */
- if (pin >= NR_MAPLE_PINS) {
+ if (pin >= NR_GPIO_PINS) {
return EXT_INTERRUPT_INVALID_PIN;
}
@@ -100,7 +77,7 @@ int attachInterrupt(uint8 pin, voidFuncPtr handler, ExtInterruptTriggerMode mode
}
int detachInterrupt(uint8 pin) {
- if (!(pin < NR_MAPLE_PINS)) {
+ if (!(pin < NR_GPIO_PINS)) {
return EXT_INTERRUPT_INVALID_PIN;
}
diff --git a/wirish/ext_interrupts.h b/wirish/ext_interrupts.h
index fc69a15..7449685 100644
--- a/wirish/ext_interrupts.h
+++ b/wirish/ext_interrupts.h
@@ -31,14 +31,14 @@
#ifndef _EXT_INTERRUPTS_H_
#define _EXT_INTERRUPTS_H_
-typedef enum ExtInterruptTriggerMode {
+enum {
RISING,
FALLING,
CHANGE
-} ExtInterruptTriggerMode;
+};
-enum ExtInterruptError {
+enum {
EXT_INTERRUPT_INVALID_PIN = (-1),
EXT_INTERRUPT_INVALID_FUNCTION = (-2),
EXT_INTERRUPT_INVALID_MODE = (-3),
@@ -48,7 +48,7 @@ enum ExtInterruptError {
extern "C"{
#endif
-int attachInterrupt(uint8 pin, voidFuncPtr, ExtInterruptTriggerMode mode);
+int attachInterrupt(uint8 pin, voidFuncPtr, uint32 mode);
int detachInterrupt(uint8 pin);
#ifdef __cplusplus
diff --git a/wirish/io.h b/wirish/io.h
index fff551c..e779604 100644
--- a/wirish/io.h
+++ b/wirish/io.h
@@ -38,48 +38,6 @@
extern "C"{
#endif
-/* stash these here for now */
-#define D0 0
-#define D1 1
-#define D2 2
-#define D3 3
-#define D4 4
-#define D5 5
-#define D6 6
-#define D7 7
-#define D8 8
-#define D9 9
-#define D10 10
-#define D11 11
-#define D12 12
-#define D13 13
-#define D14 14
-#define D15 15
-#define D16 16
-#define D16 16
-#define D17 17
-#define D18 18
-#define D19 19
-#define D20 20
-#define D21 21
-#define D22 22
-#define D23 23
-#define D24 24
-#define D25 25
-#define D26 26
-#define D27 27
-#define D28 28
-#define D29 29
-#define D30 30
-#define D31 31
-#define D32 32
-#define D33 33
-#define D34 34
-#define D35 35
-#define D36 36
-#define D37 37
-#define D38 38
-#define D39 39
typedef enum WiringPinMode {
OUTPUT,
@@ -92,15 +50,6 @@ typedef enum WiringPinMode {
PWM
} WiringPinMode;
-typedef struct PinMapping {
- GPIO_Port *port;
- uint32 pin;
- uint32 adc;
- TimerCCR timer_channel;
-} PinMapping;
-
-#define ADC_INVALID 0xFFFFFFFF
-#define TIMER_INVALID (TimerCCR)0xFFFFFFFF
/* Set pin to mode
* pinMode(pin, mode):
diff --git a/wirish/pwm.c b/wirish/pwm.c
index 40715b5..995e2c7 100644
--- a/wirish/pwm.c
+++ b/wirish/pwm.c
@@ -31,12 +31,10 @@
#include "io.h"
#include "pwm.h"
-extern const PinMapping PIN_MAP[NR_MAPLE_PINS];
-
void pwmWrite(uint8 pin, uint16 duty_cycle) {
TimerCCR ccr;
- if (pin >= NR_MAPLE_PINS) {
+ if (pin >= NR_GPIO_PINS) {
return;
}
diff --git a/wirish/time.c b/wirish/time.c
index 69e962c..ea8ebe1 100644
--- a/wirish/time.c
+++ b/wirish/time.c
@@ -23,8 +23,6 @@
* ****************************************************************************/
/**
- * @file time.c
- *
* @brief
*/
@@ -32,46 +30,24 @@
#include "systick.h"
#include "time.h"
-#define CYCLES_PER_MICROSECOND 72
-#define FUDGE 42
-
-extern volatile uint32 systick_timer_millis;
-
-uint32 millis() {
- unsigned long m;
- m = systick_timer_millis;
- return m;
-}
-
void delay(unsigned long ms)
{
- unsigned long start = millis();
-
- while (millis() - start <= ms)
- ;
+ uint32 i;
+ for (i = 0; i < ms; i++) {
+ delayMicroseconds(1000);
+ }
}
-
-
-#if 1
void delayMicroseconds(uint32 us) {
- uint32 target;
- uint32 last, cur, count;
- /* fudge factor hacky hack hack for function overhead */
- target = us * CYCLES_PER_MICROSECOND - FUDGE;
-
- /* Get current count */
- last = systick_get_count();
- cur = systick_get_count();
- count = last;
- while ((count-cur) <= target) {
- cur = systick_get_count();
-
- /* check for overflow */
- if (cur > last) {
- count += MAPLE_RELOAD_VAL;
- }
- last = cur;
- }
+ // So (2^32)/12 micros max, or less than 6 minutes
+ us *= 12;
+
+ /* fudge for function call overhead */
+ us--;
+ asm volatile(" mov r0, %[us] \n\t"
+ "1: subs r0, #1 \n\t"
+ " bhi 1b \n\t"
+ :
+ : [us] "r" (us)
+ : "r0");
}
-#endif
diff --git a/wirish/time.h b/wirish/time.h
index 9e5536b..33c04b4 100644
--- a/wirish/time.h
+++ b/wirish/time.h
@@ -23,8 +23,6 @@
* ****************************************************************************/
/**
- * @file time.h
- *
* @brief
*/
@@ -34,32 +32,42 @@
#ifdef __cplusplus
extern "C"{
#endif
-/* Returns time since boot in milliseconds */
-uint32 millis(void);
+
+#include "nvic.h"
+#include "systick.h"
+#include "boards.h"
+
+#define US_PER_MS 1000
+#define MAPLE_RELOAD_VAL (CYCLES_PER_MICROSECOND * US_PER_MS)
+
+extern volatile uint32 systick_timer_millis;
+
+/* time in milliseconds since boot */
+static inline uint32 millis(void) {
+ return systick_timer_millis;
+}
/* Time in microseconds since boot */
-uint32 micros(void);
+static inline uint32 micros(void) {
+ uint32 ms;
+ uint32 cycle_cnt;
+ uint32 res;
-/* Delay for ms milliseconds */
-void delay(unsigned long ms);
+ nvic_globalirq_disable();
-/* Delay for us microseconds */
-void delayMicroseconds(uint32 us);
+ cycle_cnt = systick_get_count();
+ ms = millis();
+
+ nvic_globalirq_enable();
-#if 0
-static inline void delay_us(uint32 us) {
- us *= 12;
- asm volatile("mov r0, %[us] \n\t"
- "subs r0, #2 \n\t"
-"1: \n\t"
- "subs r0, r0, #1 \n\t"
- "bne 1b"
- :
- : [us] "r" (us)
- : "r0", "cc");
+ res = (ms * US_PER_MS) + (MAPLE_RELOAD_VAL - cycle_cnt)/CYCLES_PER_MICROSECOND;
+ return res;
}
-#endif
+
+void delay(unsigned long ms);
+void delayMicroseconds(uint32 us);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/wirish/wirish.c b/wirish/wirish.c
index 28e7130..41f5db4 100644
--- a/wirish/wirish.c
+++ b/wirish/wirish.c
@@ -23,7 +23,14 @@
* ****************************************************************************/
/**
- * @brief Maple board bring up
+ * @brief generic maple board bring up:
+ *
+ * By default, we bring up all maple boards running on the stm32 to 72mhz,
+ * clocked off the PLL, driven by the 8MHz external crystal.
+ *
+ * AHB and APB2 are clocked at 72MHz
+ * APB1 is clocked at 36MHz
+ *
*/
#include "wirish.h"
@@ -32,35 +39,40 @@
#include "nvic.h"
#include "usb.h"
#include "rcc.h"
+#include "fsmc.h"
+#include "dac.h"
#include "flash.h"
-static void inline maple_flash_init(void) {
+void init(void) {
+ /* make sure the flash is ready before spinning the high speed clock up */
flash_enable_prefetch();
flash_set_latency(FLASH_WAIT_STATE_2);
-}
-static void inline maple_rcc_init(void) {
- struct rcc_device maple_rcc_dev = {
- .apb1_prescale = RCC_APB1_HCLK_DIV_2,
- .apb2_prescale = RCC_APB2_HCLK_DIV_1,
- .ahb_prescale = RCC_AHB_SYSCLK_DIV_1,
- .sysclk_src = RCC_CLKSRC_PLL,
- .pll_src = RCC_PLLSRC_HSE,
- .pll_mul = RCC_PLLMUL_9
- };
+ #if HAS_FSMC
+ fsmc_native_sram_init();
+ #endif
+
+ #if NR_DAC_PINS > 0
+ dac_init();
+ #endif
+
+ /* initialize clocks */
+ rcc_clk_init(RCC_CLKSRC_PLL, RCC_PLLSRC_HSE, RCC_PLLMUL_9);
+ rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1);
+ rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2);
+ rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1);
- rcc_init(&maple_rcc_dev);
-}
-void init(void) {
- maple_flash_init();
- maple_rcc_init();
nvic_init();
- systick_init();
+ systick_init(MAPLE_RELOAD_VAL);
gpio_init();
-// adc_init();
-// timer_init(1, 1);
-// timer_init(2, 1);
-// timer_init(3, 1);
-// timer_init(4, 1);
-// setupUSB();
+ adc_init();
+ timer_init(1, 1);
+ timer_init(2, 1);
+ timer_init(3, 1);
+ timer_init(4, 1);
+ #if NR_TIMERS >= 8
+ timer_init(5, 1);
+ timer_init(8, 1);
+ #endif
+ setupUSB();
}
diff --git a/wirish/wirish.h b/wirish/wirish.h
index 13ff313..7ede77c 100644
--- a/wirish/wirish.h
+++ b/wirish/wirish.h
@@ -32,10 +32,11 @@
#define _WIRISH_H_
#include "libmaple.h"
+#include "boards.h"
+#include "time.h"
#include "timers.h"
#include "io.h"
#include "bits.h"
-#include "time.h"
#include "pwm.h"
#include "ext_interrupts.h"
#include "wirish_math.h"
@@ -51,9 +52,6 @@
extern "C"{
#endif
-#define MAPLE 1
-#define NR_MAPLE_PINS 39 // temporary
-
/* Arduino wiring macros and bit defines */
#define HIGH 0x1
#define LOW 0x0
@@ -64,9 +62,6 @@ extern "C"{
#define LSBFIRST 0
#define MSBFIRST 1
-#define USER_ADDR_ROM 0x08005000
-#define USER_ADDR_RAM 0x20000C00
-
#define lowByte(w) ((w) & 0xff)
#define highByte(w) ((w) >> 8)
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
@@ -86,8 +81,5 @@ void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, byte val);
} // extern "C"
#endif
-
-
-
#endif
diff --git a/wirish/wirish_analog.c b/wirish/wirish_analog.c
index f4c1204..1b911bc 100644
--- a/wirish/wirish_analog.c
+++ b/wirish/wirish_analog.c
@@ -30,13 +30,12 @@
#include "wirish.h"
#include "io.h"
-extern const PinMapping PIN_MAP[NR_MAPLE_PINS];
-
/* Assumes that the ADC has been initialized and
* that the pin is set to ANALOG_INPUT */
uint32 analogRead(uint8 pin) {
- if (pin >= NR_ANALOG_PINS)
+ if(PIN_MAP[pin].adc == ADC_INVALID) {
return 0;
+ }
return adc_read(PIN_MAP[pin].adc);
}
diff --git a/wirish/wirish_digital.c b/wirish/wirish_digital.c
index 33217b6..c93c786 100644
--- a/wirish/wirish_digital.c
+++ b/wirish/wirish_digital.c
@@ -29,72 +29,10 @@
#include "wirish.h"
#include "io.h"
-#define ADC0 0
-#define ADC1 1
-#define ADC2 2
-#define ADC3 3
-#define ADC4 4
-#define ADC5 5
-#define ADC6 6
-#define ADC7 7
-#define ADC8 8
-#define ADC9 9
-#define ADC10 10
-#define ADC11 11
-#define ADC12 12
-#define ADC13 13
-#define ADC14 14
-#define ADC15 15
-#define ADC16 16
-
-const PinMapping PIN_MAP[NR_MAPLE_PINS] = {
- {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR}, // D0/PA3
- {GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR}, // D1/PA2
- {GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR}, // D2/PA0
- {GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR}, // D3/PA1
- {GPIOB_BASE, 5, ADC_INVALID, TIMER_INVALID}, // D4/PB5
- {GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR}, // D5/PB6
- {GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR}, // D6/PA8
- {GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR}, // D7/PA9
- {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR}, // D8/PA10
- {GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR}, // D9/PB7
- {GPIOA_BASE, 4, ADC4, TIMER_INVALID}, // D10/PA4
- {GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR}, // D11/PA7
- {GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR}, // D12/PA6
- {GPIOA_BASE, 5, ADC5, TIMER_INVALID}, // D13/PA5
- {GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR}, // D14/PB8
- /* Little header */
- {GPIOC_BASE, 0, ADC10, TIMER_INVALID}, // D15/PC0
- {GPIOC_BASE, 1, ADC11, TIMER_INVALID}, // D16/PC1
- {GPIOC_BASE, 2, ADC12, TIMER_INVALID}, // D17/PC2
- {GPIOC_BASE, 3, ADC13, TIMER_INVALID}, // D18/PC3
- {GPIOC_BASE, 4, ADC14, TIMER_INVALID}, // D19/PC4
- {GPIOC_BASE, 5, ADC15, TIMER_INVALID}, // D20/PC5
- /* External header */
- {GPIOC_BASE, 13, ADC_INVALID, TIMER_INVALID}, // D21/PC13
- {GPIOC_BASE, 14, ADC_INVALID, TIMER_INVALID}, // D22/PC14
- {GPIOC_BASE, 15, ADC_INVALID, TIMER_INVALID}, // D23/PC15
- {GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR}, // D24/PB9
- {GPIOD_BASE, 2, ADC_INVALID, TIMER_INVALID}, // D25/PD2
- {GPIOC_BASE, 10, ADC_INVALID, TIMER_INVALID}, // D26/PC10
- {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR}, // D27/PB0
- {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR}, // D28/PB1
- {GPIOB_BASE, 10, ADC_INVALID, TIMER_INVALID}, // D29/PB10
- {GPIOB_BASE, 11, ADC_INVALID, TIMER_INVALID}, // D30/PB11
- {GPIOB_BASE, 12, ADC_INVALID, TIMER_INVALID}, // D31/PB12
- {GPIOB_BASE, 13, ADC_INVALID, TIMER_INVALID}, // D32/PB13
- {GPIOB_BASE, 14, ADC_INVALID, TIMER_INVALID}, // D33/PB14
- {GPIOB_BASE, 15, ADC_INVALID, TIMER_INVALID}, // D34/PB15
- {GPIOC_BASE, 6, ADC_INVALID, TIMER_INVALID}, // D35/PC6
- {GPIOC_BASE, 7, ADC_INVALID, TIMER_INVALID}, // D36/PC7
- {GPIOC_BASE, 8, ADC_INVALID, TIMER_INVALID}, // D37/PC8
- {GPIOC_BASE, 9, ADC_INVALID, TIMER_INVALID} // D38/PC9
-};
-
void pinMode(uint8 pin, WiringPinMode mode) {
uint8 outputMode;
- if (pin >= NR_MAPLE_PINS)
+ if (pin >= NR_GPIO_PINS)
return;
switch(mode) {
@@ -130,13 +68,13 @@ void pinMode(uint8 pin, WiringPinMode mode) {
uint32 digitalRead(uint8 pin) {
- if (pin >= NR_MAPLE_PINS)
+ if (pin >= NR_GPIO_PINS)
return 0;
return gpio_read_bit(PIN_MAP[pin].port, PIN_MAP[pin].pin);
}
void digitalWrite(uint8 pin, uint8 val) {
- if (pin >= NR_MAPLE_PINS)
+ if (pin >= NR_GPIO_PINS)
return;
gpio_write_bit(PIN_MAP[pin].port, PIN_MAP[pin].pin, val);