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