aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple
diff options
context:
space:
mode:
Diffstat (limited to 'libmaple')
-rw-r--r--libmaple/adc.c4
-rw-r--r--libmaple/adc.h38
-rw-r--r--libmaple/bitband.h83
-rw-r--r--libmaple/bkp.c6
-rw-r--r--libmaple/bkp.h16
-rw-r--r--libmaple/dac.c6
-rw-r--r--libmaple/dac.h10
-rw-r--r--libmaple/exti.c244
-rw-r--r--libmaple/exti.h158
-rw-r--r--libmaple/fsmc.c89
-rw-r--r--libmaple/fsmc.h5
-rw-r--r--libmaple/gpio.c165
-rw-r--r--libmaple/gpio.h391
-rw-r--r--libmaple/libmaple.h2
-rw-r--r--libmaple/libmaple_types.h1
-rw-r--r--libmaple/pwr.h9
-rw-r--r--libmaple/rcc.h3
-rw-r--r--libmaple/ring_buffer.h17
-rw-r--r--libmaple/spi.c18
-rw-r--r--libmaple/usb/usb.c33
-rw-r--r--libmaple/usb/usb_callbacks.c2
-rw-r--r--libmaple/usb/usb_config.h7
-rw-r--r--libmaple/usb/usb_hardware.c41
-rw-r--r--libmaple/usb/usb_hardware.h36
-rw-r--r--libmaple/util.c6
-rw-r--r--libmaple/util.h35
26 files changed, 868 insertions, 557 deletions
diff --git a/libmaple/adc.c b/libmaple/adc.c
index a464746..9626a40 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_peripv(&(dev->regs->CR2), 3);
+ __io uint32 *cal_bit = bb_peripv(&(dev->regs->CR2), 2);
*rstcal_bit = 1;
while (*rstcal_bit)
diff --git a/libmaple/adc.h b/libmaple/adc.h
index ac386fb..4811dbc 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_peripv(&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_peripv(&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_peripv(&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..076335f
--- /dev/null
+++ b/libmaple/bitband.h
@@ -0,0 +1,83 @@
+/******************************************************************************
+ * 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 uint32* __bb_addr(void*, uint32, uint32, uint32);
+static inline __io uint32* __bb_addrv(__io void*, uint32, uint32, uint32);
+
+/**
+ * @brief Obtain a pointer to the bit-band address corresponding to a
+ * bit in an SRAM address.
+ * @param address Address in the bit-banded SRAM region
+ * @param bit Bit in address to bit-band
+ */
+static inline uint32* bb_sramp(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 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_srampv(__io void *address, uint32 bit) {
+ return __bb_addrv(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_peripv(__io void *address, uint32 bit) {
+ return __bb_addrv(address, bit, BB_PERI_BASE, BB_PERI_REF);
+}
+
+static inline uint32* __bb_addr(void *address,
+ uint32 bit,
+ uint32 bb_base,
+ uint32 bb_ref) {
+ return (uint32*)(bb_base + ((uint32)address - bb_ref) * 32 + bit * 4);
+}
+
+static inline __io uint32* __bb_addrv(__io void *address,
+ uint32 bit,
+ uint32 bb_base,
+ uint32 bb_ref) {
+ return (__io uint32*)__bb_addr((void*)address, bit, bb_base, bb_ref);
+}
diff --git a/libmaple/bkp.c b/libmaple/bkp.c
index ed107d8..b152069 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_peripv(&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_peripv(&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..8177e1e 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_peripv(&EXTI_BASE->RTSR, num) = 1;
+ break;
+ case EXTI_FALLING:
+ *bb_peripv(&EXTI_BASE->FTSR, num) = 1;
+ break;
+ case EXTI_RISING_FALLING:
+ *bb_peripv(&EXTI_BASE->RTSR, num) = 1;
+ *bb_peripv(&EXTI_BASE->FTSR, num) = 1;
+ break;
}
+
+ /* Map num to port */
+ afio_exti_select(num, port);
+
+ /* Unmask external interrupt request */
+ *bb_peripv(&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_peripv(&EXTI_BASE->IMR, num) = 0;
+
+ /* Then, clear the trigger selection registers */
+ *bb_peripv(&EXTI_BASE->FTSR, num) = 0;
+ *bb_peripv(&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_peripv(&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/fsmc.c b/libmaple/fsmc.c
index 49526f4..1561add 100644
--- a/libmaple/fsmc.c
+++ b/libmaple/fsmc.c
@@ -31,6 +31,8 @@
#include "gpio.h"
#include "fsmc.h"
+#ifdef STM32_HIGH_DENSITY
+
/* These values determined for a particular SRAM chip by following the
* calculations in the ST FSMC application note. */
#define FSMC_ADDSET 0x0
@@ -45,55 +47,55 @@ void fsmc_native_sram_init(void) {
/* First we setup all the GPIO pins. */
/* 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, 4, GPIO_AF_OUTPUT_PP); // NOE
+ gpio_set_mode(GPIOD, 5, GPIO_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(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
- gpio_set_mode(GPIOE_BASE, 0, MODE_AF_OUTPUT_PP); // NBL0
- gpio_set_mode(GPIOE_BASE, 1, MODE_AF_OUTPUT_PP); // NBL1
+ gpio_set_mode(GPIOE, 0, GPIO_AF_OUTPUT_PP); // NBL0
+ gpio_set_mode(GPIOE, 1, GPIO_AF_OUTPUT_PP); // NBL1
/* Next enable the clock */
rcc_clk_enable(RCC_FSMC);
@@ -132,3 +134,4 @@ void fsmc_native_sram_init(void) {
/* (FSMC_BWTR3 not used for this simple configuration.) */
}
+#endif /* STM32_HIGH_DENSITY */
diff --git a/libmaple/fsmc.h b/libmaple/fsmc.h
index e83b529..fed6894 100644
--- a/libmaple/fsmc.h
+++ b/libmaple/fsmc.h
@@ -37,6 +37,8 @@
extern "C"{
#endif
+#ifdef STM32_HIGH_DENSITY
+
// There are 4 FSMC chip-select devices; here are the SRAM-specific registers
// for each
@@ -82,9 +84,10 @@ typedef struct {
void fsmc_native_sram_init(void);
+#endif /* STM32_HIGH_DENSITY */
+
#ifdef __cplusplus
} // extern "C"
#endif
-
#endif
diff --git a/libmaple/gpio.c b/libmaple/gpio.c
index 71e5230..b08be12 100644
--- a/libmaple/gpio.c
+++ b/libmaple/gpio.c
@@ -26,44 +26,151 @@
* @brief GPIO initialization routine
*/
-#include "libmaple.h"
-#include "rcc.h"
#include "gpio.h"
+#include "rcc.h"
+
+/*
+ * GPIO devices
+ */
+
+static gpio_dev gpioa = {
+ .regs = GPIOA_BASE,
+ .clk_id = RCC_GPIOA
+};
+/** GPIO port A device. */
+gpio_dev *GPIOA = &gpioa;
+
+static gpio_dev gpiob = {
+ .regs = GPIOB_BASE,
+ .clk_id = RCC_GPIOB
+};
+/** GPIO port B device. */
+gpio_dev *GPIOB = &gpiob;
+
+static gpio_dev gpioc = {
+ .regs = GPIOC_BASE,
+ .clk_id = RCC_GPIOC
+};
+/** GPIO port C device. */
+gpio_dev *GPIOC = &gpioc;
+
+static gpio_dev gpiod = {
+ .regs = GPIOD_BASE,
+ .clk_id = RCC_GPIOD
+};
+/** GPIO port D device. */
+gpio_dev *GPIOD = &gpiod;
+
+#ifdef STM32_HIGH_
+static gpio_dev gpioe = {
+ .regs = GPIOE_BASE,
+ .clk_id = RCC_GPIOE
+};
+/** GPIO port E device. */
+gpio_dev *GPIOE = &gpioe;
+
+static gpio_dev gpiof = {
+ .regs = GPIOF_BASE,
+ .clk_id = RCC_GPIOF
+};
+/** GPIO port F device. */
+gpio_dev *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);
+static gpio_dev gpiog = {
+ .regs = GPIOG_BASE,
+ .clk_id = RCC_GPIOG
+};
+/** GPIO port G device. */
+gpio_dev *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 = &regs->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..48dbc00 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;
+
+/** GPIO port A device */
+extern gpio_dev *GPIOA;
+/** GPIO port B device */
+extern gpio_dev *GPIOB;
+/** GPIO port C device */
+extern gpio_dev *GPIOC;
+/** GPIO port D device */
+extern gpio_dev *GPIOD;
+#ifdef STM32_HIGH_DENSITY
+/** GPIO port E device */
+extern gpio_dev *GPIOE;
+/** GPIO port F device */
+extern gpio_dev *GPIOF;
+/** GPIO port G device */
+extern gpio_dev *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/libmaple.h b/libmaple/libmaple.h
index 6b75c96..0bbd34e 100644
--- a/libmaple/libmaple.h
+++ b/libmaple/libmaple.h
@@ -36,7 +36,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
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.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 410ab8b..8697e01 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_
@@ -182,7 +184,6 @@ typedef enum {
RCC_BKP,
} 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..f7baa6c 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;
/**
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/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..9003da9 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"
/******************************************************************************
******************************************************************************
@@ -31,19 +32,19 @@
/* 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 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 USB_DISC_DEV GPIOB
#define USB_DISC_PIN 8
#else
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) \