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__
|
#define __CAMBUS_H__
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.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
|
// For use with read/write_bytes
|
||||||
enum cambus_xfer_flags {
|
typedef enum cambus_xfer_flags {
|
||||||
// Stop condition after the transfer.
|
// Stop condition after the transfer.
|
||||||
// Normal transfer with start condition, address, data and stop condition.
|
// Normal transfer with start condition, address, data and stop condition.
|
||||||
CAMBUS_XFER_NO_FLAGS = (0<<0),
|
CAMBUS_XFER_NO_FLAGS = (0<<0),
|
||||||
@ -24,7 +33,17 @@ enum cambus_xfer_flags {
|
|||||||
// No stop condition after the transfer.
|
// No stop condition after the transfer.
|
||||||
// This flag allows chaining multiple writes or reads with the same direction.
|
// This flag allows chaining multiple writes or reads with the same direction.
|
||||||
CAMBUS_XFER_SUSPEND = (1<<1),
|
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_init(cambus_t *bus, uint32_t bus_id, uint32_t speed);
|
||||||
int cambus_deinit(cambus_t *bus);
|
int cambus_deinit(cambus_t *bus);
|
||||||
int cambus_scan(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)
|
int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
||||||
{
|
{
|
||||||
bus->id = bus_id;
|
bus->id = bus_id;
|
||||||
bus->speed = speed;
|
|
||||||
bus->initialized = false;
|
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) {
|
switch (bus_id) {
|
||||||
case 0: {
|
case 0: {
|
||||||
bus->scl_pin = TWI0_SCL_PIN;
|
bus->scl_pin = TWI0_SCL_PIN;
|
||||||
bus->sda_pin = TWI0_SDA_PIN;
|
bus->sda_pin = TWI0_SDA_PIN;
|
||||||
nrfx_twi_t _twi = NRFX_TWI_INSTANCE(0);
|
bus->i2c = (nrfx_twi_t) NRFX_TWI_INSTANCE(0);
|
||||||
memcpy(&bus->twi, &_twi, sizeof(nrfx_twi_t));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
bus->scl_pin = TWI1_SCL_PIN;
|
bus->scl_pin = TWI1_SCL_PIN;
|
||||||
bus->sda_pin = TWI1_SDA_PIN;
|
bus->sda_pin = TWI1_SDA_PIN;
|
||||||
nrfx_twi_t _twi = NRFX_TWI_INSTANCE(1);
|
bus->i2c = (nrfx_twi_t) NRFX_TWI_INSTANCE(1);
|
||||||
memcpy(&bus->twi, &_twi, sizeof(nrfx_twi_t));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -47,17 +58,17 @@ int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
|||||||
nrfx_twi_config_t config = {
|
nrfx_twi_config_t config = {
|
||||||
.scl = bus->scl_pin,
|
.scl = bus->scl_pin,
|
||||||
.sda = bus->sda_pin,
|
.sda = bus->sda_pin,
|
||||||
.frequency = speed,
|
.frequency = bus->speed,
|
||||||
.interrupt_priority = 4,
|
.interrupt_priority = 4,
|
||||||
.hold_bus_uninit = false
|
.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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This bus needs to be enabled for suspended transfers.
|
// This bus needs to be enabled for suspended transfers.
|
||||||
nrfx_twi_enable(&bus->twi);
|
nrfx_twi_enable(&bus->i2c);
|
||||||
|
|
||||||
bus->initialized = true;
|
bus->initialized = true;
|
||||||
return 0;
|
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)
|
int cambus_deinit(cambus_t *bus)
|
||||||
{
|
{
|
||||||
if (bus->initialized) {
|
if (bus->initialized) {
|
||||||
nrfx_twi_disable(&bus->twi);
|
nrfx_twi_disable(&bus->i2c);
|
||||||
nrfx_twi_uninit(&bus->twi);
|
nrfx_twi_uninit(&bus->i2c);
|
||||||
bus->initialized = false;
|
bus->initialized = false;
|
||||||
}
|
}
|
||||||
return 0;
|
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);
|
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;
|
ret = -1;
|
||||||
}
|
}
|
||||||
return ret;
|
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);
|
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;
|
ret = -1;
|
||||||
}
|
}
|
||||||
return ret;
|
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
|
||||||
#endif // I2C4
|
#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)
|
int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
||||||
{
|
{
|
||||||
bus->id = bus_id;
|
bus->id = bus_id;
|
||||||
bus->speed = speed;
|
|
||||||
bus->i2c = NULL;
|
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) {
|
switch (bus_id) {
|
||||||
#if defined(I2C1)
|
#if defined(I2C1)
|
||||||
@ -100,27 +114,27 @@ int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
|||||||
return -1;
|
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.
|
// Our code only knows about these two I2Cs instances.
|
||||||
if (bus->i2c->Instance == FIR_I2C) {
|
if (bus->i2c->Instance == FIR_I2C) {
|
||||||
bus->port = FIR_I2C_PORT;
|
bus->scl_pin = (omv_gpio_t) {FIR_I2C_SCL_PIN, FIR_I2C_PORT};
|
||||||
bus->scl_pin = FIR_I2C_SCL_PIN;
|
bus->sda_pin = (omv_gpio_t) {FIR_I2C_SDA_PIN, FIR_I2C_PORT};
|
||||||
bus->sda_pin = FIR_I2C_SDA_PIN;
|
|
||||||
} else if (bus->i2c->Instance == ISC_I2C) {
|
} else if (bus->i2c->Instance == ISC_I2C) {
|
||||||
bus->port = ISC_I2C_PORT;
|
bus->scl_pin = (omv_gpio_t) {ISC_I2C_SCL_PIN, ISC_I2C_PORT};
|
||||||
bus->scl_pin = ISC_I2C_SCL_PIN;
|
bus->sda_pin = (omv_gpio_t) {ISC_I2C_SDA_PIN, ISC_I2C_PORT};
|
||||||
bus->sda_pin = ISC_I2C_SDA_PIN;
|
|
||||||
} else {
|
|
||||||
bus->port = NULL;
|
|
||||||
bus->scl_pin = 0;
|
|
||||||
bus->sda_pin = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the I2C handle
|
// Configure the I2C handle
|
||||||
bus->i2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
bus->i2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||||
#if !defined(STM32F4)
|
#if !defined(STM32F4)
|
||||||
bus->i2c->Init.Timing = speed;
|
bus->i2c->Init.Timing = bus->speed;
|
||||||
#else
|
#else
|
||||||
bus->i2c->Init.ClockSpeed = speed;
|
bus->i2c->Init.ClockSpeed = bus->speed;
|
||||||
bus->i2c->Init.DutyCycle = I2C_DUTYCYCLE_2;
|
bus->i2c->Init.DutyCycle = I2C_DUTYCYCLE_2;
|
||||||
#endif
|
#endif
|
||||||
bus->i2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
|
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);
|
HAL_I2C_DeInit(bus->i2c);
|
||||||
if (HAL_I2C_Init(bus->i2c) != HAL_OK) {
|
if (HAL_I2C_Init(bus->i2c) != HAL_OK) {
|
||||||
bus->i2c = NULL;
|
bus->i2c = NULL;
|
||||||
bus->port = NULL;
|
bus->scl_pin = (omv_gpio_t) {0, 0};
|
||||||
|
bus->sda_pin = (omv_gpio_t) {0, 0};
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +179,8 @@ int cambus_init(cambus_t *bus, uint32_t bus_id, uint32_t speed)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bus->initialized = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,12 +246,14 @@ static int cambus_wait_timeout(cambus_t *bus, uint32_t timeout)
|
|||||||
|
|
||||||
int cambus_deinit(cambus_t *bus)
|
int cambus_deinit(cambus_t *bus)
|
||||||
{
|
{
|
||||||
if (bus->i2c && bus->i2c->Instance) {
|
if (bus->initialized) {
|
||||||
HAL_I2C_DeInit(bus->i2c);
|
HAL_I2C_DeInit(bus->i2c);
|
||||||
bus->i2c->Instance = NULL;
|
bus->i2c->Instance = NULL;
|
||||||
}
|
}
|
||||||
bus->i2c = 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;
|
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)
|
int cambus_pulse_scl(cambus_t *bus)
|
||||||
{
|
{
|
||||||
if (bus->port) {
|
if (bus->initialized && bus->scl_pin.port) {
|
||||||
// Configure SCL as GPIO
|
// Configure SCL as GPIO
|
||||||
GPIO_InitTypeDef GPIO_InitStructure;
|
GPIO_InitTypeDef GPIO_InitStructure;
|
||||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
|
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
|
||||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
GPIO_InitStructure.Pin = bus->scl_pin;
|
GPIO_InitStructure.Pin = bus->scl_pin.pin;
|
||||||
HAL_GPIO_Init(bus->port, &GPIO_InitStructure);
|
HAL_GPIO_Init(bus->scl_pin.port, &GPIO_InitStructure);
|
||||||
|
|
||||||
// Pulse SCL to recover stuck device.
|
// Pulse SCL to recover stuck device.
|
||||||
for (int i=0; i<10000; i++) {
|
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);
|
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);
|
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