Add i2c driver for gd32f450 MCU

This commit is contained in:
GD32-MCU
2022-12-15 15:39:17 +08:00
committed by Xiang Xiao
parent 3462061624
commit 659bd495b0
17 changed files with 3332 additions and 22 deletions
+21 -6
View File
@@ -87,7 +87,7 @@ config GD32F4_120MHZ
endchoice # CPU Frequency
config GD32F4_GD25_BLOCKMOUNT
config GD32F450ZK_EVAL_GD25_BLOCKMOUNT
bool "GD25 serial FLASH auto-mount"
default n
depends on GD32F4_SPI5 && MTD_GD25
@@ -96,18 +96,18 @@ config GD32F4_GD25_BLOCKMOUNT
choice
prompt "GD25 SPI FLASH configuration"
default GD32F4_GD25_NXFFS
depends on GD32F4_GD25_BLOCKMOUNT
default GD32F450ZK_EVAL_GD25_NXFFS
depends on GD32F450ZK_EVAL_GD25_BLOCKMOUNT
config GD32F4_GD25_FTL
config GD32F450ZK_EVAL_GD25_FTL
bool "Create GD25 SPI FLASH block driver"
---help---
Create the MTD driver for the GD25 and "wrap" the GD25 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
any other file system. Any file system may be used, but there will
be no wear-leveling.
config GD32F4_GD25_NXFFS
config GD32F450ZK_EVAL_GD25_NXFFS
bool "Create GD25 serial FLASH NXFFS file system"
depends on FS_NXFFS
---help---
@@ -117,5 +117,20 @@ config GD32F4_GD25_NXFFS
endchoice # GD25 serial FLASH configuration
config GD32F450ZK_EVAL_AT24_TEST
bool "I2C0 EEPROM AT2402 write and read test"
default n
depends on NSH_ARCHINIT && GD32F4_I2C0 && MTD_AT24XX
---help---
Automatically initialize and test the AT24 I2C EEPROM driver when
NSH starts. After test the I2C0 will be released.
config AT24XX_MTD_BLOCKSIZE
int "AT24xx MTD block size"
default 8
depends on GD32F450ZK_EVAL_AT24_TEST
---help---
The block size must be an even multiple of the pages.
The page size of AT2402 on the board is 8 Byte.
endif # ARCH_BOARD_GD32F450ZK_EVAL
@@ -29,11 +29,11 @@ CONFIG_FS_PROCFS=y
CONFIG_FS_PROCFS_REGISTER=y
CONFIG_FS_TMPFS=y
CONFIG_GD25_SPIFREQUENCY=4000000
CONFIG_GD32F450ZK_EVAL_GD25_BLOCKMOUNT=y
CONFIG_GD32F4_168MHZ=y
CONFIG_GD32F4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y
CONFIG_GD32F4_ENETMAC=y
CONFIG_GD32F4_FLASH_CONFIG_K=y
CONFIG_GD32F4_GD25_BLOCKMOUNT=y
CONFIG_GD32F4_PHY_SR=16
CONFIG_GD32F4_PHY_SR_100FD=0x0004
CONFIG_GD32F4_PHY_SR_100HD=0x0000
@@ -0,0 +1,63 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_ARCH_FPU is not set
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD="gd32f450zk-eval"
CONFIG_ARCH_BOARD_GD32F450ZK_EVAL=y
CONFIG_ARCH_BUTTONS=y
CONFIG_ARCH_CHIP="gd32f4"
CONFIG_ARCH_CHIP_GD32F450ZK=y
CONFIG_ARCH_CHIP_GD32F4=y
CONFIG_ARCH_INTERRUPTSTACK=256
CONFIG_ARCH_STACKDUMP=y
CONFIG_AT24XX_SIZE=2
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BUILTIN=y
CONFIG_DEBUG_CUSTOMOPT=y
CONFIG_DEBUG_ERROR=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_IRQ=y
CONFIG_DEBUG_LEDS=y
CONFIG_DEBUG_OPTLEVEL="-O0"
CONFIG_DEBUG_SCHED=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEBUG_WARN=y
CONFIG_FS_NXFFS=y
CONFIG_FS_PROCFS=y
CONFIG_GD32F450ZK_EVAL_AT24_TEST=y
CONFIG_GD32F4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y
CONFIG_GD32F4_FLASH_CONFIG_K=y
CONFIG_GD32F4_I2C0=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_I2C_DRIVER=y
CONFIG_I2C_POLLED=y
CONFIG_I2C_RESET=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INTELHEX_BINARY=y
CONFIG_MM_REGIONS=2
CONFIG_MTD=y
CONFIG_MTD_AT24XX=y
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_LINELEN=64
CONFIG_NSH_READLINE=y
CONFIG_NXFFS_PACKTHRESHOLD=8
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=0
CONFIG_USART0_SERIAL_CONSOLE=y
@@ -25,11 +25,11 @@ CONFIG_FS_PROCFS=y
CONFIG_FS_PROCFS_REGISTER=y
CONFIG_FS_TMPFS=y
CONFIG_GD25_SPIFREQUENCY=4000000
CONFIG_GD32F450ZK_EVAL_GD25_BLOCKMOUNT=y
CONFIG_GD32F4_168MHZ=y
CONFIG_GD32F4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y
CONFIG_GD32F4_ENETMAC=y
CONFIG_GD32F4_FLASH_CONFIG_K=y
CONFIG_GD32F4_GD25_BLOCKMOUNT=y
CONFIG_GD32F4_PHY_SR=16
CONFIG_GD32F4_PHY_SR_100FD=0x0004
CONFIG_GD32F4_PHY_SR_100HD=0x0000
@@ -283,6 +283,16 @@ typedef enum
# define GPIO_USART3_TX GPIO_USART3_TX_3
#endif
/* I2C0 gpios:
*
* PB6 I2C0_SCL
* PB7 I2C0_SDA
*
*/
#define GPIO_I2C0_SCL GPIO_I2C0_SCL_1
#define GPIO_I2C0_SDA GPIO_I2C0_SDA_1
/* SPI flash
*
* PG12 SPI5_MISO
@@ -53,4 +53,8 @@ ifeq ($(CONFIG_MTD_GD25),y)
CSRCS += gd32f4xx_gd25.c
endif
ifeq ($(CONFIG_MTD_AT24XX), y)
CSRCS += gd32f4xx_at24.c
endif
include $(TOPDIR)/boards/Board.mk
@@ -101,6 +101,41 @@
#define HAVE_GD25 1
#if !defined(CONFIG_MTD_GD25) || !defined(CONFIG_GD32F4_SPI5)
# undef HAVE_GD25
#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_GD32F450ZK_EVAL_GD25_BLOCKMOUNT)
# undef HAVE_GD25
#endif
#define HAVE_AT24 1
/* AT24 Serial EEPROM
*
* A AT24C02C Serial EEPPROM was used for tested I2C0.
*/
#define AT24_BUS 0
#define AT24_MINOR 0
#if !defined(CONFIG_MTD_AT24XX) || !defined(CONFIG_GD32F4_I2C0)
# undef HAVE_AT24
#endif
/* Can't support AT24 features if mountpoints are disabled or if we were not
* asked to mount the AT25 part
*/
#ifndef CONFIG_GD32F450ZK_EVAL_AT24_TEST
# undef HAVE_AT24
#endif
/* GPIO pins used by the GPIO Subsystem */
#define BOARD_NGPIOIN 1 /* Amount of GPIO Input pins */
@@ -144,6 +179,18 @@ void gd32_spidev_initialize(void);
int gd32_gd25_automount(int minor);
#endif
/****************************************************************************
* Name: gd32_at24_wr_test
*
* Description:
* Write and read the AT24 serial EEPROM test.
*
****************************************************************************/
#ifdef HAVE_AT24
int gd32_at24_wr_test(int minor);
#endif
/****************************************************************************
* Name: gd32_gpio_initialize
*
@@ -138,7 +138,7 @@ int board_app_initialize(uintptr_t arg)
# endif
# ifdef CONFIG_MTD_GD25
# ifdef HAVE_GD25
ret = gd32_gd25_automount(0);
if (ret < 0)
@@ -149,7 +149,18 @@ int board_app_initialize(uintptr_t arg)
# endif
#endif
# ifdef HAVE_AT24
ret = gd32_at24_wr_test(AT24_MINOR);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: I2C EEPROM write and read test fail: \
%d\n", ret);
}
# endif
#endif /* CONFIG_FS_NXFFS */
#ifdef CONFIG_DEV_GPIO
/* Register the GPIO driver */
@@ -0,0 +1,155 @@
/****************************************************************************
* boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_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 <stdbool.h>
#include <stdio.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/mtd/mtd.h>
#include <nuttx/kmalloc.h>
#include "gd32f4xx.h"
#include "gd32f450z_eval.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: gd32_at24_wr_test
*
* Description:
* Write and read the AT24 serial EEPROM test.
*
****************************************************************************/
#ifdef HAVE_AT24
#define BUFFSIZE 16
#define START_BLOCK 0
#if BUFFSIZE>=CONFIG_AT24XX_MTD_BLOCKSIZE
# define NBLOCK (BUFFSIZE/CONFIG_AT24XX_MTD_BLOCKSIZE)
#else
# error "BUFFSIZE should bigger than CONFIG_AT24XX_MTD_BLOCKSIZE"
#endif
const uint8_t write_buf[BUFFSIZE] =
{
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf
};
int gd32_at24_wr_test(int minor)
{
struct i2c_master_s *i2c;
struct mtd_dev_s *at24;
static bool initialized = false;
int ret;
ssize_t nblocks;
uint8_t *read_buf;
/* Have we already initialized? */
if (!initialized)
{
/* No.. Get the I2C port driver */
finfo("Initialize TWI%d\n", AT24_BUS);
i2c = gd32_i2cbus_initialize(AT24_BUS);
if (!i2c)
{
ferr("ERROR: Failed to initialize TWI%d\n", AT24_BUS);
return -ENODEV;
}
/* Now bind the I2C interface to the AT24 I2C EEPROM driver */
finfo("Bind the AT24 EEPROM driver to TWI%d\n", AT24_BUS);
at24 = at24c_initialize(i2c);
if (!at24)
{
ferr("ERROR: Failed to bind TWI%d to the AT24 EEPROM driver\n",
AT24_BUS);
return -ENODEV;
}
/* Now we are initializeed */
initialized = true;
}
/* Write start block is START_BLOCK, number of block is 2 */
nblocks = at24->bwrite(at24, START_BLOCK, NBLOCK, write_buf);
if (nblocks < NBLOCK)
{
ferr("ERROR: AT24 write failed: %zd\n", nblocks);
gd32_i2cbus_uninitialize(i2c);
return (int)nblocks;
}
read_buf = (uint8_t *)kmm_malloc(BUFFSIZE);
/* Read the data write before */
nblocks = at24->bread(at24, START_BLOCK, NBLOCK, read_buf);
if (nblocks < NBLOCK)
{
ferr("ERROR: AT24 read failed: %zd\n", nblocks);
gd32_i2cbus_uninitialize(i2c);
return (int)nblocks;
}
if (memcmp(read_buf, write_buf, BUFFSIZE) != 0)
{
ferr("ERROR: Read buffer does not match write buffer\n");
return -1;
}
/* Release the I2C instance.
* REVISIT: Need an interface to release the AT24 instance too
*/
ret = gd32_i2cbus_uninitialize(i2c);
if (ret < 0)
{
ferr("ERROR: Failed to release the I2C interface: %d\n", ret);
}
syslog(LOG_INFO, "INFO: I2C EEPROM write and read success: \
%d\n", ret);
return OK;
}
#endif /* HAVE_AT24 */
@@ -87,7 +87,7 @@ int gd32_gd25_automount(int minor)
return -ENODEV;
}
#if defined(CONFIG_GD32F4_GD25_FTL)
#if defined(CONFIG_GD32F450ZK_EVAL_GD25_FTL)
/* And finally, use the FTL layer to wrap the MTD driver as a block
* driver at /dev/mtdblockN, where N=minor device number.
*/
@@ -100,7 +100,7 @@ int gd32_gd25_automount(int minor)
return ret;
}
#elif defined(CONFIG_GD32F4_GD25_NXFFS)
#elif defined(CONFIG_GD32F450ZK_EVAL_GD25_NXFFS)
/* Initialize to provide NXFFS on the MTD interface */
ret = nxffs_initialize(mtd);