diff options
54 files changed, 1703 insertions, 938 deletions
| @@ -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 + +------------------------------------------------------------------------------- @@ -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); | 
