From c918737ed3af1491d0ffb883b12a8b70e565d940 Mon Sep 17 00:00:00 2001 From: Christian Mauderer Date: Thu, 24 Oct 2013 16:26:59 +0200 Subject: bsp/stm32f4: Add a simple I2C-driver. --- c/src/lib/libbsp/arm/stm32f4/Makefile.am | 6 + c/src/lib/libbsp/arm/stm32f4/configure.ac | 7 + c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c | 37 +++ c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c | 331 +++++++++++++++++++++ c/src/lib/libbsp/arm/stm32f4/include/i2c.h | 79 +++++ c/src/lib/libbsp/arm/stm32f4/include/io.h | 20 ++ c/src/lib/libbsp/arm/stm32f4/include/stm32_i2c.h | 98 ++++++ c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h | 9 + c/src/lib/libbsp/arm/stm32f4/preinstall.am | 8 + .../libbsp/arm/stm32f4/startup/start-config-io.c | 17 ++ 10 files changed, 612 insertions(+) create mode 100644 c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c create mode 100644 c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c create mode 100644 c/src/lib/libbsp/arm/stm32f4/include/i2c.h create mode 100644 c/src/lib/libbsp/arm/stm32f4/include/stm32_i2c.h diff --git a/c/src/lib/libbsp/arm/stm32f4/Makefile.am b/c/src/lib/libbsp/arm/stm32f4/Makefile.am index e4512345cb..8bdaa5e3f8 100644 --- a/c/src/lib/libbsp/arm/stm32f4/Makefile.am +++ b/c/src/lib/libbsp/arm/stm32f4/Makefile.am @@ -52,6 +52,8 @@ include_bsp_HEADERS += include/stm32f10xxx_rcc.h include_bsp_HEADERS += include/stm32f10xxx_exti.h include_bsp_HEADERS += include/stm32f4xxxx_gpio.h include_bsp_HEADERS += include/stm32f4xxxx_rcc.h +include_bsp_HEADERS += include/stm32_i2c.h +include_bsp_HEADERS += include/i2c.h include_bsp_HEADERS += include/stm32_usart.h include_bsp_HEADERS += include/io.h include_bsp_HEADERS += include/rcc.h @@ -106,6 +108,10 @@ libbsp_a_SOURCES += ../../shared/console_write.c libbsp_a_SOURCES += console/console-config.c libbsp_a_SOURCES += console/usart.c +# I2C +libbsp_a_SOURCES += i2c/i2c.c +libbsp_a_SOURCES += i2c/i2c-config.c + # Clock libbsp_a_SOURCES += ../../shared/clockdrv_shell.h libbsp_a_SOURCES += ../shared/armv7m/clock/armv7m-clock-config.c diff --git a/c/src/lib/libbsp/arm/stm32f4/configure.ac b/c/src/lib/libbsp/arm/stm32f4/configure.ac index db3175c380..0d9b861c34 100644 --- a/c/src/lib/libbsp/arm/stm32f4/configure.ac +++ b/c/src/lib/libbsp/arm/stm32f4/configure.ac @@ -63,6 +63,13 @@ RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_UART_5],[enable UART 5]) RTEMS_BSPOPTS_SET([STM32F4_ENABLE_USART_6],[*],[]) RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_USART_6],[enable USART 6]) +RTEMS_BSPOPTS_SET([STM32F4_ENABLE_I2C1],[stm32f1*],[1]) +RTEMS_BSPOPTS_SET([STM32F4_ENABLE_I2C1],[*],[]) +RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_I2C1],[enable I2C 1]) + +RTEMS_BSPOPTS_SET([STM32F4_ENABLE_I2C2],[*],[]) +RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_I2C2],[enable I2C 2]) + RTEMS_BSP_CLEANUP_OPTIONS(0, 0) RTEMS_BSP_LINKCMDS diff --git a/c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c b/c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c new file mode 100644 index 0000000000..5853e14076 --- /dev/null +++ b/c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Christian Mauderer. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include +#include +#include + +#ifdef STM32F4_ENABLE_I2C1 + static stm32f4_i2c_bus_entry stm32f4_i2c1_entry = { + .regs = STM32F4_I2C1, + .index = 0, + .vector = STM32F4_IRQ_I2C1_EV, + }; + + stm32f4_i2c_bus_entry *const stm32f4_i2c1 = &stm32f4_i2c1_entry; +#endif + +#ifdef STM32F4_ENABLE_I2C2 + static stm32f4_i2c_bus_entry stm32f4_i2c2_entry = { + .regs = STM32F4_I2C2, + .index = 1, + .vector = STM32F4_IRQ_I2C2_EV, + }; + + stm32f4_i2c_bus_entry *const stm32f4_i2c2 = &stm32f4_i2c2_entry; +#endif diff --git a/c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c b/c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c new file mode 100644 index 0000000000..631956cd59 --- /dev/null +++ b/c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2013 Christian Mauderer. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +/* The I2C-module can not run with libi2c. The reason for this is, that libi2c + * needs a possibility to generate a stop condition separately. This controller + * wants to generate the condition automatically when sending or receiving data. + */ + +#include +#include +#include +#include +#include +#include + +#define RTEMS_STATUS_CHECKS_USE_PRINTK + +#include + +#define STM32F4_I2C_INITIAL_BITRATE 100000 + +#define I2C_RW_BIT 0x1 + +stm32f4_rcc_index i2c_rcc_index [] = { + STM32F4_RCC_I2C1, + STM32F4_RCC_I2C2, +}; + +static stm32f4_rcc_index i2c_get_rcc_index(stm32f4_i2c_bus_entry *e) +{ + return i2c_rcc_index [e->index]; +} + +static uint32_t i2c_get_pclk(stm32f4_i2c_bus_entry *e) +{ + return STM32F4_PCLK1; +} + +rtems_status_code stm32f4_i2c_set_bitrate( + stm32f4_i2c_bus_entry *e, + uint32_t br +) +{ + volatile stm32f4_i2c *regs = e->regs; + uint32_t ccr; + uint32_t trise; + uint32_t pclk = i2c_get_pclk(e); + + /* Make sure, that the module is disabled */ + if((regs->cr1 & STM32F4_I2C_CR1_PE) != 0) + { + return RTEMS_RESOURCE_IN_USE; + } + + /* Configure clock control register and rise time register */ + ccr = regs->ccr; + trise = regs->trise; + + if(br <= 100000) + { + uint32_t ccr_val = pclk / (2 * br); + /* according to datasheet, the rise time for standard mode is 1us -> 1MHz */ + uint32_t trise_val = pclk / 1000000 + 1; + trise = STM32F4_I2C_TRISE_SET(trise, trise_val); + + if(ccr_val > STM32F4_I2C_CCR_CCR_MAX) + { + return RTEMS_INVALID_NUMBER; + } + + /* standard mode */ + ccr &= ~STM32F4_I2C_CCR_FS; + ccr = STM32F4_I2C_CCR_CCR_SET(ccr, ccr_val); + } + else + { + /* FIXME: Implement speeds 100kHz < f <= 400kHz (fast mode) */ + return RTEMS_NOT_IMPLEMENTED; + } + + regs->ccr = ccr; + regs->trise = trise; + + return RTEMS_SUCCESSFUL; +} + +static void stm32f4_i2c_handler(void *arg) +{ + /* This handler implements the suggested read method from stm32f103xx + * reference manual if the handler is not the one with the highest priority */ + stm32f4_i2c_bus_entry *e = arg; + volatile stm32f4_i2c *regs = e->regs; + uint32_t sr1 = regs->sr1; + uint8_t *data = e->data; + uint8_t *last = e->last; + bool read = e->read; + bool wake_task = false; + uint32_t cr1; + + if(sr1 & STM32F4_I2C_SR1_SB) { + /* Start condition sent. */ + regs->dr = e->addr_with_rw; + } + + if(read) { + size_t len = e->len; + + if(len == 1) { + /* special case for one single byte */ + if(sr1 & STM32F4_I2C_SR1_ADDR) { + cr1 = regs->cr1; + cr1 &= ~STM32F4_I2C_CR1_ACK; + regs->cr1 = cr1; + + /* Read sr2 to clear flag */ + regs->sr2; + + cr1 = regs->cr1; + cr1 |= STM32F4_I2C_CR1_STOP; + regs->cr1 = cr1; + } else if(sr1 & STM32F4_I2C_SR1_RxNE) { + *data = regs->dr; + wake_task = true; + } + } else if (len == 2) { + /* special case for two bytes */ + if(sr1 & STM32F4_I2C_SR1_ADDR) { + /* Read sr2 to clear flag */ + regs->sr2; + + cr1 = regs->cr1; + cr1 &= ~STM32F4_I2C_CR1_ACK; + regs->cr1 = cr1; + } else if(sr1 & STM32F4_I2C_SR1_BTF) { + cr1 = regs->cr1; + cr1 |= STM32F4_I2C_CR1_STOP; + regs->cr1 = cr1; + + *data = regs->dr; + ++data; + *data = regs->dr; + wake_task = true; + } + } else { + /* more than two bytes */ + if(sr1 & STM32F4_I2C_SR1_ADDR) { + /* Read sr2 to clear flag */ + regs->sr2; + } else if(sr1 & STM32F4_I2C_SR1_BTF && data == last - 2) { + cr1 = regs->cr1; + cr1 &= ~STM32F4_I2C_CR1_ACK; + regs->cr1 = cr1; + + *data = regs->dr; + ++data; + + cr1 = regs->cr1; + cr1 |= STM32F4_I2C_CR1_STOP; + regs->cr1 = cr1; + + *data = regs->dr; + ++data; + } else if((sr1 & STM32F4_I2C_SR1_RxNE) && (data != last - 2)) { + *data = regs->dr; + + if(data == last) { + wake_task = true; + } else { + ++data; + } + } + } + } else /* write */ { + if(sr1 & STM32F4_I2C_SR1_ADDR) { + /* Address sent */ + regs->sr2; + } + + if((sr1 & (STM32F4_I2C_SR1_ADDR | STM32F4_I2C_SR1_TxE)) && (data <= last)) { + regs->dr = *data; + ++data; + } else if(sr1 & STM32F4_I2C_SR1_BTF) { + uint32_t cr1 = regs->cr1; + cr1 |= STM32F4_I2C_CR1_STOP; + regs->cr1 = cr1; + wake_task = true; + } + } + + e->data = data; + + if(wake_task) { + bsp_interrupt_vector_disable(e->vector); + rtems_event_transient_send(e->task_id); + } +} + +static rtems_status_code i2c_wait_done(stm32f4_i2c_bus_entry *e) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + bsp_interrupt_vector_enable(e->vector); + e->task_id = rtems_task_self(); + return rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); +} + +rtems_status_code stm32f4_i2c_init(stm32f4_i2c_bus_entry *e) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + volatile stm32f4_i2c *regs = e->regs; + stm32f4_rcc_index rcc_index = i2c_get_rcc_index(e); + uint32_t pclk = i2c_get_pclk(e); + uint32_t cr1 = 0; + uint32_t cr2 = 0; + + assert(pclk >= 2000000); + + /* Create mutex */ + sc = rtems_semaphore_create ( + rtems_build_name ('I', '2', 'C', '1' + e->index), + 0, + RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, + 0, + &e->mutex + ); + RTEMS_CHECK_SC(sc, "create mutex"); + + /* Install interrupt handler and disable this vector */ + sc = rtems_interrupt_handler_install( + e->vector, + "I2C", + RTEMS_INTERRUPT_UNIQUE, + stm32f4_i2c_handler, + e + ); + RTEMS_CHECK_SC(sc, "install interrupt handler"); + bsp_interrupt_vector_disable(e->vector); + + /* Enable module clock */ + stm32f4_rcc_set_clock(rcc_index, true); + + /* Setup initial bit rate */ + sc = stm32f4_i2c_set_bitrate(e, STM32F4_I2C_INITIAL_BAUDRATE); + RTEMS_CHECK_SC(sc, "set bitrate"); + + /* Set config registers */ + cr2 = regs->cr2; + cr2 = STM32F4_I2C_CR2_FREQ_SET(cr2, pclk / 1000000); + cr2 |= STM32F4_I2C_CR2_ITEVTEN; + cr2 |= STM32F4_I2C_CR2_ITBUFEN; + regs->cr2 = cr2; + + cr1 = regs->cr1; + cr1 |= STM32F4_I2C_CR1_PE; + regs->cr1 = cr1; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code stm32f4_i2c_process_message( + stm32f4_i2c_bus_entry *e, + stm32f4_i2c_message *msg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_status_code sc_return = RTEMS_SUCCESSFUL; + volatile stm32f4_i2c *regs = e->regs; + uint16_t max_7_bit_address = (1 << 7) - 1; + uint32_t cr1 = regs->cr1; + + if(msg->addr > max_7_bit_address) { + return RTEMS_NOT_IMPLEMENTED; + } + + if(msg->len == 0) { + return RTEMS_INVALID_SIZE; + } + + sc = rtems_semaphore_obtain(e->mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + RTEMS_CHECK_SC(sc, "obtaining mutex"); + + e->data = msg->buf; + e->last = msg->buf + msg->len - 1; + e->len = msg->len; + + e->addr_with_rw = msg->addr << 1; + if(msg->read) { + e->addr_with_rw |= I2C_RW_BIT; + } + e->read = msg->read; + + /* Check if no stop is active. */ + if(cr1 & STM32F4_I2C_CR1_STOP) { + return RTEMS_IO_ERROR; + } + + /* Start */ + cr1 = regs->cr1; + if(e->len == 2) { + cr1 |= STM32F4_I2C_CR1_POS; + } else { + cr1 &= ~STM32F4_I2C_CR1_POS; + } + cr1 |= STM32F4_I2C_CR1_ACK; + cr1 |= STM32F4_I2C_CR1_START; + regs->cr1 = cr1; + + /* Wait for end of message */ + sc = i2c_wait_done(e); + + if(sc != RTEMS_SUCCESSFUL) { + sc_return = sc; + } + + sc = rtems_semaphore_release(e->mutex); + RTEMS_CHECK_SC(sc, "releasing mutex"); + + return sc_return; +} + diff --git a/c/src/lib/libbsp/arm/stm32f4/include/i2c.h b/c/src/lib/libbsp/arm/stm32f4/include/i2c.h new file mode 100644 index 0000000000..d4891c48e4 --- /dev/null +++ b/c/src/lib/libbsp/arm/stm32f4/include/i2c.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013 Christian Mauderer. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +/* The I2C-module can not run with libi2c. The reason for this is, that libi2c + * needs a possibility to generate a stop condition separately. This controller + * wants to generate the condition automatically when sending or receiving data. + */ + +#ifndef LIBBSP_ARM_STM32F4_I2C_H +#define LIBBSP_ARM_STM32F4_I2C_H + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct { + /* The address of the slave without the read write bit. A 7-Bit address should + * be placed in the bits [6..0] */ + uint16_t addr; + /* Read (true) or write (false) data */ + bool read; + /* Size of data to read or write */ + size_t len; + /* Buffer for data */ + uint8_t *buf; +} stm32f4_i2c_message; + +typedef struct { + volatile stm32f4_i2c *regs; + size_t index; + rtems_vector_number vector; + rtems_id mutex; + rtems_id task_id; + uint8_t *data; + uint8_t *last; + size_t len; + bool read; + uint8_t addr_with_rw; +} stm32f4_i2c_bus_entry; + +/* Initialise the i2c module. */ +rtems_status_code stm32f4_i2c_init(stm32f4_i2c_bus_entry *e); + +/* Process a i2c message */ +rtems_status_code stm32f4_i2c_process_message( + stm32f4_i2c_bus_entry *e, + stm32f4_i2c_message *msg +); + +/* Set another baud rate than the default one */ +rtems_status_code stm32f4_i2c_set_bitrate( + stm32f4_i2c_bus_entry *e, + uint32_t br +); + +extern stm32f4_i2c_bus_entry *const stm32f4_i2c1; +extern stm32f4_i2c_bus_entry *const stm32f4_i2c2; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_ARM_STM32F4_I2C_H */ diff --git a/c/src/lib/libbsp/arm/stm32f4/include/io.h b/c/src/lib/libbsp/arm/stm32f4/include/io.h index 1d8c512ec8..b97b8c80f6 100644 --- a/c/src/lib/libbsp/arm/stm32f4/include/io.h +++ b/c/src/lib/libbsp/arm/stm32f4/include/io.h @@ -346,6 +346,26 @@ bool stm32f4_gpio_get_input(int pin); #define STM32F4_PIN_UART5_TX STM32F4_PIN_USART_TX(2, 12, STM32F4_GPIO_REMAP_DONT_CHANGE) #define STM32F4_PIN_UART5_RX STM32F4_PIN_USART_RX(3, 2, STM32F4_GPIO_REMAP_DONT_CHANGE) +#define STM32F4_PIN_I2C(port, idx, remapvalue) \ + { \ + { \ + .pin_first = STM32F4_GPIO_PIN(port, idx), \ + .pin_last = STM32F4_GPIO_PIN(port, idx), \ + .mode = STM32F4_GPIO_MODE_OUTPUT_2MHz, \ + .cnf = STM32F4_GPIO_CNF_OUT_AF_OD, \ + .output = 0, \ + .remap = remapvalue \ + } \ + } + +#define STM32F4_PIN_I2C1_SCL_MAP0 STM32F4_PIN_I2C(1, 6, STM32F4_GPIO_REMAP_I2C1_0) +#define STM32F4_PIN_I2C1_SDA_MAP0 STM32F4_PIN_I2C(1, 7, STM32F4_GPIO_REMAP_I2C1_0) +#define STM32F4_PIN_I2C1_SCL_MAP1 STM32F4_PIN_I2C(1, 8, STM32F4_GPIO_REMAP_I2C1_1) +#define STM32F4_PIN_I2C1_SDA_MAP1 STM32F4_PIN_I2C(1, 9, STM32F4_GPIO_REMAP_I2C1_1) + +#define STM32F4_PIN_I2C2_SCL STM32F4_PIN_I2C(1, 10, STM32F4_GPIO_REMAP_DONT_CHANGE) +#define STM32F4_PIN_I2C2_SDA STM32F4_PIN_I2C(1, 11, STM32F4_GPIO_REMAP_DONT_CHANGE) + #endif /* STM32F4_FAMILY_F10XXX */ #ifdef __cplusplus diff --git a/c/src/lib/libbsp/arm/stm32f4/include/stm32_i2c.h b/c/src/lib/libbsp/arm/stm32f4/include/stm32_i2c.h new file mode 100644 index 0000000000..68e694122e --- /dev/null +++ b/c/src/lib/libbsp/arm/stm32f4/include/stm32_i2c.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2013 Christian Mauderer. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef LIBBSP_ARM_STM32F4_STM32_I2C_H +#define LIBBSP_ARM_STM32F4_STM32_I2C_H + +#include + +typedef struct { + uint32_t cr1; +#define STM32F4_I2C_CR1_SWRST BSP_BIT32(15) +#define STM32F4_I2C_CR1_ALERT BSP_BIT32(13) +#define STM32F4_I2C_CR1_PEC BSP_BIT32(12) +#define STM32F4_I2C_CR1_POS BSP_BIT32(11) +#define STM32F4_I2C_CR1_ACK BSP_BIT32(10) +#define STM32F4_I2C_CR1_STOP BSP_BIT32(9) +#define STM32F4_I2C_CR1_START BSP_BIT32(8) +#define STM32F4_I2C_CR1_NOSTRETCH BSP_BIT32(7) +#define STM32F4_I2C_CR1_ENGC BSP_BIT32(6) +#define STM32F4_I2C_CR1_ENPEC BSP_BIT32(5) +#define STM32F4_I2C_CR1_ENARP BSP_BIT32(4) +#define STM32F4_I2C_CR1_SMBTYPE BSP_BIT32(3) +#define STM32F4_I2C_CR1_SMBUS BSP_BIT32(1) +#define STM32F4_I2C_CR1_PE BSP_BIT32(0) + uint32_t cr2; +#define STM32F4_I2C_CR2_LAST BSP_BIT32(12) +#define STM32F4_I2C_CR2_DMAEN BSP_BIT32(11) +#define STM32F4_I2C_CR2_ITBUFEN BSP_BIT32(10) +#define STM32F4_I2C_CR2_ITEVTEN BSP_BIT32(9) +#define STM32F4_I2C_CR2_ITERREN BSP_BIT32(8) +#define STM32F4_I2C_CR2_FREQ(val) BSP_FLD32(val, 0, 5) +#define STM32F4_I2C_CR2_FREQ_GET(reg) BSP_FLD32GET(reg, 0, 5) +#define STM32F4_I2C_CR2_FREQ_SET(reg, val) BSP_FLD32SET(reg, val, 0, 5) + uint32_t oar1; +#define STM32F4_I2C_OAR1_ADDMODE BSP_BIT32(15) +#define STM32F4_I2C_OAR1_ADD(val) BSP_FLD32(val, 0, 9) +#define STM32F4_I2C_OAR1_ADD_GET(reg) BSP_FLD32GET(reg, 0, 9) +#define STM32F4_I2C_OAR1_ADD_SET(reg, val) BSP_FLD32SET(reg, val, 0, 9) + uint32_t oar2; +#define STM32F4_I2C_OAR2_ADD2(val) BSP_FLD32(val, 1, 7) +#define STM32F4_I2C_OAR2_ADD2_GET(reg) BSP_FLD32GET(reg, 1, 7) +#define STM32F4_I2C_OAR2_ADD2_SET(reg, val) BSP_FLD32SET(reg, val, 1, 7) +#define STM32F4_I2C_OAR2_ENDUAL BSP_BIT32(0) + uint32_t dr; +#define STM32F4_I2C_DR(val) BSP_FLD32(val, 0, 7) +#define STM32F4_I2C_DR_GET(reg) BSP_FLD32GET(reg, 0, 7) +#define STM32F4_I2C_DR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 7) + uint32_t sr1; +#define STM32F4_I2C_SR1_SMBALERT BSP_BIT32(15) +#define STM32F4_I2C_SR1_TIMEOUT BSP_BIT32(14) +#define STM32F4_I2C_SR1_PECERR BSP_BIT32(12) +#define STM32F4_I2C_SR1_OVR BSP_BIT32(11) +#define STM32F4_I2C_SR1_AF BSP_BIT32(10) +#define STM32F4_I2C_SR1_ARLO BSP_BIT32(9) +#define STM32F4_I2C_SR1_BERR BSP_BIT32(8) +#define STM32F4_I2C_SR1_TxE BSP_BIT32(7) +#define STM32F4_I2C_SR1_RxNE BSP_BIT32(6) +#define STM32F4_I2C_SR1_STOPF BSP_BIT32(4) +#define STM32F4_I2C_SR1_ADD10 BSP_BIT32(3) +#define STM32F4_I2C_SR1_BTF BSP_BIT32(2) +#define STM32F4_I2C_SR1_ADDR BSP_BIT32(1) +#define STM32F4_I2C_SR1_SB BSP_BIT32(0) + uint32_t sr2; +#define STM32F4_I2C_SR2_PEC(val) BSP_FLD32(val, 8, 15) +#define STM32F4_I2C_SR2_PEC_GET(reg) BSP_FLD32GET(reg, 8, 15) +#define STM32F4_I2C_SR2_PEC_SET(reg, val) BSP_FLD32SET(reg, val, 8, 15) +#define STM32F4_I2C_SR2_DUALF BSP_BIT32(7) +#define STM32F4_I2C_SR2_SMBHOST BSP_BIT32(6) +#define STM32F4_I2C_SR2_SMBDEFAULT BSP_BIT32(5) +#define STM32F4_I2C_SR2_GENCALL BSP_BIT32(4) +#define STM32F4_I2C_SR2_TRA BSP_BIT32(2) +#define STM32F4_I2C_SR2_BUSY BSP_BIT32(1) +#define STM32F4_I2C_SR2_MSL BSP_BIT32(0) + uint32_t ccr; +#define STM32F4_I2C_CCR_FS BSP_BIT32(15) +#define STM32F4_I2C_CCR_DUTY BSP_BIT32(14) +#define STM32F4_I2C_CCR_CCR(val) BSP_FLD32(val, 0, 11) +#define STM32F4_I2C_CCR_CCR_GET(reg) BSP_FLD32GET(reg, 0, 11) +#define STM32F4_I2C_CCR_CCR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 11) +#define STM32F4_I2C_CCR_CCR_MAX STM32F4_I2C_CCR_CCR_GET(BSP_MSK32(0, 11)) + uint32_t trise; +#define STM32F4_I2C_TRISE(val) BSP_FLD32(val, 0, 5) +#define STM32F4_I2C_TRISE_GET(reg) BSP_FLD32GET(reg, 0, 5) +#define STM32F4_I2C_TRISE_SET(reg, val) BSP_FLD32SET(reg, val, 0, 5) +} stm32f4_i2c; + +#endif /* LIBBSP_ARM_STM32F4_STM32_I2C_H */ diff --git a/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h index 19df011c20..9059d1814e 100644 --- a/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h +++ b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h @@ -28,6 +28,11 @@ #include #define STM32F4_RCC ((volatile stm32f4_rcc *) (STM32F4_BASE + 0x40023800)) +#include +#define STM32F4_I2C3 ((volatile stm32f4_i2c *) (STM32F4_BASE + 0x40005C00)) +#define STM32F4_I2C2 ((volatile stm32f4_i2c *) (STM32F4_BASE + 0x40005800)) +#define STM32F4_I2C1 ((volatile stm32f4_i2c *) (STM32F4_BASE + 0x40005400)) + #include #define STM32F4_USART_1 ((volatile stm32f4_usart *) (STM32F4_BASE + 0x40011000)) #define STM32F4_USART_2 ((volatile stm32f4_usart *) (STM32F4_BASE + 0x40004400)) @@ -50,6 +55,10 @@ #include #define STM32F4_RCC ((volatile stm32f4_rcc *) (STM32F4_BASE + 0x40021000)) +#include +#define STM32F4_I2C2 ((volatile stm32f4_i2c *) (STM32F4_BASE + 0x40005800)) +#define STM32F4_I2C1 ((volatile stm32f4_i2c *) (STM32F4_BASE + 0x40005400)) + #include #define STM32F4_USART_1 ((volatile stm32f4_usart *) (STM32F4_BASE + 0x40013800)) #define STM32F4_USART_2 ((volatile stm32f4_usart *) (STM32F4_BASE + 0x40004400)) diff --git a/c/src/lib/libbsp/arm/stm32f4/preinstall.am b/c/src/lib/libbsp/arm/stm32f4/preinstall.am index 8be89567a6..a75e3d070a 100644 --- a/c/src/lib/libbsp/arm/stm32f4/preinstall.am +++ b/c/src/lib/libbsp/arm/stm32f4/preinstall.am @@ -125,6 +125,14 @@ $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_rcc.h: include/stm32f4xxxx_rcc.h $(PROJECT_IN $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_rcc.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_rcc.h +$(PROJECT_INCLUDE)/bsp/stm32_i2c.h: include/stm32_i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/stm32_i2c.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/stm32_i2c.h + +$(PROJECT_INCLUDE)/bsp/i2c.h: include/i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i2c.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/i2c.h + $(PROJECT_INCLUDE)/bsp/stm32_usart.h: include/stm32_usart.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/stm32_usart.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/stm32_usart.h diff --git a/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c b/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c index 2ec863505c..39e9db0856 100644 --- a/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c +++ b/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c @@ -41,6 +41,12 @@ const stm32f4_gpio_config stm32f4_start_config_gpio [] = { STM32F4_PIN_USART6_TX_PC6, STM32F4_PIN_USART6_RX_PC7, #endif + #ifdef STM32F4_ENABLE_I2C1 + #error Not implemented. + #endif + #ifdef STM32F4_ENABLE_I2C2 + #error Not implemented. + #endif #endif /* STM32F4_FAMILY_F4XXXX */ #ifdef STM32F4_FAMILY_F10XXX #ifdef STM32F4_ENABLE_USART_1 @@ -63,6 +69,17 @@ const stm32f4_gpio_config stm32f4_start_config_gpio [] = { STM32F4_PIN_UART5_TX, STM32F4_PIN_UART5_RX, #endif + #ifdef STM32F4_ENABLE_USART_6 + #error STM32F10XXX has no USART 6 + #endif + #ifdef STM32F4_ENABLE_I2C1 + STM32F4_PIN_I2C1_SCL_MAP0, + STM32F4_PIN_I2C1_SDA_MAP0, + #endif + #ifdef STM32F4_ENABLE_I2C2 + STM32F4_PIN_I2C2_SCL, + STM32F4_PIN_I2C2_SDA, + #endif #endif /* STM32F4_FAMILY_F10XXX */ STM32F4_GPIO_CONFIG_TERMINAL }; -- cgit v1.2.3