You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ut...@apache.org on 2018/04/18 21:56:36 UTC

[mynewt-core] 13/13: Initial stm32f1 i2c support + olimex-p103 config

This is an automated email from the ASF dual-hosted git repository.

utzig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit 9f4fc4aaf90791b060a64bafa3184e8623b8f387
Author: Fabio Utzig <ut...@apache.org>
AuthorDate: Fri Mar 23 11:22:45 2018 -0300

    Initial stm32f1 i2c support + olimex-p103 config
---
 hw/bsp/nucleo-f401re/src/hal_bsp.c                 |   2 +-
 hw/bsp/olimex-p103/src/hal_bsp.c                   |  11 +-
 hw/mcu/stm/stm32_common/src/hal_i2c.c              |  77 +++++++++
 hw/mcu/stm/stm32f1xx/include/mcu/stm32_hal.h       |   5 +
 .../stm32f1xx/include/mcu/stm32f1xx_mynewt_hal.h   |   4 +-
 hw/mcu/stm/stm32f1xx/src/hal_i2c.c                 | 190 ---------------------
 hw/mcu/stm/stm32f1xx/syscfg.yml                    |   8 +-
 7 files changed, 94 insertions(+), 203 deletions(-)

diff --git a/hw/bsp/nucleo-f401re/src/hal_bsp.c b/hw/bsp/nucleo-f401re/src/hal_bsp.c
index 05fb6ce..3c43d19 100644
--- a/hw/bsp/nucleo-f401re/src/hal_bsp.c
+++ b/hw/bsp/nucleo-f401re/src/hal_bsp.c
@@ -86,7 +86,7 @@ static struct stm32_hal_i2c_cfg i2c_cfg0 = {
 #endif
 
 #if MYNEWT_VAL(SPI_0_SLAVE) || MYNEWT_VAL(SPI_0_MASTER)
-struct stm32f4_hal_spi_cfg spi0_cfg = {
+struct stm32_hal_spi_cfg spi0_cfg = {
     .ss_pin = MCU_GPIO_PORTA(4),            /* PA4 */
     .sck_pin  = MCU_GPIO_PORTA(5),          /* PA5 */
     .miso_pin = MCU_GPIO_PORTA(6),          /* PA6 */
diff --git a/hw/bsp/olimex-p103/src/hal_bsp.c b/hw/bsp/olimex-p103/src/hal_bsp.c
index f06eb71..1c64825 100644
--- a/hw/bsp/olimex-p103/src/hal_bsp.c
+++ b/hw/bsp/olimex-p103/src/hal_bsp.c
@@ -90,16 +90,15 @@ struct stm32_hal_spi_cfg spi1_cfg = {
 #endif
 
 #if MYNEWT_VAL(I2C_0)
-/* TODO */
-static struct stm32f1_hal_i2c_cfg i2c_cfg0 = {
+static struct stm32_hal_i2c_cfg i2c_cfg0 = {
     .hic_i2c = I2C1,
     .hic_rcc_reg = &RCC->APB1ENR,
     .hic_rcc_dev = RCC_APB1ENR_I2C1EN,
-    .hic_pin_sda = MCU_GPIO_PORTB(9),       /* PB9 */
-    .hic_pin_scl = MCU_GPIO_PORTB(8),       /* PB8 */
-    .hic_pin_af = GPIO_AF4_I2C1,
+    .hic_pin_sda = MCU_GPIO_PORTB(7),
+    .hic_pin_scl = MCU_GPIO_PORTB(6),
+    .hic_pin_remap_fn = LL_GPIO_AF_DisableRemap_I2C1,
     .hic_10bit = 0,
-    .hic_speed = 100000                     /* 100kHz */
+    .hic_speed = 100000,
 };
 #endif
 
diff --git a/hw/mcu/stm/stm32_common/src/hal_i2c.c b/hw/mcu/stm/stm32_common/src/hal_i2c.c
index a9c4cf4..83d4fe5 100644
--- a/hw/mcu/stm/stm32_common/src/hal_i2c.c
+++ b/hw/mcu/stm/stm32_common/src/hal_i2c.c
@@ -71,12 +71,26 @@ static struct stm32_hal_i2c *hal_i2c_devs[HAL_I2C_MAX_DEVS] = {
 #endif
 };
 
+#if defined(STM32F1)
+static void
+i2c_reset(I2C_HandleTypeDef *hi2c)
+{
+    __HAL_I2C_DISABLE(hi2c);
+    hi2c->Instance->CR1 |= I2C_CR1_SWRST;
+    hi2c->Instance->CR1 &= ~I2C_CR1_SWRST;
+    __HAL_I2C_ENABLE(hi2c);
+}
+#endif
+
 int
 hal_i2c_init(uint8_t i2c_num, void *usercfg)
 {
     struct stm32_hal_i2c_cfg *cfg = (struct stm32_hal_i2c_cfg *)usercfg;
     struct stm32_hal_i2c *dev;
     I2C_InitTypeDef *init;
+#if defined(STM32F1)
+    GPIO_InitTypeDef gpio;
+#endif
     int rc;
 
     if (i2c_num >= HAL_I2C_MAX_DEVS || !(dev = hal_i2c_devs[i2c_num])) {
@@ -102,6 +116,7 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
      * Configure GPIO pins for I2C.
      * Enable clock routing for I2C.
      */
+#if !defined(STM32F1)
     rc = hal_gpio_init_af(cfg->hic_pin_sda, cfg->hic_pin_af, HAL_GPIO_PULL_UP,
                           1);
     if (rc) {
@@ -112,7 +127,62 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
     if (rc) {
         goto err;
     }
+
+    *cfg->hic_rcc_reg |= cfg->hic_rcc_dev;
+#else
+    /* For STM32F1x initialize I2C clock before GPIOs */
     *cfg->hic_rcc_reg |= cfg->hic_rcc_dev;
+
+    if (cfg->hic_pin_remap_fn != NULL) {
+        cfg->hic_pin_remap_fn();
+    }
+
+    /*
+     * The block below applies a workaround described in 2.13.7
+     * of the STM32F103 errata (also described on F105/107 errata).
+     */
+    gpio.Mode = GPIO_MODE_OUTPUT_OD;
+    gpio.Speed = GPIO_SPEED_FREQ_LOW;
+    gpio.Pull = GPIO_NOPULL;
+
+    hal_gpio_init_stm(cfg->hic_pin_sda, &gpio);
+    hal_gpio_write(cfg->hic_pin_sda, 1);
+    hal_gpio_init_stm(cfg->hic_pin_scl, &gpio);
+    hal_gpio_write(cfg->hic_pin_scl, 1);
+
+    assert(hal_gpio_read(cfg->hic_pin_sda) == 1);
+    assert(hal_gpio_read(cfg->hic_pin_scl) == 1);
+
+    hal_gpio_write(cfg->hic_pin_sda, 0);
+    assert(hal_gpio_read(cfg->hic_pin_sda) == 0);
+
+    hal_gpio_write(cfg->hic_pin_scl, 0);
+    assert(hal_gpio_read(cfg->hic_pin_scl) == 0);
+
+    hal_gpio_write(cfg->hic_pin_scl, 1);
+    assert(hal_gpio_read(cfg->hic_pin_scl) == 1);
+
+    hal_gpio_write(cfg->hic_pin_sda, 1);
+    assert(hal_gpio_read(cfg->hic_pin_sda) == 1);
+
+    /*
+     * Normal I2C PIN initialization
+     */
+    gpio.Mode = GPIO_MODE_AF_OD;
+    gpio.Speed = GPIO_SPEED_FREQ_HIGH;
+    /* NOTE: Pull is not used in AF mode */
+    gpio.Pull = GPIO_NOPULL;
+
+    hal_gpio_init_stm(cfg->hic_pin_scl, &gpio);
+    hal_gpio_init_stm(cfg->hic_pin_sda, &gpio);
+
+    /*
+     * Reset I2C
+     */
+    dev->hid_handle.Instance->CR1 = I2C_CR1_SWRST;
+    dev->hid_handle.Instance->CR1 = 0;
+#endif
+
     rc = HAL_I2C_Init(&dev->hid_handle);
     if (rc) {
         goto err;
@@ -163,5 +233,12 @@ hal_i2c_master_probe(uint8_t i2c_num, uint8_t address, uint32_t timo)
     }
 
     rc = HAL_I2C_IsDeviceReady(&dev->hid_handle, address << 1, 1, timo);
+
+#if defined(STM32F1)
+    if (rc == HAL_BUSY) {
+        i2c_reset(&dev->hid_handle);
+    }
+#endif
+
     return rc;
 }
diff --git a/hw/mcu/stm/stm32f1xx/include/mcu/stm32_hal.h b/hw/mcu/stm/stm32f1xx/include/mcu/stm32_hal.h
index 238888e..9694e72 100644
--- a/hw/mcu/stm/stm32f1xx/include/mcu/stm32_hal.h
+++ b/hw/mcu/stm/stm32f1xx/include/mcu/stm32_hal.h
@@ -54,6 +54,11 @@ struct stm32_hal_spi_cfg {
     int irq_prio;
 };
 
+/* hal_i2c */
+#include "stm32f1xx_hal_i2c.h"
+#include "mcu/stm32f1xx_mynewt_hal.h"
+#include "mcu/stm32f1_bsp.h"
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/mcu/stm/stm32f1xx/include/mcu/stm32f1xx_mynewt_hal.h b/hw/mcu/stm/stm32f1xx/include/mcu/stm32f1xx_mynewt_hal.h
index e0eb123..437a3fd 100644
--- a/hw/mcu/stm/stm32f1xx/include/mcu/stm32f1xx_mynewt_hal.h
+++ b/hw/mcu/stm/stm32f1xx/include/mcu/stm32f1xx_mynewt_hal.h
@@ -48,13 +48,13 @@ extern "C" {
 int hal_gpio_init_stm(int pin, GPIO_InitTypeDef *cfg);
 int hal_gpio_deinit_stm(int pin, GPIO_InitTypeDef *cfg);
 
-struct stm32f1_hal_i2c_cfg {
+struct stm32_hal_i2c_cfg {
     I2C_TypeDef *hic_i2c;
     volatile uint32_t *hic_rcc_reg;     /* RCC register to modify */
     uint32_t hic_rcc_dev;               /* RCC device ID */
     uint8_t hic_pin_sda;
     uint8_t hic_pin_scl;
-    uint8_t hic_pin_af;
+    void (*hic_pin_remap_fn)(void);
     uint8_t hic_10bit;
     uint32_t hic_speed;
 };
diff --git a/hw/mcu/stm/stm32f1xx/src/hal_i2c.c b/hw/mcu/stm/stm32f1xx/src/hal_i2c.c
deleted file mode 100644
index 0d8d8f8..0000000
--- a/hw/mcu/stm/stm32f1xx/src/hal_i2c.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "os/mynewt.h"
-
-#include <hal/hal_i2c.h>
-#include <hal/hal_gpio.h>
-
-#include "stm32f1xx.h"
-#include "stm32f1xx_hal_dma.h"
-#include "stm32f1xx_hal_i2c.h"
-#include "stm32f1xx_hal_gpio.h"
-#include "stm32f1xx_hal_rcc.h"
-#include "mcu/stm32f1xx_mynewt_hal.h"
-#include "mcu/stm32f1_bsp.h"
-
-#define HAL_I2C_MAX_DEVS	3
-
-#define I2C_ADDRESS 		0xae
-
-struct stm32f1_hal_i2c {
-    I2C_HandleTypeDef hid_handle;
-};
-
-#if MYNEWT_VAL(I2C_0)
-static struct stm32f1_hal_i2c i2c0;
-#endif
-#if MYNEWT_VAL(I2C_1)
-static struct stm32f1_hal_i2c i2c1;
-#endif
-#if MYNEWT_VAL(I2C_2)
-static struct stm32f1_hal_i2c i2c2;
-#endif
-
-static struct stm32f1_hal_i2c *hal_i2c_devs[HAL_I2C_MAX_DEVS] = {
-#if MYNEWT_VAL(I2C_0)
-    &i2c0,
-#else
-    NULL,
-#endif
-#if MYNEWT_VAL(I2C_1)
-    &i2c1,
-#else
-    NULL,
-#endif
-#if MYNEWT_VAL(I2C_2)
-    &i2c2,
-#else
-    NULL,
-#endif
-};
-
-int
-hal_i2c_init(uint8_t i2c_num, void *usercfg)
-{
-    struct stm32f1_hal_i2c_cfg *cfg = (struct stm32f1_hal_i2c_cfg *)usercfg;
-    struct stm32f1_hal_i2c *dev;
-    I2C_InitTypeDef *init;
-    GPIO_InitTypeDef gpio;
-    int rc;
-
-    if (i2c_num >= HAL_I2C_MAX_DEVS || !(dev = hal_i2c_devs[i2c_num])) {
-        return -1;
-    }
-
-    init = &dev->hid_handle.Init;
-    dev->hid_handle.Instance = cfg->hic_i2c;
-    init->ClockSpeed = cfg->hic_speed;
-    if (cfg->hic_10bit) {
-        init->AddressingMode = I2C_ADDRESSINGMODE_10BIT;
-    } else {
-        init->AddressingMode = I2C_ADDRESSINGMODE_7BIT;
-    }
-    init->OwnAddress1 = I2C_ADDRESS;
-    init->OwnAddress2 = 0xFE;
-
-    init->DutyCycle = I2C_DUTYCYCLE_2;
-    init->DualAddressMode = I2C_DUALADDRESS_DISABLE;
-    init->GeneralCallMode = I2C_GENERALCALL_DISABLE;
-    init->NoStretchMode = I2C_NOSTRETCH_DISABLE;
-
-    /*
-     * Configure GPIO pins for I2C.
-     * Enable clock routing for I2C.
-     */
-    gpio.Speed = GPIO_SPEED_FREQ_HIGH;
-    gpio.Pull = GPIO_NOPULL;
-    gpio.Mode = GPIO_MODE_AF_OD;
-    hal_gpio_init_stm(cfg->hic_pin_scl, &gpio);
-    hal_gpio_init_stm(cfg->hic_pin_sda, &gpio);
-
-#if 0
-    hal_gpio_write(cfg->hic_pin_scl, 0);
-    //for (int i = 0; i < 1000; i++) asm("nop");
-    hal_gpio_write(cfg->hic_pin_scl, 1);
-
-    hal_gpio_write(cfg->hic_pin_sda, 0);
-    //for (int i = 0; i < 1000; i++) asm("nop");
-    hal_gpio_write(cfg->hic_pin_sda, 1);
-#endif
-
-    if (cfg->hic_pin_remap_fn) {
-        cfg->hic_pin_remap_fn();
-    }
-
-    *cfg->hic_rcc_reg |= cfg->hic_rcc_dev;
-    rc = HAL_I2C_Init(&dev->hid_handle);
-    if (rc) {
-        goto err;
-    }
-
-    return 0;
-err:
-    *cfg->hic_rcc_reg &= ~cfg->hic_rcc_dev;
-    return rc;
-}
-
-int
-hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *data,
-  uint32_t timo, uint8_t last_op)
-{
-    struct stm32f1_hal_i2c *dev;
-
-    if (i2c_num >= HAL_I2C_MAX_DEVS || !(dev = hal_i2c_devs[i2c_num])) {
-        return -1;
-    }
-
-    if (!last_op) {
-        //return HAL_I2C_Master_Transmit_NoStop(&dev->hid_handle,
-        return HAL_I2C_Master_Transmit(&dev->hid_handle,
-          data->address << 1, data->buffer, data->len, timo);
-    } else {
-        return HAL_I2C_Master_Transmit(&dev->hid_handle,
-          data->address << 1, data->buffer, data->len, timo);
-    }
-}
-
-int
-hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
-  uint32_t timo, uint8_t last_op)
-{
-    struct stm32f1_hal_i2c *dev;
-
-    if (i2c_num >= HAL_I2C_MAX_DEVS || !(dev = hal_i2c_devs[i2c_num])) {
-        return -1;
-    }
-
-    if (!last_op) {
-        //return HAL_I2C_Master_Receive_NoStop(&dev->hid_handle,
-        return HAL_I2C_Master_Receive(&dev->hid_handle,
-          pdata->address << 1, pdata->buffer, pdata->len, timo);
-    } else {
-        return HAL_I2C_Master_Receive(&dev->hid_handle, pdata->address << 1,
-          pdata->buffer, pdata->len, timo);
-    }
-}
-
-int
-hal_i2c_master_probe(uint8_t i2c_num, uint8_t address, uint32_t timo)
-{
-    struct stm32f1_hal_i2c *dev;
-    int rc;
-
-    if (i2c_num >= HAL_I2C_MAX_DEVS || !(dev = hal_i2c_devs[i2c_num])) {
-        return -1;
-    }
-
-    rc = HAL_I2C_IsDeviceReady(&dev->hid_handle, address, 1, timo);
-    return rc;
-}
diff --git a/hw/mcu/stm/stm32f1xx/syscfg.yml b/hw/mcu/stm/stm32f1xx/syscfg.yml
index 2b35fd2..e59fc47 100644
--- a/hw/mcu/stm/stm32f1xx/syscfg.yml
+++ b/hw/mcu/stm/stm32f1xx/syscfg.yml
@@ -19,10 +19,6 @@
 # Package: hw/bsp/stm32l152discovery
 
 syscfg.defs:
-    I2C_0:
-        description: 'I2C (TWI) interface 0'
-        value:  0
-
     MCU_FLASH_MIN_WRITE_SIZE:
         description: >
             Specifies the required alignment for internal flash writes.
@@ -33,6 +29,10 @@ syscfg.defs:
         description: MCUs are of STM32F1xx family
         value: 1
 
+    I2C_0:
+        description: 'I2C (TWI) interface 0'
+        value:  0
+
     SPI_0_MASTER:
         description: 'SPI 0 master'
         value:  0

-- 
To stop receiving notification emails like this one, please contact
utzig@apache.org.