[BSP] Add fh8620 bsp from Shanghai Fullhan Microelectronics Co., Ltd.

FH8620 BSP
Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
All rights reserved
This commit is contained in:
Bernard Xiong
2016-04-18 13:52:39 +08:00
parent 6d03ce9a7b
commit 43f68131ce
101 changed files with 23485 additions and 0 deletions

14
bsp/fh8620/SConscript Normal file
View File

@@ -0,0 +1,14 @@
# for module compiling
import os
Import('RTT_ROOT')
cwd = str(Dir('#'))
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')

33
bsp/fh8620/SConstruct Normal file
View File

@@ -0,0 +1,33 @@
import os
import sys
import rtconfig
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
TARGET = rtconfig.OUTPUT_NAME + rtconfig.TARGET_EXT
# add rtconfig.h path to the assembler
rtconfig.AFLAGS += ' -I' + str(Dir('#')) +' -I' + RTT_ROOT + '/libcpu/arm/armv6'
env = Environment(tools = ['mingw'],
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT)
# make a building
DoBuilding(TARGET, objs)

View File

@@ -0,0 +1,11 @@
import rtconfig
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd, str(Dir('#'))]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@@ -0,0 +1,45 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include <rtthread.h>
#include <components.h>
void init_thread(void *parameter)
{
rt_components_init();
return ;
}
int rt_application_init(void)
{
rt_thread_t tid;
tid = rt_thread_create("init", init_thread, RT_NULL,
4096, RT_THREAD_PRIORITY_MAX/3, 20);
if (tid) rt_thread_startup(tid);
return 0;
}

View File

@@ -0,0 +1,9 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('drivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

1386
bsp/fh8620/drivers/acw.c Normal file

File diff suppressed because it is too large Load Diff

232
bsp/fh8620/drivers/acw.h Normal file
View File

@@ -0,0 +1,232 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef ACW_H_
#define ACW_H_
#include <rtthread.h>
#include <rtdevice.h>
#ifdef RT_USING_DFS
#include <dfs_fs.h>
#endif
#include <rthw.h>
#define ACW_CAP_DMA_CHAN 2
#define ACW_PLY_DMA_CHAN 3
typedef unsigned long long dma_addr_t;
struct scatterlist {
#ifdef CONFIG_DEBUG_SG
unsigned long sg_magic;
#endif
unsigned long page_link;
unsigned int offset;
unsigned int length;
dma_addr_t dma_address;
#ifdef CONFIG_NEED_SG_DMA_LENGTH
unsigned int dma_length;
#endif
};
#define readl(a) (*(volatile rt_uint32_t *)(a))
#define rkqueue_struct rt_workqueue
#define work_struct rt_work
#define INIT_WORK(work,func) rt_work_init(work,func,RT_NULL);
#define queue_work rt_workqueue_dowork
//timer
#define timer_list rt_timer
#define wait_queue_head_t struct rt_event
#define init_waitqueue_head(event_t) rt_event_init(event_t, "audio_event", RT_IPC_FLAG_FIFO)
typedef enum{
AC_SR_8K = 8000,
AC_SR_16K = 16000,
AC_SR_32K = 32000,
AC_SR_441K = 44100,
AC_SR_48K = 48000,
} FH_AC_SAMPLE_RATE_E;
typedef enum{
AC_BW_8 = 8,
AC_BW_16 = 16,
AC_BW_24 = 24,
} FH_AC_BIT_WIDTH_E;
enum io_select{
mic_in = 0,
line_in = 1,
speaker_out = 2,
line_out = 3,
};
struct fh_audio_cfg_arg{
enum io_select io_type;
int volume;
int rate;
int frame_bit;
int channels;
int buffer_size;
int period_size;
};
typedef struct{
unsigned int len;
unsigned char *data;
}FH_AC_FRAME_S;
typedef enum{
FH_AC_MIC_IN = 0,
FH_AC_LINE_IN = 1,
FH_AC_SPK_OUT = 2,
FH_AC_LINE_OUT = 3
}FH_AC_IO_TYPE_E;
typedef struct {
FH_AC_IO_TYPE_E io_type;
FH_AC_SAMPLE_RATE_E sample_rate;
FH_AC_BIT_WIDTH_E bit_width;
unsigned int channels;
unsigned int period_size;
unsigned int volume;
} FH_AC_CONFIG;
struct device_dma_parameters {
/*
* a low level driver may set these to teach IOMMU code about
* sg limitations.
*/
unsigned int max_segment_size;
unsigned long segment_boundary_mask;
};
struct list_head {
struct list_head *next;
struct list_head *prev;
};
struct dma_coherent_mem {
void *virt_base;
dma_addr_t device_base;
int size;
int flags;
unsigned long *bitmap;
};
struct device_acw{
unsigned long long *dma_mask; /* dma mask (if dma'able device) */
unsigned long long coherent_dma_mask;/* Like dma_mask, but for
alloc_coherent mappings as
not all hardware supports
64 bit addresses for consistent
allocations such descriptors. */
struct device_dma_parameters *dma_parms;
struct list_head dma_pools;
struct dma_coherent_mem *dma_mem;
};
#define false 0
#define true 1
#define AC_INIT_CAPTURE_MEM 0x10
#define AC_INIT_PLAYBACK_MEM 0x11
#define AC_SET_VOL 0x12
#define AC_SET_INPUT_MODE 0x13
#define AC_SET_OUTPUT_MODE 0x14
#define AC_AI_EN 0x15
#define AC_AO_EN 0x16
#define AC_AI_DISABLE 0x17
#define AC_AO_DISABLE 0x18
#define AC_AI_PAUSE 0x19
#define AC_AI_RESUME 0x1a
#define AC_AO_PAUSE 0x1b
#define AC_AO_RESUME 0x1c
#define AC_MIC_BOOST 0x1d
#define POLLIN 0x001 /* There is data to read. */
#define POLLPRI 0x002 /* There is urgent data to read. */
#define POLLOUT 0x004 /* Writing now will not block. */
/* These values are defined in XPG4.2. */
# define POLLRDNORM 0x040 /* Normal data may be read. */
# define POLLRDBAND 0x080 /* Priority data may be read. */
# define POLLWRNORM 0x100 /* Writing now will not block. */
# define POLLWRBAND 0x200 /* Priority data may be written. */
/* These are extensions for Linux. */
# define POLLMSG 0x400
# define POLLREMOVE 0x1000
# define POLLRDHUP 0x2000
/* Event types always implicitly polled for. These bits need not be set in
`events', but they will appear in `revents' to indicate the status of
the file descriptor. */
#define POLLERR 0x008 /* Error condition. */
#define POLLHUP 0x010 /* Hung up. */
#define POLLNVAL 0x020 /* Invalid polling request. */
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
extern void fh_audio_init(void);
extern void fh_acw_test();
#endif

170
bsp/fh8620/drivers/dma.c Normal file
View File

@@ -0,0 +1,170 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
/*****************************************************************************
* Include Section
* add all #include here
*****************************************************************************/
#include "drivers/dma.h"
/*****************************************************************************
* Define section
* add all #define here
*****************************************************************************/
/****************************************************************************
* ADT section
* add definition of user defined Data Type that only be used in this file here
***************************************************************************/
/******************************************************************************
* Function prototype section
* add prototypes for all functions called by this file,execepting those
* declared in header file
*****************************************************************************/
/*****************************************************************************
* Global variables section - Exported
* add declaration of global variables that will be exported here
* e.g.
* int8_t foo;
****************************************************************************/
/*****************************************************************************
* static fun;
*****************************************************************************/
static rt_err_t rt_dma_init(struct rt_device *dev);
static rt_err_t rt_dma_open(struct rt_device *dev, rt_uint16_t oflag);
static rt_err_t rt_dma_close(struct rt_device *dev);
static rt_err_t rt_dma_control(struct rt_device *dev,
rt_uint8_t cmd,
void *args);
/*****************************************************************************
* Global variables section - Local
* define global variables(will be refered only in this file) here,
* static keyword should be used to limit scope of local variable to this file
* e.g.
* static uint8_t ufoo;
*****************************************************************************/
/* function body */
/*****************************************************************************
* Description:
* add funtion description here
* Parameters:
* description for each argument, new argument starts at new line
* Return:
* what does this function returned?
*****************************************************************************/
static rt_err_t rt_dma_init(struct rt_device *dev)
{
struct rt_dma_device *dma;
RT_ASSERT(dev != RT_NULL);
dma = (struct rt_dma_device *)dev;
if (dma->ops->init)
{
return (dma->ops->init(dma));
}
return (-RT_ENOSYS);
}
static rt_err_t rt_dma_open(struct rt_device *dev, rt_uint16_t oflag)
{
return (RT_EOK);
}
static rt_err_t rt_dma_close(struct rt_device *dev)
{
struct rt_dma_device *dma;
RT_ASSERT(dev != RT_NULL);
dma = (struct rt_dma_device *)dev;
if (dma->ops->control(dma, RT_DEVICE_CTRL_DMA_CLOSE, RT_NULL) != RT_EOK)
{
return (-RT_ERROR);
}
return (RT_EOK);
}
static rt_err_t rt_dma_control(struct rt_device *dev,
rt_uint8_t cmd,
void *args)
{
struct rt_dma_device *dma;
RT_ASSERT(dev != RT_NULL);
dma = (struct rt_dma_device *)dev;
//args is the private data for the soc!!
return (dma->ops->control(dma, cmd, args));
}
/**
* This function register a dma device
*/
rt_err_t rt_hw_dma_register(struct rt_dma_device *dma,
const char *name,
rt_uint32_t flag,
void *data)
{
rt_uint32_t ret;
struct rt_device *device;
RT_ASSERT(dma != RT_NULL);
device = &(dma->parent);
device->type = RT_Device_Class_Miscellaneous;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
device->init = rt_dma_init;
device->open = rt_dma_open;
device->close = rt_dma_close;
device->read = RT_NULL;
device->write = RT_NULL;
device->control = rt_dma_control;
device->user_data = data;
/* register a character device */
ret = rt_device_register(device, name, flag);
rt_kprintf("dma ret is :%x\n",ret);
return ret;
}

107
bsp/fh8620/drivers/dma.h Normal file
View File

@@ -0,0 +1,107 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef DMA_H_
#define DMA_H_
#include <rtthread.h>
/****************************************************************************
* #include section
* add #include here if any
***************************************************************************/
/****************************************************************************
* #define section
* add constant #define here if any
***************************************************************************/
#define RT_DEVICE_CTRL_DMA_OPEN (1)
#define RT_DEVICE_CTRL_DMA_CLOSE (2)
#define RT_DEVICE_CTRL_DMA_REQUEST_CHANNEL (3)
#define RT_DEVICE_CTRL_DMA_RELEASE_CHANNEL (4)
#define RT_DEVICE_CTRL_DMA_SINGLE_TRANSFER (5)
//cyclic add func below....
#define RT_DEVICE_CTRL_DMA_CYCLIC_PREPARE (6)
#define RT_DEVICE_CTRL_DMA_CYCLIC_START (7)
#define RT_DEVICE_CTRL_DMA_CYCLIC_STOP (8)
#define RT_DEVICE_CTRL_DMA_CYCLIC_FREE (9)
//#define RT_DEVICE_CTRL_ (3) /* get the left time before reboot(in seconds) */
//#define RT_DEVICE_CTRL_ (4) /* refresh watchdog */
//#define RT_DEVICE_CTRL_ (5) /* start watchdog */
//#define RT_DEVICE_CTRL_ (6) /* stop watchdog */
/****************************************************************************
* ADT section
* add Abstract Data Type definition here
***************************************************************************/
struct rt_dma_ops;
struct rt_dma_device
{
// the parent must be the fitst para..
struct rt_device parent;
struct rt_dma_ops *ops;
};
struct rt_dma_ops
{
rt_err_t (*init)(struct rt_dma_device *dma);
rt_err_t (*control)(struct rt_dma_device *dma, int cmd, void *arg);
};
/****************************************************************************
* extern variable declaration section
***************************************************************************/
/****************************************************************************
* section
* add function prototype here if any
***************************************************************************/
rt_err_t rt_hw_dma_register(struct rt_dma_device *dma,
const char *name,
rt_uint32_t flag,
void *data);
/********************************End Of File********************************/
#endif

View File

@@ -0,0 +1,122 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
/*****************************************************************************
* Include Section
* add all #include here
*****************************************************************************/
#include "dma_mem.h"
#ifdef RT_USING_DMA_MEM
/*****************************************************************************
* Define section
* add all #define here
*****************************************************************************/
//#define FH_TEST_DMA_MEM
/****************************************************************************
* ADT section
* add definition of user defined Data Type that only be used in this file here
***************************************************************************/
/******************************************************************************
* Function prototype section
* add prototypes for all functions called by this file,execepting those
* declared in header file
*****************************************************************************/
/*****************************************************************************
* Global variables section - Exported
* add declaration of global variables that will be exported here
* e.g.
* int8_t foo;
****************************************************************************/
/*****************************************************************************
* static fun;
*****************************************************************************/
/*****************************************************************************
* Global variables section - Local
* define global variables(will be refered only in this file) here,
* static keyword should be used to limit scope of local variable to this file
* e.g.
* static uint8_t ufoo;
*****************************************************************************/
static struct rt_memheap dma_heap = {0};
/* function body */
/*****************************************************************************
* Description:
* add funtion description here
* Parameters:
* description for each argument, new argument starts at new line
* Return:
* what does this function returned?
*****************************************************************************/
rt_err_t fh_dma_mem_init(rt_uint32_t *mem_start,rt_uint32_t size){
return rt_memheap_init(&dma_heap,"dma_heap",mem_start,size);
}
void *fh_dma_mem_malloc(rt_uint32_t size){
return rt_memheap_alloc(&dma_heap, size);
}
void fh_dma_mem_free(void *ptr){
rt_memheap_free(ptr);
}
#ifdef FH_TEST_DMA_MEM
int dma_mem_debug(void *ptr){
//rt_memheap_free(ptr);
rt_kprintf("dma mem start 0x%08x\n",(rt_uint32_t)dma_heap.start_addr);
rt_kprintf("dma mem total size 0x%08x\n",dma_heap.pool_size);
rt_kprintf("dma mem left size 0x%08x\n",dma_heap.available_size);
rt_kprintf("dma mem max use size 0x%08x\n",dma_heap.max_used_size);
return 0;
}
#endif
#ifdef RT_USING_FINSH
#include <finsh.h>
#ifdef FH_TEST_DMA_MEM
FINSH_FUNCTION_EXPORT(dma_mem_debug, dma_start & left size & max_use);
#endif
#endif
#endif

View File

@@ -0,0 +1,76 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef DMA_MEM_H_
#define DMA_MEM_H_
#ifndef RT_USING_MEMHEAP
#define RT_USING_MEMHEAP
#endif
#include <rtthread.h>
/****************************************************************************
* #include section
* add #include here if any
***************************************************************************/
/****************************************************************************
* #define section
* add constant #define here if any
***************************************************************************/
/****************************************************************************
* ADT section
* add Abstract Data Type definition here
***************************************************************************/
/****************************************************************************
* extern variable declaration section
***************************************************************************/
/****************************************************************************
* section
* add function prototype here if any
***************************************************************************/
#ifdef RT_USING_DMA_MEM
rt_err_t fh_dma_mem_init(rt_uint32_t *mem_start,rt_uint32_t size);
void *fh_dma_mem_malloc(rt_uint32_t size);
void fh_dma_mem_free(void *ptr);
/********************************End Of File********************************/
#endif
#endif

1618
bsp/fh8620/drivers/fh_dma.c Normal file

File diff suppressed because it is too large Load Diff

254
bsp/fh8620/drivers/fh_dma.h Normal file
View File

@@ -0,0 +1,254 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef FH_DMA_H_
#define FH_DMA_H_
/****************************************************************************
* #include section
* add #include here if any
***************************************************************************/
#include <rtthread.h>
/*********************************
*
* DMA SOC define start
*
*********************************/
#define FH81_MAX_CHANNEL (4)
#define FH81_CHANNEL_MAX_TRANSFER_SIZE (4095)
enum DMA_HW_HS_MAP{
ACODEC_RX = 0,
ACODEC_TX,
SPI0_RX,
SPI0_TX,
SPI1_RX,
SPI1_TX,
UART0_RX,
UART0_TX,
UART1_RX,
UART1_TX,
DMA_HW_HS_END,
};
/*********************************
*
* DMA SOC define end
*
*********************************/
//user use the dma could use callback function,when the dma make the work done...
typedef void (*dma_complete_callback)(void *complete_para);
typedef void (*user_prepare)(void *prepare_para);
/**************************** i'm cut-off line ************************************/
//controller private para...
struct fh81_dma;
struct dw_lli {
/* values that are not changed by hardware */
rt_uint32_t sar;
rt_uint32_t dar;
rt_uint32_t llp; /* chain to next lli */
rt_uint32_t ctllo;
/* values that may get written back: */
rt_uint32_t ctlhi;
/* sstat and dstat can snapshot peripheral register state.
* silicon config may discard either or both...
*/
rt_uint32_t sstat;
rt_uint32_t dstat;
rt_uint32_t reserve;
};
//transfer use below
struct dma_transfer{
//this is private for the dma drive....app don't touch it,the driver will manger it
//link interface for more transfer to the controller...
rt_list_t transfer_list;
struct fh81_dma *dma_controller;
//this the mem add....the dma controller will load the setting to move data ....
//user don't touch it
struct dw_lli *first_lli;
rt_uint32_t lli_size;
//new add for allign get desc...
rt_uint32_t actual_lli_size;
//user could set paras below~~~
#define AUTO_FIND_CHANNEL (0xff)
//transfer with which dma channel...if the data is 0xff, the driver will auto find a free channel.
rt_uint32_t channel_number;
//which dma you want to use...for fh81....only 0!!!
rt_uint32_t dma_number;
//user should set the para below
#define DMA_M2M (0) // MEM <=> MEM
#define DMA_M2P (1) // MEM => peripheral A
#define DMA_P2M (2) // MEM <= peripheral A
#define DMA_P2P (3) // peripheral A <=> peripheral B
rt_uint32_t fc_mode;//ip->mem. mem->mem. mem->ip
#define DMA_HW_HANDSHAKING (0)
#define DMA_SW_HANDSHAKING (1)
rt_uint32_t src_hs; //src
//if use hw handshaking ,you need to set the hw handshaking number, this SOC defined
rt_uint32_t src_per; //src hw handshake number
//rt_uint32_t irq_mode;//for each transfer,irq maybe not same. suggest for the default(transfer isr)
#define DW_DMA_SLAVE_WIDTH_8BIT (0)
#define DW_DMA_SLAVE_WIDTH_16BIT (1)
#define DW_DMA_SLAVE_WIDTH_32BIT (2)
rt_uint32_t src_width;
//the user should reference the hw handshaking watermark..
#define DW_DMA_SLAVE_MSIZE_1 (0)
#define DW_DMA_SLAVE_MSIZE_4 (1)
#define DW_DMA_SLAVE_MSIZE_8 (2)
#define DW_DMA_SLAVE_MSIZE_16 (3)
#define DW_DMA_SLAVE_MSIZE_32 (4)
#define DW_DMA_SLAVE_MSIZE_64 (5)
#define DW_DMA_SLAVE_MSIZE_128 (6)
#define DW_DMA_SLAVE_MSIZE_256 (7)
rt_uint32_t src_msize;
rt_uint32_t src_add;
#define DW_DMA_SLAVE_INC (0)
#define DW_DMA_SLAVE_DEC (1)
#define DW_DMA_SLAVE_FIX (2)
rt_uint32_t src_inc_mode; //increase mode: increase or not change
//#define DMA_DST_HW_HANDSHAKING (0)
//#define DMA_DST_SW_HANDSHAKING (1)
rt_uint32_t dst_hs; //src
//if use hw handshaking ,you need to set the hw handshaking number, this SOC defined
rt_uint32_t dst_per; //dst hw handshake number
//#define DW_DMA_SLAVE_WIDTH_8BIT (0)
//#define DW_DMA_SLAVE_WIDTH_16BIT (1)
//#define DW_DMA_SLAVE_WIDTH_32BIT (2)
rt_uint32_t dst_width;
//#define DW_DMA_SLAVE_MSIZE_1 (0)
//#define DW_DMA_SLAVE_MSIZE_4 (1)
//#define DW_DMA_SLAVE_MSIZE_8 (2)
//#define DW_DMA_SLAVE_MSIZE_16 (3)
//#define DW_DMA_SLAVE_MSIZE_32 (4)
//#define DW_DMA_SLAVE_MSIZE_64 (5)
//#define DW_DMA_SLAVE_MSIZE_128 (6)
//#define DW_DMA_SLAVE_MSIZE_256 (7)
rt_uint32_t dst_msize;
rt_uint32_t dst_add;
//#define DW_DMA_SLAVE_INC (0)
//#define DW_DMA_SLAVE_DEC (1)
//#define DW_DMA_SLAVE_FIX (2)
rt_uint32_t dst_inc_mode; //increase mode: increase or not change
//total sizes, unit: src_width/DW_DMA_SLAVE_WIDTH_8BIT...
//exg: src_width = DW_DMA_SLAVE_WIDTH_32BIT. trans_len = 2...means that: the dma will transfer 2*4 bytes..
//exg: src_width = DW_DMA_SLAVE_WIDTH_8BIT. trans_len = 6...means that: the dma will transfer 1*6 bytes..
rt_uint32_t trans_len;
//this is used when dma finish transfer job
dma_complete_callback complete_callback;
void *complete_para; //for the driver data use the dma driver.
//this is used when dma before work..the user maybe need to set his own private para..
user_prepare prepare_callback;
void *prepare_para;
//add cyclic para...
//period len..
rt_uint32_t period_len;
};
/****************************************************************************
* #define section
* add constant #define here if any
***************************************************************************/
/****************************************************************************
* ADT section
* add Abstract Data Type definition here
***************************************************************************/
/****************************************************************************
* extern variable declaration section
***************************************************************************/
/****************************************************************************
* section
* add function prototype here if any
***************************************************************************/
rt_err_t fh81_dma_register(struct fh81_dma * fh81_dma_p,
char * dma_name);
void rt_fh_dma_init(void);
/********************************End Of File********************************/
#endif /* FH81_DMA_H_ */

450
bsp/fh8620/drivers/gpio.c Normal file
View File

@@ -0,0 +1,450 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include "fh_def.h"
#include "gpio.h"
#include "Libraries/inc/fh_gpio.h"
#include "interrupt.h"
#include "board_info.h"
#include <rtdevice.h>
#include "fh_arch.h"
//#define FH_GPIO_DEBUG
#ifdef FH_GPIO_DEBUG
#define PRINT_GPIO_DBG(fmt, args...) \
do \
{ \
rt_kprintf("FH_GPIO_DEBUG: "); \
rt_kprintf(fmt, ## args); \
} \
while(0)
#else
#define PRINT_GPIO_DBG(fmt, args...) do { } while (0)
#endif
int gpio_available[NUM_OF_GPIO];
extern struct rt_irq_desc irq_desc[];
static inline rt_uint32_t gpio_to_base(rt_uint32_t gpio)
{
if (gpio >= 32 && gpio < 64)
{
return GPIO1_REG_BASE;
}
else if(gpio < 32)
{
return GPIO0_REG_BASE;
}
else
{
rt_kprintf("ERROR: %s, incorrect GPIO num\n", __func__);
return -RT_ERROR;
}
}
static inline rt_uint32_t irq_to_base(rt_uint32_t irq)
{
return (irq-NR_INTERNAL_IRQS > 32) ? GPIO1_REG_BASE : GPIO0_REG_BASE;
}
static inline rt_uint32_t irq_to_bit(rt_uint32_t irq)
{
if(irq >= NR_INTERNAL_IRQS && irq < NR_INTERNAL_IRQS + 32)
return 0;
else
return 32;
}
rt_uint32_t gpio_to_irq(rt_uint32_t gpio)
{
return (gpio + NR_INTERNAL_IRQS);
}
void gpio_enable_debounce(rt_uint32_t gpio)
{
rt_uint32_t tmp, base, offset;
offset = gpio % 32;
base = gpio_to_base(gpio);
tmp = GET_REG(base + REG_GPIO_DEBOUNCE);
tmp |= BIT(offset);
SET_REG(base + REG_GPIO_DEBOUNCE, tmp);
}
void gpio_disable_debounce(rt_uint32_t gpio)
{
rt_uint32_t tmp, base, offset;
offset = gpio % 32;
base = gpio_to_base(gpio);
tmp = GET_REG(base + REG_GPIO_DEBOUNCE);
tmp &= ~BIT(offset);
SET_REG(base + REG_GPIO_DEBOUNCE, tmp);
}
int gpio_get_value(rt_uint32_t gpio)
{
rt_uint32_t tmp, base, offset;
offset = gpio % 32;
base = gpio_to_base(gpio);
tmp = GET_REG(base + REG_GPIO_SWPORTA_DDR);
tmp &= BIT(offset);
if (tmp) {
tmp = GET_REG(base + REG_GPIO_SWPORTA_DR);
} else {
tmp = GET_REG(base + REG_GPIO_EXT_PORTA);
}
tmp &= BIT(offset);
tmp = tmp >> offset;
return tmp;
}
void gpio_set_value(rt_uint32_t gpio, int val)
{
rt_uint32_t tmp, base, offset;
offset = gpio % 32;
base = gpio_to_base(gpio);
tmp = GET_REG(base + REG_GPIO_SWPORTA_DR);
if(val)
tmp |= BIT(offset);
else
tmp &= ~BIT(offset);
SET_REG(base + REG_GPIO_SWPORTA_DR, tmp);
}
int gpio_get_direction(rt_uint32_t gpio)
{
rt_uint32_t tmp, base, offset;
offset = gpio % 32;
base = gpio_to_base(gpio);
tmp = GET_REG(base + REG_GPIO_SWPORTA_DDR);
tmp &= BIT(offset);
tmp = tmp >> offset;
return tmp;
}
void gpio_set_direction(rt_uint32_t gpio, rt_uint32_t direction)
{
rt_uint32_t tmp, base, offset;
offset = gpio % 32;
base = gpio_to_base(gpio);
tmp = GET_REG(base + REG_GPIO_SWPORTA_DDR);
if(direction == GPIO_DIR_OUTPUT)
tmp |= BIT(offset);
else
tmp &= ~BIT(offset);
SET_REG(base + REG_GPIO_SWPORTA_DDR, tmp);
}
int gpio_set_irq_type(rt_uint32_t gpio, rt_uint32_t type)
{
rt_uint32_t int_type, int_polarity;
rt_uint32_t bit = gpio % 32;
rt_uint32_t base;
base = gpio_to_base(gpio);
int_type = GET_REG(base + REG_GPIO_INTTYPE_LEVEL);
int_polarity = GET_REG(base + REG_GPIO_INT_POLARITY);
switch (type & IRQ_TYPE_TRIGGER_MASK) {
case IRQ_TYPE_EDGE_BOTH:
int_type |= BIT(bit);
// toggle trigger
if (gpio_get_value(gpio))
int_polarity &= ~BIT(bit);
else
int_polarity |= BIT(bit);
break;
case IRQ_TYPE_EDGE_RISING:
int_type |= BIT(bit);
int_polarity |= BIT(bit);
break;
case IRQ_TYPE_EDGE_FALLING:
int_type |= BIT(bit);
int_polarity &= ~BIT(bit);
break;
case IRQ_TYPE_LEVEL_HIGH:
int_type &= ~BIT(bit);
int_polarity |= BIT(bit);
break;
case IRQ_TYPE_LEVEL_LOW:
int_type &= ~BIT(bit);
int_polarity &= ~BIT(bit);
break;
case IRQ_TYPE_NONE:
return 0;
default:
return -RT_ERROR;
}
SET_REG(base + REG_GPIO_INTTYPE_LEVEL, int_type);
SET_REG(base + REG_GPIO_INT_POLARITY, int_polarity);
return 0;
}
int gpio_irq_mask(rt_uint32_t irq)
{
rt_uint32_t tmp, base, bit;
base = irq_to_base(irq);
bit = irq_to_bit(irq);
tmp = GET_REG(base + REG_GPIO_INTMASK);
tmp |= BIT(irq - NR_INTERNAL_IRQS - bit);
SET_REG(base + REG_GPIO_INTMASK, tmp);
return 0;
}
int gpio_irq_unmask(rt_uint32_t irq)
{
rt_uint32_t tmp, base, bit;
base = irq_to_base(irq);
bit = irq_to_bit(irq);
tmp = GET_REG(base + REG_GPIO_INTMASK);
tmp &= ~BIT((irq - NR_INTERNAL_IRQS - bit));
SET_REG(base + REG_GPIO_INTMASK, tmp);
return 0;
}
void gpio_irq_enable(rt_uint32_t irq)
{
rt_uint32_t tmp, base, bit;
base = irq_to_base(irq);
bit = irq_to_bit(irq);
tmp = GET_REG(base + REG_GPIO_INTEN);
tmp |= BIT(irq - NR_INTERNAL_IRQS - bit);
SET_REG(base + REG_GPIO_INTEN, tmp);
}
void gpio_irq_disable(rt_uint32_t irq)
{
rt_uint32_t tmp, base, bit;
base = irq_to_base(irq);
bit = irq_to_bit(irq);
tmp = GET_REG(base + REG_GPIO_INTEN);
tmp &= ~BIT((irq - NR_INTERNAL_IRQS - bit));
SET_REG(base + REG_GPIO_INTEN, tmp);
}
static void fh_gpio_interrupt(int irq, void *param)
{
rt_uint32_t irq_status;
int gpio_num, gpio;
rt_uint32_t base;
struct fh_gpio_obj *gpio_obj = (struct fh_gpio_obj *)param;
//rt_kprintf("fh_gpio_interrupt start\n");
//fixme: spin lock???
base = (irq==40) ? GPIO0_REG_BASE : GPIO1_REG_BASE;
irq_status = GET_REG(base + REG_GPIO_INTSTATUS);
if (irq_status == 0) {
rt_kprintf("gpio irq status is zero.\n");
return;
}
/* temporarily mask (level sensitive) parent IRQ */
gpio_irq_mask(irq);
gpio_num = __rt_ffs(irq_status) - 1;
SET_REG(base + REG_GPIO_PORTA_EOI, BIT(gpio_num));
gpio = gpio_num + ((irq==40) ? 0 : 32);
//generic_handle_irq(gpio_to_irq(gpio));
if(irq_desc[gpio_to_irq(gpio)].handler)
irq_desc[gpio_to_irq(gpio)].handler(gpio_to_irq(gpio), irq_desc[gpio_to_irq(gpio)].param);
gpio_irq_mask(irq);
/* now it may re-trigger */
}
int gpio_direction_input(rt_uint32_t gpio)
{
rt_uint32_t reg, base;
if(gpio > NUM_OF_GPIO)
{
rt_kprintf("ERROR: %s, incorrect GPIO num\n", __func__);
return -RT_ERROR;
}
if(!gpio_available[gpio])
{
rt_kprintf("ERROR: %s, GPIO %d is not available\n", __func__, gpio);
return -RT_EBUSY;
}
base = gpio_to_base(gpio);
gpio = gpio % 32;
//fixme: lock
//spin_lock_irqsave(&chip->lock, flags);
reg = GET_REG(base + REG_GPIO_SWPORTA_DDR);
reg &= ~(1 << gpio);
SET_REG(base + REG_GPIO_SWPORTA_DDR, reg);
//spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
int gpio_direction_output(rt_uint32_t gpio, rt_uint32_t val)
{
rt_uint32_t reg, base;
if(gpio > NUM_OF_GPIO)
{
rt_kprintf("ERROR: %s, incorrect GPIO num\n", __func__);
return -RT_ERROR;
}
if(!gpio_available[gpio])
{
rt_kprintf("ERROR: %s, GPIO %d is not available\n", __func__, gpio);
return -RT_EBUSY;
}
base = gpio_to_base(gpio);
gpio = gpio % 32;
//fixme: lock
//spin_lock_irqsave(&chip->lock, flags);
reg = GET_REG(base + REG_GPIO_SWPORTA_DDR);
reg |= (1 << gpio);
SET_REG(base + REG_GPIO_SWPORTA_DDR, reg);
reg = GET_REG(base + REG_GPIO_SWPORTA_DR);
if(val)
reg |= (1 << gpio);
else
reg &= ~(1 << gpio);
SET_REG(base + REG_GPIO_SWPORTA_DR, reg);
//spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
int gpio_request(rt_uint32_t gpio)
{
if(gpio > NUM_OF_GPIO)
{
rt_kprintf("ERROR: %s, incorrect GPIO num\n", __func__);
return -RT_ERROR;
}
gpio_available[gpio] = 1;
return 0;
}
int gpio_release(rt_uint32_t gpio)
{
if(gpio > NUM_OF_GPIO)
{
rt_kprintf("ERROR: %s, incorrect GPIO num\n", __func__);
return -RT_ERROR;
}
gpio_available[gpio] = 0;
return 0;
}
int fh_gpio_probe(void *priv_data)
{
struct fh_gpio_obj *gpio_obj = (struct fh_gpio_obj *)priv_data;
int i;
if(gpio_obj->id == 0){
rt_hw_interrupt_install(gpio_obj->irq, fh_gpio_interrupt, (void *)gpio_obj, "gpio_0");
}
else if(gpio_obj->id == 1){
rt_hw_interrupt_install(gpio_obj->irq, fh_gpio_interrupt, (void *)gpio_obj, "gpio_1");
}
rt_hw_interrupt_umask(gpio_obj->irq);
for(i=0; i<32; i++)
{
irq_desc[NR_INTERNAL_IRQS + 32 * gpio_obj->id + i].param = gpio_obj;
}
return 0;
}
int fh_gpio_exit(void *priv_data)
{
return 0;
}
struct fh_board_ops gpio_driver_ops =
{
.probe = fh_gpio_probe,
.exit = fh_gpio_exit,
};
void rt_hw_gpio_init(void)
{
PRINT_GPIO_DBG("%s start\n", __func__);
rt_memset(gpio_available, 0, sizeof(int) * NUM_OF_GPIO);
fh_board_driver_register("gpio", &gpio_driver_ops);
PRINT_GPIO_DBG("%s end\n", __func__);
}

188
bsp/fh8620/drivers/gpio.h Normal file
View File

@@ -0,0 +1,188 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef GPIO_H_
#define GPIO_H_
#include <rtdef.h>
/**
* GPIO interrupt trigger type macro,
* each represent an interrupt trigger mode
*
* @see gpio_set_irq_type();
*/
enum
{
IRQ_TYPE_NONE = 0x00000000, /**< none*/
IRQ_TYPE_EDGE_RISING = 0x00000001, /**< rising edge*/
IRQ_TYPE_EDGE_FALLING = 0x00000002, /**< falling edge*/
IRQ_TYPE_EDGE_BOTH = (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING),
IRQ_TYPE_LEVEL_HIGH = 0x00000004, /**< high level*/
IRQ_TYPE_LEVEL_LOW = 0x00000008, /**< low level*/
IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH),
IRQ_TYPE_TRIGGER_MASK = (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW | \
IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING),
};
/**
* GPIO direction macro,
* each represent a direction
*
* @see gpio_get_direction();
* @see gpio_set_direction();
*/
#define GPIO_DIR_OUTPUT 1 /**< output*/
#define GPIO_DIR_INPUT 0 /**< input*/
/**
* convert GPIO number to IRQ number
* @param gpio GPIO number to be converted
* @return IRQ number
*/
rt_uint32_t gpio_to_irq(rt_uint32_t gpio);
/**
* disable GPIO's debounce mode
* controls whether an external signal that is the source
* of an interrupt needs to be debounced to remove any
* spurious glitches.
* @param gpio GPIO number
*/
void gpio_disable_debounce(rt_uint32_t gpio);
/**
* enable GPIO's debounce mode
* controls whether an external signal that is the source
* of an interrupt needs to be debounced to remove any
* spurious glitches.
* @param gpio GPIO number
*/
void gpio_enable_debounce(rt_uint32_t gpio);
/**
* allows each GPIO to be configured for interrupts
* it configures the corresponding GPIO to become an interrupt
* @param gpio GPIO number
*/
void gpio_irq_enable(rt_uint32_t irq);
/**
* GPIO operates as a normal GPIO signal
* interrupts are disabled
* @param gpio GPIO number
*/
void gpio_irq_disable(rt_uint32_t irq);
/**
* it configures the interrupt type to be
* falling-edge or active-low sensitive
* rising-edge or active-high sensitive.
* @param gpio GPIO number
* @param type interrupt type
* @return 0 if OK
*/
int gpio_set_irq_type(rt_uint32_t gpio, rt_uint32_t type);
/**
* mask the interrupt
* @param gpio GPIO number
* @return 0 if OK
*/
int gpio_irq_mask(rt_uint32_t irq);
/**
* unmask the interrupt
* @param gpio GPIO number
* @return 0 if OK
*/
int gpio_irq_unmask(rt_uint32_t irq);
/**
* get corresponding GPIO's direction
* @param gpio GPIO number
* @return 0 - input
* 1 - output
*/
int gpio_get_direction(rt_uint32_t gpio);
/**
* set corresponding GPIO's direction
* @param gpio GPIO number
* @return 0 - input
* 1 - output
*/
void gpio_set_direction(rt_uint32_t gpio, rt_uint32_t direction);
/**
* get corresponding GPIO's value
* @param gpio GPIO number
* @return GPIO value
*/
int gpio_get_value(rt_uint32_t gpio);
/**
* set corresponding GPIO's value
* @param gpio GPIO number
* @param val GPIO value
*/
void gpio_set_value(rt_uint32_t gpio, int val);
/**
* set corresponding GPIO's direction to input
* @param gpio GPIO number
* @return 0 if OK
*/
int gpio_direction_input(rt_uint32_t gpio);
/**
* set corresponding GPIO's value and set direction to output
* @param gpio GPIO number
* @param val GPIO value
* @return 0 if OK
*/
int gpio_direction_output(rt_uint32_t gpio, rt_uint32_t val);
/**
* request a GPIO
* @param gpio GPIO number
* @return 0 if OK
*/
int gpio_request(rt_uint32_t gpio);
/**
* release a GPIO
* @param gpio GPIO number
* @return 0 if OK
*/
int gpio_release(rt_uint32_t gpio);
/**
* initialize GPIO driver
*/
void rt_hw_gpio_init(void);
#endif /* GPIO_H_ */

520
bsp/fh8620/drivers/i2c.c Normal file

File diff suppressed because it is too large Load Diff

56
bsp/fh8620/drivers/i2c.h Normal file
View File

@@ -0,0 +1,56 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef __FH81_I2C_H__
#define __FH81_I2C_H__
#include <rtthread.h>
struct i2c_driver
{
int cmd_err;
int msg_err;
rt_uint32_t status;
struct rt_i2c_msg *msgs;
int msgs_num;
int msg_write_idx;
rt_uint32_t tx_buf_len;
rt_uint8_t *tx_buf;
int msg_read_idx;
rt_uint32_t rx_buf_len;
rt_uint8_t *rx_buf;
struct rt_i2c_bus_device *i2c_bus_dev;
struct rt_completion transfer_completion;
rt_mutex_t lock;
void* priv;
};
void rt_hw_i2c_init(void);
#endif

View File

@@ -0,0 +1,216 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
/*****************************************************************************
* Include Section
* add all #include here
*****************************************************************************/
#include "interrupt.h"
#include "fh_def.h"
#include "fh_arch.h"
#include "Libraries/inc/fh_ictl.h"
/*****************************************************************************
* Define section
* add all #define here
*****************************************************************************/
#define MAX_HANDLERS (NR_INTERNAL_IRQS+NR_EXTERNAL_IRQS)
/****************************************************************************
* ADT section
* add definition of user defined Data Type that only be used in this file here
***************************************************************************/
/******************************************************************************
* Function prototype section
* add prototypes for all functions called by this file,execepting those
* declared in header file
*****************************************************************************/
/*****************************************************************************
* Global variables section - Exported
* add declaration of global variables that will be exported here
* e.g.
* int8_t foo;
****************************************************************************/
extern rt_uint32_t rt_interrupt_nest;
struct rt_irq_desc irq_desc[MAX_HANDLERS];
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
rt_uint32_t rt_thread_switch_interrupt_flag;
/*****************************************************************************
* Global variables section - Local
* define global variables(will be refered only in this file) here,
* static keyword should be used to limit scope of local variable to this file
* e.g.
* static uint8_t ufoo;
*****************************************************************************/
/* function body */
/*****************************************************************************
* Description:
* add funtion description here
* Parameters:
* description for each argument, new argument starts at new line
* Return:
* what does this function returned?
*****************************************************************************/
rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
{
rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
return RT_NULL;
}
/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init(void)
{
rt_int32_t i;
register rt_uint32_t idx;
fh_intc *p = (fh_intc *)INTC_REG_BASE;
ictl_close_all_isr(p);
/* init exceptions table */
for(idx=0; idx < MAX_HANDLERS; idx++)
{
irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
irq_desc[idx].param = RT_NULL;
#ifdef RT_USING_INTERRUPT_INFO
rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
irq_desc[idx].counter = 0;
#endif
}
/* init interrupt nest, and context in thread sp */
rt_interrupt_nest = 0;
rt_interrupt_from_thread = 0;
rt_interrupt_to_thread = 0;
rt_thread_switch_interrupt_flag = 0;
}
/**
* This function will mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_mask(int irq)
{
fh_intc *p = (fh_intc *)INTC_REG_BASE;
/* Disable irq on AIC */
ictl_mask_isr(p,irq);
// if (irq < 32)
// p->IRQ_EN_L &= ~(1 << irq);
// else
// p->IRQ_EN_H &= ~(1 << (irq - 32));
}
void rt_hw_interrupt_umask(int irq)
{
fh_intc *p = (fh_intc *)INTC_REG_BASE;
/* Enable irq on AIC */
ictl_unmask_isr(p,irq);
// if (irq < 32)
// p->IRQ_EN_L |= 1 << irq;
// else
// p->IRQ_EN_H |= 1 << (irq - 32);
}
/**
* This function will install a interrupt service routine to a interrupt.
* @param vector the interrupt number
* @param handler the interrupt service routine to be installed
* @param param the interrupt service function parameter
* @param name the interrupt name
* @return old handler
*/
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
if(vector < MAX_HANDLERS)
{
old_handler = irq_desc[vector].handler;
if (handler != RT_NULL)
{
irq_desc[vector].handler = (rt_isr_handler_t)handler;
irq_desc[vector].param = param;
#ifdef RT_USING_INTERRUPT_INFO
rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
irq_desc[vector].counter = 0;
#endif
}
}
return old_handler;
}
#ifdef RT_USING_FINSH
void list_irq(void)
{
#ifdef RT_USING_INTERRUPT_INFO
int irq;
rt_kprintf("number\tcount\tname\n");
for (irq = 0; irq < MAX_HANDLERS; irq++)
{
if (rt_strncmp(irq_desc[irq].name, "default", sizeof("default")))
{
rt_kprintf("%02ld: %10ld %s\n", irq, irq_desc[irq].counter, irq_desc[irq].name);
}
}
#else
rt_kprintf("please open 'RT_USING_INTERRUPT_INFO'\n");
#endif
}
#include <finsh.h>
FINSH_FUNCTION_EXPORT(list_irq, list system irq);
#endif

View File

@@ -0,0 +1,40 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef INTERRUPT_H_
#define INTERRUPT_H_
#include <rthw.h>
#define NR_INTERNAL_IRQS 56
#define NR_EXTERNAL_IRQS 64
void rt_hw_interrupt_init(void);
void rt_hw_interrupt_mask(int irq);
void rt_hw_interrupt_umask(int irq);
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, char *name);
#endif /* INTERRUPT_H_ */

View File

@@ -0,0 +1,87 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "mmu.h"
#define CHANGLINE_SIZE (1)
//#define FH_DBG_MEM_PROCESS
#ifdef FH_DBG_MEM_PROCESS
void mem_input(rt_uint32_t t_addr, rt_uint32_t t_size, rt_uint8_t t_value) {
rt_kprintf("mem process add:%x \tsize:%x\tvalue:%x\n", t_addr, t_size,
t_value);
rt_memset((void *) t_addr, t_value, t_size);
mmu_clean_invalidated_dcache(t_addr, t_size);
}
void mem_output(rt_uint32_t t_addr, rt_uint32_t t_size) {
rt_uint32_t i;
rt_uint32_t cnt = 0;
rt_uint32_t value;
rt_uint32_t addr, size;
addr = t_addr;
if (t_size % 4) {
rt_kprintf("mem must be alligned\n");
}
size = t_size / 4;
rt_int32_t *p = (rt_uint32_t *) t_addr;
//mmu_clean_invalidated_dcache(addr,t_size);
rt_kprintf("mem process add:0x%x \tsize:0x%x\n", addr, t_size);
rt_kprintf("0x%08x:", addr);
for (i = 0; i < size; i++) {
value = *p++;
if ((cnt / CHANGLINE_SIZE) && (cnt % CHANGLINE_SIZE == 0)) {
rt_kprintf("\n");
}
if (cnt / CHANGLINE_SIZE && (cnt % CHANGLINE_SIZE) == 0) {
rt_kprintf("0x%08x:", addr + i * 4);
}
rt_kprintf("\t%08x", value);
cnt++;
}
rt_kprintf("\n");
}
#endif
#ifdef RT_USING_FINSH
#include <finsh.h>
#ifdef FH_DBG_MEM_PROCESS
FINSH_FUNCTION_EXPORT(mem_input, mem_input(addr,size,value));
FINSH_FUNCTION_EXPORT(mem_output, mem_output(add,size));
#endif
#endif

710
bsp/fh8620/drivers/mmc.c Normal file

File diff suppressed because it is too large Load Diff

51
bsp/fh8620/drivers/mmc.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef MMC_H_
#define MMC_H_
#include "Libraries/inc/fh_driverlib.h"
#define MMC_FEQ_MIN 100000
#define MMC_FEQ_MAX 50000000
#define CARD_UNPLUGED 1
#define CARD_PLUGED 0
struct mmc_driver
{
MMC_DMA_Descriptors* dma_descriptors;
rt_uint32_t max_desc;
struct rt_mmcsd_host *host;
struct rt_mmcsd_req *req;
struct rt_mmcsd_data *data;
struct rt_mmcsd_cmd *cmd;
struct rt_completion transfer_completion;
void* priv;
};
void rt_hw_mmc_init(void);
#endif /* MMC_H_ */

226
bsp/fh8620/drivers/pwm.c Normal file
View File

@@ -0,0 +1,226 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include "fh_def.h"
#include "pwm.h"
#include "interrupt.h"
#include "board_info.h"
#include "inc/fh_driverlib.h"
#include <rtdevice.h>
#ifdef FH_PWM_DEBUG
#define PRINT_PWM_DBG(fmt, args...) \
do \
{ \
rt_kprintf("FH_PWM_DEBUG: "); \
rt_kprintf(fmt, ## args); \
} \
while(0)
#else
#define PRINT_PWM_DBG(fmt, args...) do { } while (0)
#endif
static struct pwm_driver pwm_drv =
{
};
static int pwm_get_duty_cycle_ns(struct pwm_device* pwm)
{
struct fh_pwm_obj *pwm_obj = (struct fh_pwm_obj *)pwm_drv.priv;
rt_uint32_t reg, period, duty;
rt_uint32_t clk_rate = 1000000/*todo: clk_get_rate(fh_pwm_ctrl.clk)*/;
reg = PWM_GetPwmCmd(pwm_obj, pwm->id);
period = reg & 0x0fff;
duty = (reg >> 16) & 0xfff;
duty = period - duty; //reverse duty cycle
if(period == 0)
{
period = duty;
}
pwm->counter_ns = duty * 1000000000 / clk_rate;
pwm->period_ns = period * 1000000000 / clk_rate;
PRINT_PWM_DBG("get duty: %d, period: %d, reg: 0x%x\n", duty, period, reg);
return 0;
}
static int pwm_set_duty_cycle_ns(struct pwm_device* pwm)
{
struct fh_pwm_obj *pwm_obj = (struct fh_pwm_obj *)pwm_drv.priv;
rt_uint32_t period, duty, reg, clk_rate, duty_revert;
clk_rate = 1000000/*todo: clk_get_rate(fh_pwm_ctrl.clk)*/;
if(!clk_rate)
{
rt_kprintf("PWM: clock rate is 0\n");
return -RT_EIO;
}
period = pwm->period_ns / (1000000000 / clk_rate);
if(period < 8)
{
rt_kprintf("PWM: min period is 8\n");
return -RT_EIO;
}
duty = pwm->counter_ns / (1000000000 / clk_rate);
if(period < duty)
{
rt_kprintf("PWM: period < duty\n");
return -RT_EIO;
}
duty_revert = period - duty;
if(duty == period)
{
reg = (duty & 0xfff) << 16 | (0 & 0xfff);
}
else
{
reg = (duty_revert & 0xfff) << 16 | (period & 0xfff);
}
PRINT_PWM_DBG("set duty_revert: %d, period: %d, reg: 0x%x\n", duty_revert, period, reg);
PWM_SetPwmCmd(pwm_obj, pwm->id, reg);
return 0;
}
static rt_err_t fh_pwm_open(rt_device_t dev, rt_uint16_t oflag)
{
struct fh_pwm_obj *pwm_obj = (struct fh_pwm_obj *)pwm_drv.priv;
PWM_Enable(pwm_obj, RT_TRUE);
return 0;
}
static rt_err_t fh_pwm_close(rt_device_t dev)
{
struct fh_pwm_obj *pwm_obj = (struct fh_pwm_obj *)pwm_drv.priv;
PWM_Enable(pwm_obj, RT_FALSE);
return 0;
}
static rt_err_t fh_pwm_ioctl(rt_device_t dev, rt_uint8_t cmd, void *arg)
{
int ret = 0;
struct pwm_device *pwm;
struct fh_pwm_obj *pwm_obj = (struct fh_pwm_obj *)pwm_drv.priv;
switch(cmd)
{
case ENABLE_PWM:
PWM_Enable(pwm_obj, RT_FALSE);
break;
case DISABLE_PWM:
PWM_Enable(pwm_obj, RT_TRUE);
break;
case SET_PWM_DUTY_CYCLE:
pwm = (struct pwm_device *)arg;
PRINT_PWM_DBG("ioctl: pwm addr: %p, pwm->period: %d ns\n", pwm, pwm->period_ns);
pwm_set_duty_cycle_ns(pwm);
break;
case GET_PWM_DUTY_CYCLE:
pwm = (struct pwm_device *)arg;
PRINT_PWM_DBG("ioctl: pwm->id: %d, pwm->counter: %d, pwm->period: %d\n", pwm->id, pwm->counter_ns, pwm->period_ns);
pwm_get_duty_cycle_ns(pwm);
break;
}
return ret;
}
int fh_pwm_probe(void *priv_data)
{
rt_device_t pwm_dev ;
struct fh_pwm_obj *pwm_obj = (struct fh_pwm_obj *)priv_data;
rt_memset(&pwm_drv, 0, sizeof(struct pwm_driver));
pwm_drv.pwm[0].id = 0;
pwm_drv.pwm[1].id = 1;
pwm_drv.pwm[2].id = 2;
pwm_drv.pwm[0].working = 0;
pwm_drv.pwm[1].working = 0;
pwm_drv.pwm[2].working = 0;
pwm_drv.priv = pwm_obj;
//todo: clk
PWM_Enable(pwm_obj, RT_FALSE);
pwm_dev = rt_malloc(sizeof(struct rt_device));
rt_memset(pwm_dev, 0, sizeof(struct rt_device));
if (pwm_dev == RT_NULL)
{
rt_kprintf("ERROR: %s rt_device malloc failed\n", __func__);
}
pwm_dev->user_data = &pwm_drv;
pwm_dev->open =fh_pwm_open;
pwm_dev->close = fh_pwm_close;
pwm_dev->control = fh_pwm_ioctl;
pwm_dev->type = RT_Device_Class_Miscellaneous;
rt_device_register(pwm_dev, "pwm", RT_DEVICE_FLAG_RDWR);
return 0;
}
int fh_pwm_exit(void *priv_data)
{
return 0;
}
struct fh_board_ops pwm_driver_ops =
{
.probe = fh_pwm_probe,
.exit = fh_pwm_exit,
};
void rt_hw_pwm_init(void)
{
PRINT_PWM_DBG("%s start\n", __func__);
fh_board_driver_register("pwm", &pwm_driver_ops);
PRINT_PWM_DBG("%s end\n", __func__);
}

57
bsp/fh8620/drivers/pwm.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef PWM_H_
#define PWM_H_
#include <rtthread.h>
#define ENABLE_PWM (0x10)
#define DISABLE_PWM (0x11)
#define SET_PWM_DUTY_CYCLE (0x12)
#define GET_PWM_DUTY_CYCLE (0x13)
struct pwm_device
{
int id;
int working;
rt_uint32_t period_ns;
rt_uint32_t counter_ns;
};
struct pwm_driver
{
//struct clk *clk;
struct pwm_device pwm[3];
struct pwm_device *cur;
void* priv;
};
#endif /* PWM_H_ */

416
bsp/fh8620/drivers/sadc.c Normal file
View File

@@ -0,0 +1,416 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include "sadc.h"
#ifdef RT_USING_SADC
#include "inc/fh_driverlib.h"
#include "board_info.h"
#include <rtdef.h>
//#define FH_SADC_DEBUG
//#define FH_TEST_SADC
#ifdef FH_SADC_DEBUG
#define PRINT_SADC_DBG(fmt, args...) \
do \
{ \
rt_kprintf("FH_SADC_DEBUG: "); \
rt_kprintf(fmt, ## args); \
} \
while(0)
#else
#define PRINT_SADC_DBG(fmt, args...) do { } while (0)
#endif
#define __raw_writeb(v,a) ( *(volatile unsigned char *)(a) = (v))
#define __raw_writew(v,a) ( *(volatile unsigned short *)(a) = (v))
#define __raw_writel(v,a) ( *(volatile unsigned int *)(a) = (v))
#define __raw_readb(a) ( *(volatile unsigned char *)(a))
#define __raw_readw(a) ( *(volatile unsigned short *)(a))
#define __raw_readl(a) ( *(volatile unsigned int *)(a))
#define wrap_readl(wrap, name) \
__raw_readl(&(((struct wrap_sadc_reg *)wrap->regs)->name))
#define wrap_writel(wrap, name, val) \
__raw_writel((val), &(((struct wrap_sadc_reg *)wrap->regs)->name))
#define wrap_readw(wrap, name) \
__raw_readw(&(((struct wrap_sadc_reg *)wrap->regs)->name))
#define wrap_writew(wrap, name, val) \
__raw_writew((val), &(((struct wrap_sadc_reg *)wrap->regs)->name))
#define wrap_readb(wrap, name) \
__raw_readb(&(((struct wrap_sadc_reg *)wrap->regs)->name))
#define wrap_writeb(wrap, name, val) \
__raw_writeb((val), &(((struct wrap_sadc_reg *)wrap->regs)->name))
#define IOCTL_GET_SADC_DATA 1
#define IOCTL_SADC_POWER_DOWN 0xff
#define SADC_WRAP_BASE (0xf1200000)
#define SADC_IRQn (23)
#define SADC_MAX_CONTROLLER (1)
#define SADC_STATUS_COLESD (0)
#define SADC_STATUS_OPEN (1)
rt_err_t fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc, rt_uint32_t channel,
rt_uint16_t *buf) {
rt_uint32_t xainsel = 1 << channel;
rt_uint32_t xversel = 0;
rt_uint32_t xpwdb = 1;
//cnt
rt_uint32_t sel2sam_pre_cnt = 2;
rt_uint32_t sam_cnt = 2;
rt_uint32_t sam2sel_pos_cnt = 2;
//time out
rt_uint32_t eoc_tos = 0xff;
rt_uint32_t eoc_toe = 0xff;
rt_uint32_t time_out = 0xffff;
//set isr en..
rt_uint32_t sadc_isr = 0x01;
//start
rt_uint32_t sadc_cmd = 0x01;
//get data
rt_uint32_t temp_data = 0;
rt_err_t ret;
//control...
wrap_writel(sadc, sadc_control, xainsel | (xversel << 8) | (xpwdb << 12));
wrap_writel(sadc, sadc_cnt,
sel2sam_pre_cnt | (sam_cnt << 8) | (sam2sel_pos_cnt << 16));
wrap_writel(sadc, sadc_timeout,
eoc_tos | (eoc_toe << 8) | (time_out << 16));
wrap_writel(sadc, sadc_ier, sadc_isr);
wrap_writel(sadc, sadc_cmd, sadc_cmd);
// ret = rt_completion_wait(&sadc->completion, RT_TICK_PER_SECOND / 2);
ret = rt_sem_take(&sadc->completion, 5000);
if(ret != RT_EOK)
return ret;
switch (channel) {
case 0:
case 1:
//read channel 0 1
temp_data = wrap_readl(sadc, sadc_dout0);
break;
case 2:
case 3:
//read channel 2 3
temp_data = wrap_readl(sadc, sadc_dout1);
break;
case 4:
case 5:
//read channel 4 5
temp_data = wrap_readl(sadc, sadc_dout2);
break;
case 6:
case 7:
//read channel 6 7
temp_data = wrap_readl(sadc, sadc_dout3);
break;
default:
break;
}
if (channel % 2) {
//read low 16bit
*buf = (rt_uint16_t) (temp_data & 0xffff);
} else {
//read high 16bit
*buf = (rt_uint16_t) (temp_data >> 16);
}
return RT_EOK;
}
static rt_err_t fh_sadc_init(rt_device_t dev)
{
// struct fh_pwm_obj *pwm_obj = (struct fh_pwm_obj *)pwm_drv.priv;
PRINT_SADC_DBG("%s\n",__func__);
struct wrap_sadc_obj *sadc_pri =(struct wrap_sadc_obj *)dev->user_data;
return RT_EOK;
}
static rt_err_t fh_sadc_open(rt_device_t dev, rt_uint16_t oflag)
{
// struct fh_pwm_obj *pwm_obj = (struct fh_pwm_obj *)pwm_drv.priv;
PRINT_SADC_DBG("%s\n",__func__);
struct wrap_sadc_obj *sadc_pri =(struct wrap_sadc_obj *)dev->user_data;
return RT_EOK;
}
static rt_err_t fh_sadc_close(rt_device_t dev)
{
PRINT_SADC_DBG("%s\n",__func__);
struct wrap_sadc_obj *sadc_pri =(struct wrap_sadc_obj *)dev->user_data;
return RT_EOK;
}
static rt_err_t fh_sadc_ioctl(rt_device_t dev, rt_uint8_t cmd, void *arg)
{
rt_uint32_t control_reg;
struct wrap_sadc_obj *sadc_pri =(struct wrap_sadc_obj *)dev->user_data;
rt_uint32_t ad_data;
rt_uint16_t ad_raw_data;
SADC_INFO *sadc_info = (SADC_INFO *)arg;
rt_err_t ret;
switch(cmd){
case SADC_CMD_READ_RAW_DATA:
ret = fh_sadc_isr_read_data(sadc_pri, sadc_info->channel, &ad_raw_data);
if(ret != RT_EOK)
return ret;
sadc_info->sadc_data = ad_raw_data;
break;
case SADC_CMD_READ_VOLT:
ret = fh_sadc_isr_read_data(sadc_pri, sadc_info->channel, &ad_raw_data);
if(ret != RT_EOK)
return ret;
ad_data = ad_raw_data * SADC_REF;
ad_data /= SADC_MAX_AD_VALUE;
sadc_info->sadc_data = ad_data;
break;
case SADC_CMD_DISABLE:
control_reg = wrap_readl(sadc_pri, sadc_control);
control_reg &= ~(1 << 12);
wrap_writel(sadc_pri, sadc_control, control_reg);
break;
default :
rt_kprintf("wrong para...\n");
return RT_EIO;
}
return RT_EOK;
}
static void fh_sadc_interrupt(int irq, void *param)
{
rt_uint32_t isr_status;
struct wrap_sadc_obj *sadc = (struct wrap_sadc_obj *) param;
isr_status = wrap_readl(sadc, sadc_int_status);
if (isr_status & 0x01) {
//close isr
rt_uint32_t sadc_isr = 0x00;
wrap_writel(sadc, sadc_ier, sadc_isr);
//clear status..
wrap_writel(sadc, sadc_int_status, isr_status);
rt_sem_release(&sadc->completion);
// rt_completion_done(&sadc->completion);
} else {
//add error handle process
rt_kprintf("sadc maybe error!\n");
}
}
int fh_sadc_probe(void *priv_data)
{
int ret;
rt_device_t sadc_dev;
//check if the hw is init already...
//caution this is a read only data...if the driver want to use.malloc and copy it..
struct wrap_sadc_obj *sadc_obj = (struct wrap_sadc_obj *)priv_data;
if(sadc_obj->init_flag == SADC_INIT_ALREADY)
return RT_EFULL;
//malloc a rt device..
sadc_dev = RT_KERNEL_MALLOC(sizeof(struct rt_device));
if(!sadc_dev){
return RT_ENOMEM;
}
rt_memset(sadc_dev, 0, sizeof(struct rt_device));
PRINT_SADC_DBG("id:%d,\treg:%x,\tirq:%d\n",sadc_obj->id,(rt_uint32_t)sadc_obj->regs,sadc_obj->irq_no);
//bind rtdev to obj data...
//caution ...this is used to free mem when exit....
//free step:1:get sadc obj...2:free sadc_obj->rt_dev->user_data..3:free sadc_obj->rt_dev 4:sadc_obj->rt_dev = NULL
sadc_obj->rt_dev = sadc_dev;
//malloc a private data sadc use only...copy data from platform...
struct wrap_sadc_obj *sadc_pri = RT_KERNEL_MALLOC(sizeof(struct wrap_sadc_obj));
if(!sadc_pri){
RT_KERNEL_FREE(sadc_dev);
return RT_ENOMEM;
}
//copy platform data to pri data..
rt_memcpy(sadc_pri,sadc_obj,sizeof(struct wrap_sadc_obj));
PRINT_SADC_DBG("pri....id:%d,\treg:%x,\tirq:%d\n",sadc_pri->id,(rt_uint32_t)sadc_pri->regs,sadc_pri->irq_no);
//init sem
//rt_completion_init(&sadc_obj->completion);
rt_sem_init(&sadc_pri->completion, "sadc_sem", 0, RT_IPC_FLAG_FIFO);
//init lock
rt_mutex_init(&sadc_pri->lock,"sadc_lock", RT_IPC_FLAG_FIFO);
//bind pri data to rt_sadc_dev...
sadc_dev->user_data = (void *)sadc_pri;
sadc_dev->open =fh_sadc_open;
sadc_dev->close = fh_sadc_close;
sadc_dev->control = fh_sadc_ioctl;
sadc_dev->init = fh_sadc_init;
if(sadc_pri->id ==0){
rt_hw_interrupt_install(sadc_pri->irq_no, fh_sadc_interrupt,
(void *)sadc_pri, "sadc_isr_0");
}
rt_hw_interrupt_umask(sadc_pri->irq_no);
rt_device_register(sadc_dev, "sadc", RT_DEVICE_FLAG_RDWR);
sadc_obj->init_flag = SADC_INIT_ALREADY;
return RT_EOK;
}
int fh_sadc_exit(void *priv_data)
{
PRINT_SADC_DBG("%s\n",__func__);
struct wrap_sadc_obj *sadc_obj = (struct wrap_sadc_obj *)priv_data;
struct wrap_sadc_obj *sadc_pri = sadc_obj->rt_dev->user_data;
//release sem;
rt_sem_detach(&sadc_pri->completion);
//sadc_pri->completion = RT_NULL;
//release lock;
rt_mutex_detach(&sadc_pri->lock);
RT_KERNEL_FREE(sadc_obj->rt_dev->user_data);
sadc_obj->rt_dev->user_data = RT_NULL;
RT_KERNEL_FREE(sadc_obj->rt_dev);
sadc_obj->rt_dev = RT_NULL;
return 0;
}
struct fh_board_ops sdac_driver_ops =
{
.probe = fh_sadc_probe,
.exit = fh_sadc_exit,
};
void rt_hw_sadc_init(void)
{
int ret;
fh_board_driver_register("sadc", &sdac_driver_ops);
}
#ifdef FH_TEST_SADC
int fh_sadc_test(void){
rt_device_t sadc_dev;
SADC_INFO info;
info.channel = 0;
info.sadc_data = 0;
sadc_dev = rt_device_find("sadc");
if(!sadc_dev){
rt_kprintf("cann't find the sadc dev\n");
}
sadc_dev->init(sadc_dev);
sadc_dev->open(sadc_dev,0);
while(1)
{
sadc_dev->control(sadc_dev,SADC_CMD_READ_VOLT,&info);
rt_kprintf("channel:%d,volt:%dmv\n",info.channel,info.sadc_data);
}
return 0;
}
#endif
#ifdef RT_USING_FINSH
#include <finsh.h>
#ifdef FH_TEST_SADC
FINSH_FUNCTION_EXPORT(fh_sadc_test, fh_sadc_test);
#endif
#endif
#endif

109
bsp/fh8620/drivers/sadc.h Normal file
View File

@@ -0,0 +1,109 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef SADC_H_
#define SADC_H_
#include <rtdef.h>
#ifdef RT_USING_SADC
/****************************************************************************
* #define section
* add constant #define here if any
***************************************************************************/
//#define FH_SADC_PROC_FILE "driver/sadc"
#define MAX_CHANNEL_NO (8)
#define SADC_REF (3300)
#define SADC_MAX_AD_VALUE (0x3ff)
#define LOOP_MODE (0x55)
#define ISR_MODE (0xAA)
#define SADC_INIT_ALREADY (0x33)
#define SADC_INIT_NOT_YET (0)
#define SADC_CMD_READ_RAW_DATA (0x22)
#define SADC_CMD_READ_VOLT (0x33)
#define SADC_CMD_DISABLE (0x44)
/****************************************************************************
* ADT section
* add Abstract Data Type definition here
***************************************************************************/
struct wrap_sadc_reg {
rt_uint32_t sadc_cmd;
rt_uint32_t sadc_control;
rt_uint32_t sadc_ier;
rt_uint32_t sadc_int_status;
rt_uint32_t sadc_dout0;
rt_uint32_t sadc_dout1;
rt_uint32_t sadc_dout2;
rt_uint32_t sadc_dout3;
rt_uint32_t sadc_debuge0;
rt_uint32_t sadc_status;
rt_uint32_t sadc_cnt;
rt_uint32_t sadc_timeout;
};
struct wrap_sadc_obj {
rt_uint32_t id;
void *regs;
rt_uint32_t irq_no;
rt_uint32_t init_flag;
rt_uint32_t active_channel_no;
rt_uint32_t active_channel_status;
rt_uint16_t channel_data[MAX_CHANNEL_NO];
rt_uint32_t error_rec;
rt_uint32_t en_isr;
rt_uint32_t sample_mode;
struct rt_mutex lock;
struct rt_semaphore completion;
//bind to the rtdev..
rt_device_t rt_dev;
};
typedef struct{
rt_uint32_t channel;
rt_uint32_t sadc_data;
}SADC_INFO;
/****************************************************************************
* extern variable declaration section
***************************************************************************/
/****************************************************************************
* section
* add function prototype here if any
***************************************************************************/
void rt_hw_sadc_init(void);
#endif
#endif /* SADC_H_ */

View File

@@ -0,0 +1,212 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
/*
* spi_fh_adapt.c
*
* Created on: Mar 2, 2016
* Author: duobao
*/
#include <stdint.h>
#include "spi_fh_adapt.h"
#include "board_info.h"
#ifdef RT_USING_W25QXX
#include "spi_flash_w25qxx.h"
#endif
#ifdef RT_USING_AT45DBXX
#include "spi_flash_at45dbxx.h"
#endif
#ifdef RT_USING_SST25VFXX
#include "spi_flash_sst25vfxx.h"
#endif
#ifdef RT_USING_GD
#include "spi_flash_gd.h"
#endif
#ifdef RT_USING_FLASH_DEFAULT
#include "spi_flash_default.h"
#endif
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define WX_MANU_ID 0xEF
#define AT_MANU_ID 0x1F /* atmel */
#define SST_MANU_ID 0xBF
#define GD_MANU_ID 0xC8
#define SPI_ADAPT_DEBUG
#ifdef SPI_ADAPT_DEBUG
#define CMD_JEDEC_ID 0x9f
#define FH_SPI_ADAPT_DEBUG(fmt, args...) \
rt_kprintf(fmt,##args);
#else
#define FH_SPI_ADAPT_DEBUG(fmt, args...)
#endif
struct fh_flash_id{
unsigned char id;
rt_err_t (*fh_flash_init)(struct flash_platform_data *plat_flash);
char *name;
};
const struct fh_flash_id id_map[] = {
#ifdef RT_USING_W25QXX
WX_MANU_ID,w25qxx_init,"winbond",
#endif
#ifdef RT_USING_AT45DBXX
AT_MANU_ID,at45dbxx_init,"atmel",
#endif
#ifdef RT_USING_SST25VFXX
SST_MANU_ID,sst25vfxx_init,"SST",
#endif
#ifdef RT_USING_GD
GD_MANU_ID,gd_init,"GD",
#endif
};
struct fh_flash_id * fh_flash_check_id_map(unsigned char id){
struct fh_flash_id *p_map = RT_NULL;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(id_map); i++) {
p_map = (struct fh_flash_id *)&id_map[i];
if (p_map->id == id){
return p_map;
}
}
return RT_NULL;
}
int fh_flash_adapt_probe(void *priv_data)
{
struct flash_platform_data *plat_flash = priv_data;
const char * flash_device_name = plat_flash->flash_name;
const char * spi_device_name = plat_flash->spi_name;
struct rt_spi_device * rt_spi_device;
struct fh_flash_id * flash_model;
rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
if(rt_spi_device == RT_NULL)
{
rt_kprintf("spi device %s not found!\r\n", spi_device_name);
return -RT_ENOSYS;
}
/* config spi */
{
struct rt_spi_configuration cfg;
cfg.data_width = 8;
cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */
cfg.max_hz = 50 * 1000 * 1000; /* 50M */
rt_spi_configure(rt_spi_device, &cfg);
}
/* init flash */
rt_uint8_t cmd;
rt_uint8_t id_recv[3];
uint16_t memory_type_capacity;
rt_err_t ret;
cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */
rt_spi_send(rt_spi_device, &cmd, 1);
/* read flash id */
cmd = CMD_JEDEC_ID;
rt_spi_send_then_recv(rt_spi_device, &cmd, 1, id_recv, 3);
//if the flash is already connect.
if(id_recv[0] != 0xff){
flash_model =fh_flash_check_id_map(id_recv[0]);
if(flash_model){
ret = flash_model->fh_flash_init(plat_flash);
if(ret != RT_EOK){
rt_kprintf("flash:%s init error\n",flash_model->name);
rt_kprintf("use default flash ops..\n");
//flash_model->fh_flash_adapt_init =flash_default_init;
ret = flash_default_init(plat_flash);
}
}
else{
rt_kprintf(
"use default flash ops...\nunrecognized flash id is :%02X %02X %02X\n",
id_recv[0], id_recv[1], id_recv[2]);
ret = flash_default_init(plat_flash);
}
int i;
for(i=0; i<plat_flash->nr_parts; i++)
{
fh_spi_partition_register(plat_flash->flash_name, &plat_flash->parts[i]);
}
return ret;
}
else{
rt_kprintf("please check if you connect the flash already...\n");
return RT_ENOSYS;
}
}
int fh_flash_adapt_exit(void *priv_data)
{
return 0;
}
struct fh_board_ops flash_driver_ops =
{
.probe = fh_flash_adapt_probe,
.exit = fh_flash_adapt_exit,
};
rt_err_t fh_flash_adapt_init(void)
{
fh_board_driver_register("fh_flash", &flash_driver_ops);
return 0;
}

View File

@@ -0,0 +1,71 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
/*
* spi_fh_adapt.h
*
* Created on: Mar 2, 2016
* Author: duobao
*/
#ifndef SPI_FH_ADAPT_H_
#define SPI_FH_ADAPT_H_
#include <rtthread.h>
#include <drivers/spi.h>
#define MTD_WRITEABLE 0x400 /* Device is writeable */
#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
#define MTD_NO_ERASE 0x1000 /* No erase necessary */
#define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */
struct mtd_partition {
char *name; /* identifier string */
rt_uint32_t size; /* partition size */
rt_uint32_t offset; /* offset within the master MTD space */
rt_uint32_t mask_flags; /* master MTD flags to mask out for this partition */
struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only) */
};
struct flash_platform_data {
char *flash_name;
char *spi_name;
struct mtd_partition *parts;
unsigned int nr_parts;
char *type;
/* we'll likely add more ... use JEDEC IDs, etc */
};
rt_err_t fh_flash_adapt_init(void);
#endif /* SPI_FH_ADAPT_H_ */

878
bsp/fh8620/drivers/ssi.c Normal file

File diff suppressed because it is too large Load Diff

134
bsp/fh8620/drivers/ssi.h Normal file
View File

@@ -0,0 +1,134 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef SSI_H_
#define SSI_H_
#include "Libraries/inc/fh_driverlib.h"
#include <drivers/spi.h>
#include <rtdevice.h>
#include "fh_dma.h"
#define SPI_PRIV(drv) ( (struct fh_spi_obj)(drv->priv) )
#define FH_SPI_SLAVE_MAX_NO 2
struct spi_controller;
//platform use below
struct spi_slave_platform_data{
rt_uint32_t cs_pin;
#define ACTIVE_LOW 1
#define ACTIVE_HIGH 2
rt_uint32_t actice_level;
};
struct spi_control_platform_data{
rt_uint32_t id;
rt_uint32_t irq;
rt_uint32_t base;
rt_uint32_t max_hz;
rt_uint32_t slave_no;
rt_uint32_t clk_in;
//handshake no...
rt_uint32_t rx_hs_no;
rt_uint32_t tx_hs_no;
char *dma_name;
//isr will be the default...
#define USE_ISR_TRANSFER 0
#define USE_DMA_TRANSFER 1
rt_uint32_t transfer_mode;
struct spi_controller *control;
struct spi_slave_platform_data plat_slave[FH_SPI_SLAVE_MAX_NO];
};
struct spi_controller;
//driver use below.......
struct spi_slave_info
{
struct rt_spi_device spi_device;
struct spi_controller *control;
struct spi_slave_platform_data plat_slave;
rt_uint32_t id;
//spi control will use to find all the slave info..
struct spi_slave_info *next;
};
struct spi_dma
{
char *dma_name;
#define DMA_BIND_OK 0
#define DMA_BIND_ERROR 1
rt_uint32_t dma_flag;
//bind to the dma dev..
rt_uint32_t rx_hs;
rt_uint32_t tx_hs;
rt_uint8_t *rx_dummy_buff;
rt_uint8_t *tx_dummy_buff;
struct rt_dma_device *dma_dev;
struct dma_transfer tx_trans;
struct dma_transfer rx_trans;
struct spi_controller *control;
};
struct spi_controller
{
rt_uint32_t id;
rt_uint32_t irq;
rt_uint32_t base;
rt_uint32_t max_hz;
rt_uint32_t slave_no;
rt_uint32_t clk_in;
//bind to the platform data....
struct spi_control_platform_data *plat_data;
//rt_uint32_t dma_xfer_flag;
#define XFER_USE_ISR 0
#define XFER_USE_DMA 1
rt_uint32_t xfer_mode;
struct spi_dma dma;
rt_uint32_t dma_complete_times;
struct rt_spi_bus spi_bus;
struct spi_slave_info *spi_slave;
struct rt_spi_message* current_message;
struct rt_completion transfer_completion;
struct rt_semaphore xfer_lock;
struct fh_spi_obj obj;
rt_uint32_t received_len;
rt_uint32_t transfered_len;
void* priv;
};
void rt_hw_spi_init(void);
#endif /* SPI_H_ */

197
bsp/fh8620/drivers/trap.c Normal file
View File

@@ -0,0 +1,197 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include <rthw.h>
#include <armv6.h>
#include "fh_arch.h"
#include "interrupt.h"
#include "Libraries/inc/fh_ictl.h"
/**
* @addtogroup FH81
*/
/*@{*/
extern struct rt_thread *rt_current_thread;
#ifdef RT_USING_FINSH
extern long list_thread(void);
#endif
/**
* this function will show registers of CPU
*
* @param regs the registers point
*/
void rt_hw_show_register (struct rt_hw_register *regs)
{
rt_kprintf("Execption:\n");
rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3);
rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7);
rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10);
rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip);
rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc);
rt_kprintf("cpsr:0x%08x\n", regs->cpsr);
}
/**
* When ARM7TDMI comes across an instruction which it cannot handle,
* it takes the undefined instruction trap.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_udef(struct rt_hw_register *regs)
{
rt_hw_show_register(regs);
rt_kprintf("undefined instruction\n");
rt_kprintf("thread - %s stack:\n", rt_current_thread->name);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* The software interrupt instruction (SWI) is used for entering
* Supervisor mode, usually to request a particular supervisor
* function.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_swi(struct rt_hw_register *regs)
{
rt_hw_show_register(regs);
rt_kprintf("software interrupt\n");
rt_hw_cpu_shutdown();
}
/**
* An abort indicates that the current memory access cannot be completed,
* which occurs during an instruction prefetch.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_pabt(struct rt_hw_register *regs)
{
rt_hw_show_register(regs);
rt_kprintf("prefetch abort\n");
rt_kprintf("thread - %s stack:\n", rt_current_thread->name);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* An abort indicates that the current memory access cannot be completed,
* which occurs during a data access.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_dabt(struct rt_hw_register *regs)
{
rt_hw_show_register(regs);
rt_kprintf("data abort\n");
rt_kprintf("thread - %s stack:\n", rt_current_thread->name);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* Normally, system will never reach here
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_resv(struct rt_hw_register *regs)
{
rt_kprintf("not used\n");
rt_hw_show_register(regs);
rt_hw_cpu_shutdown();
}
extern struct rt_irq_desc irq_desc[];
void rt_hw_trap_irq()
{
rt_isr_handler_t isr_func;
rt_uint32_t irqstat_l, irqstat_h, irq;
void *param;
fh_intc *p = (fh_intc *)INTC_REG_BASE;
irqstat_l = p->IRQ_FINALSTATUS_L;
irqstat_h = p->IRQ_FINALSTATUS_H;
if (irqstat_l)
{
irq = __rt_ffs(irqstat_l) - 1;
}
else if(irqstat_h)
{
irq = __rt_ffs(irqstat_h) - 1 + 32;
}
else
{
rt_kprintf("No interrupt occur\n");
return;
}
/* get interrupt service routine */
isr_func = irq_desc[irq].handler;
param = irq_desc[irq].param;
/* turn to interrupt service routine */
if(isr_func){
isr_func(irq, param);
}
#ifdef RT_USING_INTERRUPT_INFO
irq_desc[irq].counter ++;
#endif
}
void rt_hw_trap_fiq()
{
rt_kprintf("fast interrupt request\n");
}
/*@}*/

292
bsp/fh8620/drivers/uart.c Normal file
View File

@@ -0,0 +1,292 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include <board.h>
#include <rtdevice.h>
#include "fh_arch.h"
#include "Libraries/inc/fh_uart.h"
void rt_fh_uart_handler(int vector, void *param)
{
int status;
unsigned int ret;
struct fh_uart *uart;
unsigned int reg_status;
rt_device_t dev = (rt_device_t)param;
uart = (struct fh_uart *)dev->user_data;
status = uart_get_iir_status(uart->uart_port);
if (status & UART_IIR_NOINT)
{
return;
}
if(status & UART_IIR_THREMPTY){
//first close tx isr
uart_disable_irq(uart->uart_port,UART_IER_ETBEI);
rt_hw_serial_isr((struct rt_serial_device *)dev, RT_SERIAL_EVENT_TX_DONE);
}
else if((status & UART_IIR_CHRTOUT)==UART_IIR_CHRTOUT){
//bug....
//if no data in rx fifo
reg_status = uart_get_status(uart->uart_port);
if((reg_status & 1<<3) == 0)
ret = uart_getc(uart->uart_port);
}
else{
rt_interrupt_enter();
rt_hw_serial_isr((struct rt_serial_device *)dev, RT_SERIAL_EVENT_RX_IND);
rt_interrupt_leave();
}
}
/**
* UART device in RT-Thread
*/
static rt_err_t fh_uart_configure(struct rt_serial_device *serial,
struct serial_configure *cfg)
{
int div;
enum data_bits data_mode;
enum stop_bits stop_mode;
enum parity parity_mode;
struct fh_uart *uart;
RT_ASSERT(serial != RT_NULL);
RT_ASSERT(cfg != RT_NULL);
uart = (struct fh_uart *)serial->parent.user_data;
switch (cfg->data_bits)
{
case DATA_BITS_8:
data_mode = UART_DATA_BIT8;
break;
case DATA_BITS_7:
data_mode = UART_DATA_BIT7;
break;
case DATA_BITS_6:
data_mode = UART_DATA_BIT6;
break;
case DATA_BITS_5:
data_mode = UART_DATA_BIT5;
break;
default:
data_mode = UART_DATA_BIT8;
break;
}
switch (cfg->stop_bits)
{
case STOP_BITS_2:
stop_mode = UART_STOP_BIT2;
break;
case STOP_BITS_1:
default:
stop_mode = UART_STOP_BIT1;
break;
}
switch (cfg->parity)
{
case PARITY_ODD:
parity_mode = UART_PARITY_ODD;
break;
case PARITY_EVEN:
parity_mode = UART_PARITY_EVEN;
break;
case PARITY_NONE:
default:
parity_mode = UART_PARITY_NONE;
break;
}
uart_disable_irq(uart->uart_port, UART_IER_ERBFI);
uart_configure(uart->uart_port, data_mode,
stop_mode, parity_mode,
cfg->baud_rate, UART_CLOCK_FREQ);
uart_enable_irq(uart->uart_port, UART_IER_ERBFI);
return RT_EOK;
}
static rt_err_t fh_uart_control(struct rt_serial_device *serial,
int cmd, void *arg)
{
struct fh_uart* uart;
RT_ASSERT(serial != RT_NULL);
uart = (struct fh_uart *)serial->parent.user_data;
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
/* disable rx irq */
rt_hw_interrupt_mask(uart->irq);
uart_disable_irq(uart->uart_port,UART_IER_ERBFI);
break;
case RT_DEVICE_CTRL_SET_INT:
/* enable rx irq */
rt_hw_interrupt_umask(uart->irq);
uart_enable_irq(uart->uart_port,UART_IER_ERBFI);
break;
}
return RT_EOK;
}
static int fh_uart_putc(struct rt_serial_device *serial, char c)
{
struct fh_uart *uart = serial->parent.user_data;
unsigned int ret;
ret = uart_get_status(uart->uart_port);
if(serial->parent.open_flag & RT_DEVICE_FLAG_INT_TX){
//RT_DEVICE_FLAG_INT_TX
if(c == '\n'){
fh_uart_putc(serial,'\r');
}
if(ret & UART_USR_TFNF){
uart_putc(uart->uart_port, c);
return 1;
}
//open tx isr here..
uart_enable_irq(uart->uart_port,UART_IER_ETBEI);
return -1;
}
//poll mode
else{
while(!(uart_get_status(uart->uart_port) & UART_USR_TFNF))
;
uart_putc(uart->uart_port, c);
return 1;
}
}
static int fh_uart_getc(struct rt_serial_device *serial)
{
int result;
struct fh_uart *uart = serial->parent.user_data;
if (uart_is_rx_ready(uart->uart_port))
{
result = uart_getc(uart->uart_port);
}
else
{
result = -1;
}
return result;
}
static const struct rt_uart_ops fh_uart_ops =
{
fh_uart_configure,
fh_uart_control,
fh_uart_putc,
fh_uart_getc,
};
#if defined(RT_USING_UART0)
static struct rt_serial_device serial0;
struct fh_uart uart0 = {
(uart *)UART0_REG_BASE,
UART0_IRQn
};
#endif
#if defined(RT_USING_UART1)
static struct rt_serial_device serial1;
struct fh_uart uart1 = {
(uart *)UART1_REG_BASE,
UART1_IRQn
};
#endif
/**
* This function will handle init uart
*/
void rt_hw_uart_init(void)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
#if defined(RT_USING_UART0)
#if(0)
serial0.ops = &fh_uart_ops;
serial0.config = config;
/* register vcom device */
rt_hw_serial_register(&serial0, "uart0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_STANDALONE,
&uart0);
rt_hw_interrupt_install(uart0.irq, rt_fh_uart_handler,
(void *)&(serial0.parent), "UART0");
rt_hw_interrupt_umask(uart0.irq);
#endif
serial0.ops = &fh_uart_ops;
serial0.config = config;
/* register vcom device */
rt_hw_serial_register(&serial0, "uart0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM ,
&uart0);
rt_hw_interrupt_install(uart0.irq, rt_fh_uart_handler,
(void *)&(serial0.parent), "UART0");
rt_hw_interrupt_umask(uart0.irq);
#endif
#if defined(RT_USING_UART1)
serial1.ops = &fh_uart_ops;
serial1.config = config;
/* register vcom device */
rt_hw_serial_register(&serial1, "uart1",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM ,
&uart1);
rt_hw_interrupt_install(uart1.irq, rt_fh_uart_handler,
(void *)&(serial1.parent), "UART1");
rt_hw_interrupt_umask(uart1.irq);
#endif
}

33
bsp/fh8620/drivers/uart.h Normal file
View File

@@ -0,0 +1,33 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef UART_H_
#define UART_H_
void rt_hw_uart_init(void);
#endif

269
bsp/fh8620/drivers/wdt.c Normal file
View File

@@ -0,0 +1,269 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include "fh_def.h"
#include "wdt.h"
#include "interrupt.h"
#include "board_info.h"
#include "inc/fh_driverlib.h"
#include <rtdevice.h>
#include <drivers/watchdog.h>
#define FH_WDT_DEBUG
#ifdef FH_WDT_DEBUG
#define PRINT_WDT_DBG(fmt, args...) \
do \
{ \
rt_kprintf("FH_WDT_DEBUG: "); \
rt_kprintf(fmt, ## args); \
} \
while(0)
#else
#define PRINT_WDT_DBG(fmt, args...) do { } while (0)
#endif
static int heartbeat = WDT_HEARTBEAT;
static rt_uint32_t fh_wdt_time_left(struct wdt_driver *wdt_drv)
{
struct fh_wdt_obj *wdt_obj = wdt_drv->priv;
//todo: get clk
//return WDT_GetCurrCount(wdt_obj) / WDT_CLOCK;
return WDT_GetCurrCount(wdt_obj) / 1800000;
}
static void fh_wdt_keepalive(struct wdt_driver *wdt_drv)
{
struct fh_wdt_obj *wdt_obj = wdt_drv->priv;
WDT_Kick(wdt_obj);
}
static inline void fh_wdt_set_next_heartbeat(struct wdt_driver *wdt_drv)
{
wdt_drv->next_heartbeat = rt_tick_get() + heartbeat * RT_TICK_PER_SECOND;
}
static inline int fh_wdt_top_in_seconds(struct wdt_driver *wdt_drv, unsigned top)
{
/*
* There are 16 possible timeout values in 0..15 where the number of
* cycles is 2 ^ (16 + i) and the watchdog counts down.
*/
//todo: get_clk
return (1 << (17 + top)) / 1800000;
}
static int fh_wdt_set_top(struct wdt_driver *wdt_drv, unsigned top_s)
{
int i, top_val = FH_WDT_MAX_TOP;
struct fh_wdt_obj *wdt_obj = wdt_drv->priv;
/*
* Iterate over the timeout values until we find the closest match. We
* always look for >=.
*/
for (i = 0; i <= FH_WDT_MAX_TOP; ++i)
if (fh_wdt_top_in_seconds(wdt_drv, i) >= top_s) {
top_val = i;
break;
}
/* Set the new value in the watchdog. */
PRINT_WDT_DBG("[wdt] set topval: %d\n", top_val);
WDT_SetTopValue(wdt_obj, top_val);
fh_wdt_set_next_heartbeat(wdt_drv);
return fh_wdt_top_in_seconds(wdt_drv, top_val);
}
rt_err_t fh_watchdog_init(rt_watchdog_t *wdt)
{
struct wdt_driver *wdt_drv = wdt->parent.user_data;
struct fh_wdt_obj *wdt_obj = wdt_drv->priv;
if (wdt_drv->in_use)
return -RT_EBUSY;
//todo: spinlock
fh_wdt_set_top(wdt_drv, WDT_HW_TIMEOUT);///3000);
if (!WDT_IsEnable(wdt_obj))
{
/*
* The watchdog is not currently enabled. Set the timeout to
* the maximum and then start it.
*/
rt_uint32_t value;
value = WDOG_CONTROL_REG_WDT_EN_MASK;
value |= WDOG_CONTROL_REG_RMOD_MASK;
WDT_SetCtrl(wdt_obj, value);
fh_wdt_keepalive(wdt_drv);
}
fh_wdt_set_next_heartbeat(wdt_drv);
//todo: unlock
return RT_EOK;
}
rt_err_t fh_watchdog_ctrl(rt_watchdog_t *wdt, int cmd, void *arg)
{
struct wdt_driver *wdt_drv = wdt->parent.user_data;
struct fh_wdt_obj *wdt_obj = wdt_drv->priv;
rt_uint32_t val;
switch (cmd)
{
case RT_DEVICE_CTRL_WDT_START:
WDT_Enable(wdt_obj, RT_TRUE);
break;
case RT_DEVICE_CTRL_WDT_STOP:
WDT_Enable(wdt_obj, RT_FALSE);
break;
case RT_DEVICE_CTRL_WDT_KEEPALIVE:
//fh_wdt_set_next_heartbeat(wdt_drv);
fh_wdt_keepalive(wdt_drv);
break;
case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
heartbeat = *((int*)(arg));
PRINT_WDT_DBG("[wdt] settime value %lu\n", heartbeat);
fh_wdt_set_top(wdt_drv, heartbeat);///3000);
fh_wdt_keepalive(wdt_drv);
fh_wdt_set_next_heartbeat(wdt_drv);
break;
case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
arg = &heartbeat;
break;
case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
val = fh_wdt_time_left(wdt_drv);
arg = &val;
break;
default:
return -RT_EIO;
}
return RT_EOK;
}
static void fh_wdt_interrupt(int irq, void *param)
{
//todo: stop
//fh81_pmu_stop();
}
struct rt_watchdog_ops fh_watchdog_ops =
{
.init = &fh_watchdog_init,
.control = &fh_watchdog_ctrl,
};
int fh_wdt_probe(void *priv_data)
{
rt_watchdog_t *wdt_dev;
struct wdt_driver *wdt_drv;
struct fh_wdt_obj *wdt_obj = (struct fh_wdt_obj *)priv_data;
wdt_drv = (struct wdt_driver *)rt_malloc(sizeof(struct wdt_driver));
rt_memset(wdt_drv, 0, sizeof(struct wdt_driver));
wdt_drv->priv = wdt_obj;
rt_hw_interrupt_install(wdt_obj->irq, fh_wdt_interrupt, (void *)wdt_drv, "wdt_irq");
rt_hw_interrupt_umask(wdt_obj->irq);
//todo: clk
wdt_dev = (rt_watchdog_t *)rt_malloc(sizeof(rt_watchdog_t));
if (wdt_dev == RT_NULL)
{
rt_kprintf("ERROR: %s rt_watchdog_t malloc failed\n", __func__);
}
wdt_dev->ops = &fh_watchdog_ops;
rt_hw_watchdog_register(wdt_dev, "fh_wdt", RT_DEVICE_OFLAG_RDWR, wdt_drv);
return 0;
}
int fh_wdt_exit(void *priv_data)
{
return 0;
}
struct fh_board_ops wdt_driver_ops =
{
.probe = fh_wdt_probe,
.exit = fh_wdt_exit,
};
void rt_hw_wdt_init(void)
{
PRINT_WDT_DBG("%s start\n", __func__);
fh_board_driver_register("wdt", &wdt_driver_ops);
PRINT_WDT_DBG("%s end\n", __func__);
}
void wdt_start(int timeout, int kick_times)
{
rt_device_t wdt_dev;
int ret;
wdt_dev = rt_device_find("fh_wdt");
rt_device_open(wdt_dev, 0);
ret = rt_device_control(wdt_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout);
int i = 0;
for( ; i < kick_times; i ++ )
{
rt_thread_sleep(timeout * RT_TICK_PER_SECOND / 2);
ret = rt_device_control(wdt_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, &timeout);
rt_kprintf( "kicked\n" );
}
rt_kprintf( "stop kick the watchdog, it shall reboot for %d seconds.\n", timeout * 2);
}
#ifdef RT_USING_WDT
#ifdef RT_USING_FINSH
#include <finsh.h>
FINSH_FUNCTION_EXPORT(wdt_start, enable wdt);
#endif
#endif

46
bsp/fh8620/drivers/wdt.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef WDT_H_
#define WDT_H_
struct wdt_driver
{
//struct clk *clk;
unsigned long in_use;
unsigned long next_heartbeat;
//struct timer_list timer;
int expect_close;
void* priv;
};
#endif /* WDT_H_ */

View File

@@ -0,0 +1,14 @@
# for module compiling
import os
from building import *
objs = []
cwd = GetCurrentDir()
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
objs = objs + SConscript(os.path.join(item, 'SConscript'))
Return('objs')

View File

@@ -0,0 +1,9 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
path = [cwd + '/..']
group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path)
Return('group')

View File

@@ -0,0 +1,27 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/

View File

@@ -0,0 +1,311 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include "inc/fh_driverlib.h"
int I2C_WaitMasterIdle(struct fh_i2c_obj *i2c_obj)
{
UINT32 reg;
int timeout = 200; //20 ms
while (GET_REG(i2c_obj->base + OFFSET_I2C_STATUS) & DW_IC_STATUS_MASTER_ACTIVITY)
{
if(timeout < 0)
{
rt_kprintf( "ERROR: %s, timeout waiting for master not active, txflr: 0x%x, rxflr: 0x%x, stat: 0x%x\n",
__func__, I2C_GetReceiveFifoLevel(i2c_obj), I2C_GetTransmitFifoLevel(i2c_obj), GET_REG(i2c_obj->base + OFFSET_I2C_INTR_STAT));
return -RT_ETIMEOUT;
}
timeout--;
udelay(100);
}
return 0;
}
int I2C_WaitDeviceIdle(struct fh_i2c_obj *i2c_obj)
{
UINT32 reg;
int timeout = 2000; //200 ms
while (GET_REG(i2c_obj->base + OFFSET_I2C_STATUS) & DW_IC_STATUS_ACTIVITY)
{
if(timeout < 0)
{
rt_kprintf( "ERROR: %s, timeout waiting for device not active\n", __func__);
return -RT_ETIMEOUT;
}
timeout--;
udelay(100);
}
return 0;
}
static inline UINT32 I2C_CalcSclHcnt(UINT32 ic_clk, UINT32 tSYMBOL, UINT32 tf, int cond, int offset)
{
/*
* DesignWare I2C core doesn't seem to have solid strategy to meet
* the tHD;STA timing spec. Configuring _HCNT based on tHIGH spec
* will result in violation of the tHD;STA spec.
*/
if (cond)
/*
* Conditional expression:
*
* IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
*
* This is based on the DW manuals, and represents an ideal
* configuration. The resulting I2C bus speed will be
* faster than any of the others.
*
* If your hardware is free from tHD;STA issue, try this one.
*/
return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
else
/*
* Conditional expression:
*
* IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
*
* This is just experimental rule; the tHD;STA period turned
* out to be proportinal to (_HCNT + 3). With this setting,
* we could meet both tHIGH and tHD;STA timing specs.
*
* If unsure, you'd better to take this alternative.
*
* The reason why we need to take into account "tf" here,
* is the same as described in i2c_fh_scl_lcnt().
*/
return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
}
static inline UINT32 I2C_CalcSclLcnt(UINT32 ic_clk, UINT32 tLOW, UINT32 tf, int offset)
{
/*
* Conditional expression:
*
* IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
*
* DW I2C core starts counting the SCL CNTs for the LOW period
* of the SCL clock (tLOW) as soon as it pulls the SCL line.
* In order to meet the tLOW timing spec, we need to take into
* account the fall time of SCL signal (tf). Default tf value
* should be 0.3 us, for safety.
*/
return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
}
static int I2C_SetSpeedCount(struct fh_i2c_obj *i2c_obj)
{
UINT32 hcnt, lcnt;
/* set standard and fast speed count for high/low periods */
/* Standard-mode */
hcnt = I2C_CalcSclHcnt(i2c_obj->input_clock,
40, /* tHD;STA = tHIGH = 4.0 us */
3, /* tf = 0.3 us */
0, /* 0: DW default, 1: Ideal */
0); /* No offset */
lcnt = I2C_CalcSclLcnt(i2c_obj->input_clock,
47, /* tLOW = 4.7 us */
3, /* tf = 0.3 us */
0); /* No offset */
SET_REG(i2c_obj->base + OFFSET_I2C_SS_SCL_HCNT, hcnt);
SET_REG(i2c_obj->base + OFFSET_I2C_SS_SCL_LCNT, lcnt);
/* Fast-mode */
hcnt = I2C_CalcSclHcnt(i2c_obj->input_clock,
6, /* tHD;STA = tHIGH = 0.6 us */
3, /* tf = 0.3 us */
0, /* 0: DW default, 1: Ideal */
0); /* No offset */
lcnt = I2C_CalcSclLcnt(i2c_obj->input_clock,
13, /* tLOW = 1.3 us */
3, /* tf = 0.3 us */
0); /* No offset */
SET_REG(i2c_obj->base + OFFSET_I2C_FS_SCL_HCNT, hcnt);
SET_REG(i2c_obj->base + OFFSET_I2C_FS_SCL_LCNT, lcnt);
return 0;
}
inline UINT8 I2C_GetData(struct fh_i2c_obj *i2c_obj)
{
return GET_REG(i2c_obj->base + OFFSET_I2C_DATA_CMD) & 0xff;
}
inline void I2C_SetDataCmd(struct fh_i2c_obj *i2c_obj, UINT32 reg)
{
SET_REG(i2c_obj->base + OFFSET_I2C_DATA_CMD, reg);
}
inline void I2C_SetInterruptMask(struct fh_i2c_obj *i2c_obj, UINT32 mask)
{
SET_REG(i2c_obj->base + OFFSET_I2C_INTR_MASK, mask);
}
inline UINT32 I2C_GetInterruptMask(struct fh_i2c_obj *i2c_obj)
{
return GET_REG(i2c_obj->base + OFFSET_I2C_INTR_MASK);
}
UINT32 I2C_ClearAndGetInterrupts(struct fh_i2c_obj *i2c_obj)
{
UINT32 stat;
/*
* The IC_INTR_STAT register just indicates "enabled" interrupts.
* Ths unmasked raw version of interrupt status bits are available
* in the IC_RAW_INTR_STAT register.
*
* That is,
* stat = readl(IC_INTR_STAT);
* equals to,
* stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
*
* The raw version might be useful for debugging purposes.
*/
stat = GET_REG(i2c_obj->base + OFFSET_I2C_INTR_STAT);
/*
* Do not use the IC_CLR_INTR register to clear interrupts, or
* you'll miss some interrupts, triggered during the period from
* readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
*
* Instead, use the separately-prepared IC_CLR_* registers.
*/
if (stat & DW_IC_INTR_RX_UNDER)
GET_REG(i2c_obj->base + OFFSET_I2C_CLR_RX_UNDER);
if (stat & DW_IC_INTR_RX_OVER)
GET_REG(i2c_obj->base + OFFSET_I2C_CLR_RX_OVER);
if (stat & DW_IC_INTR_TX_OVER)
GET_REG(i2c_obj->base + OFFSET_I2C_CLR_TX_OVER);
if (stat & DW_IC_INTR_RD_REQ)
GET_REG(i2c_obj->base + OFFSET_I2C_CLR_RD_REQ);
if (stat & DW_IC_INTR_TX_ABRT)
{
/*
* The IC_TX_ABRT_SOURCE register is cleared whenever
* the IC_CLR_TX_ABRT is read. Preserve it beforehand.
*/
i2c_obj->abort_source = GET_REG(i2c_obj->base + OFFSET_I2C_TX_ABRT_SOURCE);
GET_REG(i2c_obj->base + OFFSET_I2C_CLR_TX_ABRT);
}
if (stat & DW_IC_INTR_RX_DONE)
GET_REG(i2c_obj->base + OFFSET_I2C_CLR_RX_DONE);
if (stat & DW_IC_INTR_ACTIVITY)
GET_REG(i2c_obj->base + OFFSET_I2C_CLR_ACTIVITY);
if (stat & DW_IC_INTR_STOP_DET)
GET_REG(i2c_obj->base + OFFSET_I2C_CLR_STOP_DET);
if (stat & DW_IC_INTR_START_DET)
GET_REG(i2c_obj->base + OFFSET_I2C_CLR_START_DET);
if (stat & DW_IC_INTR_GEN_CALL)
GET_REG(i2c_obj->base + OFFSET_I2C_CLR_GEN_CALL);
return stat;
}
int I2C_HandleTxAbort(struct fh_i2c_obj *i2c_obj)
{
unsigned long abort_source = i2c_obj->abort_source;
int i;
if (abort_source & DW_IC_TX_ABRT_NOACK)
{
//for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
// rt_kprintf( "%s: %s\n", __func__, abort_sources[i]);
return 0;
}
//for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
// rt_kprintf( "%s: %s\n", __func__, abort_sources[i]);
rt_kprintf("%s: abort_sources 0x%x\n", __func__, abort_sources);
if (abort_source & DW_IC_TX_ARB_LOST)
return 0;
else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
return 0; /* wrong msgs[] data */
else
return 0;
}
inline UINT32 I2C_SetTransmitThreshold(struct fh_i2c_obj *i2c_obj, int txtl)
{
return SET_REG(i2c_obj->base + OFFSET_I2C_TX_TL, txtl);
}
inline UINT32 I2C_GetReceiveFifoLevel(struct fh_i2c_obj *i2c_obj)
{
return GET_REG(i2c_obj->base + OFFSET_I2C_RXFLR);
}
inline UINT32 I2C_GetTransmitFifoLevel(struct fh_i2c_obj *i2c_obj)
{
return GET_REG(i2c_obj->base + OFFSET_I2C_TXFLR);
}
inline void I2C_SetSlaveAddress(struct fh_i2c_obj *i2c_obj, rt_uint16_t addr)
{
UINT32 reg;
reg = GET_REG(i2c_obj->base + OFFSET_I2C_TAR);
reg &= ~(0x3ff);
reg |= addr & 0x3ff;
SET_REG(i2c_obj->base + OFFSET_I2C_TAR, reg);
}
inline void I2C_Enable(struct fh_i2c_obj *i2c_obj, int enable)
{
SET_REG(i2c_obj->base + OFFSET_I2C_ENABLE, enable);
}
void I2C_Init(struct fh_i2c_obj *i2c_obj)
{
UINT32 ic_con;
UINT32 param0 = GET_REG(i2c_obj->base + OFFSET_I2C_COMP_PARAM1);
I2C_WaitMasterIdle(i2c_obj);
I2C_Enable(i2c_obj, RT_FALSE);
I2C_SetSpeedCount(i2c_obj);
i2c_obj->config.tx_fifo_depth = ((param0 >> 16) & 0xff) + 1;
i2c_obj->config.rx_fifo_depth = ((param0 >> 8) & 0xff) + 1;
/* Configure Tx/Rx FIFO threshold levels */
SET_REG(i2c_obj->base + OFFSET_I2C_TX_TL, i2c_obj->config.tx_fifo_depth - 1);
SET_REG(i2c_obj->base + OFFSET_I2C_RX_TL, 0);
/* configure the i2c master */
ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
/*OFFSET_I2C_CON_RESTART_EN |*/ DW_IC_CON_SPEED_FAST; //DW_IC_CON_SPEED_STD;
SET_REG( i2c_obj->base + OFFSET_I2C_CON, ic_con);
}

View File

@@ -0,0 +1,69 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include "inc/fh_driverlib.h"
void ictl_close_all_isr(fh_intc *p){
if(p){
//enable all interrupts
p->IRQ_EN_L = 0xffffffff;
p->IRQ_EN_H = 0xffffffff;
//mask all interrupts
p->IRQ_MASK_L = 0xffffffff;
p->IRQ_MASK_H = 0xffffffff;
}
}
void ictl_mask_isr(fh_intc *p,int irq){
if(p){
if (irq < 32)
p->IRQ_MASK_L |= (1 << irq);
else
p->IRQ_MASK_H |= (1 << (irq - 32));
}
}
void ictl_unmask_isr(fh_intc *p,int irq){
if(p){
if (irq < 32)
p->IRQ_MASK_L &= ~(1 << irq);
else
p->IRQ_MASK_H &= ~(1 << (irq - 32));
}
}

View File

@@ -0,0 +1,413 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include "inc/fh_driverlib.h"
// *1: card off
// *0: card on
inline rt_uint32_t MMC_GetCardStatus(struct fh_mmc_obj *mmc_obj)
{
rt_uint32_t card_status = GET_REG(mmc_obj->base + OFFSET_SDC_CDETECT);
return card_status & 0x1;
}
inline void MMC_StartDma(struct fh_mmc_obj *mmc_obj)
{
rt_uint32_t reg;
SET_REG(mmc_obj->base + OFFSET_SDC_DBADDR, (rt_uint32_t)mmc_obj->descriptors);
reg = GET_REG(mmc_obj->base + OFFSET_SDC_BMOD);
reg |= 1 << 7;
SET_REG(mmc_obj->base + OFFSET_SDC_BMOD, reg);
}
inline void MMC_StopDma(struct fh_mmc_obj *mmc_obj)
{
rt_uint32_t reg;
reg = GET_REG(mmc_obj->base + OFFSET_SDC_BMOD);
reg &= ~(1 << 7);
SET_REG(mmc_obj->base + OFFSET_SDC_BMOD, reg);
}
void MMC_InitDescriptors(struct fh_mmc_obj *mmc_obj, rt_uint32_t *buf, rt_uint32_t size)
{
MMC_DMA_Descriptors *desc;
rt_uint32_t len = 0;
int i, desc_cnt = 0;
desc = mmc_obj->descriptors;
while(size > 0)
{
desc[desc_cnt].desc0.bit.own = 1;
desc[desc_cnt].desc0.bit.sencond_address_chained = 1;
desc[desc_cnt].desc1.bit.buffer1_size = MIN(MMC_DMA_DESC_BUFF_SIZE, size);
desc[desc_cnt].desc2.bit.buffer_addr0 = (rt_uint32_t)buf + len;
desc[desc_cnt].desc3.bit.buffer_addr1 = (rt_uint32_t)mmc_obj->descriptors + (desc_cnt + 1) * sizeof(MMC_DMA_Descriptors);
size -= desc[desc_cnt].desc1.bit.buffer1_size;
len += desc[desc_cnt].desc1.bit.buffer1_size;
desc_cnt++;
}
desc[0].desc0.bit.first_descriptor = 1;
desc[desc_cnt-1].desc0.bit.last_descriptor = 1;
desc[desc_cnt-1].desc3.bit.buffer_addr1 = 0;
}
inline rt_uint32_t MMC_GetWaterlevel(struct fh_mmc_obj *mmc_obj)
{
return (GET_REG(mmc_obj->base + OFFSET_SDC_STATUS) >> 17) & 0x1fff;
}
inline rt_uint32_t MMC_GetStatus(struct fh_mmc_obj *mmc_obj)
{
return GET_REG(mmc_obj->base + OFFSET_SDC_STATUS);
}
inline rt_uint32_t MMC_GetRawInterrupt(struct fh_mmc_obj *mmc_obj)
{
return GET_REG(mmc_obj->base + OFFSET_SDC_RINTSTS);
}
inline rt_uint32_t MMC_GetUnmaskedInterrupt(struct fh_mmc_obj *mmc_obj)
{
return GET_REG(mmc_obj->base + OFFSET_SDC_MINTSTS);
}
inline rt_uint32_t MMC_ClearRawInterrupt(struct fh_mmc_obj *mmc_obj, rt_uint32_t interrupts)
{
return SET_REG(mmc_obj->base + OFFSET_SDC_RINTSTS, interrupts);
}
inline rt_uint32_t MMC_GetInterruptMask(struct fh_mmc_obj *mmc_obj)
{
return GET_REG(mmc_obj->base + OFFSET_SDC_INTMASK);
}
inline rt_uint32_t MMC_SetInterruptMask(struct fh_mmc_obj *mmc_obj, rt_uint32_t mask)
{
return SET_REG(mmc_obj->base + OFFSET_SDC_INTMASK, mask);
}
inline void MMC_SetByteCount(struct fh_mmc_obj *mmc_obj, rt_uint32_t bytes)
{
SET_REG(mmc_obj->base + OFFSET_SDC_BYTCNT, bytes);
}
inline void MMC_SetBlockSize(struct fh_mmc_obj *mmc_obj, rt_uint32_t size)
{
SET_REG(mmc_obj->base + OFFSET_SDC_BLKSIZ, size);
}
inline rt_uint32_t MMC_GetResponse(struct fh_mmc_obj *mmc_obj, int resp_num)
{
return GET_REG(mmc_obj->base + OFFSET_SDC_RESP0 + resp_num * 4);
}
inline rt_uint32_t MMC_IsFifoEmpty(struct fh_mmc_obj *mmc_obj)
{
return (GET_REG(mmc_obj->base + OFFSET_SDC_STATUS) >> 2) & 0x1;
}
inline rt_uint32_t MMC_IsDataStateBusy(struct fh_mmc_obj *mmc_obj)
{
return (GET_REG(mmc_obj->base + OFFSET_SDC_STATUS) >> 10) & 0x1;
}
int MMC_WriteData(struct fh_mmc_obj *mmc_obj, rt_uint32_t *buf, rt_uint32_t size)
{
int filled = 0, fifo_available, i, retries;
for (i=0; i<size/4; i++)
{
retries = 0;
do
{
fifo_available = MMC_FIFO_DEPTH - MMC_GetWaterlevel(mmc_obj);
if(retries++ > 10000)
{
rt_kprintf("ERROR: %s, get water level timeout\n", __func__);
return -RT_ETIMEOUT;
}
}
while(!fifo_available);
SET_REG(mmc_obj->base + OFFSET_SDC_FIFO, *buf++);
}
retries = 0;
while(MMC_IsDataStateBusy(mmc_obj))
{
if(retries++ > 10000)
{
rt_kprintf("ERROR: %s, timeout, data line keep being busy\n", __func__);
return -RT_ETIMEOUT;
}
}
return 0;
}
int MMC_ReadData(struct fh_mmc_obj *mmc_obj, rt_uint32_t *buf, rt_uint32_t size)
{
int fifo_available, i, retries;
for (i=0; i<size/4; i++)
{
retries = 0;
do
{
fifo_available = MMC_GetWaterlevel(mmc_obj);
if(retries++ > 10000)
{
rt_kprintf("ERROR: %s, get water level timeout\n", __func__);
return -RT_ETIMEOUT;
}
}
while(!fifo_available);
*buf++ = GET_REG(mmc_obj->base + OFFSET_SDC_FIFO);
}
retries = 0;
while(MMC_IsDataStateBusy(mmc_obj))
{
if(retries++ > 10000)
{
rt_kprintf("ERROR: %s, timeout, data line keep being busy\n", __func__);
return -RT_ETIMEOUT;
}
}
return 0;
}
int MMC_UpdateClockRegister(struct fh_mmc_obj *mmc_obj, int div)
{
rt_uint32_t tick, timeout;
tick = rt_tick_get();
timeout = tick + RT_TICK_PER_SECOND / 10; //100ms in total
/* disable clock */
SET_REG(mmc_obj->base + OFFSET_SDC_CLKENA, 0);
SET_REG(mmc_obj->base + OFFSET_SDC_CLKSRC, 0);
/* inform CIU */
SET_REG(mmc_obj->base + OFFSET_SDC_CMD, 1<<31 | 1<<21);
while(GET_REG(mmc_obj->base + OFFSET_SDC_CMD) & 0x80000000)
{
tick = rt_tick_get();
if(tick > timeout)
{
rt_kprintf("ERROR: %s, update clock timeout\n", __func__);
return -RT_ETIMEOUT;
}
}
/* set clock to desired speed */
SET_REG(mmc_obj->base + OFFSET_SDC_CLKDIV, div);
/* inform CIU */
SET_REG(mmc_obj->base + OFFSET_SDC_CMD, 1<<31 | 1<<21);
while(GET_REG(mmc_obj->base + OFFSET_SDC_CMD) & 0x80000000)
{
tick = rt_tick_get();
if(tick > timeout)
{
rt_kprintf("ERROR: %s, update clock timeout\n", __func__);
return -RT_ETIMEOUT;
}
}
/* enable clock */
SET_REG(mmc_obj->base + OFFSET_SDC_CLKENA, 1);
/* inform CIU */
SET_REG(mmc_obj->base + OFFSET_SDC_CMD, 1<<31 | 1<<21);
while(GET_REG(mmc_obj->base + OFFSET_SDC_CMD) & 0x80000000)
{
tick = rt_tick_get();
if(tick > timeout)
{
rt_kprintf("ERROR: %s, update clock timeout\n", __func__);
return -RT_ETIMEOUT;
}
}
return 0;
}
int MMC_SetCardWidth(struct fh_mmc_obj *mmc_obj, int width)
{
switch(width)
{
case MMC_CARD_WIDTH_1BIT:
SET_REG(mmc_obj->base + OFFSET_SDC_CTYPE, 0);
break;
case MMC_CARD_WIDTH_4BIT:
SET_REG(mmc_obj->base + OFFSET_SDC_CTYPE, 1);
break;
default:
rt_kprintf("ERROR: %s, card width %d is not supported\n", __func__, width);
return -RT_ERROR;
break;
}
return 0;
}
int MMC_SendCommand(struct fh_mmc_obj *mmc_obj, rt_uint32_t cmd, rt_uint32_t arg, rt_uint32_t flags)
{
rt_uint32_t reg, tick, timeout;
tick = rt_tick_get();
timeout = tick + RT_TICK_PER_SECOND; //1s
SET_REG(mmc_obj->base + OFFSET_SDC_CMDARG, arg);
flags |= 1<<31 | 1<<29 | cmd;
SET_REG(mmc_obj->base + OFFSET_SDC_CMD, flags);
while(GET_REG(mmc_obj->base + OFFSET_SDC_CMD) & MMC_CMD_START_CMD)
{
tick = rt_tick_get();
if(tick > timeout)
{
rt_kprintf("ERROR: %s, send cmd timeout\n", __func__);
return -RT_ETIMEOUT;
}
}
//fixme: check HLE_INT_STATUS
return 0;
}
int MMC_ResetFifo(struct fh_mmc_obj *mmc_obj)
{
rt_uint32_t reg, tick, timeout;
tick = rt_tick_get();
timeout = tick + RT_TICK_PER_SECOND / 10; //100ms
reg = GET_REG(mmc_obj->base + OFFSET_SDC_CTRL);
reg |= 1 << 1;
SET_REG(mmc_obj->base + OFFSET_SDC_CTRL, reg);
//wait until fifo reset finish
while(GET_REG(mmc_obj->base + OFFSET_SDC_CTRL) & MMC_CTRL_FIFO_RESET)
{
tick = rt_tick_get();
if(tick > timeout)
{
rt_kprintf("ERROR: %s, FIFO reset timeout\n", __func__);
return -RT_ETIMEOUT;
}
}
return 0;
}
int MMC_Reset(struct fh_mmc_obj *mmc_obj)
{
rt_uint32_t reg, tick, timeout;
tick = rt_tick_get();
timeout = tick + RT_TICK_PER_SECOND / 10; //100ms
reg = GET_REG(mmc_obj->base + OFFSET_SDC_BMOD);
reg |= MMC_BMOD_RESET;
SET_REG(mmc_obj->base + OFFSET_SDC_BMOD, reg);
while(GET_REG(mmc_obj->base + OFFSET_SDC_BMOD) & MMC_BMOD_RESET)
{
tick = rt_tick_get();
if(tick > timeout)
{
rt_kprintf("ERROR: %s, BMOD Software reset timeout\n", __func__);
return -RT_ETIMEOUT;
}
}
reg = GET_REG(mmc_obj->base + OFFSET_SDC_CTRL);
reg |= MMC_CTRL_CONTROLLER_RESET | MMC_CTRL_FIFO_RESET | MMC_CTRL_DMA_RESET;
SET_REG(mmc_obj->base + OFFSET_SDC_CTRL, reg);
tick = rt_tick_get();
timeout = tick + RT_TICK_PER_SECOND / 10; //100ms
while(GET_REG(mmc_obj->base + OFFSET_SDC_CTRL) & (MMC_CTRL_CONTROLLER_RESET | MMC_CTRL_FIFO_RESET | MMC_CTRL_DMA_RESET))
{
tick = rt_tick_get();
if(tick > timeout)
{
rt_kprintf("ERROR: %s, CTRL dma|fifo|ctrl reset timeout\n", __func__);
return -RT_ETIMEOUT;
}
}
return 0;
}
void MMC_Init(struct fh_mmc_obj *mmc_obj)
{
rt_uint32_t reg;
if(mmc_obj->mmc_reset)
mmc_obj->mmc_reset(mmc_obj);
MMC_Reset(mmc_obj);
//fixed burst
reg = GET_REG(mmc_obj->base + OFFSET_SDC_BMOD);
reg |= 1 << 1;
SET_REG(mmc_obj->base + OFFSET_SDC_BMOD, reg);
//fixme: power on ? ctrl by gpio ?
MMC_ClearRawInterrupt(mmc_obj, MMC_INT_STATUS_ALL);
MMC_SetInterruptMask(mmc_obj, 0x0);
//fixme: use_internal_dma
reg = GET_REG(mmc_obj->base + OFFSET_SDC_CTRL);
reg |= MMC_CTRL_INT_ENABLE;
#ifdef MMC_USE_DMA
reg |= MMC_CTRL_USE_DMA;
#endif
SET_REG(mmc_obj->base + OFFSET_SDC_CTRL, reg);
//set timeout param
SET_REG(mmc_obj->base + OFFSET_SDC_TMOUT, 0xffffffff);
//set fifo
reg = GET_REG(mmc_obj->base + OFFSET_SDC_FIFOTH);
reg = (reg >> 16) & 0x7ff;
reg = ((0x2 << 28) | ((reg/2) << 16) | ((reg/2 + 1) << 0));
SET_REG(mmc_obj->base + OFFSET_SDC_FIFOTH, reg);
}

View File

@@ -0,0 +1,42 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include "inc/fh_driverlib.h"
void PWM_Enable(struct fh_pwm_obj *pwm_obj, int enable)
{
SET_REG(pwm_obj->base + OFFSET_PWM_CTRL, enable);
}
unsigned int PWM_GetPwmCmd(struct fh_pwm_obj *pwm_obj, int device_id)
{
return GET_REG(pwm_obj->base + OFFSET_PWM_CMD(device_id));
}
void PWM_SetPwmCmd(struct fh_pwm_obj *pwm_obj, int device_id, unsigned int reg)
{
SET_REG(pwm_obj->base + OFFSET_PWM_CMD(device_id), reg);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,164 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include "fh_def.h"
#include "fh_arch.h"
#include "inc/fh_driverlib.h"
void SPI_EnableSlaveen(struct fh_spi_obj *spi_obj, rt_uint32_t port)
{
rt_uint32_t reg;
reg = GET_REG(spi_obj->base + OFFSET_SPI_SER);
reg |= (1 << port);
SET_REG(spi_obj->base + OFFSET_SPI_SER, reg);
}
void SPI_DisableSlaveen(struct fh_spi_obj *spi_obj, rt_uint32_t port)
{
rt_uint32_t reg;
reg = GET_REG(spi_obj->base + OFFSET_SPI_SER);
reg &= ~(1 << port);
SET_REG(spi_obj->base + OFFSET_SPI_SER, reg);
}
void SPI_SetTxLevel(struct fh_spi_obj *spi_obj, rt_uint32_t level)
{
SET_REG(spi_obj->base + OFFSET_SPI_TXFTLR, level);
}
void SPI_EnableInterrupt(struct fh_spi_obj *spi_obj, rt_uint32_t flag)
{
rt_uint32_t reg;
reg = GET_REG(spi_obj->base + OFFSET_SPI_IMR);
reg |= flag;
SET_REG(spi_obj->base + OFFSET_SPI_IMR, reg);
}
void SPI_EnableDma(struct fh_spi_obj *spi_obj, rt_uint32_t channel)
{
rt_uint32_t reg;
reg = GET_REG(spi_obj->base + OFFSET_SPI_DMACTRL);
reg |= channel;
SET_REG(spi_obj->base + OFFSET_SPI_DMACTRL, reg);
}
void SPI_DisableDma(struct fh_spi_obj *spi_obj, rt_uint32_t channel)
{
rt_uint32_t reg;
reg = GET_REG(spi_obj->base + OFFSET_SPI_DMACTRL);
reg &= ~channel;
SET_REG(spi_obj->base + OFFSET_SPI_DMACTRL, reg);
}
void SPI_DisableInterrupt(struct fh_spi_obj *spi_obj, rt_uint32_t flag)
{
rt_uint32_t reg;
reg = GET_REG(spi_obj->base + OFFSET_SPI_IMR);
reg &= ~flag;
SET_REG(spi_obj->base + OFFSET_SPI_IMR, reg);
}
rt_uint32_t SPI_InterruptStatus(struct fh_spi_obj *spi_obj)
{
return GET_REG(spi_obj->base + OFFSET_SPI_ISR);
}
void SPI_ClearInterrupt(struct fh_spi_obj *spi_obj)
{
GET_REG(spi_obj->base + OFFSET_SPI_ICR);
}
rt_uint32_t SPI_ReadTxFifoLevel(struct fh_spi_obj *spi_obj)
{
return GET_REG(spi_obj->base + OFFSET_SPI_TXFLR);
}
rt_uint32_t SPI_ReadRxFifoLevel(struct fh_spi_obj *spi_obj)
{
return GET_REG(spi_obj->base + OFFSET_SPI_RXFLR);
}
UINT8 SPI_ReadData(struct fh_spi_obj *spi_obj)
{
return GET_REG(spi_obj->base + OFFSET_SPI_DR) & 0xff;
}
void SPI_WriteData(struct fh_spi_obj *spi_obj, UINT8 data)
{
SET_REG(spi_obj->base + OFFSET_SPI_DR, data);
}
rt_uint32_t SPI_ReadStatus(struct fh_spi_obj *spi_obj)
{
return GET_REG(spi_obj->base + OFFSET_SPI_SR);
}
void SPI_Enable(struct fh_spi_obj *spi_obj, int enable)
{
SET_REG(spi_obj->base + OFFSET_SPI_SSIENR, enable);
}
void SPI_WriteTxDmaLevel(struct fh_spi_obj *spi_obj, rt_uint32_t data)
{
SET_REG(spi_obj->base + OFFSET_SPI_DMATDL, data);
}
void SPI_WriteRxDmaLevel(struct fh_spi_obj *spi_obj, rt_uint32_t data)
{
SET_REG(spi_obj->base + OFFSET_SPI_DMARDL, data);
}
void SPI_SetParameter(struct fh_spi_obj *spi_obj)
{
rt_uint32_t reg;
struct spi_config *config;
config = &spi_obj->config;
SET_REG(spi_obj->base + OFFSET_SPI_BAUD, config->clk_div);
reg = GET_REG(spi_obj->base + OFFSET_SPI_CTRL0);
reg &= ~(0x3ff);
reg |= config->data_size \
| config->frame_format \
| config->clk_phase \
| config->clk_polarity \
| config->transfer_mode;
SET_REG(spi_obj->base + OFFSET_SPI_CTRL0, reg);
}

View File

@@ -0,0 +1,144 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
/*****************************************************************************
* Include Section
* add all #include here
*****************************************************************************/
#include "inc/fh_driverlib.h"
/*****************************************************************************
* Define section
* add all #define here
*****************************************************************************/
/****************************************************************************
* ADT section
* add definition of user defined Data Type that only be used in this file here
***************************************************************************/
/******************************************************************************
* Function prototype section
* add prototypes for all functions called by this file,execepting those
* declared in header file
*****************************************************************************/
/*****************************************************************************
* Global variables section - Exported
* add declaration of global variables that will be exported here
* e.g.
* int8_t foo;
****************************************************************************/
/*****************************************************************************
* Global variables section - Local
* define global variables(will be refered only in this file) here,
* static keyword should be used to limit scope of local variable to this file
* e.g.
* static uint8_t ufoo;
*****************************************************************************/
/* function body */
/*****************************************************************************
* Description:
* add funtion description here
* Parameters:
* description for each argument, new argument starts at new line
* Return:
* what does this function returned?
*****************************************************************************/
int timer_init(timer *tim)
{
tim->TIMER_CTRL_REG = 0;
}
int timer_set_mode(timer *tim, enum timer_mode mode)
{
switch (mode)
{
case TIMER_MODE_PERIODIC:
tim->TIMER_CTRL_REG |= TIMER_CTRL_MODE;
break;
case TIMER_MODE_ONESHOT:
tim->TIMER_CTRL_REG |= TIMER_CTRL_MODE;
break;
default:
rt_kprintf("Not support TIMER mode\n");
return -1;
break;
}
return 0;
}
void timer_set_period(timer *tim, UINT32 period, UINT32 clock)
{
tim->TIMER_LOAD_COUNT = clock/period;
}
void timer_enable(timer *tim)
{
tim->TIMER_CTRL_REG |= TIMER_CTRL_ENABLE;
}
void timer_disable(timer *tim)
{
tim->TIMER_CTRL_REG &= ~TIMER_CTRL_ENABLE;
}
void timer_enable_irq(timer *tim)
{
tim->TIMER_CTRL_REG &= ~TIMER_CTRL_INTMASK;
}
void timer_disable_irq(timer *tim)
{
tim->TIMER_CTRL_REG |= TIMER_CTRL_INTMASK;
}
UINT32 timer_get_status(timer *tim)
{
return tim->TIMER_INT_STATUS;
}
UINT32 timer_get_eoi(timer *tim)
{
return tim->TIMER_EOI;
}
UINT32 timer_get_value(timer *tim)
{
return tim->TIMER_LOAD_COUNT - tim->TIMER_CURRENT_VALUE;
}

View File

@@ -0,0 +1,278 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
/*****************************************************************************
* Include Section
* add all #include here
*****************************************************************************/
#include "inc/fh_driverlib.h"
/*****************************************************************************
* Define section
* add all #define here
*****************************************************************************/
/****************************************************************************
* ADT section
* add definition of user defined Data Type that only be used in this file here
***************************************************************************/
/******************************************************************************
* Function prototype section
* add prototypes for all functions called by this file,execepting those
* declared in header file
*****************************************************************************/
/*****************************************************************************
* Global variables section - Exported
* add declaration of global variables that will be exported here
* e.g.
* int8_t foo;
****************************************************************************/
/*****************************************************************************
* Global variables section - Local
* define global variables(will be refered only in this file) here,
* static keyword should be used to limit scope of local variable to this file
* e.g.
* static uint8_t ufoo;
*****************************************************************************/
/* function body */
/*****************************************************************************
* Description:
* add funtion description here
* Parameters:
* description for each argument, new argument starts at new line
* Return:
* what does this function returned?
*****************************************************************************/
int uart_init(uart *port)
{
port->UART_IER = 0;
port->UART_LCR = 0;
//port->UART_DLL = 0;
//port->UART_DLH = 0;
}
UINT32 uart_get_status(uart *port)
{
return port->UART_USR;
}
void uart_configure(uart *port, enum data_bits data_bit,
enum stop_bits stop_bit, enum parity parity,
UINT32 buard_rate, UINT32 uart_clk)
{
UINT32 divisor;
UINT32 freq;
UINT32 baud_div;
UINT32 lcr_reg = 0;
UINT32 ret;
/*divisor = DIV(buard_rate);
port->UART_LCR |= UART_LCR_DLAB;
port->UART_DLL = divisor & 0xFF;
port->UART_DLH = (divisor >> 8) & 0xFF;
port->UART_LCR &= ~UART_LCR_DLAB;*/
do{
//clear fifo...
port->UART_FCR = UART_FCR_RFIFOR | UART_FCR_XFIFOR;
//read status..
ret = uart_get_status(port);
}while(ret & UART_USR_BUSY);
switch (data_bit) {
case UART_DATA_BIT5:
lcr_reg |= UART_LCR_DLS5;
break;
case UART_DATA_BIT6:
lcr_reg |= UART_LCR_DLS6;
break;
case UART_DATA_BIT7:
lcr_reg |= UART_LCR_DLS7;
break;
case UART_DATA_BIT8:
lcr_reg |= UART_LCR_DLS8;
break;
default:
lcr_reg |= UART_LCR_DLS8;
break;
}
switch (stop_bit) {
case UART_STOP_BIT1:
lcr_reg |= UART_LCR_STOP1;
break;
case UART_STOP_BIT2:
lcr_reg |= UART_LCR_STOP2;
break;
default:
lcr_reg |= UART_LCR_STOP1;
break;
}
switch (parity) {
case UART_PARITY_EVEN:
lcr_reg |= UART_LCR_EVEN | UART_LCR_PEN;
break;
case UART_PARITY_ODD:
lcr_reg |= UART_LCR_PEN;
break;
case UART_PARITY_ST:
lcr_reg |= UART_LCR_SP;
break;
case UART_PARITY_NONE:
default:
break;
}
switch (buard_rate) {
case 115200:
baud_div = BAUDRATE_115200;
break;
case 57600:
baud_div = BAUDRATE_57600;
break;
case 38400:
baud_div = BAUDRATE_38400;
break;
case 19200:
baud_div = BAUDRATE_19200;
break;
case 9600:
baud_div = BAUDRATE_9600;
break;
default:
baud_div = BAUDRATE_115200;
break;
}
//clear fifo
port->UART_FCR = UART_FCR_RFIFOR | UART_FCR_XFIFOR;
//div
ret = port->UART_LCR;
ret |= UART_LCR_DLAB;
port->UART_LCR = ret;
port->RBRTHRDLL = baud_div & 0x00ff;
port->DLHIER = (baud_div & 0x00ff)>>8;
/* clear DLAB */
ret = ret & 0x7f;
port->UART_LCR = ret;
//line control
port->UART_LCR = lcr_reg;
//fifo control
port->UART_FCR = UART_FCR_FIFOE | UART_FCR_RFIFOR | UART_FCR_XFIFOR | UART_FCR_TET_1_4 | UART_FCR_RT_ONE;
}
int uart_enable_irq(uart *port, UINT32 mode)
{
unsigned int ret;
ret = port->UART_IER;
ret |= mode;
port->UART_IER = ret;
}
int uart_disable_irq(uart *port, UINT32 mode)
{
unsigned int ret;
ret = port->UART_IER;
ret &= ~mode;
port->UART_IER = ret;
}
UINT32 uart_get_iir_status(uart *port)
{
return port->UART_IIR;
}
UINT32 uart_get_line_status(uart *port)
{
return port->UART_LSR;
}
UINT32 uart_is_rx_ready(uart *port)
{
return port->UART_LSR & UART_LSR_DR;
}
UINT8 uart_getc(uart *port)
{
return port->UART_RBR & 0xFF;
}
void uart_putc(uart *port, UINT8 c)
{
//while(!(port->UART_USR & UART_USR_TFNF));
port->UART_THR = c;
}
void uart_set_fifo_mode(uart *port, UINT32 fifo_mode)
{
port->UART_FCR = fifo_mode;
}

View File

@@ -0,0 +1,58 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include "inc/fh_driverlib.h"
void WDT_Enable(struct fh_wdt_obj *wdt_obj, int enable)
{
SET_REG(wdt_obj->base + WDOG_CONTROL_REG_OFFSET, enable);
}
inline int WDT_IsEnable(struct fh_wdt_obj *wdt_obj)
{
return GET_REG(wdt_obj->base + WDOG_CONTROL_REG_OFFSET) &
WDOG_CONTROL_REG_WDT_EN_MASK;
}
void WDT_SetTopValue(struct fh_wdt_obj *wdt_obj, int top)
{
SET_REG(wdt_obj->base + WDOG_TIMEOUT_RANGE_REG_OFFSET, top);
}
void WDT_SetCtrl(struct fh_wdt_obj *wdt_obj, UINT32 reg)
{
SET_REG(wdt_obj->base + WDOG_CONTROL_REG_OFFSET, reg);
}
void WDT_Kick(struct fh_wdt_obj *wdt_obj)
{
SET_REG(wdt_obj->base + WDOG_COUNTER_RESTART_REG_OFFSET, WDOG_COUNTER_RESTART_KICK_VALUE);
}
UINT32 WDT_GetCurrCount(struct fh_wdt_obj *wdt_obj)
{
return GET_REG(wdt_obj->base + WDOG_CURRENT_COUNT_REG_OFFSET);
}

View File

@@ -0,0 +1,39 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#include <rtthread.h>
#include <rthw.h>
#include "fh_def.h"
#include "fh_arch.h"
#include "fh_ictl.h"
#include "fh_timer.h"
#include "fh_uart.h"
#include "fh_spi.h"
#include "fh_gpio.h"
#include "fh_mmc.h"
#include "fh_i2c.h"
#include "fh_pwm.h"
#include "fh_wdt.h"

View File

@@ -0,0 +1,54 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef FH_GPIO_H_
#define FH_GPIO_H_
#define REG_GPIO_SWPORTA_DR (0x0000)
#define REG_GPIO_SWPORTA_DDR (0x0004)
#define REG_GPIO_PORTA_CTL (0x0008)
#define REG_GPIO_INTEN (0x0030)
#define REG_GPIO_INTMASK (0x0034)
#define REG_GPIO_INTTYPE_LEVEL (0x0038)
#define REG_GPIO_INT_POLARITY (0x003C)
#define REG_GPIO_INTSTATUS (0x0040)
#define REG_GPIO_RAWINTSTATUS (0x0044)
#define REG_GPIO_DEBOUNCE (0x0048)
#define REG_GPIO_PORTA_EOI (0x004C)
#define REG_GPIO_EXT_PORTA (0x0050)
#define NUM_OF_GPIO (64)
struct fh_gpio_obj
{
unsigned int id;
unsigned int irq;
};
#endif /* FH_GPIO_H_ */

View File

@@ -0,0 +1,226 @@
/*
* This file is part of FH8620 BSP for RT-Thread distribution.
*
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.fullhan.com to get contact with Fullhan.
*
* Change Logs:
* Date Author Notes
*/
#ifndef FH_I2C_H_
#define FH_I2C_H_
#include "fh_def.h"
#define OFFSET_I2C_CON (0x0000)
#define OFFSET_I2C_TAR (0x0004)
#define OFFSET_I2C_SAR (0x0008)
#define OFFSET_I2C_HS_MADDR (0x000C)
#define OFFSET_I2C_DATA_CMD (0x0010)
#define OFFSET_I2C_SS_SCL_HCNT (0x0014)
#define OFFSET_I2C_SS_SCL_LCNT (0x0018)
#define OFFSET_I2C_FS_SCL_HCNT (0x001C)
#define OFFSET_I2C_FS_SCL_LCNT (0x0020)
#define OFFSET_I2C_HS_SCL_HCNT (0x0024)
#define OFFSET_I2C_HS_SCL_LCNT (0x0028)
#define OFFSET_I2C_INTR_STAT (0x002c)
#define OFFSET_I2C_INTR_MASK (0x0030)
#define OFFSET_I2C_RAW_INTR_STAT (0x0034)
#define OFFSET_I2C_RX_TL (0x0038)
#define OFFSET_I2C_TX_TL (0x003c)
#define OFFSET_I2C_CLR_INTR (0x0040)
#define OFFSET_I2C_CLR_RX_UNDER (0x0044)
#define OFFSET_I2C_CLR_RX_OVER (0x0048)
#define OFFSET_I2C_CLR_TX_OVER (0x004c)
#define OFFSET_I2C_CLR_RD_REQ (0x0050)
#define OFFSET_I2C_CLR_TX_ABRT (0x0054)
#define OFFSET_I2C_CLR_RX_DONE (0x0058)
#define OFFSET_I2C_CLR_ACTIVITY (0x005c)
#define OFFSET_I2C_CLR_STOP_DET (0x0060)
#define OFFSET_I2C_CLR_START_DET (0x0064)
#define OFFSET_I2C_CLR_GEN_CALL (0x0068)
#define OFFSET_I2C_ENABLE (0x006c)
#define OFFSET_I2C_STATUS (0x0070)
#define OFFSET_I2C_TXFLR (0x0074)
#define OFFSET_I2C_RXFLR (0x0078)
#define OFFSET_I2C_DMA_CR (0x0088)
#define OFFSET_I2C_DMA_TDLR (0x008c)
#define OFFSET_I2C_DMA_RDLR (0x0090)
#define OFFSET_I2C_COMP_PARAM1 (0x00f4)
#define OFFSET_I2C_TX_ABRT_SOURCE (0x0080)
#define I2C_M_TEN 0x0100 /* this is a ten bit chip address */
#define I2C_M_RD 0x0001 /* read data, from slave to master */
#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
#define DW_IC_CON_MASTER 0x1
#define DW_IC_CON_SPEED_STD 0x2
#define DW_IC_CON_SPEED_FAST 0x4
#define DW_IC_CON_10BITADDR_MASTER 0x10
#define DW_IC_CON_RESTART_EN 0x20
#define DW_IC_CON_SLAVE_DISABLE 0x40
#define DW_IC_INTR_RX_UNDER 0x001
#define DW_IC_INTR_RX_OVER 0x002
#define DW_IC_INTR_RX_FULL 0x004
#define DW_IC_INTR_TX_OVER 0x008
#define DW_IC_INTR_TX_EMPTY 0x010
#define DW_IC_INTR_RD_REQ 0x020
#define DW_IC_INTR_TX_ABRT 0x040
#define DW_IC_INTR_RX_DONE 0x080
#define DW_IC_INTR_ACTIVITY 0x100
#define DW_IC_INTR_STOP_DET 0x200
#define DW_IC_INTR_START_DET 0x400
#define DW_IC_INTR_GEN_CALL 0x800
#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \
DW_IC_INTR_TX_EMPTY | \
DW_IC_INTR_TX_ABRT | \
DW_IC_INTR_STOP_DET)
#define DW_IC_STATUS_ACTIVITY 0x1
#define DW_IC_STATUS_MASTER_ACTIVITY 0x20
#define DW_IC_ERR_TX_ABRT 0x1
/*
* status codes
*/
#define STATUS_IDLE 0x0
#define STATUS_WRITE_IN_PROGRESS 0x1
#define STATUS_READ_IN_PROGRESS 0x2
#define TIMEOUT 20 /* ms */
/*
* hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
*
* only expected abort codes are listed here
* refer to the datasheet for the full list
*/
#define ABRT_7B_ADDR_NOACK 0
#define ABRT_10ADDR1_NOACK 1
#define ABRT_10ADDR2_NOACK 2
#define ABRT_TXDATA_NOACK 3
#define ABRT_GCALL_NOACK 4
#define ABRT_GCALL_READ 5
#define ABRT_SBYTE_ACKDET 7
#define ABRT_SBYTE_NORSTRT 9
#define ABRT_10B_RD_NORSTRT 10
#define ABRT_MASTER_DIS 11
#define ARB_LOST 12
#define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK)
#define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK)
#define DW_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK)
#define DW_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK)
#define DW_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK)
#define DW_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ)
#define DW_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET)
#define DW_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT)
#define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT)
#define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS)
#define DW_IC_TX_ARB_LOST (1UL << ARB_LOST)
#define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \
DW_IC_TX_ABRT_10ADDR1_NOACK | \
DW_IC_TX_ABRT_10ADDR2_NOACK | \
DW_IC_TX_ABRT_TXDATA_NOACK | \
DW_IC_TX_ABRT_GCALL_NOACK)
static char *abort_sources[] = {
[ABRT_7B_ADDR_NOACK] =
"slave address not acknowledged (7bit mode)",
[ABRT_10ADDR1_NOACK] =
"first address byte not acknowledged (10bit mode)",
[ABRT_10ADDR2_NOACK] =
"second address byte not acknowledged (10bit mode)",
[ABRT_TXDATA_NOACK] =
"data not acknowledged",
[ABRT_GCALL_NOACK] =
"no acknowledgement for a general call",
[ABRT_GCALL_READ] =
"read after general call",
[ABRT_SBYTE_ACKDET] =
"start byte acknowledged",
[ABRT_SBYTE_NORSTRT] =
"trying to send start byte when restart is disabled",
[ABRT_10B_RD_NORSTRT] =
"trying to read when restart is disabled (10bit mode)",
[ABRT_MASTER_DIS] =
"trying to use disabled adapter",
[ARB_LOST] =
"lost arbitration",
};
/* i2c interrput definition */
#define M_GEN_CALL (1<<11)
#define M_START_DET (1<<10)
#define M_STOP_DET (1<<9)
#define M_ACTIVITY (1<<8)
#define M_RX_DONE (1<<7)
#define M_TX_ABRT (1<<6)
#define M_RD_REQ (1<<5)
#define M_TX_EMPTY (1<<4)
#define M_TX_OVER (1<<3)
#define M_RX_FULL (1<<2)
#define M_RX_OVER (1<<1)
#define M_RX_UNDER (1<<0)
#define M_NONE (0)
struct i2c_config
{
int speed_mode;
UINT32 tx_fifo_depth;
UINT32 rx_fifo_depth;
};
struct fh_i2c_obj
{
UINT32 id;
UINT32 irq;
UINT32 base;
UINT32 input_clock;
UINT32 abort_source;
struct i2c_config config;
};
void I2C_Init(struct fh_i2c_obj *i2c_obj);
inline void I2C_Enable(struct fh_i2c_obj *i2c_obj, int enable);
inline void I2C_SetSlaveAddress(struct fh_i2c_obj *i2c_obj, rt_uint16_t addr);
inline UINT32 I2C_GetTransmitFifoLevel(struct fh_i2c_obj *i2c_obj);
inline UINT32 I2C_GetReceiveFifoLevel(struct fh_i2c_obj *i2c_obj);
inline UINT32 I2C_SetTransmitThreshold(struct fh_i2c_obj *i2c_obj, int txtl);
int I2C_HandleTxAbort(struct fh_i2c_obj *i2c_obj);
UINT32 I2C_ClearAndGetInterrupts(struct fh_i2c_obj *i2c_obj);
inline void I2C_SetInterruptMask(struct fh_i2c_obj *i2c_obj, UINT32 mask);
inline UINT32 I2C_GetInterruptMask(struct fh_i2c_obj *i2c_obj);
inline void I2C_SetDataCmd(struct fh_i2c_obj *i2c_obj, UINT32 reg);
inline UINT8 I2C_GetData(struct fh_i2c_obj *i2c_obj);
int I2C_WaitMasterIdle(struct fh_i2c_obj *i2c_obj);
int I2C_WaitDeviceIdle(struct fh_i2c_obj *i2c_obj);
#endif /* FH_I2C_H_ */

Some files were not shown because too many files have changed in this diff Show More