[bsp]update x1000 bsp driver

This commit is contained in:
tangyuxin
2017-11-11 13:51:56 +08:00
parent f7a6078c5c
commit d724e75f22
102 changed files with 22111 additions and 1488 deletions

24
bsp/x1000/Kconfig Normal file
View File

@@ -0,0 +1,24 @@
mainmenu "RT-Thread Configuration"
config $BSP_DIR
string
option env="BSP_ROOT"
default "."
config $RTT_DIR
string
option env="RTT_ROOT"
default "E:/rt-thread"
# you can change the RTT_ROOT default "../.." to your rtthread_root,
# example : default "F:/git_repositories/rt-thread"
config $PKGS_DIR
string
option env="PKGS_ROOT"
default "packages"
source "$RTT_DIR/KConfig"
source "$PKGS_DIR/KConfig"
source "$BSP_DIR/drivers/Kconfig"

View File

@@ -1,8 +1,12 @@
import os
import sys
import rtconfig
from rtconfig import RTT_ROOT
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.join(Dir('#').get_abspath(), 'rt-thread')
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
@@ -11,16 +15,19 @@ TARGET = 'rtthread-x1000.' + rtconfig.TARGET_EXT
env = Environment(tools = ['mingw'],
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
CXX = rtconfig.CC, CXXFLAGS = rtconfig.CXXFLAGS,
CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
# add --start-group and --end-group for GNU GCC
env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS -Wl,--start-group $_LIBFLAGS -Wl,--end-group'
Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT)
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)
# make a building
DoBuilding(TARGET, objs)

View File

@@ -1,13 +1,10 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
src = Glob('*.c') + Glob('*.cpp')
CPPPATH = [cwd, str(Dir('#'))]
if not GetDepend("RT_USING_DFS_ROMFS"):
SrcRemove(src, "romfs.c")
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@@ -0,0 +1,74 @@
/*
* File : blink.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2017, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2017-11-8 Tangyuxin first version
*/
#include <rtthread.h>
#include <board.h>
#include <drv_gpio.h>
void blink_task(void* param)
{
rt_uint8_t cnt = 0;
while(1)
{
rt_thread_delay(RT_TICK_PER_SECOND / 4);
if(cnt & 0x01)
gpio_set_value(BLINK_LED0_PORT,BLINK_LED0_PIN,0);
else
gpio_set_value(BLINK_LED0_PORT,BLINK_LED0_PIN,1);
if(cnt & 0x02)
gpio_set_value(BLINK_LED1_PORT,BLINK_LED1_PIN,0);
else
gpio_set_value(BLINK_LED1_PORT,BLINK_LED1_PIN,1);
if(cnt & 0x04)
gpio_set_value(BLINK_LED2_PORT,BLINK_LED2_PIN,0);
else
gpio_set_value(BLINK_LED2_PORT,BLINK_LED2_PIN,1);
if(cnt & 0x08)
gpio_set_value(BLINK_LED3_PORT,BLINK_LED3_PIN,0);
else
gpio_set_value(BLINK_LED3_PORT,BLINK_LED3_PIN,1);
cnt ++;
}
}
int blink_init(void)
{
rt_thread_t tid;
tid = rt_thread_create("blink",
blink_task, RT_NULL,
512,
RT_THREAD_PRIORITY_MAX - 2,
10);
if (tid != RT_NULL)
rt_thread_startup(tid);
}
INIT_APP_EXPORT(blink_init);

View File

@@ -1,7 +1,7 @@
/*
* File : _main.c
* File : main.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
* COPYRIGHT (C) 2008 - 2017, RT-Thread Development Team
*
* 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
@@ -19,14 +19,12 @@
*
* Change Logs:
* Date Author Notes
* 2015-11-19 Urey the first version
* 2017-11-8 Tangyuxin first version
*/
#include <stdio.h>
#include <stdlib.h>
#include <rtthread.h>
int main(int argc, char** argv)
{
printf("Hello RT-Thread!\n");
{
return 0;
}

View File

@@ -0,0 +1,72 @@
/*
* File : mnt_init.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2017, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2017-11-8 Tangyuxin first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#ifdef RT_USING_DFS
#include <dfs_fs.h>
int mnt_init(void)
{
rt_kprintf("init filesystem...\n");
#ifdef RT_USING_MTD_NOR
//mount rootfs
if (dfs_mount("rootfs", "/", "elm", 0, 0) == 0)
{
rt_kprintf("File System on root initialized!\n");
}
else
{
rt_kprintf("File System on root initialization failed!\n");
}
//mount appfs
if (dfs_mount("appfs", "/appfs", "elm", 0, 0) == 0)
{
rt_kprintf("File System on appfs initialized!\n");
}
else
{
rt_kprintf("File System on appfs initialization failed!\n");
}
#endif
#if (defined(RT_USING_SDIO) && defined(RT_USING_MSC0))
rt_thread_delay(RT_TICK_PER_SECOND/5);
if (dfs_mount("sd0", "/sd", "elm", 0, 0) == 0)
{
rt_kprintf("File System on TF initialized!\n");
}
else
{
rt_kprintf("File System on TF fail!\n");
}
#endif
return 0;
}
INIT_ENV_EXPORT(mnt_init);
#endif

View File

@@ -0,0 +1,154 @@
/*
* File : rtgui_demo.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2017, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2017-11-8 Tangyuxin first version
*/
#include <rtthread.h>
// #define DEBUG
#ifdef DEBUG
#define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__)
#else
#define DEBUG_PRINTF(...)
#endif
#ifdef RT_USING_GUIENGINE
#include <rtgui/rtgui.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/rtgui_app.h>
#include <rtgui/widgets/window.h>
#include <rtgui/dc.h>
struct rtgui_win *main_win;
rt_bool_t dc_event_handler(struct rtgui_object *object, rtgui_event_t *event);
static void rt_gui_demo_entry(void *parameter)
{
struct rtgui_app *app;
DEBUG_PRINTF("gui demo entry\n");
/* create gui app */
app = rtgui_app_create("gui_demo");
if (app == RT_NULL)
{
DEBUG_PRINTF("rtgui_app_create faild\n");
return;
}
/* create main window */
main_win = rtgui_mainwin_create(RT_NULL,
"UiWindow", RTGUI_WIN_STYLE_NO_TITLE | RTGUI_WIN_STYLE_NO_BORDER);
if (main_win == RT_NULL)
{
DEBUG_PRINTF("main_win is null\n");
rtgui_app_destroy(app);
return;
}
rtgui_object_set_event_handler(RTGUI_OBJECT(main_win), dc_event_handler);
DEBUG_PRINTF("rtgui_win_show\n");
rtgui_win_show(main_win, RT_FALSE);
DEBUG_PRINTF("rtgui_app_run\n");
rtgui_app_run(app);
DEBUG_PRINTF("rtgui_win_destroy\n");
rtgui_win_destroy(main_win);
DEBUG_PRINTF("rtgui_app_destroy\n");
rtgui_app_destroy(app);
}
rt_bool_t dc_event_handler(struct rtgui_object *object, rtgui_event_t *event)
{
struct rtgui_widget *widget = RTGUI_WIDGET(object);
if (event->type == RTGUI_EVENT_PAINT)
{
struct rtgui_dc *dc;
rtgui_rect_t rect;
rt_kprintf("\r\n RTGUI_EVENT_PAINT \r\n");
rtgui_win_event_handler(RTGUI_OBJECT(widget), event);
rtgui_widget_get_rect(widget, &rect);
DEBUG_PRINTF("widget react x1: %d, y1: %d, x2: %d, y2: %d\r\n",
rect.x1, rect.y1, rect.x2, rect.y2);
dc = rtgui_dc_begin_drawing(widget);
if(dc == RT_NULL)
{
DEBUG_PRINTF("\r\n dc is null \r\n");
return RT_FALSE;
}
rtgui_dc_draw_line(dc, rect.x1, rect.y1, rect.x2, rect.y2);
rtgui_dc_draw_line(dc, rect.x1, rect.y2, rect.x2, rect.y1);
rect.x1 += (rect.x2 - rect.x1) / 2;
rect.y1 += (rect.y2 - rect.y1) / 2;
rtgui_dc_draw_text_stroke(dc, __DATE__"--"__TIME__, &rect, HIGH_LIGHT, BLUE);
rtgui_dc_end_drawing(dc,RT_TRUE);
}
return RT_FALSE;
}
int rt_gui_demo_init(void)
{
rt_thread_t tid;
rt_device_t device;
rt_err_t err;
device = rt_device_find("lcd");
if(device == RT_NULL)
{
rt_kprintf("Not found LCD driver\n");
return RT_ERROR;
}
err = rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
if (err != RT_EOK)
{
rt_kprintf("Open LCD driver fail\n");
return RT_ERROR;
}
/* set graphic device */
rtgui_graphic_set_device(device);
tid = rt_thread_create("mygui",
rt_gui_demo_entry, RT_NULL,
2048, 25, 10);
if (tid != RT_NULL)
rt_thread_startup(tid);
return 0;
}
INIT_APP_EXPORT(rt_gui_demo_init);
#endif /* RT_USING_GUIENGINE */

View File

@@ -1,63 +0,0 @@
/*
* File : board.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2015-11-19 Urey the first version
*/
#ifndef _BOARD_H_
#define _BOARD_H_
#include <stdint.h>
#include "x1000.h"
#define RT_USING_JZ_X1000
// #define BOARD_PHOENIX
// #define BOARD_CANNA
#ifdef BOARD_PHOENIX
#define RT_USING_EMAC
#endif
/*********************************************************************************************************
** Clock for Board
*********************************************************************************************************/
#define BOARD_EXTAL_CLK 24000000
#define BOARD_RTC_CLK 32768
#define BOARD_CPU_CLK (1008 * 1000 * 1000UL)
/*********************************************************************************************************
** HEAP Setting
*********************************************************************************************************/
extern unsigned char __bss_start;
extern unsigned char __bss_end;
#define RT_HW_HEAP_BEGIN (void*)&__bss_end
#define RT_HW_HEAP_END (void*)(0x80000000 + 32 * 1024 * 1024)
/*********************************************************************************************************
** UART Setting
*********************************************************************************************************/
#define RT_USING_UART2
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,264 +0,0 @@
/*
* File : drv_uart.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2015-11-19 Urey the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "drv_uart.h"
struct jz_uart_s
{
rt_uint32_t hw_base;
rt_uint32_t irqno;
char name[RT_NAME_MAX];
};
static rt_err_t uart_configure (struct rt_serial_device *serial, struct serial_configure *cfg);
static rt_err_t uart_control (struct rt_serial_device *serial, int cmd, void *arg);
static int uart_putc (struct rt_serial_device *serial, char c);
static int uart_getc (struct rt_serial_device *serial);
static rt_size_t uart_dma_transmit (struct rt_serial_device *serial, const rt_uint8_t *buf, rt_size_t size, int direction);
static void uart_irq_handler (int irqno, void *param);
const struct rt_uart_ops _uart_ops =
{
uart_configure,
uart_control,
uart_putc,
uart_getc,
uart_dma_transmit
};
/*
* UART Initiation
*/
void rt_hw_uart_init(void)
{
struct rt_serial_device *serial;
struct jz_uart_s *uart;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
#ifdef RT_USING_UART1
{
static struct rt_serial_device serial1;
static struct jz_uart_s uart1;
serial = &serial1;
uart = &uart1;
serial->ops = &_uart_ops;
serial->config = config;
serial->config.baud_rate = 115200;
uart->hw_base = UART0_BASE;
uart->irqno = IRQ_UART0;
rt_hw_serial_register(serial,
"uart1",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
}
#endif
#ifdef RT_USING_UART2
{
static struct rt_serial_device serial2;
static struct jz_uart_s uart2;
serial = &serial2;
uart = &uart2;
serial->ops = &_uart_ops;
serial->config = config;
serial->config.baud_rate = 115200;
uart->hw_base = UART2_BASE;
uart->irqno = IRQ_UART2;
rt_hw_serial_register(serial,
"uart2",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
}
#endif
#ifdef RT_USING_UART3
{
static struct rt_serial_device serial3;
static struct jz_uart_s uart3;
serial = &serial3;
uart = &uart3;
serial->ops = &_uart_ops;
serial->config = config;
serial->config.baud_rate = 115200;
uart->hw_base = UART3_BASE;
uart->irqno = IRQ_UART3;
rt_hw_serial_register(serial,
"uart3",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
}
#endif
}
/*
* UART interface
*/
static rt_err_t uart_configure (struct rt_serial_device *serial, struct serial_configure *cfg)
{
rt_uint32_t baud_div;
struct jz_uart_s * uart;
RT_ASSERT(serial != RT_NULL);
serial->config = *cfg;
uart = serial->parent.user_data;
RT_ASSERT(uart != RT_NULL);
/* Init UART Hardware */
UART_IER(uart->hw_base) = 0; /* clear interrupt */
UART_FCR(uart->hw_base) = ~UARTFCR_UUE; /* disable UART unite */
/* Enable UART clock */
/* Set both receiver and transmitter in UART mode (not SIR) */
UART_SIRCR(uart->hw_base) = ~(SIRCR_RSIRE | SIRCR_TSIRE);
/* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
UART_LCR(uart->hw_base) = UARTLCR_WLEN_8;
/* set baudrate */
#if defined(RT_USING_JZ4750) || defined(RT_USING_JZ4755) || defined(RT_USING_JZ4760)
if(REG_CPM_CPCCR & (1UL << 30))
{
/* CPCCR.ECS = 1: clock source is EXCLK/2 */
baud_div = BOARD_EXTAL_CLK / 2 / 16 / cfg->baud_rate;
}
else
#endif
{
/* CPCCR.ECS = 0: clock source is EXCLK */
baud_div = BOARD_EXTAL_CLK / 16 / cfg->baud_rate;
}
UART_LCR(uart->hw_base) |= UARTLCR_DLAB;
UART_DLHR(uart->hw_base) = (baud_div >> 8) & 0xff;
UART_DLLR(uart->hw_base) = baud_div & 0xff;
UART_LCR(uart->hw_base) &= ~UARTLCR_DLAB;
/* Enable UART unit, enable and clear FIFO */
UART_FCR(uart->hw_base) = UARTFCR_UUE | UARTFCR_FE | UARTFCR_TFLS | UARTFCR_RFLS;
return (RT_EOK);
}
static rt_err_t uart_control (struct rt_serial_device *serial, int cmd, void *arg)
{
struct jz_uart_s * uart;
uart = serial->parent.user_data;
RT_ASSERT(uart != RT_NULL);
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
/* Disable the UART Interrupt */
UART_IER(uart->hw_base) &= ~(UARTIER_RIE | UARTIER_RTIE);
rt_hw_interrupt_mask(uart->irqno);
break;
case RT_DEVICE_CTRL_SET_INT:
/* install interrupt */
rt_hw_interrupt_install(uart->irqno, uart_irq_handler,
serial, uart->name);
rt_hw_interrupt_umask(uart->irqno);
/* Enable the UART Interrupt */
UART_IER(uart->hw_base) |= (UARTIER_RIE | UARTIER_RTIE);
break;
}
return (RT_EOK);
}
static int uart_putc (struct rt_serial_device *serial, char c)
{
struct jz_uart_s* uart;
uart = serial->parent.user_data;
/* FIFO status, contain valid data */
while (!((UART_LSR(uart->hw_base) & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60));
/* write data */
UART_TDR(uart->hw_base) = c;
return (1);
}
static int uart_getc (struct rt_serial_device *serial)
{
struct jz_uart_s* uart = serial->parent.user_data;
/* Receive Data Available */
if (UART_LSR(uart->hw_base) & UARTLSR_DR)
{
return UART_RDR(uart->hw_base);
}
return (-1);
}
static rt_size_t uart_dma_transmit (struct rt_serial_device *serial, const rt_uint8_t *buf, rt_size_t size, int direction)
{
return (0);
}
/* UART ISR */
static void uart_irq_handler(int irqno, void *param)
{
rt_ubase_t isr;
struct rt_serial_device *serial = (struct rt_serial_device*)param;
struct jz_uart_s* uart = serial->parent.user_data;
/* read interrupt status and clear it */
isr = UART_ISR(uart->hw_base);
if (isr & UARTISR_IID_RDI) /* Receive Data Available */
{
rt_hw_serial_isr(serial,RT_SERIAL_EVENT_RX_IND);
}
if(isr & UARTISR_IID_THRI)
{
rt_hw_serial_isr(serial,RT_SERIAL_EVENT_TX_DONE);
}
}

131
bsp/x1000/drivers/Kconfig Normal file
View File

@@ -0,0 +1,131 @@
choice
prompt "Choice bsp board"
default BOARD_HALLEY2_REALBOARD_V2
config BOARD_HALLEY2
bool "Using haller2 board"
config BOARD_PHOENIX
bool "Using phoenix board"
config BOARD_CANNA
bool "Using canna board"
config BOARD_HALLEY2_FIR
bool "Using haller2 fir board"
config BOARD_HALLEY2_REALBOARD
bool "Using haller2 realboard board"
config BOARD_HALLEY2_REALBOARD_V2
bool "Using haller2 realboard v2 board"
config BOARD_HALLEY2_IDELAN
bool "Using haller2 idelan board"
endchoice
if RT_USING_SERIAL
config RT_USING_UART0
bool "Using UART0"
default n
config RT_USING_UART1
bool "Using UART1"
default n
config RT_USING_UART2
bool "Using UART2"
default y
endif
if RT_USING_SDIO
config RT_USING_MSC0
bool "Using MSC0 for sd card"
default y
config RT_USING_MSC1
bool "Using MSC1 for wifi"
default y
config RT_MMCSD_STACK_SIZE
int "Set mmc thread stack size"
default 2048
endif
if RT_USING_GUIENGINE
config RT_USING_SLCD
bool "Using lcd display"
default y
if RT_USING_SLCD
choice
prompt "Choice LCD controller"
default RT_USING_ILI9488
config RT_USING_ILI9488
bool "Using ILI9488 controller"
config RT_USING_ILI9341
bool "Using ILI9341 controller"
config RT_USING_OTM4802
bool "Using OTM4802 controller"
config RT_USING_TRULY_TFT240240
bool "Using TFT240240 controller"
endchoice
endif
if RT_USING_I2C
config RT_USING_TOUCH
bool "Using touch"
default y
if RT_USING_TOUCH
choice
prompt "Choice touch controller"
default RT_USING_GT9XX
config RT_USING_GT9XX
bool "Using GT9XX controller"
config RT_USING_FT6x06
bool "Using FT6x06 controller"
endchoice
config RT_TOUCH_THREAD_PRIORITY
int "Set touch thread priority"
range 2 32
default 10
endif
endif
endif
if RT_USING_I2C
config RT_USING_I2C0
bool "Using iic0 bus"
default y
config RT_USING_I2C1
bool "Using iic1 bus"
default n
config RT_USING_I2C2
bool "Using iic2 bus"
default n
endif
config RT_USING_AUDIO
bool "Using audio"
default n
if RT_USING_AUDIO
config RT_USING_ICODEC
bool "Using icodec"
default n
endif
config RT_USING_CPU_FFS
bool "Using CPU FFS"
default y

View File

@@ -0,0 +1,28 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.S')
CPPPATH = [cwd, str(Dir('#'))]
if not GetDepend('RT_USING_I2C'):
SrcRemove(src, ['drv_i2c.c'])
if not GetDepend('RT_USING_SPI'):
SrcRemove(src, ['drv_spi.c'])
if not GetDepend('RT_USING_WDT'):
SrcRemove(src, ['drv_reset.c'])
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
# build for sub-directory
list = os.listdir(cwd)
objs = []
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'))
group = group + objs
Return('group')

View File

@@ -0,0 +1,11 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.S')
CPPPATH = [cwd]
group = DefineGroup('drv_audio', src, depend = ['RT_USING_AUDIO'], CPPPATH = CPPPATH)
Return('group')

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
/*
* drv_aic_i2s.h
*
* Created on: 2016年4月1日
* Author: Urey
*/
#ifndef DRIVER_DRV_AIC_I2S_H_
#define DRIVER_DRV_AIC_I2S_H_
#include "board.h"
#ifdef RT_USING_ICODEC
# define CODEC_AS_MASTER
#define CODEC_DEF_RATE (24000000)
#else
//# undef CODEC_AS_MASTER
//# define CODEC_AS_MASTER
#define CODEC_DEF_RATE (44100)
#endif
#ifdef RT_USING_ECODEC_WM8978
# define CFG_AIC_I2S_EXT_CODEC
#endif
#define CFG_AIC_SOC_CLKOUT
//#define CFG_AIC_SOC_CLKIN
#define CFG_I2S_DMA_PAGE_SIZE (32 * 1024)
#define CFG_I2S_DMA_PAGE_NUM 8
enum
{
I2S_TRIGGER_STOP = 0,
I2S_TRIGGER_START ,
I2S_TRIGGER_PAUSE_PUSH ,
I2S_TRIGGER_PAUSE_RELEASE ,
I2S_TRIGGER_SUSPEND ,
I2S_TRIGGER_RESUME,
};
/*********************************************************************************************************
** 数据结构
*********************************************************************************************************/
struct jz_i2s
{
struct jz_aic *aic;
int i2s_init;
#define I2S_WRITE 0x1
#define I2S_READ 0x2
#define I2S_INCODEC (0x1 <<4)
#define I2S_EXCODEC (0x2 <<4)
#define I2S_SLAVE (0x1 << 8)
#define I2S_MASTER (0x2 << 8)
int i2s_mode;
uint32_t tx_dr_base;
int channels;
int fmt_width;
int rates;
/* used for DMA transform */
struct rt_dma_channel *tx_dmac;
struct rt_dma_channel *rx_dmac;
};
/*********************************************************************************************************
** 函数申明
*********************************************************************************************************/
int aic_set_rate(struct jz_aic *aic, uint32_t freq);
struct jz_i2s *rt_hw_aic_i2s_init(void);
//void aic_i2s_start_substream(struct jz_i2s *i2s,int stream);
//void aic_i2s_stop_substream(struct jz_i2s *i2s,int stream);
int aic_i2s_set_sysclk(struct jz_i2s *i2s,uint32_t freq);
int aic_i2s_set_clkdiv(struct jz_i2s *i2s,int div_id, int div);
int aic_i2s_startup(struct jz_i2s *i2s,int stream);
int aic_i2s_trigger(struct jz_i2s* i2s,int cmd,int stream);
int aic_i2s_hw_params(struct jz_i2s* i2s,int stream);
void aic_i2s_shutdown(struct jz_i2s *i2s,int stream);
rt_size_t aic_i2s_send(struct jz_i2s *i2s, const void* buffer, rt_size_t size,void (*tx_callback)(void *,void *), void *tx_arg);
rt_size_t aic_i2s_recv(struct jz_i2s *i2s, void* buffer, rt_size_t size,void (*rx_callback)(void *,void *), void *rx_arg);
void aic_i2s_set_rate(struct jz_i2s *i2s,int rate);
#endif /* DRIVER_DRV_AIC_I2S_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,406 @@
/*
* drv_codec_icodec.h
*
* Created on: 2017Äê1ÔÂ10ÈÕ
* Author: Urey
*/
#ifndef _DRV_CODEC_ICODEC_H_
#define _DRV_CODEC_ICODEC_H_
#include <stdint.h>
#include "x1000.h"
#include "drv_clock.h"
struct jz_icodec
{
struct jz_i2s *i2s;
struct rt_audio_configure replay_config;
#ifdef AUDIO_DEVICE_USE_PRIVATE_BUFFER
struct rt_mempool mp;
#endif /* AUDIO_DEVICE_USE_PRIVATE_BUFFER */
uint32_t mapped_base;
/* replay */
int user_replay_volume;
int dac_user_mute; /*dac user mute state*/
int aohp_in_pwsq; /*aohp in power up/down seq*/
int hpl_wished_gain; /*keep original hpl/r gain register value*/
int hpr_wished_gain;
int linl_wished_gain; /*keep original hpl/r gain register value*/
int linr_wished_gain;
};
#define ICODEC_PCM_FORMAT AUDIO_FMT_PCM_S16_LE
#define ICODEC_SAMPLING_RATE 44100
/* icodec internal register space */
enum {
SCODA_REG_SR = 0x0,
SCODA_REG_SR2,
SCODA_REG_SIGR,
SCODA_REG_SIGR2,
SCODA_REG_SIGR3,
SCODA_REG_SIGR5,
SCODA_REG_SIGR7,
SCODA_REG_MR,
SCODA_REG_AICR_DAC,
SCODA_REG_AICR_ADC,
SCODA_REG_CR_DMIC,
SCODA_REG_CR_MIC1,
SCODA_REG_CR_MIC2,
SCODA_REG_CR_DAC,
SCODA_REG_CR_DAC2,
SCODA_REG_CR_ADC,
SCODA_REG_CR_MIX,
SCODA_REG_DR_MIX,
SCODA_REG_CR_VIC,
SCODA_REG_CR_CK,
SCODA_REG_FCR_DAC,
SCODA_REG_SFCCR_DAC,
SCODA_REG_SFFCR_DAC,
SCODA_REG_FCR_ADC,
SCODA_REG_CR_TIMER_MSB,
SCODA_REG_CR_TIMER_LSB,
SCODA_REG_ICR,
SCODA_REG_IMR,
SCODA_REG_IFR,
SCODA_REG_IMR2,
SCODA_REG_IFR2,
SCODA_REG_GCR_DACL,
SCODA_REG_GCR_DACR,
SCODA_REG_GCR_DACL2,
SCODA_REG_GCR_DACR2,
SCODA_REG_GCR_MIC1,
SCODA_REG_GCR_MIC2,
SCODA_REG_GCR_ADCL,
SCODA_REG_GCR_ADCR,
SCODA_REG_GCR_MIXDACL,
SCODA_REG_GCR_MIXDACR,
SCODA_REG_GCR_MIXADCL,
SCODA_REG_GCR_MIXADCR,
SCODA_REG_CR_DAC_AGC,
SCODA_REG_DR_DAC_AGC,
SCODA_REG_CR_DAC2_AGC,
SCODA_REG_DR_DAC2_AGC,
SCODA_REG_CR_ADC_AGC,
SCODA_REG_DR_ADC_AGC,
SCODA_REG_SR_ADC_AGCDGL,
SCODA_REG_SR_ADC_AGCDGR,
SCODA_REG_SR_ADC_AGCAGL,
SCODA_REG_SR_ADC_AGCAGR,
SCODA_REG_CR_TR,
SCODA_REG_DR_TR,
SCODA_REG_SR_TR1,
SCODA_REG_SR_TR2,
SCODA_REG_SR_TR_SRCDAC,
/* icodec internal register extend space */
SCODA_MIX_0,
SCODA_MIX_1,
SCODA_MIX_2,
SCODA_MIX_3,
SCODA_MIX_4,
SCODA_DAC_AGC0,
SCODA_DAC_AGC1,
SCODA_DAC_AGC2,
SCODA_DAC_AGC3,
SCODA_DAC2_AGC0,
SCODA_DAC2_AGC1,
SCODA_DAC2_AGC2,
SCODA_DAC2_AGC3,
SCODA_ADC_AGC0,
SCODA_ADC_AGC1,
SCODA_ADC_AGC2,
SCODA_ADC_AGC3,
SCODA_ADC_AGC4,
SCODA_MAX_REG_NUM,
};
/*aicr dac*/
#define SCODA_AICR_DAC_ADWL_SHIFT (6)
#define SCODA_AICR_DAC_ADWL_MASK (0x3 << SCODA_AICR_DAC_ADWL_SHIFT)
#define SCODA_AICR_DAC_SLAVE_SHIFT (5)
#define SCODA_AICR_DAC_SLAVE_MASK (0x1 << SCODA_AICR_DAC_SLAVE_SHIFT)
#define SCODA_AICR_DAC_SLAVE (1 << 5)
#define SCODA_AICR_DAC_SB_SHIFT (4)
#define SCODA_AICR_DAC_SB_MASK (0x1 << SCODA_AICR_DAC_SB_SHIFT)
#define SCODA_AICR_DAC_AUDIOIF_SHIFT (0)
#define SCODA_AICR_DAC_AUDIO_MASK (0x3 << SCODA_AICR_DAC_AUDIOIF_SHIFT)
#define SCODA_AICR_DAC_AUDIOIF_I2S (0x3)
/* aicr adc */
#define SCODA_AICR_ADC_ADWL_SHIFT (6)
#define SCODA_AICR_ADC_ADWL_MASK (0x3 << SCODA_AICR_ADC_ADWL_SHIFT)
#define SCODA_AICR_ADC_SB_SHIFT (4)
#define SCODA_AICR_ADC_SB_MASK (0x1 << SCODA_AICR_ADC_SB_SHIFT)
#define SCODA_AICR_ADC_AUDIOIF_SHIFT (0)
#define SCODA_AICR_ADC_AUDIO_MASK (0x3 << SCODA_AICR_ADC_AUDIOIF_SHIFT)
#define SCODA_AICR_ADC_AUDIOIF_I2S (0x3)
/* cr vic */
#define SCODA_CR_VIC_SB_SHIFT (0)
#define SCODA_CR_VIC_SB_MASK (1 << SCODA_CR_VIC_SB_SHIFT)
#define SCODA_CR_VIC_SB_SLEEP_SHIFT (1)
#define SCODA_CR_VIC_SB_SLEEP_MASK (1 << SCODA_CR_VIC_SB_SLEEP_SHIFT)
/* fcr adc/dac */
#define SCODA_FCR_FREQ_SHIFT (0)
#define SCODA_FCR_FREQ_MASK (0xf << SCODA_FCR_FREQ_SHIFT)
/* cr dac */
#define SCODA_CR_DAC_SMUTE_SHIFT (7)
#define SCODA_CR_DAC_SMUTE_MASK (0x1 << SCODA_CR_DAC_SMUTE_SHIFT)
#define SCODA_CR_DAC_SB_SHIFT (4)
#define SCODA_CR_DAC_SB_MASK (0x1 << SCODA_CR_DAC_SB_SHIFT)
#define SCODA_CR_DAC_ZERO_SHIFT (0)
#define SCODA_CR_DAC_ZERO_MASK (0x1 << SCODA_CR_DAC_ZERO_SHIFT)
/* cr dac */
#define SCODA_CR_ADC_SMUTE_SHIFT (7)
#define SCODA_CR_ADC_SMUTE_MASK (0x1 << SCODA_CR_ADC_SMUTE_SHIFT)
#define SCODA_CR_ADC_MIC_SEL_SHIFT (6)
#define SCODA_CR_ADC_MIC_SEL_MASK (0x1 << SCODA_CR_ADC_MIC_SEL_SHIFT)
#define SCODA_CR_ADC_SB_SHIFT (4)
#define SCODA_CR_ADC_SB_MASK (0x1 << SCODA_CR_ADC_SB_SHIFT)
#define SCODA_CR_ADC_ZERO_SHIFT (0)
#define SCODA_CR_ADC_ZERO_MASK (0x1 << SCODA_CR_ADC_ZERO_SHIFT)
/* ifr */
#define SCODA_IFR_DAC_MUTE_SHIFT (0)
#define SCODA_IFR_DAC_MUTE_MASK (0x1 << SCODA_IFR_DAC_MUTE_SHIFT)
#define SCODA_IFR_ADC_MUTE_SHIFT (2)
#define SCODA_IFR_ADC_MUTE_MASK (0x1 << SCODA_IFR_ADC_MUTE_SHIFT)
#define SCODA_IFR_ADAS_LOCK_SHIFT (7)
#define SCODA_IFR_ADAS_LOCK_MASK (0x1 << SCODA_IFR_ADAS_LOCK_SHIFT)
/* cr ck */
#define SCODA_CR_CK_MCLK_DIV_SHIFT (6)
#define SCODA_CR_CK_MCLK_DIV_MASK (0x1 << SCODA_CR_CK_MCLK_DIV_SHIFT)
#define SCODA_CR_CK_SDCLK_SHIFT (4)
#define SCODA_CR_CK_SDCLK_MASK (0x1 << SCODA_CR_CK_SDCLK_SHIFT)
#define SCODA_CR_CRYSTAL_SHIFT (0)
#define SCODA_CR_CRYSTAL_MASK (0xf << SCODA_CR_CRYSTAL_SHIFT)
/* icr */
#define SCODA_ICR_INT_FORM_SHIFT (6)
#define SCODA_ICR_INT_FORM_MASK (0x3 << SCODA_ICR_INT_FORM_SHIFT)
#define SCODA_ICR_INT_FORM_HIGH (0)
#define SCODA_ICR_INT_FORM_LOW (1)
/* imr */
#define SCODA_IMR_COMMON_MASK (0xff)
#define SCODA_IMR2_COMMON_MASK (0xff)
/*For Codec*/
#define RGADW (0x4)
#define RGDATA (0x8)
static inline void icodec_mapped_reg_set(uint32_t xreg, int xmask, int xval)
{
int val = readl(xreg);
val &= ~(xmask);
val |= xval;
writel(val, xreg);
}
static inline int icodec_mapped_test_bits(uint32_t xreg, int xmask, int xval)
{
int val = readl(xreg);
val &= xmask;
return (val == xval);
}
/*
* RGADW
*/
#define SCODA_RGDIN_BIT (0)
#define SCODA_RGDIN_MASK (0xff << SCODA_RGDIN_BIT)
#define SCODA_RGADDR_BIT (8)
#define SCODA_RGADDR_MASK (0x7f << SCODA_RGADDR_BIT)
#define SCODA_RGWR_BIT (16)
#define SCODA_RGWR_MASK (0x1 << SCODA_RGWR_BIT)
#define icodec_test_rw_inval(icodec) \
icodec_mapped_test_bits((icodec->mapped_base + RGADW), SCODA_RGWR_MASK, (1 << SCODA_RGWR_BIT))
/*
* RGDATA
*/
#define SCODA_RGDOUT_BIT (0)
#define SCODA_RGDOUT_MASK (0xff << SCODA_RGDOUT_BIT)
#define SCODA_IRQ_BIT (8)
#define SCODA_IRQ_MASK (0x1 << SCODA_IRQ_BIT)
#define icodec_test_irq(icodec) \
icodec_mapped_test_bits((icodec->mapped_base + RGDATA), SCODA_IRQ_MASK, (1 << SCODA_IRQ_BIT))
static inline uint8_t icodec_hw_read_normal(struct jz_icodec *icodec, int reg)
{
uint32_t mapped_base = icodec->mapped_base;
int reval;
int timeout = 0xfffff;
uint32_t flags;
while (icodec_test_rw_inval(icodec))
{
timeout--;
if (!timeout)
{
// rt_kprintf("icodec test_rw_inval timeout\n");
break;
}
}
icodec_mapped_reg_set((mapped_base + RGADW), SCODA_RGWR_MASK,(0 << SCODA_RGWR_BIT));
icodec_mapped_reg_set((mapped_base + RGADW), SCODA_RGADDR_MASK,(reg << SCODA_RGADDR_BIT));
reval = readl((mapped_base + RGDATA));
reval = readl((mapped_base + RGDATA));
reval = readl((mapped_base + RGDATA));
reval = readl((mapped_base + RGDATA));
reval = readl((mapped_base + RGDATA));
reval = ((reval & SCODA_RGDOUT_MASK) >> SCODA_RGDOUT_BIT);
// rt_kprintf("reg %x = %x\n", reg, reval);
return (uint8_t) reval;
}
static inline int icodec_hw_write_normal(struct jz_icodec *icodec, int reg, int data)
{
uint32_t mapped_base = icodec->mapped_base;
int ret = 0;
int timeout = 0xfffff;
uint32_t flags;
while (icodec_test_rw_inval(icodec))
{
timeout--;
if (!timeout)
{
// rt_kprintf("icodec test_rw_inval timeout\n");
break;
}
}
icodec_mapped_reg_set((mapped_base + RGADW), SCODA_RGDIN_MASK | SCODA_RGADDR_MASK,
(data << SCODA_RGDIN_BIT) | (reg << SCODA_RGADDR_BIT));
icodec_mapped_reg_set((mapped_base + RGADW), SCODA_RGWR_MASK ,
1 << SCODA_RGWR_BIT);
if (reg != SCODA_REG_IFR && reg != SCODA_REG_IFR2)
{
ret = icodec_hw_read_normal(icodec, reg);
if (data != ret)
{
// rt_kprintf("icdc write reg %x err exp %x now is %x\n", reg, data, ret);
ret = -1;
}
}
return ret;
}
static int icodec_hw_write_extend(struct jz_icodec *icodec, uint8_t sreg, uint8_t sdata)
{
int creg, cdata, dreg;
switch (sreg) {
case SCODA_MIX_0 ... SCODA_MIX_4:
creg = SCODA_REG_CR_MIX;
dreg = SCODA_REG_DR_MIX;
sreg -= (SCODA_REG_SR_TR_SRCDAC + 1);
break;
case SCODA_DAC_AGC0 ... SCODA_DAC_AGC3:
creg = SCODA_REG_CR_DAC_AGC;
dreg = SCODA_REG_DR_DAC_AGC;
sreg -= (SCODA_MIX_4 +1);
break;
case SCODA_DAC2_AGC0 ... SCODA_DAC2_AGC3:
creg = SCODA_REG_CR_DAC2;
dreg = SCODA_REG_DR_DAC2_AGC;
sreg -= (SCODA_DAC_AGC3 + 1);
break;
case SCODA_ADC_AGC0 ... SCODA_ADC_AGC4:
creg = SCODA_REG_CR_ADC_AGC;
dreg = SCODA_REG_DR_ADC_AGC;
sreg -= (SCODA_ADC_AGC4 + 1);
break;
default:
return 0;
}
// rt_kprintf("write extend : sreg: %d [0 - 4], creg: %x sdata: %d\n", sreg, creg, sdata);
cdata = (icodec_hw_read_normal(icodec,creg)&(~0x3f))|((sreg&0x3f)|0x40);
icodec_hw_write_normal(icodec, creg, cdata);
icodec_hw_write_normal(icodec, dreg, sdata);
if(sdata!=icodec_hw_read_normal(icodec,dreg))
return -1;
return 0;
}
static uint8_t icodec_hw_read_extend(struct jz_icodec *icodec, uint8_t sreg)
{
int creg, cdata, dreg, ddata;
switch (sreg)
{
case SCODA_MIX_0 ... SCODA_MIX_4:
creg = SCODA_REG_CR_MIX;
dreg = SCODA_REG_DR_MIX;
sreg -= (SCODA_REG_SR_TR_SRCDAC + 1);
break;
case SCODA_DAC_AGC0 ... SCODA_DAC_AGC3:
creg = SCODA_REG_CR_DAC_AGC;
dreg = SCODA_REG_DR_DAC_AGC;
sreg -= (SCODA_MIX_4 +1);
break;
case SCODA_DAC2_AGC0 ... SCODA_DAC2_AGC3:
creg = SCODA_REG_CR_DAC2;
dreg = SCODA_REG_DR_DAC2_AGC;
sreg -= (SCODA_DAC_AGC3 + 1);
break;
case SCODA_ADC_AGC0 ... SCODA_ADC_AGC4:
creg = SCODA_REG_CR_ADC_AGC;
dreg = SCODA_REG_DR_ADC_AGC;
sreg -= (SCODA_ADC_AGC4 + 1);
break;
default:
return 0;
}
cdata = (icodec_hw_read_normal(icodec, creg) & (~0x7f)) | (sreg & 0x3f);
icodec_hw_write_normal(icodec, creg, cdata);
ddata = icodec_hw_read_normal(icodec, dreg);
return (uint8_t) ddata;
}
static inline uint8_t icodec_hw_read(struct jz_icodec *icodec, int reg)
{
if (reg > SCODA_REG_SR_TR_SRCDAC)
return icodec_hw_read_extend(icodec, reg);
else
return icodec_hw_read_normal(icodec, reg);
}
static inline int icodec_hw_write(struct jz_icodec *icodec, int reg, int data)
{
if (reg > SCODA_REG_SR_TR_SRCDAC)
return icodec_hw_write_extend(icodec, reg, data);
else
return icodec_hw_write_normal(icodec, reg, data);
}
#endif /* _DRV_CODEC_ICODEC_H_ */

View File

@@ -0,0 +1,428 @@
/*
* File : drv_dmic.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2015-11-19 Urey the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <drivers/audio.h>
#ifdef RT_USING_FINSH
# include <finsh.h>
#endif
#include "board.h"
#include "drv_gpio.h"
#include "drv_dma.h"
#include "drv_aic.h"
#include "drv_clock.h"
#include "drv_dmic.h"
#include "dma.h"
#include "audio_pipe.h"
#define DMIC_DEBUG 0
#if DMIC_DEBUG
# define DMIC_DBG(...) rt_kprintf("[DMIC]"),rt_kprintf(__VA_ARGS__)
#else
# define DMIC_DBG(...)
#endif
#define DMIC_DMA_RX_CHAN 4
#define DMIC_FIFO_DEPTH 64
#define JZ_DMIC_FORMATS 16
#define JZ_DMIC_RATE (8000)
ALIGN(32) rt_uint32_t _g_dmic_dma_buffer[DMIC_DMA_PAGE_NUM*DMIC_DMA_PAGE_SIZE/sizeof(rt_uint32_t)];
static struct jz_dmic _g_jz_dmic=
{
.io_base = DMIC_BASE,
.dma_buf = (rt_uint8_t *)_g_dmic_dma_buffer,
.dma_offset = 0,
};
static void dump_dmic_registers(void)
{
struct jz_dmic *jz_dmic = &_g_jz_dmic;
rt_kprintf("DMICCR0 %p : 0x%08x\n", (jz_dmic->io_base+DMICCR0),dmic_read_reg(jz_dmic, DMICCR0));
rt_kprintf("DMICGCR %p : 0x%08x\n", (jz_dmic->io_base+DMICGCR),dmic_read_reg(jz_dmic, DMICGCR));
rt_kprintf("DMICIMR %p : 0x%08x\n", (jz_dmic->io_base+DMICIMR),dmic_read_reg(jz_dmic, DMICIMR));
rt_kprintf("DMICINTCR %p : 0x%08x\n", (jz_dmic->io_base+DMICINTCR),dmic_read_reg(jz_dmic, DMICINTCR));
rt_kprintf("DMICTRICR %p : 0x%08x\n", (jz_dmic->io_base+DMICTRICR),dmic_read_reg(jz_dmic, DMICTRICR));
rt_kprintf("DMICTHRH %p : 0x%08x\n", (jz_dmic->io_base+DMICTHRH),dmic_read_reg(jz_dmic, DMICTHRH));
rt_kprintf("DMICTHRL %p : 0x%08x\n", (jz_dmic->io_base+DMICTHRL),dmic_read_reg(jz_dmic, DMICTHRL));
rt_kprintf("DMICTRIMMAX %p : 0x%08x\n", (jz_dmic->io_base+DMICTRIMMAX),dmic_read_reg(jz_dmic, DMICTRIMMAX));
rt_kprintf("DMICTRINMAX %p : 0x%08x\n", (jz_dmic->io_base+DMICTRINMAX),dmic_read_reg(jz_dmic, DMICTRINMAX));
rt_kprintf("DMICDR %p : 0x%08x\n", (jz_dmic->io_base+DMICDR),dmic_read_reg(jz_dmic, DMICDR));
rt_kprintf("DMICFTHR %p : 0x%08x\n", (jz_dmic->io_base+DMICFTHR),dmic_read_reg(jz_dmic, DMICFTHR));
rt_kprintf("DMICFSR %p : 0x%08x\n", (jz_dmic->io_base+DMICFSR),dmic_read_reg(jz_dmic, DMICFSR));
rt_kprintf("DMICCGDIS %p : 0x%08x\n", (jz_dmic->io_base+DMICCGDIS),dmic_read_reg(jz_dmic, DMICCGDIS));
return;
}
MSH_CMD_EXPORT(dump_dmic_registers,"dump dmic regs...\n");
int jz_dmic_set_rate(struct jz_dmic* dmic, int rate)
{
// rt_kprintf("rate = %d\n",rate);
switch (rate)
{
case 8000:
__dmic_set_sr_8k(dmic);
break;
case 16000:
__dmic_set_sr_16k(dmic);
break;
case 48000:
__dmic_set_sr_48k(dmic);
break;
default:
DMIC_DBG("dmic unsupport rate %d\n", rate);
}
return 0;
}
int jz_dmic_set_channels(struct jz_dmic* dmic, int channels)
{
if (channels > 4)
channels = 4;
if (channels <= 1)
channels = 1;
__dmic_set_chnum(dmic,channels - 1);
}
int jz_dmic_set_record_volume(struct jz_dmic* dmic, int vol)
{
if(vol >= 32)
vol = 31;
__dmic_set_gcr(dmic,vol);
dmic->record_gain = vol;
}
static void jz_dmic_dma_complete(struct rt_dma_channel *dmac, struct dma_message *msg)
{
rt_base_t level;
if(msg->complete_cb)
msg->complete_cb(msg->complete_arg,msg->dst_addr);
/* restart DMA Job */
rt_dma_trans_message(dmac,msg);
}
void jz_dmic_start_recv(struct jz_dmic* dmic,void (*rx_callback)(void *,void *), void *rx_arg)
{
rt_base_t level;
rt_uint32_t i;
struct dma_message message;
__dmic_enable_rdms(dmic);
__dmic_enable(dmic);
level = rt_hw_interrupt_disable();
dmic->dma_offset = 0;
dmic->dma_buf = (rt_uint8_t *)_g_dmic_dma_buffer;
for (i = 0; i < DMIC_DMA_PAGE_NUM; ++i)
{
message.src_addr = (uint8_t *) (DMIC_BASE + DMICDR);
message.src_option = RT_DMA_ADDR_FIX;
message.dst_addr = (uint8_t *) (dmic->dma_buf + DMIC_DMA_PAGE_SIZE * i);
message.dst_option = RT_DMA_ADDR_INC;
message.t_size = DMIC_DMA_PAGE_SIZE;
message.t_mode = JZDMA_REQ_DMIC_RX;
/* init callback */
message.complete_cb = rx_callback;
message.complete_arg = rx_arg;
rt_dma_trans_message(dmic->rx_dmac,&message);
}
rt_hw_interrupt_enable(level);
return ;
}
void jz_dmic_stop_recv(struct jz_dmic* dmic)
{
if (__dmic_is_enable_rdms(dmic))
{
__dmic_disable_rdms(dmic);
}
__dmic_disable(dmic);
}
void dmic_rx_complete(void *data,void *pbuf)
{
struct jz_dmic *dmic = (struct jz_dmic *)data;
rt_device_write(RT_DEVICE(&dmic->pipe),0,pbuf,DMIC_DMA_PAGE_SIZE);
}
#define CFG_DMIC_PIPE_SIZE (2 * 1024)
struct jz_dmic* rt_hw_dmic_init(void)
{
struct jz_dmic *dmic = &_g_jz_dmic;
//init pipe for record
{
rt_uint8_t *buf = rt_malloc(CFG_DMIC_PIPE_SIZE);
if(buf == RT_NULL)
{
rt_kprintf("request pipe memory error\n");
return RT_NULL;
}
rt_audio_pipe_init(&dmic->pipe,"recdmic",RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD,buf,(CFG_DMIC_PIPE_SIZE));
rt_device_open(RT_DEVICE(&dmic->pipe),RT_DEVICE_OFLAG_RDONLY);
}
/* GPIO config
* PB05 -> FUNC1 DMIC1_IN
* PB21 -> FUNC0 DMIC_CLK
* PB22 -> FUNC0 DMIC0_IN
* */
gpio_set_func(GPIO_PORT_B,GPIO_Pin_5,GPIO_FUNC_1);
gpio_set_func(GPIO_PORT_B,GPIO_Pin_21,GPIO_FUNC_0);
gpio_set_func(GPIO_PORT_B,GPIO_Pin_22,GPIO_FUNC_0);
/* enable clock */
dmic->clk_gate = clk_get("dmic");
if (dmic->clk_gate == RT_NULL)
{
DMIC_DBG("Failed to get dmic gate clock \n");
return RT_NULL;
}
clk_enable(dmic->clk_gate);
/*gain: 0, ..., e*/
__dmic_reset(dmic);
while (__dmic_get_reset(dmic)) ;
jz_dmic_set_rate(dmic, 8000);
__dmic_set_chnum(dmic,0); //mono
__dmic_enable_hpf1(dmic);
__dmic_set_gcr(dmic, 27);
__dmic_mask_all_int(dmic);
__dmic_enable_pack(dmic);
__dmic_enable_sw_lr(dmic);
__dmic_enable_lp(dmic);
__dmic_disable_lp(dmic);
__dmic_set_request(dmic, 48);
__dmic_enable_hpf2(dmic);
__dmic_set_thr_high(dmic, 32);
__dmic_set_thr_low(dmic, 16);
__dmic_enable_tri(dmic);
//config DMA
{
int trigger;
/* DMA config */
struct dma_config config;
dmic->rx_dmac = rt_dma_get_channel(DMIC_DMA_RX_CHAN);
if (dmic->rx_dmac != RT_NULL)
{
DMIC_DBG("config dmic dma rx channel...\n");
config.direction = RT_DMA_DEV_TO_MEM;
config.src_addr_width = RT_DMA_BUSWIDTH_2_BYTES;
config.src_maxburst = (DMIC_FIFO_DEPTH * RT_DMA_BUSWIDTH_2_BYTES) / 2;
config.dst_addr_width = RT_DMA_BUSWIDTH_2_BYTES;
config.dst_maxburst = (64 * 1024);
rt_dma_configture(dmic->rx_dmac, &config);
dmic->rx_dmac->start = RT_NULL;
dmic->rx_dmac->complete = jz_dmic_dma_complete;
}
trigger = config.src_maxburst / config.src_addr_width;
__dmic_set_request(dmic, trigger);
}
jz_dmic_start_recv(dmic,dmic_rx_complete,dmic);
return dmic;
_error_exit:
__dmic_disable(dmic);
rt_audio_pipe_detach(&dmic->pipe);
clk_disable(dmic->clk_gate);
return RT_NULL;
}
//INIT_ENV_EXPORT(rt_hw_dmic_init);
struct speech_wav_header
{
char riff_id[4]; //"RIFF"
uint32_t size0; //file len - 8
char wave_fmt[8]; //"WAVEfmt "
uint32_t size1; //0x10
uint16_t fmttag; //0x01
uint16_t channel; //1
uint32_t samplespersec; //8000
uint32_t bytepersec; //8000 * 2
uint16_t blockalign; //1 * 16 / 8
uint16_t bitpersamples; //16
char data_id[4]; //"data"
uint32_t size2; //file len - 44
};
static void speech_wav_init_header(struct speech_wav_header *header,rt_uint16_t Channels,int SamplesPerSec,int BitsPerSample)
{
strcpy(header->riff_id, "RIFF");
header->size0 = 0; // Final file size not known yet, write 0
strcpy(header->wave_fmt, "WAVEfmt ");
header->size1 = 16; // Sub-chunk size, 16 for PCM
header->fmttag = 1; // AudioFormat, 1 for PCM
header->channel = Channels; // Number of channels, 1 for mono, 2 for stereo
header->samplespersec = SamplesPerSec; // Sample rate
header->bytepersec = SamplesPerSec * BitsPerSample * Channels / 8; //Byte rate
header->blockalign = Channels * BitsPerSample / 8; // Block align, NumberOfChannels*BitsPerSample/8
header->bitpersamples = BitsPerSample;
strcpy(header->data_id, "data");
header->size2 = 0;
}
static void speech_wav_upgrade_size(struct speech_wav_header *header,rt_uint32_t paylodSize)
{
header->size0 = paylodSize + 36;
header->size2 = paylodSize;
}
#include <finsh.h>
#include <dfs_posix.h>
rt_uint8_t rec_buff[2048];
int dmic_record(int samplingrates)
{
struct jz_dmic *dmic = &_g_jz_dmic;
rt_device_t dmic_pipe;
struct speech_wav_header wav_header;
rt_uint32_t wav_len = 0;
char *file_name;
int fd;
int i = 0;
int rdlen, wrlen;
rt_kprintf("samplingrates = %d\n",samplingrates);
if((samplingrates != 8000) && (samplingrates != 16000))
{
rt_kprintf("un-support this samplingrates\n");
return -RT_EIO;
}
dmic_pipe = rt_device_find("recdmic");
if(dmic_pipe == RT_NULL)
{
rt_kprintf("can't find the record device\n");
return -RT_ERROR ;
}
rt_kprintf("pls hold WAKE key to start record...\n");
while(gpio_get_value(GPIO_PORT_B, GPIO_Pin_31) == 1)
rt_thread_delay(100);
rt_kprintf("OK,start record....\n");
if(samplingrates == 8000)
file_name = "/appfs/dmic8k.wav";
else
file_name = "/appfs/dmic16k.wav";
fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0);
if (fd < 0)
{
rt_kprintf("open file for write failed\n");
return -RT_EIO;
}
speech_wav_init_header(&wav_header,1,samplingrates,16);
write(fd, &wav_header, wav_len);
jz_dmic_set_rate(dmic,samplingrates);
wav_len = 0;
while(i++ < 1000)
{
rdlen = rt_device_read(dmic_pipe,0,rec_buff,sizeof(rec_buff));
wrlen = write(fd, rec_buff, rdlen);
if (wrlen != rdlen)
{
rt_kprintf("write data failed\n");
close(fd);
return -RT_EIO;
}
wav_len += wrlen;
if(gpio_get_value(GPIO_PORT_B, GPIO_Pin_31) == 1)
break;
}
rt_kprintf("record complete...\n");
//upgrage wav header
lseek(fd,0,SEEK_SET);
speech_wav_upgrade_size(&wav_header,wav_len);
write(fd, &wav_header, sizeof(struct speech_wav_header));
close(fd);
rt_kprintf("WAV file saved ok!\n");
}
FINSH_FUNCTION_EXPORT(dmic_record,dmic record test);
#if 0
int dmic_test(void)
{
rt_device_t device;
int i = 0;
device = rt_device_find("recdmic");
if(device == RT_NULL)
{
rt_kprintf("can't find the record device\n");
return -RT_ERROR ;
}
audio_device_set_rate(8000);
while(i++ < 1000)
{
int len;
uint8_t *sendBuf;
sendBuf = audio_device_get_buffer(&len);
len = rt_device_read(device,0,sendBuf,len);
audio_device_write(sendBuf,len);
}
rt_kprintf("dmic test complete...\n");
return 0;
}
MSH_CMD_EXPORT(dmic_test,dmic test ....);
#endif

View File

@@ -0,0 +1,262 @@
/*
* drv_dmic.h
*
* Created on: 2017Äê1ÔÂ11ÈÕ
* Author: Urey
*/
#ifndef _DRV_DMIC_H_
#define _DRV_DMIC_H_
/*
* File : drv_dmic.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2015-11-19 Urey the first version
*/
#include <dma.h>
#include "audio_pipe.h"
#define DMIC_DMA_PAGE_SIZE 512
#define DMIC_DMA_PAGE_NUM RT_DMA_MAX_NODES
struct jz_dmic
{
struct rt_audio_pipe pipe;
struct rt_audio_configure record_config;
uint32_t io_base;
struct clk *clk_gate;
struct rt_dma_channel *rx_dmac;
rt_uint8_t *dma_buf;
rt_uint32_t dma_offset;
/* record */
int record_gain;
};
static inline void dmic_write_reg(struct jz_dmic *dmic, uint32_t reg, uint32_t val)
{
writel(val, dmic->io_base + reg);
}
static inline uint32_t dmic_read_reg(struct jz_dmic *jz_dmic, unsigned int reg)
{
return readl(jz_dmic->io_base + reg);
}
#define dmic_set_reg(dmic, addr, val, mask, offset)\
do { \
int tmp_val = val; \
int read_val = dmic_read_reg(dmic, addr); \
read_val &= (~mask); \
tmp_val = ((tmp_val << offset) & mask); \
tmp_val |= read_val; \
dmic_write_reg(dmic, addr, tmp_val); \
}while(0)
#define dmic_get_reg(dmic, addr, mask, offset) \
((dmic_read_reg(dmic, addr) & mask) >> offset)
/*********************************************************************************************************
**
*********************************************************************************************************/
#define DMICCR0 0x00
#define DMICGCR 0x04
#define DMICIMR 0x08
#define DMICINTCR 0x0c
#define DMICTRICR 0x10
#define DMICTHRH 0x14
#define DMICTHRL 0x18
#define DMICTRIMMAX 0x1c
#define DMICTRINMAX 0x20
#define DMICDR 0x30
#define DMICFTHR 0x34
#define DMICFSR 0x38
#define DMICCGDIS 0x50
/* DMICCR0 */
#define DMIC_RESET 31
#define DMIC_RESET_MASK (0x1 << DMIC_RESET)
#define DMIC_RESET_TRI 30
#define DMIC_RESET_TRI_MASK (0x1 << DMIC_RESET_TRI)
#define DMIC_CHNUM 16
#define DMIC_CHNUM_MASK (0x7 << DMIC_CHNUM)
#define DMIC_UNPACK_MSB 13
#define DMIC_UNPACK_MSB_MASK (0x1 << DMIC_UNPACK_MSB)
#define DMIC_UNPACK_DIS 12
#define DMIC_UNPACK_DIS_MASK (0x1 << DMIC_UNPACK_DIS)
#define DMIC_SW_LR 11
#define DMIC_SW_LR_MASK (0x1 << DMIC_SW_LR)
#define DMIC_SPLIT_DI 10
#define DMIC_SPLIT_DI_MASK (0x1 << DMIC_SPLIT_DI)
#define DMIC_PACK_EN 8
#define DMIC_PACK_EN_MASK (0x1 << DMIC_PACK_EN)
#define DMIC_SR 6
#define DMIC_SR_MASK (0x3 << DMIC_SR)
#define DMIC_LP_MODE 3
#define DMIC_LP_MODE_MASK (0x1 << DMIC_LP_MODE)
#define DMIC_HPF1_MODE 2
#define DMIC_HPF1_MODE_MASK (0x1 << DMIC_HPF1_MODE)
#define DMIC_TRI_EN 1
#define DMIC_TRI_EN_MASK (0x1 << DMIC_TRI_EN)
#define DMIC_EN 0
#define DMIC_EN_MASK (0x1 << DMIC_EN)
#define __dmic_reset(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_RESET_MASK,DMIC_RESET)
#define __dmic_get_reset(dmic)\
dmic_get_reg(dmic,DMICCR0,DMIC_RESET_MASK,DMIC_RESET)
#define __dmic_reset_tri(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_RESET_TRI_MASK,DMIC_RESET_TRI)
#define __dmic_set_chnum(dmic,n)\
dmic_set_reg(dmic,DMICCR0,n,DMIC_CHNUM_MASK,DMIC_CHNUM)
#define __dmic_get_chnum(dmic,n)\
dmic_set_reg(dmic,DMICCR0,DMIC_CHNUM_MASK,DMIC_CHNUM)
#define __dmic_unpack_msb(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_UNPACK_MSB_MASK,DMIC_UNPACK_MSB)
#define __dmic_unpack_dis(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_UNPACK_DIS_MASK,DMIC_UNPACK_DIS)
#define __dmic_enable_sw_lr(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_SW_LR_MASK,DMIC_SW_LR)
#define __dmic_disable_sw_lr(dmic)\
dmic_set_reg(dmic,DMICCR0,0,DMIC_SW_LR_MASK,DMIC_SW_LR)
#define __dmic_split(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_SPLIT_DI_MASK,DMIC_SPLIT_DI)
#define __dmic_enable_pack(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_PACK_EN_MASK,DMIC_PACK_EN)
#define __dmic_set_sr(dmic,n)\
dmic_set_reg(dmic,DMICCR0,n,DMIC_SR_MASK,DMIC_SR)
#define __dmic_set_sr_8k(dmic)\
__dmic_set_sr(dmic,0)
#define __dmic_set_sr_16k(dmic)\
__dmic_set_sr(dmic,1)
#define __dmic_set_sr_48k(dmic)\
__dmic_set_sr(dmic,2)
#define __dmic_enable_lp(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_LP_MODE_MASK,DMIC_LP_MODE)
#define __dmic_disable_lp(dmic)\
dmic_set_reg(dmic,DMICCR0,0,DMIC_LP_MODE_MASK,DMIC_LP_MODE)
#define __dmic_enable_hpf1(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_HPF1_MODE_MASK,DMIC_HPF1_MODE)
#define __dmic_disable_hpf1(dmic)\
dmic_set_reg(dmic,DMICCR0,0,DMIC_HPF1_MODE_MASK,DMIC_HPF1_MODE)
#define __dmic_is_enable_tri(dmic)\
dmic_get_reg(dmic,DMICCR0,DMIC_TRI_EN_MASK,DMIC_TRI_EN)
#define __dmic_enable_tri(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_TRI_EN_MASK,DMIC_TRI_EN)
#define __dmic_disable_tri(dmic)\
dmic_set_reg(dmic,DMICCR0,0,DMIC_TRI_EN_MASK,DMIC_TRI_EN)
#define __dmic_is_enable(dmic)\
dmic_get_reg(dmic,DMICCR0,DMIC_EN_MASK,DMIC_EN)
#define __dmic_enable(dmic)\
dmic_set_reg(dmic,DMICCR0,1,DMIC_EN_MASK,DMIC_EN)
#define __dmic_disable(dmic)\
dmic_set_reg(dmic,DMICCR0,0,DMIC_EN_MASK,DMIC_EN)
/*DMICGCR*/
#define DMIC_GCR 0
#define DMIC_GCR_MASK (0Xf << DMIC_GCR)
#define __dmic_set_gcr(dmic,n)\
dmic_set_reg(dmic, DMICGCR, n, DMIC_GCR_MASK,DMIC_GCR)
/* DMICIMR */
#define DMIC_FIFO_TRIG_MASK 5
#define DMIC_FIFO_TRIG_MSK (1 << DMIC_FIFO_TRIG_MASK)
#define DMIC_WAKE_MASK 4
#define DMIC_WAKE_MSK (1 << DMIC_WAKE_MASK)
#define DMIC_EMPTY_MASK 3
#define DMIC_EMPTY_MSK (1 << DMIC_EMPTY_MASK)
#define DMIC_FULL_MASK 2
#define DMIC_FULL_MSK (1 << DMIC_FULL_MASK)
#define DMIC_PRERD_MASK 1
#define DMIC_PRERD_MSK (1 << DMIC_PRERD_MASK)
#define DMIC_TRI_MASK 0
#define DMIC_TRI_MSK (1 << DMIC_TRI_MASK)
#define __dmic_mask_all_int(dmic)\
dmic_set_reg(dmic,DMICIMR, 0x3f, 0x3f, 0)
/*DMICINTCR*/
#define DMIC_FIFO_TRIG_FLAG 4
#define DMIC_FIFO_TRIG_FLAG_MASK (1 << DMIC_WAKE_FLAG)
#define DMIC_WAKE_FLAG 4
#define DMIC_WAKE_FLAG_MASK (1 << DMIC_WAKE_FLAG)
#define DMIC_EMPTY_FLAG 3
#define DMIC_EMPTY_FLAG_MASK (1 << DMIC_EMPTY_FLAG)
#define DMIC_FULL_FLAG 2
#define DMIC_FULL_FLAG_MASK (1 << DMIC_FULL_FLAG)
#define DMIC_PRERD_FLAG 1
#define DMIC_PRERD_FLAG_MASK (1 << DMIC_PRERD_FLAG)
#define DMIC_TRI_FLAG 0
#define DMIC_TRI_FLAG_MASK (1 << DMIC_TRI_FLAG)
/*DMICTRICR*/
#define DMIC_TRI_MODE 16
#define DMIC_TRI_MODE_MASK (0xf << DMIC_TRI_MODE)
#define DMIC_TRI_DEBUG 4
#define DMIC_TRI_DEBUG_MASK (0x1 << DMIC_TRI_DEBUG)
#define DMIC_HPF2_EN 3
#define DMIC_HPF2_EN_MASK (0x1 << DMIC_HPF2_EN)
#define DMIC_PREFETCH 1
#define DMIC_PREFETCH_MASK (0x3 << DMIC_PREFETCH)
#define DMIC_TRI_CLR 0
#define DMIC_TRI_CLR_MASK (0x1 << DMIC_TRI_CLR)
#define __dmic_enable_hpf2(dmic) \
dmic_set_reg(dmic, DMICTRICR, 1, DMIC_HPF2_EN_MASK, DMIC_HPF2_EN)
#define __dmic_disable_hpf2(dmic) \
dmic_set_reg(dmic, DMICTRICR, 0, DMIC_HPF2_EN_MASK, DMIC_HPF2_EN)
/*DMICTHRH*/
#define DMIC_THR_H 0
#define DMIC_THR_H_MASK (0xfffff << DMIC_THR_H)
#define __dmic_set_thr_high(dmic,n) \
dmic_set_reg(dmic, DMICTHRH, n, DMIC_THR_H_MASK, DMIC_THR_H)
/*DMICTHRL*/
#define DMIC_THR_L 0
#define DMIC_THR_L_MASK (0xfffff << DMIC_THR_L)
#define __dmic_set_thr_low(dmic,n) \
dmic_set_reg(dmic, DMICTHRL, n, DMIC_THR_L_MASK, DMIC_THR_L)
/* DMICTRIMMAX */
#define DMIC_M_MAX 0
#define DMIC_M_MAX_MASK (0xffffff << DMIC_M_MAX)
/* DMICTRINMAX */
#define DMIC_N_MAX 0
#define DMIC_N_MAX_MASK (0xffff << DMIC_N_MAX)
/* DMICFTHR */
#define DMIC_RDMS 31
#define DMIC_RDMS_MASK (0x1 << DMIC_RDMS)
#define DMIC_FIFO_THR 0
#define DMIC_FIFO_THR_MASK (0x3f << DMIC_FIFO_THR)
#define __dmic_is_enable_rdms(dmic)\
dmic_get_reg(dmic, DMICFTHR,DMIC_RDMS_MASK,DMIC_RDMS)
#define __dmic_enable_rdms(dmic)\
dmic_set_reg(dmic, DMICFTHR,1,DMIC_RDMS_MASK,DMIC_RDMS)
#define __dmic_disable_rdms(dmic)\
dmic_set_reg(dmic, DMICFTHR,1,DMIC_RDMS_MASK,DMIC_RDMS)
#define __dmic_set_request(dmic,n) \
dmic_set_reg(dmic, DMICFTHR, n, DMIC_FIFO_THR_MASK, DMIC_FIFO_THR)
/*DMICFSR*/
#define DMIC_FULLS 19
#define DMIC_FULLS_MASK (0x1 << DMIC_FULLS)
#define DMIC_TRIGS 18
#define DMIC_TRIGS_MASK (0x1 << DMIC_TRIGS)
#define DMIC_PRERDS 17
#define DMIC_PRERDS_MASK (0x1 << DMIC_PRERDS)
#define DMIC_EMPTYS 16
#define DMIC_EMPTYS_MASK (0x1 << DMIC_EMPTYS)
#define DMIC_FIFO_LVL 0
#define DMIC_FIFO_LVL_MASK (0x3f << DMIC_FIFO_LVL)
/*********************************************************************************************************
**
*********************************************************************************************************/
struct jz_dmic* rt_hw_dmic_init(void);
int jz_dmic_set_rate(struct jz_dmic* dmic, int rate);
int jz_dmic_set_gain(struct jz_dmic* dmic, int vol);
int jz_dmic_set_channels(struct jz_dmic* dmic, int channels);
#endif /* _DRV_DMIC_H_ */

View File

@@ -24,6 +24,7 @@
#include <rthw.h>
#include <rtthread.h>
#include <string.h>
#include "board.h"
#include "drv_clock.h"
@@ -32,12 +33,38 @@
extern void rt_hw_cache_init(void);
extern unsigned char _iramcopy;
extern unsigned char _iramstart;
extern unsigned char _iramend;
#ifdef RT_USING_CPLUSPLUS
int cplusplus_system_init(void)
{
typedef void (*pfunc) ();
extern pfunc __ctors_start__[];
extern pfunc __ctors_end__[];
pfunc *p;
for (p = __ctors_end__ - 2; p > __ctors_start__; )
{
(*p)();
p--;
}
return 0;
}
#endif
void rt_hw_board_init(void)
{
memcpy((void*)&_iramstart, (void*)&_iramcopy, (rt_uint32_t)&_iramend - (rt_uint32_t)&_iramstart);
memset((void*)&__bss_start, 0x0, (rt_uint32_t)&__bss_end - (rt_uint32_t)&__bss_start);
rt_hw_cache_init();
rt_hw_exception_init();
/* init hardware interrupt */
rt_hw_interrupt_init();
rt_hw_uart_init();
#ifdef RT_USING_CONSOLE
/* set console device */
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);

102
bsp/x1000/drivers/board.h Normal file
View File

@@ -0,0 +1,102 @@
/*
* File : board.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2015-11-19 Urey the first version
*/
#ifndef _BOARD_H_
#define _BOARD_H_
#include <rtthread.h>
#include <stdint.h>
#include "x1000.h"
#define RT_USING_JZ_X1000
#define X1000
#ifdef BOARD_HALLEY2_FIR
#include "board/halley2_fir/board_halley2_fir.h"
#endif
#ifdef BOARD_HALLEY2_REALBOARD
#include "board/halley2_realboard/board_halley2_readboard.h"
#endif
#ifdef BOARD_HALLEY2_REALBOARD_V2
#include "board/halley2_realboard_v2/board_halley2_readboard_v2.h"
#endif
#ifdef BOARD_HALLEY2_IDELAN
#include "board/halley2_idelan/board_halley2_idelan.h"
#endif
#ifdef BOARD_HALLEY2
#include "board/halley2/board_halley2.h"
#endif
#ifdef BOARD_PHOENIX
#include "board/phoenix/board_phoenix.h"
#endif
#ifdef BOARD_CANNA
#include "board/canna/board_canna.h"
#endif
/*
* Clock setting
*/
#define BOARD_EXTAL_CLK 24000000
#define BOARD_RTC_CLK 32768
#define BOARD_CPU_CLK (1008 * 1000 * 1000UL)
#define BOARD_APLL_FREQ 1008000000 /*If APLL not use mast be set 0*/
#define BOARD_MPLL_FREQ 600000000 /*If MPLL not use mast be set 0*/
/*
* Heap setting
*/
extern unsigned char __bss_start;
extern unsigned char __bss_end;
#define RT_HW_HEAP_BEGIN (void*)&__bss_end
#define RT_HW_HEAP_END (void*)(0x80000000 + 32 * 1024 * 1024)
/* HW EVENT */
#define EVENT_NONE 0x0000
#define EVENT_TYPE_MSK 0xFF00
#define EVENT_VALUE_MSK 0x00FF
#define EVENT_LINEIN 0x0100
#define EVENT_LINEIN_INSERT 0x0101
#define EVENT_LINEIN_REMOVE 0x0102
#define EVENT_LINEIN_SHUTDOWN 0x0103
#define EVENT_BAT 0x0200
#define EVENT_BAT_ALONE 0x0201
#define EVENT_BAT_CHARGE_IN 0x0202
#define EVENT_BAT_CHARGE_FULL 0x0203
#define EVENT_BAT_ERROR 0x0204
#define EVENT_KEY_DOWN 0x0300
#define EVENT_KEY_UP 0x0400
#endif /* _BOARD_H_ */

View File

@@ -0,0 +1,6 @@
#ifndef BOARD_CANNA_H__
#define BOARD_CANNA_H__
#endif

View File

@@ -0,0 +1,14 @@
#ifndef BOARD_HALLEY2_H__
#define BOARD_HALLEY2_H__
#define LCD_RST_PORT GPIO_PORT_D
#define LCD_RST_PIN GPIO_Pin_0
#define LCD_BLPWM_PORT GPIO_PORT_C
#define LCD_BLPWM_PIN GPIO_Pin_25
#define LCD_BLEN_PORT GPIO_PORT_A
#define LCD_BLEN_PIN GPIO_Pin_25
#endif

View File

@@ -0,0 +1,80 @@
#ifndef BOARD_HALLEY2_IDELAN_H__
#define BOARD_HALLEY2_IDELAN_H__
#define AUDIO_SHUTDOWN_PORT GPIO_PORT_B
#define AUDIO_SHUTDOWN_PIN GPIO_Pin_7
#define AUDIO_SHUTDOWN_MUTE 1
/*
* IO LCD
*/
#define LCD_PWEN_PORT GPIO_PORT_B
#define LCD_PWEN_PIN GPIO_Pin_19 //原理图不对实际连接到LCD_TE
#define LCD_RST_PORT GPIO_PORT_B
#define LCD_RST_PIN GPIO_Pin_14
#define LCD_BL_PORT GPIO_PORT_B
#define LCD_BL_PIN GPIO_Pin_9
/*
* IO Touch
*/
#define TP_INT_PORT GPIO_PORT_B
#define TP_INT_PIN GPIO_Pin_11
#define TP_RST_PORT GPIO_PORT_B
#define TP_RST_PIN GPIO_Pin_12
#define TP_PWEN_PORT GPIO_PORT_B
#define TP_PWEN_PIN GPIO_Pin_15
/*
* IO KeyBoard:
*/
#define KEY_WIFI_PORT GPIO_PORT_A
#define KEY_WIFI_PIN GPIO_Pin_20
#define KEY_BT_PORT GPIO_PORT_A
#define KEY_BT_PIN GPIO_Pin_21
#define KEY_VOLD_PORT GPIO_PORT_A
#define KEY_VOLD_PIN GPIO_Pin_22
#define KEY_VOLU_PORT GPIO_PORT_B
#define KEY_VOLU_PIN GPIO_Pin_28
#define KEY_WKUP_PORT GPIO_PORT_B
#define KEY_WKUP_PIN GPIO_Pin_31
/*
* IO Camera
*/
#define CIM_PWDN_PORT GPIO_PORT_A
#define CIM_PWDN_PIN GPIO_Pin_25
#define CIM_RST_PORT GPIO_PORT_A
#define CIM_RST_PIN GPIO_Pin_24
#define CIM_PWEN_PORT GPIO_PORT_A
#define CIM_PWEN_PIN GPIO_Pin_23
/*
* IO LED Config
*/
#define LED_BT_PORT GPIO_PORT_B
#define LED_BT_PIN GPIO_Pin_6
#define LED_WIFI_PORT GPIO_PORT_B
#define LED_WIFI_PIN GPIO_Pin_24
#define LED_ZB_PORT GPIO_PORT_C
#define LED_ZB_PIN GPIO_Pin_27
/*
* Others
*/
#define IO_IRQ_FG_PORT GPIO_PORT_B
#define IO_IRQ_FG_PIN GPIO_Pin_13
#endif

View File

@@ -0,0 +1,6 @@
2016/08/29发布
已知的硬件错误:
-I2S 信号分配错误 I2SDI I2SDO反了 核心板的DO是输出 Codec的DO也是输出核心板的DO需要接到Codec的SDI0上
-X1 12.288晶振不焊接R13 需要焊接核心板提供时钟layout的时候晶振保留
-
-layout问题整个板子GND走线 很多实连接,手工焊接质量不保证

View File

@@ -0,0 +1,5 @@
#ifndef BOARD_HALLEY2_IDELAN_H__
#define BOARD_HALLEY2_IDELAN_H__
#endif

View File

@@ -0,0 +1,14 @@
#ifndef BOARD_HALLEY2_IDELAN_H__
#define BOARD_HALLEY2_IDELAN_H__
#define AUDIO_SHUTDOWN_PORT GPIO_PORT_B
#define AUDIO_SHUTDOWN_PIN GPIO_Pin_6
#define AUDIO_SHUTDOWN_MUTE 1
#define LCD_RST_PORT GPIO_PORT_C
#define LCD_RST_PIN GPIO_Pin_25
#define LCD_BL_PORT GPIO_PORT_B
#define LCD_BL_PIN GPIO_Pin_19
#endif

View File

@@ -0,0 +1,61 @@
/*
* File : board_halley2_readboard_v2.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2017-01-01 Urey first version
*/
#ifndef DRIVER_BOARD_HALLEY2_REALBOARD_V2_BOARD_HALLEY2_READBOARD_V2_H_
#define DRIVER_BOARD_HALLEY2_REALBOARD_V2_BOARD_HALLEY2_READBOARD_V2_H_
#ifdef __cplusplus
extern "C" {
#endif
#define AUDIO_SHUTDOWN_PORT GPIO_PORT_C
#define AUDIO_SHUTDOWN_PIN GPIO_Pin_26
#define AUDIO_SHUTDOWN_MUTE 0
#define LCD_RST_PORT GPIO_PORT_C
#define LCD_RST_PIN GPIO_Pin_23
#define LCD_BL_PORT GPIO_PORT_D
#define LCD_BL_PIN GPIO_Pin_1
#define LCD_TP_INT_PORT GPIO_PORT_C
#define LCD_TP_INT_PIN GPIO_Pin_25
/* BLINK LED */
#define BLINK_LED0_PORT GPIO_PORT_B
#define BLINK_LED0_PIN GPIO_Pin_9
#define BLINK_LED1_PORT GPIO_PORT_B
#define BLINK_LED1_PIN GPIO_Pin_8
#define BLINK_LED2_PORT GPIO_PORT_B
#define BLINK_LED2_PIN GPIO_Pin_13
#define BLINK_LED3_PORT GPIO_PORT_B
#define BLINK_LED3_PIN GPIO_Pin_11
#ifdef __cplusplus
}
#endif
#endif /* DRIVER_BOARD_HALLEY2_REALBOARD_V2_BOARD_HALLEY2_READBOARD_V2_H_ */

Binary file not shown.

View File

@@ -0,0 +1,4 @@
#ifndef BOARD_HALLEY2_H__
#define BOARD_HALLEY2_H__
#endif

View File

@@ -0,0 +1,11 @@
#connect to the JDI gdb server
target remote 169.28.23.51:2823
#set remote write size
set remotewritesize fixed
set remotewritesize 8192
#load the debug image
load
#debug begin

View File

@@ -0,0 +1,222 @@
#include <board.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_gpio.h"
static void _delay_us(rt_uint32_t ns)
{
volatile rt_uint16_t delay;
while(ns--)
{
delay = 200;
while(delay--);
}
}
static void _delay_ms(rt_uint32_t ms)
{
volatile rt_uint16_t delay;
while(ms--)
{
_delay_us(1000);
}
}
#if defined(RT_USING_WIFI) && (defined(WIFI_USING_AP6212) || defined(WIFI_USING_AP6181))
/**
* PC16 WL_WAKE_HOST
* PC17 WL_REG_EN
*/
int io_AP6212(void)
{
gpio_set_func(GPIO_PORT_C, GPIO_Pin_17, GPIO_FUNC_0);
gpio_direction_output(GPIO_PORT_C, GPIO_Pin_17, 0);
rt_kprintf("Enable WL_REG_EN\n");
gpio_set_value(GPIO_PORT_C, GPIO_Pin_17, 0);
rt_thread_delay(1);
gpio_set_value(GPIO_PORT_C, GPIO_Pin_17, 1);
return 0;
}
INIT_DEVICE_EXPORT(io_AP6212);
#endif
#if defined(RT_USING_BT) && (defined(WIFI_USING_AP6212) || defined(WIFI_USING_AP6181))
#include <drv_rtc.h>
/**
* PC16 32768 clock
*/
int io_AP6212_bt(void)
{
rtc32k_enable();
return 0;
}
INIT_DEVICE_EXPORT(io_AP6212_bt);
#endif
#if defined(BOARD_CANNA)
int io_canna(void)
{
/* PC25(1) for Audio Shutdown IO */
gpio_set_func(GPIO_PORT_C, GPIO_Pin_25, GPIO_FUNC_1);
gpio_direction_output(GPIO_PORT_C,GPIO_Pin_25, 0);
gpio_set_value(GPIO_PORT_C,GPIO_Pin_25, 0);
return 0;
}
INIT_DEVICE_EXPORT(io_canna);
#endif
#if defined(BOARD_HALLEY2)
int io_halley2(void)
{
#ifdef RT_USING_EMAC
/* PC23 for MAC_RST_N */
gpio_set_func(GPIO_PORT_C, GPIO_Pin_23, GPIO_FUNC_0);
gpio_direction_output(GPIO_PORT_C, GPIO_Pin_23, 0);
rt_thread_delay(1);
gpio_direction_output(GPIO_PORT_C, GPIO_Pin_23, 1);
rt_thread_delay(1);
#endif
return 0;
}
INIT_DEVICE_EXPORT(io_halley2);
#endif
#if defined(BOARD_PHOENIX)
int io_phoenix(void)
{
/* PB0(1) for Audio Shutdown IO */
gpio_set_func(GPIO_PORT_B, GPIO_Pin_0, GPIO_FUNC_2);
gpio_direction_output(GPIO_PORT_B,GPIO_Pin_0, 0);
gpio_set_value(GPIO_PORT_B,GPIO_Pin_0,0);
/* PB3 for reset EMAC PHY */
gpio_set_func(GPIO_PORT_B, GPIO_Pin_3, GPIO_FUNC_2);
gpio_direction_output(GPIO_PORT_B, GPIO_Pin_3, 0);
rt_thread_delay(1);
gpio_direction_output(GPIO_PORT_B, GPIO_Pin_3, 1);
rt_thread_delay(1);
return 0;
}
INIT_DEVICE_EXPORT(io_phoenix);
#endif
#if defined(BOARD_OX)
int io_ox(void)
{
/* PB6 for Audio Shutdown IO */
gpio_set_func(GPIO_PORT_B, GPIO_Pin_6, GPIO_FUNC_1);
gpio_direction_output(GPIO_PORT_B,GPIO_Pin_6, 0);
gpio_set_value(GPIO_PORT_B,GPIO_Pin_6, 0);
gpio_direction_output(GPIO_PORT_C, GPIO_Pin_25, GPIO_OUTPUT0);
rt_thread_delay(rt_tick_from_millisecond(100));
gpio_direction_output(GPIO_PORT_C, GPIO_Pin_25, GPIO_OUTPUT1);
/* PB19 for LCD black light */
gpio_direction_output(GPIO_PORT_B,GPIO_Pin_19, GPIO_OUTPUT1);
#ifdef RT_USING_EMAC
/* PC23 for MAC_RST_N */
// gpio_set_func(GPIO_PORT_C, GPIO_Pin_23, GPIO_FUNC_0);
gpio_direction_output(GPIO_PORT_C, GPIO_Pin_23, 0);
rt_thread_delay(1);
gpio_direction_output(GPIO_PORT_C, GPIO_Pin_23, 1);
rt_thread_delay(1);
#endif
return 0;
}
INIT_DEVICE_EXPORT(io_ox);
#endif
#ifdef BOARD_HALLEY2_REALBOARD
int io_realboard(void)
{
/* Audio Shutdown IO */
gpio_direction_output(AUDIO_SHUTDOWN_PORT,AUDIO_SHUTDOWN_PIN, AUDIO_SHUTDOWN_MUTE);
gpio_set_value(AUDIO_SHUTDOWN_PORT,AUDIO_SHUTDOWN_PIN, AUDIO_SHUTDOWN_MUTE);
#ifdef RT_USING_EMAC
gpio_set_func(GPIO_PORT_B, GPIO_Pin_7, GPIO_OUTPUT0);
gpio_set_func(GPIO_PORT_B, GPIO_Pin_8, GPIO_OUTPUT0);
gpio_set_func(GPIO_PORT_B, GPIO_Pin_9, GPIO_OUTPUT0);
gpio_set_func(GPIO_PORT_B, GPIO_Pin_10, GPIO_OUTPUT0);
gpio_set_func(GPIO_PORT_B, GPIO_Pin_11, GPIO_OUTPUT0);
gpio_set_func(GPIO_PORT_B, GPIO_Pin_12, GPIO_OUTPUT0);
gpio_set_func(GPIO_PORT_B, GPIO_Pin_13, GPIO_INPUT);
gpio_set_func(GPIO_PORT_B, GPIO_Pin_14, GPIO_INPUT);
gpio_set_func(GPIO_PORT_B, GPIO_Pin_15, GPIO_INPUT);
/* PC23 for MAC_RST_N */
gpio_direction_output(GPIO_PORT_C, GPIO_Pin_23, 0);
_delay_ms(100);
gpio_direction_output(GPIO_PORT_C, GPIO_Pin_23, 1);
_delay_ms(100);
#endif
return 0;
}
INIT_BOARD_EXPORT(io_realboard);
#endif /* BOARD_HALLEY2_REALBOARD_X1000 */
#ifdef BOARD_HALLEY2_REALBOARD_V2
int io_realboard_v2(void)
{
/* Audio Shutdown IO */
gpio_direction_output(AUDIO_SHUTDOWN_PORT,AUDIO_SHUTDOWN_PIN, AUDIO_SHUTDOWN_MUTE);
gpio_set_value(AUDIO_SHUTDOWN_PORT,AUDIO_SHUTDOWN_PIN, AUDIO_SHUTDOWN_MUTE);
/* Reset lcd,TP,... */
gpio_direction_output(LCD_TP_INT_PORT, LCD_TP_INT_PIN,1);
_delay_ms(300);
gpio_direction_output(LCD_RST_PORT, LCD_RST_PIN,0);
_delay_ms(100);
gpio_set_value(LCD_RST_PORT, LCD_RST_PIN, 1);
/* LED */
gpio_direction_output(BLINK_LED0_PORT, BLINK_LED0_PIN,1);
gpio_direction_output(BLINK_LED1_PORT, BLINK_LED1_PIN,1);
gpio_direction_output(BLINK_LED2_PORT, BLINK_LED2_PIN,1);
gpio_direction_output(BLINK_LED3_PORT, BLINK_LED3_PIN,1);
return 0;
}
INIT_BOARD_EXPORT(io_realboard_v2);
#endif /* BOARD_HALLEY2_REALBOARD_V2 */
#ifdef BOARD_HALLEY2_FIR
int io_halley2_fir(void)
{
/* Audio Shutdown IO */
gpio_direction_output(AUDIO_SHUTDOWN_PORT,AUDIO_SHUTDOWN_PIN, AUDIO_SHUTDOWN_MUTE);
/* LCD */
rt_kprintf("lcd power enable...\n");
gpio_direction_output(LCD_PWEN_PORT,LCD_PWEN_PIN, 0); //LCD Power Enable
gpio_direction_output(LCD_RST_PORT,LCD_RST_PIN, 0);
gpio_direction_output(LCD_BL_PORT,LCD_BL_PIN, 0);
/* Touch */
gpio_direction_output(TP_PWEN_PORT,TP_PWEN_PIN, 0);
gpio_direction_output(TP_RST_PORT,TP_RST_PIN, 0);
/* LED */
gpio_direction_output(LED_BT_PORT,LED_BT_PIN, 1);
gpio_direction_output(LED_WIFI_PORT,LED_WIFI_PIN, 1);
gpio_direction_output(LED_ZB_PORT,LED_ZB_PIN, 1);
return 0;
}
INIT_BOARD_EXPORT(io_halley2_fir);
#endif /* BOARD_HALLEY2_FIR */

View File

@@ -0,0 +1,305 @@
/*
* File : drv_gpio_keyboard.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2015-11-19 Urey the first version
*/
/*********************************************************************************************************
** Include Files
*********************************************************************************************************/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "drv_gpio.h"
#include "board_key.h"
#ifdef RT_USING_AUDIO_PLAYER
#include <player_app.h>
#endif
#define KEY_DEBUG
#ifdef KEY_DEBUG
#define KEY_DBG(...) rt_kprintf("[KEY]"),rt_kprintf(__VA_ARGS__)
#else
#define KEY_DBG(...)
#endif
static keyboard_event_handler_t _handler = RT_NULL;
#if defined(BOARD_HALLEY2)
/* 4 keys
* SW1 SW2 SW3 SW5
* Vol- Vol+ Play/Pause Mode/Config
* PA10 PA11 PB28 PB31
*/
static struct keyboard_io_def keyboard_io_tbl[] =
{
//Vol-/Next Song
{
GPIO_PORT_A, GPIO_Pin_10 ,
KEY_NEXT, KEY_VOLDEC,
},
//Vol+/Prev Song
{
GPIO_PORT_A, GPIO_Pin_11 ,
KEY_PREV, KEY_VOLINC,
},
//Play_Pause
{
GPIO_PORT_B, GPIO_Pin_28 ,
KEY_UNKNOWN, KEY_PLAY_PAUSE,
},
//Mode/Config
{
GPIO_PORT_B, GPIO_Pin_31,
KEY_CONFIG, KEY_NETWORK_MODE,
},
};
#elif defined(BOARD_HALLEY2_REALBOARD)
/* 6 keys
* 11 12 21 22 31 32
* ON/OFF MODE V+ V- BT/MUTE WIFI
*/
static struct keyboard_io_def keyboard_io_tbl[] =
{
//ON/OFF
{
GPIO_PORT_B, GPIO_Pin_31,
KEY_UNKNOWN, KEY_PWROFF,
},
//V+
{
GPIO_PORT_B, GPIO_Pin_25,
KEY_UNKNOWN, KEY_VOLINC,
},
//V-
{
GPIO_PORT_B, GPIO_Pin_2,
KEY_UNKNOWN, KEY_VOLDEC,
},
//BT/MUTE
{
GPIO_PORT_B, GPIO_Pin_3,
KEY_SOURCE, KEY_MUTE,
},
//WIFI
{
GPIO_PORT_B, GPIO_Pin_28,
KEY_UNKNOWN, KEY_CONFIG,
},
};
#elif defined(BOARD_HALLEY2_REALBOARD_V2)
struct keyboard_io_def keyboard_io_tbl[] =
{
//ON/OFF
{
GPIO_PORT_D, GPIO_Pin_0,
KEY_UNKNOWN, KEY_UNKNOWN,
},
//V+
{
GPIO_PORT_B, GPIO_Pin_28,
KEY_UNKNOWN, KEY_UNKNOWN,
},
//V-
{
GPIO_PORT_B, GPIO_Pin_31,
KEY_UNKNOWN, KEY_UNKNOWN,
},
//WIFI config
{
GPIO_PORT_D, GPIO_Pin_2,
KEY_UNKNOWN, KEY_UNKNOWN,
},
};
#else
struct keyboard_io_def keyboard_io_tbl[] =
{
//PWRKEY KEY
{
GPIO_PORT_B, GPIO_Pin_31,
KEY_UNKNOWN, KEY_UNKNOWN
},
};
#endif
#define CFG_MAX_KEY_NBR sizeof(keyboard_io_tbl)/sizeof(keyboard_io_tbl[0])
static struct rt_mailbox* _keyMb = RT_NULL;
void keyboard_irq_callback(void *param)
{
KEY_DBG("%d\n", (int)param);
if (_keyMb)
{
struct keyboard_io_def* key;
int value = (int)param;
key = &keyboard_io_tbl[value];
if(rt_mb_send(_keyMb, (rt_uint32_t)param) == RT_EOK)
gpio_mask_irq(key->port, key->pin);
}
}
#define KEY_EVENT_DOWN 0x01
#define KEY_EVENT_HOLD 0x02
#define KEY_EVENT_UP 0x04
#define KEY_SCAN_STEP_TIME 10
#define KEY_SCAN_HOLD_THRESHOLD 2000
//Scan the single key
rt_uint8_t key_scan(struct keyboard_io_def *keyIO)
{
static rt_uint8_t keyTrigger = 0;
static rt_uint8_t keyRelease = 0;
static rt_uint8_t keyHold = 0;
rt_uint8_t keyValue = 0;
//elimination buffeting
do
{
keyValue = gpio_get_value(keyIO->port,keyIO->pin);
rt_thread_delay(rt_tick_from_millisecond(KEY_SCAN_STEP_TIME));
}while(keyValue != gpio_get_value(keyIO->port,keyIO->pin));
keyValue ^= 0x01;
keyTrigger = keyValue &(keyValue ^ keyHold);
keyRelease = (keyValue ^ keyTrigger ^ keyHold);
keyHold = keyValue;
// KEY_DBG("keyValue = %x\n,keyTrigger = %x\n,keyRelese = %x\n,keyHold = %x\n",keyValue,keyTrigger,keyRelease,keyHold);
if(keyTrigger != 0)
return KEY_EVENT_DOWN;
else if(keyHold != 0)
return KEY_EVENT_HOLD;
return KEY_EVENT_UP;
}
void kbd_thread(void* parameter)
{
int keyId;
rt_uint8_t keyEvent;
rt_uint8_t keyValue;
rt_uint32_t keyHoldTime;
_keyMb = rt_mb_create("key", 4, RT_IPC_FLAG_FIFO);
while (1)
{
if(rt_mb_recv(_keyMb, (rt_uint32_t*)&keyId, RT_TICK_PER_SECOND) != RT_EOK)
{
//if no key pressed,check power key...
keyId = 0;
}
{
struct keyboard_io_def* key;
// Check key ID
if(keyId >= CFG_MAX_KEY_NBR)
{
rt_kprintf("keyID error\n");
continue;
}
key = &keyboard_io_tbl[keyId];
keyEvent = key_scan(key);
/* No key input */
if(keyEvent == KEY_EVENT_UP)
{
gpio_unmask_irq(key->port, key->pin);
continue;
}
KEY_DBG("key %d down\n", keyId);
//Wait for key RELEASE
keyHoldTime = 0;
do
{
keyEvent = key_scan(key);
if(keyEvent == KEY_EVENT_HOLD)
{
keyHoldTime += KEY_SCAN_STEP_TIME;
if(keyHoldTime > KEY_SCAN_HOLD_THRESHOLD)
break;
}
} while (keyEvent != KEY_EVENT_UP);
KEY_DBG("key %d up,hold time = %dms\n", keyId,keyHoldTime);
if(keyHoldTime > KEY_SCAN_HOLD_THRESHOLD)
keyValue = key->longKey;
else
keyValue = key->shortKey;
//send key event
if (_handler) _handler(EVENT_KEY_DOWN | keyValue);
//Wait for KEYUP
while (keyEvent != KEY_EVENT_UP)
{
keyEvent = key_scan(key);
rt_thread_delay(RT_TICK_PER_SECOND / 10);
}
if (_handler) _handler(EVENT_KEY_UP | keyValue);
gpio_unmask_irq(key->port, key->pin);
}
}
}
void rt_hw_keyboard_set_handler(keyboard_event_handler_t handler)
{
_handler = handler;
}
void rt_hw_keyboard_init(void)
{
int i;
rt_thread_t tid;
tid = rt_thread_create("key", kbd_thread, RT_NULL, 2048, 16, 10);
if (tid)
rt_thread_startup(tid);
/* initialize all IO for keyboard */
for (i = 0; i < CFG_MAX_KEY_NBR; ++i)
{
gpio_set_func(keyboard_io_tbl[i].port,keyboard_io_tbl[i].pin,GPIO_INPUT_PULL | GPIO_INT_FE);
gpio_set_irq_callback(keyboard_io_tbl[i].port,keyboard_io_tbl[i].pin,keyboard_irq_callback, (void*)i);
gpio_unmask_irq(keyboard_io_tbl[i].port,keyboard_io_tbl[i].pin);
}
}

View File

@@ -0,0 +1,48 @@
#ifndef BOARD_KEY_H__
#define BOARD_KEY_H__
#ifndef RT_USING_AUDIO_PLAYER
enum KEY_VALUE
{
KEY_VOLINC,
KEY_VOLDEC,
KEY_NEXT,
KEY_PREV,
KEY_PAUSE,
KEY_PLAY,
KEY_PLAY_PAUSE,
KEY_MUTE,
KEY_MIC,
KEY_EQ,
KEY_MENU,
KEY_CHANNEL,
KEY_FAVORITE,
//system shutdown, wifi config...
KEY_PWROFF,
KEY_CONFIG,
KEY_NETWORK_MODE,
KEY_SOURCE,
KEY_UNKNOWN,
};
#endif
struct keyboard_io_def
{
enum gpio_port port;
enum gpio_pin pin;
int longKey;
int shortKey;
};
typedef void (*keyboard_event_handler_t)(uint32_t event);
void rt_hw_keyboard_init(void);
void rt_hw_keyboard_set_handler(keyboard_event_handler_t handler);
#endif

View File

@@ -0,0 +1,104 @@
/*
* File : drv_gpio_led.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2016/05/13 Urey the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "drv_gpio.h"
#if 0
#include "board_led.h"
#if defined(BOARD_CANNA)
#define MAX_LED_NBR 3
struct led_io_def led_io_tbl[MAX_LED_NBR] =
{
//LED_POWER
{
GPIO_PORT_C,
GPIO_Pin_24
},
//LED_WIFI
{
GPIO_PORT_D,
GPIO_Pin_5
},
//LED_CHARGING
{
GPIO_PORT_A,
GPIO_Pin_0
},
};
#else
#define MAX_LED_NBR 0
struct led_io_def led_io_tbl[] =
{
//LED_POWER
{
GPIO_PORT_B,
GPIO_Pin_6
},
};
#endif
void rt_hw_led_on(int led)
{
if((led >= LED_LAST) || (led > MAX_LED_NBR))
return;
gpio_set_value(led_io_tbl[led].port,led_io_tbl[led].pin,0);
}
void rt_hw_led_off(int led)
{
if((led >= LED_LAST) || (led > MAX_LED_NBR))
return;
gpio_set_value(led_io_tbl[led].port,led_io_tbl[led].pin,1);
}
int rt_hw_led_init(void)
{
rt_uint8_t i;
/* Init all IO for keyboard */
for (i = 0; i < MAX_LED_NBR; ++i)
{
gpio_set_func(led_io_tbl[i].port,led_io_tbl[i].pin,GPIO_OUTPUT1);
}
return 0;
}
INIT_DEVICE_EXPORT(rt_hw_led_init);
#endif

View File

@@ -0,0 +1,13 @@
#ifndef BOARD_LED_H__
#define BOARD_LED_H__
struct led_io_def
{
enum gpio_port port;
enum gpio_pin pin;
};
void rt_hw_led_off(int led);
void rt_hw_led_on (int led);
#endif

357
bsp/x1000/drivers/dma.c Normal file
View File

@@ -0,0 +1,357 @@
/*
* File : dma.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2015-11-19 Urey the first version
*/
/*********************************************************************************************************
** 头文件
*********************************************************************************************************/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "dma.h"
/*********************************************************************************************************
** 全局变量
*********************************************************************************************************/
/*********************************************************************************************************
** 宏定义
*********************************************************************************************************/
#define DMA_DEBUG 0
#if DMA_DEBUG
#include <stdio.h>
#define DMA_DBG(...) rt_kprintf("[DMA]"),rt_kprintf(__VA_ARGS__)
#else
#define DMA_DBG(...)
#endif
#define __DMA_CHANNEL_RESET(dmac) do { \
if (dmac->ops && dmac->ops->reset) {\
dmac->ops->reset(dmac); \
} \
} while (0)
#define __DMA_CHANNEL_TRANS(dmac, message, ret) do { \
if (dmac->ops && dmac->ops->trans) { \
ret = dmac->ops->trans(dmac, message); \
} \
} while (0)
#define __DMA_CHANNEL_STATUS(ch, ret) do { \
if (dmac->ops && dmac->ops->status) {\
ret = dmac->ops->status(dmac); \
} \
} while (0)
/*********************************************************************************************************
** 全局变量
*********************************************************************************************************/
struct rt_dma_channel _g_dma_chan_head;
static rt_bool_t rt_dma_init_flag = RT_FALSE;
/*********************************************************************************************************
** 函数名称: _dma_init
** 功能描述: 初始化 DMA
** 输  入: void
** 返 回: void
** 备 注: NONE
*********************************************************************************************************/
void _dma_init (void)
{
_g_dma_chan_head.ch = -1;
rt_list_init(&(_g_dma_chan_head.list));
} /* _dma_init */
/*********************************************************************************************************
** 函数名称: rt_dma_drv_install
** 功能描述: DMA 通用驱动程序安装
** 输  入: rt_uint32_t channel,RT_DMA_FUNCS* funcs,rt_size_t maxBurstBytes
** 返 回: rt_err_t
** 备 注: NONE
*********************************************************************************************************/
rt_err_t rt_dma_drv_install(struct rt_dma_channel *dmac, struct dma_ops *ops,struct dma_config *config,void* user_data)
{
/* 参数检查 */
RT_ASSERT(dmac != RT_NULL);
if(rt_dma_init_flag == RT_FALSE)
{
rt_dma_init_flag = RT_TRUE;
_dma_init();
}
if(ops == RT_NULL)
{
DMA_DBG("dma param invalid.\r\n");
return -RT_EIO;
}
/* 挂载到通道列表 */
rt_list_insert_after(&(_g_dma_chan_head.list),&(dmac->list));
dmac->ops = ops;
if(config != RT_NULL)
{
dmac->config.direction = config->direction;
dmac->config.src_addr_width = config->src_addr_width;
dmac->config.src_maxburst = config->src_maxburst;
dmac->config.dst_addr_width = config->dst_addr_width;
dmac->config.dst_maxburst = config->dst_maxburst;
}
dmac->user_data = user_data;
rt_memset(dmac->msg_list,0,RT_DMA_MAX_NODES * sizeof(struct dma_message));
__DMA_CHANNEL_RESET(dmac);
return RT_EOK;
}
struct rt_dma_channel *rt_dma_get_channel(int id)
{
struct rt_dma_channel *dmac;
struct rt_list_node *node;
for (node = _g_dma_chan_head.list.next; node != &(_g_dma_chan_head.list); node = node->next)
{
dmac = rt_list_entry(node, struct rt_dma_channel, list);
if(dmac->ch == id)
return dmac;
}
return RT_NULL;
}
//
///*********************************************************************************************************
//** 函数名称: rt_dma_flush
//** 功能描述: 删除所有被延迟处理的传输请求 (不调用回调函数)
//** 输  入: rt_uint32_t channel
//** 返 回: rt_err_t
//** 备 注: NONE
//*********************************************************************************************************/
//rt_err_t rt_dma_flush (struct rt_dma_channel *dmac)
//{
// rt_size_t data_size;
// struct dma_message *last_message,*message;
// rt_uint16_t next_index;
// /* 参数检查 */
// RT_ASSERT(dmac != RT_NULL);
//
//
// next_index = dmac->get_index + 1;
// if(next_index >= RT_DMA_MAX_NODES)
// next_index = 0;
//
//
//// while (rt_data_queue_pop(&(dmac->tmsg_queue),(const void **)&message, &data_size, 0) == RT_EOK)
//// {
//// /* 清除 DMA消息 */
////// if(message->release_cb != RT_NULL)
////// message->release_cb(dmac,message);
//// }
//
// __DMA_CHANNEL_RESET(dmac);
//
//// dmac->tmsg_actived = RT_FALSE;
// return RT_EOK;
//}
/*********************************************************************************************************
** 函数名称: rt_dma_trans_message
** 功能描述: 添加 一个DMA请求
** 输  入: rt_uint32_t channel DMA_MSG *pMsg
** 返 回: rt_err_t
** 备 注: NONE
*********************************************************************************************************/
rt_err_t rt_dma_trans_message (struct rt_dma_channel *dmac,struct dma_message* message)
{
rt_base_t level;
rt_err_t result;
rt_uint16_t next_index;
struct dma_message *msg_node;
/* 参数检查 */
RT_ASSERT(dmac != RT_NULL);
RT_ASSERT(message != RT_NULL);
RT_ASSERT(message->t_size <= (64 * 1024));
if(message->t_size == 0)
{
if (dmac->complete != RT_NULL)
{
dmac->complete(dmac, message);
}
return RT_EOK;
}
//判断传输队列是否满
next_index = dmac->put_index + 1;
if(next_index >= RT_DMA_MAX_NODES)
next_index = 0;
if(next_index == dmac->get_index)
return -RT_ENOMEM;
level = rt_hw_interrupt_disable();
msg_node = &(dmac->msg_list[dmac->put_index]);
dmac->put_index = next_index;
//保存message
rt_memcpy(msg_node,message,sizeof(struct dma_message));
next_index = dmac->get_index + 1;
if(next_index >= RT_DMA_MAX_NODES)
next_index = 0;
/* check message list whether is empty */
if(next_index == dmac->put_index)
{
rt_hw_interrupt_enable(level);
/* Make a DMA transfer */
if(dmac->start != RT_NULL)
dmac->start(dmac,message);
do{
int ret;
__DMA_CHANNEL_TRANS(dmac, message, ret); /* 初始化传输诸元 */
(void)ret;
} while (0);
}
else
{
rt_hw_interrupt_enable(level);
}
return RT_EOK;
}
/*********************************************************************************************************
** 函数名称: rt_dma_configture
** 功能描述: DMA 通道配置
** 输  入: struct rt_dma_channel *dmac,struct dma_config *config
** 返 回: rt_err_t
** 备 注: NONE
*********************************************************************************************************/
rt_err_t rt_dma_configture (struct rt_dma_channel *dmac,struct dma_config *config)
{
/* 参数检查 */
RT_ASSERT(dmac != RT_NULL);
RT_ASSERT(config != RT_NULL);
dmac->config.direction = config->direction;
dmac->config.src_addr_width = config->src_addr_width;
dmac->config.src_maxburst = config->src_maxburst;
dmac->config.dst_addr_width = config->dst_addr_width;
dmac->config.dst_maxburst = config->dst_maxburst;
__DMA_CHANNEL_RESET(dmac);
return RT_EOK;
} /* rt_dma_configture */
/*********************************************************************************************************
** 函数名称: rt_dma_get_current_message
** 功能描述: DMA 获取当前传输的消息句柄
** 输  入: struct rt_dma_channel *dmac
** 返 回: struct dma_message *
** 备 注: NONE
*********************************************************************************************************/
struct dma_message * rt_dma_get_current_message (struct rt_dma_channel *dmac)
{
rt_base_t level;
struct dma_message *message;
level = rt_hw_interrupt_disable();
message = &(dmac->msg_list[dmac->get_index]);
rt_hw_interrupt_enable(level);
return message;
} /* rt_dma_get_current_message */
/*********************************************************************************************************
** 函数名称: rt_dma_contex_service
** 功能描述: DMA 中断服务
** 输  入: rt_uint32_t channel
** 返 回: rt_err_t
** 备 注: global
*********************************************************************************************************/
rt_err_t rt_dma_contex_service (struct rt_dma_channel *dmac,rt_uint32_t event)
{
rt_base_t level;
rt_size_t data_size;
struct dma_message *last_message,*message;
rt_uint16_t next_index;
/* 参数检查 */
RT_ASSERT(dmac != RT_NULL);
switch (event)
{
case RT_DMA_EVENT_COMPLETE:
next_index = dmac->get_index + 1;
if(next_index >= RT_DMA_MAX_NODES)
next_index = 0;
level = rt_hw_interrupt_disable();
/* 优先发送 缓冲区中的消息 */
last_message = &(dmac->msg_list[dmac->get_index]);
dmac->get_index = next_index;
if(dmac->get_index != dmac->put_index)
{
/* 队列中有消息未发送,优先处理 */
message = &(dmac->msg_list[dmac->get_index]);
rt_hw_interrupt_enable(level);
/* Make a DMA transfer */
if(dmac->start != RT_NULL)
dmac->start(dmac,message);
do{
int ret;
__DMA_CHANNEL_TRANS(dmac, message, ret); /* 初始化传输诸元 */
(void)ret;
} while (0);
}
else
{
rt_hw_interrupt_enable(level);
}
/* 处理上一个消息的回调函数 */
if (dmac->complete != RT_NULL)
{
dmac->complete(dmac, last_message);
}
break;
default:
break;
}
return RT_EOK;
}

155
bsp/x1000/drivers/dma.h Normal file
View File

@@ -0,0 +1,155 @@
/*
* File : dma.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* 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.
*
* Change Logs:
* Date Author Notes
* 2015-11-19 Urey the first version
*/
#ifndef _DMA_H_
#define _DMA_H_
/*********************************************************************************************************
** 头文件
*********************************************************************************************************/
#include <stdlib.h>
#include <rtdef.h>
#include <rtthread.h>
#ifdef __cplusplus
extern "C"{
#endif
#define RT_DMA_CHANNEL(n) (n)
#ifndef RT_DMA_MAX_NODES
# define RT_DMA_MAX_NODES 8
#endif
/*********************************************************************************************************
** DMA 状态定义
*********************************************************************************************************/
#define RT_DMA_STATUS_IDLE 0 /* DMA 处于空闲模式 */
#define RT_DMA_STATUS_BUSY 1 /* DMA 处于正在工作 */
#define RT_DMA_STATUS_ERROR 2 /* DMA 处于错误状态 */
/*********************************************************************************************************
** DMA 地址方向定义
*********************************************************************************************************/
#define RT_DMA_ADDR_INC 0 /* 地址增长方式 */
#define RT_DMA_ADDR_FIX 1 /* 地址不变 */
#define RT_DMA_ADDR_DEC 2 /* 地址减少方式 */
/*********************************************************************************************************
** DMA 传输方向定义
*********************************************************************************************************/
#define RT_DMA_MEM_TO_MEM 0
#define RT_DMA_MEM_TO_DEV 1
#define RT_DMA_DEV_TO_MEM 2
#define RT_DMA_DEV_TO_DEV 3
#define RT_DMA_TRANS_NONE 4
/*********************************************************************************************************
** DMA 总线宽度
*********************************************************************************************************/
#define RT_DMA_BUSWIDTH_UNDEFINED 0
#define RT_DMA_BUSWIDTH_1_BYTE 1
#define RT_DMA_BUSWIDTH_2_BYTES 2
#define RT_DMA_BUSWIDTH_4_BYTES 4
#define RT_DMA_BUSWIDTH_8_BYTES 8
/*********************************************************************************************************
** DMA 传输 时间
*********************************************************************************************************/
#define RT_DMA_EVENT_COMPLETE 0x01
#define RT_DMA_EVENT_ERROR 0x02
/*********************************************************************************************************
** 数据结构
*********************************************************************************************************/
struct rt_dma_channel;
struct dma_message;
struct dma_config;
struct dma_ops
{
void (*reset)(struct rt_dma_channel *dmac);
rt_size_t (*trans)(struct rt_dma_channel *dmac,struct dma_message *message);
int (*status)(struct rt_dma_channel *dmac);
int (*configure)(struct rt_dma_channel *dmac,struct dma_config *config);
};
struct dma_message
{
rt_uint8_t *src_addr; /* 源端缓冲区地址 */
rt_uint8_t *dst_addr; /* 目的端缓冲区地址 */
rt_uint8_t src_option; /* 源端地址方向控制 */
rt_uint8_t dst_option; /* 目的地址方向控制 */
rt_size_t t_size; /* 传输的字节数 */
rt_uint32_t t_mode; /* 传输模式, 自定义 */
void (*complete_cb)(void *data,void *pbuf);
void *complete_arg;
};
struct dma_config
{
rt_uint32_t direction;
rt_uint32_t src_addr_width;
rt_uint32_t dst_addr_width;
rt_uint32_t src_maxburst;
rt_uint32_t dst_maxburst;
};
struct rt_dma_channel
{
int ch;
rt_list_t list; /* channel list */
struct dma_config config;
struct dma_ops *ops;
struct dma_message msg_list[RT_DMA_MAX_NODES];
rt_uint16_t get_index;
rt_uint16_t put_index;
void (*start)(struct rt_dma_channel *dmac,struct dma_message *msg); /* 启动传输 回调函数 */
void (*complete)(struct rt_dma_channel *dmac,struct dma_message *msg); /* 传输完成 回调函数 */
void *user_data; /* 自定义数据 */
};
/*********************************************************************************************************
** 函数申明
*********************************************************************************************************/
rt_err_t rt_dma_drv_install(struct rt_dma_channel *dmac, struct dma_ops *ops,struct dma_config *config,void* user_data);
struct rt_dma_channel *rt_dma_get_channel(int id);
struct dma_message *rt_dma_get_current_message (struct rt_dma_channel *dmac);
rt_err_t rt_dma_reset (struct rt_dma_channel *dmac);
rt_err_t rt_dma_trans_message (struct rt_dma_channel *dmac,struct dma_message* message);
rt_err_t rt_dma_configture (struct rt_dma_channel *dmac,struct dma_config *config);
rt_err_t rt_dma_contex_service (struct rt_dma_channel *dmac,rt_uint32_t event);
#ifdef __cplusplus
}
#endif
#endif /* _DMA_H_ */

View File

@@ -21,16 +21,16 @@
* Date Author Notes
* 2015-11-19 Urey the first version
*/
#include <string.h>
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <x1000.h>
#include "board.h"
#include "drv_clock.h"
#define DEBUG 0
#if DEBUG
#define PRINT(...) rt_kprintf(__VA_ARGS__)
@@ -834,8 +834,42 @@ const struct clk_selectors audio_selector[] =
[SELECTOR_AUDIO].route = {CLK(EXT1),CLK(SCLKA),CLK(EXT1),CLK(MPLL)},
#undef CLK
};
static int audio_div_apll[64];
static int audio_div_mpll[64];
static int audio_div_apll[64] =
{
8000 , 1 , 126000 ,
11025 , 2 , 182857 ,
12000 , 1 , 84000 ,
16000 , 1 , 63000 ,
22050 , 4 , 182857 ,
24000 , 1 , 42000 ,
32000 , 1 , 31500 ,
44100 , 7 , 160000 ,
48000 , 1 , 21000 ,
88200 , 21 , 240000 ,
96000 , 1 , 10500 ,
176400 , 42 , 240000 ,
192000 , 1 , 5250 ,
0
};
static int audio_div_mpll[64] =
{
8000 , 1 , 75000 ,
11025 , 4 , 217687 ,
12000 , 1 , 50000 ,
16000 , 1 , 37500 ,
22050 , 8 , 217687 ,
24000 , 1 , 25000 ,
32000 , 1 , 18750 ,
44100 , 16 , 217687 ,
48000 , 1 , 12500 ,
88200 , 25 , 170068 ,
96000 , 1 , 6250 ,
176400 , 75 , 255102 ,
192000 , 1 , 3125 ,
0
};
struct cgu_audio_clk
{
@@ -920,13 +954,14 @@ static int get_div_val(int max1,int max2,int machval, int* res1, int* res2)
*res2 = tmp2;
return 0;
}
static int cgu_audio_calculate_set_rate(struct clk* clk, uint32_t rate, uint32_t pid){
static int cgu_audio_calculate_set_rate(struct clk* clk, uint32_t rate, uint32_t pid)
{
int i,m,n,d,sync,tmp_val,d_max,sync_max;
int no = CLK_CGU_AUDIO_NO(clk->flags);
int n_max = cgu_audio_clks[no].maskn >> cgu_audio_clks[no].bitn;
int *audio_div;
if(pid == CLK_ID_MPLL)
{
audio_div = (int*)audio_div_mpll;
@@ -946,7 +981,8 @@ static int cgu_audio_calculate_set_rate(struct clk* clk, uint32_t rate, uint32_t
PRINT("cgu aduio set rate err!\n");
return -1;
}
else{
else
{
m = audio_div[i+1];
if(no == CGU_AUDIO_I2S)
{
@@ -954,7 +990,7 @@ static int cgu_audio_calculate_set_rate(struct clk* clk, uint32_t rate, uint32_t
m*=2;
#endif
d_max = 0x1ff;
tmp_val = audio_div[i+2]/64;
tmp_val = audio_div[i + 2] / 64;
if (tmp_val > n_max)
{
if (get_div_val(n_max, d_max, tmp_val, &n, &d))
@@ -962,8 +998,8 @@ static int cgu_audio_calculate_set_rate(struct clk* clk, uint32_t rate, uint32_t
}
else
{
n = tmp_val;
d = 1;
n = tmp_val / 4;
d = 4;
}
tmp_val = cpm_inl(cgu_audio_clks[no].off)&(~(cgu_audio_clks[no].maskm|cgu_audio_clks[no].maskn));
tmp_val |= (m<<cgu_audio_clks[no].bitm)|(n<<cgu_audio_clks[no].bitn);
@@ -975,8 +1011,9 @@ static int cgu_audio_calculate_set_rate(struct clk* clk, uint32_t rate, uint32_t
{
cgu_audio_clks[no].cache = tmp_val;
}
writel(d - 1,I2S_PRI_DIV);
cpm_outl(0,CPM_I2SCDR1);
writel(d - 1,I2S_PRI_DIV);
}
else if (no == CGU_AUDIO_PCM)
{
@@ -1094,10 +1131,12 @@ static int cgu_audio_set_rate(struct clk *clk, uint32_t rate)
}
else
{
cgu_audio_calculate_set_rate(clk,rate,CLK_ID_MPLL);
if(get_clk_id(clk->parent) == CLK_ID_EXT1)
cgu_audio_set_parent(clk,get_clk_from_id(CLK_ID_MPLL));
clk->parent = get_clk_from_id(CLK_ID_MPLL);
cgu_audio_set_parent(clk,get_clk_from_id(CLK_ID_SCLKA));
cgu_audio_calculate_set_rate(clk,rate,CLK_ID_SCLKA);
clk->parent = get_clk_from_id(CLK_ID_SCLKA);
}
return 0;
}
@@ -1124,9 +1163,6 @@ void init_cgu_audio_clk(struct clk *clk)
{
int no,id,tmp_val;
rt_memcpy(audio_div_apll,(void*)(0xf4000000),256);
rt_memcpy(audio_div_mpll,(void*)(0xf4000000)+256,256);
if (clk->flags & CLK_FLG_PARENT)
{
id = CLK_PARENT(clk->flags);
@@ -1461,3 +1497,61 @@ int init_all_clk(void)
return 0;
}
INIT_BOARD_EXPORT(init_all_clk);
#ifdef RT_USING_FINSH
#include <finsh.h>
#endif
int clk_dump(int argc, char** argv)
{
// dump = 1;
rt_kprintf("CCLK:%luMHz L2CLK:%luMhz H0CLK:%luMHz H2CLK:%luMhz PCLK:%luMhz\n",
clk_srcs[CLK_ID_CCLK].rate/1000/1000,
clk_srcs[CLK_ID_L2CLK].rate/1000/1000,
clk_srcs[CLK_ID_H0CLK].rate/1000/1000,
clk_srcs[CLK_ID_H2CLK].rate/1000/1000,
clk_srcs[CLK_ID_PCLK].rate/1000/1000);
return 0;
}
MSH_CMD_EXPORT(clk_dump, dump clock debug log);
int clk(int argc, char**argv)
{
uint32_t value;
value = cpm_inl(CPM_CLKGR);
rt_kprintf("CLKGR = 0x%08x\n", value);
value &= ~(1 << 14);
cpm_outl(value, CPM_CLKGR);
value = cpm_inl(CPM_CLKGR);
rt_kprintf("CLKGR = 0x%08x\n", value);
return 0;
}
MSH_CMD_EXPORT(clk, clock information dump);
int uart0_clk(void)
{
uint32_t value;
value = cpm_inl(CPM_CLKGR);
value &= ~(1 << 14);
cpm_outl(value, CPM_CLKGR);
return 0;
}
int uart1_clk(void)
{
uint32_t value;
value = cpm_inl(CPM_CLKGR);
value &= ~(1 << 15);
cpm_outl(value, CPM_CLKGR);
return 0;
}

View File

@@ -27,66 +27,6 @@
#include "board.h"
#define CPM_CPCCR (0x00)
#define CPM_CPCSR (0xd4)
#define CPM_DDRCDR (0x2c)
#define CPM_I2SCDR (0x60)
#define CPM_I2SCDR1 (0x70)
#define CPM_LPCDR (0x64)
#define CPM_MSC0CDR (0x68)
#define CPM_MSC1CDR (0xa4)
#define CPM_USBCDR (0x50)
#define CPM_MACCDR (0x54)
#define CPM_UHCCDR (0x6c)
#define CPM_SFCCDR (0x74)
#define CPM_CIMCDR (0x7c)
#define CPM_PCMCDR (0x84)
#define CPM_PCMCDR1 (0xe0)
#define CPM_MPHYC (0xe8)
#define CPM_INTR (0xb0)
#define CPM_INTRE (0xb4)
#define CPM_DRCG (0xd0)
#define CPM_CPSPPR (0x38)
#define CPM_CPPSR (0x34)
#define CPM_USBPCR (0x3c)
#define CPM_USBRDT (0x40)
#define CPM_USBVBFIL (0x44)
#define CPM_USBPCR1 (0x48)
#define CPM_CPAPCR (0x10)
#define CPM_CPMPCR (0x14)
#define CPM_LCR (0x04)
#define CPM_PSWC0ST (0x90)
#define CPM_PSWC1ST (0x94)
#define CPM_PSWC2ST (0x98)
#define CPM_PSWC3ST (0x9c)
#define CPM_CLKGR (0x20)
#define CPM_MESTSEL (0xec)
#define CPM_SRBC (0xc4)
#define CPM_ERNG (0xd8)
#define CPM_RNG (0xdc)
#define CPM_SLBC (0xc8)
#define CPM_SLPC (0xcc)
#define CPM_OPCR (0x24)
#define CPM_RSR (0x08)
#define LCR_LPM_MASK (0x3)
#define LCR_LPM_SLEEP (0x1)
#define OPCR_ERCS (0x1<<2)
#define OPCR_PD (0x1<<3)
#define OPCR_IDLE (0x1<<31)
#define cpm_inl(off) readl(CPM_BASE + (off))
#define cpm_outl(val,off) writel(val, CPM_BASE + (off))
#define cpm_test_bit(bit,off) (cpm_inl(off) & 0x1<<(bit))
#define cpm_set_bit(bit,off) (cpm_outl((cpm_inl(off) | 0x1<<(bit)),off))
#define cpm_clear_bit(bit,off) (cpm_outl(cpm_inl(off) & ~(0x1 << bit), off))
#define I2S_PRI_DIV 0xb0020030
#define PCM_PRI_DIV 0xb0030014

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