From 4b86c281410aa330a1640e4211ae9da476dd0f56 Mon Sep 17 00:00:00 2001 From: Jeff Ciesielski Date: Fri, 19 Oct 2012 16:27:17 -0700 Subject: stm32/f1/can: Add loopback/silent vars to init function. Also: add helper function for mailbox checking --- include/libopencm3/stm32/can.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/libopencm3') diff --git a/include/libopencm3/stm32/can.h b/include/libopencm3/stm32/can.h index d6636d5..f787df7 100644 --- a/include/libopencm3/stm32/can.h +++ b/include/libopencm3/stm32/can.h @@ -619,7 +619,8 @@ BEGIN_DECLS void can_reset(u32 canport); int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart, - bool rflm, bool txfp, u32 sjw, u32 ts1, u32 ts2, u32 brp); + bool rflm, bool txfp, u32 sjw, u32 ts1, u32 ts2, u32 brp, + bool loopback, bool silent); void can_filter_init(u32 canport, u32 nr, bool scale_32bit, bool id_list_mode, u32 fr1, u32 fr2, u32 fifo, bool enable); @@ -640,7 +641,7 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext, bool *rtr, u32 *fmi, u8 *length, u8 *data); void can_fifo_release(u32 canport, u8 fifo); - +bool can_available_mailbox(u32 canport); END_DECLS #endif -- cgit v1.2.3 From a2fc8768c60acdc01b5907984c4f5b79575d4c47 Mon Sep 17 00:00:00 2001 From: Jeff Ciesielski Date: Fri, 19 Oct 2012 16:28:44 -0700 Subject: stm32/f1/dma: add clear_flag helper function --- include/libopencm3/stm32/f1/dma.h | 1 + lib/stm32/f1/dma.c | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'include/libopencm3') diff --git a/include/libopencm3/stm32/f1/dma.h b/include/libopencm3/stm32/f1/dma.h index b08803f..8a2edba 100644 --- a/include/libopencm3/stm32/f1/dma.h +++ b/include/libopencm3/stm32/f1/dma.h @@ -369,6 +369,7 @@ void dma_disable_channel(u32 dma, u8 channel); void dma_set_peripheral_address(u32 dma, u8 channel, u32 address); void dma_set_memory_address(u32 dma, u8 channel, u32 address); void dma_set_number_of_data(u32 dma, u8 channel, u16 number); +void dma_clear_flag(u32 dma, u32 flag); END_DECLS diff --git a/lib/stm32/f1/dma.c b/lib/stm32/f1/dma.c index 04cb8a1..2bc8926 100644 --- a/lib/stm32/f1/dma.c +++ b/lib/stm32/f1/dma.c @@ -363,5 +363,10 @@ void dma_set_number_of_data(u32 dma, u8 channel, u16 number) { DMA_CNDTR(dma, channel) = number; } + +void dma_clear_flag(u32 dma, u32 flag) +{ + DMA_ISR(dma) &= ~flag; +} /**@}*/ -- cgit v1.2.3 From be4ee41ef98bfd40480634812fee6cccd5cd7360 Mon Sep 17 00:00:00 2001 From: Jeff Ciesielski Date: Fri, 19 Oct 2012 16:29:20 -0700 Subject: stm32/f1/i2c: add a whole bevy of additional helper functions --- include/libopencm3/stm32/i2c.h | 16 +++++++- lib/stm32/i2c.c | 93 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 2 deletions(-) (limited to 'include/libopencm3') diff --git a/include/libopencm3/stm32/i2c.h b/include/libopencm3/stm32/i2c.h index a59c420..05a4d16 100644 --- a/include/libopencm3/stm32/i2c.h +++ b/include/libopencm3/stm32/i2c.h @@ -322,7 +322,8 @@ LGPL License Terms @ref lgpl_license /* DUTY: Fast Mode Duty Cycle */ #define I2C_CCR_DUTY (1 << 14) - +#define I2C_CCR_DUTY_DIV2 0 +#define I2C_CCR_DUTY_16_DIV_9 1 /* Note: Bits [13:12] are reserved, and forced to 0 by hardware. */ /* @@ -359,6 +360,7 @@ void i2c_peripheral_enable(u32 i2c); void i2c_peripheral_disable(u32 i2c); void i2c_send_start(u32 i2c); void i2c_send_stop(u32 i2c); +void i2c_clear_stop(u32 i2c); void i2c_set_own_7bit_slave_address(u32 i2c, u8 slave); void i2c_set_own_10bit_slave_address(u32 i2c, u16 slave); void i2c_set_fast_mode(u32 i2c); @@ -368,6 +370,18 @@ void i2c_set_ccr(u32 i2c, u16 freq); void i2c_set_trise(u32 i2c, u16 trise); void i2c_send_7bit_address(u32 i2c, u8 slave, u8 readwrite); void i2c_send_data(u32 i2c, u8 data); +uint8_t i2c_get_data(u32 i2c); +void i2c_enable_interrupt(u32 i2c, u32 interrupt); +void i2c_disable_interrupt(u32 i2c, u32 interrupt); +void i2c_enable_ack(u32 i2c); +void i2c_disable_ack(u32 i2c); +void i2c_nack_next(u32 i2c); +void i2c_nack_current(u32 i2c); +void i2c_set_dutycycle(u32 i2c, u32 dutycycle); +void i2c_enable_dma(u32 i2c); +void i2c_disable_dma(u32 i2c); +void i2c_set_dma_last_transfer(u32 i2c); +void i2c_clear_dma_last_transfer(u32 i2c); END_DECLS diff --git a/lib/stm32/i2c.c b/lib/stm32/i2c.c index e1d3a09..e1e6253 100644 --- a/lib/stm32/i2c.c +++ b/lib/stm32/i2c.c @@ -124,6 +124,18 @@ void i2c_send_stop(u32 i2c) I2C_CR1(i2c) |= I2C_CR1_STOP; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Clear Stop Flag. + +Clear the "Send Stop" flag in the I2C config register + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ +void i2c_clear_stop(u32 i2c) +{ + I2C_CR1(i2c) &= ~I2C_CR1_STOP; +} + /*-----------------------------------------------------------------------------*/ /** @brief I2C Set the 7 bit Slave Address for the Peripheral. @@ -269,5 +281,84 @@ void i2c_send_data(u32 i2c, u8 data) I2C_DR(i2c) = data; } -/**@}*/ +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Get Data. + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ +uint8_t i2c_get_data(u32 i2c) +{ + return (I2C_DR(i2c) & 0xff); +} + +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Enable Interrupt + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +@param[in] interrupt Unsigned int32. Interrupt to enable. +*/ +void i2c_enable_interrupt(u32 i2c, u32 interrupt) +{ + I2C_CR2(i2c) |= interrupt; +} + +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Disable Interrupt + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +@param[in] interrupt Unsigned int32. Interrupt to disable. +*/ +void i2c_disable_interrupt(u32 i2c, u32 interrupt) +{ + I2C_CR2(i2c) &= ~interrupt; +} +void i2c_enable_ack(u32 i2c) +{ + I2C_CR1(i2c) |= I2C_CR1_ACK; +} + +void i2c_disable_ack(u32 i2c) +{ + I2C_CR1(i2c) &= ~I2C_CR1_ACK; +} + +void i2c_nack_next(u32 i2c) +{ + I2C_CR1(i2c) |= I2C_CR1_POS; +} + +void i2c_nack_current(u32 i2c) +{ + I2C_CR1(i2c) &= ~I2C_CR1_POS; +} + +void i2c_set_dutycycle(u32 i2c, u32 dutycycle) +{ + if (dutycycle == I2C_CCR_DUTY_DIV2) + I2C_CCR(i2c) &= ~I2C_CCR_DUTY; + else + I2C_CCR(i2c) |= I2C_CCR_DUTY; +} + +void i2c_enable_dma(u32 i2c) +{ + I2C_CR2(i2c) |= I2C_CR2_DMAEN; +} + +void i2c_disable_dma(u32 i2c) +{ + I2C_CR2(i2c) &= ~I2C_CR2_DMAEN; +} + +void i2c_set_dma_last_transfer(u32 i2c) +{ + I2C_CR2(i2c) |= I2C_CR2_LAST; +} + +void i2c_clear_dma_last_transfer(u32 i2c) +{ + I2C_CR2(i2c) &= ~I2C_CR2_LAST; +} + +/**@}*/ -- cgit v1.2.3 From 069a758f6c59faaed61da45c12573f831da9c4af Mon Sep 17 00:00:00 2001 From: Jeff Ciesielski Date: Fri, 19 Oct 2012 16:31:52 -0700 Subject: stm32/f1/rcc: add 25mhz in to 72mhz out clock tree setup function. also: added support for previously undefined PLLs --- include/libopencm3/stm32/f1/rcc.h | 24 +++++- lib/stm32/f1/rcc.c | 167 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 2 deletions(-) (limited to 'include/libopencm3') diff --git a/include/libopencm3/stm32/f1/rcc.h b/include/libopencm3/stm32/f1/rcc.h index 855e43b..52b3469 100644 --- a/include/libopencm3/stm32/f1/rcc.h +++ b/include/libopencm3/stm32/f1/rcc.h @@ -86,7 +86,7 @@ LGPL License Terms @ref lgpl_license #define RCC_CFGR_MCO_SYSCLK 0x4 #define RCC_CFGR_MCO_HSICLK 0x5 #define RCC_CFGR_MCO_HSECLK 0x6 -#define RCC_CFGR_RMCO_PLLCLK_DIV2 0x7 +#define RCC_CFGR_MCO_PLLCLK_DIV2 0x7 #define RCC_CFGR_MCO_PLL2CLK 0x8 /* (**) */ #define RCC_CFGR_MCO_PLL3CLK_DIV2 0x9 /* (**) */ #define RCC_CFGR_MCO_XT1 0xa /* (**) */ @@ -448,6 +448,24 @@ LGPL License Terms @ref lgpl_license #define RCC_CFGR2_PLL2MUL_PLL2_CLK_MUL16 0xe #define RCC_CFGR2_PLL2MUL_PLL2_CLK_MUL20 0xf +/* PREDIV: PREDIV division factor */ +#define RCC_CFGR2_PREDIV_NODIV 0x0 +#define RCC_CFGR2_PREDIV_DIV2 0x1 +#define RCC_CFGR2_PREDIV_DIV3 0x2 +#define RCC_CFGR2_PREDIV_DIV4 0x3 +#define RCC_CFGR2_PREDIV_DIV5 0x4 +#define RCC_CFGR2_PREDIV_DIV6 0x5 +#define RCC_CFGR2_PREDIV_DIV7 0x6 +#define RCC_CFGR2_PREDIV_DIV8 0x7 +#define RCC_CFGR2_PREDIV_DIV9 0x8 +#define RCC_CFGR2_PREDIV_DIV10 0x9 +#define RCC_CFGR2_PREDIV_DIV11 0xa +#define RCC_CFGR2_PREDIV_DIV12 0xb +#define RCC_CFGR2_PREDIV_DIV13 0xc +#define RCC_CFGR2_PREDIV_DIV14 0xd +#define RCC_CFGR2_PREDIV_DIV15 0xe +#define RCC_CFGR2_PREDIV_DIV16 0xf + /* PREDIV2: PREDIV2 division factor */ #define RCC_CFGR2_PREDIV2_NODIV 0x0 #define RCC_CFGR2_PREDIV2_DIV2 0x1 @@ -473,7 +491,7 @@ extern u32 rcc_ppre2_frequency; /* --- Function prototypes ------------------------------------------------- */ typedef enum { - PLL, HSE, HSI, LSE, LSI + PLL, PLL2, PLL3, HSE, HSI, LSE, LSI } osc_t; BEGIN_DECLS @@ -497,6 +515,7 @@ void rcc_peripheral_reset(volatile u32 *reg, u32 reset); void rcc_peripheral_clear_reset(volatile u32 *reg, u32 clear_reset); void rcc_set_sysclk_source(u32 clk); void rcc_set_pll_multiplication_factor(u32 mul); +void rcc_set_pll2_multiplication_factor(u32 mul); void rcc_set_pll_source(u32 pllsrc); void rcc_set_pllxtpre(u32 pllxtpre); void rcc_set_adcpre(u32 adcpre); @@ -512,6 +531,7 @@ void rcc_clock_setup_in_hse_8mhz_out_24mhz(void); void rcc_clock_setup_in_hse_8mhz_out_72mhz(void); void rcc_clock_setup_in_hse_12mhz_out_72mhz(void); void rcc_clock_setup_in_hse_16mhz_out_72mhz(void); +void rcc_clock_setup_in_hse_25mhz_out_72mhz(void); void rcc_backupdomain_reset(void); END_DECLS diff --git a/lib/stm32/f1/rcc.c b/lib/stm32/f1/rcc.c index ab3350b..9cd8658 100644 --- a/lib/stm32/f1/rcc.c +++ b/lib/stm32/f1/rcc.c @@ -71,6 +71,12 @@ void rcc_osc_ready_int_clear(osc_t osc) case PLL: RCC_CIR |= RCC_CIR_PLLRDYC; break; + case PLL2: + RCC_CIR |= RCC_CIR_PLL2RDYC; + break; + case PLL3: + RCC_CIR |= RCC_CIR_PLL3RDYC; + break; case HSE: RCC_CIR |= RCC_CIR_HSERDYC; break; @@ -98,6 +104,12 @@ void rcc_osc_ready_int_enable(osc_t osc) case PLL: RCC_CIR |= RCC_CIR_PLLRDYIE; break; + case PLL2: + RCC_CIR |= RCC_CIR_PLL2RDYIE; + break; + case PLL3: + RCC_CIR |= RCC_CIR_PLL3RDYIE; + break; case HSE: RCC_CIR |= RCC_CIR_HSERDYIE; break; @@ -125,6 +137,12 @@ void rcc_osc_ready_int_disable(osc_t osc) case PLL: RCC_CIR &= ~RCC_CIR_PLLRDYIE; break; + case PLL2: + RCC_CIR &= ~RCC_CIR_PLL2RDYIE; + break; + case PLL3: + RCC_CIR &= ~RCC_CIR_PLL3RDYIE; + break; case HSE: RCC_CIR &= ~RCC_CIR_HSERDYIE; break; @@ -153,6 +171,12 @@ int rcc_osc_ready_int_flag(osc_t osc) case PLL: return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0); break; + case PLL2: + return ((RCC_CIR & RCC_CIR_PLL2RDYF) != 0); + break; + case PLL3: + return ((RCC_CIR & RCC_CIR_PLL3RDYF) != 0); + break; case HSE: return ((RCC_CIR & RCC_CIR_HSERDYF) != 0); break; @@ -203,6 +227,12 @@ void rcc_wait_for_osc_ready(osc_t osc) case PLL: while ((RCC_CR & RCC_CR_PLLRDY) == 0); break; + case PLL2: + while ((RCC_CR & RCC_CR_PLL2RDY) == 0); + break; + case PLL3: + while ((RCC_CR & RCC_CR_PLL3RDY) == 0); + break; case HSE: while ((RCC_CR & RCC_CR_HSERDY) == 0); break; @@ -238,6 +268,12 @@ void rcc_osc_on(osc_t osc) case PLL: RCC_CR |= RCC_CR_PLLON; break; + case PLL2: + RCC_CR |= RCC_CR_PLL2ON; + break; + case PLL3: + RCC_CR |= RCC_CR_PLL3ON; + break; case HSE: RCC_CR |= RCC_CR_HSEON; break; @@ -273,6 +309,12 @@ void rcc_osc_off(osc_t osc) case PLL: RCC_CR &= ~RCC_CR_PLLON; break; + case PLL2: + RCC_CR &= ~RCC_CR_PLL2ON; + break; + case PLL3: + RCC_CR &= ~RCC_CR_PLL3ON; + break; case HSE: RCC_CR &= ~RCC_CR_HSEON; break; @@ -331,6 +373,8 @@ void rcc_osc_bypass_enable(osc_t osc) RCC_BDCR |= RCC_BDCR_LSEBYP; break; case PLL: + case PLL2: + case PLL3: case HSI: case LSI: /* Do nothing, only HSE/LSE allowed here. */ @@ -361,6 +405,8 @@ void rcc_osc_bypass_disable(osc_t osc) RCC_BDCR &= ~RCC_BDCR_LSEBYP; break; case PLL: + case PLL2: + case PLL3: case HSI: case LSI: /* Do nothing, only HSE/LSE allowed here. */ @@ -484,6 +530,40 @@ void rcc_set_pll_multiplication_factor(u32 mul) RCC_CFGR = (reg32 | (mul << 18)); } +/*-----------------------------------------------------------------------------*/ +/** @brief RCC Set the PLL2 Multiplication Factor. + +@note This only has effect when the PLL is disabled. + +@param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf +*/ + +void rcc_set_pll2_multiplication_factor(u32 mul) +{ + u32 reg32; + + reg32 = RCC_CFGR2; + reg32 &= ~((1 << 11) | (1 << 10) | (1 << 9) | (1 << 8)); + RCC_CFGR2 = (reg32 | (mul << 8)); +} + +/*-----------------------------------------------------------------------------*/ +/** @brief RCC Set the PLL3 Multiplication Factor. + +@note This only has effect when the PLL is disabled. + +@param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf +*/ + +void rcc_set_pll3_multiplication_factor(u32 mul) +{ + u32 reg32; + + reg32 = RCC_CFGR2; + reg32 &= ~((1 << 15) | (1 << 14) | (1 << 13) | (1 << 12)); + RCC_CFGR2 = (reg32 | (mul << 12)); +} + /*-----------------------------------------------------------------------------*/ /** @brief RCC Set the PLL Clock Source. @@ -602,6 +682,36 @@ void rcc_set_usbpre(u32 usbpre) RCC_CFGR = (reg32 | (usbpre << 22)); } +void rcc_set_prediv1(u32 prediv) +{ + u32 reg32; + reg32 = RCC_CFGR2; + reg32 &= ~(1 << 3) | (1 << 2) | (1 << 1) | (1 << 0); + RCC_CFGR2 |= (reg32 | prediv); +} + +void rcc_set_prediv2(u32 prediv) +{ + u32 reg32; + reg32 = RCC_CFGR2; + reg32 &= ~(1 << 7) | (1 << 6) | (1 << 5) | (1 << 4); + RCC_CFGR2 |= (reg32 | (prediv << 4)); +} + +void rcc_set_prediv1_source(u32 rccsrc) +{ + RCC_CFGR2 &= ~(1 << 16); + RCC_CFGR2 |= (rccsrc << 16); +} + +void rcc_set_mco(u32 mcosrc) +{ + u32 reg32; + reg32 = RCC_CFGR; + reg32 &= ~((1 << 27) | (1 << 26) | (1 << 25) | (1 << 24)); + RCC_CFGR |= (reg32 | (mcosrc << 24)); +} + /*-----------------------------------------------------------------------------*/ /** @brief RCC Get the System Clock Source. @@ -1030,6 +1140,63 @@ void rcc_clock_setup_in_hse_16mhz_out_72mhz(void) rcc_ppre2_frequency = 72000000; } +/*-----------------------------------------------------------------------------*/ +/** @brief RCC Set System Clock PLL at 72MHz from HSE at 25MHz + +*/ + +void rcc_clock_setup_in_hse_25mhz_out_72mhz(void) +{ + /* Enable external high-speed oscillator 25MHz. */ + rcc_osc_on(HSE); + rcc_wait_for_osc_ready(HSE); + rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK); + + /* + * Sysclk runs with 72MHz -> 2 waitstates. + * 0WS from 0-24MHz + * 1WS from 24-48MHz + * 2WS from 48-72MHz + */ + flash_set_ws(FLASH_LATENCY_2WS); + + /* + * Set prescalers for AHB, ADC, ABP1, ABP2. + * Do this before touching the PLL (TODO: why?). + */ + rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 72MHz Max. 72MHz */ + rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV6); /* Set. 12MHz Max. 14MHz */ + rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 36MHz Max. 36MHz */ + rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 72MHz Max. 72MHz */ + + /* Set pll2 prediv and multiplier */ + rcc_set_prediv2(RCC_CFGR2_PREDIV2_DIV5); + rcc_set_pll2_multiplication_factor(RCC_CFGR2_PLL2MUL_PLL2_CLK_MUL8); + + /* Enable PLL2 oscillator and wait for it to stabilize */ + rcc_osc_on(PLL2); + rcc_wait_for_osc_ready(PLL2); + + /* Set pll1 prediv/multiplier, prediv1 src, and usb predivider */ + rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK); + rcc_set_prediv1_source(RCC_CFGR2_PREDIV1SRC_PLL2_CLK); + rcc_set_prediv1(RCC_CFGR2_PREDIV_DIV5); + rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL9); + rcc_set_pll_source(RCC_CFGR_PLLSRC_PREDIV1_CLK); + rcc_set_usbpre(RCC_CFGR_USBPRE_PLL_VCO_CLK_DIV3); + + /* enable PLL1 and wait for it to stabilize */ + rcc_osc_on(PLL); + rcc_wait_for_osc_ready(PLL); + + /* Select PLL as SYSCLK source. */ + rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK); + + /* Set the peripheral clock frequencies used */ + rcc_ppre1_frequency = 36000000; + rcc_ppre2_frequency = 72000000; +} + /*-----------------------------------------------------------------------------*/ /** @brief RCC Reset the backup domain -- cgit v1.2.3 From f80bf1ccb107e2ad54d7d8ac586e9ffd09e8730e Mon Sep 17 00:00:00 2001 From: Jeff Ciesielski Date: Mon, 22 Oct 2012 15:48:22 -0700 Subject: stm32/i2c: Add DOXYGEN strings for i2c helper functions. Also: Define i2c_dutycycle group in i2c header --- include/libopencm3/stm32/i2c.h | 6 +++++ lib/stm32/i2c.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) (limited to 'include/libopencm3') diff --git a/include/libopencm3/stm32/i2c.h b/include/libopencm3/stm32/i2c.h index 05a4d16..1b2dc0e 100644 --- a/include/libopencm3/stm32/i2c.h +++ b/include/libopencm3/stm32/i2c.h @@ -321,9 +321,15 @@ LGPL License Terms @ref lgpl_license #define I2C_CCR_FS (1 << 15) /* DUTY: Fast Mode Duty Cycle */ +/** @defgroup i2c_duty_cycle I2C peripheral clock duty cycles +@ingroup i2c_defines + +@{*/ #define I2C_CCR_DUTY (1 << 14) #define I2C_CCR_DUTY_DIV2 0 #define I2C_CCR_DUTY_16_DIV_9 1 +/**@}*/ + /* Note: Bits [13:12] are reserved, and forced to 0 by hardware. */ /* diff --git a/lib/stm32/i2c.c b/lib/stm32/i2c.c index e6869f6..a67bece 100644 --- a/lib/stm32/i2c.c +++ b/lib/stm32/i2c.c @@ -313,26 +313,57 @@ void i2c_disable_interrupt(u32 i2c, u32 interrupt) I2C_CR2(i2c) &= ~interrupt; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Enable ACK + +Enables acking of own 7/10 bit address +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ void i2c_enable_ack(u32 i2c) { I2C_CR1(i2c) |= I2C_CR1_ACK; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Disable ACK + +Disables acking of own 7/10 bit address +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ void i2c_disable_ack(u32 i2c) { I2C_CR1(i2c) &= ~I2C_CR1_ACK; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C NACK Next Byte + +Causes the I2C controller to NACK the reception of the next byte +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ void i2c_nack_next(u32 i2c) { I2C_CR1(i2c) |= I2C_CR1_POS; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C NACK Next Byte + +Causes the I2C controller to NACK the reception of the current byte + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ void i2c_nack_current(u32 i2c) { I2C_CR1(i2c) &= ~I2C_CR1_POS; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Set clock duty cycle + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +@param[in] dutycycle Unsigned int32. I2C duty cycle @ref i2c_duty_cycle. +*/ void i2c_set_dutycycle(u32 i2c, u32 dutycycle) { if (dutycycle == I2C_CCR_DUTY_DIV2) @@ -341,21 +372,41 @@ void i2c_set_dutycycle(u32 i2c, u32 dutycycle) I2C_CCR(i2c) |= I2C_CCR_DUTY; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Enable DMA + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ void i2c_enable_dma(u32 i2c) { I2C_CR2(i2c) |= I2C_CR2_DMAEN; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Disable DMA + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ void i2c_disable_dma(u32 i2c) { I2C_CR2(i2c) &= ~I2C_CR2_DMAEN; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Set DMA last transfer + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ void i2c_set_dma_last_transfer(u32 i2c) { I2C_CR2(i2c) |= I2C_CR2_LAST; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Clear DMA last transfer + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ void i2c_clear_dma_last_transfer(u32 i2c) { I2C_CR2(i2c) &= ~I2C_CR2_LAST; -- cgit v1.2.3 From 7e9b79aa55875b636e690ddf6f9ec2ac7aebf786 Mon Sep 17 00:00:00 2001 From: Jeff Ciesielski Date: Wed, 31 Oct 2012 17:01:56 -0700 Subject: stm32/can: add 'shift' defines for can timing bits Useful whe you want to return min/max values of timing parameters --- include/libopencm3/stm32/can.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/libopencm3') diff --git a/include/libopencm3/stm32/can.h b/include/libopencm3/stm32/can.h index f787df7..1919da4 100644 --- a/include/libopencm3/stm32/can.h +++ b/include/libopencm3/stm32/can.h @@ -417,6 +417,7 @@ #define CAN_BTR_SJW_3TQ (0x2 << 24) #define CAN_BTR_SJW_4TQ (0x3 << 24) #define CAN_BTR_SJW_MASK (0x3 << 24) +#define CAN_BTR_SJW_SHIFT 24 /* 23 Reserved, forced by hardware to 0 */ @@ -430,6 +431,7 @@ #define CAN_BTR_TS2_7TQ (0x6 << 20) #define CAN_BTR_TS2_8TQ (0x7 << 20) #define CAN_BTR_TS2_MASK (0x7 << 20) +#define CAN_BTR_TS2_SHIFT 20 /* TS1[3:0]: Time segment 1 */ #define CAN_BTR_TS1_1TQ (0x0 << 16) @@ -449,6 +451,7 @@ #define CAN_BTR_TS1_15TQ (0xE << 16) #define CAN_BTR_TS1_16TQ (0xF << 16) #define CAN_BTR_TS1_MASK (0xF << 16) +#define CAN_BTR_TS1_SHIFT 16 /* 15:10 Reserved, forced by hardware to 0 */ -- cgit v1.2.3 From e5cf92b9aee4ce70f000961309d4fb9a9222a7b5 Mon Sep 17 00:00:00 2001 From: Jeff Ciesielski Date: Fri, 2 Nov 2012 10:52:25 -0700 Subject: stm32/f1/rcc: expose method for selecting MCO source --- include/libopencm3/stm32/f1/rcc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/libopencm3') diff --git a/include/libopencm3/stm32/f1/rcc.h b/include/libopencm3/stm32/f1/rcc.h index 52b3469..868ad9c 100644 --- a/include/libopencm3/stm32/f1/rcc.h +++ b/include/libopencm3/stm32/f1/rcc.h @@ -507,6 +507,7 @@ void rcc_osc_on(osc_t osc); void rcc_osc_off(osc_t osc); void rcc_css_enable(void); void rcc_css_disable(void); +void rcc_set_mco(u32 mcosrc); void rcc_osc_bypass_enable(osc_t osc); void rcc_osc_bypass_disable(osc_t osc); void rcc_peripheral_enable_clock(volatile u32 *reg, u32 en); -- cgit v1.2.3 From 7a5da60e2669c57d7b615aabe16ab851606f8bf1 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 6 Nov 2012 16:46:55 -0800 Subject: Change USB strings handling code This commit add an extra field to the _usbd_device, that allows to keep track of the number of USB strings which allows simplify boundaries checking code in usb_standard_get_descriptor. This commit also changes the index base for strings in usb_standard_get_descriptor which allows to get rid of necessity to have a dummy one-character string in a strings array. --- include/libopencm3/usb/usbd.h | 2 +- lib/usb/usb.c | 4 +++- lib/usb/usb_private.h | 1 + lib/usb/usb_standard.c | 22 +++++++++++----------- 4 files changed, 16 insertions(+), 13 deletions(-) (limited to 'include/libopencm3') diff --git a/include/libopencm3/usb/usbd.h b/include/libopencm3/usb/usbd.h index e4b3578..9da8379 100644 --- a/include/libopencm3/usb/usbd.h +++ b/include/libopencm3/usb/usbd.h @@ -38,7 +38,7 @@ extern u8 usbd_control_buffer[]; extern int usbd_init(const usbd_driver *driver, const struct usb_device_descriptor *dev, const struct usb_config_descriptor *conf, - const char **strings); + const char **strings, int num_strings); extern void usbd_set_control_buffer_size(u16 size); extern void usbd_register_reset_callback(void (*callback)(void)); diff --git a/lib/usb/usb.c b/lib/usb/usb.c index 1ebb6ec..d5ec980 100644 --- a/lib/usb/usb.c +++ b/lib/usb/usb.c @@ -45,12 +45,14 @@ u8 usbd_control_buffer[128] __attribute__((weak)); */ int usbd_init(const usbd_driver *driver, const struct usb_device_descriptor *dev, - const struct usb_config_descriptor *conf, const char **strings) + const struct usb_config_descriptor *conf, + const char **strings, int num_strings) { _usbd_device.driver = driver; _usbd_device.desc = dev; _usbd_device.config = conf; _usbd_device.strings = strings; + _usbd_device.num_strings = num_strings; _usbd_device.ctrl_buf = usbd_control_buffer; _usbd_device.ctrl_buf_len = sizeof(usbd_control_buffer); diff --git a/lib/usb/usb_private.h b/lib/usb/usb_private.h index a1e5e4c..238f14f 100644 --- a/lib/usb/usb_private.h +++ b/lib/usb/usb_private.h @@ -29,6 +29,7 @@ extern struct _usbd_device { const struct usb_device_descriptor *desc; const struct usb_config_descriptor *config; const char **strings; + int num_strings; u8 *ctrl_buf; /**< Internal buffer used for control transfers */ u16 ctrl_buf_len; diff --git a/lib/usb/usb_standard.c b/lib/usb/usb_standard.c index 2d7c619..1c8b952 100644 --- a/lib/usb/usb_standard.c +++ b/lib/usb/usb_standard.c @@ -90,7 +90,7 @@ static u16 build_config_descriptor(u8 index, u8 *buf, u16 len) static int usb_standard_get_descriptor(struct usb_setup_data *req, u8 **buf, u16 *len) { - int i; + int i, index; struct usb_string_descriptor *sd; switch (req->wValue >> 8) { @@ -105,16 +105,20 @@ static int usb_standard_get_descriptor(struct usb_setup_data *req, case USB_DT_STRING: sd = (struct usb_string_descriptor *)_usbd_device.ctrl_buf; + /* Send sane Language ID descriptor... */ + if ((req->wValue & 0xff) == 0) + sd->wData[0] = 0x409; + + index = (req->wValue & 0xff) - 1; + if (!_usbd_device.strings) return 0; /* Device doesn't support strings. */ /* Check that string index is in range. */ - for (i = 0; i <= (req->wValue & 0xff); i++) - if (_usbd_device.strings[i] == NULL) - return 0; + if (index >= _usbd_device.num_strings) + return 0; - sd->bLength = strlen(_usbd_device.strings[req->wValue & 0xff]) - * 2 + 2; + sd->bLength = strlen(_usbd_device.strings[index]) * 2 + 2; sd->bDescriptorType = USB_DT_STRING; *buf = (u8 *)sd; @@ -122,11 +126,7 @@ static int usb_standard_get_descriptor(struct usb_setup_data *req, for (i = 0; i < (*len / 2) - 1; i++) sd->wData[i] = - _usbd_device.strings[req->wValue & 0xff][i]; - - /* Send sane Language ID descriptor... */ - if ((req->wValue & 0xff) == 0) - sd->wData[0] = 0x409; + _usbd_device.strings[index][i]; return 1; } -- cgit v1.2.3 From 12e178686331fd0a8e3564a9f0e77fece4a04617 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 6 Nov 2012 16:48:40 -0800 Subject: Add a desig_get_unique_id_as_string This commit adds desig_get_unique_id_as_string which is useful if one wants to use device ID as USB serial number(iSerialNumber), for example. --- include/libopencm3/stm32/f1/desig.h | 9 +++++++++ lib/stm32/f1/desig.c | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'include/libopencm3') diff --git a/include/libopencm3/stm32/f1/desig.h b/include/libopencm3/stm32/f1/desig.h index 74cfb35..6ceb665 100644 --- a/include/libopencm3/stm32/f1/desig.h +++ b/include/libopencm3/stm32/f1/desig.h @@ -51,6 +51,15 @@ u16 desig_get_flash_size(void); */ void desig_get_unique_id(u32 result[]); +/** + * Read the full 96 bit unique identifier and return it as a + * zero-terminated string + * @param string memory region to write the result to + 8 @param string_len the size of string in bytes + */ +void desig_get_unique_id_as_string(char *string, + unsigned int string_len); + END_DECLS #endif diff --git a/lib/stm32/f1/desig.c b/lib/stm32/f1/desig.c index 7ae968e..7f213fa 100644 --- a/lib/stm32/f1/desig.c +++ b/lib/stm32/f1/desig.c @@ -35,3 +35,25 @@ void desig_get_unique_id(u32 result[]) result[1] = bits63_32; result[2] = bits31_16 << 16 | bits15_0; } + +void desig_get_unique_id_as_string(char *string, + unsigned int string_len) +{ + int i, len; + u8 device_id[12]; + static const char chars[] = "0123456789ABCDEF"; + + desig_get_unique_id((u32 *)device_id); + + /* Each byte produces two characters */ + len = (2 * sizeof(device_id) < string_len) ? + 2 * sizeof(device_id) : string_len - 1; + + for (i = 0; i < len; i += 2) { + string[i] = chars[(device_id[i / 2] >> 0) & 0x0F]; + string[i + 1] = chars[(device_id[i / 2] >> 4) & 0x0F]; + } + + string[len] = '\0'; +} + -- cgit v1.2.3 From c5c4db01969608ac19bba290b9f6ec965ef01e5c Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Wed, 7 Nov 2012 10:33:51 -0800 Subject: Extend control hook framework This commits adds a new error code that can be return from a registered control callback: USBD_REQ_NEXT_CALLBACK. This return code signifies that the callback is done processing the data successfully, but user would like to have all matching callbacks down the callback chain to be executed too. This change allows for example to intercept standard requests like GET_DESCRIPTOR, do some small action upon receiving of one, but still have the standard callback executed and do it's job. This way user doesn't have to re-implement standard GET_DESCRIPTOR functionality if they want to intercept that request to do some small thing. --- include/libopencm3/usb/usbd.h | 7 +++++++ lib/usb/usb_control.c | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'include/libopencm3') diff --git a/include/libopencm3/usb/usbd.h b/include/libopencm3/usb/usbd.h index 9da8379..8f68555 100644 --- a/include/libopencm3/usb/usbd.h +++ b/include/libopencm3/usb/usbd.h @@ -24,6 +24,13 @@ BEGIN_DECLS + +enum usbd_request_return_codes { + USBD_REQ_NOTSUPP = 0, + USBD_REQ_HANDLED = 1, + USBD_REQ_NEXT_CALLBACK = 2, +}; + typedef struct _usbd_driver usbd_driver; extern const usbd_driver stm32f103_usb_driver; extern const usbd_driver stm32f107_usb_driver; diff --git a/lib/usb/usb_control.c b/lib/usb/usb_control.c index 3dd0857..b4ac57e 100644 --- a/lib/usb/usb_control.c +++ b/lib/usb/usb_control.c @@ -102,7 +102,8 @@ static int usb_control_request_dispatch(struct usb_setup_data *req) result = cb[i].cb(req, &control_state.ctrl_buf, &control_state.ctrl_len, &control_state.complete); - if (result) + if (result == USBD_REQ_HANDLED || + result == USBD_REQ_NOTSUPP) return result; } } -- cgit v1.2.3 From 720e85f850064ad6ab3e79101b972e43d4e31ef6 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Wed, 7 Nov 2012 11:30:44 -0800 Subject: Further re-factor USB string handling code This commit refactors USB string code, making it, hopefully, less buggy and more easier to understand. It also removes "magic" bit manipulation and "magic" numbers; --- include/libopencm3/usb/usbstd.h | 3 ++ lib/usb/usb_standard.c | 70 +++++++++++++++++++++++++++-------------- 2 files changed, 50 insertions(+), 23 deletions(-) (limited to 'include/libopencm3') diff --git a/include/libopencm3/usb/usbstd.h b/include/libopencm3/usb/usbstd.h index 8610fdb..01fc7e3 100644 --- a/include/libopencm3/usb/usbstd.h +++ b/include/libopencm3/usb/usbstd.h @@ -220,4 +220,7 @@ struct usb_iface_assoc_descriptor { #define USB_DT_INTERFACE_ASSOCIATION_SIZE \ sizeof(struct usb_iface_assoc_descriptor) +enum usb_language_id { + USB_LANGID_ENGLISH_US = 0x409, +}; #endif diff --git a/lib/usb/usb_standard.c b/lib/usb/usb_standard.c index 1c8b952..08923d8 100644 --- a/lib/usb/usb_standard.c +++ b/lib/usb/usb_standard.c @@ -87,50 +87,74 @@ static u16 build_config_descriptor(u8 index, u8 *buf, u16 len) return total; } +static int usb_descriptor_type(u16 wValue) +{ + return wValue >> 8; +} + +static int usb_descriptor_index(u16 wValue) +{ + return wValue & 0xFF; +} + static int usb_standard_get_descriptor(struct usb_setup_data *req, u8 **buf, u16 *len) { - int i, index; + int i, array_idx, descr_idx; struct usb_string_descriptor *sd; - switch (req->wValue >> 8) { + descr_idx = usb_descriptor_index(req->wValue); + + switch (usb_descriptor_type(req->wValue)) { case USB_DT_DEVICE: *buf = (u8 *) _usbd_device.desc; *len = MIN(*len, _usbd_device.desc->bLength); - return 1; + return USBD_REQ_HANDLED; case USB_DT_CONFIGURATION: *buf = _usbd_device.ctrl_buf; - *len = build_config_descriptor(req->wValue & 0xff, *buf, *len); - return 1; + *len = build_config_descriptor(descr_idx, *buf, *len); + return USBD_REQ_HANDLED; case USB_DT_STRING: sd = (struct usb_string_descriptor *)_usbd_device.ctrl_buf; - /* Send sane Language ID descriptor... */ - if ((req->wValue & 0xff) == 0) - sd->wData[0] = 0x409; + if (descr_idx == 0) { + /* Send sane Language ID descriptor... */ + sd->wData[0] = USB_LANGID_ENGLISH_US; + sd->bLength = sizeof(sd->bLength) + sizeof(sd->bDescriptorType) + + sizeof(sd->wData[0]); - index = (req->wValue & 0xff) - 1; + *len = MIN(*len, sd->bLength); + } else { + array_idx = descr_idx - 1; - if (!_usbd_device.strings) - return 0; /* Device doesn't support strings. */ + if (!_usbd_device.strings) + return USBD_REQ_NOTSUPP; /* Device doesn't support strings. */ + /* Check that string index is in range. */ + if (array_idx >= _usbd_device.num_strings) + return USBD_REQ_NOTSUPP; - /* Check that string index is in range. */ - if (index >= _usbd_device.num_strings) - return 0; + /* Strings with Language ID differnet from + * USB_LANGID_ENGLISH_US are not supported */ + if (req->wIndex != USB_LANGID_ENGLISH_US) + return USBD_REQ_NOTSUPP; - sd->bLength = strlen(_usbd_device.strings[index]) * 2 + 2; - sd->bDescriptorType = USB_DT_STRING; + /* Ths string is returned as UTF16, hence the multiplication */ + sd->bLength = strlen(_usbd_device.strings[array_idx]) * 2 + + sizeof(sd->bLength) + sizeof(sd->bDescriptorType); - *buf = (u8 *)sd; - *len = MIN(*len, sd->bLength); + *len = MIN(*len, sd->bLength); + + for (i = 0; i < (*len / 2) - 1; i++) + sd->wData[i] = + _usbd_device.strings[array_idx][i]; + } - for (i = 0; i < (*len / 2) - 1; i++) - sd->wData[i] = - _usbd_device.strings[index][i]; + sd->bDescriptorType = USB_DT_STRING; + *buf = (u8 *)sd; - return 1; + return USBD_REQ_HANDLED; } - return 0; + return USBD_REQ_NOTSUPP; } static int usb_standard_set_address(struct usb_setup_data *req, u8 **buf, -- cgit v1.2.3