diff --git a/examples/stm32/f1/lisa-m-1/can/can.c b/examples/stm32/f1/lisa-m-1/can/can.c index a4cf30dc..463d7fcd 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 268274e8..44dde169 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 c5313949..65aca5ca 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 74cfb353..6ceb6658 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 6e5cc20f..6257394c 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 855e43bb..868ad9ce 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/i2c.h b/include/libopencm3/stm32/i2c.h index a59c4202..1b2dc0ee 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/usb/usbd.h b/include/libopencm3/usb/usbd.h index 98bf6ebb..2e5b7fbb 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[]; /* */ 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 5b1cea4d..79082806 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/stm32/can.c b/lib/stm32/can.c index 9b2f22af..7fde5852 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 0743dc87..ea861aaa 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 fa7fb720..1f06c114 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 f0b7f700..2b33cad9 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 ab3350b2..9cd86588 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 diff --git a/lib/stm32/f1/rtc.c b/lib/stm32/f1/rtc.c index 08a49536..cfc5f5b6 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/i2c.c b/lib/stm32/i2c.c index e1d3a095..a67beced 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,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/usb/usb.c b/lib/usb/usb.c index ecebde2d..0799202a 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 245ab1ce..82843dfb 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 2506ba53..454e8c6b 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 5a92cd85..e14fee35 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; + + 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; + + /* Strings with Language ID differnet from + * USB_LANGID_ENGLISH_US are not supported */ + if (req->wIndex != USB_LANGID_ENGLISH_US) + return USBD_REQ_NOTSUPP; + + /* Ths string is returned as UTF16, hence the multiplication */ + sd->bLength = strlen(usbd_dev->strings[array_idx]) * 2 + + sizeof(sd->bLength) + sizeof(sd->bDescriptorType); + + *len = MIN(*len, sd->bLength); + + for (i = 0; i < (*len / 2) - 1; i++) + sd->wData[i] = + usbd_dev->strings[array_idx][i]; + } - sd->bLength = strlen(usbd_dev->strings[req->wValue & 0xff]) - * 2 + 2; sd->bDescriptorType = USB_DT_STRING; - *buf = (u8 *)sd; - *len = MIN(*len, sd->bLength); - for (i = 0; i < (*len / 2) - 1; i++) - sd->wData[i] = - usbd_dev->strings[req->wValue & 0xff][i]; - - /* Send sane Language ID descriptor... */ - if ((req->wValue & 0xff) == 0) - sd->wData[0] = 0x409; - - return 1; + return USBD_REQ_HANDLED; } - return 0; + return USBD_REQ_NOTSUPP; } static int usb_standard_set_address(usbd_device *usbd_dev,