Browse Source

Merging pull request #63 Improvements to STM32F1 I2C, CAN, RCC, and USB (f107)

Merge remote-tracking branch 'icd/master'
pull/64/merge
Piotr Esden-Tempski 12 years ago
parent
commit
c904c3ae57
  1. 4
      examples/stm32/f1/lisa-m-1/can/can.c
  2. 2
      examples/stm32/f1/other/usb_dfu/usbdfu.c
  3. 8
      include/libopencm3/stm32/can.h
  4. 9
      include/libopencm3/stm32/desig.h
  5. 1
      include/libopencm3/stm32/f1/dma.h
  6. 25
      include/libopencm3/stm32/f1/rcc.h
  7. 20
      include/libopencm3/stm32/i2c.h
  8. 14
      include/libopencm3/usb/usbd.h
  9. 3
      include/libopencm3/usb/usbstd.h
  10. 24
      lib/stm32/can.c
  11. 22
      lib/stm32/desig.c
  12. 5
      lib/stm32/f1/dma.c
  13. 4
      lib/stm32/f1/gpio.c
  14. 167
      lib/stm32/f1/rcc.c
  15. 2
      lib/stm32/f1/rtc.c
  16. 144
      lib/stm32/i2c.c
  17. 3
      lib/usb/usb.c
  18. 5
      lib/usb/usb_control.c
  19. 1
      lib/usb/usb_private.h
  20. 73
      lib/usb/usb_standard.c

4
examples/stm32/f1/lisa-m-1/can/can.c

@ -135,7 +135,9 @@ void can_setup(void)
CAN_BTR_SJW_1TQ, CAN_BTR_SJW_1TQ,
CAN_BTR_TS1_3TQ, CAN_BTR_TS1_3TQ,
CAN_BTR_TS2_4TQ, 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(GPIOA, GPIO8); /* LED0 off */
gpio_set(GPIOB, GPIO4); /* LED1 off */ gpio_set(GPIOB, GPIO4); /* LED1 off */

2
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; AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON;
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); 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_dev = usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings);
usbd_set_control_buffer_size(usbd_dev, sizeof(usbd_control_buffer)); usbd_set_control_buffer_size(usbd_dev, sizeof(usbd_control_buffer));
usbd_register_control_callback( usbd_register_control_callback(

8
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_3TQ (0x2 << 24)
#define CAN_BTR_SJW_4TQ (0x3 << 24) #define CAN_BTR_SJW_4TQ (0x3 << 24)
#define CAN_BTR_SJW_MASK (0x3 << 24) #define CAN_BTR_SJW_MASK (0x3 << 24)
#define CAN_BTR_SJW_SHIFT 24
/* 23 Reserved, forced by hardware to 0 */ /* 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_7TQ (0x6 << 20)
#define CAN_BTR_TS2_8TQ (0x7 << 20) #define CAN_BTR_TS2_8TQ (0x7 << 20)
#define CAN_BTR_TS2_MASK (0x7 << 20) #define CAN_BTR_TS2_MASK (0x7 << 20)
#define CAN_BTR_TS2_SHIFT 20
/* TS1[3:0]: Time segment 1 */ /* TS1[3:0]: Time segment 1 */
#define CAN_BTR_TS1_1TQ (0x0 << 16) #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_15TQ (0xE << 16)
#define CAN_BTR_TS1_16TQ (0xF << 16) #define CAN_BTR_TS1_16TQ (0xF << 16)
#define CAN_BTR_TS1_MASK (0xF << 16) #define CAN_BTR_TS1_MASK (0xF << 16)
#define CAN_BTR_TS1_SHIFT 16
/* 15:10 Reserved, forced by hardware to 0 */ /* 15:10 Reserved, forced by hardware to 0 */
@ -641,7 +644,8 @@ BEGIN_DECLS
void can_reset(u32 canport); void can_reset(u32 canport);
int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart, 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, void can_filter_init(u32 canport, u32 nr, bool scale_32bit, bool id_list_mode,
u32 fr1, u32 fr2, u32 fifo, bool enable); 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); bool *rtr, u32 *fmi, u8 *length, u8 *data);
void can_fifo_release(u32 canport, u8 fifo); void can_fifo_release(u32 canport, u8 fifo);
bool can_available_mailbox(u32 canport);
END_DECLS END_DECLS
#endif #endif

9
include/libopencm3/stm32/desig.h

@ -51,6 +51,15 @@ u16 desig_get_flash_size(void);
*/ */
void desig_get_unique_id(u32 result[]); 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 END_DECLS
#endif #endif

1
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_peripheral_address(u32 dma, u8 channel, u32 address);
void dma_set_memory_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_set_number_of_data(u32 dma, u8 channel, u16 number);
void dma_clear_flag(u32 dma, u32 flag);
END_DECLS END_DECLS

25
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_SYSCLK 0x4
#define RCC_CFGR_MCO_HSICLK 0x5 #define RCC_CFGR_MCO_HSICLK 0x5
#define RCC_CFGR_MCO_HSECLK 0x6 #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_PLL2CLK 0x8 /* (**) */
#define RCC_CFGR_MCO_PLL3CLK_DIV2 0x9 /* (**) */ #define RCC_CFGR_MCO_PLL3CLK_DIV2 0x9 /* (**) */
#define RCC_CFGR_MCO_XT1 0xa /* (**) */ #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_MUL16 0xe
#define RCC_CFGR2_PLL2MUL_PLL2_CLK_MUL20 0xf #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 */ /* PREDIV2: PREDIV2 division factor */
#define RCC_CFGR2_PREDIV2_NODIV 0x0 #define RCC_CFGR2_PREDIV2_NODIV 0x0
#define RCC_CFGR2_PREDIV2_DIV2 0x1 #define RCC_CFGR2_PREDIV2_DIV2 0x1
@ -473,7 +491,7 @@ extern u32 rcc_ppre2_frequency;
/* --- Function prototypes ------------------------------------------------- */ /* --- Function prototypes ------------------------------------------------- */
typedef enum { typedef enum {
PLL, HSE, HSI, LSE, LSI PLL, PLL2, PLL3, HSE, HSI, LSE, LSI
} osc_t; } osc_t;
BEGIN_DECLS BEGIN_DECLS
@ -489,6 +507,7 @@ void rcc_osc_on(osc_t osc);
void rcc_osc_off(osc_t osc); void rcc_osc_off(osc_t osc);
void rcc_css_enable(void); void rcc_css_enable(void);
void rcc_css_disable(void); void rcc_css_disable(void);
void rcc_set_mco(u32 mcosrc);
void rcc_osc_bypass_enable(osc_t osc); void rcc_osc_bypass_enable(osc_t osc);
void rcc_osc_bypass_disable(osc_t osc); void rcc_osc_bypass_disable(osc_t osc);
void rcc_peripheral_enable_clock(volatile u32 *reg, u32 en); 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_peripheral_clear_reset(volatile u32 *reg, u32 clear_reset);
void rcc_set_sysclk_source(u32 clk); void rcc_set_sysclk_source(u32 clk);
void rcc_set_pll_multiplication_factor(u32 mul); 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_pll_source(u32 pllsrc);
void rcc_set_pllxtpre(u32 pllxtpre); void rcc_set_pllxtpre(u32 pllxtpre);
void rcc_set_adcpre(u32 adcpre); 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_8mhz_out_72mhz(void);
void rcc_clock_setup_in_hse_12mhz_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_16mhz_out_72mhz(void);
void rcc_clock_setup_in_hse_25mhz_out_72mhz(void);
void rcc_backupdomain_reset(void); void rcc_backupdomain_reset(void);
END_DECLS END_DECLS

20
include/libopencm3/stm32/i2c.h

@ -321,7 +321,14 @@ LGPL License Terms @ref lgpl_license
#define I2C_CCR_FS (1 << 15) #define I2C_CCR_FS (1 << 15)
/* DUTY: Fast Mode Duty Cycle */ /* 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 (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. */ /* 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_peripheral_disable(u32 i2c);
void i2c_send_start(u32 i2c); void i2c_send_start(u32 i2c);
void i2c_send_stop(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_7bit_slave_address(u32 i2c, u8 slave);
void i2c_set_own_10bit_slave_address(u32 i2c, u16 slave); void i2c_set_own_10bit_slave_address(u32 i2c, u16 slave);
void i2c_set_fast_mode(u32 i2c); 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_set_trise(u32 i2c, u16 trise);
void i2c_send_7bit_address(u32 i2c, u8 slave, u8 readwrite); void i2c_send_7bit_address(u32 i2c, u8 slave, u8 readwrite);
void i2c_send_data(u32 i2c, u8 data); 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 END_DECLS

14
include/libopencm3/usb/usbd.h

@ -24,6 +24,13 @@
BEGIN_DECLS 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_driver usbd_driver;
typedef struct _usbd_device usbd_device; typedef struct _usbd_device usbd_device;
@ -40,9 +47,10 @@ extern u8 usbd_control_buffer[];
/* <usb.c> */ /* <usb.c> */
extern usbd_device *usbd_init(const usbd_driver *driver, extern usbd_device *usbd_init(const usbd_driver *driver,
const struct usb_device_descriptor *dev, const struct usb_device_descriptor *dev,
const struct usb_config_descriptor *conf, const struct usb_config_descriptor *conf,
const char **strings); const char **strings, int num_strings);
extern void usbd_set_control_buffer_size(usbd_device *usbd_dev, u16 size); extern void usbd_set_control_buffer_size(usbd_device *usbd_dev, u16 size);
extern void usbd_register_reset_callback(usbd_device *usbd_dev, extern void usbd_register_reset_callback(usbd_device *usbd_dev,

3
include/libopencm3/usb/usbstd.h

@ -223,4 +223,7 @@ struct usb_iface_assoc_descriptor {
#define USB_DT_INTERFACE_ASSOCIATION_SIZE \ #define USB_DT_INTERFACE_ASSOCIATION_SIZE \
sizeof(struct usb_iface_assoc_descriptor) sizeof(struct usb_iface_assoc_descriptor)
enum usb_language_id {
USB_LANGID_ENGLISH_US = 0x409,
};
#endif #endif

24
lib/stm32/can.c

@ -85,7 +85,8 @@ Initialize the selected CAN peripheral block.
@returns int 0 on success, 1 on initialization failure. @returns int 0 on success, 1 on initialization failure.
*/ */
int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart, 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 wait_ack = 0x00000000;
u32 can_msr_inak_timeout = 0x0000FFFF; 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) if ((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK)
return 1; return 1;
/* clear can timing bits */
CAN_BTR(canport) = 0;
/* Set the automatic bus-off management. */ /* Set the automatic bus-off management. */
if (ttcm) if (ttcm)
CAN_MCR(canport) |= CAN_MCR_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 else
CAN_MCR(canport) &= ~CAN_MCR_TXFP; 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. */ /* Set bit timings. */
CAN_BTR(canport) = sjw | ts2 | ts1 | CAN_BTR(canport) |= sjw | ts2 | ts1 |
(u32)(CAN_BTR_BRP_MASK & (brp - 1)); (u32)(CAN_BTR_BRP_MASK & (brp - 1));
/* Request initialization "leave". */ /* Request initialization "leave". */
@ -456,3 +471,8 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
if (release) if (release)
can_fifo_release(canport, fifo); can_fifo_release(canport, fifo);
} }
bool can_available_mailbox(u32 canport)
{
return CAN_TSR(canport) & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2);
}

22
lib/stm32/desig.c

@ -35,3 +35,25 @@ void desig_get_unique_id(u32 result[])
result[1] = bits63_32; result[1] = bits63_32;
result[2] = bits31_16 << 16 | bits15_0; 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';
}

5
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; DMA_CNDTR(dma, channel) = number;
} }
void dma_clear_flag(u32 dma, u32 flag)
{
DMA_ISR(dma) &= ~flag;
}
/**@}*/ /**@}*/

4
lib/stm32/f1/gpio.c

@ -164,7 +164,7 @@ value cannot be ascertained from the hardware.
*/ */
void gpio_primary_remap(u8 swjdisable, u32 maps) 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) void gpio_secondary_remap(u32 maps)
{ {
AFIO_MAPR2 = maps; AFIO_MAPR2 |= maps;
} }
/**@}*/ /**@}*/

167
lib/stm32/f1/rcc.c

@ -71,6 +71,12 @@ void rcc_osc_ready_int_clear(osc_t osc)
case PLL: case PLL:
RCC_CIR |= RCC_CIR_PLLRDYC; RCC_CIR |= RCC_CIR_PLLRDYC;
break; break;
case PLL2:
RCC_CIR |= RCC_CIR_PLL2RDYC;
break;
case PLL3:
RCC_CIR |= RCC_CIR_PLL3RDYC;
break;
case HSE: case HSE:
RCC_CIR |= RCC_CIR_HSERDYC; RCC_CIR |= RCC_CIR_HSERDYC;
break; break;
@ -98,6 +104,12 @@ void rcc_osc_ready_int_enable(osc_t osc)
case PLL: case PLL:
RCC_CIR |= RCC_CIR_PLLRDYIE; RCC_CIR |= RCC_CIR_PLLRDYIE;
break; break;
case PLL2:
RCC_CIR |= RCC_CIR_PLL2RDYIE;
break;
case PLL3:
RCC_CIR |= RCC_CIR_PLL3RDYIE;
break;
case HSE: case HSE:
RCC_CIR |= RCC_CIR_HSERDYIE; RCC_CIR |= RCC_CIR_HSERDYIE;
break; break;
@ -125,6 +137,12 @@ void rcc_osc_ready_int_disable(osc_t osc)
case PLL: case PLL:
RCC_CIR &= ~RCC_CIR_PLLRDYIE; RCC_CIR &= ~RCC_CIR_PLLRDYIE;
break; break;
case PLL2:
RCC_CIR &= ~RCC_CIR_PLL2RDYIE;
break;
case PLL3:
RCC_CIR &= ~RCC_CIR_PLL3RDYIE;
break;
case HSE: case HSE:
RCC_CIR &= ~RCC_CIR_HSERDYIE; RCC_CIR &= ~RCC_CIR_HSERDYIE;
break; break;
@ -153,6 +171,12 @@ int rcc_osc_ready_int_flag(osc_t osc)
case PLL: case PLL:
return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0); return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0);
break; break;
case PLL2:
return ((RCC_CIR & RCC_CIR_PLL2RDYF) != 0);
break;
case PLL3:
return ((RCC_CIR & RCC_CIR_PLL3RDYF) != 0);
break;
case HSE: case HSE:
return ((RCC_CIR & RCC_CIR_HSERDYF) != 0); return ((RCC_CIR & RCC_CIR_HSERDYF) != 0);
break; break;
@ -203,6 +227,12 @@ void rcc_wait_for_osc_ready(osc_t osc)
case PLL: case PLL:
while ((RCC_CR & RCC_CR_PLLRDY) == 0); while ((RCC_CR & RCC_CR_PLLRDY) == 0);
break; break;
case PLL2:
while ((RCC_CR & RCC_CR_PLL2RDY) == 0);
break;
case PLL3:
while ((RCC_CR & RCC_CR_PLL3RDY) == 0);
break;
case HSE: case HSE:
while ((RCC_CR & RCC_CR_HSERDY) == 0); while ((RCC_CR & RCC_CR_HSERDY) == 0);
break; break;
@ -238,6 +268,12 @@ void rcc_osc_on(osc_t osc)
case PLL: case PLL:
RCC_CR |= RCC_CR_PLLON; RCC_CR |= RCC_CR_PLLON;
break; break;
case PLL2:
RCC_CR |= RCC_CR_PLL2ON;
break;
case PLL3:
RCC_CR |= RCC_CR_PLL3ON;
break;
case HSE: case HSE:
RCC_CR |= RCC_CR_HSEON; RCC_CR |= RCC_CR_HSEON;
break; break;
@ -273,6 +309,12 @@ void rcc_osc_off(osc_t osc)
case PLL: case PLL:
RCC_CR &= ~RCC_CR_PLLON; RCC_CR &= ~RCC_CR_PLLON;
break; break;
case PLL2:
RCC_CR &= ~RCC_CR_PLL2ON;
break;
case PLL3:
RCC_CR &= ~RCC_CR_PLL3ON;
break;
case HSE: case HSE:
RCC_CR &= ~RCC_CR_HSEON; RCC_CR &= ~RCC_CR_HSEON;
break; break;
@ -331,6 +373,8 @@ void rcc_osc_bypass_enable(osc_t osc)
RCC_BDCR |= RCC_BDCR_LSEBYP; RCC_BDCR |= RCC_BDCR_LSEBYP;
break; break;
case PLL: case PLL:
case PLL2:
case PLL3:
case HSI: case HSI:
case LSI: case LSI:
/* Do nothing, only HSE/LSE allowed here. */ /* Do nothing, only HSE/LSE allowed here. */
@ -361,6 +405,8 @@ void rcc_osc_bypass_disable(osc_t osc)
RCC_BDCR &= ~RCC_BDCR_LSEBYP; RCC_BDCR &= ~RCC_BDCR_LSEBYP;
break; break;
case PLL: case PLL:
case PLL2:
case PLL3:
case HSI: case HSI:
case LSI: case LSI:
/* Do nothing, only HSE/LSE allowed here. */ /* Do nothing, only HSE/LSE allowed here. */
@ -484,6 +530,40 @@ void rcc_set_pll_multiplication_factor(u32 mul)
RCC_CFGR = (reg32 | (mul << 18)); 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. /** @brief RCC Set the PLL Clock Source.
@ -602,6 +682,36 @@ void rcc_set_usbpre(u32 usbpre)
RCC_CFGR = (reg32 | (usbpre << 22)); 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. /** @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; 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 /** @brief RCC Reset the backup domain

2
lib/stm32/f1/rtc.c

@ -67,6 +67,8 @@ void rtc_awake_from_off(osc_t clock_source)
RCC_BDCR |= (1 << 9) | (1 << 8); RCC_BDCR |= (1 << 9) | (1 << 8);
break; break;
case PLL: case PLL:
case PLL2:
case PLL3:
case HSI: case HSI:
/* Unusable clock source, here to prevent warnings. */ /* Unusable clock source, here to prevent warnings. */
/* Turn off clock sources to RTC. */ /* Turn off clock sources to RTC. */

144
lib/stm32/i2c.c

@ -124,6 +124,18 @@ void i2c_send_stop(u32 i2c)
I2C_CR1(i2c) |= I2C_CR1_STOP; 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. /** @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; 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;
}
/**@}*/

3
lib/usb/usb.c

@ -44,7 +44,7 @@ u8 usbd_control_buffer[128] __attribute__((weak));
usbd_device *usbd_init(const usbd_driver *driver, usbd_device *usbd_init(const usbd_driver *driver,
const struct usb_device_descriptor *dev, const struct usb_device_descriptor *dev,
const struct usb_config_descriptor *conf, const struct usb_config_descriptor *conf,
const char **strings) const char **strings, int num_strings)
{ {
usbd_device *usbd_dev; usbd_device *usbd_dev;
@ -54,6 +54,7 @@ usbd_device *usbd_init(const usbd_driver *driver,
usbd_dev->desc = dev; usbd_dev->desc = dev;
usbd_dev->config = conf; usbd_dev->config = conf;
usbd_dev->strings = strings; usbd_dev->strings = strings;
usbd_dev->num_strings = num_strings;
usbd_dev->ctrl_buf = usbd_control_buffer; usbd_dev->ctrl_buf = usbd_control_buffer;
usbd_dev->ctrl_buf_len = sizeof(usbd_control_buffer); usbd_dev->ctrl_buf_len = sizeof(usbd_control_buffer);

5
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_buf),
&(usbd_dev->control_state.ctrl_len), &(usbd_dev->control_state.ctrl_len),
&(usbd_dev->control_state.complete)); &(usbd_dev->control_state.complete));
if (result) if (result == USBD_REQ_HANDLED ||
result == USBD_REQ_NOTSUPP)
return result; return result;
} }
} }
/* Try standard request if not already handled. */ /* Try standard request if not already handled. */
return _usbd_standard_request(usbd_dev, req, return _usbd_standard_request(usbd_dev, req,
&(usbd_dev->control_state.ctrl_buf), &(usbd_dev->control_state.ctrl_buf),

1
lib/usb/usb_private.h

@ -29,6 +29,7 @@ struct _usbd_device {
const struct usb_device_descriptor *desc; const struct usb_device_descriptor *desc;
const struct usb_config_descriptor *config; const struct usb_config_descriptor *config;
const char **strings; const char **strings;
int num_strings;
u8 *ctrl_buf; /**< Internal buffer used for control transfers */ u8 *ctrl_buf; /**< Internal buffer used for control transfers */
u16 ctrl_buf_len; u16 ctrl_buf_len;

73
lib/usb/usb_standard.c

@ -90,52 +90,75 @@ static u16 build_config_descriptor(usbd_device *usbd_dev,
return total; 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, static int usb_standard_get_descriptor(usbd_device *usbd_dev,
struct usb_setup_data *req, struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
int i; int i, array_idx, descr_idx;
struct usb_string_descriptor *sd; 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: case USB_DT_DEVICE:
*buf = (u8 *) usbd_dev->desc; *buf = (u8 *) usbd_dev->desc;
*len = MIN(*len, usbd_dev->desc->bLength); *len = MIN(*len, usbd_dev->desc->bLength);
return 1; return USBD_REQ_HANDLED;
case USB_DT_CONFIGURATION: case USB_DT_CONFIGURATION:
*buf = usbd_dev->ctrl_buf; *buf = usbd_dev->ctrl_buf;
*len = build_config_descriptor(usbd_dev, req->wValue & 0xff, *len = build_config_descriptor(usbd_dev, descr_idx, *buf, *len);
*buf, *len); return USBD_REQ_HANDLED;
return 1;
case USB_DT_STRING: case USB_DT_STRING:
sd = (struct usb_string_descriptor *)usbd_dev->ctrl_buf; sd = (struct usb_string_descriptor *)usbd_dev->ctrl_buf;
if (!usbd_dev->strings) if (descr_idx == 0) {
return 0; /* Device doesn't support strings. */ /* 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. */ *len = MIN(*len, sd->bLength);
for (i = 0; i <= (req->wValue & 0xff); i++) } else {
if (usbd_dev->strings[i] == NULL) array_idx = descr_idx - 1;
return 0;
sd->bLength = strlen(usbd_dev->strings[req->wValue & 0xff]) if (!usbd_dev->strings)
* 2 + 2; return USBD_REQ_NOTSUPP; /* Device doesn't support strings. */
sd->bDescriptorType = USB_DT_STRING; /* Check that string index is in range. */
if (array_idx >= usbd_dev->num_strings)
return USBD_REQ_NOTSUPP;
*buf = (u8 *)sd; /* Strings with Language ID differnet from
*len = MIN(*len, sd->bLength); * 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++) /* Ths string is returned as UTF16, hence the multiplication */
sd->wData[i] = sd->bLength = strlen(usbd_dev->strings[array_idx]) * 2 +
usbd_dev->strings[req->wValue & 0xff][i]; sizeof(sd->bLength) + sizeof(sd->bDescriptorType);
/* Send sane Language ID descriptor... */ *len = MIN(*len, sd->bLength);
if ((req->wValue & 0xff) == 0)
sd->wData[0] = 0x409;
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, static int usb_standard_set_address(usbd_device *usbd_dev,

Loading…
Cancel
Save