aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/stm32/f1/lisa-m-1/can/can.c4
-rw-r--r--examples/stm32/f1/other/usb_dfu/usbdfu.c2
-rw-r--r--include/libopencm3/stm32/can.h8
-rw-r--r--include/libopencm3/stm32/desig.h9
-rw-r--r--include/libopencm3/stm32/f1/dma.h1
-rw-r--r--include/libopencm3/stm32/f1/rcc.h25
-rw-r--r--include/libopencm3/stm32/f4/memorymap.h5
-rw-r--r--include/libopencm3/stm32/i2c.h20
-rw-r--r--include/libopencm3/stm32/l1/flash.h125
-rw-r--r--include/libopencm3/stm32/l1/pwr.h93
-rw-r--r--include/libopencm3/stm32/l1/rcc.h44
-rw-r--r--include/libopencm3/stm32/usart.h2
-rw-r--r--include/libopencm3/usb/usbd.h14
-rw-r--r--include/libopencm3/usb/usbstd.h3
-rw-r--r--lib/cm3/vector.c2
-rw-r--r--lib/stm32/can.c24
-rw-r--r--lib/stm32/desig.c22
-rw-r--r--lib/stm32/f1/dma.c5
-rw-r--r--lib/stm32/f1/gpio.c4
-rw-r--r--lib/stm32/f1/rcc.c167
-rw-r--r--lib/stm32/f1/rtc.c2
-rw-r--r--lib/stm32/f4/adc.c10
-rw-r--r--lib/stm32/i2c.c144
-rw-r--r--lib/stm32/l1/Makefile6
-rw-r--r--lib/stm32/l1/flash.c52
-rw-r--r--lib/stm32/l1/pwr_chipset.c37
-rw-r--r--lib/stm32/l1/rcc.c121
-rw-r--r--lib/stm32/timer.c109
-rw-r--r--lib/stm32/usart.c21
-rw-r--r--lib/usb/usb.c3
-rw-r--r--lib/usb/usb_control.c5
-rw-r--r--lib/usb/usb_private.h1
-rw-r--r--lib/usb/usb_standard.c73
33 files changed, 1079 insertions, 84 deletions
diff --git a/examples/stm32/f1/lisa-m-1/can/can.c b/examples/stm32/f1/lisa-m-1/can/can.c
index a4cf30d..463d7fc 100644
--- a/examples/stm32/f1/lisa-m-1/can/can.c
+++ b/examples/stm32/f1/lisa-m-1/can/can.c
@@ -135,7 +135,9 @@ void can_setup(void)
CAN_BTR_SJW_1TQ,
CAN_BTR_TS1_3TQ,
CAN_BTR_TS2_4TQ,
- 12)) /* BRP+1: Baud rate prescaler */
+ 12, /* BRP+1: Baud rate prescaler */
+ false, /* loopback mode */
+ false)) /* silent mode */
{
gpio_set(GPIOA, GPIO8); /* LED0 off */
gpio_set(GPIOB, GPIO4); /* LED1 off */
diff --git a/examples/stm32/f1/other/usb_dfu/usbdfu.c b/examples/stm32/f1/other/usb_dfu/usbdfu.c
index 268274e..44dde16 100644
--- a/examples/stm32/f1/other/usb_dfu/usbdfu.c
+++ b/examples/stm32/f1/other/usb_dfu/usbdfu.c
@@ -249,6 +249,8 @@ int main(void)
AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON;
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15);
+ rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_OTGFSEN);
+
usbd_dev = usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings);
usbd_set_control_buffer_size(usbd_dev, sizeof(usbd_control_buffer));
usbd_register_control_callback(
diff --git a/include/libopencm3/stm32/can.h b/include/libopencm3/stm32/can.h
index c531394..65aca5c 100644
--- a/include/libopencm3/stm32/can.h
+++ b/include/libopencm3/stm32/can.h
@@ -439,6 +439,7 @@ LGPL License Terms @ref lgpl_license
#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 */
@@ -452,6 +453,7 @@ LGPL License Terms @ref lgpl_license
#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)
@@ -471,6 +473,7 @@ LGPL License Terms @ref lgpl_license
#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 */
@@ -641,7 +644,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);
@@ -662,7 +666,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
diff --git a/include/libopencm3/stm32/desig.h b/include/libopencm3/stm32/desig.h
index 74cfb35..6ceb665 100644
--- a/include/libopencm3/stm32/desig.h
+++ b/include/libopencm3/stm32/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/include/libopencm3/stm32/f1/dma.h b/include/libopencm3/stm32/f1/dma.h
index 6e5cc20..6257394 100644
--- a/include/libopencm3/stm32/f1/dma.h
+++ b/include/libopencm3/stm32/f1/dma.h
@@ -394,6 +394,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/include/libopencm3/stm32/f1/rcc.h b/include/libopencm3/stm32/f1/rcc.h
index 855e43b..868ad9c 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
@@ -489,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);
@@ -497,6 +516,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 +532,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/include/libopencm3/stm32/f4/memorymap.h b/include/libopencm3/stm32/f4/memorymap.h
index 0a22ad4..7625838 100644
--- a/include/libopencm3/stm32/f4/memorymap.h
+++ b/include/libopencm3/stm32/f4/memorymap.h
@@ -75,8 +75,9 @@
#define USART6_BASE (PERIPH_BASE_APB2 + 0x1400)
/* PERIPH_BASE_APB2 + 0x1800 (0x4001 1800 - 0x4001 1FFF): Reserved */
#define ADC1_BASE (PERIPH_BASE_APB2 + 0x2000)
-#define ADC2_BASE (PERIPH_BASE_APB2 + 0x2000)
-#define ADC3_BASE (PERIPH_BASE_APB2 + 0x2000)
+#define ADC2_BASE (PERIPH_BASE_APB2 + 0x2100)
+#define ADC3_BASE (PERIPH_BASE_APB2 + 0x2200)
+#define ADC_COMMON_BASE (PERIPH_BASE_APB2 + 0x2300)
/* PERIPH_BASE_APB2 + 0x2400 (0x4001 2400 - 0x4001 27FF): Reserved */
#define SDIO_BASE (PERIPH_BASE_APB2 + 0x2800)
/* PERIPH_BASE_APB2 + 0x2C00 (0x4001 2C00 - 0x4001 2FFF): Reserved */
diff --git a/include/libopencm3/stm32/i2c.h b/include/libopencm3/stm32/i2c.h
index a59c420..1b2dc0e 100644
--- a/include/libopencm3/stm32/i2c.h
+++ b/include/libopencm3/stm32/i2c.h
@@ -321,7 +321,14 @@ 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. */
@@ -359,6 +366,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 +376,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/include/libopencm3/stm32/l1/flash.h b/include/libopencm3/stm32/l1/flash.h
new file mode 100644
index 0000000..ed0a696
--- /dev/null
+++ b/include/libopencm3/stm32/l1/flash.h
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
+ * Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * All extracted from PM0062 rev2, L15xx and L16xx Flash/EEPROM programming manual
+ */
+
+#ifndef LIBOPENCM3_FLASH_H
+#define LIBOPENCM3_FLASH_H
+
+#include <libopencm3/stm32/memorymap.h>
+#include <libopencm3/cm3/common.h>
+
+/* --- FLASH registers ----------------------------------------------------- */
+
+#define FLASH_ACR MMIO32(FLASH_MEM_INTERFACE_BASE + 0x00)
+#define FLASH_PECR MMIO32(FLASH_MEM_INTERFACE_BASE + 0x04)
+#define FLASH_PDKEYR MMIO32(FLASH_MEM_INTERFACE_BASE + 0x08)
+#define FLASH_PEKEYR MMIO32(FLASH_MEM_INTERFACE_BASE + 0x0C)
+#define FLASH_PRGKEYR MMIO32(FLASH_MEM_INTERFACE_BASE + 0x10)
+#define FLASH_OPTKEYR MMIO32(FLASH_MEM_INTERFACE_BASE + 0x14)
+#define FLASH_SR MMIO32(FLASH_MEM_INTERFACE_BASE + 0x18)
+#define FLASH_OBR MMIO32(FLASH_MEM_INTERFACE_BASE + 0x1c)
+#define FLASH_WRPR1 MMIO32(FLASH_MEM_INTERFACE_BASE + 0x20)
+#define FLASH_WRPR2 MMIO32(FLASH_MEM_INTERFACE_BASE + 0x80)
+#define FLASH_WRPR3 MMIO32(FLASH_MEM_INTERFACE_BASE + 0x84)
+
+/* --- FLASH_ACR values ---------------------------------------------------- */
+
+#define FLASH_RUNPD (1 << 4)
+#define FLASH_SLEEPPD (1 << 3)
+#define FLASH_ACC64 (1 << 2)
+#define FLASH_PRFTEN (1 << 1)
+#define FLASH_LATENCY_0WS 0x00
+#define FLASH_LATENCY_1WS 0x01
+
+/* --- FLASH_PECR values. Program/erase control register */
+#define FLASH_OBL_LAUNCH (1 << 18)
+#define FLASH_ERRIE (1 << 17)
+#define FLASH_EOPIE (1 << 16)
+#define FLASH_PARALLBANK (1 << 15)
+#define FLASH_FPRG (1 << 10)
+#define FLASH_ERASE (1 << 9)
+#define FLASH_FTDW (1 << 8)
+#define FLASH_FTDW (1 << 8)
+#define FLASH_DATA (1 << 4)
+#define FLASH_PROG (1 << 3)
+#define FLASH_OPTLOCK (1 << 2)
+#define FLASH_PRGLOCK (1 << 1)
+#define FLASH_PELOCK (1 << 0)
+
+/* Power down key register (FLASH_PDKEYR) */
+#define FLASH_PDKEY1 ((u32)0x04152637)
+#define FLASH_PDKEY2 ((u32)0xFAFBFCFD)
+
+/* Program/erase key register (FLASH_PEKEYR) */
+#define FLASH_PEKEY1 ((u32)0x89ABCDEF)
+#define FLASH_PEKEY2 ((u32)0x02030405)
+
+/* Program memory key register (FLASH_PRGKEYR) */
+#define FLASH_PRGKEY1 ((u32)0x8C9DAEBF)
+#define FLASH_PRGKEY2 ((u32)0x13141516)
+
+/* Option byte key register (FLASH_OPTKEYR) */
+#define FLASH_OPTKEY1 ((u32)0xFBEAD9C8)
+#define FLASH_OPTKEY2 ((u32)0x24252627)
+
+
+/* --- FLASH_SR values ----------------------------------------------------- */
+#define FLASH_OPTVERRUSR (1 << 12)
+#define FLASH_OPTVERR (1 << 11)
+#define FLASH_SIZEERR (1 << 10)
+#define FLASH_PGAERR (1 << 9)
+#define FLASH_WRPERR (1 << 8)
+#define FLASH_READY (1 << 3)
+#define FLASH_ENDHV (1 << 2)
+#define FLASH_EOP (1 << 1)
+#define FLASH_BSY (1 << 0)
+
+/* --- FLASH_OBR values ----------------------------------------------------- */
+#define FLASH_BFB2 (1 << 23)
+#define FLASH_NRST_STDBY (1 << 22)
+#define FLASH_NRST_STOP (1 << 21)
+#define FLASH_IWDG_SW (1 << 20)
+#define FLASH_BOR_OFF (0x0 << 16)
+#define FLASH_BOR_LEVEL_1 (0x8 << 16)
+#define FLASH_BOR_LEVEL_2 (0x9 << 16)
+#define FLASH_BOR_LEVEL_3 (0xa << 16)
+#define FLASH_BOR_LEVEL_4 (0xb << 16)
+#define FLASH_BOR_LEVEL_5 (0xc << 16)
+#define FLASH_RDPRT_LEVEL_0 (0xaa)
+#define FLASH_RDPRT_LEVEL_1 (0x00)
+#define FLASH_RDPRT_LEVEL_2 (0xcc)
+
+/* --- Function prototypes ------------------------------------------------- */
+
+BEGIN_DECLS
+
+void flash_64bit_enable(void);
+void flash_64bit_disable(void);
+void flash_prefetch_enable(void);
+void flash_prefetch_disable(void);
+void flash_set_ws(u32 ws);
+
+END_DECLS
+
+#endif
diff --git a/include/libopencm3/stm32/l1/pwr.h b/include/libopencm3/stm32/l1/pwr.h
new file mode 100644
index 0000000..309b464
--- /dev/null
+++ b/include/libopencm3/stm32/l1/pwr.h
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIBOPENCM3_PWR_L1_H
+#define LIBOPENCM3_PWR_L1_H
+
+#include <libopencm3/stm32/pwr.h>
+
+/*
+ * This file extends the common STM32 version with definitions only
+ * applicable to the STM32L1 series of devices.
+ */
+
+/* --- PWR_CR values ------------------------------------------------------- */
+
+/* Bits [31:15]: Reserved */
+
+/* LPRUN: Low power run mode */
+#define PWR_CR_LPRUN (1 << 14)
+
+/* VOS[12:11]: Regulator voltage scaling output selection */
+#define PWR_CR_VOS_LSB 11
+/** @defgroup pwr_vos Voltage Scaling Output level selection
+@ingroup STM32F_pwr_defines
+
+@{*/
+#define PWR_CR_VOS_RANGE1 (0x1 << PWR_CR_VOS_LSB)
+#define PWR_CR_VOS_RANGE2 (0x2 << PWR_CR_VOS_LSB)
+#define PWR_CR_VOS_RANGE3 (0x3 << PWR_CR_VOS_LSB)
+/**@}*/
+#define PWR_CR_VOS_MASK (0x3 << PWR_CR_VOS_LSB)
+
+/* FWU: Fast wakeup */
+#define PWR_CR_FWU (1 << 10)
+
+/* ULP: Ultralow power mode */
+#define PWR_CR_ULP (1 << 9)
+
+/* --- PWR_CSR values ------------------------------------------------------- */
+
+/* Bits [31:11]: Reserved */
+/* EWUP3: Enable WKUP3 pin */
+#define PWR_CSR_EWUP3 (1 << 10)
+
+/* EWUP2: Enable WKUP2 pin */
+#define PWR_CSR_EWUP2 (1 << 9)
+
+/* EWUP1: Enable WKUP1 pin */
+#define PWR_CSR_EWUP1 PWR_CSR_EWUP
+
+/* REGLPF : Regulator LP flag */
+#define PWR_CSR_REGLPF (1 << 5)
+
+/* VOSF: Voltage Scaling select flag */
+#define PWR_CSR_VOSF (1 << 4)
+
+/* VREFINTRDYF: Internal voltage reference (VREFINT) ready flag */
+#define PWR_CSR_VREFINTRDYF (1 << 3)
+
+
+
+/* --- Function prototypes ------------------------------------------------- */
+
+typedef enum {
+ RANGE1,
+ RANGE2,
+ RANGE3,
+} vos_scale_t;
+
+BEGIN_DECLS
+
+void pwr_set_vos_scale(vos_scale_t scale);
+
+END_DECLS
+
+#endif
diff --git a/include/libopencm3/stm32/l1/rcc.h b/include/libopencm3/stm32/l1/rcc.h
index d888d7c..21b073b 100644
--- a/include/libopencm3/stm32/l1/rcc.h
+++ b/include/libopencm3/stm32/l1/rcc.h
@@ -46,6 +46,7 @@ LGPL License Terms @ref lgpl_license
#include <libopencm3/stm32/memorymap.h>
#include <libopencm3/cm3/common.h>
+#include <libopencm3/stm32/l1/pwr.h>
/* --- RCC registers ------------------------------------------------------- */
@@ -110,6 +111,8 @@ LGPL License Terms @ref lgpl_license
#define RCC_CFGR_PLLDIV_DIV2 0x1
#define RCC_CFGR_PLLDIV_DIV3 0x2
#define RCC_CFGR_PLLDIV_DIV4 0x3
+#define RCC_CFGR_PLLDIV_SHIFT 22
+#define RCC_CFGR_PLLDIV_MASK 0x3
/* PLLMUL: PLL multiplication factor */
#define RCC_CFGR_PLLMUL_MUL3 0x0
@@ -121,6 +124,8 @@ LGPL License Terms @ref lgpl_license
#define RCC_CFGR_PLLMUL_MUL24 0x6
#define RCC_CFGR_PLLMUL_MUL32 0x7
#define RCC_CFGR_PLLMUL_MUL48 0x8
+#define RCC_CFGR_PLLMUL_SHIFT 18
+#define RCC_CFGR_PLLMUL_MASK 0xf
/* PLLSRC: PLL entry clock source */
#define RCC_CFGR_PLLSRC_HSI_CLK 0x0
@@ -231,6 +236,7 @@ LGPL License Terms @ref lgpl_license
#define RCC_APB1RSTR_LCDRST (1 << 9)
#define RCC_APB1RSTR_TIM7RST (1 << 5)
#define RCC_APB1RSTR_TIM6RST (1 << 4)
+#define RCC_APB1RSTR_TIM5RST (1 << 3)
#define RCC_APB1RSTR_TIM4RST (1 << 2)
#define RCC_APB1RSTR_TIM3RST (1 << 1)
#define RCC_APB1RSTR_TIM2RST (1 << 0)
@@ -348,6 +354,28 @@ LGPL License Terms @ref lgpl_license
#define RCC_CSR_LSIRDY (1 << 1)
#define RCC_CSR_LSION (1 << 0)
+typedef struct {
+ uint8_t pll_mul;
+ uint16_t pll_div;
+ uint8_t pll_source;
+ uint32_t flash_config;
+ uint8_t hpre;
+ uint8_t ppre1;
+ uint8_t ppre2;
+ vos_scale_t voltage_scale;
+ uint32_t apb1_frequency;
+ uint32_t apb2_frequency;
+} clock_scale_t;
+
+typedef enum {
+ CLOCK_VRANGE1_HSI_PLL_24MHZ,
+ CLOCK_VRANGE1_HSI_PLL_32MHZ,
+ CLOCK_VRANGE1_HSI_RAW_16MHZ,
+ CLOCK_VRANGE1_END
+} clock_volt_range1_t;
+
+extern const clock_scale_t clock_vrange1_config[CLOCK_VRANGE1_END];
+
/* --- Variable definitions ------------------------------------------------ */
extern u32 rcc_ppre1_frequency;
@@ -377,26 +405,16 @@ void rcc_peripheral_disable_clock(volatile u32 *reg, u32 en);
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_pll_configuration(u32 source, u32 multiplier, u32 divisor);
void rcc_set_pll_source(u32 pllsrc);
-void rcc_set_pllxtpre(u32 pllxtpre);
void rcc_set_adcpre(u32 adcpre);
void rcc_set_ppre2(u32 ppre2);
void rcc_set_ppre1(u32 ppre1);
void rcc_set_hpre(u32 hpre);
void rcc_set_usbpre(u32 usbpre);
u32 rcc_get_system_clock_source(int i);
-void rcc_clock_setup_in_hsi_out_64mhz(void);
-void rcc_clock_setup_in_hsi_out_48mhz(void);
-
-/**
- * Maximum speed possible for F100 (Value Line) on HSI
- */
-void rcc_clock_setup_in_hsi_out_24mhz(void);
-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_hsi(const clock_scale_t *clock);
+void rcc_clock_setup_pll(const clock_scale_t *clock);
void rcc_backupdomain_reset(void);
/**@}*/
diff --git a/include/libopencm3/stm32/usart.h b/include/libopencm3/stm32/usart.h
index 088e67b..9994002 100644
--- a/include/libopencm3/stm32/usart.h
+++ b/include/libopencm3/stm32/usart.h
@@ -371,6 +371,8 @@ void usart_enable_rx_interrupt(u32 usart);
void usart_disable_rx_interrupt(u32 usart);
void usart_enable_tx_interrupt(u32 usart);
void usart_disable_tx_interrupt(u32 usart);
+void usart_enable_error_interrupt(u32 usart);
+void usart_disable_error_interrupt(u32 usart);
bool usart_get_flag(u32 usart, u32 flag);
bool usart_get_interrupt_source(u32 usart, u32 flag);
diff --git a/include/libopencm3/usb/usbd.h b/include/libopencm3/usb/usbd.h
index 98bf6eb..2e5b7fb 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;
typedef struct _usbd_device usbd_device;
@@ -40,9 +47,10 @@ extern u8 usbd_control_buffer[];
/* <usb.c> */
extern usbd_device *usbd_init(const usbd_driver *driver,
- const struct usb_device_descriptor *dev,
- const struct usb_config_descriptor *conf,
- const char **strings);
+ const struct usb_device_descriptor *dev,
+ const struct usb_config_descriptor *conf,
+ const char **strings, int num_strings);
+
extern void usbd_set_control_buffer_size(usbd_device *usbd_dev, u16 size);
extern void usbd_register_reset_callback(usbd_device *usbd_dev,
diff --git a/include/libopencm3/usb/usbstd.h b/include/libopencm3/usb/usbstd.h
index 5b1cea4..7908280 100644
--- a/include/libopencm3/usb/usbstd.h
+++ b/include/libopencm3/usb/usbstd.h
@@ -223,4 +223,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/cm3/vector.c b/lib/cm3/vector.c
index b049526..f7b0f5c 100644
--- a/lib/cm3/vector.c
+++ b/lib/cm3/vector.c
@@ -63,7 +63,7 @@ vector_table_t vector_table = {
}
};
-void WEAK reset_handler(void)
+void WEAK __attribute__ ((naked)) reset_handler(void)
{
volatile unsigned *src, *dest;
diff --git a/lib/stm32/can.c b/lib/stm32/can.c
index 9b2f22a..7fde585 100644
--- a/lib/stm32/can.c
+++ b/lib/stm32/can.c
@@ -85,7 +85,8 @@ Initialize the selected CAN peripheral block.
@returns int 0 on success, 1 on initialization failure.
*/
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)
{
u32 wait_ack = 0x00000000;
u32 can_msr_inak_timeout = 0x0000FFFF;
@@ -107,6 +108,9 @@ int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart,
if ((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK)
return 1;
+ /* clear can timing bits */
+ CAN_BTR(canport) = 0;
+
/* Set the automatic bus-off management. */
if (ttcm)
CAN_MCR(canport) |= CAN_MCR_TTCM;
@@ -138,8 +142,19 @@ int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart,
else
CAN_MCR(canport) &= ~CAN_MCR_TXFP;
+ if (silent)
+ CAN_BTR(canport) |= CAN_BTR_SILM;
+ else
+ CAN_BTR(canport) &= ~CAN_BTR_SILM;
+
+ if (loopback)
+ CAN_BTR(canport) |= CAN_BTR_LBKM;
+ else
+ CAN_BTR(canport) &= ~CAN_BTR_LBKM;
+
+
/* Set bit timings. */
- CAN_BTR(canport) = sjw | ts2 | ts1 |
+ CAN_BTR(canport) |= sjw | ts2 | ts1 |
(u32)(CAN_BTR_BRP_MASK & (brp - 1));
/* Request initialization "leave". */
@@ -456,3 +471,8 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
if (release)
can_fifo_release(canport, fifo);
}
+
+bool can_available_mailbox(u32 canport)
+{
+ return CAN_TSR(canport) & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2);
+}
diff --git a/lib/stm32/desig.c b/lib/stm32/desig.c
index 0743dc8..ea861aa 100644
--- a/lib/stm32/desig.c
+++ b/lib/stm32/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';
+}
+
diff --git a/lib/stm32/f1/dma.c b/lib/stm32/f1/dma.c
index fa7fb72..1f06c11 100644
--- a/lib/stm32/f1/dma.c
+++ b/lib/stm32/f1/dma.c
@@ -433,5 +433,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;
+}
/**@}*/
diff --git a/lib/stm32/f1/gpio.c b/lib/stm32/f1/gpio.c
index f0b7f70..2b33cad 100644
--- a/lib/stm32/f1/gpio.c
+++ b/lib/stm32/f1/gpio.c
@@ -164,7 +164,7 @@ value cannot be ascertained from the hardware.
*/
void gpio_primary_remap(u8 swjdisable, u32 maps)
{
- AFIO_MAPR = swjdisable | (maps & 0x1FFFFF);
+ AFIO_MAPR |= swjdisable | (maps & 0x1FFFFF);
}
/*-----------------------------------------------------------------------------*/
@@ -182,7 +182,7 @@ The AFIO remapping feature is used only with the STM32F10x series.
*/
void gpio_secondary_remap(u32 maps)
{
- AFIO_MAPR2 = maps;
+ AFIO_MAPR2 |= maps;
}
/**@}*/
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. */
@@ -485,6 +531,40 @@ void rcc_set_pll_multiplication_factor(u32 mul)
}
/*-----------------------------------------------------------------------------*/
+/** @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.
@note This only has effect when the PLL is disabled.
@@ -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.
@@ -1031,6 +1141,63 @@ void rcc_clock_setup_in_hse_16mhz_out_72mhz(void)
}
/*-----------------------------------------------------------------------------*/
+/** @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
The backup domain register is reset to disable all controls.
diff --git a/lib/stm32/f1/rtc.c b/lib/stm32/f1/rtc.c
index 08a4953..cfc5f5b 100644
--- a/lib/stm32/f1/rtc.c
+++ b/lib/stm32/f1/rtc.c
@@ -67,6 +67,8 @@ void rtc_awake_from_off(osc_t clock_source)
RCC_BDCR |= (1 << 9) | (1 << 8);
break;
case PLL:
+ case PLL2:
+ case PLL3:
case HSI:
/* Unusable clock source, here to prevent warnings. */
/* Turn off clock sources to RTC. */
diff --git a/lib/stm32/f4/adc.c b/lib/stm32/f4/adc.c
index 7475fac..aef49a4 100644
--- a/lib/stm32/f4/adc.c
+++ b/lib/stm32/f4/adc.c
@@ -435,17 +435,12 @@ void adc_set_right_aligned(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Enable DMA Transfers
-Only available for ADC1 through DMA1 channel1, and ADC3 through DMA2 channel5.
-ADC2 will use DMA if it is set as slave in dual mode with ADC1 in DMA transfer
-mode.
-
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_enable_dma(u32 adc)
{
- if ((adc == ADC1) | (adc == ADC3))
- ADC_CR2(adc) |= ADC_CR2_DMA;
+ ADC_CR2(adc) |= ADC_CR2_DMA;
}
/*-----------------------------------------------------------------------------*/
@@ -456,8 +451,7 @@ void adc_enable_dma(u32 adc)
void adc_disable_dma(u32 adc)
{
- if ((adc == ADC1) | (adc == ADC3))
- ADC_CR2(adc) &= ~ADC_CR2_DMA;
+ ADC_CR2(adc) &= ~ADC_CR2_DMA;
}
/*-----------------------------------------------------------------------------*/
diff --git a/lib/stm32/i2c.c b/lib/stm32/i2c.c
index e1d3a09..a67bece 100644
--- a/lib/stm32/i2c.c
+++ b/lib/stm32/i2c.c
@@ -125,6 +125,18 @@ void i2c_send_stop(u32 i2c)
}
/*-----------------------------------------------------------------------------*/
+/** @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.
This sets an address for Slave mode operation, in 7 bit form.
@@ -269,5 +281,135 @@ 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;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @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)
+ I2C_CCR(i2c) &= ~I2C_CCR_DUTY;
+ else
+ 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;
+}
+
+/**@}*/
diff --git a/lib/stm32/l1/Makefile b/lib/stm32/l1/Makefile
index 7f3e157..a3c8856 100644
--- a/lib/stm32/l1/Makefile
+++ b/lib/stm32/l1/Makefile
@@ -28,8 +28,10 @@ CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
-ffunction-sections -fdata-sections -MD -DSTM32L1
# ARFLAGS = rcsv
ARFLAGS = rcs
-OBJS = rcc.o gpio.o desig.o crc.o usart.o exti2.o \
- gpio_common_all.o gpio_common_f24.o
+OBJS = rcc.o gpio.o desig.o crc.o usart.o exti2.o
+OBJS += flash.o gpio_common_all.o gpio_common_f24.o
+OBJS += pwr_chipset.o # TODO, get pwr.o to fix f2/f4 first... pwr.o
+OBJS += timer.o
VPATH += ../../usb:../:../../cm3:../common
diff --git a/lib/stm32/l1/flash.c b/lib/stm32/l1/flash.c
new file mode 100644
index 0000000..06e8a59
--- /dev/null
+++ b/lib/stm32/l1/flash.c
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
+ * Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/l1/flash.h>
+
+void flash_64bit_enable(void)
+{
+ FLASH_ACR |= FLASH_ACC64;
+}
+
+void flash_64bit_disable(void)
+{
+ FLASH_ACR &= ~FLASH_ACC64;
+}
+
+void flash_prefetch_enable(void)
+{
+ FLASH_ACR |= FLASH_PRFTEN;
+}
+
+void flash_prefetch_disable(void)
+{
+ FLASH_ACR &= ~FLASH_PRFTEN;
+}
+
+void flash_set_ws(u32 ws)
+{
+ u32 reg32;
+
+ reg32 = FLASH_ACR;
+ reg32 &= ~(1 << 0);
+ reg32 |= ws;
+ FLASH_ACR = reg32;
+} \ No newline at end of file
diff --git a/lib/stm32/l1/pwr_chipset.c b/lib/stm32/l1/pwr_chipset.c
new file mode 100644
index 0000000..9f4f599
--- /dev/null
+++ b/lib/stm32/l1/pwr_chipset.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/l1/pwr.h>
+
+void pwr_set_vos_scale(vos_scale_t scale)
+{
+ PWR_CR &= ~(PWR_CR_VOS_MASK);
+ switch (scale) {
+ case RANGE1:
+ PWR_CR |= PWR_CR_VOS_RANGE1;
+ break;
+ case RANGE2:
+ PWR_CR |= PWR_CR_VOS_RANGE2;
+ break;
+ case RANGE3:
+ PWR_CR |= PWR_CR_VOS_RANGE3;
+ break;
+ }
+}
+
diff --git a/lib/stm32/l1/rcc.c b/lib/stm32/l1/rcc.c
index a023622..bbba9a9 100644
--- a/lib/stm32/l1/rcc.c
+++ b/lib/stm32/l1/rcc.c
@@ -22,11 +22,50 @@
*/
#include <libopencm3/stm32/l1/rcc.h>
+#include <libopencm3/stm32/l1/flash.h>
+#include <libopencm3/stm32/l1/pwr.h>
/* Set the default ppre1 and ppre2 peripheral clock frequencies after reset. */
u32 rcc_ppre1_frequency = 2097000;
u32 rcc_ppre2_frequency = 2097000;
+const clock_scale_t clock_vrange1_config[CLOCK_VRANGE1_END] =
+{
+ { /* 24MHz PLL from HSI */
+ .pll_source = RCC_CFGR_PLLSRC_HSI_CLK,
+ .pll_mul = RCC_CFGR_PLLMUL_MUL3,
+ .pll_div = RCC_CFGR_PLLDIV_DIV2,
+ .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
+ .voltage_scale = RANGE1,
+ .flash_config = FLASH_LATENCY_1WS,
+ .apb1_frequency = 24000000,
+ .apb2_frequency = 24000000,
+ },
+ { /* 32MHz PLL from HSI */
+ .pll_source = RCC_CFGR_PLLSRC_HSI_CLK,
+ .pll_mul = RCC_CFGR_PLLMUL_MUL6,
+ .pll_div = RCC_CFGR_PLLDIV_DIV3,
+ .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
+ .voltage_scale = RANGE1,
+ .flash_config = FLASH_LATENCY_1WS,
+ .apb1_frequency = 32000000,
+ .apb2_frequency = 32000000,
+ },
+ { /* 16MHz HSI raw */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
+ .voltage_scale = RANGE1,
+ .flash_config = FLASH_LATENCY_0WS,
+ .apb1_frequency = 16000000,
+ .apb2_frequency = 16000000,
+ },
+};
+
void rcc_osc_ready_int_clear(osc_t osc)
{
switch (osc) {
@@ -304,6 +343,20 @@ void rcc_set_sysclk_source(u32 clk)
RCC_CFGR = (reg32 | clk);
}
+void rcc_set_pll_configuration(u32 source, u32 multiplier, u32 divisor)
+{
+ u32 reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~(RCC_CFGR_PLLDIV_MASK << RCC_CFGR_PLLDIV_SHIFT);
+ reg32 &= ~(RCC_CFGR_PLLMUL_MASK << RCC_CFGR_PLLMUL_SHIFT);
+ reg32 &= ~(1 << 16);
+ reg32 |= (source << 16);
+ reg32 |= (multiplier << RCC_CFGR_PLLMUL_SHIFT);
+ reg32 |= (divisor << RCC_CFGR_PLLDIV_SHIFT);
+ RCC_CFGR = reg32;
+}
+
void rcc_set_pll_source(u32 pllsrc)
{
u32 reg32;
@@ -355,3 +408,71 @@ u32 rcc_system_clock_source(void)
return ((RCC_CFGR & 0x000c) >> 2);
}
+void rcc_clock_setup_hsi(const clock_scale_t *clock)
+{
+ /* Enable internal high-speed oscillator. */
+ rcc_osc_on(HSI);
+ rcc_wait_for_osc_ready(HSI);
+
+ /* Select HSI as SYSCLK source. */
+ rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
+
+ /*
+ * Set prescalers for AHB, ADC, ABP1, ABP2.
+ * Do this before touching the PLL (TODO: why?).
+ */
+ rcc_set_hpre(clock->hpre);
+ rcc_set_ppre1(clock->ppre1);
+ rcc_set_ppre2(clock->ppre2);
+
+ pwr_set_vos_scale(clock->voltage_scale);
+
+ // I guess this should be in the settings?
+ flash_64bit_enable();
+ flash_prefetch_enable();
+ /* Configure flash settings. */
+ flash_set_ws(clock->flash_config);
+
+ /* Set the peripheral clock frequencies used. */
+ rcc_ppre1_frequency = clock->apb1_frequency;
+ rcc_ppre2_frequency = clock->apb2_frequency;
+}
+
+void rcc_clock_setup_pll(const clock_scale_t *clock)
+{
+ /* Enable internal high-speed oscillator. */
+ rcc_osc_on(HSI);
+ rcc_wait_for_osc_ready(HSI);
+
+ /* Select HSI as SYSCLK source. */
+ rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
+
+ /*
+ * Set prescalers for AHB, ADC, ABP1, ABP2.
+ * Do this before touching the PLL (TODO: why?).
+ */
+ rcc_set_hpre(clock->hpre);
+ rcc_set_ppre1(clock->ppre1);
+ rcc_set_ppre2(clock->ppre2);
+
+ pwr_set_vos_scale(clock->voltage_scale);
+
+ // I guess this should be in the settings?
+ flash_64bit_enable();
+ flash_prefetch_enable();
+ /* Configure flash settings. */
+ flash_set_ws(clock->flash_config);
+
+ rcc_set_pll_configuration(clock->pll_source, clock->pll_mul, clock->pll_div);
+
+ /* Enable PLL oscillator 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 = clock->apb1_frequency;
+ rcc_ppre2_frequency = clock->apb2_frequency;
+}
diff --git a/lib/stm32/timer.c b/lib/stm32/timer.c
index a5cf99d..d3c26e8 100644
--- a/lib/stm32/timer.c
+++ b/lib/stm32/timer.c
@@ -99,13 +99,18 @@ push-pull outputs where the PWM output will appear.
#include <libopencm3/stm32/timer.h>
#if defined(STM32F1)
+#define ADVANCED_TIMERS (defined (TIM1_BASE) || defined(TIM8_BASE))
# include <libopencm3/stm32/f1/rcc.h>
#elif defined(STM32F2)
+#define ADVANCED_TIMERS (defined (TIM1_BASE) || defined(TIM8_BASE))
# include <libopencm3/stm32/f2/timer.h>
# include <libopencm3/stm32/f2/rcc.h>
#elif defined(STM32F4)
+#define ADVANCED_TIMERS (defined (TIM1_BASE) || defined(TIM8_BASE))
# include <libopencm3/stm32/f4/timer.h>
# include <libopencm3/stm32/f4/rcc.h>
+#elif defined(STM32L1)
+# include <libopencm3/stm32/l1/rcc.h>
#else
# error "stm32 family not defined."
#endif
@@ -124,10 +129,12 @@ system.
void timer_reset(u32 timer_peripheral)
{
switch (timer_peripheral) {
+#if defined(TIM1_BASE)
case TIM1:
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM1RST);
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM1RST);
break;
+#endif
case TIM2:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM2RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM2RST);
@@ -140,10 +147,12 @@ void timer_reset(u32 timer_peripheral)
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM4RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM4RST);
break;
+#if defined(TIM5_BASE)
case TIM5:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM5RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM5RST);
break;
+#endif
case TIM6:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM6RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM6RST);
@@ -152,10 +161,12 @@ void timer_reset(u32 timer_peripheral)
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM7RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM7RST);
break;
+#if defined(TIM8_BASE)
case TIM8:
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM8RST);
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM8RST);
break;
+#endif
/* These timers are not supported in libopencm3 yet */
/*
case TIM9:
@@ -230,8 +241,10 @@ bool timer_interrupt_source(u32 timer_peripheral, u32 flag)
if (((TIM_SR(timer_peripheral) & TIM_DIER(timer_peripheral) & flag) == 0) ||
(flag > TIM_SR_BIF)) return false;
/* Only an interrupt source for advanced timers */
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((flag == TIM_SR_BIF) || (flag == TIM_SR_COMIF))
return ((timer_peripheral == TIM1) || (timer_peripheral == TIM8));
+#endif
return true;
}
@@ -416,7 +429,7 @@ void timer_continuous_mode(u32 timer_peripheral)
/*---------------------------------------------------------------------------*/
/** @brief Set the Timer to Generate Update IRQ or DMA on any Event.
-The events which will generate an interrupt or DMA request can be
+The events which will generate an interrupt or DMA request can be
@li a counter underflow/overflow,
@li a forced update,
@li an event from the slave mode controller.
@@ -504,8 +517,10 @@ If several settings are to be made, use the logical OR of the output control val
void timer_set_output_idle_state(u32 timer_peripheral, u32 outputs)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_CR2(timer_peripheral) |= outputs & TIM_CR2_OIS_MASK;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -523,8 +538,10 @@ This determines the value of the timer output compare when it enters idle state.
void timer_reset_output_idle_state(u32 timer_peripheral, u32 outputs)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_CR2(timer_peripheral) &= ~(outputs & TIM_CR2_OIS_MASK);
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -611,8 +628,10 @@ outputs.
void timer_enable_compare_control_update_on_trigger(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_CR2(timer_peripheral) |= TIM_CR2_CCUS;
+ TIM_CR2(timer_peripheral) |= TIM_CR2_CCUS;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -630,8 +649,10 @@ outputs.
void timer_disable_compare_control_update_on_trigger(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCUS;
+ TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCUS;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -648,8 +669,10 @@ outputs.
void timer_enable_preload_complementry_enable_bits(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_CR2(timer_peripheral) |= TIM_CR2_CCPC;
+ TIM_CR2(timer_peripheral) |= TIM_CR2_CCPC;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -665,8 +688,10 @@ outputs.
void timer_disable_preload_complementry_enable_bits(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCPC;
+ TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCPC;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -697,8 +722,10 @@ count cycles have been completed.
void timer_set_repetition_counter(u32 timer_peripheral, u32 value)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_RCR(timer_peripheral) = value;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1019,7 +1046,7 @@ void timer_set_oc_mode(u32 timer_peripheral, enum tim_oc_id oc_id,
/** @brief Timer Enable the Output Compare Preload Register
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (no action taken)
*/
@@ -1050,7 +1077,7 @@ void timer_enable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id)
/** @brief Timer Disable the Output Compare Preload Register
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (no action)
*/
@@ -1083,7 +1110,7 @@ void timer_disable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id)
The polarity of the channel output is set active high.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
@@ -1110,8 +1137,12 @@ void timer_set_oc_polarity_high(u32 timer_peripheral, enum tim_oc_id oc_id)
}
/* Acting for TIM1 and TIM8 only from here onwards. */
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
+#else
+ return;
+#endif
switch (oc_id) {
case TIM_OC1N:
@@ -1138,7 +1169,7 @@ void timer_set_oc_polarity_high(u32 timer_peripheral, enum tim_oc_id oc_id)
The polarity of the channel output is set active low.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
@@ -1165,8 +1196,12 @@ void timer_set_oc_polarity_low(u32 timer_peripheral, enum tim_oc_id oc_id)
}
/* Acting for TIM1 and TIM8 only from here onwards. */
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
+#else
+ return;
+#endif
switch (oc_id) {
case TIM_OC1N:
@@ -1193,7 +1228,7 @@ void timer_set_oc_polarity_low(u32 timer_peripheral, enum tim_oc_id oc_id)
The channel output compare functionality is enabled.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
@@ -1220,8 +1255,12 @@ void timer_enable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
}
/* Acting for TIM1 and TIM8 only from here onwards. */
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
+#else
+ return;
+#endif
switch (oc_id) {
case TIM_OC1N:
@@ -1248,7 +1287,7 @@ void timer_enable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
The channel output compare functionality is disabled.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
@@ -1275,8 +1314,12 @@ void timer_disable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
}
/* Acting for TIM1 and TIM8 only from here onwards. */
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
+#else
+ return;
+#endif
switch (oc_id) {
case TIM_OC1N:
@@ -1306,12 +1349,13 @@ void timer_disable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
@note This setting is only valid for the advanced timers.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
void timer_set_oc_idle_state_set(u32 timer_peripheral, enum tim_oc_id oc_id)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
/* Acting for TIM1 and TIM8 only. */
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
@@ -1339,6 +1383,7 @@ void timer_set_oc_idle_state_set(u32 timer_peripheral, enum tim_oc_id oc_id)
TIM_CR2(timer_peripheral) |= TIM_CR2_OIS4;
break;
}
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1350,12 +1395,13 @@ void timer_set_oc_idle_state_set(u32 timer_peripheral, enum tim_oc_id oc_id)
@note This setting is only valid for the advanced timers.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
void timer_set_oc_idle_state_unset(u32 timer_peripheral, enum tim_oc_id oc_id)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
/* Acting for TIM1 and TIM8 only. */
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
@@ -1383,6 +1429,7 @@ void timer_set_oc_idle_state_unset(u32 timer_peripheral, enum tim_oc_id oc_id)
TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS4;
break;
}
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1393,7 +1440,7 @@ to the compare register.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
(TIM9 .. TIM14 not yet supported here).
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (no action taken)
@param[in] value Unsigned int32. Compare value.
*/
@@ -1438,8 +1485,10 @@ timer <b>even if break or deadtime features are not being used</b>.
void timer_enable_break_main_output(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_MOE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1455,8 +1504,10 @@ the Master Output Enable in the Break and Deadtime Register.
void timer_disable_break_main_output(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_MOE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1464,7 +1515,7 @@ void timer_disable_break_main_output(u32 timer_peripheral)
Enables the automatic output feature of the Break function of an advanced
timer so that the output is re-enabled at the next update event following a
-break event.
+break event.
@note This setting is only valid for the advanced timers.
@@ -1473,8 +1524,10 @@ break event.
void timer_enable_break_automatic_output(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_AOE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1482,7 +1535,7 @@ void timer_enable_break_automatic_output(u32 timer_peripheral)
Disables the automatic output feature of the Break function of an advanced
timer so that the output is re-enabled at the next update event following a
-break event.
+break event.
@note This setting is only valid for the advanced timers.
@@ -1491,8 +1544,10 @@ break event.
void timer_disable_break_automatic_output(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_AOE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1507,8 +1562,10 @@ Sets the break function to activate when the break input becomes high.
void timer_set_break_polarity_high(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_BKP;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1523,8 +1580,10 @@ Sets the break function to activate when the break input becomes low.
void timer_set_break_polarity_low(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_BKP;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1539,8 +1598,10 @@ Enables the break function of an advanced timer.
void timer_enable_break(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_BKE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1555,8 +1616,10 @@ Disables the break function of an advanced timer.
void timer_disable_break(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_BKE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1575,8 +1638,10 @@ inactive level as defined by the output polarity.
void timer_set_enabled_off_state_in_run_mode(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_OSSR;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1594,8 +1659,10 @@ disabled, the output is also disabled.
void timer_set_disabled_off_state_in_run_mode(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_OSSR;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1612,8 +1679,10 @@ inactive level as defined by the output polarity.
void timer_set_enabled_off_state_in_idle_mode(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_OSSI;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1629,8 +1698,10 @@ timer. When the master output is disabled the output is also disabled.
void timer_set_disabled_off_state_in_idle_mode(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_OSSI;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1648,8 +1719,10 @@ timer reset has occurred.
void timer_set_break_lock(u32 timer_peripheral, u32 lock)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= lock;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1672,8 +1745,10 @@ number of DTSC cycles:
void timer_set_deadtime(u32 timer_peripheral, u32 deadtime)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= deadtime;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1842,7 +1917,7 @@ void timer_ic_set_input(u32 timer_peripheral, enum tim_ic_id ic, enum tim_ic_inp
/* Input select bits are flipped for these combinations */
in ^= 3;
}
-
+
switch (ic) {
case TIM_IC1:
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_CC1S_MASK;
diff --git a/lib/stm32/usart.c b/lib/stm32/usart.c
index 1faf486..cb46db8 100644
--- a/lib/stm32/usart.c
+++ b/lib/stm32/usart.c
@@ -400,6 +400,27 @@ void usart_disable_tx_interrupt(u32 usart)
USART_CR1(usart) &= ~USART_CR1_TXEIE;
}
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Error Interrupt Enable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_enable_error_interrupt(u32 usart)
+{
+ USART_CR3(usart) |= USART_CR3_EIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Error Interrupt Disable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_disable_error_interrupt(u32 usart)
+{
+ USART_CR3(usart) &= ~USART_CR3_EIE;
+}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Status Flag.
diff --git a/lib/usb/usb.c b/lib/usb/usb.c
index ecebde2..0799202 100644
--- a/lib/usb/usb.c
+++ b/lib/usb/usb.c
@@ -44,7 +44,7 @@ u8 usbd_control_buffer[128] __attribute__((weak));
usbd_device *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)
{
usbd_device *usbd_dev;
@@ -54,6 +54,7 @@ usbd_device *usbd_init(const usbd_driver *driver,
usbd_dev->desc = dev;
usbd_dev->config = conf;
usbd_dev->strings = strings;
+ usbd_dev->num_strings = num_strings;
usbd_dev->ctrl_buf = usbd_control_buffer;
usbd_dev->ctrl_buf_len = sizeof(usbd_control_buffer);
diff --git a/lib/usb/usb_control.c b/lib/usb/usb_control.c
index 245ab1c..82843df 100644
--- a/lib/usb/usb_control.c
+++ b/lib/usb/usb_control.c
@@ -99,11 +99,12 @@ static int usb_control_request_dispatch(usbd_device *usbd_dev,
&(usbd_dev->control_state.ctrl_buf),
&(usbd_dev->control_state.ctrl_len),
&(usbd_dev->control_state.complete));
- if (result)
+ if (result == USBD_REQ_HANDLED ||
+ result == USBD_REQ_NOTSUPP)
return result;
}
}
-
+
/* Try standard request if not already handled. */
return _usbd_standard_request(usbd_dev, req,
&(usbd_dev->control_state.ctrl_buf),
diff --git a/lib/usb/usb_private.h b/lib/usb/usb_private.h
index 2506ba5..454e8c6 100644
--- a/lib/usb/usb_private.h
+++ b/lib/usb/usb_private.h
@@ -29,6 +29,7 @@ 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 5a92cd8..e14fee3 100644
--- a/lib/usb/usb_standard.c
+++ b/lib/usb/usb_standard.c
@@ -90,52 +90,75 @@ static u16 build_config_descriptor(usbd_device *usbd_dev,
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(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
- int i;
+ 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_dev->desc;
*len = MIN(*len, usbd_dev->desc->bLength);
- return 1;
+ return USBD_REQ_HANDLED;
case USB_DT_CONFIGURATION:
*buf = usbd_dev->ctrl_buf;
- *len = build_config_descriptor(usbd_dev, req->wValue & 0xff,
- *buf, *len);
- return 1;
+ *len = build_config_descriptor(usbd_dev, descr_idx, *buf, *len);
+ return USBD_REQ_HANDLED;
case USB_DT_STRING:
sd = (struct usb_string_descriptor *)usbd_dev->ctrl_buf;
- if (!usbd_dev->strings)
- return 0; /* Device doesn't support strings. */
+ 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]);
- /* Check that string index is in range. */
- for (i = 0; i <= (req->wValue & 0xff); i++)
- if (usbd_dev->strings[i] == NULL)
- return 0;
+ *len = MIN(*len, sd->bLength);
+ } else {
+ array_idx = descr_idx - 1;
- sd->bLength = strlen(usbd_dev->strings[req->wValue & 0xff])
- * 2 + 2;
- sd->bDescriptorType = USB_DT_STRING;
+ if (!usbd_dev->strings)
+ return USBD_REQ_NOTSUPP; /* Device doesn't support strings. */
+ /* Check that string index is in range. */
+ if (array_idx >= usbd_dev->num_strings)
+ return USBD_REQ_NOTSUPP;
- *buf = (u8 *)sd;
- *len = MIN(*len, sd->bLength);
+ /* Strings with Language ID differnet from
+ * USB_LANGID_ENGLISH_US are not supported */
+ if (req->wIndex != USB_LANGID_ENGLISH_US)
+ return USBD_REQ_NOTSUPP;
- for (i = 0; i < (*len / 2) - 1; i++)
- sd->wData[i] =
- usbd_dev->strings[req->wValue & 0xff][i];
+ /* Ths string is returned as UTF16, hence the multiplication */
+ sd->bLength = strlen(usbd_dev->strings[array_idx]) * 2 +
+ sizeof(sd->bLength) + sizeof(sd->bDescriptorType);
- /* Send sane Language ID descriptor... */
- if ((req->wValue & 0xff) == 0)
- sd->wData[0] = 0x409;
+ *len = MIN(*len, sd->bLength);
- return 1;
+ for (i = 0; i < (*len / 2) - 1; i++)
+ sd->wData[i] =
+ usbd_dev->strings[array_idx][i];
+ }
+
+ sd->bDescriptorType = USB_DT_STRING;
+ *buf = (u8 *)sd;
+
+ return USBD_REQ_HANDLED;
}
- return 0;
+ return USBD_REQ_NOTSUPP;
}
static int usb_standard_set_address(usbd_device *usbd_dev,