diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 09:45:28 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 15:18:43 +0200 |
commit | a2dad96ab736f66ed54421cad53caf31f250e181 (patch) | |
tree | 1935320b5b52276ed2e52741cdae71637f209f77 /c/src/lib/libbsp/arm/stm32f4 | |
parent | bsps/arm: Remove unused stm32f* files (diff) | |
download | rtems-a2dad96ab736f66ed54421cad53caf31f250e181.tar.bz2 |
bsps: Move I2C drivers to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'c/src/lib/libbsp/arm/stm32f4')
-rw-r--r-- | c/src/lib/libbsp/arm/stm32f4/Makefile.am | 4 | ||||
-rw-r--r-- | c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c | 37 | ||||
-rw-r--r-- | c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c | 329 |
3 files changed, 2 insertions, 368 deletions
diff --git a/c/src/lib/libbsp/arm/stm32f4/Makefile.am b/c/src/lib/libbsp/arm/stm32f4/Makefile.am index fd159fd6c1..4671386696 100644 --- a/c/src/lib/libbsp/arm/stm32f4/Makefile.am +++ b/c/src/lib/libbsp/arm/stm32f4/Makefile.am @@ -60,8 +60,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/stm32f4/console/console-conf librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/stm32f4/console/usart.c # I2C -librtemsbsp_a_SOURCES += i2c/i2c.c -librtemsbsp_a_SOURCES += i2c/i2c-config.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/stm32f4/i2c/i2c.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/stm32f4/i2c/i2c-config.c # Clock librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/clock/clock-armv7m.c diff --git a/c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c b/c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c deleted file mode 100644 index eac16bafc0..0000000000 --- a/c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2013 Christian Mauderer. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * <rtems@embedded-brains.de> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include <bspopts.h> -#include <bsp/i2c.h> -#include <bsp/irq.h> - -#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 deleted file mode 100644 index 1d0a409455..0000000000 --- a/c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (c) 2013 Christian Mauderer. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * <rtems@embedded-brains.de> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/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 <bsp.h> -#include <bsp/i2c.h> -#include <bsp/rcc.h> -#include <bsp/irq.h> -#include <bsp/irq-generic.h> -#include <assert.h> - -#define RTEMS_STATUS_CHECKS_USE_PRINTK - -#include <rtems/status-checks.h> - -#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) -{ - 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_BITRATE); - 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; -} - |