diff options
Diffstat (limited to 'libmaple')
| -rw-r--r-- | libmaple/adc.c | 4 | ||||
| -rw-r--r-- | libmaple/adc.h | 38 | ||||
| -rw-r--r-- | libmaple/bitband.h | 65 | ||||
| -rw-r--r-- | libmaple/bkp.c | 6 | ||||
| -rw-r--r-- | libmaple/bkp.h | 16 | ||||
| -rw-r--r-- | libmaple/dac.c | 6 | ||||
| -rw-r--r-- | libmaple/dac.h | 10 | ||||
| -rw-r--r-- | libmaple/exti.c | 244 | ||||
| -rw-r--r-- | libmaple/exti.h | 158 | ||||
| -rw-r--r-- | libmaple/flash.c | 39 | ||||
| -rw-r--r-- | libmaple/flash.h | 98 | ||||
| -rw-r--r-- | libmaple/fsmc.c | 140 | ||||
| -rw-r--r-- | libmaple/fsmc.h | 313 | ||||
| -rw-r--r-- | libmaple/gpio.c | 158 | ||||
| -rw-r--r-- | libmaple/gpio.h | 391 | ||||
| -rw-r--r-- | libmaple/i2c.c | 12 | ||||
| -rw-r--r-- | libmaple/i2c.h | 2 | ||||
| -rw-r--r-- | libmaple/libmaple.h | 9 | ||||
| -rw-r--r-- | libmaple/libmaple_types.h | 1 | ||||
| -rw-r--r-- | libmaple/pwr.c | 2 | ||||
| -rw-r--r-- | libmaple/pwr.h | 9 | ||||
| -rw-r--r-- | libmaple/rcc.h | 3 | ||||
| -rw-r--r-- | libmaple/ring_buffer.h | 30 | ||||
| -rw-r--r-- | libmaple/rules.mk | 1 | ||||
| -rw-r--r-- | libmaple/spi.c | 18 | ||||
| -rw-r--r-- | libmaple/usb/descriptors.h | 2 | ||||
| -rw-r--r-- | libmaple/usb/usb.c | 33 | ||||
| -rw-r--r-- | libmaple/usb/usb_callbacks.c | 2 | ||||
| -rw-r--r-- | libmaple/usb/usb_config.h | 17 | ||||
| -rw-r--r-- | libmaple/usb/usb_hardware.c | 41 | ||||
| -rw-r--r-- | libmaple/usb/usb_hardware.h | 36 | ||||
| -rw-r--r-- | libmaple/util.c | 6 | ||||
| -rw-r--r-- | libmaple/util.h | 35 | 
33 files changed, 1250 insertions, 695 deletions
| diff --git a/libmaple/adc.c b/libmaple/adc.c index a464746..3d38596 100644 --- a/libmaple/adc.c +++ b/libmaple/adc.c @@ -126,8 +126,8 @@ void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate) {   * @param dev adc device   */  static void adc_calibrate(const adc_dev *dev) { -    __io uint32 *rstcal_bit = (__io uint32*)BITBAND_PERI(&(dev->regs->CR2), 3); -    __io uint32 *cal_bit = (__io uint32*)BITBAND_PERI(&(dev->regs->CR2), 2); +    __io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3); +    __io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2);      *rstcal_bit = 1;      while (*rstcal_bit) diff --git a/libmaple/adc.h b/libmaple/adc.h index ac386fb..53ef032 100644 --- a/libmaple/adc.h +++ b/libmaple/adc.h @@ -30,14 +30,16 @@  #ifndef _ADC_H_  #define _ADC_H_ -#include "util.h" +#include "libmaple.h" +#include "bitband.h"  #include "rcc.h"  #ifdef __cplusplus  extern "C"{  #endif +/** ADC register map type. */  typedef struct adc_reg_map {      __io uint32 SR;             ///< Status register      __io uint32 CR1;            ///< Control register 1 @@ -61,22 +63,30 @@ typedef struct adc_reg_map {      __io uint32 DR;             ///< Regular data register  } adc_reg_map; +/** ADC device type. */  typedef struct adc_dev { -    adc_reg_map *regs; -    rcc_clk_id clk_id; +    adc_reg_map *regs; /**< Register map */ +    rcc_clk_id clk_id; /**< RCC clock information */  } adc_dev; +/** ADC1 device. */  extern const adc_dev *ADC1; +/** ADC2 device. */  extern const adc_dev *ADC2;  #ifdef STM32_HIGH_DENSITY +/** ADC3 device. */  extern const adc_dev *ADC3;  #endif  /*   * ADC peripheral base addresses   */ + +/** ADC1 register map base pointer. */  #define ADC1_BASE               ((adc_reg_map*)0x40012400) +/** ADC2 register map base pointer. */  #define ADC2_BASE               ((adc_reg_map*)0x40012800) +/** ADC3 register map base pointer. */  #define ADC3_BASE               ((adc_reg_map*)0x40013C00)  /* @@ -138,8 +148,8 @@ void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate);  /**   * @brief Perform a single synchronous software triggered conversion on a - * channel - * @param regs ADC register map + * channel. + * @param dev ADC device to use for reading.   * @param channel channel to convert   * @return conversion result   */ @@ -161,27 +171,27 @@ static inline uint32 adc_read(const adc_dev *dev, uint8 channel) {  /**   * @brief Set external trigger conversion mode event for regular channels - * @param dev adc device - * @param enable if 1, conversion on external events is enabled, 0 to disable + * @param dev    ADC device + * @param enable If 1, conversion on external events is enabled, 0 to disable   */  static inline void adc_set_exttrig(const adc_dev *dev, uint8 enable) { -    __write(BITBAND_PERI(&(dev->regs->CR2), 20), enable); +    *bb_perip(&dev->regs->CR2, 20) = !!enable;  }  /**   * @brief Enable an adc peripheral - * @param regs register map of peripheral to enable + * @param dev ADC device to enable   */  static inline void adc_enable(const adc_dev *dev) { -    __write(BITBAND_PERI(&(dev->regs->CR2), 0), 1); +    *bb_perip(&dev->regs->CR2, 0) = 1;  }  /** - * @brief Disable an adc peripheral - * @param regs register map of peripheral to disable + * @brief Disable an ADC peripheral + * @param dev ADC device to disable   */  static inline void adc_disable(const adc_dev *dev) { -    __write(BITBAND_PERI(&(dev->regs->CR2), 0), 0); +    *bb_perip(&dev->regs->CR2, 0) = 0;  }  /** @@ -198,5 +208,5 @@ static inline void adc_disable_all(void) {  #ifdef __cplusplus  } // extern "C"  #endif -#endif +#endif diff --git a/libmaple/bitband.h b/libmaple/bitband.h new file mode 100644 index 0000000..b817f73 --- /dev/null +++ b/libmaple/bitband.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 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. + *****************************************************************************/ + +/** + * @file bitband.h + * + * @brief Bit-banding utility functions + */ + +#define BB_SRAM_REF      0x20000000 +#define BB_SRAM_BASE     0x22000000 +#define BB_PERI_REF      0x40000000 +#define BB_PERI_BASE     0x42000000 + +static inline __io uint32* __bb_addr(__io void*, uint32, uint32, uint32); + +/** + * @brief Obtain a pointer to the bit-band address corresponding to a + * bit in a volatile SRAM address. + * @param address Address in the bit-banded SRAM region + * @param bit     Bit in address to bit-band + */ +static inline __io uint32* bb_sramp(__io void *address, uint32 bit) { +    return __bb_addr(address, bit, BB_SRAM_BASE, BB_SRAM_REF); +} + +/** + * @brief Obtain a pointer to the bit-band address corresponding to a + * bit in a peripheral address. + * @param address Address in the bit-banded peripheral region + * @param bit     Bit in address to bit-band + */ +static inline __io uint32* bb_perip(__io void *address, uint32 bit) { +    return __bb_addr(address, bit, BB_PERI_BASE, BB_PERI_REF); +} + +static inline __io uint32* __bb_addr(__io void *address, +                                     uint32 bit, +                                     uint32 bb_base, +                                     uint32 bb_ref) { +    return (__io uint32*)(bb_base + ((uint32)address - bb_ref) * 32 + bit * 4); +} diff --git a/libmaple/bkp.c b/libmaple/bkp.c index ed107d8..aaccb1f 100644 --- a/libmaple/bkp.c +++ b/libmaple/bkp.c @@ -27,7 +27,7 @@  #include "bkp.h"  #include "pwr.h"  #include "rcc.h" -#include "util.h" +#include "bitband.h"  static inline __io uint32* data_register(uint8 reg); @@ -57,14 +57,14 @@ void bkp_init(void) {   * @see bkp_init()   */  void bkp_enable_writes(void) { -    __write(BITBAND_PERI(&(PWR_BASE->CR), PWR_CR_DBP), 1); +    *bb_perip(&PWR_BASE->CR, PWR_CR_DBP) = 1;  }  /**   * Disable write access to the backup registers.   */  void bkp_disable_writes(void) { -    __write(BITBAND_PERI(&(PWR_BASE->CR), PWR_CR_DBP), 0); +    *bb_perip(&PWR_BASE->CR, PWR_CR_DBP) = 0;  }  /** diff --git a/libmaple/bkp.h b/libmaple/bkp.h index 96ef8d2..cea39b6 100644 --- a/libmaple/bkp.h +++ b/libmaple/bkp.h @@ -44,6 +44,7 @@ extern "C" {  #define BKP_NR_DATA_REGS 42  #endif +/** Backup peripheral register map type. */  typedef struct bkp_reg_map {      const uint32 RESERVED1;      __io uint32 DR1;            ///< Data register 1 @@ -97,20 +98,17 @@ typedef struct bkp_reg_map {  #endif  } bkp_reg_map; +/** Backup peripheral register map base pointer. */ +#define BKP_BASE        ((bkp_reg_map*)0x40006C00) + +/** Backup peripheral device type. */  typedef struct bkp_dev { -    bkp_reg_map *regs; +    bkp_reg_map *regs; /**< Register map */  } bkp_dev; -/** - * Backup device. - */ +/** Backup device. */  extern const bkp_dev *BKP; -/* - * Backup peripheral base. - */ -#define BKP_BASE        ((bkp_reg_map*)0x40006C00) -  void bkp_init(void);  void bkp_enable_writes(void);  void bkp_disable_writes(void); diff --git a/libmaple/dac.c b/libmaple/dac.c index 54b555b..ef3a9f9 100644 --- a/libmaple/dac.c +++ b/libmaple/dac.c @@ -80,15 +80,15 @@ void dac_write_channel(uint8 channel, uint16 val) {  void dac_enable_channel(uint8 channel) {      /*       * Setup ANALOG mode on PA4 and PA5. This mapping is consistent across -     * all STM32 chips with a DAC. See RM008 12.2. +     * all STM32 chips with a DAC. See RM0008 12.2.       */      switch (channel) {      case 1: -        gpio_set_mode(GPIOA_BASE, 4, GPIO_MODE_INPUT_ANALOG); +        gpio_set_mode(GPIOA, 4, GPIO_INPUT_ANALOG);          DAC->regs->CR |= DAC_CR_EN1;          break;      case 2: -        gpio_set_mode(GPIOA_BASE, 5, GPIO_MODE_INPUT_ANALOG); +        gpio_set_mode(GPIOA, 5, GPIO_INPUT_ANALOG);          DAC->regs->CR |= DAC_CR_EN2;          break;      } diff --git a/libmaple/dac.h b/libmaple/dac.h index bc64324..c897bb2 100644 --- a/libmaple/dac.h +++ b/libmaple/dac.h @@ -25,9 +25,10 @@  /**   * @file dac.h   * @brief Digital to analog converter header file - *      See notes/dac.txt for more info   */ +/* See notes/dac.txt for more info */ +  #ifndef _DAC_H_  #define _DAC_H_ @@ -63,16 +64,15 @@ typedef struct dac_reg_map {      __io uint32 DOR2;    /**< Channel 2 data output register */  } dac_reg_map; +/** DAC device type. */  typedef struct dac_dev { -    dac_reg_map *regs; +    dac_reg_map *regs; /**< Register map */  } dac_dev;  /** DAC device. */  extern const dac_dev *DAC; -/* - * DAC peripheral base address - */ +/** DAC register map base address */  #define DAC_BASE                ((dac_reg_map*)0x40007400)  /* diff --git a/libmaple/exti.c b/libmaple/exti.c index e8ad52a..7f56712 100644 --- a/libmaple/exti.c +++ b/libmaple/exti.c @@ -23,19 +23,29 @@   *****************************************************************************/  /** + * @file exti.c   * @brief External interrupt control routines   */  #include "libmaple.h"  #include "exti.h"  #include "nvic.h" +#include "bitband.h" -typedef struct ExtIChannel { +/* + * Internal state + */ + +/* Status bitmaps, for external interrupts with multiplexed IRQs */ +static uint16 exti_9_5_en = 0; +static uint16 exti_15_10_en = 0; + +typedef struct exti_channel {      void (*handler)(void);      uint32 irq_line; -} ExtIChannel; +} exti_channel; -static ExtIChannel exti_channels[] = { +static exti_channel exti_channels[] = {      { .handler = NULL, .irq_line = NVIC_EXTI0     },  // EXTI0      { .handler = NULL, .irq_line = NVIC_EXTI1     },  // EXTI1      { .handler = NULL, .irq_line = NVIC_EXTI2     },  // EXTI2 @@ -54,63 +64,127 @@ static ExtIChannel exti_channels[] = {      { .handler = NULL, .irq_line = NVIC_EXTI15_10 },  // EXTI15  }; -static inline void clear_pending(int bit) { -    __set_bits(EXTI_PR, BIT(bit)); -    /* If the pending bit is cleared as the last instruction in an ISR, -     * it won't actually be cleared in time and the ISR will fire again. -     * Insert a 2-cycle buffer to allow it to take effect. */ -    asm volatile("nop"); -    asm volatile("nop"); -} +/* + * Convenience routines + */ + +static inline void enable_irq(afio_exti_num exti_num); +static inline void maybe_disable_irq(afio_exti_num exti_num); + +/** + * @brief Register a handler to run upon external interrupt. + * + * This function assumes that the interrupt request corresponding to + * the given external interrupt is masked. + * + * @param num     External interrupt line number. + * @param port    Port to use as source input for external interrupt. + * @param handler Function handler to execute when interrupt is triggered. + * @param mode    Type of transition to trigger on, one of: + *                EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING. + * @see exti_num + * @see exti_port + * @see exti_trigger_mode + */ +void exti_attach_interrupt(afio_exti_num num, +                           afio_exti_port port, +                           voidFuncPtr handler, +                           exti_trigger_mode mode) { +    ASSERT(handler); -static inline void dispatch_handler(uint32 channel) { -    ASSERT(exti_channels[channel].handler); -    if (exti_channels[channel].handler) { -        (exti_channels[channel].handler)(); +    /* Register the handler */ +    exti_channels[num].handler = handler; + +    /* Set trigger mode */ +    switch (mode) { +    case EXTI_RISING: +        *bb_perip(&EXTI_BASE->RTSR, num) = 1; +        break; +    case EXTI_FALLING: +        *bb_perip(&EXTI_BASE->FTSR, num) = 1; +        break; +    case EXTI_RISING_FALLING: +        *bb_perip(&EXTI_BASE->RTSR, num) = 1; +        *bb_perip(&EXTI_BASE->FTSR, num) = 1; +        break;      } + +    /* Map num to port */ +    afio_exti_select(num, port); + +    /* Unmask external interrupt request */ +    *bb_perip(&EXTI_BASE->IMR, num) = 1; + +    /* Enable the interrupt line */ +    enable_irq(num); +} + +/** + * @brief Unregister an external interrupt handler + * @param num Number of the external interrupt line to disable. + * @see exti_num + */ +void exti_detach_interrupt(afio_exti_num num) { +    /* First, mask the interrupt request */ +    *bb_perip(&EXTI_BASE->IMR, num) = 0; + +    /* Then, clear the trigger selection registers */ +    *bb_perip(&EXTI_BASE->FTSR, num) = 0; +    *bb_perip(&EXTI_BASE->RTSR, num) = 0; + +    /* Next, disable the IRQ, unless it's multiplexed and there are +     * other active external interrupts on the same IRQ line */ +    maybe_disable_irq(num); + +    /* Finally, unregister the user's handler */ +    exti_channels[num].handler = NULL;  } -/* For EXTI0 through EXTI4, only one handler - * is associated with each channel, so we - * don't have to keep track of which channel +/* + * Interrupt handlers + */ + +static inline void clear_pending(uint32 exti_num); +static inline void dispatch_handler(uint32 exti_num); + +/* For AFIO_EXTI_0 through AFIO_EXTI_4, only one handler is associated + * with each channel, so we don't have to keep track of which channel   * we came from */  void __irq_exti0(void) { -    dispatch_handler(EXTI0); -    clear_pending(EXTI0); +    dispatch_handler(AFIO_EXTI_0); +    clear_pending(AFIO_EXTI_0);  }  void __irq_exti1(void) { -    dispatch_handler(EXTI1); -    clear_pending(EXTI1); +    dispatch_handler(AFIO_EXTI_1); +    clear_pending(AFIO_EXTI_1);  }  void __irq_exti2(void) { -    dispatch_handler(EXTI2); -    clear_pending(EXTI2); +    dispatch_handler(AFIO_EXTI_2); +    clear_pending(AFIO_EXTI_2);  }  void __irq_exti3(void) { -    dispatch_handler(EXTI3); -    clear_pending(EXTI3); +    dispatch_handler(AFIO_EXTI_3); +    clear_pending(AFIO_EXTI_3);  }  void __irq_exti4(void) { -    dispatch_handler(EXTI4); -    clear_pending(EXTI4); +    dispatch_handler(AFIO_EXTI_4); +    clear_pending(AFIO_EXTI_4);  }  void __irq_exti9_5(void) {      /* Figure out which channel it came from  */ -    uint32 pending; +    uint32 pending = GET_BITS(EXTI_BASE->PR, 5, 9);      uint32 i; -    pending = REG_GET(EXTI_PR); -    pending = GET_BITS(pending, 5, 9);      /* Dispatch every handler if the pending bit is set */      for (i = 0; i < 5; i++) {          if (pending & 0x1) { -            dispatch_handler(EXTI5 + i); -            clear_pending(EXTI5 + i); +            dispatch_handler(AFIO_EXTI_5 + i); +            clear_pending(AFIO_EXTI_5 + i);          }          pending >>= 1;      } @@ -118,89 +192,59 @@ void __irq_exti9_5(void) {  void __irq_exti15_10(void) {      /* Figure out which channel it came from  */ -    uint32 pending; +    uint32 pending = GET_BITS(EXTI_BASE->PR, 10, 15);      uint32 i; -    pending = REG_GET(EXTI_PR); -    pending = GET_BITS(pending, 10, 15);      /* Dispatch every handler if the pending bit is set */      for (i = 0; i < 6; i++) {          if (pending & 0x1) { -            dispatch_handler(EXTI10 + i); -            clear_pending(EXTI10 + i); +            dispatch_handler(AFIO_EXTI_10 + i); +            clear_pending(AFIO_EXTI_10 + i);          }          pending >>= 1;      }  } - -/** - * @brief Register a handler to run upon external interrupt - * @param port source port of pin (eg EXTI_CONFIG_PORTA) - * @param pin pin number on the source port - * @param handler function handler to execute - * @param mode type of transition to trigger on +/* + * Auxiliary functions   */ -void exti_attach_interrupt(uint32 port, -                           uint32 pin, -                           voidFuncPtr handler, -                           uint32 mode) { -    static uint32 afio_regs[] = { -        AFIO_EXTICR1,         // EXT0-3 -        AFIO_EXTICR2,         // EXT4-7 -        AFIO_EXTICR3,         // EXT8-11 -        AFIO_EXTICR4,         // EXT12-15 -    }; - -    /* Note: All of the following code assumes that EXTI0 = 0  */ -    ASSERT(EXTI0 == 0); -    ASSERT(handler); - -    uint32 channel = pin; -    /* map port to channel */ -    __write(afio_regs[pin/4], (port << ((pin % 4) * 4))); - -    /* Unmask appropriate interrupt line  */ -    __set_bits(EXTI_IMR, BIT(channel)); - -    /* Set trigger mode  */ -    switch (mode) { -    case EXTI_RISING: -        __set_bits(EXTI_RTSR, BIT(channel)); -        break; - -    case EXTI_FALLING: -        __set_bits(EXTI_FTSR, BIT(channel)); -        break; +static inline void clear_pending(uint32 exti_num) { +    *bb_perip(&EXTI_BASE->PR, exti_num) = 1; +    /* If the pending bit is cleared as the last instruction in an ISR, +     * it won't actually be cleared in time and the ISR will fire again. +     * Insert a 2-cycle buffer to allow it to take effect. */ +    asm volatile("nop"); +    asm volatile("nop"); +} -    case EXTI_RISING_FALLING: -        __set_bits(EXTI_RTSR, BIT(channel)); -        __set_bits(EXTI_FTSR, BIT(channel)); -        break; +static inline void dispatch_handler(uint32 exti_num) { +    ASSERT(exti_channels[exti_num].handler); +    if (exti_channels[exti_num].handler) { +        (exti_channels[exti_num].handler)();      } - -    /* Register the handler  */ -    exti_channels[channel].handler = handler; - -    /* Configure the enable interrupt bits for the NVIC  */ -    nvic_irq_enable(exti_channels[channel].irq_line);  } +static inline void enable_irq(afio_exti_num exti) { +    /* Maybe twiddle the IRQ bitmap for extis with multiplexed IRQs */ +    if (exti > 4) { +        uint16 *bitmap = exti < 10 ? &exti_9_5_en : &exti_15_10_en; +        *bb_sramp(bitmap, exti) = 1; +    } -/** - * @brief Unregister an external interrupt handler - * @param channel channel to disable (eg EXTI0) - */ -void exti_detach_interrupt(uint32 channel) { -    ASSERT(channel < NR_EXTI_CHANNELS); -    ASSERT(EXTI0 == 0); - -    __clear_bits(EXTI_IMR,  BIT(channel)); -    __clear_bits(EXTI_FTSR, BIT(channel)); -    __clear_bits(EXTI_RTSR, BIT(channel)); - -    nvic_irq_disable(exti_channels[channel].irq_line); +    nvic_irq_enable(exti_channels[exti].irq_line); +} -    exti_channels[channel].handler = NULL; +static inline void maybe_disable_irq(afio_exti_num exti) { +    if (exti > 4) { +        uint16 *bitmap = exti < 10 ? &exti_9_5_en : &exti_15_10_en; +        *bb_sramp(bitmap, exti) = 0; +        if (*bitmap == 0) { +            /* All of the external interrupts which share this IRQ +             * line are disabled. */ +            nvic_irq_disable(exti_channels[exti].irq_line); +        } +    } else { +        nvic_irq_disable(exti_channels[exti].irq_line); +    }  } diff --git a/libmaple/exti.h b/libmaple/exti.h index 806578f..e145033 100644 --- a/libmaple/exti.h +++ b/libmaple/exti.h @@ -22,145 +22,51 @@   * THE SOFTWARE.   *****************************************************************************/ -  /** - *  @file exti.h - * - *  @brief External interrupt control prototypes and defines + * @file exti.h + * @brief External interrupt control prototypes and defines   */ -#ifndef _EXTI_H_ -#define _EXTI_H_ - -/* Notes: - * - * To generate the interrupt, the interrupt line should be configured - * and enabled. This is done by programming the two trigger registers - * with the desired edge detection and by enabling the interrupt - * request by writing a '1' to the corresponding bit in the interrupt - * mask register.  When the selected edge occurs on the external - * interrupt line, an interrupt request is generated. The pending bit - * corresponding to the interrupt line is also set.  This request is - * reset by writing a '1' in the pending register. - * - * Hardware interrupt selection: - * - * To configure the 20 lines as interrupt sources, use the following - * procedure: - * - * 1) Configure AFIO_EXTIICR[y] to select the source input for EXTIx - *    external interrupt - * 2) Configure the mask bits of the 20 interrupt lines (EXTI_IMR) - * 3) Configure the trigger selection bits of the interrupt lines - *    (EXTI_RTSR and EXTI_FTSR) - * 4) Configure the enable and mask bits that control the NVIC_IRQ - *    channel mapped to the External - * - * Interrupt Controller (EXTI) so that an inerrupt coming from one of - * the 20 lines can be correctly acknowledged. - * - * AFIO clock must be on. - * - * RM0008, page 107: "PD0, PD1 cannot be used for external - * interrupt/event generation on 36, 48, 64-bin packages." - * - * ---------------------------------------------------------------------------- - * Pin to EXTI Line Mappings: - * EXTI0          EXTI1          EXTI2           EXTI3           EXTI4 - * -------------------------------------------------------------------------- - * D2/PA0         D3/PA1         D1/PA2          D0/A6/PA3       D10/A10/PA4 - * D26/EXT7/PB0   D27/EXT8/PB1   D16/A2/PC2      D17/A3/PC3      D18/A4/PC4 - * D14/A0/PC0     D15/PC1        D25/EXT5/PD2 - * - * EXTI5          EXTI6          EXTI7           EXTI8           EXTI9 - * ---------------------------------------------------------------------------- - * D13/A13/PA5    D12/A12/PA6    D11/A11/PA7     D6/PA8          D7/PA9 - * D4/PB5         D5/PB6         D9/PB7          D38/PB8         D23/EXT4/PB9 - * D19/A5/PC5     D34/EXTI15/PC6 D35/EXT16/PC7   D36/PC8         D37/EXT18/PC9 - * - * EXTI10         EXTI11         EXTI12          EXTI13          EXTI14 - * ---------------------------------------------------------------------------- - * D8/PA10        D29/EXT10/PB11 D30/EXTI1/PB12  D31/EXTI12/PB13 D32/EXT13/PB14 - * D28/PB10                                      D20/EXTI1/PC13  D21/EXT2/PC14 - * D25/PC10 - * - * EXTI15 - * ---------------------------------------------------------------------------- - * D33/EXTI14/PB15 - * D22/EXT3/PC15 - * - * - * The 16 EXTI interrupts are mapped to 7 interrupt handlers. - * - * EXTI Lines to Interrupt Mapping: - * EXTI0 -> EXTI0 - * EXTI1 -> EXTI1 - * EXTI2 -> EXTI2 - * EXTI3 -> EXTI3 - * EXTI4 -> EXTI4 - * EXTI[5-9] -> EXT9_5 - * EXTI[10-15] -> EXT15_10 - * - * */ - -#define NR_EXTI_MODES             3 -#define NR_EXTI_CHANNELS         16 -#define NR_EXTI_PORTS            NR_GPIO_PORTS       // board specific +/* See notes/exti.txt for more info */ -#define EXTI_RISING                     0 -#define EXTI_FALLING                    1 -#define EXTI_RISING_FALLING             2 +#include "libmaple.h" +#include "gpio.h" -#define EXTI_IMR        0x40010400        // Interrupt mask register -#define EXTI_EMR        (EXTI_IMR + 0x04) // Event mask register -#define EXTI_RTSR       (EXTI_IMR + 0x08) // Rising trigger selection register -#define EXTI_FTSR       (EXTI_IMR + 0x0C) // Falling trigger selection register -#define EXTI_SWIER      (EXTI_IMR + 0x10) // Software interrupt event register -#define EXTI_PR         (EXTI_IMR + 0x14) // Pending register - -#define AFIO_EVCR       0x40010000 -#define AFIO_EXTICR1    (AFIO_EVCR + 0x08) -#define AFIO_EXTICR2    (AFIO_EVCR + 0x0C) -#define AFIO_EXTICR3    (AFIO_EVCR + 0x10) -#define AFIO_EXTICR4    (AFIO_EVCR + 0x14) - -#define EXTI0  0 -#define EXTI1  1 -#define EXTI2  2 -#define EXTI3  3 -#define EXTI4  4 -#define EXTI5  5 -#define EXTI6  6 -#define EXTI7  7 -#define EXTI8  8 -#define EXTI9  9 -#define EXTI10 10 -#define EXTI11 11 -#define EXTI12 12 -#define EXTI13 13 -#define EXTI14 14 -#define EXTI15 15 - -#define EXTI_CONFIG_PORTA 0     // Maple, Maple Native, Maple Mini -#define EXTI_CONFIG_PORTB 1     // Maple, Maple Native, Maple Mini -#define EXTI_CONFIG_PORTC 2     // Maple, Maple Native, Maple Mini -#define EXTI_CONFIG_PORTD 3     // Maple and Maple Native only -#define EXTI_CONFIG_PORTE 4     // Native only -#define EXTI_CONFIG_PORTF 5     // Native only -#define EXTI_CONFIG_PORTG 6     // Native only +#ifndef _EXTI_H_ +#define _EXTI_H_  #ifdef __cplusplus  extern "C"{  #endif -void exti_attach_interrupt(uint32 port, uint32 pin, voidFuncPtr handler, -                           uint32 mode); -void exti_detach_interrupt(uint32 channel); +/** EXTI register map type */ +typedef struct exti_reg_map { +    __io uint32 IMR;   /**< Interrupt mask register */ +    __io uint32 EMR;   /**< Event mask register */ +    __io uint32 RTSR;  /**< Rising trigger selection register */ +    __io uint32 FTSR;  /**< Falling trigger selection register */ +    __io uint32 SWIER; /**< Software interrupt event register */ +    __io uint32 PR;    /**< Pending register */ +} exti_reg_map; + +/** EXTI register map base pointer */ +#define EXTI_BASE             ((exti_reg_map*)0x40010400) + +/** External interrupt trigger mode */ +typedef enum exti_trigger_mode { +    EXTI_RISING,         /**< Trigger on the rising edge */ +    EXTI_FALLING,        /**< Trigger on the falling edge */ +    EXTI_RISING_FALLING  /**< Trigger on both the rising and falling edges */ +} exti_trigger_mode; + +void exti_attach_interrupt(afio_exti_num num, +                           afio_exti_port port, +                           voidFuncPtr handler, +                           exti_trigger_mode mode); +void exti_detach_interrupt(afio_exti_num num);  #ifdef __cplusplus  } // extern "C"  #endif -  #endif - diff --git a/libmaple/flash.c b/libmaple/flash.c index 1d7bfa6..c921256 100644 --- a/libmaple/flash.c +++ b/libmaple/flash.c @@ -28,41 +28,30 @@  #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) - -/* flash wait states  */ -#define ACR_LATENCY                     (0x7) - -#define FLASH_WRITE_ACR(val)            __write(FLASH_ACR, val) -#define FLASH_READ_ACR()                __read(FLASH_ACR) +#include "bitband.h"  /** - * @brief turn on the hardware prefetcher + * @brief Turn on the hardware prefetcher.   */  void flash_enable_prefetch(void) { -    uint32 val = FLASH_READ_ACR(); - -    val |= ACR_PRFTBE_ENABLE; - -    FLASH_WRITE_ACR(val); +    *bb_perip(&FLASH_BASE->ACR, FLASH_ACR_PRFTBE_BIT) = 1;  }  /** - * @brief set flash wait states - * @param number of wait states + * @brief Set flash wait states + * + * See ST PM0042, section 3.1 for restrictions on the acceptable value + * of wait_states for a given SYSCLK configuration. + * + * @param wait_states number of wait states (one of + *                    FLASH_WAIT_STATE_0, FLASH_WAIT_STATE_1, + *                    FLASH_WAIT_STATE_2).   */  void flash_set_latency(uint32 wait_states) { -    uint32 val = FLASH_READ_ACR(); +    uint32 val = FLASH_BASE->ACR; -    val &= ~ACR_LATENCY; +    val &= ~FLASH_ACR_LATENCY;      val |= wait_states; -    FLASH_WRITE_ACR(val); +    FLASH_BASE->ACR = val;  } diff --git a/libmaple/flash.h b/libmaple/flash.h index 7b74c83..9db5015 100644 --- a/libmaple/flash.h +++ b/libmaple/flash.h @@ -25,20 +25,108 @@  /**   * @file flash.h - * @brief basic stm32 flash setup routines + * @brief STM32 Medium and high density Flash register map and setup + * routines   */  #ifndef _FLASH_H_  #define _FLASH_H_ -#define FLASH_WAIT_STATE_0              0x0 -#define FLASH_WAIT_STATE_1              0x1 -#define FLASH_WAIT_STATE_2              0x2 -  #ifdef __cplusplus  extern "C"{  #endif +/** Flash register map type */ +typedef struct flash_reg_map { +    __io uint32 ACR;            /**< Access control register */ +    __io uint32 KEYR;           /**< Key register */ +    __io uint32 OPTKEYR;        /**< OPTKEY register */ +    __io uint32 SR;             /**< Status register */ +    __io uint32 CR;             /**< Control register */ +    __io uint32 AR;             /**< Address register */ +    __io uint32 OBR;            /**< Option byte register */ +    __io uint32 WRPR;           /**< Write protection register */ +} flash_reg_map; + +/** Flash register map base pointer */ +#define FLASH_BASE                      ((flash_reg_map*)0x40022000) + +/* + * Register bit definitions + */ + +/* Access control register */ + +#define FLASH_ACR_PRFTBS_BIT            5 +#define FLASH_ACR_PRFTBE_BIT            4 +#define FLASH_ACR_HLFCYA_BIT            3 + +#define FLASH_ACR_PRFTBS                BIT(FLASH_ACR_PRFTBS_BIT) +#define FLASH_ACR_PRFTBE                BIT(FLASH_ACR_PRFTBE_BIT) +#define FLASH_ACR_HLFCYA                BIT(FLASH_ACR_HLFCYA_BIT) +#define FLASH_ACR_LATENCY               0x7 + +/* Status register */ + +#define FLASH_SR_EOP_BIT                5 +#define FLASH_SR_WRPRTERR_BIT           4 +#define FLASH_SR_PGERR_BIT              2 +#define FLASH_SR_BSY_BIT                0 + +#define FLASH_SR_EOP                    BIT(FLASH_SR_EOP_BIT) +#define FLASH_SR_WRPRTERR               BIT(FLASH_SR_WRPRTERR_BIT) +#define FLASH_SR_PGERR                  BIT(FLASH_SR_PGERR_BIT) +#define FLASH_SR_BSY                    BIT(FLASH_SR_BSY_BIT) + +/* Control register */ + +#define FLASH_CR_EOPIE_BIT              12 +#define FLASH_CR_ERRIE_BIT              10 +#define FLASH_CR_OPTWRE_BIT             9 +#define FLASH_CR_LOCK_BIT               7 +#define FLASH_CR_STRT_BIT               6 +#define FLASH_CR_OPTER_BIT              5 +#define FLASH_CR_OPTPG_BIT              4 +#define FLASH_CR_MER_BIT                2 +#define FLASH_CR_PER_BIT                1 +#define FLASH_CR_PG_BIT                 0 + +#define FLASH_CR_EOPIE                  BIT(FLASH_CR_EOPIE_BIT) +#define FLASH_CR_ERRIE                  BIT(FLASH_CR_ERRIE_BIT) +#define FLASH_CR_OPTWRE                 BIT(FLASH_CR_OPTWRE_BIT) +#define FLASH_CR_LOCK                   BIT(FLASH_CR_LOCK_BIT) +#define FLASH_CR_STRT                   BIT(FLASH_CR_STRT_BIT) +#define FLASH_CR_OPTER                  BIT(FLASH_CR_OPTER_BIT) +#define FLASH_CR_OPTPG                  BIT(FLASH_CR_OPTPG_BIT) +#define FLASH_CR_MER                    BIT(FLASH_CR_MER_BIT) +#define FLASH_CR_PER                    BIT(FLASH_CR_PER_BIT) +#define FLASH_CR_PG                     BIT(FLASH_CR_PG_BIT) + +/* Option byte register */ + +#define FLASH_OBR_nRST_STDBY_BIT        4 +#define FLASH_OBR_nRST_STOP_BIT         3 +#define FLASH_OBR_WDG_SW_BIT            2 +#define FLASH_OBR_RDPRT_BIT             1 +#define FLASH_OBR_OPTERR_BIT            0 + +#define FLASH_OBR_DATA1                 (0xFF << 18) +#define FLASH_OBR_DATA0                 (0xFF << 10) +#define FLASH_OBR_USER                  0x3FF +#define FLASH_OBR_nRST_STDBY            BIT(FLASH_OBR_nRST_STDBY_BIT) +#define FLASH_OBR_nRST_STOP             BIT(FLASH_OBR_nRST_STOP_BIT) +#define FLASH_OBR_WDG_SW                BIT(FLASH_OBR_WDG_SW_BIT) +#define FLASH_OBR_RDPRT                 BIT(FLASH_OBR_RDPRT_BIT) +#define FLASH_OBR_OPTERR                BIT(FLASH_OBR_OPTERR_BIT) + +/* + * Setup routines + */ + +#define FLASH_WAIT_STATE_0              0x0 +#define FLASH_WAIT_STATE_1              0x1 +#define FLASH_WAIT_STATE_2              0x2 +  void flash_enable_prefetch(void);  void flash_set_latency(uint32 wait_states); diff --git a/libmaple/fsmc.c b/libmaple/fsmc.c index 49526f4..70d7e0d 100644 --- a/libmaple/fsmc.c +++ b/libmaple/fsmc.c @@ -31,104 +31,62 @@  #include "gpio.h"  #include "fsmc.h" -/* These values determined for a particular SRAM chip by following the - * calculations in the ST FSMC application note. */ -#define FSMC_ADDSET 0x0 -#define FSMC_DATAST 0x3 +#ifdef STM32_HIGH_DENSITY -/* Sets up the FSMC peripheral to use the SRAM chip on the maple - * native as an external segment of system memory space.  This - * implementation is for the IS62WV51216BLL 8mbit chip (55ns - * timing) */ -void fsmc_native_sram_init(void) { -    FSMC_Bank *bank; - -    /* First we setup all the GPIO pins. */ +/** + * Configure FSMC GPIOs for use with SRAM. + */ +void fsmc_sram_init_gpios(void) {      /* Data lines... */ -    gpio_set_mode(GPIOD_BASE,  0, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOD_BASE,  1, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOD_BASE,  8, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOD_BASE,  9, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOD_BASE, 10, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOD_BASE, 14, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOD_BASE, 15, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOE_BASE,  7, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOE_BASE,  8, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOE_BASE,  9, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOE_BASE, 10, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOE_BASE, 11, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOE_BASE, 12, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOE_BASE, 13, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOE_BASE, 14, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOE_BASE, 15, MODE_AF_OUTPUT_PP); +    gpio_set_mode(GPIOD,  0, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOD,  1, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOD,  8, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOD,  9, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOD, 10, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOD, 14, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOD, 15, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOE,  7, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOE,  8, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOE,  9, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOE, 10, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOE, 11, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOE, 12, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOE, 13, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOE, 14, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOE, 15, GPIO_AF_OUTPUT_PP);      /* Address lines... */ -    gpio_set_mode(GPIOD_BASE, 11, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOD_BASE, 12, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOD_BASE, 13, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOF_BASE,  0, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOF_BASE,  1, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOF_BASE,  2, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOF_BASE,  3, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOF_BASE,  4, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOF_BASE,  5, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOF_BASE, 12, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOF_BASE, 13, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOF_BASE, 14, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOF_BASE, 15, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOG_BASE,  0, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOG_BASE,  1, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOG_BASE,  2, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOG_BASE,  3, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOG_BASE,  4, MODE_AF_OUTPUT_PP); -    gpio_set_mode(GPIOG_BASE,  5, MODE_AF_OUTPUT_PP); +    gpio_set_mode(GPIOD, 11, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOD, 12, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOD, 13, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOF,  0, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOF,  1, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOF,  2, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOF,  3, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOF,  4, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOF,  5, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOF, 12, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOF, 13, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOF, 14, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOF, 15, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOG,  0, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOG,  1, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOG,  2, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOG,  3, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOG,  4, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(GPIOG,  5, GPIO_AF_OUTPUT_PP);      /* And control lines... */ -    gpio_set_mode(GPIOD_BASE,  4, MODE_AF_OUTPUT_PP);   // NOE -    gpio_set_mode(GPIOD_BASE,  5, MODE_AF_OUTPUT_PP);   // NWE - -    gpio_set_mode(GPIOD_BASE,  7, MODE_AF_OUTPUT_PP);   // NE1 -    gpio_set_mode(GPIOG_BASE,  9, MODE_AF_OUTPUT_PP);   // NE2 -    gpio_set_mode(GPIOG_BASE, 10, MODE_AF_OUTPUT_PP);   // NE3 -    gpio_set_mode(GPIOG_BASE, 12, MODE_AF_OUTPUT_PP);   // NE4 - -    gpio_set_mode(GPIOE_BASE,  0, MODE_AF_OUTPUT_PP);   // NBL0 -    gpio_set_mode(GPIOE_BASE,  1, MODE_AF_OUTPUT_PP);   // NBL1 - -    /* Next enable the clock */ -    rcc_clk_enable(RCC_FSMC); - -    /* Then we configure channel 1 the FSMC SRAM peripheral (all SRAM -     * channels are in "Bank 1" of the FSMC) */ -    bank = (FSMC_Bank*)(FSMC1_BASE); - -    /* Everything else is cleared (BCR1) */ -    bank->BCR = 0x0000; - -    /* Memory type is SRAM */ -    bank->BCR &= ~(FSMC_BCR_MTYP);  // '00' - -    /* Databus width is 16bits */ -    bank->BCR &= ~(FSMC_BCR_MWID); -    bank->BCR |= 0x1 << 4;          // '01' - -    /* Memory is nonmultiplexed */ -    bank->BCR &= ~(FSMC_BCR_MUXEN); // '0' - -    /* Need write enable to write to the chip */ -    bank->BCR |= FSMC_BCR_WREN; - -    /* Set ADDSET */ -    bank->BTR &= ~(FSMC_BTR_ADDSET); -    bank->BTR |= (FSMC_BTR_ADDSET | FSMC_ADDSET); - -    /* Set DATAST */ -    bank->BTR &= ~(FSMC_BTR_DATAST); -    bank->BTR |= (FSMC_BTR_DATAST | (FSMC_DATAST << 8)); +    gpio_set_mode(GPIOD,  4, GPIO_AF_OUTPUT_PP);   // NOE +    gpio_set_mode(GPIOD,  5, GPIO_AF_OUTPUT_PP);   // NWE -    /* Enable channel 1 */ -    bank->BCR |= FSMC_BCR_MBKEN;    // '1' +    gpio_set_mode(GPIOD,  7, GPIO_AF_OUTPUT_PP);   // NE1 +    gpio_set_mode(GPIOG,  9, GPIO_AF_OUTPUT_PP);   // NE2 +    gpio_set_mode(GPIOG, 10, GPIO_AF_OUTPUT_PP);   // NE3 +    gpio_set_mode(GPIOG, 12, GPIO_AF_OUTPUT_PP);   // NE4 -    /* (FSMC_BWTR3 not used for this simple configuration.) */ +    gpio_set_mode(GPIOE,  0, GPIO_AF_OUTPUT_PP);   // NBL0 +    gpio_set_mode(GPIOE,  1, GPIO_AF_OUTPUT_PP);   // NBL1  } +#endif  /* STM32_HIGH_DENSITY */ diff --git a/libmaple/fsmc.h b/libmaple/fsmc.h index e83b529..fccaf0b 100644 --- a/libmaple/fsmc.h +++ b/libmaple/fsmc.h @@ -37,54 +37,275 @@  extern "C"{  #endif -// There are 4 FSMC chip-select devices; here are the SRAM-specific registers -// for each - -#define FSMC1_BASE  0xA0000000 -#define FSMC2_BASE  0xA0000008 -#define FSMC3_BASE  0xA0000010 -#define FSMC4_BASE  0xA0000018 - -typedef struct { -    volatile uint32 BCR; -    volatile uint32 BTR; -    //uint32 pad[62];      // double check this? -    //__io uint32 BWTR; -} FSMC_Bank; - -// And here are the register bit ranges -#define FSMC_BCR_MBKEN      0b00000000000000000000000000000001 -#define FSMC_BCR_MUXEN      0b00000000000000000000000000000010 -#define FSMC_BCR_MTYP       0b00000000000000000000000000001100 -#define FSMC_BCR_MWID       0b00000000000000000000000000110000 -#define FSMC_BCR_FACCEN     0b00000000000000000000000001000000 -#define FSMC_BCR_BURSTEN    0b00000000000000000000000100000000 -#define FSMC_BCR_WAITPOL    0b00000000000000000000001000000000 -#define FSMC_BCR_WRAPMOD    0b00000000000000000000010000000000 -#define FSMC_BCR_WAITCFG    0b00000000000000000000100000000000 -#define FSMC_BCR_WREN       0b00000000000000000001000000000000 -#define FSMC_BCR_WAITEN     0b00000000000000000010000000000000 -#define FSMC_BCR_EXTMOD     0b00000000000000000100000000000000 -#define FSMC_BCR_CBURSTRW   0b00000000000010000000000000000000 -#define FSMC_BTR_ADDSET     0b00000000000000000000000000001111 -#define FSMC_BTR_ADDHOLD    0b00000000000000000000000011110000 -#define FSMC_BTR_DATAST     0b00000000000000001111111100000000 -#define FSMC_BTR_BUSTURN    0b00000000000011110000000000000000 -#define FSMC_BTR_CLKDIV     0b00000000111100000000000000000000 -#define FSMC_BTR_DATALAT    0b00001111000000000000000000000000 -#define FSMC_BTR_ACCMOD     0b00110000000000000000000000000000 -#define FSMC_BWTR_ADDSET    0b00000000000000000000000000001111 -#define FSMC_BWTR_ADDHLD    0b00000000000000000000000011110000 -#define FSMC_BWTR_DATAST    0b00000000000000001111111100000000 -#define FSMC_BWTR_CLKDIV    0b00000000111100000000000000000000 -#define FSMC_BWTR_DATLAT    0b00001111000000000000000000000000 -#define FSMC_BWTR_ACCMOD    0b00110000000000000000000000000000 - -void fsmc_native_sram_init(void); +#ifdef STM32_HIGH_DENSITY + +/* + * Register maps and devices + */ + +/** FSMC register map type */ +typedef struct fsmc_reg_map { +    __io uint32 BCR1; /**< SRAM/NOR-Flash chip-select control register 1 */ +    __io uint32 BTR1; /**< SRAM/NOR-Flash chip-select timing register 1 */ +    __io uint32 BCR2; /**< SRAM/NOR-Flash chip-select control register 2 */ +    __io uint32 BTR2; /**< SRAM/NOR-Flash chip-select timing register 2 */ +    __io uint32 BCR3; /**< SRAM/NOR-Flash chip-select control register 3 */ +    __io uint32 BTR3; /**< SRAM/NOR-Flash chip-select timing register 3 */ +    __io uint32 BCR4; /**< SRAM/NOR-Flash chip-select control register 4 */ +    __io uint32 BTR4; /**< SRAM/NOR-Flash chip-select timing register 4 */ +    const uint8 RESERVED1[64];  /**< Reserved */ +    __io uint32 PCR2;  /**< PC Card/NAND Flash control register 2 */ +    __io uint32 SR2;   /**< FIFO status and interrupt register 2 */ +    __io uint32 PMEM2; /**< Common memory space timing register 2 */ +    __io uint32 PATT2; /**< Attribute memory space timing register 2 */ +    const uint8 RESERVED2[4];   /**< Reserved */ +    __io uint32 ECCR2; /**< ECC result register 2 */ +    const uint8 RESERVED3[2]; +    __io uint32 PCR3;  /**< PC Card/NAND Flash control register 3 */ +    __io uint32 SR3;   /**< FIFO status and interrupt register 3 */ +    __io uint32 PMEM3; /**< Common memory space timing register 3 */ +    __io uint32 PATT3; /**< Attribute memory space timing register 3 */ +    const uint32 RESERVED4;     /**< Reserved */ +    __io uint32 ECCR3; /**< ECC result register 3 */ +    const uint8 RESERVED5[8];   /**< Reserved */ +    __io uint32 PCR4;  /**< PC Card/NAND Flash control register 4 */ +    __io uint32 SR4;   /**< FIFO status and interrupt register 4 */ +    __io uint32 PMEM4; /**< Common memory space timing register 4 */ +    __io uint32 PATT4; /**< Attribute memory space timing register 4 */ +    __io uint32 PIO4;  /**< I/O space timing register 4 */ +    const uint8 RESERVED6[80];  /**< Reserved */ +    __io uint32 BWTR1; /**< SRAM/NOR-Flash write timing register 1 */ +    const uint32 RESERVED7;     /**< Reserved */ +    __io uint32 BWTR2; /**< SRAM/NOR-Flash write timing register 2 */ +    const uint32 RESERVED8;     /**< Reserved */ +    __io uint32 BWTR3; /**< SRAM/NOR-Flash write timing register 3 */ +    const uint32 RESERVED9;     /**< Reserved */ +    __io uint32 BWTR4; /**< SRAM/NOR-Flash write timing register 4 */ +} __attribute__((packed)) fsmc_reg_map; + +#define __FSMC_B                        0xA0000000 + +/** FSMC register map base pointer */ +#define FSMC_BASE                       ((struct fsmc_reg_map*)__FSMC_B) + +/** FSMC NOR/PSRAM register map type */ +typedef struct fsmc_nor_psram_reg_map { +    __io uint32 BCR;            /**< Chip-select control register */ +    __io uint32 BTR;            /**< Chip-select timing register */ +    const uint8 RESERVED[252];  /**< Reserved */ +    __io uint32 BWTR;           /**< Write timing register */ +} fsmc_nor_psram_reg_map; + +/** FSMC NOR/PSRAM base pointer 1 */ +#define FSMC_NOR_PSRAM1_BASE ((struct fsmc_nor_psram_reg_map*)__FSMC_B) + +/** FSMC NOR/PSRAM base pointer 2 */ +#define FSMC_NOR_PSRAM2_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMC_B + 0x8)) + +/** FSMC NOR/PSRAM base pointer 3 */ +#define FSMC_NOR_PSRAM3_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMC_B+0x10)) + +/** FSMC NOR/PSRAM base pointer 4 */ +#define FSMC_NOR_PSRAM4_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMC_B+0x18)) + +/* + * Register bit definitions + */ + +/* NOR/PSRAM chip-select control registers */ + +#define FSMC_BCR_CBURSTRW_BIT           19 +#define FSMC_BCR_ASYNCWAIT_BIT          15 +#define FSMC_BCR_EXTMOD_BIT             14 +#define FSMC_BCR_WAITEN_BIT             13 +#define FSMC_BCR_WREN_BIT               12 +#define FSMC_BCR_WAITCFG_BIT            11 +#define FSMC_BCR_WRAPMOD_BIT            10 +#define FSMC_BCR_WAITPOL_BIT            9 +#define FSMC_BCR_BURSTEN_BIT            8 +#define FSMC_BCR_FACCEN_BIT             6 +#define FSMC_BCR_MUXEN_BIT              1 +#define FSMC_BCR_MBKEN_BIT              0 + +#define FSMC_BCR_CBURSTRW               BIT(FSMC_BCR_CBURSTRW_BIT) +#define FSMC_BCR_ASYNCWAIT              BIT(FSMC_BCR_ASYNCWAIT_BIT) +#define FSMC_BCR_EXTMOD                 BIT(FSMC_BCR_EXTMOD_BIT) +#define FSMC_BCR_WAITEN                 BIT(FSMC_BCR_WAITEN_BIT) +#define FSMC_BCR_WREN                   BIT(FSMC_BCR_WREN_BIT) +#define FSMC_BCR_WAITCFG                BIT(FSMC_BCR_WAITCFG_BIT) +#define FSMC_BCR_WRAPMOD                BIT(FSMC_BCR_WRAPMOD_BIT) +#define FSMC_BCR_WAITPOL                BIT(FSMC_BCR_WAITPOL_BIT) +#define FSMC_BCR_BURSTEN                BIT(FSMC_BCR_BURSTEN_BIT) +#define FSMC_BCR_FACCEN                 BIT(FSMC_BCR_FACCEN_BIT) +#define FSMC_BCR_MWID                   (0x3 << 4) +#define FSMC_BCR_MWID_8BITS             (0x0 << 4) +#define FSMC_BCR_MWID_16BITS            (0x1 << 4) +#define FSMC_BCR_MTYP                   (0x3 << 2) +#define FSMC_BCR_MTYP_SRAM              (0x0 << 2) +#define FSMC_BCR_MTYP_PSRAM             (0x1 << 2) +#define FSMC_BCR_MTYP_NOR_FLASH         (0x2 << 2) +#define FSMC_BCR_MUXEN                  BIT(FSMC_BCR_MUXEN_BIT) +#define FSMC_BCR_MBKEN                  BIT(FSMC_BCR_MBKEN_BIT) + +/* SRAM/NOR-Flash chip-select timing registers */ + +#define FSMC_BTR_ACCMOD                 (0x3 << 28) +#define FSMC_BTR_ACCMOD_A               (0x0 << 28) +#define FSMC_BTR_ACCMOD_B               (0x1 << 28) +#define FSMC_BTR_ACCMOD_C               (0x2 << 28) +#define FSMC_BTR_ACCMOD_D               (0x3 << 28) +#define FSMC_BTR_DATLAT                 (0xF << 24) +#define FSMC_BTR_CLKDIV                 (0xF << 20) +#define FSMC_BTR_BUSTURN                (0xF << 16) +#define FSMC_BTR_DATAST                 (0xFF << 8) +#define FSMC_BTR_ADDHLD                 (0xF << 4) +#define FSMC_BTR_ADDSET                 0xF + +/* SRAM/NOR-Flash write timing registers */ + +#define FSMC_BWTR_ACCMOD                 (0x3 << 28) +#define FSMC_BWTR_ACCMOD_A               (0x0 << 28) +#define FSMC_BWTR_ACCMOD_B               (0x1 << 28) +#define FSMC_BWTR_ACCMOD_C               (0x2 << 28) +#define FSMC_BWTR_ACCMOD_D               (0x3 << 28) +#define FSMC_BWTR_DATLAT                 (0xF << 24) +#define FSMC_BWTR_CLKDIV                 (0xF << 20) +#define FSMC_BWTR_DATAST                 (0xFF << 8) +#define FSMC_BWTR_ADDHLD                 (0xF << 4) +#define FSMC_BWTR_ADDSET                 0xF + +/* NAND Flash/PC Card controller registers */ + +#define FSMC_PCR_ECCEN_BIT               6 +#define FSMC_PCR_PTYP_BIT                3 +#define FSMC_PCR_PBKEN_BIT               2 +#define FSMC_PCR_PWAITEN_BIT             1 + +#define FSMC_PCR_ECCPS                   (0x7 << 17) +#define FSMC_PCR_ECCPS_256B              (0x0 << 17) +#define FSMC_PCR_ECCPS_512B              (0x1 << 17) +#define FSMC_PCR_ECCPS_1024B             (0x2 << 17) +#define FSMC_PCR_ECCPS_2048B             (0x3 << 17) +#define FSMC_PCR_ECCPS_4096B             (0x4 << 17) +#define FSMC_PCR_ECCPS_8192B             (0x5 << 17) +#define FSMC_PCR_TAR                     (0xF << 13) +#define FSMC_PCR_TCLR                    (0xF << 9) +#define FSMC_PCR_ECCEN                   BIT(FSMC_PCR_ECCEN_BIT) +#define FSMC_PCR_PWID                    (0x3 << 4) +#define FSMC_PCR_PWID_8BITS              (0x0 << 4) +#define FSMC_PCR_PWID_16BITS             (0x1 << 4) +#define FSMC_PCR_PTYP                    BIT(FSMC_PCR_PTYP_BIT) +#define FSMC_PCR_PTYP_PC_CF_PCMCIA       (0x0 << FSMC_PCR_PTYP_BIT) +#define FSMC_PCR_PTYP_NAND               (0x1 << FSMC_PCR_PTYP_BIT) +#define FSMC_PCR_PBKEN                   BIT(FSMC_PCR_PBKEN_BIT) +#define FSMC_PCR_PWAITEN                 BIT(FSMC_PCR_PWAITEN_BIT) + +/* FIFO status and interrupt registers */ + +#define FSMC_SR_FEMPT_BIT                6 +#define FSMC_SR_IFEN_BIT                 5 +#define FSMC_SR_ILEN_BIT                 4 +#define FSMC_SR_IREN_BIT                 3 +#define FSMC_SR_IFS_BIT                  2 +#define FSMC_SR_ILS_BIT                  1 +#define FSMC_SR_IRS_BIT                  0 + +#define FSMC_SR_FEMPT                    BIT(FSMC_SR_FEMPT_BIT) +#define FSMC_SR_IFEN                     BIT(FSMC_SR_IFEN_BIT) +#define FSMC_SR_ILEN                     BIT(FSMC_SR_ILEN_BIT) +#define FSMC_SR_IREN                     BIT(FSMC_SR_IREN_BIT) +#define FSMC_SR_IFS                      BIT(FSMC_SR_IFS_BIT) +#define FSMC_SR_ILS                      BIT(FSMC_SR_ILS_BIT) +#define FSMC_SR_IRS                      BIT(FSMC_SR_IRS_BIT) + +/* Common memory space timing registers */ + +#define FSMC_PMEM_MEMHIZ                 (0xFF << 24) +#define FSMC_PMEM_MEMHOLD                (0xFF << 16) +#define FSMC_PMEM_MEMWAIT                (0xFF << 8) +#define FSMC_PMEM_MEMSET                 0xFF + +/* Attribute memory space timing registers */ + +#define FSMC_PATT_ATTHIZ                 (0xFF << 24) +#define FSMC_PATT_ATTHOLD                (0xFF << 16) +#define FSMC_PATT_ATTWAIT                (0xFF << 8) +#define FSMC_PATT_ATTSET                 0xFF + +/* I/O space timing register 4 */ + +#define FSMC_PIO_IOHIZ                  (0xFF << 24) +#define FSMC_PIO_IOHOLD                 (0xFF << 16) +#define FSMC_PIO_IOWAIT                 (0xFF << 8) +#define FSMC_PIO_IOSET                  0xFF + +/* + * Memory bank boundary addresses + */ + +/** Pointer to base address of FSMC memory bank 1 (split into 4 + * regions, each supporting 1 NOR Flash, SRAM, or PSRAM chip)  */ +#define FSMC_BANK1                      ((void*)0x60000000) + +/** Pointer to base address of FSMC memory bank 1, region 1 (for NOR/PSRAM) */ +#define FSMC_NOR_PSRAM_REGION1          FSMC_BANK1 + +/** Pointer to base address of FSMC memory bank 1, region 2 (for NOR/PSRAM) */ +#define FSMC_NOR_PSRAM_REGION2          ((void*)0x64000000) + +/** Pointer to base address of FSMC memory bank 1, region 3 (for NOR/PSRAM) */ +#define FSMC_NOR_PSRAM_REGION3          ((void*)0x68000000) + +/** Pointer to base address of FSMC memory bank 1, region 4 (for NOR/PSRAM) */ +#define FSMC_NOR_PSRAM_REGION4          ((void*)0x6C000000) + +/** Pointer to base address of FSMC memory bank 2 (for NAND Flash) */ +#define FSMC_BANK2                      ((void*)0x70000000) + +/** Pointer to base address of FSMC memory bank 3 (for NAND Flash) */ +#define FSMC_BANK3                      ((void*)0x80000000) + +/** Pointer to base address of FSMC memory bank 4 (for PC card devices */ +#define FSMC_BANK4                      ((void*)0x90000000) + +/* + * SRAM/NOR Flash routines + */ + +void fsmc_sram_init_gpios(void); + +/** + * Set the DATAST bits in the given NOR/PSRAM register map's + * chip-select timing register (FSMC_BTR). + * + * @param regs   NOR Flash/PSRAM register map whose chip-select timing + *               register to set. + * @param datast Value to use for DATAST bits. + */ +static inline void fsmc_nor_psram_set_datast(fsmc_nor_psram_reg_map *regs, +                                             uint8 datast) { +    regs->BTR &= ~FSMC_BTR_DATAST; +    regs->BTR |= datast << 8; +} + +/** + * Set the ADDHLD bits in the given NOR/PSRAM register map's chip + * select timing register (FSMC_BTRx). + * + * @param regs   NOR Flash/PSRAM register map whose chip-select timing + *               register to set. + * @param addset Value to use for ADDSET bits. + */ +static inline void fsmc_nor_psram_set_addset(fsmc_nor_psram_reg_map *regs, +                                             uint8 addset) { +    regs->BTR &= ~FSMC_BTR_ADDSET; +    regs->BTR |= addset & 0xF; +} + +#endif /* STM32_HIGH_DENSITY */  #ifdef __cplusplus -} // extern "C" +} /* extern "C" */  #endif -  #endif diff --git a/libmaple/gpio.c b/libmaple/gpio.c index 71e5230..18b856b 100644 --- a/libmaple/gpio.c +++ b/libmaple/gpio.c @@ -26,44 +26,144 @@   * @brief GPIO initialization routine   */ -#include "libmaple.h" -#include "rcc.h"  #include "gpio.h" +#include "rcc.h" + +/* + * GPIO devices + */ + +gpio_dev gpioa = { +    .regs   = GPIOA_BASE, +    .clk_id = RCC_GPIOA +}; +gpio_dev* const GPIOA = &gpioa; + +gpio_dev gpiob = { +    .regs   = GPIOB_BASE, +    .clk_id = RCC_GPIOB +}; +gpio_dev* const GPIOB = &gpiob; + +gpio_dev gpioc = { +    .regs   = GPIOC_BASE, +    .clk_id = RCC_GPIOC +}; +gpio_dev* const GPIOC = &gpioc; + +gpio_dev gpiod = { +    .regs   = GPIOD_BASE, +    .clk_id = RCC_GPIOD +}; +gpio_dev* const GPIOD = &gpiod; + +#ifdef STM32_HIGH_DENSITY +gpio_dev gpioe = { +    .regs   = GPIOE_BASE, +    .clk_id = RCC_GPIOE +}; +gpio_dev* const GPIOE = &gpioe; + +gpio_dev gpiof = { +    .regs   = GPIOF_BASE, +    .clk_id = RCC_GPIOF +}; +gpio_dev* const GPIOF = &gpiof; -void gpio_init(void) { -    rcc_clk_enable(RCC_GPIOA); -    rcc_clk_enable(RCC_GPIOB); -    rcc_clk_enable(RCC_GPIOC); -#if NR_GPIO_PORTS >= 4          /* Maple, but not Maple Mini */ -    rcc_clk_enable(RCC_GPIOD); -#elif NR_GPIO_PORTS >= 7        /* Maple Native (high density only) */ -    rcc_clk_enable(RCC_GPIOE); -    rcc_clk_enable(RCC_GPIOF); -    rcc_clk_enable(RCC_GPIOG); +gpio_dev gpiog = { +    .regs   = GPIOG_BASE, +    .clk_id = RCC_GPIOG +}; +gpio_dev* const GPIOG = &gpiog;  #endif -    rcc_clk_enable(RCC_AFIO); + +/* + * GPIO convenience routines + */ + +/** + * Initialize a GPIO device. + * + * Enables the clock for and resets the given device. + * + * @param dev GPIO device to initialize. + */ +void gpio_init(gpio_dev *dev) { +    rcc_clk_enable(dev->clk_id); +    rcc_reset_dev(dev->clk_id);  } -void gpio_set_mode(GPIO_Port* port, uint8 gpio_pin, GPIOPinMode mode) { -    uint32 tmp; -    uint32 shift = POS(gpio_pin % 8); -    GPIOReg CR; +/** + * Initialize and reset all available GPIO devices. + */ +void gpio_init_all(void) { +    gpio_init(GPIOA); +    gpio_init(GPIOB); +    gpio_init(GPIOC); +    gpio_init(GPIOD); +#ifdef STM32_HIGH_DENSITY +    gpio_init(GPIOE); +    gpio_init(GPIOF); +    gpio_init(GPIOG); +#endif +} -    ASSERT(port); -    ASSERT(gpio_pin < 16); +/** + * Set the mode of a GPIO pin. + * + * @param dev GPIO device. + * @param pin Pin on the device whose mode to set, 0--15. + * @param mode General purpose or alternate function mode to set the pin to. + * @see gpio_pin_mode + */ +void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) { +    gpio_reg_map *regs = dev->regs; +    __io uint32 *cr = ®s->CRL + (pin >> 3); +    uint32 shift = (pin & 0x7) * 4; +    uint32 tmp = *cr; + +    tmp &= ~(0xF << shift); +    tmp |= (mode == GPIO_INPUT_PU ? GPIO_INPUT_PD : mode) << shift; +    *cr = tmp; -    if (mode == GPIO_MODE_INPUT_PU) { -        port->ODR |= BIT(gpio_pin); -        mode = CNF_INPUT_PD; -    } else if (mode == GPIO_MODE_INPUT_PD) { -        port->ODR &= ~BIT(gpio_pin); +    if (mode == GPIO_INPUT_PD) { +        regs->ODR &= ~BIT(pin); +    } else if (mode == GPIO_INPUT_PU) { +        regs->ODR |= BIT(pin);      } +} + +/* + * AFIO + */ -    CR = (gpio_pin < 8) ? &(port->CRL) : &(port->CRH); +/** + * Initialize the AFIO clock, and reset the AFIO registers. + */ +void afio_init(void) { +    rcc_clk_enable(RCC_AFIO); +    rcc_reset_dev(RCC_AFIO); +} -    tmp = *CR; -    tmp &= POS_MASK(shift); -    tmp |= mode << shift; +#define AFIO_EXTI_SEL_MASK 0xF + +/** + * Select a source input for an external interrupt. + * + * @param exti      External interrupt.  One of: AFIO_EXTI_0, + *                  AFIO_EXTI_1, ..., AFIO_EXTI_15. + * @param gpio_port Port which contains pin to use as source input. + *                  One of: AFIO_EXTI_PA, AFIO_EXTI_PB, AFIO_EXTI_PC, + *                  AFIO_EXTI_PD, and, on high density devices, + *                  AFIO_EXTI_PE, AFIO_EXTI_PF, AFIO_EXTI_PG. + * @see exti_port + */ +void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port) { +    __io uint32 *exti_cr = &AFIO_BASE->EXTICR1 + exti / 4; +    uint32 shift = 4 * (exti % 4); +    uint32 cr = *exti_cr; -    *CR = tmp; +    cr &= ~(AFIO_EXTI_SEL_MASK << shift); +    cr |= gpio_port << shift; +    *exti_cr = cr;  } diff --git a/libmaple/gpio.h b/libmaple/gpio.h index 53f77c4..a8a4985 100644 --- a/libmaple/gpio.h +++ b/libmaple/gpio.h @@ -3,126 +3,331 @@   *   * Copyright (c) 2010 Perry Hung.   * - * 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 + * 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 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. + * 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.   *****************************************************************************/  /**   *  @file gpio.h   * - *  @brief GPIO prototypes, defines, and inlined access functions + *  @brief General purpose I/0 (GPIO) and Alternate Function I/O + *         (AFIO) prototypes, defines, and inlined access functions.   */ -#ifndef _GPIO_H -#define _GPIO_H - -/* Each of the GPIO port bits can be in the following modes (STM32 138/995): - *      Input floating - *      Input pull-up - *      Input pull-down - *      Analog Input - *      Output open-drain - *      Output push-pull - *      Alternate function push-pull - *      Alternate function open-drain - * - * - After reset, the alternate functions are not active and IO prts - * are set to Input Floating mode, EXCEPT for the Serial Wire and JTAG - * ports, which are in alternate function mode by default. */ - -#define AFIO_MAPR     ((volatile uint32*)0x40010004) - -#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) - -#define MODE_OUTPUT_PP         ((0x00 << 2) | GPIO_SPEED_50MHZ) -#define MODE_OUTPUT_OD         ((0x01 << 2) | GPIO_SPEED_50MHZ) -#define MODE_AF_OUTPUT_PP      ((0x02 << 2) | GPIO_SPEED_50MHZ) -#define MODE_AF_OUTPUT_OD      ((0x03 << 2) | GPIO_SPEED_50MHZ) - -#define CNF_INPUT_ANALOG      (0x00 << 2) -#define CNF_INPUT_FLOATING    (0x01 << 2) -#define CNF_INPUT_PD          (0x02 << 2) -#define CNF_INPUT_PU          (0x02 << 2) - -typedef enum GPIOPinMode { -    GPIO_MODE_OUTPUT_PP      = MODE_OUTPUT_PP, -    GPIO_MODE_OUTPUT_OD      = MODE_OUTPUT_OD, -    GPIO_MODE_AF_OUTPUT_PP   = MODE_AF_OUTPUT_PP, -    GPIO_MODE_AF_OUTPUT_OD   = MODE_AF_OUTPUT_OD, -    GPIO_MODE_INPUT_ANALOG   = CNF_INPUT_ANALOG, -    GPIO_MODE_INPUT_FLOATING = CNF_INPUT_FLOATING, -    GPIO_MODE_INPUT_PD       = CNF_INPUT_PD, -    GPIO_MODE_INPUT_PU, -} GPIOPinMode; - -typedef struct { -    volatile uint32 CRL;      // Port configuration register low -    volatile uint32 CRH;      // Port configuration register high -    volatile uint32 IDR;      // Port input data register -    volatile uint32 ODR;      // Port output data register -    volatile uint32 BSRR;     // Port bit set/reset register -    volatile uint32 BRR;      // Port bit reset register -    volatile uint32 LCKR;     // Port configuration lock register -} GPIO_Port; - -typedef volatile uint32* GPIOReg; - -#define POS_MASK(shift) (~(0xF << shift)) -#define POS(val)        (val << 2) +#ifndef _GPIO_H_ +#define _GPIO_H_ + +#include "libmaple.h" +#include "rcc.h"  #ifdef __cplusplus  extern "C"{  #endif -void gpio_init(void); -void gpio_set_mode(GPIO_Port* port, uint8 gpio_pin, GPIOPinMode mode); +/* + * GPIO register maps and devices + */ + +/** GPIO register map type */ +typedef struct gpio_reg_map { +    __io uint32 CRL;      ///< Port configuration register low +    __io uint32 CRH;      ///< Port configuration register high +    __io uint32 IDR;      ///< Port input data register +    __io uint32 ODR;      ///< Port output data register +    __io uint32 BSRR;     ///< Port bit set/reset register +    __io uint32 BRR;      ///< Port bit reset register +    __io uint32 LCKR;     ///< Port configuration lock register +} gpio_reg_map; + +/** GPIO device type */ +typedef struct gpio_dev { +    gpio_reg_map *regs; ///< Register map +    rcc_clk_id clk_id;  ///< RCC clock information +} gpio_dev; + +extern gpio_dev gpioa; +extern gpio_dev* const GPIOA; +extern gpio_dev gpiob; +extern gpio_dev* const GPIOB; +extern gpio_dev gpioc; +extern gpio_dev* const GPIOC; +extern gpio_dev gpiod; +extern gpio_dev* const GPIOD; +#ifdef STM32_HIGH_DENSITY +extern gpio_dev gpioe; +extern gpio_dev* const GPIOE; +extern gpio_dev gpiof; +extern gpio_dev* const GPIOF; +extern gpio_dev gpiog; +extern gpio_dev* const GPIOG; +#endif + +/** GPIO port A register map base pointer */ +#define GPIOA_BASE ((gpio_reg_map*)0x40010800) +/** GPIO port B register map base pointer */ +#define GPIOB_BASE ((gpio_reg_map*)0x40010C00) +/** GPIO port C register map base pointer */ +#define GPIOC_BASE ((gpio_reg_map*)0x40011000) +/** GPIO port D register map base pointer */ +#define GPIOD_BASE ((gpio_reg_map*)0x40011400) +#ifdef STM32_HIGH_DENSITY +/** GPIO port E register map base pointer */ +#define GPIOE_BASE ((gpio_reg_map*)0x40011800) +/** GPIO port F register map base pointer */ +#define GPIOF_BASE ((gpio_reg_map*)0x40011C00) +/** GPIO port G register map base pointer */ +#define GPIOG_BASE ((gpio_reg_map*)0x40012000) +#endif + +/* + * GPIO register bit definitions + */ + +/* Control registers, low and high */ +#define GPIO_CR_CNF_INPUT_ANALOG        (0x0 << 2) +#define GPIO_CR_CNF_INPUT_FLOATING      (0x1 << 2) +#define GPIO_CR_CNF_INPUT_PU_PD         (0x2 << 2) +#define GPIO_CR_CNF_OUTPUT_PP           (0x0 << 2) +#define GPIO_CR_CNF_OUTPUT_OD           (0x1 << 2) +#define GPIO_CR_CNF_AF_OUTPUT_PP        (0x2 << 2) +#define GPIO_CR_CNF_AF_OUTPUT_OD        (0x3 << 2) +#define GPIO_CR_MODE_INPUT              0x0 +#define GPIO_CR_MODE_OUTPUT_10MHZ       0x1 +#define GPIO_CR_MODE_OUTPUT_2MHZ        0x2 +#define GPIO_CR_MODE_OUTPUT_50MHZ       0x3 + +/** GPIO Pin modes.  These only allow for 50MHZ max output speeds; if + * you want slower, use direct register access. */ +typedef enum gpio_pin_mode { +    GPIO_OUTPUT_PP = (GPIO_CR_CNF_OUTPUT_PP | +                      GPIO_CR_MODE_OUTPUT_50MHZ), /**< Output push-pull. */ +    GPIO_OUTPUT_OD = (GPIO_CR_CNF_OUTPUT_OD | +                      GPIO_CR_MODE_OUTPUT_50MHZ), /**< Output open-drain. */ +    GPIO_AF_OUTPUT_PP = (GPIO_CR_CNF_AF_OUTPUT_PP | +                         GPIO_CR_MODE_OUTPUT_50MHZ), /**< Alternate function +                                                        output push-pull. */ +    GPIO_AF_OUTPUT_OD = (GPIO_CR_CNF_AF_OUTPUT_OD | +                         GPIO_CR_MODE_OUTPUT_50MHZ), /**< Alternate function +                                                        output open drain. */ +    GPIO_INPUT_ANALOG = (GPIO_CR_CNF_INPUT_ANALOG | +                         GPIO_CR_MODE_INPUT), /**< Analog input. */ +    GPIO_INPUT_FLOATING = (GPIO_CR_CNF_INPUT_FLOATING | +                           GPIO_CR_MODE_INPUT), /**< Input floating. */ +    GPIO_INPUT_PD = (GPIO_CR_CNF_INPUT_PU_PD | +                     GPIO_CR_MODE_INPUT), /**< Input pull-down. */ +    GPIO_INPUT_PU /**< Input pull-up. */ +    /* GPIO_INPUT_PU treated as a special case, for ODR twiddling */ +} gpio_pin_mode; -static inline void gpio_write_bit(GPIO_Port *port, uint8 gpio_pin, uint8 val) { -    if (val){ -        port->BSRR = BIT(gpio_pin); +/* + * GPIO Convenience routines + */ + +void gpio_init(gpio_dev *dev); +void gpio_init_all(void); +void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode); + +/** + * Set or reset a GPIO pin. + * + * Pin must have previously been configured to output mode. + * + * @param dev GPIO device whose pin to set. + * @param pin Pin on to set or reset + * @param val If true, set the pin.  If false, reset the pin. + */ +static inline void gpio_write_bit(gpio_dev *dev, uint8 pin, uint8 val) { +    if (val) { +        dev->regs->BSRR = BIT(pin);      } else { -        port->BRR = BIT(gpio_pin); +        dev->regs->BRR = BIT(pin);      }  } -static inline uint32 gpio_read_bit(GPIO_Port *port, uint8 gpio_pin) { -    return (port->IDR & BIT(gpio_pin) ? 1 : 0); +/** + * Determine whether or not a GPIO pin is set. + * + * Pin must have previously been configured to input mode. + * + * @param dev GPIO device whose pin to test. + * @param pin Pin on dev to test. + * @return True if the pin is set, false otherwise. + */ +static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) { +    return dev->regs->IDR & BIT(pin);  } -/* For pins configured as output push-pull, reading the ODR returns - * the last value written in push-pull mode. +/** + * Toggle a pin configured as output push-pull. + * @param dev GPIO device. + * @param pin Pin on dev to toggle.   */ -static inline void gpio_toggle_pin(GPIO_Port *port, uint8 gpio_pin) { -    port->ODR = port->ODR ^ BIT(gpio_pin); +static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) { +    dev->regs->ODR = dev->regs->ODR ^ BIT(pin);  } -#ifdef __cplusplus -} // extern "C" +/* + * AFIO register map + */ + +/** AFIO register map */ +typedef struct afio_reg_map { +    __io uint32 EVCR;        /**< Event control register.  */ +    __io uint32 MAPR;        /**< AF remap and debug I/O configuration +                                register. */ +    __io uint32 EXTICR1;     /**< External interrupt configuration +                                register 1. */ +    __io uint32 EXTICR2;     /**< External interrupt configuration +                                register 2. */ +    __io uint32 EXTICR3;     /**< External interrupt configuration +                                register 3. */ +    __io uint32 EXTICR4;     /**< External interrupt configuration +                                register 4. */ +    __io uint32 MAPR2;       /**< AF remap and debug I/O configuration +                                register 2. */ +} afio_reg_map; + +/** AFIO register map base pointer. */ +#define AFIO_BASE ((afio_reg_map *)0x40010000) + +/* + * AFIO register bit definitions + */ + +/* Event control register */ +#define AFIO_EVCR_EVOE                  (0x1 << 7) +#define AFIO_EVCR_PORT_PA               (0x0 << 4) +#define AFIO_EVCR_PORT_PB               (0x1 << 4) +#define AFIO_EVCR_PORT_PC               (0x2 << 4) +#define AFIO_EVCR_PORT_PD               (0x3 << 4) +#define AFIO_EVCR_PORT_PE               (0x4 << 4) +#define AFIO_EVCR_PIN_0                 0x0 +#define AFIO_EVCR_PIN_1                 0x1 +#define AFIO_EVCR_PIN_2                 0x2 +#define AFIO_EVCR_PIN_3                 0x3 +#define AFIO_EVCR_PIN_4                 0x4 +#define AFIO_EVCR_PIN_5                 0x5 +#define AFIO_EVCR_PIN_6                 0x6 +#define AFIO_EVCR_PIN_7                 0x7 +#define AFIO_EVCR_PIN_8                 0x8 +#define AFIO_EVCR_PIN_9                 0x9 +#define AFIO_EVCR_PIN_10                0xA +#define AFIO_EVCR_PIN_11                0xB +#define AFIO_EVCR_PIN_12                0xC +#define AFIO_EVCR_PIN_13                0xD +#define AFIO_EVCR_PIN_14                0xE +#define AFIO_EVCR_PIN_15                0xF + +/* AF remap and debug I/O configuration register */ +#define AFIO_MAPR_SWJ_FULL_SWJ                 (0x0 << 24) +#define AFIO_MAPR_SWJ_FULL_SWJ_NO_NJRST        (0x1 << 24) +#define AFIO_MAPR_SWJ_NO_JTAG_SW               (0x2 << 24) +#define AFIO_MAPR_SWJ_NO_JTAG_NO_SW            (0x4 << 24) +#define AFIO_MAPR_ADC2_ETRGREG_REMAP           BIT(20) +#define AFIO_MAPR_ADC2_ETRGINJ_REMAP           BIT(19) +#define AFIO_MAPR_ADC1_ETRGREG_REMAP           BIT(18) +#define AFIO_MAPR_ADC1_ETRGINJ_REMAP           BIT(17) +#define AFIO_MAPR_TIM5CH4_IREMAP               BIT(16) +#define AFIO_MAPR_PD01_REMAP                   BIT(15) +#define AFIO_MAPR_CAN_REMAP                    (BIT(14) | BIT(13)) +#define AFIO_MAPR_TIM4_REMAP_FULL              BIT(12) +#define AFIO_MAPR_TIM3_REMAP                   (BIT(11) | BIT(10)) +#define AFIO_MAPR_TIM2_REMAP                   (BIT(9) | BIT(8)) +#define AFIO_MAPR_TIM1_REMAP                   (BIT(7) | BIT(6)) +#define AFIO_MAPR_USART3_REMAP                 (BIT(5) | BIT(4)) +#define AFIO_MAPR_USART2_REMAP                 BIT(3) +#define AFIO_MAPR_USART1_REMAP                 BIT(2) +#define AFIO_MAPR_I2C1_REMAP                   BIT(1) +#define AFIO_MAPR_SPI1_REMAP                   BIT(0) + +/* External interrupt configuration registers */ + +/** + * External interrupt line port selector.  Used to determine which + * GPIO port to map an external interrupt line onto. */ +typedef enum { +    AFIO_EXTI_PA,               /**< Use PAx pin. */ +    AFIO_EXTI_PB,               /**< Use PBx pin. */ +    AFIO_EXTI_PC,               /**< Use PCx pin. */ +    AFIO_EXTI_PD,               /**< Use PDx pin. */ +#ifdef STM32_HIGH_DENSITY +    AFIO_EXTI_PE,               /**< Use PEx pin. */ +    AFIO_EXTI_PF,               /**< Use PFx pin. */ +    AFIO_EXTI_PG,               /**< Use PGx pin. */  #endif +} afio_exti_port; + +/** + * External interrupt line numbers. + */ +typedef enum { +    AFIO_EXTI_0,                /**< External interrupt line 0. */ +    AFIO_EXTI_1,                /**< External interrupt line 1. */ +    AFIO_EXTI_2,                /**< External interrupt line 2. */ +    AFIO_EXTI_3,                /**< External interrupt line 3. */ +    AFIO_EXTI_4,                /**< External interrupt line 4. */ +    AFIO_EXTI_5,                /**< External interrupt line 5. */ +    AFIO_EXTI_6,                /**< External interrupt line 6. */ +    AFIO_EXTI_7,                /**< External interrupt line 7. */ +    AFIO_EXTI_8,                /**< External interrupt line 8. */ +    AFIO_EXTI_9,                /**< External interrupt line 9. */ +    AFIO_EXTI_10,               /**< External interrupt line 10. */ +    AFIO_EXTI_11,               /**< External interrupt line 11. */ +    AFIO_EXTI_12,               /**< External interrupt line 12. */ +    AFIO_EXTI_13,               /**< External interrupt line 13. */ +    AFIO_EXTI_14,               /**< External interrupt line 14. */ +    AFIO_EXTI_15,               /**< External interrupt line 15. */ +} afio_exti_num; +/* AF remap and debug I/O configuration register 2 */ +#define AFIO_MAPR2_FSMC_NADV            BIT(10) +#define AFIO_MAPR2_TIM14_REMAP          BIT(9) +#define AFIO_MAPR2_TIM13_REMAP          BIT(8) +#define AFIO_MAPR2_TIM11_REMAP          BIT(7) +#define AFIO_MAPR2_TIM10_REMAP          BIT(6) +#define AFIO_MAPR2_TIM9_REMAP           BIT(5) + +/* + * AFIO convenience routines + */ + +void afio_init(void); +void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port); + +/** + * Set the SWJ_CONFIG bits in the AFIO MAPR register. + * + * @param config Desired SWJ_CONFIG bits setting.  One of: + *        AFIO_MAPR_SWJ_FULL_SWJ (full SWJ), + *        AFIO_MAPR_SWJ_FULL_SWJ_NO_NJRST (full SWJ, no NJTRST), + *        AFIO_MAPR_SWJ_NO_JTAG_SW (JTAG-DP disabled, SW-DP enabled), + *        AFIO_MAPR_SWJ_NO_JTAG_NO_SW (JTAG-DP and SW-DP both disabled). + */ +static inline void afio_mapr_swj_config(uint32 config) { +    __io uint32 *mapr = &AFIO_BASE->MAPR; +    *mapr = (*mapr & ~(0x7 << 24)) | config; +} + +#ifdef __cplusplus +} +#endif  #endif diff --git a/libmaple/i2c.c b/libmaple/i2c.c index 8bd252c..a6638be 100644 --- a/libmaple/i2c.c +++ b/libmaple/i2c.c @@ -37,8 +37,8 @@  static inline int32 wait_for_state_change(i2c_dev *dev, i2c_state state);  static i2c_dev i2c_dev1 = { -    .regs         = (i2c_reg_map*)I2C1_BASE, -    .gpio_port    = GPIOB_BASE, +    .regs         = I2C1_BASE, +    .gpio_port    = &gpiob,      .sda_pin      = 7,      .scl_pin      = 6,      .clk_line     = RCC_I2C1, @@ -261,8 +261,8 @@ static void i2c_bus_reset(const i2c_dev *dev) {      /* Release both lines */      gpio_write_bit(dev->gpio_port, dev->scl_pin, 1);      gpio_write_bit(dev->gpio_port, dev->sda_pin, 1); -    gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_MODE_OUTPUT_OD); -    gpio_set_mode(dev->gpio_port, dev->sda_pin, GPIO_MODE_OUTPUT_OD); +    gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_OUTPUT_OD); +    gpio_set_mode(dev->gpio_port, dev->sda_pin, GPIO_OUTPUT_OD);      /*       * Make sure the bus is free by clocking it until any slaves release the @@ -309,8 +309,8 @@ void i2c_master_enable(i2c_dev *dev, uint32 flags) {      /* Turn on clock and set GPIO modes */      rcc_reset_dev(dev->clk_line);      rcc_clk_enable(dev->clk_line); -    gpio_set_mode(dev->gpio_port, dev->sda_pin, GPIO_MODE_AF_OUTPUT_OD); -    gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_MODE_AF_OUTPUT_OD); +    gpio_set_mode(dev->gpio_port, dev->sda_pin, GPIO_AF_OUTPUT_OD); +    gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_AF_OUTPUT_OD);      /* I2C1 and I2C2 are fed from APB1, clocked at 36MHz */      i2c_set_input_clk(dev, 36); diff --git a/libmaple/i2c.h b/libmaple/i2c.h index a9e2c7b..21c17c1 100644 --- a/libmaple/i2c.h +++ b/libmaple/i2c.h @@ -60,7 +60,7 @@ typedef struct i2c_msg {  typedef struct i2c_dev {      i2c_reg_map *regs; -    GPIO_Port *gpio_port; +    gpio_dev *gpio_port;      uint8 sda_pin;      uint8 scl_pin;      uint8 clk_line; diff --git a/libmaple/libmaple.h b/libmaple/libmaple.h index 50887bc..8e11660 100644 --- a/libmaple/libmaple.h +++ b/libmaple/libmaple.h @@ -38,7 +38,7 @@  /*   * Where to put usercode, based on space reserved for bootloader.   * - * FIXME this has no business being here  + * FIXME this has no business being here   */  #define USER_ADDR_ROM 0x08005000  #define USER_ADDR_RAM 0x20000C00 @@ -58,7 +58,6 @@      /* e.g., LeafLabs Maple Native */      #define NR_GPIO_PORTS              7 -      #define SRAM_SIZE            0x10000  #elif defined(MCU_STM32F103CB) @@ -71,6 +70,12 @@      #define SRAM_SIZE             0x5000 +#elif defined(MCU_STM32F103RE) +    /* e.g., LeafLabs Maple RET6 edition */ + +    #define NR_GPIO_PORTS              4 +    #define SRAM_SIZE            0x10000 +  #else  #error "No MCU type specified. Add something like -DMCU_STM32F103RB "   \ diff --git a/libmaple/libmaple_types.h b/libmaple/libmaple_types.h index a976a9e..54bef65 100644 --- a/libmaple/libmaple_types.h +++ b/libmaple/libmaple_types.h @@ -44,6 +44,7 @@ typedef long long int64;  typedef void (*voidFuncPtr)(void);  #define __io volatile +#define __attr_flash __attribute__((section (".USER_FLASH")))  #ifndef NULL  #define NULL 0 diff --git a/libmaple/pwr.c b/libmaple/pwr.c index b43193e..d63a92d 100644 --- a/libmaple/pwr.c +++ b/libmaple/pwr.c @@ -28,7 +28,7 @@  #include "rcc.h"  pwr_dev pwr = { -    .regs = PWR_BASE; +    .regs = PWR_BASE,  };  const pwr_dev *PWR = &pwr; diff --git a/libmaple/pwr.h b/libmaple/pwr.h index 5ff815d..5f68c34 100644 --- a/libmaple/pwr.h +++ b/libmaple/pwr.h @@ -41,20 +41,19 @@ typedef struct pwr_reg_map {      __io uint32 CSR;     /**< Control and status register */  } pwr_reg_map; -/* - * Power peripheral base. - */ +/** Power peripheral register map base pointer. */  #define PWR_BASE    ((pwr_reg_map*)0x40007000) -/** Power interface device. */ +/** Power device type. */  typedef struct pwr_dev { -    pwr_reg_map *regs; +    pwr_reg_map *regs; /**< Register map */  } pwr_dev;  /**   * Power device.   */  extern const pwr_dev *PWR; +  /*   * Register bit definitions   */ diff --git a/libmaple/rcc.h b/libmaple/rcc.h index 569da57..dcb9ea2 100644 --- a/libmaple/rcc.h +++ b/libmaple/rcc.h @@ -27,6 +27,8 @@   * @brief reset and clock control definitions and prototypes   */ +#include "libmaple_types.h" +  #ifndef _RCC_H_  #define _RCC_H_ @@ -184,7 +186,6 @@ typedef enum {      RCC_I2C2  } rcc_clk_id; -  void rcc_clk_init(uint32 sysclk_src, uint32 pll_src, uint32 pll_mul);  void rcc_clk_enable(rcc_clk_id device);  void rcc_reset_dev(rcc_clk_id device); diff --git a/libmaple/ring_buffer.h b/libmaple/ring_buffer.h index a44088e..3b5d4e7 100644 --- a/libmaple/ring_buffer.h +++ b/libmaple/ring_buffer.h @@ -13,21 +13,20 @@  extern "C"{  #endif -/* The buffer is empty when head == tail. +/** + * Ring buffer type. + * + * The buffer is empty when head == tail.   *   * The buffer is full when the head is one byte in front of the tail,   * modulo buffer length.   *   * One byte is left free to distinguish empty from full. */  typedef struct ring_buffer { -    /** Buffer items are stored into */ -    volatile uint8 *buf; -    /** Index of the next item to remove */ -    uint16 head; -    /** Index where the next item will get inserted */ -    uint16 tail; -    /** Buffer capacity minus one */ -    uint16 size; +    volatile uint8 *buf; /**< Buffer items are stored into */ +    uint16 head;         /**< Index of the next item to remove */ +    uint16 tail;         /**< Index where the next item will get inserted */ +    uint16 size;         /**< Buffer capacity minus one */  } ring_buffer;  /** @@ -66,6 +65,11 @@ static inline int rb_is_full(ring_buffer *rb) {          (rb->tail == rb->size && rb->head == 0);  } +/** Return true if and only if the ring buffer is empty. */ +static inline int rb_is_empty(ring_buffer *rb) { +    return rb->head == rb->tail; +} +  /** Append element onto the end of the ring buffer. */  static inline void rb_insert(ring_buffer *rb, uint8 element) {      rb->buf[rb->tail] = element; @@ -80,6 +84,14 @@ static inline uint8 rb_remove(ring_buffer *rb) {  }  /** + * If the ring buffer is nonempty, removes and returns its first item. + * If it is empty, does nothing and returns a negative value. + */ +static inline int16 rb_safe_remove(ring_buffer *rb) { +    return rb_is_empty(rb) ? -1 : rb_remove(rb); +} + +/**   * If rb is not full, appends element and returns true; otherwise,   * does nothing and returns false. */  static inline int rb_safe_insert(ring_buffer *rb, uint8 element) { diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 3d8171f..48b5ed4 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -22,6 +22,7 @@ cSRCS_$(d) := adc.c                    \                gpio.c                   \                iwdg.c                   \                nvic.c                   \ +              pwr.c		       \                i2c.c                    \                rcc.c                    \                spi.c                    \ diff --git a/libmaple/spi.c b/libmaple/spi.c index 8bba0d6..7bdc18a 100644 --- a/libmaple/spi.c +++ b/libmaple/spi.c @@ -43,23 +43,23 @@  typedef struct spi_dev {      SPI *base; -    GPIO_Port *port; +    gpio_dev *gpio_d;      uint8 sck_pin;      uint8 miso_pin;      uint8 mosi_pin;  } spi_dev; -static const spi_dev spi_dev1 = { +spi_dev spi_dev1 = {      .base     = (SPI*)SPI1_BASE, -    .port     = GPIOA_BASE, +    .gpio_d   = NULL,      .sck_pin  = 5,      .miso_pin = 6,      .mosi_pin = 7  }; -static const spi_dev spi_dev2 = { +spi_dev spi_dev2 = {      .base     = (SPI*)SPI2_BASE, -    .port     = GPIOB_BASE, +    .gpio_d   = NULL,      .sck_pin  = 13,      .miso_pin = 14,      .mosi_pin = 15 @@ -90,11 +90,13 @@ void spi_init(uint32 spi_num,          ASSERT(prescale != CR1_BR_PRESCALE_2);          spi = (SPI*)SPI1_BASE;          rcc_clk_enable(RCC_SPI1); +        spi_dev1.gpio_d = GPIOA;          spi_gpio_cfg(&spi_dev1);          break;      case 2:          spi = (SPI*)SPI2_BASE;          rcc_clk_enable(RCC_SPI2); +        spi_dev1.gpio_d = GPIOB,          spi_gpio_cfg(&spi_dev2);          break;      } @@ -155,7 +157,7 @@ uint8 spi_tx(uint32 spi_num, uint8 *buf, uint32 len) {  }  static void spi_gpio_cfg(const spi_dev *dev) { -    gpio_set_mode(dev->port, dev->sck_pin, GPIO_MODE_AF_OUTPUT_PP); -    gpio_set_mode(dev->port, dev->miso_pin, GPIO_MODE_AF_OUTPUT_PP); -    gpio_set_mode(dev->port, dev->mosi_pin, GPIO_MODE_AF_OUTPUT_PP); +    gpio_set_mode(dev->gpio_d, dev->sck_pin, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(dev->gpio_d, dev->miso_pin, GPIO_AF_OUTPUT_PP); +    gpio_set_mode(dev->gpio_d, dev->mosi_pin, GPIO_AF_OUTPUT_PP);  } diff --git a/libmaple/usb/descriptors.h b/libmaple/usb/descriptors.h index 6f7d08b..460a88c 100644 --- a/libmaple/usb/descriptors.h +++ b/libmaple/usb/descriptors.h @@ -61,7 +61,7 @@ extern "C" {      uint16 bString[len];			\    } -#define CDC_FUCNTIONAL_DESCRIPTOR(DataSize)	\ +#define CDC_FUNCTIONAL_DESCRIPTOR(DataSize)	\    struct					\    {						\      uint8 bLength;				\ diff --git a/libmaple/usb/usb.c b/libmaple/usb/usb.c index 62f56fc..2fc4eb2 100644 --- a/libmaple/usb/usb.c +++ b/libmaple/usb/usb.c @@ -44,7 +44,7 @@  volatile uint32 bDeviceState = UNCONNECTED;  volatile uint16 wIstr = 0; -volatile bIntPackSOF  = 0; +volatile uint32 bIntPackSOF = 0;  DEVICE Device_Table =      {NUM_ENDPTS, @@ -99,15 +99,13 @@ struct {  } ResumeS;  void setupUSB (void) { -  gpio_set_mode(USB_DISC_BANK, -                USB_DISC_PIN, -                GPIO_MODE_OUTPUT_PP); +  gpio_set_mode(USB_DISC_DEV, USB_DISC_PIN, GPIO_OUTPUT_PP);    /* setup the apb1 clock for USB */    pRCC->APB1ENR |= 0x00800000;    /* initialize the usb application */ -  gpio_write_bit(USB_DISC_BANK, USB_DISC_PIN, 0); // presents us to the host +  gpio_write_bit(USB_DISC_DEV, USB_DISC_PIN, 0); // presents us to the host    USB_Init();  // low level init routine provided by the ST library  } @@ -115,7 +113,7 @@ void disableUSB (void) {    // These are just guesses about how to do this    // TODO: real disable function    usbDsbISR(); -  gpio_write_bit(USB_DISC_BANK,USB_DISC_PIN,1); +  gpio_write_bit(USB_DISC_DEV, USB_DISC_PIN, 1);  }  void usbSuspend(void) { @@ -320,8 +318,29 @@ if (wIstr & ISTR_CTR & wInterrupt_Mask) {  } +static void FIXME_delayMicroseconds_copy(uint32 us) { +    /* 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"); +} + +static void FIXME_delay_copy(unsigned long ms) { +    uint32 i; +    for (i = 0; i < ms; i++) { +        FIXME_delayMicroseconds_copy(1000); +    } +} +  void usbWaitReset(void) { -  delay(RESET_DELAY); +  FIXME_delay_copy(RESET_DELAY);    systemHardReset();  } diff --git a/libmaple/usb/usb_callbacks.c b/libmaple/usb/usb_callbacks.c index ccb0fdd..8184537 100644 --- a/libmaple/usb/usb_callbacks.c +++ b/libmaple/usb/usb_callbacks.c @@ -129,7 +129,7 @@ u8* vcomGetSetLineCoding(uint16 length) {      return (uint8*)&line_coding;  } -vcomSetLineState(void) { +void vcomSetLineState(void) {  }  void usbInit(void) { diff --git a/libmaple/usb/usb_config.h b/libmaple/usb/usb_config.h index 394c580..0860b90 100644 --- a/libmaple/usb/usb_config.h +++ b/libmaple/usb/usb_config.h @@ -4,6 +4,7 @@  #define __USB_CONFIG_H  #include "usb_lib.h" +#include "gpio.h"  /******************************************************************************   ****************************************************************************** @@ -27,31 +28,31 @@  #define RESET_DELAY               (100)  #define USB_CONFIG_MAX_POWER      (100 >> 1) -#if defined(BOARD_maple) +#if defined(BOARD_maple) || defined(BOARD_maple_RET6)      /* USB Identifier numbers */      #define VCOM_ID_PRODUCT      0x0004 -    #define USB_DISC_BANK        GPIOC_BASE +    #define USB_DISC_DEV         GPIOC      #define USB_DISC_PIN         12  #elif defined(BOARD_maple_mini) -    #define VCOM_ID_PRODUCT      0x0005 -    #define USB_DISC_BANK        GPIOB_BASE +    #define VCOM_ID_PRODUCT      0x0004 +    #define USB_DISC_DEV         GPIOB      #define USB_DISC_PIN         9  #elif defined(BOARD_maple_native) -    #define VCOM_ID_PRODUCT      0x0006 -    #define USB_DISC_BANK        GPIOB_BASE +    #define VCOM_ID_PRODUCT      0x0004 +    #define USB_DISC_DEV         GPIOB      #define USB_DISC_PIN         8  #else  #error ("Sorry! the USB stack relies on LeafLabs board-specific "       \          "configuration right now.  If you want, you can pretend you're one " \ -        "of our boards; i.e., #define BOARD_maple, BOARD_maple_mini, or "  \ -        "BOARD_maple_native according to what matches your MCU best. " \ +        "of our boards; i.e., #define BOARD_maple, BOARD_maple_mini, or " \ +        "BOARD_maple_native according to what matches your MCU best. "  \          "You should also take a look at libmaple/usb/descriptors.c; we make " \          "some assumptions there that you probably won't like.") diff --git a/libmaple/usb/usb_hardware.c b/libmaple/usb/usb_hardware.c index 505dcf1..9a7d12c 100644 --- a/libmaple/usb/usb_hardware.c +++ b/libmaple/usb/usb_hardware.c @@ -33,47 +33,6 @@  #include "usb_hardware.h" -void setPin(u32 bank, u8 pin) { -    u32 pinMask = 0x1 << (pin); -    SET_REG(GPIO_BSRR(bank),pinMask); -} - -void resetPin(u32 bank, u8 pin) { -    u32 pinMask = 0x1 << (16+pin); -    SET_REG(GPIO_BSRR(bank),pinMask); -} - -void systemReset(void) { -    SET_REG(RCC_CR, GET_REG(RCC_CR)     | 0x00000001); -    SET_REG(RCC_CFGR, GET_REG(RCC_CFGR) & 0xF8FF0000); -    SET_REG(RCC_CR, GET_REG(RCC_CR)     & 0xFEF6FFFF); -    SET_REG(RCC_CR, GET_REG(RCC_CR)     & 0xFFFBFFFF); -    SET_REG(RCC_CFGR, GET_REG(RCC_CFGR) & 0xFF80FFFF); - -    SET_REG(RCC_CIR, 0x00000000); // disable all RCC interrupts -} - -void setupCLK (void) { -    /* enable HSE */ -    SET_REG(RCC_CR,GET_REG(RCC_CR) | 0x00010001); -    /* for it to come on */ -    while ((GET_REG(RCC_CR) & 0x00020000) == 0); - -    /* Configure PLL */ -    /* pll=72Mhz,APB1=36Mhz,AHB=72Mhz */ -    SET_REG(RCC_CFGR,GET_REG(RCC_CFGR) | 0x001D0400); -    /* enable the pll */ -    SET_REG(RCC_CR,GET_REG(RCC_CR)     | 0x01000000); -    /* wait for it to come on */ -    while ((GET_REG(RCC_CR) & 0x03000000) == 0); - -    /* Set SYSCLK as PLL */ -    SET_REG(RCC_CFGR,GET_REG(RCC_CFGR) | 0x00000002); -    /* wait for it to come on */ -    while ((GET_REG(RCC_CFGR) & 0x00000008) == 0); -} - -  void nvicInit(NVIC_InitTypeDef* NVIC_InitStruct) {      u32 tmppriority = 0x00;      u32 tmpreg      = 0x00; diff --git a/libmaple/usb/usb_hardware.h b/libmaple/usb/usb_hardware.h index e4a26b4..cfead1a 100644 --- a/libmaple/usb/usb_hardware.h +++ b/libmaple/usb/usb_hardware.h @@ -22,34 +22,20 @@   * THE SOFTWARE.   * ****************************************************************************/ -#ifndef __HARDWARE_H -#define __HARDWARE_H - +#include "rcc.h"  #include "usb_type.h" +#ifndef _USB_HARDWARE_H_ +#define _USB_HARDWARE_H_ +  /* macro'd register and peripheral definitions */  #define EXC_RETURN 0xFFFFFFF9  #define DEFAULT_CPSR 0x61000000 -#define RCC   ((u32)0x40021000)  #define FLASH ((u32)0x40022000) -#define GPIOA ((u32)0x40010800) -#define GPIOC ((u32)0x40011000)  #define USB_PACKET_BUFFER ((u32)0x40006000) -#define RCC_CR      RCC -#define RCC_CFGR    RCC + 0x04 -#define RCC_CIR     RCC + 0x08 -#define RCC_AHBENR  RCC + 0x14 -#define RCC_APB2ENR RCC + 0x18 -#define RCC_APB1ENR RCC + 0x16 - -#define GPIO_CRL(port)  port -#define GPIO_CRH(port)  port+0x04 -#define GPIO_ODR(port)  port+0x0c -#define GPIO_BSRR(port) port+0x10 -  #define SCS_BASE   ((u32)0xE000E000)  #define NVIC_BASE  (SCS_BASE + 0x0100)  #define SCB_BASE   (SCS_BASE + 0x0D00) @@ -74,9 +60,8 @@  #define __PSC(__TIMCLK, __PERIOD)  (((__VAL(__TIMCLK, __PERIOD)+49999UL)/50000UL) - 1)  #define __ARR(__TIMCLK, __PERIOD) ((__VAL(__TIMCLK, __PERIOD)/(__PSC(__TIMCLK, __PERIOD)+1)) - 1) -/* todo, wrap in do whiles for the natural ; */ -#define SET_REG(addr,val) *(vu32*)(addr)=val -#define GET_REG(addr)     *(vu32*)(addr) +#define SET_REG(addr,val)  do { *(vu32*)(addr)=val; } while (0) +#define GET_REG(addr)      do { *(vu32*)(addr); } while (0)  #if defined(__cplusplus)  extern "C" { @@ -85,7 +70,7 @@ extern "C" {  /* todo: there must be some major misunderstanding in how we access regs. The direct access approach (GET_REG)     causes the usb init to fail upon trying to activate RCC_APB1 |= 0x00800000. However, using the struct approach     from ST, it works fine...temporarily switching to that approach */ -typedef struct  +typedef struct  {    vu32 CR;    vu32 CFGR; @@ -98,7 +83,7 @@ typedef struct    vu32 BDCR;    vu32 CSR;  } RCC_RegStruct; -#define pRCC ((RCC_RegStruct *) RCC) +#define pRCC ((RCC_RegStruct *) RCC_BASE)  typedef struct {    vu32 ISER[2]; @@ -139,12 +124,7 @@ typedef struct {  } SCB_TypeDef; -void setPin    (u32 bank, u8 pin); -void resetPin  (u32 bank, u8 pin); -  void systemHardReset(void); -void systemReset   (void); -void setupCLK      (void);  void nvicInit        (NVIC_InitTypeDef*);  void nvicDisableInterrupts(void); diff --git a/libmaple/util.c b/libmaple/util.c index 3408a2e..09fbecd 100644 --- a/libmaple/util.c +++ b/libmaple/util.c @@ -38,7 +38,7 @@  #ifndef ERROR_USART_NUM  #define ERROR_USART_NUM        USART2  #define ERROR_USART_BAUD       9600 -#define ERROR_TX_PORT          GPIOA_BASE +#define ERROR_TX_PORT          GPIOA  #define ERROR_TX_PIN           2  #endif @@ -87,7 +87,7 @@ void __error(void) {   */  void _fail(const char* file, int line, const char* exp) {      /* Initialize the error usart */ -    gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_MODE_AF_OUTPUT_PP); +    gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_AF_OUTPUT_PP);      usart_init(ERROR_USART_NUM, ERROR_USART_BAUD);      /* Print failed assert message */ @@ -116,7 +116,7 @@ void throb(void) {      uint32 TOP_CNT = 0x0200;      uint32 i       = 0; -    gpio_set_mode(ERROR_LED_PORT, ERROR_LED_PIN, GPIO_MODE_OUTPUT_PP); +    gpio_set_mode(ERROR_LED_PORT, ERROR_LED_PIN, GPIO_OUTPUT_PP);      /* Error fade  */      while (1) {          if (CC == TOP_CNT)  { diff --git a/libmaple/util.h b/libmaple/util.h index fb524c2..25dd56e 100644 --- a/libmaple/util.h +++ b/libmaple/util.h @@ -28,6 +28,8 @@   *  @brief Various macros and utility procedures.   */ +#include "libmaple_types.h" +  /* Generally "useful" utility procedures  */  #ifndef _UTIL_H_  #define _UTIL_H_ @@ -51,40 +53,29 @@ extern "C"{  /* Return bits m to n of x  */  #define GET_BITS(x, m, n) ((((uint32)x) << (31 - (n))) >> ((31 - (n)) + (m))) -/* Bit-banding macros  */ -/* Bitbanded Memory sections */ -#define BITBAND_SRAM_REF   0x20000000 -#define BITBAND_SRAM_BASE  0x22000000 -#define BITBAND_PERI_REF   0x40000000 -#define BITBAND_PERI_BASE  0x42000000 -/* Convert SRAM address */ -#define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE+(a-BITBAND_SRAM_REF)*32+(b*4))) -/* Convert peripheral address */ -#define BITBAND_PERI(a, b) ((BITBAND_PERI_BASE +                \ -                            ((uint32)a - BITBAND_PERI_REF) * 32 + (b * 4))) - -#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)) -#define REG_SET_MASK(reg, mask)   (*(volatile uint32*)(reg) |= (uint32)(mask)) -#define REG_CLEAR_MASK(reg, mask) (*(volatile uint32*)(reg) &= (uint32)~(mask)) - -#define REG_GET(reg)              (*(volatile uint32*)(reg)) +/* + * Register reads and writes + */  #define __set_bits(addr, mask)   (*(volatile uint32*)(addr) |= (uint32)(mask))  #define __clear_bits(addr, mask) (*(volatile uint32*)(addr) &= (uint32)~(mask))  #define __get_bits(addr, mask)   (*(volatile uint32*)(addr) & (uint32)(mask)) -  #define __read(reg)              (*(volatile uint32*)(reg))  #define __write(reg, value)      (*(volatile uint32*)(reg) = (value))  #define IS_POWER_OF_TWO(v)  (v && !(v & (v - 1))) + +/* + * Failure routines + */ +  void __error(void);  void _fail(const char*, int, const char*);  void throb(void); -/* Asserts for sanity checks, redefine DEBUG_LEVEL in libmaple.h to - * compile out these checks */ +/* + * Asserts and debug levels + */  #if DEBUG_LEVEL >= DEBUG_ALL  #define ASSERT(exp)                              \ | 
