arch: samd5e5:

- Add MTD progmem support.
- NVM USER PAGE IOCTLs support.

boards: metro-m4  Add support for:

- SmartFS inicialization.
- AT24 EEPROM.
- GPIO dev support.
- BQ27426 gauge inicialization.

drives: power
- Add BQ27426 fuel gauge support.

Testing:
- Build check only.

Signed-off-by: Leomar Mateus Radke  <leomar@falker.com.br>
This commit is contained in:
leomarradke 2020-08-20 01:07:22 -03:00 committed by Alan Carvalho de Assis
parent 946601da2f
commit 8a2c480a48
18 changed files with 2761 additions and 22 deletions

View File

@ -549,6 +549,26 @@ config SAMD5E5_WDT
bool "Watchdog Timer" bool "Watchdog Timer"
default n default n
menuconfig SAMD5E5_PROGMEM
bool "FLASH program memory"
default n
select ARCH_HAVE_PROGMEM
---help---
Enable support FLASH interfaces as defined in include/nuttx/progmem.h
if SAMD5E5_PROGMEM
config SAMD5E5_PROGMEM_NSECTORS
int "Number of 32Kbytes sectors"
default 2
range 1 32
---help---
This is the number of 32Kbytes FLASH sectors at the end of the program
flash memory that will be reserved for use with by the interfaces
prototyped in include/nuttx/progmem.h
endif # SAMD5E5_PROGMEM
endmenu # SAMD5x/E5x Peripheral Support endmenu # SAMD5x/E5x Peripheral Support
config SAMD5E5_DMAC_NDESC config SAMD5E5_DMAC_NDESC

View File

@ -177,3 +177,7 @@ endif
ifeq ($(CONFIG_SAMD5E5_RTC),y) ifeq ($(CONFIG_SAMD5E5_RTC),y)
CHIP_CSRCS += sam_rtc.c CHIP_CSRCS += sam_rtc.c
endif endif
ifeq ($(CONFIG_SAMD5E5_PROGMEM),y)
CHIP_CSRCS += sam_progmem.c
endif

View File

@ -66,11 +66,11 @@
#define SAM_NVMCTRL_SEECFG_OFFSET 0x002a /* SmartEEPROM configuration register */ #define SAM_NVMCTRL_SEECFG_OFFSET 0x002a /* SmartEEPROM configuration register */
#define SAM_NVMCTRL_SEESTAT_OFFSET 0x002c /* SmartEEPROM status register */ #define SAM_NVMCTRL_SEESTAT_OFFSET 0x002c /* SmartEEPROM status register */
/* NVMCTRL register addresses ***************************************************************/ /* NVMCTRL register addresses ***************************************************************/
#define SAM_NVMCTRL_CTRLA (SAM_NVMCTRL_BASE + SAM_NVMCTRL_CTRLA_OFFSET) #define SAM_NVMCTRL_CTRLA (SAM_NVMCTRL_BASE + SAM_NVMCTRL_CTRLA_OFFSET)
#define SAM_NVMCTRL_CTRLB (SAM_NVMCTRL_BASE + SAM_NVMCTRL_CTRLB_OFFSET) #define SAM_NVMCTRL_CTRLB (SAM_NVMCTRL_BASE + SAM_NVMCTRL_CTRLB_OFFSET)
#define SAM_NVMCTRL_PARAM (SAM_NVMCTRL_BASE + SAM_NVMCTRL_PARAM_OFFSET)
#define SAM_NVMCTRL_INTENCLR (SAM_NVMCTRL_BASE + SAM_NVMCTRL_INTENCLR_OFFSET) #define SAM_NVMCTRL_INTENCLR (SAM_NVMCTRL_BASE + SAM_NVMCTRL_INTENCLR_OFFSET)
#define SAM_NVMCTRL_INTENSET (SAM_NVMCTRL_BASE + SAM_NVMCTRL_INTENSET_OFFSET) #define SAM_NVMCTRL_INTENSET (SAM_NVMCTRL_BASE + SAM_NVMCTRL_INTENSET_OFFSET)
#define SAM_NVMCTRL_INTFLAG (SAM_NVMCTRL_BASE + SAM_NVMCTRL_INTFLAG_OFFSET) #define SAM_NVMCTRL_INTFLAG (SAM_NVMCTRL_BASE + SAM_NVMCTRL_INTFLAG_OFFSET)
@ -95,8 +95,8 @@
# define NVMCTRL_CTRLA_WMODE_MAN (0 << NVMCTRL_CTRLA_WMODE_SHIFT) /* Manual Write */ # define NVMCTRL_CTRLA_WMODE_MAN (0 << NVMCTRL_CTRLA_WMODE_SHIFT) /* Manual Write */
# define NVMCTRL_CTRLA_WMODE_ADW (1 << NVMCTRL_CTRLA_WMODE_SHIFT) /* Automatic Double Word Write */ # define NVMCTRL_CTRLA_WMODE_ADW (1 << NVMCTRL_CTRLA_WMODE_SHIFT) /* Automatic Double Word Write */
# define NVMCTRL_CTRLA_WMODE_AQW (2 << NVMCTRL_CTRLA_WMODE_SHIFT) /* Automatic Quad Word */ # define NVMCTRL_CTRLA_WMODE_AQW (2 << NVMCTRL_CTRLA_WMODE_SHIFT) /* Automatic Quad Word */
# define NVMCTRL_CTRLA_WMODE_AP (2 << NVMCTRL_CTRLA_WMODE_SHIFT) /* Automatic Page Write */ # define NVMCTRL_CTRLA_WMODE_AP (3 << NVMCTRL_CTRLA_WMODE_SHIFT) /* Automatic Page Write */
#define NVMCTRL_CTRLA_PRM_SHIFT (8) /* Bits 8-9: Power Reduction Mode during Sleep */ #define NVMCTRL_CTRLA_PRM_SHIFT (6) /* Bits 8-9: Power Reduction Mode during Sleep */
#define NVMCTRL_CTRLA_PRM_MASK (3 << NVMCTRL_CTRLA_PRM_SHIFT) #define NVMCTRL_CTRLA_PRM_MASK (3 << NVMCTRL_CTRLA_PRM_SHIFT)
# define NVMCTRL_CTRLA_PRM_SEMIAUTO (0 << NVMCTRL_CTRLA_PRM_SHIFT) /* Enter low power on STANDBY/SPRM cmd; # define NVMCTRL_CTRLA_PRM_SEMIAUTO (0 << NVMCTRL_CTRLA_PRM_SHIFT) /* Enter low power on STANDBY/SPRM cmd;
* Exit on first access */ * Exit on first access */
@ -160,9 +160,10 @@
# define NVMCTRL_PARAM_PSZ_1KB (7 << NVMCTRL_PARAM_PSZ_SHIFT) /* 1024 bytes */ # define NVMCTRL_PARAM_PSZ_1KB (7 << NVMCTRL_PARAM_PSZ_SHIFT) /* 1024 bytes */
#define NVMCTRL_PARAM_SEE_ (1 << 31) /* Bit 31: SmartEEPROM Supported */ #define NVMCTRL_PARAM_SEE_ (1 << 31) /* Bit 31: SmartEEPROM Supported */
/* Interrupt clear register */ /* Interrupt clear register
/* Interrupt set register */ * Interrupt set register
/* Interface flags status and clear register */ * Interface flags status and clear register
*/
#define NVMCTRL_INT_DONE (1 << 0) /* Bit 0: Command done interrupt */ #define NVMCTRL_INT_DONE (1 << 0) /* Bit 0: Command done interrupt */
#define NVMCTRL_INT_ADDRE (1 << 1) /* Bit 1: Address error interrupt */ #define NVMCTRL_INT_ADDRE (1 << 1) /* Bit 1: Address error interrupt */
@ -247,7 +248,7 @@
********************************************************************************************/ ********************************************************************************************/
/******************************************************************************************** /********************************************************************************************
* Public Functions * Public Functions Prototypes
********************************************************************************************/ ********************************************************************************************/
#endif /* __ARCH_ARM_SRC_SAMD5E5_HARDWARE_SAM_NVMCTRL_H */ #endif /* __ARCH_ARM_SRC_SAMD5E5_HARDWARE_SAM_NVMCTRL_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/****************************************************************************
* arch/arm/src/samd5e5/sam_progmem.h
*
* 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.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMD5E5_SAM_PROGMEM_H
#define __ARCH_ARM_SRC_SAMD5E5_SAM_PROGMEM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "arm_arch.h"
#include "hardware/sam_nvmctrl.h"
#include <nuttx/progmem.h>
/****************************************************************************
* Inline Functions
****************************************************************************/
/****************************************************************************
* Name: sam_progmem_initialize
*
* Description:
* Call to initialize FLASH programming memory access
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void sam_progmem_initialize(void);
#endif /* __ARCH_ARM_SRC_SAMD5E5_SAM_PROGMEM_H */

View File

@ -45,6 +45,36 @@ config METRO_M4_32KHZXTAL
slow clock source. This option will select instead XOSC32 as the slow clock source. This option will select instead XOSC32 as the
slow clock source. slow clock source.
config METRO_M4_AT24_BLOCKMOUNT
bool "AT24 Serial EEPROM auto-mount"
default n
depends on MTD_AT24XX
---help---
Automatically initialize the AT24 I2C EEPROM driver when NSH starts.
choice
prompt "AT24 serial EPPROM configuration"
default METRO_M4_AT24_FTL
depends on METRO_M4_AT24_BLOCKMOUNT
config METRO_M4_AT24_FTL
bool "Create AT24 block driver"
---help---
Create the MTD driver for the AT24 and "wrap" the AT24 as a standard
block driver that could then, for example, be mounted using FAT or
any other file system. Any file system may be used, but there will
be no wear-leveling.
config METRO_M4_AT24_NXFFS
bool "Create AT24 NXFFS file system"
depends on FS_NXFFS
---help---
Create the MTD driver for the AT24 and mount the AT24 device as
a wear-leveling, NuttX FLASH file system (NXFFS). The downside of
NXFFS is that it can be very slow.
endchoice # AT24 serial EPPROM configuration
if FS_AUTOMOUNTER if FS_AUTOMOUNTER
config METRO_M4_USB_AUTOMOUNT config METRO_M4_USB_AUTOMOUNT
bool "USB automounter" bool "USB automounter"

View File

@ -69,6 +69,21 @@ endif
ifeq ($(CONFIG_SAMD5E5_SERCOM5_ISI2C),y) ifeq ($(CONFIG_SAMD5E5_SERCOM5_ISI2C),y)
CSRCS += sam_i2c.c CSRCS += sam_i2c.c
ifeq ($(CONFIG_MTD_AT24XX),y)
CSRCS += sam_at24.c
endif
endif
ifeq ($(CONFIG_FS_SMARTFS),y)
CSRCS += sam_smartfs.c
endif
ifeq ($(CONFIG_BQ27426),y)
CSRCS += sam_bq27426.c
endif
ifeq ($(CONFIG_DEV_GPIO),y)
CSRCS += sam_gpio.c
endif endif
include $(TOPDIR)/boards/Board.mk include $(TOPDIR)/boards/Board.mk

View File

@ -68,8 +68,47 @@
* D13 PA16 GPIO output * D13 PA16 GPIO output
*/ */
#define PORT_RED_LED (PORT_OUTPUT | PORT_PULL_NONE | PORT_OUTPUT_SET | \ #define PORT_RED_LED (PORT_OUTPUT | PORT_PULL_NONE | PORT_OUTPUT_SET | PORTA | PORT_PIN16)
PORTA | PORT_PIN16)
#define PORT_D8 (PORT_OUTPUT | PORT_PULL_NONE | PORT_OUTPUT_SET | PORTA | PORT_PIN21)
#define PORT_D9 (PORT_INTERRUPT | PORT_PULL_NONE | PORT_INT_RISING | PORTA | PORT_PIN20)
#define PORT_D10 (PORT_INPUT | PORT_PULL_NONE | PORT_INT_CHANGE | PORTA | PORT_PIN18)
/* GPIO pins used by the GPIO Subsystem */
#define BOARD_NGPIOIN 1 /* Amount of GPIO Input pins */
#define BOARD_NGPIOOUT 1 /* Amount of GPIO Output pins */
#define BOARD_NGPIOINT 1 /* Amount of GPIO Input w/ Interruption pins */
#define HAVE_AT24 1
/* AT24 Serial EEPROM */
#define AT24_I2C_BUS 5 /* AT24C256 connected to I2C5 */
#define AT24_MINOR 0
#if !defined(CONFIG_MTD_AT24XX) || !defined(CONFIG_SAMD5E5_SERCOM5_ISI2C)
# undef HAVE_AT24
#endif
/* Can't support AT24 features if mountpoints are disabled or if we were not
* asked to mount the AT25 part
*/
#if defined(CONFIG_DISABLE_MOUNTPOINT) || \
!defined(CONFIG_METRO_M4_AT24_BLOCKMOUNT)
# undef HAVE_AT24
#endif
/* On-chip Programming Memory */
#if defined(CONFIG_SAMD5E5_PROGMEM) || defined(CONFIG_MTD_PROGMEM)
#define HAVE_PROGMEM_CHARDEV
#endif
/* This is the on-chip progmem memroy driver minor number */
#define PROGMEM_MTD_MINOR 0
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
@ -123,5 +162,17 @@ FAR struct i2c_master_s *g_i2c5_dev;
int metro_m4_i2cdev_initialize(void); int metro_m4_i2cdev_initialize(void);
#endif #endif
#ifdef CONFIG_FS_SMARTFS
int sam_smartfs_initialize(void);
#endif
#ifdef CONFIG_BQ27426
int sam_bq27426_initialize(FAR const char *devname);
#endif
#ifdef CONFIG_DEV_GPIO
int sam_gpio_initialize(void);
#endif
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __BOARDS_ARM_SAMD5E5_METRO_M4_SRC_METRO_M4_H */ #endif /* __BOARDS_ARM_SAMD5E5_METRO_M4_SRC_METRO_M4_H */

View File

@ -0,0 +1,126 @@
/****************************************************************************
* boards/arm/samd5e5/metro-m4/src/sam_at24.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/mount.h>
#include <stdbool.h>
#include <stdio.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/mtd/mtd.h>
#include <nuttx/fs/nxffs.h>
#include "metro-m4.h"
#ifdef HAVE_AT24
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sam_at24_automount
*
* Description:
* Initialize and configure the AT24 serial EEPROM
*
****************************************************************************/
extern FAR struct i2c_master_s *g_i2c5_dev;
int sam_at24_automount(int minor)
{
FAR struct mtd_dev_s *mtd;
static bool initialized = false;
int ret;
/* Have we already initialized? */
if (!initialized)
{
/* Now bind the I2C interface to the AT24 I2C EEPROM driver */
finfo("Bind the AT24 EEPROM driver to I2C%d\n", AT24_I2C_BUS);
mtd = at24c_initialize(g_i2c5_dev);
if (!mtd)
{
ferr("ERROR: Failed to bind TWI%d to the AT24 EEPROM driver\n",
AT24_I2C_BUS);
return -ENODEV;
}
#if defined(CONFIG_METRO_M4_AT24_FTL)
/* And finally, use the FTL layer
* to wrap the MTD driver as a block driver
*/
finfo("Initialize the FTL layer to create /dev/mtdblock%d\n",
AT24_MINOR);
ret = ftl_initialize(AT24_MINOR, mtd);
if (ret < 0)
{
ferr("ERROR: Failed to initialize the FTL layer: %d\n", ret);
return ret;
}
#elif defined(CONFIG_METRO_M4_AT24_NXFFS)
/* Initialize to provide NXFFS on the MTD interface */
finfo("Initialize the NXFFS file system\n");
ret = nxffs_initialize(mtd);
if (ret < 0)
{
ferr("ERROR: NXFFS initialization failed: %d\n", ret);
return ret;
}
/* Mount the file system at /mnt/at24 */
finfo("Mount the NXFFS file system at /dev/at24\n");
ret = mount(NULL, "/mnt/at24", "nxffs", 0, NULL);
if (ret < 0)
{
ferr("ERROR: Failed to mount the NXFFS volume: %d\n",
errno);
return ret;
}
#endif
/* Now we are initialized */
initialized = true;
}
return OK;
}
#endif /* HAVE_AT24 */

View File

@ -0,0 +1,75 @@
/****************************************************************************
* boards/arm/samd5e5/metro-m4/src/sam_bq27426.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/power/battery_gauge.h>
#include <nuttx/power/bq27426.h>
#include <nuttx/power/battery_ioctl.h>
#include "arm_arch.h"
#include "chip.h"
#include "hardware/sam_i2c_master.h"
#include "metro-m4.h"
#include <arch/board/board.h>
#include "sam_config.h"
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef CONFIG_BQ27426
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sam_bq24298_initialize
*
* Description:
* Called to configure bq24298
*
****************************************************************************/
int sam_bq27426_initialize(FAR const char *devname)
{
FAR struct battery_gauge_dev_s *bq27426_m4;
bq27426_m4 = (FAR struct battery_gauge_dev_s *)bq27426_initialize(
g_i2c5_dev,
BQ27426_I2C_ADDRESS,
100000);
return battery_gauge_register(devname, bq27426_m4);
}
#endif /* CONFIG_BQ27426 */

View File

@ -64,6 +64,11 @@
# include <nuttx/usb/usbmonitor.h> # include <nuttx/usb/usbmonitor.h>
#endif #endif
#ifdef CONFIG_BQ27426
#include <nuttx/power/battery_gauge.h>
#include <nuttx/power/battery_ioctl.h>
#endif
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
@ -98,7 +103,7 @@ int sam_bringup(void)
ret = mount(NULL, PROCFS_MOUNTPOINT, "procfs", 0, NULL); ret = mount(NULL, PROCFS_MOUNTPOINT, "procfs", 0, NULL);
if (ret < 0) if (ret < 0)
{ {
syslot(LOG_ERR, "ERROR: Failed to mount procfs at %s: %d\n", syslog(LOG_ERR, "ERROR: Failed to mount procfs at %s: %d\n",
PROCFS_MOUNTPOINT, ret); PROCFS_MOUNTPOINT, ret);
} }
#endif #endif
@ -137,12 +142,47 @@ int sam_bringup(void)
} }
#endif #endif
#ifdef CONFIG_FS_SMARTFS
/* Initialize Smart File System (SMARTFS) */
ret = sam_smartfs_initialize();
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: Failed to mount smartfs %d\n", ret);
return ret;
}
/* Mount the file system at /mnt/nvm */
ret = mount("/dev/smart0", "/mnt/nvm", "smartfs", 0, NULL);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: Failed to mount the SmartFS volume: %d\n",
ret);
return ret;
}
#endif
#ifdef CONFIG_FS_AUTOMOUNTER #ifdef CONFIG_FS_AUTOMOUNTER
/* Initialize the auto-mounter */ /* Initialize the auto-mounter */
sam_automount_initialize(); sam_automount_initialize();
#endif #endif
#ifdef CONFIG_BQ27426
/* Configure and initialize the BQ2426 distance sensor */
ret = sam_bq27426_initialize("/dev/batt1");
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: sam_bq27426_initialize() failed: %d\n", ret);
}
#endif
#ifdef CONFIG_DEV_GPIO
ret = sam_gpio_initialize();
#endif
UNUSED(ret); UNUSED(ret);
return OK; return OK;
} }

View File

@ -0,0 +1,341 @@
/****************************************************************************
* boards/arm/samd5e5/metro-m4/src/sam_gpio.c
*
* Copyright 2020 Falker Automacao Agricola LTDA.
* Author: Leomar Mateus Radke <leomar@falker.com.br>
* Author: Ricardo Wartchow <wartchow@gmail.com>
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/clock.h>
#include <nuttx/wdog.h>
#include <nuttx/ioexpander/gpio.h>
#include <nuttx/irq.h>
#include "irq/irq.h"
#include "chip.h"
#include <arch/board/board.h>
#include "sam_config.h"
#include "metro-m4.h"
#include "sam_port.h"
#include "sam_eic.h"
#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF)
/****************************************************************************
* Private Types
****************************************************************************/
struct samgpio_dev_s
{
struct gpio_dev_s gpio;
uint8_t id;
};
struct samgpint_dev_s
{
struct samgpio_dev_s samgpio;
pin_interrupt_t callback;
};
irqstate_t flags;
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
#if BOARD_NGPIOIN > 0
static int gpin_read(FAR struct gpio_dev_s *dev, FAR bool *value);
#endif
static int gpout_read(FAR struct gpio_dev_s *dev, FAR bool *value);
static int gpout_write(FAR struct gpio_dev_s *dev, bool value);
static int gpint_read(FAR struct gpio_dev_s *dev, FAR bool *value);
static int gpint_attach(FAR struct gpio_dev_s *dev,
pin_interrupt_t callback);
static int gpint_enable(FAR struct gpio_dev_s *dev, bool enable);
/****************************************************************************
* Private Data
****************************************************************************/
#if BOARD_NGPIOIN > 0
static const struct gpio_operations_s gpin_ops =
{
.go_read = gpin_read,
.go_write = NULL,
.go_attach = NULL,
.go_enable = NULL,
};
#endif
static const struct gpio_operations_s gpout_ops =
{
.go_read = gpout_read,
.go_write = gpout_write,
.go_attach = NULL,
.go_enable = NULL,
};
static const struct gpio_operations_s gpint_ops =
{
.go_read = gpint_read,
.go_write = NULL,
.go_attach = gpint_attach,
.go_enable = gpint_enable,
};
static const int g_extint[1] = /* SAM_IRQ_EXTINT0 offset! */
{
4, /* PORT_D9 - PA20 - EXTINT 4 */
};
#if BOARD_NGPIOIN > 0
/* This array maps the GPIO pins used as INPUT */
static const uint32_t g_gpioinputs[BOARD_NGPIOIN] =
{
PORT_D10,
};
static struct samgpio_dev_s g_gpin[BOARD_NGPIOIN];
#endif
#if BOARD_NGPIOOUT
/* This array maps the GPIO pins used as OUTPUT */
static const uint32_t g_gpiooutputs[BOARD_NGPIOOUT] =
{
PORT_D8,
};
static struct samgpio_dev_s g_gpout[BOARD_NGPIOOUT];
#endif
#if BOARD_NGPIOINT > 0
/* This array maps the GPIO pins used as INTERRUPT INPUTS */
static const uint32_t g_gpiointinputs[BOARD_NGPIOINT] =
{
PORT_D9
};
static struct samgpint_dev_s g_gpint[BOARD_NGPIOINT];
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
static int samgpio_interrupt(int irq, void *context, void *arg)
{
FAR struct samgpint_dev_s *samgpint = (FAR struct samgpint_dev_s *)arg;
DEBUGASSERT(samgpint != NULL && samgpint->callback != NULL);
gpioinfo("Interrupt! callback=%p\n", samgpint->callback);
samgpint->callback(&samgpint->samgpio.gpio, samgpint->samgpio.id);
return OK;
}
#if BOARD_NGPIOIN > 0
static int gpin_read(FAR struct gpio_dev_s *dev, FAR bool *value)
{
FAR struct samgpio_dev_s *samgpio = (FAR struct samgpio_dev_s *)dev;
DEBUGASSERT(samgpio != NULL && value != NULL);
DEBUGASSERT(samgpio->id < BOARD_NGPIOIN);
gpioinfo("Reading...\n");
*value = sam_portread(g_gpioinputs[samgpio->id]);
return OK;
}
#endif
static int gpout_read(FAR struct gpio_dev_s *dev, FAR bool *value)
{
FAR struct samgpio_dev_s *samgpio = (FAR struct samgpio_dev_s *)dev;
DEBUGASSERT(samgpio != NULL && value != NULL);
DEBUGASSERT(samgpio->id < BOARD_NGPIOOUT);
gpioinfo("Reading...\n");
*value = sam_portread(g_gpiooutputs[samgpio->id]);
return OK;
}
static int gpout_write(FAR struct gpio_dev_s *dev, bool value)
{
FAR struct samgpio_dev_s *samgpio = (FAR struct samgpio_dev_s *)dev;
DEBUGASSERT(samgpio != NULL);
DEBUGASSERT(samgpio->id < BOARD_NGPIOOUT);
gpioinfo("Writing %d\n", (int)value);
sam_portwrite(g_gpiooutputs[samgpio->id], value);
return OK;
}
static int gpint_read(FAR struct gpio_dev_s *dev, FAR bool *value)
{
FAR struct samgpint_dev_s *samgpint = (FAR struct samgpint_dev_s *)dev;
DEBUGASSERT(samgpint != NULL && value != NULL);
DEBUGASSERT(samgpint->samgpio.id < BOARD_NGPIOINT);
gpioinfo("Reading int pin...\n");
*value = sam_portread(g_gpiointinputs[samgpint->samgpio.id]);
return OK;
}
static int gpint_attach(FAR struct gpio_dev_s *dev,
pin_interrupt_t callback)
{
FAR struct samgpint_dev_s *samgpint = (FAR struct samgpint_dev_s *)dev;
gpioinfo("Attaching the callback\n");
flags = enter_critical_section();
/* Make sure the interrupt is disabled */
int ret = irq_attach(SAM_IRQ_EXTINT0 + g_extint[samgpint->samgpio.id],
samgpio_interrupt, &g_gpint[samgpint->samgpio.id]);
if (ret == OK)
{
/* Configure the interrupt edge sensitivity
* in CONFIGn register of the EIC
*/
sam_eic_configure(g_extint[samgpint->samgpio.id],
g_gpiointinputs[samgpint->samgpio.id]);
}
leave_critical_section(flags);
gpioinfo("Attach %p\n", callback);
samgpint->callback = callback;
return OK;
}
static int gpint_enable(FAR struct gpio_dev_s *dev, bool enable)
{
FAR struct samgpint_dev_s *samgpint = (FAR struct samgpint_dev_s *)dev;
flags = enter_critical_section();
if (enable)
{
if (samgpint->callback != NULL)
{
gpioinfo("Enabling the interrupt\n");
up_enable_irq(SAM_IRQ_EXTINT0 + g_extint[samgpint->samgpio.id]);
}
}
else
{
up_disable_irq(SAM_IRQ_EXTINT0 + g_extint[samgpint->samgpio.id]);
gpioinfo("Disable the interrupt\n");
}
leave_critical_section(flags);
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sam_gpio_initialize
*
* Description:
* Initialize GPIO drivers for use with /apps/examples/gpio
*
****************************************************************************/
int sam_gpio_initialize(void)
{
int i;
int pincount = 0;
#if BOARD_NGPIOIN > 0
for (i = 0; i < BOARD_NGPIOIN; i++)
{
/* Setup and register the GPIO pin */
g_gpin[i].gpio.gp_pintype = GPIO_INPUT_PIN;
g_gpin[i].gpio.gp_ops = &gpin_ops;
g_gpin[i].id = i;
(void)gpio_pin_register(&g_gpin[i].gpio, pincount);
/* Configure the pin that will be used as input */
sam_portconfig(g_gpioinputs[i]);
pincount++;
}
#endif
#if BOARD_NGPIOOUT > 0
for (i = 0; i < BOARD_NGPIOOUT; i++)
{
/* Setup and register the GPIO pin */
g_gpout[i].gpio.gp_pintype = GPIO_OUTPUT_PIN;
g_gpout[i].gpio.gp_ops = &gpout_ops;
g_gpout[i].id = i;
(void)gpio_pin_register(&g_gpout[i].gpio, pincount);
/* Configure the pin that will be used as output */
sam_portconfig(g_gpiooutputs[i]);
pincount++;
}
#endif
#if BOARD_NGPIOINT > 0
for (i = 0; i < BOARD_NGPIOINT; i++)
{
/* Setup and register the GPIO pin */
g_gpint[i].samgpio.gpio.gp_pintype = GPIO_INTERRUPT_PIN;
g_gpint[i].samgpio.gpio.gp_ops = &gpint_ops;
g_gpint[i].samgpio.id = i;
(void)gpio_pin_register(&g_gpint[i].samgpio.gpio, pincount);
/* Configure the pin that will be used as interrupt input */
sam_portconfig(g_gpiointinputs[i]);
pincount++;
}
#endif
return 0;
}
#endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */

View File

@ -0,0 +1,235 @@
/****************************************************************************
* boards/arm/samd5e5/metro-m4/src/sam_smartfs.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <debug.h>
#include "arm_arch.h"
#include "chip.h"
#include <arch/board/board.h>
#include "metro-m4.h"
#ifdef CONFIG_MTD
# include <nuttx/mtd/mtd.h>
# include <nuttx/mtd/configdata.h>
# include <nuttx/drivers/drivers.h>
# include "sam_progmem.h"
#endif
#ifdef CONFIG_FS_SMARTFS
# include <nuttx/fs/smart.h>
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_FS_SMARTFS
int ret;
FAR struct mtd_dev_s *mtd;
FAR struct mtd_geometry_s geo;
#endif
#if defined(CONFIG_MTD_PARTITION_NAMES)
const char *partname = "mnta";
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef CONFIG_FS_SMARTFS
int sam_smartfs_initialize(void)
{
/* Initialize the SAMD5E5 FLASH programming memory library */
sam_progmem_initialize();
/* Create an instance of the SAMD5E5 FLASH program memory device driver */
mtd = progmem_initialize();
if (!mtd)
{
syslog(LOG_ERR, "ERROR: progmem_initialize failed\n");
}
ret = mtd->ioctl(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo));
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: mtd->ioctl failed: %d\n", ret);
return ret;
}
#ifdef CONFIG_MTD_PARTITION
{
int partno;
int partsize;
int partoffset;
int partszbytes;
int erasesize;
const char *partstring = "256";
const char *ptr;
FAR struct mtd_dev_s *mtd_part;
char partref[4];
/* Now create a partition on the FLASH device */
partno = 0;
ptr = partstring;
partoffset = 0;
/* Get the Flash erase size */
erasesize = geo.erasesize;
while (*ptr != '\0')
{
/* Get the partition size */
partsize = atoi(ptr);
partszbytes = (partsize << 10); /* partsize is defined in KB */
printf("partsize %d partszbytes %d\n", partsize, partszbytes);
/* Check if partition size is bigger then erase block */
if (partszbytes < erasesize)
{
syslog(LOG_ERR,
"ERROR: Partition size is lesser than erasesize!\n");
return -1;
}
/* Check if partition size is multiple of erase block */
if ((partszbytes % erasesize) != 0)
{
syslog(LOG_ERR,
"ERROR: Partition size is not multiple of erasesize!\n");
return -1;
}
mtd_part = mtd_partition(mtd, partoffset,
partszbytes / erasesize);
partoffset += partszbytes / erasesize;
/* Test if this is the config partition */
#if defined CONFIG_MTD_CONFIG
if (partno == 0)
{
/* Register the partition as the config device */
mtdconfig_register(mtd_part);
}
else
#endif
{
/* Now initialize a SMART Flash block device
* and bind it to the MTD device.
*/
#if defined(CONFIG_MTD_SMART) && defined(CONFIG_FS_SMARTFS)
sprintf(partref, "p%d", partno);
smart_initialize(0, mtd_part, partref);
#endif
}
/* Set the partition name */
#ifdef CONFIG_MTD_PARTITION_NAMES
if (!mtd_part)
{
syslog(LOG_ERR,
"Error: failed to create partition %s\n",
partname);
return -1;
}
mtd_setpartitionname(mtd_part, partname);
/* Now skip to next name.
* We don't need to split the string here
* because the MTD partition logic will only
* display names up to the comma,
* thus allowing us to use a single static name
* in the code.
*/
while (*partname != ',' && *partname != '\0')
{
/* Skip to next ',' */
partname++;
}
if (*partname == ',')
{
partname++;
}
#endif
/* Update the pointer to point to the next size in the list */
while ((*ptr >= '0') && (*ptr <= '9'))
{
ptr++;
}
if (*ptr == ',')
{
ptr++;
}
/* Increment the part number */
partno++;
}
}
#else /* CONFIG_MTD_PARTITION */
/* Configure the device with no partition support */
smart_initialize(0, mtd, NULL);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: SmartFS initialization failed: %d\n", ret);
return ret;
}
#endif
return OK;
}
#endif /* CONFIG_FS_SMARTFS */

View File

@ -448,6 +448,27 @@ config MAX1704X
The MAX17040 is configured to operate with a single lithium cell and the The MAX17040 is configured to operate with a single lithium cell and the
MAX17041 is configured for a dual-cell 2S pack. MAX17041 is configured for a dual-cell 2S pack.
config BQ27426
bool "BQ27426 Battery fuel gauge support"
default n
select I2C
depends on BATTERY_GAUGE
---help---
The bq27426 battery fuel gauge accurately predicts the battery capacity and other
operational characteristics of a single, Li-based, rechargeable cell.
It can be interrogated by a system processor to provide cell information,
such as state-of-charge (SOC).
if BQ27426
config DEBUG_BQ27426
bool "BQ27426 Debug Features"
default n
---help---
Enable BQ27426 battery management debug features.
endif # BQ27426
config I2C_BQ2425X config I2C_BQ2425X
bool bool
default y if BQ2425X default y if BQ2425X

View File

@ -152,6 +152,12 @@ ifeq ($(CONFIG_I2C_MAX1704X),y)
CSRCS += max1704x.c CSRCS += max1704x.c
endif endif
# Add the bq27426 I2C-based battery guage driver
ifeq ($(CONFIG_BQ27426),y)
CSRCS += bq27426.c
endif
endif endif
# Include battery support in the build # Include battery support in the build

457
drivers/power/bq27426.c Normal file
View File

@ -0,0 +1,457 @@
/****************************************************************************
* drivers/power/bq27426.c
*
* Lower half driver for BQ27426 battery fuel gauge
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/signal.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/power/battery_gauge.h>
#include <nuttx/power/bq27426.h>
/* This driver requires:
*
* CONFIG_BATTERY - Upper half battery driver support
* CONFIG_I2C - I2C support
* CONFIG_BQ27426 - And the driver must be explictly selected.
*/
#if defined(CONFIG_BATTERY_GAUGE) && defined(CONFIG_I2C) && \
defined(CONFIG_BQ27426)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Debug ********************************************************************/
#ifdef CONFIG_DEBUG_BQ27426
# define baterr _err
# define batdbg _info
# define batinfo _info
#else
# ifdef CONFIG_CPP_HAVE_VARARGS
# define baterr(x...)
# define batdbg(x...)
# define batinfo(x...)
# else
# define baterr (void)
# define batdbg (void)
# define batinfo(void)
# endif
#endif
/****************************************************************************
* Private
****************************************************************************/
/* Parameters for the capacity() function,
* to specify which capacity to read in mAh
*/
typedef enum
{
REMAIN, /* Remaining Capacity (DEFAULT) */
FULL, /* Full Capacity */
AVAIL, /* Available Capacity */
AVAIL_FULL, /* Full Available Capacity */
REMAIN_F, /* Remaining Capacity Filtered */
REMAIN_UF, /* Remaining Capacity Unfiltered */
FULL_F, /* Full Capacity Filtered */
FULL_UF /* Full Capacity Unfiltered */
} capacity_measure;
/****************************************************************************
* Private
****************************************************************************/
struct bq27426_dev_s
{
/* The common part of the battery driver visible to the upper-half driver */
FAR const struct battery_gauge_operations_s *ops; /* Battery operations */
sem_t batsem; /* Enforce mutually exclusive access */
/* Data fields specific to the lower half bq27426 driver follow */
FAR struct i2c_master_s *i2c; /* I2C interface */
uint8_t addr; /* I2C address */
uint32_t frequency; /* I2C frequency */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* I2C support */
static int bq27426_getreg16(FAR struct bq27426_dev_s *priv, uint8_t regaddr,
FAR uint16_t *regval);
static int bq27426_putreg16(FAR struct bq27426_dev_s *priv, uint8_t regaddr,
uint16_t regval);
static inline int bq27426_getvoltage(FAR struct bq27426_dev_s *priv,
b16_t *voltage);
static inline int bq27426_getsoc(FAR struct bq27426_dev_s *priv,
b16_t *soc);
static inline int bq27426_getcapacity(FAR struct bq27426_dev_s *priv,
uint8_t capacity,
b16_t *value);
static inline int bq27426_get_device_id(FAR struct bq27426_dev_s *priv,
uint16_t *id);
/* Battery driver lower half methods */
static int bq27426_state(struct battery_gauge_dev_s *dev, int *status);
static int bq27426_online(struct battery_gauge_dev_s *dev, bool *status);
static int bq27426_voltage(struct battery_gauge_dev_s *dev, b16_t *value);
static int bq27426_capacity_full(struct battery_gauge_dev_s *dev,
b16_t *capacity_full);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct battery_gauge_operations_s g_bq27426ops =
{
bq27426_state,
bq27426_online,
bq27426_voltage,
bq27426_capacity_full,
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: bq27426_getreg16
*
* Description:
* Read a 16-bit value from a bq27426 register pair.
*
* START <I2C write address> ACK <Reg address> ACK
* REPEATED-START <I2C read address> ACK Data0 ACK Data1 NO-ACK STOP
*
****************************************************************************/
static int bq27426_getreg16(FAR struct bq27426_dev_s *priv, uint8_t regaddr,
FAR uint16_t *regval)
{
struct i2c_config_s config;
uint8_t buffer[2];
int ret;
/* Set up the configuration and perform the write-read operation */
config.frequency = priv->frequency;
config.address = priv->addr;
config.addrlen = 7;
/* Write the register address */
ret = i2c_write(priv->i2c, &config, &regaddr, 1);
if (ret < 0)
{
baterr("i2c_write failed: %d\n", ret);
return ret;
}
/* Restart and read 16-bits from the register */
ret = i2c_read(priv->i2c, &config, buffer, 2);
if (ret < 0)
{
baterr("i2c_read failed: %d\n", ret);
return ret;
}
*regval = ((uint16_t) buffer[1] << 8) | buffer[0];
return OK;
}
/****************************************************************************
* Name: bq27426_putreg16
*
* Description:
* Write a 16-bit value to a bq27426 register pair.
*
* START <I2C write address> ACK <Reg address> ACK Data0 ACK Data1 ACK STOP
*
****************************************************************************/
static int bq27426_putreg16(FAR struct bq27426_dev_s *priv, uint8_t regaddr,
uint16_t regval)
{
struct i2c_config_s config;
uint8_t buffer[3];
baterr("addr: %02x regval: %04x\n", regaddr, regval);
/* Set up a 3 byte message to send */
buffer[0] = regaddr;
buffer[1] = (uint8_t)(regval & 0x00ff);
buffer[2] = (uint8_t)(regval >> 8);
/* Set up the configuration and perform the write-read operation */
config.frequency = priv->frequency;
config.address = priv->addr;
config.addrlen = 7;
/* Write the register address followed by the data (no RESTART) */
return i2c_write(priv->i2c, &config, buffer, 3);
}
/****************************************************************************
* Name: bq27426_get_device_id
*
* Description:
* Read the ID register
*
****************************************************************************/
static inline int bq27426_get_device_id(FAR struct bq27426_dev_s *priv,
uint16_t *id)
{
uint16_t regval = 0;
int ret;
ret = bq27426_putreg16(priv, BQ27426_COMMAND_CONTROL,
BQ27426_CONTROL_DEVICE_TYPE);
if (ret == OK)
{
ret = bq27426_getreg16(priv, BQ27426_COMMAND_CONTROL, &regval);
*id = regval;
}
return ret;
}
/****************************************************************************
* Name: bq27426_getvoltage
*
* Description:
* Read the VCELL register and scale the returned value
*
****************************************************************************/
static inline int bq27426_getvoltage(FAR struct bq27426_dev_s *priv,
b16_t *voltage)
{
uint16_t regval = 0;
int ret;
ret = bq27426_getreg16(priv, BQ27426_COMMAND_VOLTAGE, &regval);
if (ret == OK)
{
*voltage = regval;
}
return ret;
}
/****************************************************************************
* Name: bq27426_getsoc
*
* Description:
* Read the SOC register and scale the returned value
*
****************************************************************************/
static inline int bq27426_getsoc(FAR struct bq27426_dev_s *priv, b16_t *soc)
{
uint16_t regval = 0;
int ret;
ret = bq27426_getreg16(priv, BQ27426_COMMAND_SOC, &regval);
if (ret == OK)
*soc = regval;
return ret;
}
/****************************************************************************
* Name: bq27426_getcapacity
*
* Description:
* Read the SOC register and scale the returned value
*
****************************************************************************/
static inline int bq27426_getcapacity(FAR struct bq27426_dev_s *priv,
uint8_t capacity, b16_t *value)
{
uint16_t regval = 0;
return bq27426_getreg16(priv, capacity, &regval);
}
/****************************************************************************
* Name: bq27426_state
*
* Description:
* Return the battery state
*
****************************************************************************/
static int bq27426_state(struct battery_gauge_dev_s *dev, int *status)
{
FAR struct bq27426_dev_s *priv = (FAR struct bq27426_dev_s *)dev;
b16_t soc = 0;
int ret;
/* Only a few of the possible battery states are supported by this driver:
*
* BATTERY_UNKNOWN - Returned on error conditions
* BATTERY_IDLE - This is what will usually be reported
* BATTERY_FULL - This will be reported if the SoC is greater than 95%
* BATTERY_CHARGING and BATTERY_DISCHARGING - I don't think this hardware
* knows anything about current (charging or dischargin).
*
*/
ret = bq27426_getsoc(priv, &soc);
if (ret < 0)
{
*status = BATTERY_UNKNOWN;
return ret;
}
*status = soc;
return OK;
}
/****************************************************************************
* Name: bq27426_voltage
*
* Description:
* Current battery voltage
*
****************************************************************************/
static int bq27426_voltage(struct battery_gauge_dev_s *dev, b16_t *value)
{
FAR struct bq27426_dev_s *priv = (FAR struct bq27426_dev_s *)dev;
return bq27426_getvoltage(priv, value);
}
/****************************************************************************
* Name: bq27426_capacity_full
*
* Description:
* Battery capacity (mAh)
*
****************************************************************************/
static int bq27426_capacity_full(struct battery_gauge_dev_s *dev,
b16_t *value)
{
FAR struct bq27426_dev_s *priv = (FAR struct bq27426_dev_s *)dev;
return bq27426_getcapacity(priv, BQ27426_COMMAND_FULL_CAP_FIL, value);
}
/****************************************************************************
* Name: bq27426_online
*
* Description:
* Return true if the batter is online
*
****************************************************************************/
static int bq27426_online(struct battery_gauge_dev_s *dev, bool *status)
{
/* There is no concept of online/offline in this driver */
*status = true;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bq27426_initialize
*
* Description:
* Initialize the bq27426 battery driver and return an instance of the
* lower_half interface that may be used with battery_register();
*
* This driver requires:
*
* CONFIG_BATTERY - Upper half battery driver support
* CONFIG_I2C - I2C support
* CONFIG_BQ27426 - And the driver must be explictly selected.
*
* Input Parameters:
* i2c - An instance of the I2C interface to use to communicate with the bq
* addr - The I2C address of the bq27426 (Better be 0x55).
* frequency - The I2C frequency
*
* Returned Value:
* A pointer to the initializeed lower-half driver instance. A NULL
* pointer is returned on a failure to initialize the bq27426 lower half.
*
****************************************************************************/
FAR struct battery_gauge_dev_s *bq27426_initialize(
FAR struct i2c_master_s *i2c,
uint8_t addr,
uint32_t frequency)
{
FAR struct bq27426_dev_s *priv;
/* Initialize the bq27426 device structure */
priv = (FAR struct bq27426_dev_s *)kmm_zalloc(sizeof(
struct bq27426_dev_s));
if (priv)
{
/* Initialize the bq27426 device structure */
nxsem_init(&priv->batsem, 0, 1);
priv->ops = &g_bq27426ops;
priv->i2c = i2c;
priv->addr = addr;
priv->frequency = frequency;
}
return (FAR struct battery_gauge_dev_s *)priv;
}
#endif /* CONFIG_BATTERY && CONFIG_I2C && CONFIG_BQ27426 */

View File

@ -53,7 +53,9 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/
/* Configuration */
/* CONFIG_BATTERY_GAUGE - Upper half battery fuel gauge driver support /* CONFIG_BATTERY_GAUGE - Upper half battery fuel gauge driver support
* *
* Specific, lower-half drivers will have other configuration requirements * Specific, lower-half drivers will have other configuration requirements
@ -63,7 +65,8 @@
* CONFIG_I2C_MAX1704X - The MAX1704x driver must be explicitly selected. * CONFIG_I2C_MAX1704X - The MAX1704x driver must be explicitly selected.
*/ */
/* IOCTL Commands ***********************************************************/ /* IOCTL Commands */
/* The upper-half battery fuel gauge driver provides a character driver /* The upper-half battery fuel gauge driver provides a character driver
* "wrapper" * around the lower-half battery driver that does all of the * "wrapper" * around the lower-half battery driver that does all of the
* real work. * real work.
@ -89,6 +92,7 @@
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
****************************************************************************/ ****************************************************************************/
/* Battery status */ /* Battery status */
enum battery_gauge_status_e enum battery_gauge_status_e
@ -100,7 +104,7 @@ enum battery_gauge_status_e
BATTERY_DISCHARGING /* Probably not full, discharging */ BATTERY_DISCHARGING /* Probably not full, discharging */
}; };
/* This structure defines the lower half battery interface */ /* This structure defines the lower half battery interface */
struct battery_gauge_dev_s; struct battery_gauge_dev_s;
struct battery_gauge_operations_s struct battery_gauge_operations_s
@ -151,6 +155,7 @@ extern "C"
/**************************************************************************** /****************************************************************************
* Public Function Prototypes * Public Function Prototypes
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: battery_gauge_register * Name: battery_gauge_register
* *
@ -171,6 +176,40 @@ extern "C"
int battery_gauge_register(FAR const char *devpath, int battery_gauge_register(FAR const char *devpath,
FAR struct battery_gauge_dev_s *dev); FAR struct battery_gauge_dev_s *dev);
/****************************************************************************
* Name: bq27426_initialize
*
* Description:
* Initialize the bq2742 battery driver and return an instance of the
* lower_half interface that may be used with battery_gauge_register();
*
* This driver requires:
*
* CONFIG_BATTERY_GAUGE - Upper half battery fuel gauge driver support
* CONFIG_I2C - I2C support
* CONFIG_BQ27426 - And the driver must be explictly selected.
*
* Input Parameters:
* i2c - An instance of the I2C interface to use to communicate with the
* bq27426
* addr - The I2C address of the bq27426 (Better be 0x55).
* frequency - The I2C frequency
*
* Returned Value:
* A pointer to the initializeed battery driver instance. A NULL pointer
* is returned on a failure to initialize the bq27426 lower half.
*
****************************************************************************/
#if defined(CONFIG_I2C) && defined(CONFIG_BQ27426)
struct i2c_master_s; /* Forward reference */
FAR struct battery_gauge_dev_s *bq27426_initialize(
FAR struct i2c_master_s *i2c,
uint8_t addr,
uint32_t frequency);
#endif
/**************************************************************************** /****************************************************************************
* Name: max1704x_initialize * Name: max1704x_initialize
* *
@ -187,7 +226,8 @@ int battery_gauge_register(FAR const char *devpath,
* chip is on the board in order to scale the voltage correctly. * chip is on the board in order to scale the voltage correctly.
* *
* Input Parameters: * Input Parameters:
* i2c - An instance of the I2C interface to use to communicate with the MAX1704x * i2c - An instance of the I2C interface to use to communicate with
* the MAX1704x.
* addr - The I2C address of the MAX1704x (Better be 0x36). * addr - The I2C address of the MAX1704x (Better be 0x36).
* frequency - The I2C frequency * frequency - The I2C frequency
* *
@ -200,7 +240,8 @@ int battery_gauge_register(FAR const char *devpath,
#if defined(CONFIG_I2C) && defined(CONFIG_I2C_MAX1704X) #if defined(CONFIG_I2C) && defined(CONFIG_I2C_MAX1704X)
struct i2c_master_s; /* Forward reference */ struct i2c_master_s; /* Forward reference */
FAR struct battery_gauge_dev_s *max1704x_initialize(FAR struct i2c_master_s *i2c, FAR struct battery_gauge_dev_s *max1704x_initialize(
FAR struct i2c_master_s *i2c,
uint8_t addr, uint8_t addr,
uint32_t frequency); uint32_t frequency);
#endif #endif

View File

@ -0,0 +1,210 @@
/****************************************************************************
* include/nuttx/power/bq27426.h
* Lower half driver for bq27426 battery fuel gauge.
*
* 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.
*
****************************************************************************/
#ifndef __DRIVERS_POWER_BQ27426_H
#define __DRIVERS_POWER_BQ27426_H
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Auxiliary Definitions */
#define BQ27426_I2C_TIMEOUT 2000
#define BQ27426_I2C_ADDRESS 0x55 /* Default I2C address of the BQ27426 */
/* General Constants */
#define BQ27426_UNSEAL_KEY 0x8000 /* Secret code to unseal the BQ27426 */
#define BQ27426_DEVICE_ID 0x0426 /* Default device ID */
/* Standard Commands */
/* The fuel gauge uses a series of 2-byte standard commands to enable system
* reading and writing of battery information. Each command has an associated
* sequential command-code pair.
*/
#define BQ27426_COMMAND_CONTROL 0x00 /* Control() */
#define BQ27426_COMMAND_TEMP 0x02 /* Temperature() */
#define BQ27426_COMMAND_VOLTAGE 0x04 /* Voltage() */
#define BQ27426_COMMAND_FLAGS 0x06 /* Flags() */
#define BQ27426_COMMAND_NOM_CAPACITY 0x08 /* NominalAvailableCapacity() */
#define BQ27426_COMMAND_AVAIL_CAPACITY 0x0A /* FullAvailableCapacity() */
#define BQ27426_COMMAND_REM_CAPACITY 0x0C /* RemainingCapacity() */
#define BQ27426_COMMAND_FULL_CAPACITY 0x0E /* FullChargeCapacity() */
#define BQ27426_COMMAND_AVG_CURRENT 0x10 /* AverageCurrent() */
#define BQ27426_COMMAND_AVG_POWER 0x18 /* AveragePower() */
#define BQ27426_COMMAND_SOC 0x1C /* StateOfCharge() */
#define BQ27426_COMMAND_INT_TEMP 0x1E /* InternalTemperature() */
#define BQ27426_COMMAND_SOH 0x20 /* StateOfHealth() */
#define BQ27426_COMMAND_REM_CAP_UNFL 0x28 /* RemainingCapacityUnfiltered() */
#define BQ27426_COMMAND_REM_CAP_FIL 0x2A /* RemainingCapacityFiltered() */
#define BQ27426_COMMAND_FULL_CAP_UNFL 0x2C /* FullChargeCapacityUnfiltered() */
#define BQ27426_COMMAND_FULL_CAP_FIL 0x2E /* FullChargeCapacityFiltered() */
#define BQ27426_COMMAND_SOC_UNFL 0x30 /* StateOfChargeUnfiltered() */
/* Control Sub-commands */
/* Issuing a Control() command requires a subsequent 2-byte subcommand. These
* additional bytes specify the particular control function desired. The
* Control() command allows the system to control specific features of the
* fuel gauge during normal operation and additional features when the
* device is in different access modes.
*/
#define BQ27426_CONTROL_STATUS 0x0000
#define BQ27426_CONTROL_DEVICE_TYPE 0x0001
#define BQ27426_CONTROL_FW_VERSION 0x0002
#define BQ27426_CONTROL_DM_CODE 0x0004
#define BQ27426_CONTROL_PREV_MACWRITE 0x0007
#define BQ27426_CONTROL_CHEM_ID 0x0008
#define BQ27426_CONTROL_BAT_INSERT 0x000C
#define BQ27426_CONTROL_BAT_REMOVE 0x000D
#define BQ27426_CONTROL_SET_CFGUPDATE 0x0013
#define BQ27426_CONTROL_SMOOTH_SYNC 0x0019
#define BQ27426_CONTROL_SHUTDOWN_ENABLE 0x001B
#define BQ27426_CONTROL_SHUTDOWN 0x001C
#define BQ27426_CONTROL_SEALED 0x0020
#define BQ27426_CONTROL_PULSE_SOC_INT 0x0023
#define BQ27426_CONTROL_CHEM_A 0x0030
#define BQ27426_CONTROL_CHEM_B 0x0031
#define BQ27426_CONTROL_CHEM_C 0x0032
#define BQ27426_CONTROL_RESET 0x0041
#define BQ27426_CONTROL_SOFT_RESET 0x0042
/* Control Status Word - Bit Definitions */
/* Bit positions for the 16-bit data of CONTROL_STATUS.
* CONTROL_STATUS instructs the fuel gauge to return status
* information to Control() addresses 0x00 and 0x01.
* The read-only status word contains status bits that are
* set or cleared either automatically as conditions warrant or
* through using specified subcommands.
*/
#define BQ27426_STATUS_SHUTDOWNEN (1 << 15)
#define BQ27426_STATUS_WDRESET (1 << 14)
#define BQ27426_STATUS_SS (1 << 13)
#define BQ27426_STATUS_CALMODE (1 << 12)
#define BQ27426_STATUS_CCA (1 << 11)
#define BQ27426_STATUS_BCA (1 << 10)
#define BQ27426_STATUS_QMAX_UP (1 << 9)
#define BQ27426_STATUS_RES_UP (1 << 8)
#define BQ27426_STATUS_INITCOMP (1 << 7)
#define BQ27426_STATUS_SLEEP (1 << 4)
#define BQ27426_STATUS_LDMD (1 << 3)
#define BQ27426_STATUS_RUP_DIS (1 << 2)
#define BQ27426_STATUS_VOK (1 << 1)
#define BQ27426_STATUS_CHEMCHANGE (1 << 0)
/* Flag Command - Bit Definitions */
/* Bit positions for the 16-bit data of Flags()
* This read-word function returns the contents of the fuel gauging status
* register, depicting the current operating status.
*/
#define BQ27426_FLAG_OT (1 << 15)
#define BQ27426_FLAG_UT (1 << 14)
#define BQ27426_FLAG_FC (1 << 9)
#define BQ27426_FLAG_CHG (1 << 8)
#define BQ27426_FLAG_OCVTAKEN (1 << 7)
#define BQ27426_FLAG_DODCORRECT (1 << 6)
#define BQ27426_FLAG_ITPOR (1 << 5)
#define BQ27426_FLAG_CFGUPMODE (1 << 4)
#define BQ27426_FLAG_BAT_DET (1 << 3)
#define BQ27426_FLAG_SOC1 (1 << 2)
#define BQ27426_FLAG_SOCF (1 << 1)
#define BQ27426_FLAG_DSG (1 << 0)
/* Extended Data Commands */
/* Extended data commands offer additional functionality beyond
* the standard set of commands.
* They are used in the same manner; however, unlike standard
* scommands, extended commands are not limited to 2-byte words.
*/
#define BQ27426_EXTENDED_OPCONFIG 0x3A /* OpConfig()*/
#define BQ27426_EXTENDED_CAPACITY 0x3C /* DesignCapacity()*/
#define BQ27426_EXTENDED_DATACLASS 0x3E /* DataClass()*/
#define BQ27426_EXTENDED_DATABLOCK 0x3F /* DataBlock()*/
#define BQ27426_EXTENDED_BLOCKDATA 0x40 /* BlockData()*/
#define BQ27426_EXTENDED_CHECKSUM 0x60 /* BlockDataCheckSum()*/
#define BQ27426_EXTENDED_CONTROL 0x61 /* BlockDataControl()*/
/* Configuration Class, Subclass ID's */
/* To access a subclass of the extended data, set the DataClass()
* function with one of these values.
*/
/* Configuration Classes */
#define BQ27426_ID_SAFETY 2 /* Safety */
#define BQ27426_ID_CHG_TERMINATION 6 /* Charge Termination */
#define BQ27426_ID_CONFIG_DATA 48 /* Data */
#define BQ27426_ID_DISCHARGE 49 /* Discharge */
#define BQ27426_ID_REGISTERS 64 /* Registers */
#define BQ27426_ID_POWER 68 /* Power */
/* Gas Gauging Classes */
#define BQ27426_ID_IT_CFG 80 /* IT Cfg */
#define BQ27426_ID_CURRENT_THRESH 81 /* Current Thresholds */
#define BQ27426_ID_STATE 82 /* State */
/* Ra Tables Classes */
#define BQ27426_ID_R_A_RAM 89 /* R_a RAM */
/* Calibration Classes */
#define BQ27426_ID_CALIB_DATA 104 /* Data */
#define BQ27426_ID_CC_CAL 105 /* CC Cal */
#define BQ27426_ID_CURRENT 107 /* Current */
/* Security Classes */
#define BQ27426_ID_CODES 112 /* Codes */
/* OpConfig Register - Bit Definitions */
/* Bit positions of the OpConfig Register */
#define BQ27426_OPCONFIG_BIE (1 << 13)
#define BQ27426_OPCONFIG_GPIOPOL (1 << 11)
#define BQ27426_OPCONFIG_RESFACTSTEP (1 << 6)
#define BQ27426_OPCONFIG_SLEEP (1 << 5)
#define BQ27426_OPCONFIG_RMFCC (1 << 4)
#define BQ27426_OPCONFIG_FASTCONVEN (1 << 3)
#define BQ27426_OPCONFIG_BATLOWEN (1 << 2)
#define BQ27426_OPCONFIG_TEMPS (1 << 0)
#define BQ27426_ACCESS_SUB_CLASS_80 0x50
#define BQ27426_ACCESS_SUB_CLASS_81 0x51
#define BQ27426_ACCESS_SUB_CLASS_82 0x52
#define BQ27426_ACCESS_SUB_CLASS_89 0x59
#define BQ27426_ACCESS_SUB_CLASS_64 0x40
#endif /* __DRIVERS_POWER_BQ27426_H */