mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Add OpenMV gpio and i2c abstraction layer.
This commit is contained in:
parent
3813fed939
commit
e122e4e82d
@ -12,9 +12,18 @@
|
||||
#define __CAMBUS_H__
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "cambus_struct.h"
|
||||
#include "omv_portconfig.h"
|
||||
|
||||
// Transfer speeds
|
||||
typedef enum _cambus_speed {
|
||||
CAMBUS_SPEED_STANDARD = (0U),
|
||||
CAMBUS_SPEED_FULL = (1U),
|
||||
CAMBUS_SPEED_FAST = (2U),
|
||||
CAMBUS_SPEED_MAX = (3U)
|
||||
} cambus_speed_t;
|
||||
|
||||
// For use with read/write_bytes
|
||||
enum cambus_xfer_flags {
|
||||
typedef enum cambus_xfer_flags {
|
||||
// Stop condition after the transfer.
|
||||
// Normal transfer with start condition, address, data and stop condition.
|
||||
CAMBUS_XFER_NO_FLAGS = (0<<0),
|
||||
@ -24,7 +33,17 @@ enum cambus_xfer_flags {
|
||||
// No stop condition after the transfer.
|
||||
// This flag allows chaining multiple writes or reads with the same direction.
|
||||
CAMBUS_XFER_SUSPEND = (1<<1),
|
||||
};
|
||||
} cambus_xfer_flags_t;
|
||||
|
||||
typedef struct _cambus {
|
||||
uint32_t id;
|
||||
uint32_t speed;
|
||||
uint32_t initialized;
|
||||
omv_gpio_t scl_pin;
|
||||
omv_gpio_t sda_pin;
|
||||
omv_cambus_t i2c;
|
||||
} cambus_t;
|
||||
|
||||
int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed);
|
||||
int cambus_deinit(cambus_t *bus);
|
||||
int cambus_scan(cambus_t *bus);
|
||||
|
||||
@ -22,22 +22,33 @@
|
||||
int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
||||
{
|
||||
bus->id = bus_id;
|
||||
bus->speed = speed;
|
||||
bus->initialized = false;
|
||||
|
||||
switch (speed) {
|
||||
case CAMBUS_SPEED_STANDARD:
|
||||
bus->speed = TWI_FREQUENCY_FREQUENCY_K100; ///< 100 kbps
|
||||
break;
|
||||
case CAMBUS_SPEED_FULL:
|
||||
bus->speed = TWI_FREQUENCY_FREQUENCY_K250; ///< 250 kbps
|
||||
break;
|
||||
case CAMBUS_SPEED_FAST:
|
||||
bus->speed = TWI_FREQUENCY_FREQUENCY_K400; ///< 400 kbps
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (bus_id) {
|
||||
case 0: {
|
||||
bus->scl_pin = TWI0_SCL_PIN;
|
||||
bus->sda_pin = TWI0_SDA_PIN;
|
||||
nrfx_twi_t _twi = NRFX_TWI_INSTANCE(0);
|
||||
memcpy(&bus->twi, &_twi, sizeof(nrfx_twi_t));
|
||||
bus->i2c = (nrfx_twi_t) NRFX_TWI_INSTANCE(0);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
bus->scl_pin = TWI1_SCL_PIN;
|
||||
bus->sda_pin = TWI1_SDA_PIN;
|
||||
nrfx_twi_t _twi = NRFX_TWI_INSTANCE(1);
|
||||
memcpy(&bus->twi, &_twi, sizeof(nrfx_twi_t));
|
||||
bus->i2c = (nrfx_twi_t) NRFX_TWI_INSTANCE(1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -47,17 +58,17 @@ int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
||||
nrfx_twi_config_t config = {
|
||||
.scl = bus->scl_pin,
|
||||
.sda = bus->sda_pin,
|
||||
.frequency = speed,
|
||||
.frequency = bus->speed,
|
||||
.interrupt_priority = 4,
|
||||
.hold_bus_uninit = false
|
||||
};
|
||||
|
||||
if (nrfx_twi_init(&bus->twi, &config, NULL, NULL) != NRFX_SUCCESS) {
|
||||
if (nrfx_twi_init(&bus->i2c, &config, NULL, NULL) != NRFX_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// This bus needs to be enabled for suspended transfers.
|
||||
nrfx_twi_enable(&bus->twi);
|
||||
nrfx_twi_enable(&bus->i2c);
|
||||
|
||||
bus->initialized = true;
|
||||
return 0;
|
||||
@ -66,8 +77,8 @@ int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
||||
int cambus_deinit(cambus_t *bus)
|
||||
{
|
||||
if (bus->initialized) {
|
||||
nrfx_twi_disable(&bus->twi);
|
||||
nrfx_twi_uninit(&bus->twi);
|
||||
nrfx_twi_disable(&bus->i2c);
|
||||
nrfx_twi_uninit(&bus->i2c);
|
||||
bus->initialized = false;
|
||||
}
|
||||
return 0;
|
||||
@ -93,7 +104,7 @@ int cambus_read_bytes(cambus_t *bus, uint8_t slv_addr, uint8_t *buf, int len, ui
|
||||
}
|
||||
|
||||
nrfx_twi_xfer_desc_t desc = NRFX_TWI_XFER_DESC_RX(slv_addr, buf, len);
|
||||
if (nrfx_twi_xfer(&bus->twi, &desc, xfer_flags) != NRFX_SUCCESS) {
|
||||
if (nrfx_twi_xfer(&bus->i2c, &desc, xfer_flags) != NRFX_SUCCESS) {
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
@ -111,7 +122,7 @@ int cambus_write_bytes(cambus_t *bus, uint8_t slv_addr, uint8_t *buf, int len, u
|
||||
}
|
||||
|
||||
nrfx_twi_xfer_desc_t desc = NRFX_TWI_XFER_DESC_TX(slv_addr, buf, len);
|
||||
if (nrfx_twi_xfer(&bus->twi, &desc, xfer_flags) != NRFX_SUCCESS) {
|
||||
if (nrfx_twi_xfer(&bus->i2c, &desc, xfer_flags) != NRFX_SUCCESS) {
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
|
||||
21
src/omv/ports/nrf/omv_portconfig.h
Normal file
21
src/omv/ports/nrf/omv_portconfig.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
*
|
||||
* Copyright (c) 2013-2019 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||
* Copyright (c) 2013-2019 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||
*
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* OpenMV nRF port abstraction layer.
|
||||
*/
|
||||
#ifndef __OMV_PORTCONFIG_H__
|
||||
#define __OMV_PORTCONFIG_H__
|
||||
|
||||
#include "nrfx_twi.h"
|
||||
|
||||
// omv_gpio_t definition
|
||||
typedef uint32_t omv_gpio_t;
|
||||
|
||||
// cambus/i2c definition
|
||||
typedef nrfx_twi_t omv_cambus_t;
|
||||
#endif // __OMV_PORTCONFIG_H__
|
||||
@ -61,11 +61,25 @@ void I2C4_ER_IRQHandler(void) { HAL_I2C_ER_IRQHandler(&I2CHandle4); }
|
||||
#endif
|
||||
#endif // I2C4
|
||||
|
||||
static const uint32_t cambus_timing[CAMBUS_SPEED_MAX] = {
|
||||
#if defined(STM32F4)
|
||||
100000U, 400000U, 400000U,
|
||||
#elif defined(STM32F7)
|
||||
0x1090699B, 0x70330309, 0x50100103,
|
||||
#elif defined(STM32H7)
|
||||
0x20D09DE7, 0x40900C22, 0x4030040B,
|
||||
#else
|
||||
#error "no I2C timings for this MCU"
|
||||
#endif
|
||||
};
|
||||
|
||||
int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
||||
{
|
||||
bus->id = bus_id;
|
||||
bus->speed = speed;
|
||||
bus->i2c = NULL;
|
||||
bus->initialized = false;
|
||||
bus->scl_pin = (omv_gpio_t) {0, 0};
|
||||
bus->sda_pin = (omv_gpio_t) {0, 0};
|
||||
|
||||
switch (bus_id) {
|
||||
#if defined(I2C1)
|
||||
@ -100,27 +114,27 @@ int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (speed < 0 || speed >= CAMBUS_SPEED_MAX) {
|
||||
return -1;
|
||||
} else {
|
||||
bus->speed = cambus_timing[speed];
|
||||
}
|
||||
|
||||
// Our code only knows about these two I2Cs instances.
|
||||
if (bus->i2c->Instance == FIR_I2C) {
|
||||
bus->port = FIR_I2C_PORT;
|
||||
bus->scl_pin = FIR_I2C_SCL_PIN;
|
||||
bus->sda_pin = FIR_I2C_SDA_PIN;
|
||||
bus->scl_pin = (omv_gpio_t) {FIR_I2C_SCL_PIN, FIR_I2C_PORT};
|
||||
bus->sda_pin = (omv_gpio_t) {FIR_I2C_SDA_PIN, FIR_I2C_PORT};
|
||||
} else if (bus->i2c->Instance == ISC_I2C) {
|
||||
bus->port = ISC_I2C_PORT;
|
||||
bus->scl_pin = ISC_I2C_SCL_PIN;
|
||||
bus->sda_pin = ISC_I2C_SDA_PIN;
|
||||
} else {
|
||||
bus->port = NULL;
|
||||
bus->scl_pin = 0;
|
||||
bus->sda_pin = 0;
|
||||
bus->scl_pin = (omv_gpio_t) {ISC_I2C_SCL_PIN, ISC_I2C_PORT};
|
||||
bus->sda_pin = (omv_gpio_t) {ISC_I2C_SDA_PIN, ISC_I2C_PORT};
|
||||
}
|
||||
|
||||
// Configure the I2C handle
|
||||
bus->i2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||
#if !defined(STM32F4)
|
||||
bus->i2c->Init.Timing = speed;
|
||||
bus->i2c->Init.Timing = bus->speed;
|
||||
#else
|
||||
bus->i2c->Init.ClockSpeed = speed;
|
||||
bus->i2c->Init.ClockSpeed = bus->speed;
|
||||
bus->i2c->Init.DutyCycle = I2C_DUTYCYCLE_2;
|
||||
#endif
|
||||
bus->i2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
|
||||
@ -135,7 +149,8 @@ int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
||||
HAL_I2C_DeInit(bus->i2c);
|
||||
if (HAL_I2C_Init(bus->i2c) != HAL_OK) {
|
||||
bus->i2c = NULL;
|
||||
bus->port = NULL;
|
||||
bus->scl_pin = (omv_gpio_t) {0, 0};
|
||||
bus->sda_pin = (omv_gpio_t) {0, 0};
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -164,6 +179,8 @@ int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bus->initialized = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -229,12 +246,14 @@ static int cambus_wait_timeout(cambus_t *bus, uint32_t timeout)
|
||||
|
||||
int cambus_deinit(cambus_t *bus)
|
||||
{
|
||||
if (bus->i2c && bus->i2c->Instance) {
|
||||
if (bus->initialized) {
|
||||
HAL_I2C_DeInit(bus->i2c);
|
||||
bus->i2c->Instance = NULL;
|
||||
}
|
||||
bus->i2c = NULL;
|
||||
bus->port = NULL;
|
||||
bus->scl_pin = (omv_gpio_t) {0, 0};
|
||||
bus->sda_pin = (omv_gpio_t) {0, 0};
|
||||
bus->initialized = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -391,20 +410,20 @@ int cambus_write_bytes(cambus_t *bus, uint8_t slv_addr, uint8_t *buf, int len, u
|
||||
|
||||
int cambus_pulse_scl(cambus_t *bus)
|
||||
{
|
||||
if (bus->port) {
|
||||
if (bus->initialized && bus->scl_pin.port) {
|
||||
// Configure SCL as GPIO
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStructure.Pin = bus->scl_pin;
|
||||
HAL_GPIO_Init(bus->port, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.Pin = bus->scl_pin.pin;
|
||||
HAL_GPIO_Init(bus->scl_pin.port, &GPIO_InitStructure);
|
||||
|
||||
// Pulse SCL to recover stuck device.
|
||||
for (int i=0; i<10000; i++) {
|
||||
HAL_GPIO_WritePin(bus->port, bus->scl_pin, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(bus->scl_pin.port, bus->scl_pin.pin, GPIO_PIN_SET);
|
||||
mp_hal_delay_us(10);
|
||||
HAL_GPIO_WritePin(bus->port, bus->scl_pin, GPIO_PIN_RESET);
|
||||
HAL_GPIO_WritePin(bus->scl_pin.port, bus->scl_pin.pin, GPIO_PIN_RESET);
|
||||
mp_hal_delay_us(10);
|
||||
}
|
||||
|
||||
|
||||
25
src/omv/ports/stm32/omv_portconfig.h
Normal file
25
src/omv/ports/stm32/omv_portconfig.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
*
|
||||
* Copyright (c) 2013-2019 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||
* Copyright (c) 2013-2019 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||
*
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* OpenMV STM32 port abstraction layer.
|
||||
*/
|
||||
#ifndef __OMV_PORTCONFIG_H__
|
||||
#define __OMV_PORTCONFIG_H__
|
||||
#include STM32_HAL_H
|
||||
|
||||
// omv_gpio_t definition
|
||||
typedef struct _omv_gpio {
|
||||
uint32_t pin;
|
||||
GPIO_TypeDef *port;
|
||||
} omv_gpio_t;
|
||||
|
||||
// cambus/i2c definition
|
||||
// This pointer will be set to its respective I2C handle which is defined in MicroPython along with
|
||||
// IRQ handlers, if this I2C is enabled in Micropython, or defined and handled in stm32fxxx_hal_msp.c.
|
||||
typedef I2C_HandleTypeDef *omv_cambus_t;
|
||||
#endif // __OMV_PORTCONFIG_H__
|
||||
Loading…
Reference in New Issue
Block a user