[bsp] add imx6ull smart board bsp (#7716)

This commit is contained in:
Bernard Xiong 2023-06-27 08:20:45 +08:00 committed by GitHub
parent 6c55d81120
commit ce4a9c324d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
139 changed files with 260863 additions and 0 deletions

File diff suppressed because it is too large Load Diff

5
bsp/imx/imx6ull-smart/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.img
*.imx
*.bin
*.elf
*.map

View File

@ -0,0 +1,45 @@
mainmenu "RT-Thread Project Configuration"
config BSP_DIR
string
option env="BSP_ROOT"
default "."
config RTT_DIR
string
option env="RTT_ROOT"
default "../../.."
config PKGS_DIR
string
option env="PKGS_ROOT"
default "packages"
source "$RTT_DIR/Kconfig"
source "$PKGS_DIR/Kconfig"
config SOC_IMX6ULL
bool
select ARCH_ARM_CORTEX_A7
select RT_USING_CACHE
select ARCH_ARM_MMU
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
select RT_USING_FPU
select RT_USING_GIC_V2
default y
if SOC_IMX6ULL
config CPU_MCIMX6Y2CVM05
bool
default y
config FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
depends on RT_USING_CACHE
int
default 1
config FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL
int "Disable Clock control in fsl files"
default 1
endif
source "$BSP_DIR/drivers/Kconfig"

View File

@ -0,0 +1,41 @@
# RT-Thread Smart for i.MX6ULL
这是一份ART-pi smart开发板的BSP支持smart模式也支持传统的RTOS模式
ART-pi smart采用了米尔科技的imx6ull核心板硬件由韦东山团队完成由社区来完成整体的BSP。硬件规格情况如下
![硬件资源](figures/hw_resources.png)
## 如何编译
如果使用smart的模式请使用smart sdk环境然后进入到这个bsp目录执行
```bash
scons
```
进行编译;
如果使用RTOS模式请确保在menuconfig中不选择smart模式然后执行
```bash
scons
```
进行编译。
## 如何运行
* 从eMMC中加载运行
```bash
bootcmd=fatload mmc 1:1 0x80001000 /kernel/rtthread.bin; dcache flush; go 0x80001000
```
* 网络方式启动
```bash
tftp 0x80001000 rtthread.bin
dcache flush
go 0x80001000
```

View File

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

View File

@ -0,0 +1,43 @@
import os
import sys
import rtconfig
import re
RTT_ROOT = os.getenv('RTT_ROOT') or os.path.join('..', '..', '..')
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
TARGET = 'rtthread.' + rtconfig.TARGET_EXT
content = ""
TRACE_CONFIG = ''
with open("rtconfig.h") as f:
for line in f.readlines():
if line.find("RT_BACKTRACE_FUNCTION_NAME") != -1:
for token in line.split(" "):
if re.match(r'RT_BACKTRACE_FUNCTION_NAME$', token, flags=0):
TRACE_CONFIG = " -mpoke-function-name"
DefaultEnvironment(tools=[])
env = Environment(tools = ['mingw'],
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS + TRACE_CONFIG,
CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS + TRACE_CONFIG,
CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS + TRACE_CONFIG,
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
env['ASCOM'] = env['ASPPCOM']
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)
if GetDepend('RT_USING_SMART'):
# use smart link.lds
env['LINKFLAGS'] = env['LINKFLAGS'].replace('link.lds', 'link_smart.lds')
# make a building
DoBuilding(TARGET, objs)

View File

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

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022/01/20 bernard the first version
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <rtthread.h>
#include <msh.h>
int em_init(void)
{
int count = 5;
char *em_cmd = "/services/em.elf &";
while (count --)
{
int fd;
fd = open("/services/em.elf", O_RDONLY);
if (fd >= 0)
{
close(fd);
msh_exec(em_cmd, rt_strlen(em_cmd) + 1);
return 0;
}
else
{
rt_thread_mdelay(500);
}
}
if (count <= 0)
{
printf("open em failed!\n");
}
return -1;
}
INIT_APP_EXPORT(em_init);

View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include <rtthread.h>
#if defined(RT_USING_DFS)
#include <dfs.h>
#include <dfs_fs.h>
#include <dfs_file.h>
#include <ioremap.h>
#include <drv_sdio.h>
#define DBG_TAG "app.filesystem"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
void filesysytem_try_mount(char *device_name, char *mount_point, char *fs_type_name, int mkfs_count)
{
struct statfs fs_stat;
int rc = 0;
LOG_I("mount(\"%s\",\"%s\",\"%s\");", device_name, mount_point, fs_type_name);
if (rt_device_find(device_name) == NULL)
{
LOG_I("%s not find!!!", device_name);
return;
}
mkdir(mount_point, 0);
_remount:
rc = dfs_mount(device_name, mount_point, fs_type_name, 0, 0);
if (rc == 0)
{
LOG_I("mounted %s on %s", device_name, mount_point);
if (dfs_statfs(mount_point, &fs_stat) >= 0)
{
LOG_I("%s size:%d, total: %d, free: %d", mount_point,
fs_stat.f_bsize, fs_stat.f_blocks, fs_stat.f_bfree);
}
}
else
{
if (mkfs_count > 0)
{
LOG_I("[%s]try mkfs -t %s %s ", mkfs_count, fs_type_name, device_name);
dfs_mkfs(fs_type_name, device_name);
mkfs_count--;
goto _remount;
}
LOG_I("mount failed :%d ", rc);
}
}
void filesysytem_try_unmount(char *mount_point)
{
struct stat filestat = {0};
LOG_I("unmount(\"%s\");", mount_point);
if ((dfs_file_stat(mount_point, &filestat) >= 0) && (S_ISDIR(filestat.st_mode)))
{
dfs_unmount(mount_point);
}
}
static void sd_task_entry(void *parameter)
{
volatile unsigned int *IN_STATUS;
IN_STATUS = (volatile unsigned int *)rt_ioremap((void *)0x2190030, 4); // cd status
int change = 0;
while (1)
{
rt_thread_mdelay(200);
change = 0;
if (((*IN_STATUS >> 6) & 0x1) == 1)
{
*IN_STATUS = 0x40;
change = 1;
}
if (((*IN_STATUS >> 7) & 0x1) == 1)
{
*IN_STATUS = (0x80);
change = 2;
}
if (change > 0)
{
LOG_D("sdio host change: %d", change);
mmcsd_wait_cd_changed(0); // clear
host_change(); // send cd change to host
int result = mmcsd_wait_cd_changed(RT_TICK_PER_SECOND);
if (result == MMCSD_HOST_PLUGED)
{
LOG_D("mmcsd change pluged");
filesysytem_try_mount("sd0", "/mnt/sd0", "elm", 0);
}
else if (result == MMCSD_HOST_UNPLUGED)
{
LOG_D("mmcsd change unpluged");
filesysytem_try_unmount("/mnt/sd0");
}
else
{
LOG_I("mmcsd wait_cd_changed %d", result);
}
}
}
}
int sd_task_init(void)
{
rt_thread_t tid;
tid = rt_thread_create("tsdcard", sd_task_entry, RT_NULL,
2048, RT_THREAD_PRIORITY_MAX - 2, 20);
if (tid != RT_NULL)
{
rt_thread_startup(tid);
}
else
{
LOG_E("create sd mount task error!");
}
return RT_EOK;
}
INIT_APP_EXPORT(sd_task_init);
#endif

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022/01/20 bernard the first version
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <rtthread.h>
#ifdef PKG_USING_RW007
#define WIFI_SH_PATH "/sd/wifi.sh"
int rw007_wifi_init(void)
{
if (access(WIFI_SH_PATH, 0) != -1)
{
msh_exec(WIFI_SH_PATH, rt_strlen(WIFI_SH_PATH));
}
else
{
rt_kprintf("%s wi-fi configuration file not exist in sd card!\n", WIFI_SH_PATH);
}
return 0
}
INIT_APP_EXPORT(rw007_wifi_init);
#endif

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/10/7 bernard the first version
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("hello rt-smart\n");
return 0;
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include <rtthread.h>
#ifdef RT_USING_DFS
#include <dfs_fs.h>
#include <dfs_romfs.h>
int mnt_init(void)
{
#ifdef RT_USING_SDIO2
rt_thread_mdelay(500);
int part_id = 0;
if (dfs_mount("emmc0", "/", "elm", 0, (void *)part_id) != 0)
{
rt_kprintf("Dir / emmc mount failed!\n");
return -1;
}
else
{
rt_kprintf("emmc file system initialization done!\n");
}
part_id = 0;
if (dfs_mount("sd0", "/mnt/sd0", "elm", 0, (void *)part_id) != 0)
{
rt_kprintf("Dir /mnt/sd0 mount failed!\n");
return -1;
}
else
{
rt_kprintf("sd0 file system initialization done!\n");
}
#else
rt_thread_mdelay(500);
if (dfs_mount(NULL, "/", "rom", 0, &romfs_root) != 0)
{
rt_kprintf("Dir / mount failed!\n");
return -1;
}
rt_kprintf("file system initialization done!\n");
#endif
return 0;
}
INIT_ENV_EXPORT(mnt_init);
#endif

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/10/7 bernard the first version
*/
#include <dfs_romfs.h>
static const struct romfs_dirent _romfs_root[] = {
{ROMFS_DIRENT_DIR, "bin", RT_NULL, 0},
{ROMFS_DIRENT_DIR, "dev", RT_NULL, 0},
{ROMFS_DIRENT_DIR, "etc", RT_NULL, 0},
{ROMFS_DIRENT_DIR, "mnt", RT_NULL, 0},
};
const struct romfs_dirent romfs_root = {
ROMFS_DIRENT_DIR, "/", (rt_uint8_t *)_romfs_root, sizeof(_romfs_root) / sizeof(_romfs_root[0])};

View File

@ -0,0 +1,242 @@
menu "Platform Driver Configuration"
menu "Select UART Driver"
if RT_USING_SERIAL
config BSP_USING_UART1
bool "Enable UART1"
default y
config BSP_USING_UART2
bool "Enable UART2"
default n
config BSP_USING_UART3
bool "Enable UART3"
default n
config BSP_USING_UART4
bool "Enable UART4"
default n
config BSP_USING_UART5
bool "Enable UART5"
default n
config BSP_USING_UART6
bool "Enable UART6"
default n
config BSP_USING_UART7
bool "Enable UART7"
default n
config BSP_USING_UART8
bool "Enable UART8"
default n
endif
endmenu
menu "Select SPI Driver"
config BSP_USING_SPI
bool "Enable SPI"
select RT_USING_SPI
default n
if BSP_USING_SPI
config BSP_USING_SPI1
bool "Enable SPI1"
default n
config BSP_USING_SPI2
bool "Enable SPI2"
default n
config BSP_USING_SPI3
bool "Enable SPI3"
default y
config BSP_USING_SPI4
bool "Enable SPI4"
default n
endif
endmenu
menu "Select I2C Driver"
config BSP_USING_I2C
bool "Enable I2C"
select RT_USING_I2C
default n
if BSP_USING_I2C
config BSP_USING_I2C1
bool "Enable I2C1"
default n
if BSP_USING_I2C1
config I2C1_BAUD_RATE
int "Set i2c1 baud rate (HZ)"
default 100000
endif
config BSP_USING_I2C2
bool "Enable I2C2"
default n
if BSP_USING_I2C2
config I2C2_BAUD_RATE
int "Set i2c2 baud rate (HZ)"
default 100000
endif
config BSP_USING_I2C3
bool "Enable I2C3"
default n
if BSP_USING_I2C3
config I2C3_BAUD_RATE
int "Set i2c3 baud rate (HZ)"
default 100000
endif
config BSP_USING_I2C4
bool "Enable I2C4"
default n
if BSP_USING_I2C4
config I2C4_BAUD_RATE
int "Set i2c4 baud rate (HZ)"
default 100000
endif
endif
endmenu
menu "Select LCD Driver"
config BSP_USING_LCD
bool "Enable LCD"
select RT_USING_LCD
default y
if BSP_USING_LCD
config BSP_LCD_WIDTH
int "Width of LCD panel"
default 1000
config BSP_LCD_HEIGHT
int "Height of LCD panel"
default 600
config BSP_LCD_VSW
int "value of LCD_VSW"
default 2
config BSP_LCD_VBP
int "value of LCD_VBP"
default 23
config BSP_LCD_VFP
int "value of LCD_VFP"
default 22
config BSP_LCD_HSW
int "value of LCD_HSW"
default 2
config BSP_LCD_HBP
int "value of LCD_HBP"
default 46
config BSP_LCD_HFP
int "value of LCD_HFP"
default 210
config BSP_LCD_PLL_DIV
int "value of PLL DIV"
default 8
endif
endmenu
menu "Select SDHC Driver"
if RT_USING_SDIO
config RT_USING_SDIO1
bool "Enable SDHC1"
default n
config RT_USING_SDIO2
bool "Enable SDHC2"
default n
endif
endmenu
menu "Select RTC Driver"
if RT_USING_RTC
config BSP_USING_ONCHIP_RTC
bool "Enable On-Chip RTC"
default y
endif
endmenu
menu "Select PWM Driver"
config RT_USING_PWM
bool "Enable PWM"
default n
if RT_USING_PWM
config BSP_USING_PWM1
bool "Enable PWM1"
default n
config BSP_USING_PWM2
bool "Enable PWM2"
default n
config BSP_USING_PWM3
bool "Enable PWM3"
default n
config BSP_USING_PWM4
bool "Enable PWM4"
default n
endif
endmenu
menu "Select ADC Driver"
config RT_USING_ADC
bool "Enable ADC"
default n
if RT_USING_ADC
config BSP_USING_ADC1_1
bool "Enable ADC1 CH1"
default n
config BSP_USING_ADC1_2
bool "Enable ADC1 CH2"
default n
config BSP_USING_ADC1_3
bool "Enable ADC1 CH3"
default n
config BSP_USING_ADC1_4
bool "Enable ADC1 CH4"
default n
endif
endmenu
menu "Select WDT Driver"
if RT_USING_WDT
config RT_USING_WDT1
bool "Enable WDT1"
default n
config RT_USING_WDT2
bool "Enable WDT2"
default n
config RT_USING_WDT3
bool "Enable WDT3"
default n
endif
endmenu
menu "Select ENET Driver"
config RT_USING_ENET1
bool "Enable ENET1"
default y
config RT_USING_ENET2
bool "Enable ENET2"
default n
endmenu
menu "Select Wifi Driver"
config RT_USING_WIFI_RW007
bool "Enable wifi RW007"
select BSP_USING_SPI2
select PKG_USING_RW007
select RT_USING_WIFI
default n
if RT_USING_WIFI_RW007
config RW007_DAFAULT_SSID
string "default ssid"
default "rt-thread"
config RW007_DAFAULT_PASSWARD
string "default passward"
default "12345678"
endif
endmenu
menu "Select USB Driver"
config BSP_USING_USB_DEVICE
bool "Enable USB device"
default y
endmenu
endmenu

View File

@ -0,0 +1,22 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('iomux/*.c')
if GetDepend(['BSP_USING_USB_DEVICE']):
src += Glob('usb/device/*.c')
src += Glob('usb/phy/*.c')
list = os.listdir(cwd)
CPPPATH = [cwd]
objs = []
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
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'))
objs = objs + group
Return('objs')

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2012-11-20 Bernard the first version
* 2018-11-22 Jesven add rt_hw_spin_lock
* add rt_hw_spin_unlock
* add smp ipi init
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdbg.h>
#include "board.h"
#include "mm_aspace.h"
#include <mmu.h>
#ifdef RT_USING_SMART
#include <page.h>
#include <lwp_arch.h>
#endif
#ifdef RT_USING_SMART
extern size_t MMUTable[];
struct mem_desc platform_mem_desc[] = { /* 100ask_imx6ull ddr 512M */
{KERNEL_VADDR_START, KERNEL_VADDR_START + 0x1FFFFFFF, (rt_size_t)ARCH_MAP_FAILED, NORMAL_MEM}
};
#else
struct mem_desc platform_mem_desc[] = {
{0x00000000, 0x80000000, 0x00000000, DEVICE_MEM},
{0x80000000, 0xFFF00000, 0x80000000, NORMAL_MEM}
};
#endif
const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
void idle_wfi(void)
{
asm volatile ("wfi");
}
/**
* This function will initialize board
*/
#ifdef RT_USING_SMART
rt_region_t init_page_region = {
(uint32_t)PAGE_START,
(uint32_t)PAGE_END,
};
#endif
int board_reboot(int argc, char **argv)
{
wdog_config_t config;
SRC_Type *src = (SRC_Type*)g_src_vbase;
WDOG_Type *wdog = (WDOG_Type*)g_wdog1_vbase;
LOG_E("resetting ...\n");
rt_hw_ms_delay(50);
src->SCR &= ~SRC_SCR_WARM_RESET_ENABLE_MASK;
CLOCK_EnableClock(kCLOCK_Wdog1);
WDOG_GetDefaultConfig(&config);
config.timeoutValue = 0x00u;
WDOG_Init(wdog, &config);
while (1)
{
//waiting...
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(board_reboot, reboot, reboot system);
void assert_handler(const char *ex_string, const char *func, rt_size_t line)
{
volatile char dummy = 0;
extern int list_thread(void);
extern void rt_backtrace(void);
list_thread();
rt_backtrace();
rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex_string, func, line);
while (dummy == 0)
;
}
#define PUTC(periph, ch) \
do { \
while (0 == (periph->USR2 & UART_USR2_TXDC_MASK)); \
periph->UTXD = ch; \
} while (0)
void rt_hw_board_init(void)
{
#ifdef RT_USING_SMART
rt_hw_mmu_map_init(&rt_kernel_space, (void*)0xf0000000, 0x10000000, MMUTable, PV_OFFSET);
rt_page_init(init_page_region);
rt_hw_mmu_ioremap_init(&rt_kernel_space, (void*)0xf0000000, 0x10000000);
arch_kuser_init(&rt_kernel_space, (void*)0xffff0000);
#else
rt_hw_mmu_map_init(&rt_kernel_space, (void*)0x80000000, 0x10000000, MMUTable, 0);
rt_hw_mmu_ioremap_init(&rt_kernel_space, (void*)0x80000000, 0x10000000);
#endif
/* initialize system heap */
rt_system_heap_init(HEAP_BEGIN, HEAP_END);
/* initialize hardware interrupt */
rt_hw_interrupt_init();
SystemAddressMapping();
SystemClockInit();
rt_components_board_init();
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
rt_thread_idle_sethook(idle_wfi);
rt_assert_set_hook(assert_handler);
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef __BOARD_H__
#define __BOARD_H__
#include <rtconfig.h>
#include "imx6ull.h"
#include "mmu.h"
#if defined(__CC_ARM)
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN ((void*)&Image$$RW_IRAM1$$ZI$$Limit)
#elif defined(__GNUC__)
extern int __bss_end;
#define HEAP_BEGIN ((void*)&__bss_end)
#endif
#ifdef RT_USING_SMART
#define HEAP_END (void*)(KERNEL_VADDR_START + 16 * 1024 * 1024)
#define PAGE_START HEAP_END
#define PAGE_END (void*)(KERNEL_VADDR_START + 128 * 1024 * 1024)
#else
#define HEAP_END (void*)(0x80000000 + 64 * 1024 * 1024)
#endif
/*
* memory map for peripherals
*/
/*
start addr - end addr , size
0x0090_0000 - 0x0091_FFFF, 128KB, OCRAM
0x0200_0000 - 0x020F_FFFF, 1MB, AIPS-1
0x0210_0000 - 0x021F_FFFF, 1MB, AIPS-2
0x0220_0000 - 0x022F_FFFF, 1MB, AIPS-3
*/
void rt_hw_board_init(void);
#endif

View File

@ -0,0 +1,235 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-20 Lyons first version
* 2021-06-24 RiceChen add spi and lcd clock config
*/
#include "board.h"
#include "fsl_clock.h"
#define _K_GPT_LOAD_VALUE RT_UINT32_MAX
/* only used by MCIMX6Y2.h */
uint32_t *g_ccm_vbase = (uint32_t*)IMX6ULL_CCM_BASE;
uint32_t *g_ccm_analog_vbase = (uint32_t*)IMX6ULL_CCM_ANALOGY_BASE;
uint32_t *g_pmu_vbase = (uint32_t*)IMX6ULL_PMU_BASE;
uint32_t g_usbphy1_base = IMX6ULL_USBPHY1_BASE;
uint32_t g_usbphy2_base = IMX6ULL_USBPHY2_BASE;
uint32_t g_usb1_base = IMX6ULL_USB1_BASE;
uint32_t g_usb2_base = IMX6ULL_USB2_BASE;
uint32_t g_usb_analog_base = IMX6ULL_USB_ANALOG_BASE;
/* used by all files */
uint32_t *g_iomuxc_vbase = (uint32_t*)IMX6ULL_IOMUXC_BASE;
uint32_t *g_iomuxc_snvs_vbase = (uint32_t*)IMX6ULL_IOMUXC_SNVS_BASE;
uint32_t *g_src_vbase = (uint32_t*)IMX6ULL_SRC_BASE;
uint32_t *g_wdog1_vbase = (uint32_t*)IMX6ULL_WATCHDOG1_BASE;
uint32_t *g_snvs_vbase = (uint32_t*)IMX6ULL_SNVS_BASE;
_internal_rw uint32_t *_s_gpt1_vbase = (uint32_t*)IMX6ULL_GPT1_BASE;
static void _clk_enable( CCM_Type *base )
{
base->CCGR0 = 0XFFFFFFFF;
base->CCGR1 = 0XFFFFFFFF;
base->CCGR2 = 0XFFFFFFFF;
base->CCGR3 = 0XFFFFFFFF;
base->CCGR4 = 0XFFFFFFFF;
base->CCGR5 = 0XFFFFFFFF;
base->CCGR6 = 0XFFFFFFFF;
}
void BOARD_BootClockRUN(void)
{
rt_uint32_t reg_value;
/* Boot ROM did initialize the XTAL, here we only sets external XTAL OSC freq */
CLOCK_SetXtalFreq(24000000U);
CLOCK_SetRtcXtalFreq(32768U);
/*
* ARM_CLK from 'pll1_sw_clk', whitch from 'pll1_main_clk' or 'step_clk'
* if edit 'pll1_main_clk', switch to 'step_clk' first
*/
reg_value = CCM->CCSR;
if (0 == (reg_value & CCM_CCSR_PLL1_SW_CLK_SEL_MASK)) //if sel 'pll1_main_clk'
{
reg_value &= ~CCM_CCSR_STEP_SEL_MASK;
reg_value |= CCM_CCSR_STEP_SEL(0); //sel 'osc_clk(24M)'
reg_value |= CCM_CCSR_PLL1_SW_CLK_SEL(1); //sel 'step_clk'
CCM->CCSR = reg_value;
}
/*
* set PLL1(ARM PLL) at 1056MHz
* set ARM_CLK at 528MHz
* PLL output frequency = Fref * DIV_SEL / 2
* = 24M * DIV_SEL / 2 = 1056M
*/
CCM_ANALOG->PLL_ARM = CCM_ANALOG_PLL_ARM_ENABLE(1)
| CCM_ANALOG_PLL_ARM_DIV_SELECT(88);
reg_value = CCM->CCSR;
reg_value &= ~CCM_CCSR_PLL1_SW_CLK_SEL_MASK;
reg_value |= CCM_CCSR_PLL1_SW_CLK_SEL(0); //resel 'pll1_main_clk'
CCM->CCSR = reg_value;
CCM->CACRR = CCM_CACRR_ARM_PODF(1); //'CACRR[ARM_PODF]=0b001' divide by 2
/*
* set PLL2(System PLL) at fixed 528MHz
* PLL2_PFD0: 528M * 18 / FRAC
* PLL2_PFD1: 528M * 18 / FRAC
* PLL2_PFD2: 528M * 18 / FRAC
* PLL2_PFD3: 528M * 18 / FRAC
*/
reg_value = CCM_ANALOG->PFD_528;
reg_value &= ~0x3F3F3F3F;
reg_value |= CCM_ANALOG_PFD_528_SET_PFD0_FRAC(27); //27: 352MHz
reg_value |= CCM_ANALOG_PFD_528_SET_PFD1_FRAC(16); //16: 594MHz
reg_value |= CCM_ANALOG_PFD_528_SET_PFD2_FRAC(24); //24: 396MHz
reg_value |= CCM_ANALOG_PFD_528_SET_PFD3_FRAC(32); //32: 297MHz
CCM_ANALOG->PFD_528 = reg_value;
/*
* set PLL3(USB PLL) at fixed 480MHz
* PLL3_PFD0: 480M * 18 / FRAC
* PLL3_PFD1: 480M * 18 / FRAC
* PLL3_PFD2: 480M * 18 / FRAC
* PLL3_PFD3: 480M * 18 / FRAC
*/
reg_value = CCM_ANALOG->PFD_480;
reg_value &= ~0x3F3F3F3F;
reg_value |= CCM_ANALOG_PFD_480_SET_PFD0_FRAC(12); //12: 720MHz
reg_value |= CCM_ANALOG_PFD_480_SET_PFD1_FRAC(16); //16: 540MHz
reg_value |= CCM_ANALOG_PFD_480_SET_PFD2_FRAC(17); //17: 508.24MHz
reg_value |= CCM_ANALOG_PFD_480_SET_PFD3_FRAC(19); //19: 457.74MHz
CCM_ANALOG->PFD_480 = reg_value;
/*
* set PERCLK_CLK at 66MHz from IPG_CLK
*/
reg_value = CCM->CSCMR1;
reg_value &= ~CCM_CSCMR1_PERCLK_CLK_SEL_MASK;
reg_value |= CCM_CSCMR1_PERCLK_CLK_SEL(0); //sel IPG_CLK
reg_value &= ~CCM_CSCMR1_PERCLK_PODF_MASK;
reg_value |= CCM_CSCMR1_PERCLK_PODF(0); //'CSCMR1[PERCLK_PODF]=0b000000' divide by 1
CCM->CSCMR1 = reg_value;
CLOCK_DeinitAudioPll();
CLOCK_DeinitVideoPll();
CLOCK_DeinitEnetPll();
/* Configure UART divider to default */
CLOCK_SetMux(kCLOCK_UartMux, 0); /* Set UART source to PLL3 80M */
CLOCK_SetDiv(kCLOCK_UartDiv, 0); /* Set UART divider to 1 */
/* Configure ECSPI divider to default */
CLOCK_SetMux(kCLOCK_EcspiMux, 0); /* Set ECSPI source to PLL3 60M */
CLOCK_SetDiv(kCLOCK_EcspiDiv, 0); /* Set ECSPI divider to 1 */
/* Set LCDIF_PRED. */
CLOCK_SetDiv(kCLOCK_Lcdif1PreDiv, 2);
/* Set LCDIF_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_Lcdif1Div, 4);
/* Set Lcdif pre clock source. */
CLOCK_SetMux(kCLOCK_Lcdif1PreMux, 2);
CLOCK_SetMux(kCLOCK_Lcdif1Mux, 0);
}
void BOARD_DelayInit(void)
{
GPT_Type *_GPT = (GPT_Type*)_s_gpt1_vbase;
_GPT->CR = 0;
_GPT->CR = GPT_CR_SWR(1);
while (_GPT->CR & GPT_CR_SWR_MASK);
/*
* 000 No clock
* 001 derive clock from ipg_clk
* 010 derive clock from ipg_clk_highfreq
* 011 derive clock from External Clock
* 100 derive clock from ipg_clk_32k
* 101 derive clock from ipg_clk_24M
*/
_GPT->CR = GPT_CR_CLKSRC(0x1);
_GPT->PR = GPT_PR_PRESCALER(65); //Set GPT1 Clock to 66MHz/66 = 1MHz
_GPT->OCR[0] = GPT_OCR_COMP(_K_GPT_LOAD_VALUE);
_GPT->CR |= GPT_CR_EN(1);
}
//execution before SystemClockInit called
void SystemAddressMapping(void)
{
g_ccm_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_ccm_vbase);
g_ccm_analog_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_ccm_analog_vbase);
g_pmu_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_pmu_vbase);
g_iomuxc_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_iomuxc_vbase);
g_iomuxc_snvs_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_iomuxc_snvs_vbase);
g_src_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_src_vbase);
g_wdog1_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_wdog1_vbase);
g_snvs_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_snvs_vbase);
_s_gpt1_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)_s_gpt1_vbase);
g_usbphy1_base = (uint32_t)platform_get_periph_vaddr((rt_uint32_t)g_usbphy1_base);
g_usbphy2_base = (uint32_t)platform_get_periph_vaddr((rt_uint32_t)g_usbphy2_base);
g_usb1_base = (uint32_t)platform_get_periph_vaddr((rt_uint32_t)g_usb1_base);
g_usb2_base = (uint32_t)platform_get_periph_vaddr((rt_uint32_t)g_usb2_base);
g_usb_analog_base = (uint32_t)platform_get_periph_vaddr((rt_uint32_t)g_usb_analog_base);
}
void SystemClockInit(void)
{
BOARD_BootClockRUN();
BOARD_DelayInit();
_clk_enable(CCM);
}
void rt_hw_us_delay(uint32_t us)
{
GPT_Type *_GPT = (GPT_Type*)_s_gpt1_vbase;
rt_uint64_t old_cnt, new_cnt;
rt_uint64_t total = 0;
old_cnt = _GPT->CNT;
while (1)
{
new_cnt = _GPT->CNT;
if (old_cnt != new_cnt)
{
if (new_cnt > old_cnt)
{
total += (new_cnt - old_cnt);
} else {
total += (new_cnt + _K_GPT_LOAD_VALUE - old_cnt);
}
old_cnt = new_cnt;
if (total >= us)
break;
}
}
}
void rt_hw_ms_delay(uint32_t ms)
{
while (ms--)
{
rt_hw_us_delay(1000);
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-20 Lyons first version
*/
#ifndef __BSP_CLOCK_H__
#define __BSP_CLOCK_H__
extern uint32_t *g_iomuxc_vbase;
extern uint32_t *g_iomuxc_snvs_vbase;
extern uint32_t *g_src_vbase;
extern uint32_t *g_wdog1_vbase;
extern uint32_t *g_snvs_vbase;
void SystemAddressMapping(void);
void SystemClockInit(void);
void rt_hw_us_delay(uint32_t us);
void rt_hw_ms_delay(uint32_t ms);
#endif //#ifndef __BSP_CLOCK_H__

View File

@ -0,0 +1,244 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-04-28 tyustli first version
*
*/
#include <rtthread.h>
#define RT_USING_ADC
#ifdef RT_USING_ADC
#define LOG_TAG "drv.adc"
#include <drv_log.h>
#include <rtdevice.h>
#include <ioremap.h>
#include "fsl_adc.h"
#include "drv_adc.h"
#include <drv_common.h>
#include <drivers/adc.h>
static rt_err_t imx6ull_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
{
return RT_EOK;
}
static rt_err_t imx6ull_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
{
adc_channel_config_t adc_channel;
ADC_Type *base;
base = (ADC_Type *)(device->parent.user_data);
adc_channel.channelNumber = channel;
adc_channel.enableInterruptOnConversionCompleted = 0;
ADC_SetChannelConfig(base, 0, &adc_channel);
while (0U == ADC_GetChannelStatusFlags(base, 0))
{
continue;
}
*value = ADC_GetChannelConversionValue(base, 0);
return RT_EOK;
}
#if defined(BSP_USING_ADC1_1) || defined(BSP_USING_ADC1_2) || defined(BSP_USING_ADC1_3) || defined(BSP_USING_ADC1_4)
static struct rt_adc_ops imx6ull_adc_ops =
{
.enabled = imx6ull_adc_enabled,
.convert = imx6ull_adc_convert,
};
#endif
int imx6ull_adc_gpio_init(void)
{
#ifdef BSP_USING_ADC1_1
do {
struct imx6ull_iomuxc gpio;
uint32_t pin_fun_id[5]={IOMUXC_GPIO1_IO01_GPIO1_IO01};
gpio.muxRegister = pin_fun_id[0];
gpio.muxMode = pin_fun_id[1];
gpio.inputRegister = pin_fun_id[2];
gpio.inputDaisy = pin_fun_id[3];
gpio.configRegister = pin_fun_id[4];
gpio.inputOnfield = 0;
gpio.configValue = IOMUXC_SW_PAD_CTL_PAD_DSE(2U) | IOMUXC_SW_PAD_CTL_PAD_SPEED(2U);
imx6ull_gpio_init(&gpio);
}while(0);
#endif
#ifdef BSP_USING_ADC1_2
do {
struct imx6ull_iomuxc gpio;
uint32_t pin_fun_id[5]={IOMUXC_GPIO1_IO02_GPIO1_IO02};
gpio.muxRegister = pin_fun_id[0];
gpio.muxMode = pin_fun_id[1];
gpio.inputRegister = pin_fun_id[2];
gpio.inputDaisy = pin_fun_id[3];
gpio.configRegister = pin_fun_id[4];
gpio.inputOnfield = 0;
gpio.configValue = IOMUXC_SW_PAD_CTL_PAD_DSE(2U) | IOMUXC_SW_PAD_CTL_PAD_SPEED(2U);
imx6ull_gpio_init(&gpio);
}while(0);
#endif
#ifdef BSP_USING_ADC1_3
do {
struct imx6ull_iomuxc gpio;
uint32_t pin_fun_id[5]={IOMUXC_GPIO1_IO03_GPIO1_IO03};
gpio.muxRegister = pin_fun_id[0];
gpio.muxMode = pin_fun_id[1];
gpio.inputRegister = pin_fun_id[2];
gpio.inputDaisy = pin_fun_id[3];
gpio.configRegister = pin_fun_id[4];
gpio.inputOnfield = 0;
gpio.configValue = IOMUXC_SW_PAD_CTL_PAD_DSE(2U) | IOMUXC_SW_PAD_CTL_PAD_SPEED(2U);
imx6ull_gpio_init(&gpio);
}while(0);
#endif
#ifdef BSP_USING_ADC1_4
do {
struct imx6ull_iomuxc gpio;
uint32_t pin_fun_id[5]={IOMUXC_GPIO1_IO04_GPIO1_IO04};
gpio.muxRegister = pin_fun_id[0];
gpio.muxMode = pin_fun_id[1];
gpio.inputRegister = pin_fun_id[2];
gpio.inputDaisy = pin_fun_id[3];
gpio.configRegister = pin_fun_id[4];
gpio.inputOnfield = 0;
gpio.configValue = IOMUXC_SW_PAD_CTL_PAD_DSE(2U) | IOMUXC_SW_PAD_CTL_PAD_SPEED(2U);
imx6ull_gpio_init(&gpio);
}while(0);
#endif
return 0;
}
int rt_hw_adc_init(void)
{
rt_err_t ret = RT_EOK;
imx6ull_adc_gpio_init();
#if defined(BSP_USING_ADC1_1) || defined(BSP_USING_ADC1_2) || defined(BSP_USING_ADC1_3) || defined(BSP_USING_ADC1_4)
static adc_config_t ADC1_config_value;
static struct rt_adc_device adc1_device;
ADC_Type *adc1_base;
adc1_base = (ADC_Type *)rt_ioremap((void*)ADC1, 0x1000);
ADC_GetDefaultConfig(&ADC1_config_value);
ADC_Init(adc1_base, &ADC1_config_value);
ADC_DoAutoCalibration(adc1_base);
ret = rt_hw_adc_register(&adc1_device, "adc1", &imx6ull_adc_ops, adc1_base);
if (ret != RT_EOK)
{
LOG_E("register adc1 device failed error code = %d\n", ret);
}
#endif
return ret;
}
INIT_DEVICE_EXPORT(rt_hw_adc_init);
void set_adc_default(void *parameter)
{
int result = 0;
result = result;
#ifdef BSP_USING_ADC1_1
do {
struct rt_adc_device *device = RT_NULL;
device = (struct rt_adc_device *)rt_device_find("adc1");
if (!device)
{
result = -RT_EIO;
return;
}
result = rt_adc_enable(device, 1);
result = rt_adc_read(device, 1);
rt_kprintf("adc ch1 read result is %d\n",result);
} while(0);
#endif
#ifdef BSP_USING_ADC1_2
do {
struct rt_adc_device *device = RT_NULL;
device = (struct rt_adc_device *)rt_device_find("adc1");
if (!device)
{
result = -RT_EIO;
return;
}
result = rt_adc_enable(device, 2);
result = rt_adc_read(device, 2);
rt_kprintf("adc ch2 read result is %d\n",result);
} while(0);
#endif
#ifdef BSP_USING_ADC1_3
do {
struct rt_adc_device *device = RT_NULL;
device = (struct rt_adc_device *)rt_device_find("adc1");
if (!device)
{
result = -RT_EIO;
return;
}
result = rt_adc_enable(device, 3);
result = rt_adc_read(device, 3);
rt_kprintf("adc ch3 read result is %d\n",result);
} while(0);
#endif
#ifdef BSP_USING_ADC1_4
do {
struct rt_adc_device *device = RT_NULL;
device = (struct rt_adc_device *)rt_device_find("adc1");
if (!device)
{
result = -RT_EIO;
return;
}
result = rt_adc_enable(device, 4);
result = rt_adc_read(device, 4);
rt_kprintf("adc ch4 read result is %d\n",result);
} while(0);
#endif
}
static int set_adc_init(void)
{
rt_thread_t tid = rt_thread_create("adc_loop", set_adc_default, RT_NULL, 1024, 16, 20);
RT_ASSERT(tid != RT_NULL);
rt_thread_startup(tid);
return(RT_EOK);
}
INIT_APP_EXPORT(set_adc_init);
#endif /* BSP_USING_ADC */

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-04-20 Lee the first version.
*/
#ifndef DRV_ADC_H__
#define DRV_ADC_H__
#include <rtdevice.h>
int rt_hw_adc_init(void);
#endif /* DRV_ADC_H__ */

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-11 RiceChen the first version
*
*/
#include <rthw.h>
#include <rtdevice.h>
#include "board.h"
#include "mmu.h"
#include "ioremap.h"
#include "fsl_iomuxc.h"
#include "drv_common.h"
void *imx6ull_get_periph_vaddr(rt_uint32_t paddr)
{
return rt_ioremap((void *)paddr, sizeof(sizeof(rt_uint32_t)));
}
void *imx6ull_get_periph_paddr(rt_uint32_t vaddr)
{
return rt_kmem_v2p((void *)vaddr);
}
void imx6ull_gpio_init(const struct imx6ull_iomuxc *gpio)
{
rt_uint32_t mux_reg_vaddr = 0;
rt_uint32_t input_reg_vaddr = 0;
rt_uint32_t config_reg_vaddr = 0;
mux_reg_vaddr = (rt_uint32_t)(gpio->muxRegister ? (rt_uint32_t)imx6ull_get_periph_vaddr(gpio->muxRegister) : gpio->muxRegister);
input_reg_vaddr = (rt_uint32_t)(gpio->inputRegister ? (rt_uint32_t)imx6ull_get_periph_vaddr(gpio->inputRegister) : gpio->inputRegister);
config_reg_vaddr = (rt_uint32_t)(gpio->configRegister ? (rt_uint32_t)imx6ull_get_periph_vaddr(gpio->configRegister) : gpio->configRegister);
IOMUXC_SetPinMux(mux_reg_vaddr, gpio->muxMode, input_reg_vaddr, gpio->inputDaisy, config_reg_vaddr, gpio->inputOnfield);
IOMUXC_SetPinConfig(mux_reg_vaddr, gpio->muxMode, input_reg_vaddr, gpio->inputDaisy, config_reg_vaddr, gpio->configValue);
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-11 RiceChen the first version
*
*/
#ifndef __DRV_COMMON_H__
#define __DRV_COMMON_H__
#include <board.h>
struct imx6ull_iomuxc
{
rt_uint32_t muxRegister;
rt_uint32_t muxMode;
rt_uint32_t inputRegister;
rt_uint32_t inputDaisy;
rt_uint32_t configRegister;
rt_uint32_t inputOnfield;
rt_uint32_t configValue;
};
void *imx6ull_get_periph_vaddr(rt_uint32_t paddr);
void *imx6ull_get_periph_paddr(rt_uint32_t vaddr);
void imx6ull_gpio_init(const struct imx6ull_iomuxc *gpio);
#endif

View File

@ -0,0 +1,568 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-06-16 songchao support emac driver
* 2021-06-29 songchao add phy link detect
* 2021-08-13 songchao support dual mac and reduse copy
*/
#include "drv_eth.h"
#define DBG_TAG "drv.enet"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#define BSP_USING_IMX6ULL_ART_PI
#if (defined(RT_USING_ENET1)) || (defined(RT_USING_ENET2))
#ifdef BSP_USING_IMX6ULL_ART_PI
static struct imx6ull_iomuxc mdio_gpio[2] =
{
{IOMUXC_GPIO1_IO06_ENET1_MDIO,0U,0xB029},
{IOMUXC_GPIO1_IO07_ENET1_MDC,0U,0xB0E9}
};
#else
static struct imx6ull_iomuxc mdio_gpio[2] =
{
{IOMUXC_GPIO1_IO06_ENET2_MDIO,0U,0xB029},
{IOMUXC_GPIO1_IO07_ENET2_MDC,0U,0xB0E9},
};
#endif
enum
{
#ifdef RT_USING_ENET1
DEV_ENET1,
#endif
#ifdef RT_USING_ENET2
DEV_ENET2,
#endif
DEV_ENET_MAX,
};
static struct rt_imx6ul_ethps _imx6ul_eth_device[DEV_ENET_MAX] =
{
#ifdef RT_USING_ENET1
{
.dev_addr = {0xa8,0x5e,0x45,0x91,0x92,0x93},
.mac_name = "e1",
.irq_name = "emac1_intr",
.enet_phy_base_addr = ENET1,
.irq_num = IMX_INT_ENET1,
.phy_num = ENET_PHY1,
.mac_num = 1,
.phy_base_addr = GPIO5,
.phy_gpio_pin = 9,
.phy_id = 7,
.buffConfig =
{
ENET_RXBD_NUM,
ENET_TXBD_NUM,
ENET_RXBUFF_ALIGN_SIZE,
ENET_TXBUFF_ALIGN_SIZE,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
ENET_RXBUFF_TOTAL_SIZE,
ENET_TXBUFF_TOTAL_SIZE
},
.gpio =
{
{IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09,0U,0x110B0},
{IOMUXC_ENET1_RX_DATA0_ENET1_RDATA00,0U,0xB0E9},
{IOMUXC_ENET1_RX_DATA1_ENET1_RDATA01,0U,0xB0E9},
{IOMUXC_ENET1_RX_EN_ENET1_RX_EN,0U,0xB0E9},
{IOMUXC_ENET1_RX_ER_ENET1_RX_ER,0U,0xB0E9},
{IOMUXC_ENET1_TX_CLK_ENET1_REF_CLK1,1U,0x00F0},
{IOMUXC_ENET1_TX_DATA0_ENET1_TDATA00,0U,0xB0E9},
{IOMUXC_ENET1_TX_DATA1_ENET1_TDATA01,0U,0xB0E9},
{IOMUXC_ENET1_TX_EN_ENET1_TX_EN,0U,0xB0E9}
}
},
#endif
#ifdef RT_USING_ENET2
{
.dev_addr = {0xa8,0x5e,0x45,0x01,0x02,0x03},
.mac_name = "e2",
.irq_name = "emac2_intr",
.enet_phy_base_addr = ENET2,
.irq_num = IMX_INT_ENET2,
.phy_num = ENET_PHY2,
.mac_num = 2,
.phy_base_addr = GPIO5,
.phy_gpio_pin = 6,
.phy_id = 7,
.buffConfig =
{
ENET_RXBD_NUM,
ENET_TXBD_NUM,
ENET_RXBUFF_ALIGN_SIZE,
ENET_TXBUFF_ALIGN_SIZE,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
ENET_RXBUFF_TOTAL_SIZE,
ENET_TXBUFF_TOTAL_SIZE
},
.gpio =
{
{IOMUXC_SNVS_SNVS_TAMPER6_GPIO5_IO06,0U,0x110B0},
{IOMUXC_ENET2_RX_DATA0_ENET2_RDATA00,0U,0xB0E9},
{IOMUXC_ENET2_RX_DATA1_ENET2_RDATA01,0U,0xB0E9},
{IOMUXC_ENET2_RX_EN_ENET2_RX_EN,0U,0xB0E9},
{IOMUXC_ENET2_RX_ER_ENET2_RX_ER,0U,0xB0E9},
{IOMUXC_ENET2_TX_CLK_ENET2_REF_CLK2,1U,0x00F0},
{IOMUXC_ENET2_TX_DATA0_ENET2_TDATA00,0U,0xB0E9},
{IOMUXC_ENET2_TX_DATA1_ENET2_TDATA01,0U,0xB0E9},
{IOMUXC_ENET2_TX_EN_ENET2_TX_EN,0U,0xB0E9}
}
},
#endif
};
void imx6ul_eth_link_change(struct rt_imx6ul_ethps *imx6ul_device,rt_bool_t up)
{
if(up)
{
LOG_D("enet%d link up",imx6ul_device->mac_num);
eth_device_linkchange(&imx6ul_device->parent, RT_TRUE);
imx6ul_device->phy_link_status = RT_TRUE;
}
else
{
LOG_D("enet%d link down",imx6ul_device->mac_num);
eth_device_linkchange(&imx6ul_device->parent, RT_FALSE);
imx6ul_device->phy_link_status = RT_FALSE;
}
}
void ENET_InitModuleClock(void)
{
const clock_enet_pll_config_t config = {true, true, false, 1, 1};
CLOCK_InitEnetPll(&config);
}
rt_err_t enet_buffer_init(enet_buffer_config_t *buffConfig)
{
void *tx_buff_addr = RT_NULL;
void *rx_buff_addr = RT_NULL;
void *tx_bd_addr = RT_NULL;
void *rx_bd_addr = RT_NULL;
if(((SYS_PAGE_SIZE<<RX_BUFFER_INDEX_NUM)<buffConfig->rxBufferTotalSize)||
((SYS_PAGE_SIZE<<TX_BUFFER_INDEX_NUM)<buffConfig->txBufferTotalSize))
{
LOG_E("ERROR: alloc mem not enough for enet driver");
return RT_ERROR;
}
rx_buff_addr = rt_pages_alloc(RX_BUFFER_INDEX_NUM);
if(!rx_buff_addr)
{
LOG_E("ERROR: rx buff page alloc failed");
return RT_ERROR;
}
buffConfig->rxBufferAlign = (void *)rt_ioremap_nocache(virtual_to_physical(rx_buff_addr), (SYS_PAGE_SIZE<<RX_BUFFER_INDEX_NUM));
buffConfig->rxPhyBufferAlign = (void *)virtual_to_physical(rx_buff_addr);
tx_buff_addr = rt_pages_alloc(TX_BUFFER_INDEX_NUM);
if(!tx_buff_addr)
{
LOG_E("ERROR: tx buff page alloc failed");
return RT_ERROR;
}
buffConfig->txBufferAlign = (void *)rt_ioremap_nocache(virtual_to_physical(tx_buff_addr), (SYS_PAGE_SIZE<<TX_BUFFER_INDEX_NUM));
buffConfig->txPhyBufferAlign = (void *)virtual_to_physical(tx_buff_addr);
rx_bd_addr = rt_pages_alloc(RX_BD_INDEX_NUM);
if(!rx_bd_addr)
{
LOG_E("ERROR: rx bd page alloc failed");
return RT_ERROR;
}
buffConfig->rxBdStartAddrAlign = (void *)rt_ioremap_nocache(virtual_to_physical(rx_bd_addr), (SYS_PAGE_SIZE<<RX_BD_INDEX_NUM));
buffConfig->rxPhyBdStartAddrAlign = virtual_to_physical(rx_bd_addr);
tx_bd_addr = rt_pages_alloc(TX_BD_INDEX_NUM);
if(!tx_bd_addr)
{
LOG_E("ERROR: tx bd page alloc failed");
return RT_ERROR;
}
buffConfig->txBdStartAddrAlign = (void *)rt_ioremap_nocache(virtual_to_physical(tx_bd_addr), (SYS_PAGE_SIZE<<TX_BD_INDEX_NUM));
buffConfig->txPhyBdStartAddrAlign = virtual_to_physical(tx_bd_addr);
return RT_EOK;
}
/* EMAC initialization function */
static rt_err_t rt_imx6ul_eth_init(rt_device_t dev)
{
rt_err_t state;
struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev;
ENET_Type *base_addr = RT_NULL;
enet_config_t *config;
enet_handle_t *handle;
enet_buffer_config_t *buffConfig;
rt_uint32_t reg_value;
imx6ul_device->enet_virtual_base_addr = (ENET_Type *)rt_ioremap((void *)imx6ul_device->enet_phy_base_addr,SYS_PAGE_SIZE);
base_addr = imx6ul_device->enet_virtual_base_addr;
config = &imx6ul_device->config;
handle = &imx6ul_device->handle;
buffConfig = &imx6ul_device->buffConfig;
for (int i=0; i<GET_ARRAY_NUM(imx6ul_device->gpio); i++)
{
imx6ull_gpio_init(&imx6ul_device->gpio[i]);
}
IOMUXC_GPR_Type *GPR1 = (IOMUXC_GPR_Type *)rt_ioremap((void *)IOMUXC_GPR,0x1000);
if(imx6ul_device->mac_num == 1)
{
reg_value = GPR1->GPR1;
reg_value &= ~(IOMUXC_GPR_GPR1_ENET1_CLK_SEL_MASK
| IOMUXC_GPR_GPR1_ENET1_CLK_SEL_MASK);
reg_value |= IOMUXC_GPR_GPR1_ENET1_TX_CLK_DIR(1);
reg_value |= IOMUXC_GPR_GPR1_ENET1_CLK_SEL(0);
GPR1->GPR1 = reg_value;
}
else if(imx6ul_device->mac_num == 2)
{
reg_value = GPR1->GPR1;
reg_value &= ~(IOMUXC_GPR_GPR1_ENET2_CLK_SEL_MASK
| IOMUXC_GPR_GPR1_ENET2_CLK_SEL_MASK);
reg_value |= IOMUXC_GPR_GPR1_ENET2_TX_CLK_DIR(1);
reg_value |= IOMUXC_GPR_GPR1_ENET2_CLK_SEL(0);
GPR1->GPR1 = reg_value;
}
ENET_InitModuleClock();
ENET_GetDefaultConfig(config);
config->interrupt |= (ENET_RX_INTERRUPT);
state = enet_buffer_init(buffConfig);
if(state != RT_EOK)
{
return state;
}
ENET_Init(base_addr, handle, config, buffConfig, &imx6ul_device->dev_addr[0], SYS_CLOCK_HZ);
ENET_ActiveRead(base_addr);
rt_hw_interrupt_install(imx6ul_device->irq_num, (rt_isr_handler_t)ENET_DriverIRQHandler, (void *)base_addr,imx6ul_device->irq_name);
rt_hw_interrupt_umask(imx6ul_device->irq_num);
return RT_EOK;
}
static rt_err_t rt_imx6ul_eth_control(rt_device_t dev, int cmd, void *args)
{
struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev;
switch (cmd)
{
case NIOCTL_GADDR:
/* get MAC address */
if (args)
{
OCOTP_Type *ocotp_base;
rt_uint32_t uid[2];
rt_uint32_t uid_crc = 0;
ocotp_base = (OCOTP_Type *)rt_ioremap((void*)OCOTP_BASE, 0x1000);
uid[0] = ocotp_base->CFG0;
uid[1] = ocotp_base->CFG1;
rt_iounmap(ocotp_base);
LOG_D("UNIQUE_ID is %x%x",uid[0], uid[1]);
uid_crc = uid[0] - uid[1];
LOG_D("UNIQUE_ID change to 32 bits %x", uid_crc);
if (imx6ul_device->enet_phy_base_addr == ENET1)
{
imx6ul_device->dev_addr[0] = 0xa8;
imx6ul_device->dev_addr[1] = 0x5e;
imx6ul_device->dev_addr[2] = 0x45;
imx6ul_device->dev_addr[3] = (uid_crc>>16) & 0x7f;
imx6ul_device->dev_addr[4] = (uid_crc>>8) & 0xff;
imx6ul_device->dev_addr[5] = uid_crc & 0xff;
}
else /*if (imx6ul_device->enet_phy_base_addr == ENET2)*/
{
imx6ul_device->dev_addr[0] = 0xa8;
imx6ul_device->dev_addr[1] = 0x5e;
imx6ul_device->dev_addr[2] = 0x46;
imx6ul_device->dev_addr[3] = (uid_crc >> 16) & 0x7f;
imx6ul_device->dev_addr[4] = (uid_crc >> 8) & 0xff;
imx6ul_device->dev_addr[5] = uid_crc & 0xff;
}
rt_memcpy(args, imx6ul_device->dev_addr, MAX_ADDR_LEN);
}
else
{
return -RT_ERROR;
}
break;
default :
break;
}
return RT_EOK;
}
static status_t read_data_from_eth(rt_device_t dev,void *read_data,uint16_t *read_length)
{
status_t status = 0;
uint16_t length = 0;
ENET_Type *base_addr = RT_NULL;
enet_config_t *config;
enet_handle_t *handle;
enet_buffer_config_t *buffConfig;
struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev;
base_addr = imx6ul_device->enet_virtual_base_addr;
config = &imx6ul_device->config;
handle = &imx6ul_device->handle;
buffConfig = &imx6ul_device->buffConfig;
/* Get the Frame size */
status = ENET_ReadFrame(base_addr,handle,config,read_data,&length);
if((status == kStatus_ENET_RxFrameEmpty)||(status == kStatus_ENET_RxFrameError))
{
ENET_EnableInterrupts(base_addr,ENET_RX_INTERRUPT);
if(status == kStatus_ENET_RxFrameError)
{
/*recv error happend reinitialize mac*/
ENET_Init(base_addr, handle, config, buffConfig, &imx6ul_device->dev_addr[0], SYS_CLOCK_HZ);
ENET_ActiveRead(base_addr);
return kStatus_ENET_RxFrameError;
}
else if(status == kStatus_ENET_RxFrameEmpty)
{
return kStatus_ENET_RxFrameEmpty;
}
}
*read_length = length;
return status;
}
/* transmit data*/
rt_err_t rt_imx6ul_eth_tx(rt_device_t dev, struct pbuf *p)
{
rt_err_t ret = RT_ERROR;
struct pbuf *q = RT_NULL;
uint16_t offset = 0;
uint32_t last_flag = 0;
status_t status;
ENET_Type *base_addr = RT_NULL;
enet_handle_t *handle;
struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev;
base_addr = imx6ul_device->enet_virtual_base_addr;
handle = &imx6ul_device->handle;
RT_ASSERT(p);
for(q = p;q != RT_NULL;q=q->next)
{
if(q->next == RT_NULL)
{
last_flag = 1;
}
else
{
last_flag = 0;
}
status = ENET_SendFrame(base_addr, handle, q->payload, q->len,last_flag);
offset = offset + q->len;
if(status == kStatus_Success)
{
}
else
{
return RT_ERROR;
}
}
if(offset > ENET_FRAME_MAX_FRAMELEN)
{
LOG_E("net error send length %d exceed max length",offset);
}
return ret;
}
struct pbuf *rt_imx6ul_eth_rx(rt_device_t dev)
{
static struct pbuf *p_s = RT_NULL;
struct pbuf *p = RT_NULL;
status_t status;
uint16_t length = 0;
if(p_s == RT_NULL)
{
p_s = pbuf_alloc(PBUF_RAW, ENET_FRAME_MAX_FRAMELEN, PBUF_POOL);
if(p_s == RT_NULL)
{
return RT_NULL;
}
}
p = p_s;
status = read_data_from_eth(dev,p->payload,&length);
if(status == kStatus_ENET_RxFrameEmpty)
{
return RT_NULL;
}
else if(status == kStatus_ENET_RxFrameError)
{
return RT_NULL;
}
if(length > ENET_FRAME_MAX_FRAMELEN)
{
LOG_E("net error recv length %d exceed max length",length);
return RT_NULL;
}
pbuf_realloc(p, length);
p_s = RT_NULL;
return p;
}
int32_t get_instance_by_base(void *base)
{
int32_t i = 0;
int32_t instance = 0;
for(i = 0; i < DEV_ENET_MAX; i ++)
{
if((void *)_imx6ul_eth_device[i].enet_virtual_base_addr == base)
{
break;
}
}
if(i == DEV_ENET_MAX)
{
return -1;
}
return instance;
}
void rx_enet_callback(void *base)
{
int32_t instance = 0;
instance = get_instance_by_base(base);
if(instance == -1)
{
LOG_E("interrput match base addr error");
return;
}
eth_device_ready(&(_imx6ul_eth_device[instance].parent));
ENET_DisableInterrupts(base,ENET_RX_INTERRUPT);
}
void tx_enet_callback(void *base)
{
ENET_DisableInterrupts(base,ENET_TX_INTERRUPT);
}
/*phy link detect thread*/
static void phy_detect_thread_entry(void *param)
{
bool link = false;
phy_speed_t speed;
phy_duplex_t duplex;
ENET_Type *base_addr = RT_NULL;
struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)param;
base_addr = imx6ul_device->enet_virtual_base_addr;
phy_reset(imx6ul_device->phy_base_addr,imx6ul_device->phy_gpio_pin);
PHY_Init(base_addr, imx6ul_device->phy_num, SYS_CLOCK_HZ,imx6ul_device->phy_id);
PHY_GetLinkStatus(base_addr, imx6ul_device->phy_num, &link);
if (link)
{
/* Get the actual PHY link speed. */
PHY_GetLinkSpeedDuplex(base_addr, imx6ul_device->phy_num, &speed, &duplex);
/* Change the MII speed and duplex for actual link status. */
imx6ul_device->config.miiSpeed = (enet_mii_speed_t)speed;
imx6ul_device->config.miiDuplex = (enet_mii_duplex_t)duplex;
}
else
{
LOG_W("PHY Link down, please check the cable connection and link partner setting.");
}
while(1)
{
PHY_GetLinkStatus(base_addr, imx6ul_device->phy_num, &link);
if(link != imx6ul_device->phy_link_status)
{
if(link == true)
{
PHY_StartNegotiation(base_addr,imx6ul_device->phy_num);
}
imx6ul_eth_link_change(imx6ul_device,link);
}
rt_thread_delay(DETECT_DELAY_ONE_SECOND);
}
}
_internal_ro struct rt_device_ops _k_enet_ops =
{
.init = rt_imx6ul_eth_init,
.control = rt_imx6ul_eth_control,
};
static int imx6ul_eth_init(void)
{
rt_err_t state = RT_EOK;
char link_detect[10];
imx6ull_gpio_init(&mdio_gpio[0]);
imx6ull_gpio_init(&mdio_gpio[1]);
for (int idx=0; idx<GET_ARRAY_NUM(_imx6ul_eth_device); idx++)
{
_imx6ul_eth_device[idx].parent.parent.ops = &_k_enet_ops;
_imx6ul_eth_device[idx].parent.eth_rx = rt_imx6ul_eth_rx;
_imx6ul_eth_device[idx].parent.eth_tx = rt_imx6ul_eth_tx;
_imx6ul_eth_device[idx].phy_link_status = RT_FALSE;
/* register eth device */
state = eth_device_init(&(_imx6ul_eth_device[idx].parent), _imx6ul_eth_device[idx].mac_name);
if (RT_EOK == state)
{
LOG_I("emac device init success");
}
else
{
LOG_E("emac device init faild: %d", state);
state = -RT_ERROR;
}
rt_sprintf(link_detect,"link_d%d",_imx6ul_eth_device[idx].mac_num);
/* start phy link detect */
rt_thread_t phy_link_tid;
phy_link_tid = rt_thread_create(link_detect,
phy_detect_thread_entry,
&_imx6ul_eth_device[idx],
4096,
RT_THREAD_PRIORITY_MAX - 2,
2);
if (phy_link_tid != RT_NULL)
{
rt_thread_startup(phy_link_tid);
}
memset(link_detect,0,sizeof(link_detect));
}
return state;
}
INIT_DEVICE_EXPORT(imx6ul_eth_init);
#endif

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-06-16 songchao first version
* 2021-08-13 songchao add more device info
*/
#ifndef __DRV_ETH_H__
#define __DRV_ETH_H__
#include <rtthread.h>
#include <netif/ethernetif.h>
#include "fsl_phy.h"
#include "imx6ull.h"
#include "drv_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_ADDR_LEN 6
struct rt_imx6ul_ethps
{
/* inherit from ethernet device */
struct eth_device parent;
/* interface address info, hw address */
rt_uint8_t dev_addr[MAX_ADDR_LEN];
/* ETH_Speed */
uint32_t ETH_Speed;
/* ETH_Duplex_Mode */
uint32_t ETH_Mode;
rt_bool_t phy_link_status;
const char *mac_name;
const char *irq_name;
enum _imx_interrupts irq_num;
uint8_t phy_num;
const ENET_Type *enet_phy_base_addr;
ENET_Type *enet_virtual_base_addr;
uint32_t mac_num;
enet_buffer_config_t buffConfig;
enet_config_t config;
enet_handle_t handle;
struct imx6ull_iomuxc gpio[9];
GPIO_Type *phy_base_addr;
uint32_t phy_gpio_pin;
uint32_t phy_id;
};
int32_t get_instance_by_base(void *base);
#ifdef __cplusplus
}
#endif
#endif /* __DRV_ETH_H__ */

View File

@ -0,0 +1,204 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-13 Lyons first version
* 2021-06-23 RiceChen refactor
*/
#include <rthw.h>
#include <rtdevice.h>
#ifdef BSP_USING_I2C
#define LOG_TAG "drv.i2c"
#include <drv_log.h>
#if !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2) && !defined(BSP_USING_I2C3) && !defined(BSP_USING_I2C4)
#error "Please define at least one BSP_USING_I2Cx"
#endif
#include "fsl_iomuxc.h"
#include "drv_i2c.h"
static struct imx6ull_i2c_config i2c_config[] =
{
#ifdef BSP_USING_I2C1
I2C1_BUS_CONFIG,
#endif
#ifdef BSP_USING_I2C2
I2C2_BUS_CONFIG,
#endif
#ifdef BSP_USING_I2C3
I2C3_BUS_CONFIG,
#endif
#ifdef BSP_USING_I2C4
I2C4_BUS_CONFIG,
#endif
};
static struct imx6ull_i2c_bus i2c_obj[sizeof(i2c_config) / sizeof(i2c_config[0])];
static char i2c_buff_temp[4][1024];
extern uint32_t I2C_GetInstance(I2C_Type *base);
#ifdef IMX_I2C_IRQ_MODE
static uint32_t g_MasterCompletionFlag[4] = {0,0,0,0};
static void i2c_master_callback(I2C_Type *base, i2c_master_handle_t *handle, status_t status, void *userData)
{
/* Signal transfer success when received success status. */
struct imx6ull_i2c_config *config;
config = (struct imx6ull_i2c_config*)userData;
uint32_t instance = I2C_GetInstance(config->hw_base);
if (status == kStatus_Success)
{
g_MasterCompletionFlag[instance-1] = 1;
}
}
#endif
static rt_ssize_t imx6ull_i2c_mst_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
{
rt_ssize_t i = 0;
struct imx6ull_i2c_bus *i2c_bus = RT_NULL;
static i2c_master_transfer_t xfer = {0};
RT_ASSERT(bus != RT_NULL);
#ifdef IMX_I2C_IRQ_MODE
uint32_t timeout_cnt = 100;
#endif
uint32_t instance = 0;
i2c_bus = (struct imx6ull_i2c_bus *)bus;
instance = I2C_GetInstance(i2c_bus->config->hw_base);
for(i = 0 ;i < num; i++)
{
if(msgs[i].flags & RT_I2C_RD)
{
xfer.flags = kI2C_TransferNoStartFlag;
xfer.slaveAddress = msgs[i].addr;
xfer.direction = kI2C_Read;
xfer.subaddress = 0;
xfer.subaddressSize = 0;
xfer.data = (uint8_t *volatile)i2c_buff_temp[instance - 1];
xfer.dataSize = msgs[i].len ;
#ifdef IMX_I2C_IRQ_MODE
I2C_MasterTransferNonBlocking(i2c_bus->config->I2C, &i2c_bus->config->master_handle,&xfer);
while(!g_MasterCompletionFlag[instance - 1])
{
rt_thread_delay(1);
timeout_cnt--;
if(timeout_cnt == 0)
{
break;
}
}
timeout_cnt = 100;
g_MasterCompletionFlag[instance - 1] = 0;
#else
I2C_MasterTransferBlocking(i2c_bus->config->I2C, &xfer);
#endif
rt_memcpy(msgs[i].buf,i2c_buff_temp[instance - 1],msgs[i].len);
}
else
{
xfer.flags = kI2C_TransferNoStartFlag;
xfer.slaveAddress = msgs[i].addr;
xfer.direction = kI2C_Write;
xfer.subaddress = 0;
xfer.subaddressSize = 0;
xfer.data = (uint8_t *volatile)i2c_buff_temp[instance - 1];
xfer.dataSize = msgs[i].len;
rt_memcpy(i2c_buff_temp[instance - 1],msgs[i].buf,msgs[i].len);
#ifdef IMX_I2C_IRQ_MODE
I2C_MasterTransferNonBlocking(i2c_bus->config->I2C, &i2c_bus->config->master_handle,&xfer);
while(!g_MasterCompletionFlag[instance - 1])
{
timeout_cnt--;
rt_thread_delay(1);
if(timeout_cnt == 0)
{
break;
}
}
timeout_cnt = 100;
g_MasterCompletionFlag[instance - 1] = 0;
#else
I2C_MasterTransferBlocking(i2c_bus->config->I2C, &xfer);
#endif
}
}
return i;
}
static rt_err_t imx6ull_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t cmd, rt_uint32_t arg)
{
return RT_EOK;
}
static rt_err_t imx6ull_i2c_gpio_init(struct imx6ull_i2c_bus *bus)
{
struct imx6ull_i2c_bus *i2c_bus = RT_NULL;
i2c_bus = (struct imx6ull_i2c_bus *)bus;
imx6ull_gpio_init(&i2c_bus->config->scl_gpio);
imx6ull_gpio_init(&i2c_bus->config->sda_gpio);
return RT_EOK;
}
#ifdef RT_USING_DEVICE_OPS
static const struct rt_i2c_bus_device_ops imx6ull_i2c_ops =
{
.master_xfer = imx6ull_i2c_mst_xfer,
.slave_xfer = RT_NULL,
.i2c_bus_control = imx6ull_i2c_bus_control,
};
#endif
extern void I2C_DriverIRQHandler(int irq, void *base);
int rt_hw_i2c_init(void)
{
rt_uint16_t obj_num = 0;
rt_uint32_t src_clock;
i2c_master_config_t masterConfig = {0};
obj_num = sizeof(i2c_config) / sizeof(i2c_config[0]);
src_clock = (CLOCK_GetFreq(kCLOCK_IpgClk) / (CLOCK_GetDiv(kCLOCK_PerclkDiv) + 1U));
for(int i = 0; i < obj_num; i++)
{
i2c_obj[i].config = &i2c_config[i];
i2c_obj[i].config->hw_base = i2c_obj[i].config->I2C;
i2c_obj[i].config->I2C = (I2C_Type *)imx6ull_get_periph_vaddr((rt_uint32_t)i2c_obj[i].config->hw_base);
i2c_obj[i].parent.ops = &imx6ull_i2c_ops;
imx6ull_i2c_gpio_init(&i2c_obj[i]);
I2C_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate_Bps = i2c_config[i].baud_rate;
CLOCK_EnableClock(i2c_obj[i].config->clk_ip_name);
I2C_MasterInit(i2c_obj[i].config->I2C, &masterConfig, src_clock);
rt_i2c_bus_device_register(&i2c_obj[i].parent, i2c_obj[i].config->name);
#ifdef IMX_I2C_IRQ_MODE
I2C_MasterTransferCreateHandle(i2c_obj[i].config->hw_base, &i2c_obj[i].config->master_handle, i2c_master_callback, i2c_obj[i].config);
rt_hw_interrupt_install(i2c_obj[i].config->irq_num, (rt_isr_handler_t)I2C_DriverIRQHandler, i2c_obj[i].config, i2c_obj[i].config->name);
#endif
}
return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_i2c_init);
#endif

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-13 Lyons first version
* 2021-06-23 RiceChen refactor
*/
#ifndef __DRV_I2C_H__
#define __DRV_I2C_H__
#include <board.h>
#include "drv_common.h"
#include "fsl_iomuxc.h"
#include "fsl_clock.h"
#include "fsl_i2c.h"
#define IMX_I2C_IRQ_MODE
struct imx6ull_i2c_config
{
void *hw_base; /* hardware physical address base */
I2C_Type *I2C;
char *name;
rt_uint32_t baud_rate;
rt_uint32_t clk_ip_name;
rt_uint32_t irq_num;
struct imx6ull_iomuxc scl_gpio;
struct imx6ull_iomuxc sda_gpio;
i2c_master_handle_t master_handle;
};
struct imx6ull_i2c_bus
{
struct rt_i2c_bus_device parent;
struct imx6ull_i2c_config *config;
};
#ifdef BSP_USING_I2C1
#define I2C1_BUS_CONFIG \
{ \
.I2C = I2C1, \
.name = "i2c1", \
.clk_ip_name = kCLOCK_I2c1S, \
.baud_rate = I2C1_BAUD_RATE, \
.irq_num = IMX_INT_I2C1, \
.scl_gpio = {IOMUXC_UART4_TX_DATA_I2C1_SCL, 1, 0x70B0}, \
.sda_gpio = {IOMUXC_UART4_RX_DATA_I2C1_SDA, 1, 0x70B0}, \
}
#endif /* BSP_USING_I2C1 */
#ifdef BSP_USING_I2C2
#define I2C2_BUS_CONFIG \
{ \
.I2C = I2C2, \
.name = "i2c2", \
.clk_ip_name = kCLOCK_I2c2S, \
.baud_rate = I2C2_BAUD_RATE, \
.irq_num = IMX_INT_I2C2, \
.scl_gpio = {IOMUXC_UART5_TX_DATA_I2C2_SCL, 1, 0x70B0}, \
.sda_gpio = {IOMUXC_UART5_RX_DATA_I2C2_SDA, 1, 0x70B0}, \
}
#endif /* BSP_USING_I2C2 */
#ifdef BSP_USING_I2C3
#define I2C3_BUS_CONFIG \
{ \
.I2C = I2C3, \
.name = "i2c3", \
.clk_ip_name = kCLOCK_I2c3S, \
.baud_rate = I2C3_BAUD_RATE, \
.irq_num = IMX_INT_I2C3, \
.scl_gpio = {IOMUXC_ENET2_RX_DATA0_I2C3_SCL, 1, 0x70B0}, \
.sda_gpio = {IOMUXC_ENET2_RX_DATA1_I2C3_SDA, 1, 0x70B0}, \
}
#endif /* BSP_USING_I2C3 */
#ifdef BSP_USING_I2C4
#define I2C4_BUS_CONFIG \
{ \
.I2C = I2C4, \
.name = "i2c4", \
.clk_ip_name = kCLOCK_I2c4S, \
.baud_rate = I2C4_BAUD_RATE, \
.irq_num = IMX_INT_I2C4, \
.scl_gpio = {IOMUXC_UART2_TX_DATA_I2C4_SCL, 1, 0x70B0}, \
.sda_gpio = {IOMUXC_UART2_RX_DATA_I2C4_SDA, 1, 0x70B0}, \
}
#endif /* BSP_USING_I2C4 */
#endif

View File

@ -0,0 +1,223 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-11 Lyons first version
* 2021-06-24 RiceChen refactor
* 2021-07-28 songchao add cmd
*/
#include <rthw.h>
#include <rtdevice.h>
#ifdef BSP_USING_LCD
#define LOG_TAG "drv.lcd"
#include <drv_log.h>
#include "fsl_iomuxc.h"
#include "drv_lcd.h"
#include <lwp_user_mm.h>
static struct imx6ull_lcd_config _lcd_config = LCD_BUS_CONFIG;
static struct imx6ull_lcd_bus _lcd_obj;
static rt_err_t imx6ull_elcd_init(rt_device_t device)
{
struct imx6ull_lcd_bus *elcd_dev = RT_NULL;
clock_video_pll_config_t pll_config;
elcdif_rgb_mode_config_t lcd_config;
RT_ASSERT(device != RT_NULL);
elcd_dev = (struct imx6ull_lcd_bus *)device;
ELCDIF_Reset(elcd_dev->config->ELCDIF);
pll_config.loopDivider = 32;
pll_config.postDivider = LCD_PLL_DIV;
pll_config.numerator = 0;
pll_config.denominator = 0;
CLOCK_InitVideoPll(&pll_config);
lcd_config.hfp = LCD_HFP;
lcd_config.vfp = LCD_VFP;
lcd_config.hbp = LCD_HBP;
lcd_config.vbp = LCD_VBP;
lcd_config.hsw = LCD_HSW;
lcd_config.vsw = LCD_VSW;
lcd_config.polarityFlags = kELCDIF_DataEnableActiveHigh |
kELCDIF_VsyncActiveLow |
kELCDIF_HsyncActiveLow |
kELCDIF_DriveDataOnRisingClkEdge;
switch(elcd_dev->info.pixel_format)
{
case RTGRAPHIC_PIXEL_FORMAT_RGB888:
lcd_config.pixelFormat = kELCDIF_PixelFormatRGB888;
break;
case RTGRAPHIC_PIXEL_FORMAT_RGB565:
lcd_config.pixelFormat = kELCDIF_PixelFormatRGB565;
break;
default:
LOG_E("not support this pixel_format %d\n",elcd_dev->info.pixel_format);
return RT_ERROR;
}
lcd_config.panelWidth = elcd_dev->info.width;
lcd_config.panelHeight = elcd_dev->info.height;
lcd_config.bufferAddr = (uint32_t)elcd_dev->fb_phy;
lcd_config.dataBus = kELCDIF_DataBus24Bit;
ELCDIF_RgbModeInit(elcd_dev->config->ELCDIF, &lcd_config);
ELCDIF_RgbModeStart(elcd_dev->config->ELCDIF);
return RT_EOK;
}
static rt_err_t imx6ull_elcd_control(rt_device_t device, int cmd, void *args)
{
struct imx6ull_lcd_bus *elcd_dev = RT_NULL;
int mem_size = 0;
RT_ASSERT(device != RT_NULL);
elcd_dev = (struct imx6ull_lcd_bus *)device;
switch(cmd)
{
case RTGRAPHIC_CTRL_RECT_UPDATE:
{
mem_size = elcd_dev->info.width * elcd_dev->info.height * elcd_dev->info.bits_per_pixel / 8;
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void *)(_lcd_obj.info.framebuffer), mem_size);
break;
}
case RTGRAPHIC_CTRL_POWERON:
{
rt_pin_write(IMX6ULL_LCD_BL_PIN, PIN_HIGH);
break;
}
case RTGRAPHIC_CTRL_POWEROFF:
{
rt_pin_write(IMX6ULL_LCD_BL_PIN, PIN_LOW);
break;
}
case RTGRAPHIC_CTRL_GET_INFO:
{
struct lcd_info *info = (struct lcd_info *)args;
RT_ASSERT(info != RT_NULL);
rt_memcpy(&info->graphic, &elcd_dev->info, sizeof(struct rt_device_graphic_info));
info->screen.shamem_len = elcd_dev->info.width * elcd_dev->info.height * elcd_dev->info.bits_per_pixel / 8;
info->screen.shamem_start = (rt_uint32_t)lwp_map_user_phy(lwp_self(), RT_NULL,
elcd_dev->fb_phy,
info->screen.shamem_len, 1);
break;
}
case RTGRAPHIC_CTRL_SET_MODE:
{
break;
}
case FBIOGET_FSCREENINFO:
{
struct fb_fix_screeninfo *info = (struct fb_fix_screeninfo *)args;
rt_memcpy(info->id, elcd_dev->config->name, (strlen(elcd_dev->config->name)+1));
info->smem_len = elcd_dev->info.width * elcd_dev->info.height * elcd_dev->info.bits_per_pixel / 8;
info->smem_start = (rt_uint32_t)lwp_map_user_phy(lwp_self(), RT_NULL,
elcd_dev->fb_phy,
info->smem_len, 1);
info->line_length = elcd_dev->info.width * 2;
break;
}
case FBIOGET_VSCREENINFO:
{
struct fb_var_screeninfo *info = (struct fb_var_screeninfo *)args;
info->bits_per_pixel = elcd_dev->info.bits_per_pixel;
info->xres = elcd_dev->info.width;
info->yres = elcd_dev->info.height;
break;
}
}
return RT_EOK;
}
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops elcd_ops =
{
imx6ull_elcd_init,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
imx6ull_elcd_control,
};
#endif
int rt_hw_elcd_init(void)
{
rt_err_t ret = 0;
_lcd_config.ELCDIF = (LCDIF_Type *)imx6ull_get_periph_vaddr((rt_uint32_t)(_lcd_config.ELCDIF));
_lcd_config.lcd_mux_base = (rt_uint32_t)imx6ull_get_periph_vaddr((rt_uint32_t)(_lcd_config.lcd_mux_base));
_lcd_config.lcd_cfg_base = (rt_uint32_t)imx6ull_get_periph_vaddr((rt_uint32_t)(_lcd_config.lcd_cfg_base));
for(int i = 0; i < LCD_GPIO_MAX; i++)
{
IOMUXC_SetPinMux((_lcd_config.lcd_mux_base + i * 4),
0x0U, 0x0U, 0x0U, (_lcd_config.lcd_cfg_base + i * 4), 0);
IOMUXC_SetPinConfig((_lcd_config.lcd_mux_base + i * 4),
0x0U, 0x0U, 0x0U, (_lcd_config.lcd_cfg_base + i * 4), 0xB9);
}
CLOCK_EnableClock(_lcd_config.apd_clk_name);
CLOCK_EnableClock(_lcd_config.pix_clk_name);
_lcd_obj.config = &_lcd_config;
_lcd_obj.fb_virt = rt_pages_alloc(rt_page_bits(LCD_BUF_SIZE));
_lcd_obj.fb_phy = _lcd_obj.fb_virt + PV_OFFSET;
LOG_D("fb address => 0x%08x\n", _lcd_obj.fb_phy);
if(_lcd_obj.fb_phy == RT_NULL)
{
LOG_E("initialize frame buffer failed!\n");
return -RT_ERROR;
}
_lcd_obj.info.width = LCD_WIDTH;
_lcd_obj.info.height = LCD_HEIGHT;
_lcd_obj.info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
_lcd_obj.info.bits_per_pixel = LCD_BITS_PER_PIXEL;
_lcd_obj.info.framebuffer = (void *)_lcd_obj.fb_virt;
_lcd_obj.parent.type = RT_Device_Class_Graphic;
#ifdef RT_USING_DEVICE_OPS
_lcd_obj.parent.ops = &elcd_ops;
#else
_lcd_obj.parent.init = imx6ull_elcd_init;
_lcd_obj.parent.open = RT_NULL;
_lcd_obj.parent.close = RT_NULL;
_lcd_obj.parent.read = RT_NULL;
_lcd_obj.parent.write = RT_NULL;
_lcd_obj.parent.control = imx6ull_elcd_control;
#endif
_lcd_obj.parent.user_data = (void *)&_lcd_obj.info;
ret = rt_device_register(&_lcd_obj.parent, _lcd_obj.config->name, RT_DEVICE_FLAG_RDWR);
/* LCD_BL */
rt_pin_mode(IMX6ULL_LCD_BL_PIN, PIN_MODE_OUTPUT);
rt_pin_write(IMX6ULL_LCD_BL_PIN, PIN_HIGH);
rt_memset((rt_uint8_t *)_lcd_obj.fb_virt, 0xff, LCD_BUF_SIZE);
return ret;
}
INIT_DEVICE_EXPORT(rt_hw_elcd_init);
#endif

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-11 Lyons first version
* 2021-06-24 RiceChen refactor
*/
#ifndef __DRV_LCD_H__
#define __DRV_LCD_H__
#include <board.h>
#include "drv_pin.h"
#include "drv_common.h"
#include "fsl_iomuxc.h"
#include "fsl_clock.h"
#include "fsl_elcdif.h"
#define LCD_GPIO_MAX 29
#define LCD_MUX_BASE 0x020E0104U
#define LCD_CONFIG_BASE 0x020E0390U
#define LCD_WIDTH BSP_LCD_WIDTH
#define LCD_HEIGHT BSP_LCD_HEIGHT
#define LCD_VSW BSP_LCD_VSW
#define LCD_VBP BSP_LCD_VBP
#define LCD_VFP BSP_LCD_VFP
#define LCD_HSW BSP_LCD_HSW
#define LCD_HBP BSP_LCD_HBP
#define LCD_HFP BSP_LCD_HFP
#define LCD_PLL_DIV BSP_LCD_PLL_DIV
#define LCD_BITS_PER_PIXEL 32
#define LCD_BUF_SIZE (LCD_WIDTH * LCD_HEIGHT * LCD_BITS_PER_PIXEL / 8)
#define IMX6ULL_LCD_BL_PIN GET_PIN(1, 8)
struct fb_fix_screen_info
{
rt_uint32_t shamem_start;
rt_uint32_t shamem_len;
};
struct lcd_info
{
struct rt_device_graphic_info graphic;
struct fb_fix_screen_info screen;
};
struct imx6ull_lcd_config
{
LCDIF_Type *ELCDIF;
char *name;
rt_uint32_t apd_clk_name;
rt_uint32_t pix_clk_name;
rt_uint32_t lcd_mux_base;
rt_uint32_t lcd_cfg_base;
};
struct imx6ull_lcd_bus
{
struct rt_device parent;
struct rt_device_graphic_info info;
struct imx6ull_lcd_config *config;
rt_uint8_t *fb_phy;
rt_uint8_t *fb_virt;
};
#ifdef BSP_USING_LCD
#define LCD_BUS_CONFIG \
{ \
.ELCDIF = LCDIF, \
.name = "lcd", \
.apd_clk_name = kCLOCK_Lcd, \
.pix_clk_name = kCLOCK_Lcdif1, \
.lcd_mux_base = LCD_MUX_BASE, \
.lcd_cfg_base = LCD_CONFIG_BASE, \
}
#endif /* BSP_USING_LCD */
#endif

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-03 RiceChen first version
*/
/*
* NOTE: DO NOT include this file on the header file.
*/
#ifndef LOG_TAG
#define DBG_TAG "drv"
#else
#define DBG_TAG LOG_TAG
#endif /* LOG_TAG */
#ifdef DRV_DEBUG
#define DBG_LVL DBG_LOG
#else
#define DBG_LVL DBG_INFO
#endif /* DRV_DEBUG */
#include <rtdbg.h>

View File

@ -0,0 +1,568 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-01-13 Lyons edit and remove irq setting
* 2021-06-23 RiceChen refactor gpio driver and support gpio IRQ
*/
#include <rthw.h>
#include <rtdevice.h>
#include "drv_pin.h"
#include "drv_common.h"
#include "fsl_gpio.h"
#include "fsl_iomuxc.h"
rt_uint32_t iomuxc_base = IOMUXC_BASE;
rt_uint32_t iomuxc_snvs_base = IOMUXC_SNVS_BASE;
struct pin_mask
{
GPIO_Type *gpio;
rt_int32_t valid_mask;
clock_ip_name_t gpio_clock;
};
struct pin_mask mask_tab[5] =
{
{GPIO1, 0xffffffff, kCLOCK_Gpio1}, /* GPIO1 */
{GPIO2, 0x003fffff, kCLOCK_Gpio2}, /* GPIO2 */
{GPIO3, 0x1fffffff, kCLOCK_Gpio3}, /* GPIO3,29~31 not supported */
{GPIO4, 0x1fffffff, kCLOCK_Gpio4}, /* GPIO4,29~31 not supported */
{GPIO5, 0x00000fff, kCLOCK_Gpio5} /* GPIO5,12~31 not supported */
};
const rt_int8_t gpio_reg_offset[5][32] =
{
{ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,},
{32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 94, 95, 96, 97, 98, 99, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,},
{48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, -1, -1, -1,},
{77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,100,101,102,103,104,105,106,107,108,109,110,111, -1, -1, -1,},
{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,},
};
static struct rt_pin_irq_hdr pin_irq_hdr_tab[] =
{
// GPIO1
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
// GPIO2
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
// GPIO3
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
// GPIO4
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
// GPIO5
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
{-1, 0, RT_NULL, RT_NULL},
};
static void imx6ull_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
{
GPIO_Type *gpio_base = RT_NULL;
gpio_pin_config_t config;
rt_uint32_t config_value = 0;
rt_int8_t port, pin_num, reg_offset;
rt_uint32_t mux_base_addr, config_base_addr;
port = pin >> 5;
pin_num = pin & 31;
config.outputLogic = PIN_LOW;
config.interruptMode = kGPIO_NoIntmode;
switch (mode)
{
case PIN_MODE_OUTPUT:
{
config.direction = kGPIO_DigitalOutput;
config_value = 0x0030U;
}
break;
case PIN_MODE_INPUT:
{
config.direction = kGPIO_DigitalInput;
config_value = 0x0830U;
}
break;
case PIN_MODE_INPUT_PULLDOWN:
{
config.direction = kGPIO_DigitalInput;
config_value = 0x3030U;
}
break;
case PIN_MODE_INPUT_PULLUP:
{
config.direction = kGPIO_DigitalInput;
config_value = 0xB030U;
}
break;
case PIN_MODE_OUTPUT_OD:
{
config.direction = kGPIO_DigitalOutput;
config_value = 0x0830U;
}
break;
}
reg_offset = gpio_reg_offset[port][pin_num];
gpio_base = (GPIO_Type *)imx6ull_get_periph_paddr((rt_uint32_t)mask_tab[port].gpio);
if(gpio_base != GPIO5)
{
IOMUXC_Type *periph = (IOMUXC_Type*)iomuxc_base;
mux_base_addr = (rt_uint32_t)&periph->SW_MUX_CTL_PAD[reg_offset];
config_base_addr = (rt_uint32_t)&periph->SW_PAD_CTL_PAD[reg_offset];
}
else
{
IOMUXC_SNVS_Type *periph = (IOMUXC_SNVS_Type*)iomuxc_snvs_base;
mux_base_addr = (rt_uint32_t)&periph->SW_MUX_CTL_PAD[reg_offset];
config_base_addr = (rt_uint32_t)&periph->SW_PAD_CTL_PAD[reg_offset];
}
IOMUXC_SetPinMux(mux_base_addr, 0x5U, 0x00000000U, 0x0U, config_base_addr, 1);
IOMUXC_SetPinConfig(mux_base_addr, 0x5U, 0x00000000U, 0x0U, config_base_addr, config_value);
GPIO_PinInit(mask_tab[port].gpio, pin_num, &config);
}
static void imx6ull_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
{
rt_int8_t port = 0, pin_num = 0;
port = pin >> 5;
pin_num = pin & 31;
GPIO_WritePinOutput(mask_tab[port].gpio, pin_num, value);
}
static rt_int8_t imx6ull_pin_read(struct rt_device *device, rt_base_t pin)
{
rt_int8_t value = 0;
rt_int8_t port = 0, pin_num = 0;
value = PIN_LOW;
port = pin >> 5;
pin_num = pin & 31;
value = GPIO_ReadPadStatus(mask_tab[port].gpio, pin_num);
return value;
}
static rt_err_t imx6ull_pin_attach_irq(struct rt_device *device, rt_base_t pin,
rt_uint8_t mode, void (*hdr)(void *args),
void *args)
{
rt_base_t level = 0;
level = rt_hw_interrupt_disable();
if (pin_irq_hdr_tab[pin].pin == pin &&
pin_irq_hdr_tab[pin].hdr == hdr &&
pin_irq_hdr_tab[pin].mode == mode &&
pin_irq_hdr_tab[pin].args == args)
{
rt_hw_interrupt_enable(level);
return RT_EOK;
}
pin_irq_hdr_tab[pin].pin = pin;
pin_irq_hdr_tab[pin].hdr = hdr;
pin_irq_hdr_tab[pin].mode = mode;
pin_irq_hdr_tab[pin].args = args;
rt_hw_interrupt_enable(level);
return RT_EOK;
}
static rt_err_t imx6ull_pin_detach_irq(struct rt_device *device, rt_base_t pin)
{
rt_base_t level = 0;
level = rt_hw_interrupt_disable();
if (pin_irq_hdr_tab[pin].pin == -1)
{
rt_hw_interrupt_enable(level);
return RT_EOK;
}
pin_irq_hdr_tab[pin].pin = -1;
pin_irq_hdr_tab[pin].hdr = RT_NULL;
pin_irq_hdr_tab[pin].mode = 0;
pin_irq_hdr_tab[pin].args = RT_NULL;
rt_hw_interrupt_enable(level);
return RT_EOK;
}
static rt_err_t imx6ull_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
{
gpio_interrupt_mode_t int_mode;
rt_int8_t port = 0, pin_num = 0;
port = pin >> 5;
pin_num = pin & 31;
if (pin_irq_hdr_tab[pin].pin == -1)
{
rt_kprintf("rtt pin: %d callback function not initialized!\n", pin);
return RT_ENOSYS;
}
if (enabled == PIN_IRQ_ENABLE)
{
switch (pin_irq_hdr_tab[pin].mode)
{
case PIN_IRQ_MODE_RISING:
int_mode = kGPIO_IntRisingEdge;
break;
case PIN_IRQ_MODE_FALLING:
int_mode = kGPIO_IntFallingEdge;
break;
case PIN_IRQ_MODE_RISING_FALLING:
int_mode = kGPIO_IntRisingOrFallingEdge;
break;
case PIN_IRQ_MODE_HIGH_LEVEL:
int_mode = kGPIO_IntHighLevel;
break;
case PIN_IRQ_MODE_LOW_LEVEL:
int_mode = kGPIO_IntLowLevel;
break;
default:
int_mode = kGPIO_IntRisingEdge;
break;
}
GPIO_SetPinInterruptConfig(mask_tab[port].gpio, pin_num, int_mode);
GPIO_EnableInterrupts(mask_tab[port].gpio, 1U << pin_num);
}
else if (enabled == PIN_IRQ_DISABLE)
{
GPIO_DisableInterrupts(mask_tab[port].gpio, pin_num);
}
else
{
return RT_EINVAL;
}
return RT_EOK;
}
static void imx6ull_isr(rt_int16_t index_offset, rt_int8_t pin_start, GPIO_Type *base)
{
rt_int32_t isr_status = 0, index = 0;
rt_int8_t i = 0, pin_end = 0;
pin_end = pin_start + 15;
isr_status = GPIO_GetPinsInterruptFlags(base) & base->IMR;
for (i = pin_start; i <= pin_end ; i++)
{
if (isr_status & (1 << i))
{
GPIO_ClearPinsInterruptFlags(base, (1 << i));
index = index_offset + i;
if (pin_irq_hdr_tab[index].hdr != RT_NULL)
{
pin_irq_hdr_tab[index].hdr(pin_irq_hdr_tab[index].args);
}
}
}
}
/* GPIO1 index offset is 0 */
void GPIO1_Combined_0_15_IRQHandler(int irqno, void *param)
{
rt_interrupt_enter();
imx6ull_isr(0, 0, mask_tab[0].gpio);
rt_interrupt_leave();
}
void GPIO1_Combined_16_31_IRQHandler(int irqno, void *param)
{
rt_interrupt_enter();
imx6ull_isr(0, 15, mask_tab[0].gpio);
rt_interrupt_leave();
}
/* GPIO2 index offset is 32 */
void GPIO2_Combined_0_15_IRQHandler(int irqno, void *param)
{
rt_interrupt_enter();
imx6ull_isr(32, 0, mask_tab[1].gpio);
rt_interrupt_leave();
}
void GPIO2_Combined_16_31_IRQHandler(int irqno, void *param)
{
rt_interrupt_enter();
imx6ull_isr(32, 15, mask_tab[1].gpio);
rt_interrupt_leave();
}
/* GPIO3 index offset is 64 */
void GPIO3_Combined_0_15_IRQHandler(int irqno, void *param)
{
rt_interrupt_enter();
imx6ull_isr(64, 0, mask_tab[2].gpio);
rt_interrupt_leave();
}
void GPIO3_Combined_16_31_IRQHandler(int irqno, void *param)
{
rt_interrupt_enter();
imx6ull_isr(64, 15, mask_tab[2].gpio);
rt_interrupt_leave();
}
/* GPIO4 index offset is 96 */
void GPIO4_Combined_0_15_IRQHandler(int irqno, void *param)
{
rt_interrupt_enter();
imx6ull_isr(96, 0, mask_tab[3].gpio);
rt_interrupt_leave();
}
void GPIO4_Combined_16_31_IRQHandler(int irqno, void *param)
{
rt_interrupt_enter();
imx6ull_isr(96, 15, mask_tab[3].gpio);
rt_interrupt_leave();
}
/* GPIO5 index offset is 128 */
void GPIO5_Combined_0_15_IRQHandler(int irqno, void *param)
{
rt_interrupt_enter();
imx6ull_isr(128, 0, mask_tab[4].gpio);
rt_interrupt_leave();
}
/* GPIO5 index offset is 128 */
void GPIO5_Combined_16_31_IRQHandler(int irqno, void *param)
{
rt_interrupt_enter();
imx6ull_isr(128, 0, mask_tab[4].gpio);
rt_interrupt_leave();
}
static const struct rt_pin_ops gpio_ops =
{
.pin_mode = imx6ull_pin_mode,
.pin_write = imx6ull_pin_write,
.pin_read = imx6ull_pin_read,
.pin_attach_irq = imx6ull_pin_attach_irq,
.pin_detach_irq = imx6ull_pin_detach_irq,
.pin_irq_enable = imx6ull_pin_irq_enable,
.pin_get = RT_NULL,
};
static void imx6ull_pin_interrupt_install(void)
{
rt_hw_interrupt_install(IMX_INT_GPIO1_INT15_0, GPIO1_Combined_0_15_IRQHandler, RT_NULL, "GPIO1_0_15");
rt_hw_interrupt_install(IMX_INT_GPIO1_INT31_16, GPIO1_Combined_16_31_IRQHandler, RT_NULL, "GPIO1_16_31");
rt_hw_interrupt_install(IMX_INT_GPIO2_INT15_0, GPIO2_Combined_0_15_IRQHandler, RT_NULL, "GPIO2_0_15");
rt_hw_interrupt_install(IMX_INT_GPIO2_INT31_16, GPIO2_Combined_16_31_IRQHandler, RT_NULL, "GPIO2_16_31");
rt_hw_interrupt_install(IMX_INT_GPIO3_INT15_0, GPIO3_Combined_0_15_IRQHandler, RT_NULL, "GPIO3_0_15");
rt_hw_interrupt_install(IMX_INT_GPIO3_INT31_16, GPIO3_Combined_16_31_IRQHandler, RT_NULL, "GPIO3_16_31");
rt_hw_interrupt_install(IMX_INT_GPIO4_INT15_0, GPIO4_Combined_0_15_IRQHandler, RT_NULL, "GPIO4_0_15");
rt_hw_interrupt_install(IMX_INT_GPIO4_INT31_16, GPIO4_Combined_16_31_IRQHandler, RT_NULL, "GPIO4_16_31");
rt_hw_interrupt_install(IMX_INT_GPIO5_INT15_0, GPIO5_Combined_0_15_IRQHandler, RT_NULL, "GPIO5_0_15");
rt_hw_interrupt_install(IMX_INT_GPIO5_INT31_16, GPIO5_Combined_16_31_IRQHandler, RT_NULL, "GPIO5_16_31");
rt_hw_interrupt_umask(IMX_INT_GPIO1_INT15_0);
rt_hw_interrupt_umask(IMX_INT_GPIO1_INT31_16);
rt_hw_interrupt_umask(IMX_INT_GPIO2_INT15_0);
rt_hw_interrupt_umask(IMX_INT_GPIO2_INT31_16);
rt_hw_interrupt_umask(IMX_INT_GPIO3_INT15_0);
rt_hw_interrupt_umask(IMX_INT_GPIO3_INT31_16);
rt_hw_interrupt_umask(IMX_INT_GPIO4_INT15_0);
rt_hw_interrupt_umask(IMX_INT_GPIO4_INT31_16);
rt_hw_interrupt_umask(IMX_INT_GPIO5_INT15_0);
rt_hw_interrupt_umask(IMX_INT_GPIO5_INT31_16);
}
int imx6ull_hw_pin_init(void)
{
iomuxc_base = (size_t)imx6ull_get_periph_vaddr(iomuxc_base);
iomuxc_snvs_base = (size_t)imx6ull_get_periph_vaddr(iomuxc_snvs_base);
for(int port = 0; port < sizeof(mask_tab) / sizeof(mask_tab[0]); port++)
{
mask_tab[port].gpio = (GPIO_Type *)imx6ull_get_periph_vaddr((rt_uint32_t)mask_tab[port].gpio);
CLOCK_EnableClock(mask_tab[port].gpio_clock);
}
imx6ull_pin_interrupt_install();
rt_device_pin_register("pin", &gpio_ops, RT_NULL);
rt_kprintf("pin driver init success\n");
return RT_EOK;
}
INIT_BOARD_EXPORT(imx6ull_hw_pin_init);

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-01-13 Lyons first version
* 2021-06-23 RiceChen add get pin API
*/
#ifndef __DRV_PIN_H__
#define __DRV_PIN_H__
#include "board.h"
#define GET_PIN(PORTx, PIN) (32 * (PORTx - 1) + (PIN & 31))
#endif //#ifndef __DRV_PIN_H__

View File

@ -0,0 +1,347 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-04-28 tyustli first version
*
*/
#include <rtthread.h>
#ifdef RT_USING_PWM
#define LOG_TAG "drv.pwm"
#include <drv_log.h>
#include <rtdevice.h>
#include <ioremap.h>
#include "fsl_pwm.h"
#include "drv_pwm.h"
#include <drv_common.h>
#include <drivers/rt_drv_pwm.h>
#define PWM_SRC_CLK_FREQ CLOCK_GetFreq(kCLOCK_IpgClk)
/* PWMPR register value of 0xffff has the same effect as 0xfffe */
#define IMX_PWMPR_MAX 0xfffe
#define NSEC_PER_MSEC 1000000
#define NSEC_PER_SEC 1000
#define MX3_PWMCR_SWR BIT(3)
#define MX3_PWM_SWR_LOOP 5
#define MX3_PWMSR_FIFOAV_EMPTY 0
#define MX3_PWMSR_FIFOAV_1WORD 1
#define MX3_PWMSR_FIFOAV_2WORDS 2
#define MX3_PWMSR_FIFOAV_3WORDS 3
#define MX3_PWMSR_FIFOAV_4WORDS 4
#define MX3_PWMCR_STOPEN BIT(25)
#define MX3_PWMCR_DOZEN BIT(24)
#define MX3_PWMCR_WAITEN BIT(23)
#define MX3_PWMCR_DBGEN BIT(22)
#define MX3_PWMCR_BCTR BIT(21)
#define MX3_PWMCR_HCTR BIT(20)
#define MX3_PWMCR_CLKSRC BIT(17)
#define MX3_PWMCR_EN BIT(0)
static rt_err_t imx6ull_drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg);
static struct rt_pwm_ops imxrt_drv_ops =
{
.control = imx6ull_drv_pwm_control
};
static void imx6ull_pwm_reset(PWM_Type *base)
{
int wait_count = 0;
uint32_t cr = 0;
base->PWMCR = MX3_PWMCR_SWR;
do {
rt_thread_mdelay(1);
cr = base->PWMCR;
} while ((cr & MX3_PWMCR_SWR) &&
(wait_count++ < MX3_PWM_SWR_LOOP));
if (cr & MX3_PWMCR_SWR)
{
LOG_E("software reset timeout\n");
}
}
static void imx6ull_pwm_wait_fifo_slot(PWM_Type *base, struct rt_pwm_configuration *configuration)
{
unsigned int period_ms = 0;
int fifoav = 0;
uint32_t sr = 0;
sr = base->PWMSR;
fifoav = sr & 0x7;
if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) {
period_ms = configuration->period / NSEC_PER_MSEC;
rt_thread_mdelay(period_ms);
sr = base->PWMSR;
if (fifoav == (sr & 0x7))
{
LOG_E("there is no free FIFO slot\n");
}
}
}
static rt_err_t imx6ull_pwm_enable(struct rt_device_pwm *device, rt_bool_t enable)
{
PWM_Type *base = (PWM_Type *)device->parent.user_data;
if (!enable)
{
pwm_stop_timer(base);
}
else
{
pwm_start_timer(base);
}
return RT_EOK;
}
static rt_err_t imx6ull_pwm_get(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
{
uint32_t period = 0, prescaler = 0, val = 0;
uint64_t tmp = 0;
PWM_Type *base = (PWM_Type *)device->parent.user_data;
uint32_t pwm_src_clk;
pwm_src_clk = PWM_SRC_CLK_FREQ / 1000000;
val = base->PWMCR;
prescaler = ((val >> 4) & 0xfff)+1;
val = base->PWMPR;
period = val >= IMX_PWMPR_MAX ? IMX_PWMPR_MAX : val;
tmp = NSEC_PER_SEC * (uint64_t)(period + 2) * prescaler;
configuration->period = (tmp) / pwm_src_clk;
val = base->PWMSAR;
tmp = NSEC_PER_SEC * (uint64_t)(val) * prescaler;
configuration->pulse = (tmp) / pwm_src_clk;
return RT_EOK;
}
static rt_err_t imx6ull_pwm_set(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
{
RT_ASSERT(configuration->period > 0);
RT_ASSERT(configuration->pulse <= configuration->period);
PWM_Type *base = (PWM_Type *)device->parent.user_data;
uint32_t period_cycles = 0, duty_cycles = 0, prescale = 0;
uint32_t cr = 0;
uint32_t pwm_src_clk = 0;
pwm_src_clk = PWM_SRC_CLK_FREQ / 1000000;
period_cycles = pwm_src_clk * configuration->period / NSEC_PER_SEC;
prescale = period_cycles / 0x10000 + 1;
period_cycles /= prescale;
duty_cycles = configuration->pulse * pwm_src_clk / NSEC_PER_SEC ;
duty_cycles /= prescale;
/*
* according to imx pwm RM, the real period value should be PERIOD
* value in PWMPR plus 2.
*/
if (period_cycles > 2)
{
period_cycles -= 2;
}
else
{
period_cycles = 0;
}
if (((base->PWMCR) & 0x1) == 1)
{
imx6ull_pwm_wait_fifo_slot(base, configuration);
}
else
{
pwm_start_timer(base);
imx6ull_pwm_reset(base);
}
base->PWMSAR = duty_cycles;
base->PWMPR = period_cycles;
cr = ((prescale -1 ) << 4) |
MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEN | MX3_PWMCR_WAITEN | MX3_PWMCR_CLKSRC | MX3_PWMCR_DBGEN;
cr |= MX3_PWMCR_EN;
base->PWMCR = cr;
return RT_EOK;
}
static rt_err_t imx6ull_drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
{
struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
switch (cmd)
{
case PWM_CMD_ENABLE:
return imx6ull_pwm_enable(device, RT_TRUE);
case PWM_CMD_DISABLE:
return imx6ull_pwm_enable(device, RT_FALSE);
case PWM_CMD_SET:
return imx6ull_pwm_set(device, configuration);
case PWM_CMD_GET:
return imx6ull_pwm_get(device, configuration);
default:
return RT_EINVAL;
}
}
static rt_err_t imx6ull_drv_pwm_init(PWM_Type *base)
{
pwm_config_t PwmConfig;
pwm_get_default_config(&PwmConfig);
if (pwm_init(base, &PwmConfig) == kStatus_Fail)
{
LOG_E("init pwm failed \n");
return RT_ERROR;
}
return RT_EOK;
}
int imx6ull_pwm_gpio_init(void)
{
#ifdef BSP_USING_PWM1
struct imx6ull_iomuxc gpio;
gpio.muxRegister = 0x020E007C;
gpio.muxMode = 0x0;
gpio.inputRegister = 0x00000000;
gpio.inputDaisy = 0x0;
gpio.configRegister = 0x020E0308;
gpio.inputOnfield = 0;
gpio.configValue = IOMUXC_SW_PAD_CTL_PAD_DSE(2U) | IOMUXC_SW_PAD_CTL_PAD_SPEED(2U);
imx6ull_gpio_init(&gpio);
#endif
return 0;
}
int rt_hw_pwm_init(void)
{
rt_err_t ret = RT_EOK;
#ifdef BSP_USING_PWM1
static struct rt_device_pwm pwm1_device;
PWM_Type *pwm1_base;
imx6ull_pwm_gpio_init();
pwm1_base = (PWM_Type *)rt_ioremap((void*)PWM1, 0x1000);
if (imx6ull_drv_pwm_init(pwm1_base) != RT_EOK)
{
LOG_E("init pwm1 failed\n");
}
ret = rt_device_pwm_register(&pwm1_device, "pwm1", &imxrt_drv_ops, pwm1_base);
if (ret != RT_EOK)
{
LOG_E("%s register failed", "pwm1");
}
#endif /* BSP_USING_PWM1 */
#ifdef BSP_USING_PWM2
static struct rt_device_pwm pwm2_device;
imx6ull_pwm_gpio_init();
if (imx6ull_drv_pwm_init(PWM2) != RT_EOK)
{
LOG_E("init pwm2 failed\n");
}
ret = rt_device_pwm_register(&pwm2_device, "pwm2", &imxrt_drv_ops, PWM2);
if (ret != RT_EOK)
{
LOG_E("%s register failed", "pwm2");
}
#endif /* BSP_USING_PWM2 */
#ifdef BSP_USING_PWM3
static struct rt_device_pwm pwm3_device;
imx6ull_pwm_gpio_init();
if (imx6ull_drv_pwm_init(PWM3) != RT_EOK)
{
LOG_E("init pwm3 failed\n");
}
ret = rt_device_pwm_register(&pwm3_device, "pwm3", &imxrt_drv_ops, PWM3);
if (ret != RT_EOK)
{
LOG_E("%s register failed", "pwm3");
}
#endif /* BSP_USING_PWM3 */
#ifdef BSP_USING_PWM4
static struct rt_device_pwm pwm4_device;
imx6ull_pwm_gpio_init();
if (imx6ull_drv_pwm_init(PWM4) != RT_EOK)
{
LOG_E("init pwm4 failed\n");
}
ret = rt_device_pwm_register(&pwm4_device, "pwm4", &imxrt_drv_ops, PWM4);
if (ret != RT_EOK)
{
LOG_E("%s register failed", "pwm4");
}
#endif /* BSP_USING_PWM4 */
return ret;
}
INIT_DEVICE_EXPORT(rt_hw_pwm_init);
int set_pwm_default(void)
{
int result = 0;
struct rt_device_pwm *device = RT_NULL;
device = (struct rt_device_pwm *)rt_device_find("pwm1");
if (!device)
{
result = -RT_EIO;
goto _exit;
}
result = rt_pwm_set(device, 1, 1000000, 500000);
result = rt_pwm_enable(device, 1);
_exit:
return result;
}
INIT_APP_EXPORT(set_pwm_default);
#endif /* BSP_USING_PWM */

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-04-28 tyustli the first version.
*
*/
#ifndef DRV_PWM_H__
#define DRV_PWM_H__
#include <rtdevice.h>
#define BIT(nr) ((1) << (nr))
int rt_hw_pwm_init(void);
#endif

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-25 Lyons first version
*/
#include <rtconfig.h>
#ifdef BSP_USING_ONCHIP_RTC
#include "board.h"
#define DBG_TAG "drv.rtc"
#define DBG_LVL DBG_WARNING
#include <rtdbg.h>
#define _DEVICE_NAME "rtc"
_internal_rw struct rt_device _s_rtc_device;
static time_t _get_rtc_timestamp(void)
{
snvs_hp_rtc_datetime_t rtcDate;
SNVS_Type *snvs = (SNVS_Type*)g_snvs_vbase;
struct tm tm_new;
SNVS_HP_RTC_GetDatetime(snvs, &rtcDate);
tm_new.tm_sec = rtcDate.second;
tm_new.tm_min = rtcDate.minute;
tm_new.tm_hour = rtcDate.hour;
tm_new.tm_mday = rtcDate.day;
tm_new.tm_mon = rtcDate.month - 1;
tm_new.tm_year = rtcDate.year - 1900;
return mktime(&tm_new);
}
static rt_err_t _set_rtc_time_stamp(time_t time_stamp)
{
snvs_hp_rtc_datetime_t rtcDate;
SNVS_Type *snvs = (SNVS_Type*)g_snvs_vbase;
struct tm *p_tm;
p_tm = localtime(&time_stamp);
rtcDate.second = p_tm->tm_sec;
rtcDate.minute = p_tm->tm_min;
rtcDate.hour = p_tm->tm_hour;
rtcDate.day = p_tm->tm_mday;
rtcDate.month = p_tm->tm_mon + 1;
rtcDate.year = p_tm->tm_year + 1900;
if (kStatus_Success != SNVS_HP_RTC_SetDatetime(snvs, &rtcDate))
{
return -RT_ERROR;
}
return RT_EOK;
}
static void _rtc_init(void)
{
snvs_hp_rtc_config_t snvsRtcConfig;
SNVS_Type *snvs = (SNVS_Type*)g_snvs_vbase;
SNVS_HP_RTC_GetDefaultConfig(&snvsRtcConfig);
SNVS_HP_RTC_Init(snvs, &snvsRtcConfig);
SNVS_HP_RTC_StartTimer(snvs);
}
static rt_err_t _rtc_config(struct rt_device *dev)
{
return RT_EOK;
}
static rt_err_t _rtc_ops_control( rt_device_t dev, int cmd, void *args )
{
rt_err_t result;
RT_ASSERT(RT_NULL != dev);
result = RT_EOK;
switch (cmd)
{
case RT_DEVICE_CTRL_RTC_GET_TIME:
*(time_t *)args = _get_rtc_timestamp();
LOG_D("RTC: get rtc_time %x", *(time_t *)args);
break;
case RT_DEVICE_CTRL_RTC_SET_TIME:
if (_set_rtc_time_stamp(*(time_t *)args))
{
result = -RT_ERROR;
}
LOG_D("RTC: set rtc_time %x", *(time_t *)args);
break;
}
return result;
}
#ifdef RT_USING_DEVICE_OPS
_internal_ro struct rt_device_ops _k_rtc_ops =
{
RT_NULL, /* init */
RT_NULL, /* open */
RT_NULL, /* close */
RT_NULL, /* read */
RT_NULL, /* write */
_rtc_ops_control, /* control */
};
#endif
static rt_err_t _rt_rtc_register( rt_device_t device, const char *name, rt_uint32_t flag )
{
RT_ASSERT(RT_NULL != device);
_rtc_init();
if (RT_EOK != _rtc_config(device))
{
return -RT_ERROR;
}
device->type = RT_Device_Class_RTC;
#ifdef RT_USING_DEVICE_OPS
device->ops = &_k_rtc_ops;
#else
device->init = RT_NULL;
device->open = RT_NULL;
device->close = RT_NULL;
device->read = RT_NULL;
device->write = RT_NULL;
device->control = _rtc_ops_control;
#endif
device->user_data = RT_NULL;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
/* register a character device */
return rt_device_register(device, name, flag);
}
int rt_hw_rtc_init(void)
{
rt_err_t result;
result = _rt_rtc_register(&_s_rtc_device, _DEVICE_NAME, RT_DEVICE_FLAG_RDWR);
if (RT_EOK != result)
{
LOG_E("rtc register err code: %d", result);
return result;
}
LOG_D("rtc init success.");
return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_rtc_init);
#endif /* BSP_USING_ONCHIP_RTC */

View File

@ -0,0 +1,94 @@
#include <rtthread.h>
#ifdef PKG_USING_RW007
#include <rtdevice.h>
#include <drv_spi.h>
#include <drv_pin.h>
#include <board.h>
#include <spi_wifi_rw007.h>
#ifndef PKG_USING_RW007_LATEST_VERSION
#error "please select rw007 latest version."
#endif
#define RW007_SPI_BUS_NAME "spi2"
#define RW007_CS_PIN GET_PIN(1, 29) /* IOMUXC_UART4_RX_DATA_ECSPI2_SS0 IOMUXC_UART4_RX_DATA_GPIO1_IO29 */
#define RW007_INT_BUSY_PIN GET_PIN(5, 0) /* IOMUXC_SNVS_SNVS_TAMPER0_GPIO5_IO00 */
#define RW007_RST_PIN GET_PIN(5, 1) /* IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01 */
extern void spi_wifi_isr(int vector);
static int rw007_gpio_init(void)
{
int ret = 0;
uint8_t errorCnt = 10;
/* Configure IO */
rt_pin_mode(RW007_RST_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(RW007_INT_BUSY_PIN, PIN_MODE_INPUT_PULLDOWN);
/* Reset rw007 and config mode */
rt_pin_write(RW007_RST_PIN, PIN_LOW);
rt_thread_delay(rt_tick_from_millisecond(100));
rt_pin_write(RW007_RST_PIN, PIN_HIGH);
/* Wait rw007 ready(exit busy stat) */
while(!rt_pin_read(RW007_INT_BUSY_PIN))
{
rt_thread_delay(rt_tick_from_millisecond(100));
if (errorCnt)
{
errorCnt--;
}
else
{
ret = -1;
break;
}
}
rt_thread_delay(rt_tick_from_millisecond(200));
rt_pin_mode(RW007_INT_BUSY_PIN, PIN_MODE_INPUT_PULLUP);
return ret;
}
int wifi_spi_device_init(void)
{
char sn_version[32];
if (rw007_gpio_init() == -1)
{
rt_hw_wifi_init("rw007 gpio init fault!\n");
return -1;
}
rt_hw_spi_device_attach(RW007_SPI_BUS_NAME, "rw007", RW007_CS_PIN);
rt_hw_wifi_init("rw007");
rt_wlan_set_mode(RT_WLAN_DEVICE_STA_NAME, RT_WLAN_STATION);
rt_wlan_set_mode(RT_WLAN_DEVICE_AP_NAME, RT_WLAN_AP);
rw007_sn_get(sn_version);
rt_kprintf("\nrw007 sn: [%s]\n", sn_version);
rw007_version_get(sn_version);
rt_kprintf("rw007 ver: [%s]\n\n", sn_version);
#ifdef RW007_DAFAULT_SSID
rt_wlan_connect(RW007_DAFAULT_SSID, RW007_DAFAULT_PASSWARD);
#endif
return 0;
}
INIT_APP_EXPORT(wifi_spi_device_init);
static void int_wifi_irq(void * p)
{
((void)p);
spi_wifi_isr(0);
}
void spi_wifi_hw_init(void)
{
rt_pin_attach_irq(RW007_INT_BUSY_PIN, PIN_IRQ_MODE_FALLING, int_wifi_irq, 0);
rt_pin_irq_enable(RW007_INT_BUSY_PIN, RT_TRUE);
}
#endif /* RW007_USING_STM32_DRIVERS */

View File

@ -0,0 +1,706 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-10-10 Tanek first version
* 2021-07-07 linzhenxing add sd card drivers in mmu
* 2021-07-14 linzhenxing add emmc
*/
#include <rtthread.h>
#include <rthw.h>
#include <drivers/mmcsd_core.h>
#include <ioremap.h>
#include <board.h>
#include <fsl_usdhc.h>
#include <fsl_gpio.h>
#include <fsl_iomuxc.h>
#include <ioremap.h>
#include <string.h>
#define DBG_TAG "drv_sdio"
#ifdef RT_SDIO_DEBUG
#define DBG_LVL DBG_LOG
#else
#define DBG_LVL DBG_INFO
#endif /* RT_SDIO_DEBUG */
#include <rtdbg.h>
#define CACHE_LINESIZE (32)
#define USDHC_ADMA_TABLE_WORDS (8U) /* define the ADMA descriptor table length */
#define USDHC_ADMA2_ADDR_ALIGN (4U) /* define the ADMA2 descriptor table addr align size */
#define IMXRT_MAX_FREQ (52UL * 1000UL * 1000UL)
#define USDHC_ADMA_TABLE_WORDS (8U) /* define the ADMA descriptor table length */
#define USDHC_ADMA2_ADDR_ALIGN (4U) /* define the ADMA2 descriptor table addr align size */
#define USDHC_READ_BURST_LEN (8U) /*!< number of words USDHC read in a single burst */
#define USDHC_WRITE_BURST_LEN (8U) /*!< number of words USDHC write in a single burst */
#define USDHC_DATA_TIMEOUT (0xFU) /*!< data timeout counter value */
/* Read/write watermark level. The bigger value indicates DMA has higher read/write performance. */
#define USDHC_READ_WATERMARK_LEVEL (0x80U)
#define USDHC_WRITE_WATERMARK_LEVEL (0x80U)
/* DMA mode */
#define USDHC_DMA_MODE kUSDHC_DmaModeAdma2
/* Endian mode. */
#define USDHC_ENDIAN_MODE kUSDHC_EndianModeLittle
uint32_t g_usdhcAdma2Table[USDHC_ADMA_TABLE_WORDS];
struct rt_mmcsd_host *host1;
struct rt_mmcsd_host *host2;
static rt_mutex_t mmcsd_mutex = RT_NULL;
void host_change(void);
struct imxrt_mmcsd
{
struct rt_mmcsd_host *host;
struct rt_mmcsd_req *req;
struct rt_mmcsd_cmd *cmd;
struct rt_timer timer;
rt_uint32_t *buf;
usdhc_host_t usdhc_host;
clock_div_t usdhc_div;
clock_ip_name_t ip_clock;
uint32_t *usdhc_adma2_table;
};
/*! @name Configuration */
/*@{*/
/*!
* @brief Sets the IOMUXC pin mux mode.
* @note The first five parameters can be filled with the pin function ID macros.
*
* This is an example to set the ENET1_RX_DATA0 Pad as FLEXCAN1_TX:
* @code
* IOMUXC_SetPinMux(IOMUXC_ENET1_RX_DATA0_FLEXCAN1_TX, 0);
* @endcode
*
* This is an example to set the GPIO1_IO02 Pad as I2C1_SCL:
* @code
* IOMUXC_SetPinMux(IOMUXC_GPIO1_IO02_I2C1_SCL, 0);
* @endcode
*
* @param muxRegister The pin mux register.
* @param muxMode The pin mux mode.
* @param inputRegister The select input register.
* @param inputDaisy The input daisy.
* @param configRegister The config register.
* @param inputOnfield Software input on field.
*/
static inline void _IOMUXC_SetPinMux(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t inputOnfield)
{
*((volatile uint32_t *)rt_ioremap((void*)muxRegister, 0x4)) =
IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield);
if (inputRegister)
{
*((volatile uint32_t *)rt_ioremap((void*)inputRegister, 0x4)) = IOMUXC_SELECT_INPUT_DAISY(inputDaisy);
}
}
/*!
* @brief Sets the IOMUXC pin configuration.
* @note The previous five parameters can be filled with the pin function ID macros.
*
* This is an example to set pin configuration for IOMUXC_GPIO1_IO02_I2C1_SCL:
* @code
* IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO02_I2C1_SCL, IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(2U));
* @endcode
*
* @param muxRegister The pin mux register.
* @param muxMode The pin mux mode.
* @param inputRegister The select input register.
* @param inputDaisy The input daisy.
* @param configRegister The config register.
* @param configValue The pin config value.
*/
static inline void _IOMUXC_SetPinConfig(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t configValue)
{
if (configRegister)
{
*((volatile uint32_t *)rt_ioremap((void*)configRegister, 0x4)) = configValue;
}
}
static void _mmcsd_gpio_init(struct imxrt_mmcsd *mmcsd)
{
CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
#ifdef RT_USING_SDIO1
/* uSDHC1 pins start*/
_IOMUXC_SetPinMux(IOMUXC_UART1_RTS_B_USDHC1_CD_B, 0U);
_IOMUXC_SetPinConfig(IOMUXC_UART1_RTS_B_USDHC1_CD_B,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_SD1_CLK_USDHC1_CLK, 0U);
_IOMUXC_SetPinConfig(IOMUXC_SD1_CLK_USDHC1_CLK,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(1U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_SD1_CMD_USDHC1_CMD, 0U);
_IOMUXC_SetPinConfig(IOMUXC_SD1_CMD_USDHC1_CMD,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_SD1_DATA0_USDHC1_DATA0, 0U);
_IOMUXC_SetPinConfig(IOMUXC_SD1_DATA0_USDHC1_DATA0,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_SD1_DATA1_USDHC1_DATA1, 0U);
_IOMUXC_SetPinConfig(IOMUXC_SD1_DATA1_USDHC1_DATA1,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_SD1_DATA2_USDHC1_DATA2, 0U);
_IOMUXC_SetPinConfig(IOMUXC_SD1_DATA2_USDHC1_DATA2,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_SD1_DATA3_USDHC1_DATA3, 0U);
_IOMUXC_SetPinConfig(IOMUXC_SD1_DATA3_USDHC1_DATA3,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
/* uSDHC1 pins end*/
#endif
#ifdef RT_USING_SDIO2
/* uSDHC2 pins start*/
_IOMUXC_SetPinMux(IOMUXC_NAND_WE_B_USDHC2_CMD, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_WE_B_USDHC2_CMD,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_NAND_RE_B_USDHC2_CLK, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_RE_B_USDHC2_CLK,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_NAND_ALE_USDHC2_RESET_B, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_ALE_USDHC2_RESET_B,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_NAND_DATA00_USDHC2_DATA0, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_DATA00_USDHC2_DATA0,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_NAND_DATA01_USDHC2_DATA1, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_DATA01_USDHC2_DATA1,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_NAND_DATA02_USDHC2_DATA2, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_DATA02_USDHC2_DATA2,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_NAND_DATA03_USDHC2_DATA3, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_DATA03_USDHC2_DATA3,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_NAND_DATA04_USDHC2_DATA4, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_DATA04_USDHC2_DATA4,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_NAND_DATA05_USDHC2_DATA5, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_DATA05_USDHC2_DATA5,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_NAND_DATA06_USDHC2_DATA6, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_DATA06_USDHC2_DATA6,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(7U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
_IOMUXC_SetPinMux(IOMUXC_NAND_DATA07_USDHC2_DATA7, 0U);
_IOMUXC_SetPinConfig(IOMUXC_NAND_DATA07_USDHC2_DATA7,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
/* uSDHC2 pins end*/
#endif
}
static void SDMMCHOST_ErrorRecovery(USDHC_Type *base)
{
uint32_t status = 0U;
/* get host present status */
status = USDHC_GetPresentStatusFlags(base);
/* check command inhibit status flag */
if ((status & kUSDHC_CommandInhibitFlag) != 0U)
{
/* reset command line */
USDHC_Reset(base, kUSDHC_ResetCommand, 1000U);
}
/* check data inhibit status flag */
if ((status & kUSDHC_DataInhibitFlag) != 0U)
{
/* reset data line */
USDHC_Reset(base, kUSDHC_ResetData, 1000U);
}
}
static void _mmcsd_host_init(struct imxrt_mmcsd *mmcsd)
{
usdhc_host_t *usdhc_host = &mmcsd->usdhc_host;
/* Initializes SDHC. */
usdhc_host->config.dataTimeout = USDHC_DATA_TIMEOUT;
usdhc_host->config.endianMode = USDHC_ENDIAN_MODE;
usdhc_host->config.readWatermarkLevel = USDHC_READ_WATERMARK_LEVEL;
usdhc_host->config.writeWatermarkLevel = USDHC_WRITE_WATERMARK_LEVEL;
usdhc_host->config.readBurstLen = USDHC_READ_BURST_LEN;
usdhc_host->config.writeBurstLen = USDHC_WRITE_BURST_LEN;
USDHC_Init(usdhc_host->base, &(usdhc_host->config));
}
static void _mmcsd_clk_init(struct imxrt_mmcsd *mmcsd)
{
CLOCK_EnableClock(mmcsd->ip_clock);
CLOCK_SetDiv(mmcsd->usdhc_div, 5U);
}
static void _mmc_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
{
struct imxrt_mmcsd *mmcsd;
struct rt_mmcsd_cmd *cmd;
struct rt_mmcsd_data *data;
status_t error;
usdhc_adma_config_t dmaConfig;
usdhc_transfer_t fsl_content = {0};
usdhc_command_t fsl_command = {0};
usdhc_data_t fsl_data = {0};
rt_uint32_t *buf = NULL;
rt_mutex_take(mmcsd_mutex, RT_WAITING_FOREVER);
RT_ASSERT(host != RT_NULL);
RT_ASSERT(req != RT_NULL);
mmcsd = (struct imxrt_mmcsd *)host->private_data;
RT_ASSERT(mmcsd != RT_NULL);
cmd = req->cmd;
RT_ASSERT(cmd != RT_NULL);
LOG_D("\tcmd->cmd_code: %02d, cmd->arg: %08x, cmd->flags: %08x --> ", cmd->cmd_code, cmd->arg, cmd->flags);
data = cmd->data;
memset(&dmaConfig, 0, sizeof(usdhc_adma_config_t));
/* config adma */
dmaConfig.dmaMode = USDHC_DMA_MODE;
dmaConfig.burstLen = kUSDHC_EnBurstLenForINCR;
dmaConfig.admaTable = mmcsd->usdhc_adma2_table;
dmaConfig.admaTableWords = USDHC_ADMA_TABLE_WORDS;
fsl_command.index = cmd->cmd_code;
fsl_command.argument = cmd->arg;
if (cmd->cmd_code == STOP_TRANSMISSION)
fsl_command.type = kCARD_CommandTypeAbort;
else
fsl_command.type = kCARD_CommandTypeNormal;
switch (cmd->flags & RESP_MASK)
{
case RESP_NONE:
fsl_command.responseType = kCARD_ResponseTypeNone;
break;
case RESP_R1:
fsl_command.responseType = kCARD_ResponseTypeR1;
break;
case RESP_R1B:
fsl_command.responseType = kCARD_ResponseTypeR1b;
break;
case RESP_R2:
fsl_command.responseType = kCARD_ResponseTypeR2;
break;
case RESP_R3:
fsl_command.responseType = kCARD_ResponseTypeR3;
break;
case RESP_R4:
fsl_command.responseType = kCARD_ResponseTypeR4;
break;
case RESP_R6:
fsl_command.responseType = kCARD_ResponseTypeR6;
break;
case RESP_R7:
fsl_command.responseType = kCARD_ResponseTypeR7;
break;
case RESP_R5:
fsl_command.responseType = kCARD_ResponseTypeR5;
break;
default:
RT_ASSERT(NULL);
}
fsl_command.flags = 0;
fsl_content.command = &fsl_command;
if (data)
{
if (req->stop != NULL)
fsl_data.enableAutoCommand12 = true;
else
fsl_data.enableAutoCommand12 = false;
fsl_data.enableAutoCommand23 = false;
fsl_data.enableIgnoreError = false;
fsl_data.blockSize = data->blksize;
fsl_data.blockCount = data->blks;
LOG_D(" blksize:%d, blks:%d ", fsl_data.blockSize, fsl_data.blockCount);
if (((rt_uint32_t)data->buf & (CACHE_LINESIZE - 1)) || // align cache(32byte)
((rt_uint32_t)data->buf > 0x00000000 && (rt_uint32_t)data->buf < 0x00080000) /*|| // ITCM
((rt_uint32_t)data->buf >= 0x20000000 && (rt_uint32_t)data->buf < 0x20080000)*/) // DTCM
{
buf = rt_malloc_align(fsl_data.blockSize * fsl_data.blockCount, CACHE_LINESIZE);
RT_ASSERT(buf != RT_NULL);
LOG_D(" malloc buf: %p, data->buf:%p, %d ", buf, data->buf, fsl_data.blockSize * fsl_data.blockCount);
}
if ((cmd->cmd_code == WRITE_BLOCK) || (cmd->cmd_code == WRITE_MULTIPLE_BLOCK))
{
if (buf)
{
LOG_D(" write(data->buf to buf) ");
rt_memcpy(buf, data->buf, fsl_data.blockSize * fsl_data.blockCount);
fsl_data.txData = (uint32_t const *)buf;
}
else
{
fsl_data.txData = (uint32_t const *)data->buf;
}
fsl_data.rxData = NULL;
}
else
{
if (buf)
{
fsl_data.rxData = (uint32_t *)buf;
}
else
{
fsl_data.rxData = (uint32_t *)data->buf;
}
fsl_data.txData = NULL;
}
fsl_content.data = &fsl_data;
}
else
{
fsl_content.data = NULL;
}
error = USDHC_TransferBlocking(mmcsd->usdhc_host.base, &dmaConfig, &fsl_content);
if (error == kStatus_Fail)
{
SDMMCHOST_ErrorRecovery(mmcsd->usdhc_host.base);
LOG_D(" ***USDHC_TransferBlocking error: %d*** --> \n", error);
cmd->err = -RT_ERROR;
}
if (buf)
{
if (fsl_data.rxData)
{
LOG_D("read copy buf to data->buf ");
rt_memcpy(data->buf, buf, fsl_data.blockSize * fsl_data.blockCount);
}
rt_free_align(buf);
}
if ((cmd->flags & RESP_MASK) == RESP_R2)
{
cmd->resp[3] = fsl_command.response[0];
cmd->resp[2] = fsl_command.response[1];
cmd->resp[1] = fsl_command.response[2];
cmd->resp[0] = fsl_command.response[3];
LOG_D(" resp 0x%08X 0x%08X 0x%08X 0x%08X\n",
cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
}
else
{
cmd->resp[0] = fsl_command.response[0];
LOG_D(" resp 0x%08X\n", cmd->resp[0]);
}
mmcsd_req_complete(host);
rt_mutex_release(mmcsd_mutex);
return;
}
static void _mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
{
struct imxrt_mmcsd *mmcsd;
unsigned int usdhc_clk;
unsigned int bus_width;
uint32_t src_clk;
RT_ASSERT(host != RT_NULL);
RT_ASSERT(host->private_data != RT_NULL);
RT_ASSERT(io_cfg != RT_NULL);
mmcsd = (struct imxrt_mmcsd *)host->private_data;
usdhc_clk = io_cfg->clock;
bus_width = io_cfg->bus_width;
if (usdhc_clk > IMXRT_MAX_FREQ)
usdhc_clk = IMXRT_MAX_FREQ;
src_clk = (CLOCK_GetSysPfdFreq(kCLOCK_Pfd2) / (CLOCK_GetDiv(mmcsd->usdhc_div) + 1U));
LOG_D("\tsrc_clk: %d, usdhc_clk: %d, bus_width: %d\n", src_clk, usdhc_clk, bus_width);
if (usdhc_clk)
{
USDHC_SetSdClock(mmcsd->usdhc_host.base, src_clk, usdhc_clk);
/* Change bus width */
if (bus_width == MMCSD_BUS_WIDTH_8)
USDHC_SetDataBusWidth(mmcsd->usdhc_host.base, kUSDHC_DataBusWidth8Bit);
else if (bus_width == MMCSD_BUS_WIDTH_4)
USDHC_SetDataBusWidth(mmcsd->usdhc_host.base, kUSDHC_DataBusWidth4Bit);
else if (bus_width == MMCSD_BUS_WIDTH_1)
USDHC_SetDataBusWidth(mmcsd->usdhc_host.base, kUSDHC_DataBusWidth1Bit);
else
RT_ASSERT(RT_NULL);
}
}
static const struct rt_mmcsd_host_ops ops =
{
_mmc_request,
_mmc_set_iocfg,
RT_NULL,//_mmc_get_card_status,
RT_NULL,//_mmc_enable_sdio_irq,
};
rt_int32_t imxrt_mci_init(void)
{
#ifdef RT_USING_SDIO1
struct imxrt_mmcsd *mmcsd1;
host1 = mmcsd_alloc_host();
if (!host1)
{
return -RT_ERROR;
}
mmcsd1 = rt_malloc(sizeof(struct imxrt_mmcsd));
if (!mmcsd1)
{
LOG_E("alloc mci failed\n");
goto err;
}
rt_memset(mmcsd1, 0, sizeof(struct imxrt_mmcsd));
mmcsd1->usdhc_host.base = (USDHC_Type *)rt_ioremap((void*)USDHC1_BASE, 0x1000);
mmcsd1->usdhc_div = kCLOCK_Usdhc1Div;
mmcsd1->usdhc_adma2_table = g_usdhcAdma2Table;
strncpy(host1->name, "sd", sizeof(host1->name)-1);
host1->ops = &ops;
host1->freq_min = 375000;
host1->freq_max = 25000000;
host1->valid_ocr = VDD_32_33 | VDD_33_34;
host1->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | \
MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
host1->max_seg_size = 65535;
host1->max_dma_segs = 2;
host1->max_blk_size = 512;
host1->max_blk_count = 4096;
mmcsd1->host = host1;
_mmcsd_clk_init(mmcsd1);
_mmcsd_gpio_init(mmcsd1);
_mmcsd_host_init(mmcsd1);
host1->private_data = mmcsd1;
mmcsd_change(host1);
#endif
#ifdef RT_USING_SDIO2
struct imxrt_mmcsd *mmcsd2;
host2 = mmcsd_alloc_host();
if (!host2)
{
return -RT_ERROR;
}
mmcsd2 = rt_malloc(sizeof(struct imxrt_mmcsd));
if (!mmcsd2)
{
LOG_E("alloc mci failed\n");
goto err;
}
rt_memset(mmcsd2, 0, sizeof(struct imxrt_mmcsd));
mmcsd2->usdhc_host.base = (USDHC_Type *)rt_ioremap((void*)USDHC2_BASE, 0x1000);
mmcsd2->usdhc_div = kCLOCK_Usdhc1Div;
mmcsd2->usdhc_adma2_table = g_usdhcAdma2Table;
strncpy(host2->name, "emmc", sizeof(host2->name)-1);
host2->ops = &ops;
host2->freq_min = 375000;
host2->freq_max = 52000000;
host2->valid_ocr = VDD_35_36;
host2->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | \
MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
host2->max_seg_size = 65535;
host2->max_dma_segs = 2;
host2->max_blk_size = 512;
host2->max_blk_count = 4096;
mmcsd2->host = host2;
_mmcsd_clk_init(mmcsd2);
_mmcsd_gpio_init(mmcsd2);
_mmcsd_host_init(mmcsd2);
host2->private_data = mmcsd2;
mmcsd_change(host2);
#endif
mmcsd_mutex = rt_mutex_create("mmutex", RT_IPC_FLAG_FIFO);
if (mmcsd_mutex == RT_NULL)
{
LOG_E("create mmcsd mutex failed.\n");
return -1;
}
return 0;
err:
#ifdef RT_USING_SDIO1
mmcsd_free_host(host1);
#endif
#ifdef RT_USING_SDIO2
mmcsd_free_host(host2);
#endif
return -RT_ENOMEM;
}
INIT_DEVICE_EXPORT(imxrt_mci_init);
void host_change(void)
{
mmcsd_change(host1);
}

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-07-14 linzhenxing first version
*/
#ifndef __DRV_SDIO_H__
#define __DRV_SDIO_H__
void host_change(void);
#endif

View File

@ -0,0 +1,207 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-13 Lyons first version
* 2021-06-23 RiceChen refactor
*/
#include <rthw.h>
#include <rtdevice.h>
#ifdef BSP_USING_SPI
#define LOG_TAG "drv.spi"
#include <drv_log.h>
#include "fsl_iomuxc.h"
#include "drv_spi.h"
static struct imx6ull_spi_config spi_config[] =
{
#ifdef BSP_USING_SPI1
SPI1_BUS_CONFIG,
#endif
#ifdef BSP_USING_SPI2
SPI2_BUS_CONFIG,
#endif
#ifdef BSP_USING_SPI3
SPI3_BUS_CONFIG,
#endif
#ifdef BSP_USING_SPI4
SPI4_BUS_CONFIG,
#endif
};
static struct imx6ull_spi_bus spi_obj[sizeof(spi_config) / sizeof(spi_config[0])];
static rt_err_t imx6ull_ecspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
{
struct imx6ull_spi_bus *spi_dev = RT_NULL;
ecspi_master_config_t config;
rt_uint32_t scr_clock = 0;
spi_dev = (struct imx6ull_spi_bus *)(device->bus->parent.user_data);
ECSPI_MasterGetDefaultConfig(&config);
config.samplePeriod = 10;
config.txFifoThreshold = 0;
config.channelConfig.dataLineInactiveState = kECSPI_DataLineInactiveStateHigh;
if (cfg->data_width == 8)
{
config.burstLength = 8;
}
else
{
return -RT_EINVAL;
}
if (cfg->mode & RT_SPI_SLAVE)
{
config.channelConfig.channelMode = kECSPI_Slave;
}
else
{
config.channelConfig.channelMode = kECSPI_Master;
}
if(cfg->mode & RT_SPI_CPHA)
{
config.channelConfig.phase = kECSPI_ClockPhaseSecondEdge;
}
else
{
config.channelConfig.phase = kECSPI_ClockPhaseFirstEdge;
}
if(cfg->mode & RT_SPI_CPOL)
{
config.channelConfig.polarity = kECSPI_PolarityActiveLow;
}
else
{
config.channelConfig.polarity = kECSPI_PolarityActiveHigh;
}
config.baudRate_Bps = cfg->max_hz;
scr_clock = (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 8U);
ECSPI_MasterInit(spi_dev->config->ECSPI, &config, scr_clock);
return RT_EOK;
}
static rt_ssize_t imx6ull_ecspi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
struct imx6ull_spi_bus *spi_dev = RT_NULL;
struct imx6ull_spi_cs *cs = RT_NULL;
const rt_uint8_t *send_ptr = RT_NULL;
rt_uint8_t *recv_ptr = RT_NULL;
rt_uint16_t size = 0;
rt_uint8_t temp_data;
spi_dev = (struct imx6ull_spi_bus *)(device->bus->parent.user_data);
cs = (struct imx6ull_spi_cs *)device->parent.user_data;
recv_ptr = (rt_uint8_t *)message->recv_buf;
send_ptr = (rt_uint8_t *)message->send_buf;
size = message->length;
if(message->cs_take && cs)
{
rt_pin_write(cs->pin, PIN_LOW);
}
ECSPI_SetChannelSelect(spi_dev->config->ECSPI, kECSPI_Channel0);
while (size--)
{
temp_data = (send_ptr != RT_NULL) ? (*send_ptr++) : 0xff;
while (!(spi_dev->config->ECSPI->STATREG & ECSPI_STATREG_TE_MASK));
ECSPI_WriteData(spi_dev->config->ECSPI, temp_data);
while (!(spi_dev->config->ECSPI->STATREG & ECSPI_STATREG_RR_MASK));
temp_data = ECSPI_ReadData(spi_dev->config->ECSPI);
if (recv_ptr != RT_NULL)
{
*recv_ptr++ = temp_data;
}
}
if(message->cs_release && cs)
{
rt_pin_write(cs->pin, PIN_HIGH);
}
return message->length;
}
rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin)
{
rt_err_t ret = RT_EOK;
struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
RT_ASSERT(spi_device != RT_NULL);
struct imx6ull_spi_cs *cs_pin = (struct imx6ull_spi_cs *)rt_malloc(sizeof(struct imx6ull_spi_cs));
RT_ASSERT(cs_pin != RT_NULL);
cs_pin->pin = pin;
rt_pin_mode(pin, PIN_MODE_OUTPUT);
rt_pin_write(pin, PIN_HIGH);
ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
return ret;
}
static rt_err_t imx6ull_spi_gpio_init(struct imx6ull_spi_bus *bus)
{
struct imx6ull_spi_bus *spi_bus = RT_NULL;
spi_bus = (struct imx6ull_spi_bus *)bus;
imx6ull_gpio_init(&spi_bus->config->clk_gpio);
imx6ull_gpio_init(&spi_bus->config->miso_gpio);
imx6ull_gpio_init(&spi_bus->config->mosi_gpio);
return RT_EOK;
}
#ifdef RT_USING_DEVICE_OPS
static const struct rt_spi_ops imxrt_spi_ops =
{
.configure = imx6ull_ecspi_configure,
.xfer = imx6ull_ecspi_xfer,
};
#endif
int rt_hw_spi_init(void)
{
rt_uint16_t obj_num = 0;
obj_num = sizeof(spi_config) / sizeof(spi_config[0]);
for(int i = 0; i < obj_num; i++)
{
spi_obj[i].config = &spi_config[i];
spi_obj[i].config->ECSPI = (ECSPI_Type *)imx6ull_get_periph_vaddr((rt_uint32_t)(spi_obj[i].config->ECSPI));
imx6ull_spi_gpio_init(&spi_obj[i]);
CLOCK_EnableClock(spi_obj[i].config->clk_ip_name);
spi_obj[i].parent.parent.user_data = &spi_obj[i];
rt_spi_bus_register(&spi_obj[i].parent, spi_obj[i].config->name, &imxrt_spi_ops);
}
return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_spi_init);
#endif

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-13 Lyons first version
* 2021-06-23 RiceChen refactor
*/
#ifndef __DRV_SPI_H__
#define __DRV_SPI_H__
#include <board.h>
#include "drv_common.h"
#include "fsl_iomuxc.h"
#include "fsl_clock.h"
#include "fsl_ecspi.h"
struct imx6ull_spi_cs
{
rt_uint32_t pin;
};
struct imx6ull_spi_config
{
ECSPI_Type *ECSPI;
char *name;
rt_uint32_t clk_ip_name;
struct imx6ull_iomuxc clk_gpio;
struct imx6ull_iomuxc miso_gpio;
struct imx6ull_iomuxc mosi_gpio;
};
struct imx6ull_spi_bus
{
struct rt_spi_bus parent;
struct imx6ull_spi_config *config;
};
#ifdef BSP_USING_SPI1
#define SPI1_BUS_CONFIG \
{ \
.ECSPI = ECSPI1, \
.name = "spi1", \
.clk_ip_name = kCLOCK_Ecspi1, \
.clk_gpio = {IOMUXC_CSI_DATA04_ECSPI1_SCLK, 0, 0X10B1}, \
.miso_gpio = {IOMUXC_CSI_DATA07_ECSPI1_MISO, 0, 0X10B1}, \
.mosi_gpio = {IOMUXC_CSI_DATA06_ECSPI1_MOSI, 0, 0X10B1}, \
}
#endif /* BSP_USING_SPI1 */
#ifdef BSP_USING_SPI2
#define SPI2_BUS_CONFIG \
{ \
.ECSPI = ECSPI2, \
.name = "spi2", \
.clk_ip_name = kCLOCK_Ecspi2, \
.clk_gpio = {IOMUXC_UART4_TX_DATA_ECSPI2_SCLK, 0, 0X10B1}, \
.miso_gpio = {IOMUXC_UART5_RX_DATA_ECSPI2_MISO, 0, 0X10B1}, \
.mosi_gpio = {IOMUXC_UART5_TX_DATA_ECSPI2_MOSI, 0, 0X10B1}, \
}
#endif /* BSP_USING_SPI2 */
#ifdef BSP_USING_SPI3
#define SPI3_BUS_CONFIG \
{ \
.ECSPI = ECSPI3, \
.name = "spi3", \
.clk_ip_name = kCLOCK_Ecspi3, \
.clk_gpio = {IOMUXC_UART2_RX_DATA_ECSPI3_SCLK, 0, 0X10B1}, \
.miso_gpio = {IOMUXC_UART2_RTS_B_ECSPI3_MISO, 0, 0X10B1}, \
.mosi_gpio = {IOMUXC_UART2_CTS_B_ECSPI3_MOSI, 0, 0X10B1}, \
}
#endif /* BSP_USING_SPI3 */
#ifdef BSP_USING_SPI4
#define SPI4_BUS_CONFIG \
{ \
.ECSPI = ECSPI4, \
.name = "spi4", \
.clk_ip_name = kCLOCK_Ecspi4, \
.clk_gpio = {IOMUXC_ENET2_TX_DATA1_ECSPI4_SCLK, 0, 0X10B1}, \
.miso_gpio = {IOMUXC_ENET2_TX_CLK_ECSPI4_MISO, 0, 0X10B1}, \
.mosi_gpio = {IOMUXC_ENET2_TX_EN_ECSPI4_MOSI, 0, 0X10B1}, \
}
#endif /* BSP_USING_SPI4 */
rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin);
#endif

View File

@ -0,0 +1,172 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-22 Jesven first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <stdint.h>
#include <board.h>
#include "mmu.h"
#define TICK_PERIOD (g_sys_freq / RT_TICK_PER_SECOND)
static int g_sys_freq;
#define IRQ_SECURE_PHY_TIMER 29 /* Secure physical timer event */
#define IRQ_NOSECURE_PHY_TIMER 30 /* No-Secure physical timer event */
#define IRQ_SYS_TICK IRQ_SECURE_PHY_TIMER
/* System Counter */
struct sctr_regs {
rt_uint32_t cntcr;
rt_uint32_t cntsr;
rt_uint32_t cntcv1;
rt_uint32_t cntcv2;
rt_uint32_t resv1[4];
rt_uint32_t cntfid0;
rt_uint32_t cntfid1;
rt_uint32_t cntfid2;
rt_uint32_t resv2[1001];
rt_uint32_t counterid[1];
};
#define SC_CNTCR_ENABLE (1 << 0)
#define SC_CNTCR_HDBG (1 << 1)
#define SC_CNTCR_FREQ0 (1 << 8)
#define SC_CNTCR_FREQ1 (1 << 9)
#define isb() __asm__ __volatile__ ("" : : : "memory")
#define dsb() __asm__ __volatile__ ("" : : : "memory")
#define dmb() __asm__ __volatile__ ("" : : : "memory")
static inline void enable_cntp(void)
{
rt_uint32_t cntv_ctl;
cntv_ctl = 1;
asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r"(cntv_ctl)); // write CNTP_CTL
isb();
}
static inline void disable_cntp(void)
{
rt_uint32_t cntv_ctl;
cntv_ctl = 0;
asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r"(cntv_ctl)); // write CNTP_CTL
isb();
}
static inline rt_uint32_t read_cntfrq(void)
{
rt_uint32_t val;
asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r"(val));
return val;
}
static inline void write_cntp_tval(rt_uint32_t val)
{
asm volatile ("mcr p15, 0, %0, c14, c2, 0" :: "r"(val));
isb();
return;
}
static inline void write_cntp_cval(rt_uint64_t val)
{
asm volatile ("mcrr p15, 2, %Q0, %R0, c14" :: "r" (val));
isb();
return;
}
static inline rt_uint64_t read_cntp_cval(void)
{
rt_uint64_t val;
asm volatile ("mrrc p15, 2, %Q0, %R0, c14" : "=r" (val));
return (val);
}
volatile unsigned int *CCM_CLPCR;
static void imx6ull_enable_clk_in_waitmode(void)
{
CCM_CLPCR = rt_ioremap((void*)0x20C4054, 4);
*CCM_CLPCR &= ~((1 << 5) | 0x3);
}
static void system_counter_clk_source_init(void)
{
/* to do */
}
static void system_counter_init(void)
{
/* enable system_counter */
#define SCTR_BASE_ADDR 0x021DC000
#define CONFIG_SC_TIMER_CLK 8000000
/* imx6ull, enable system counter */
struct sctr_regs *sctr = (struct sctr_regs *)rt_ioremap((void*)SCTR_BASE_ADDR, sizeof(struct sctr_regs));
unsigned long val, freq;
freq = CONFIG_SC_TIMER_CLK;
asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
sctr->cntfid0 = freq;
/* Enable system counter */
val = sctr->cntcr;
val &= ~(SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1);
val |= SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG;
sctr->cntcr = val;
imx6ull_enable_clk_in_waitmode();
}
static void arch_timer_init(void)
{
g_sys_freq = read_cntfrq();
/* set timeout val */
disable_cntp();
write_cntp_tval(TICK_PERIOD);
/* start timer */
enable_cntp();
/* enable irq */
}
static void rt_hw_timer_isr(int vector, void *param)
{
rt_tick_increase();
/* setup for next irq */
/* clear interrupt */
disable_cntp();
write_cntp_cval(read_cntp_cval() + TICK_PERIOD);
enable_cntp();
}
int rt_hw_timer_init(void)
{
/* Setup Timer for generating irq */
/* enable timer */
system_counter_clk_source_init();
system_counter_init();
arch_timer_init();
/* insall irq, enable irq */
rt_hw_interrupt_install(IRQ_SYS_TICK, rt_hw_timer_isr, RT_NULL, "tick");
rt_hw_interrupt_umask(IRQ_SYS_TICK);
return 0;
}
INIT_BOARD_EXPORT(rt_hw_timer_init);

View File

@ -0,0 +1,17 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-22 Jesven first version
*/
#ifndef DRV_TIMER_H__
#define DRV_TIMER_H__
void timer_init(int timer, unsigned int preload);
void timer_clear_pending(int timer);
#endif

View File

@ -0,0 +1,502 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-13 RiceChen the first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>
#include <time.h>
#define DBG_TAG "gt911"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include "drv_touch.h"
#define GET_PIN(PORTx, PIN) (32 * (PORTx - 1) + (PIN & 31))
#define IRQ_PIN GET_PIN(1, 5)
#define RST_PIN GET_PIN(5, 2)
static struct rt_i2c_client gt911_client;
/* hardware section */
static rt_uint8_t GT911_CFG_TBL[] =
{
0x6b, 0x00, 0x04, 0x58, 0x02, 0x05, 0x0d, 0x00, 0x01, 0x0f,
0x28, 0x0f, 0x50, 0x32, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2a, 0x0c,
0x45, 0x47, 0x0c, 0x08, 0x00, 0x00, 0x00, 0x40, 0x03, 0x2c,
0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x64, 0x32, 0x00, 0x00,
0x00, 0x28, 0x64, 0x94, 0xd5, 0x02, 0x07, 0x00, 0x00, 0x04,
0x95, 0x2c, 0x00, 0x8b, 0x34, 0x00, 0x82, 0x3f, 0x00, 0x7d,
0x4c, 0x00, 0x7a, 0x5b, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0e, 0x0c, 0x0a,
0x08, 0x06, 0x04, 0x02, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x16, 0x18, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
0x22, 0x24, 0x13, 0x12, 0x10, 0x0f, 0x0a, 0x08, 0x06, 0x04,
0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x79, 0x01,
};
static rt_err_t gt911_write_reg(struct rt_i2c_client *dev, rt_uint8_t *data, rt_uint8_t len)
{
struct rt_i2c_msg msgs;
msgs.addr = dev->client_addr;
msgs.flags = RT_I2C_WR;
msgs.buf = data;
msgs.len = len;
if (rt_i2c_transfer(dev->bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static rt_err_t gt911_read_regs(struct rt_i2c_client *dev, rt_uint8_t *reg, rt_uint8_t *data, rt_uint8_t len)
{
struct rt_i2c_msg msgs[2];
msgs[0].addr = dev->client_addr;
msgs[0].flags = RT_I2C_WR;
msgs[0].buf = reg;
msgs[0].len = GT911_REGITER_LEN;
msgs[1].addr = dev->client_addr;
msgs[1].flags = RT_I2C_RD;
msgs[1].buf = data;
msgs[1].len = len;
if (rt_i2c_transfer(dev->bus, msgs, 2) == 2)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static rt_err_t gt911_get_product_id(struct rt_i2c_client *dev, rt_uint8_t *data, rt_uint8_t len)
{
rt_uint8_t reg[2];
reg[0] = (rt_uint8_t)(GT911_PRODUCT_ID >> 8);
reg[1] = (rt_uint8_t)(GT911_PRODUCT_ID & 0xff);
if (gt911_read_regs(dev, reg, data, len) != RT_EOK)
{
LOG_E("read id failed");
return -RT_ERROR;
}
return RT_EOK;
}
static rt_err_t gt911_get_info(struct rt_i2c_client *dev, struct rt_touch_info *info)
{
rt_uint8_t reg[2];
rt_uint8_t out_info[7];
rt_uint8_t out_len = 7;
reg[0] = (rt_uint8_t)(GT911_CONFIG_REG >> 8);
reg[1] = (rt_uint8_t)(GT911_CONFIG_REG & 0xFF);
if(gt911_read_regs(dev, reg, out_info, out_len) != RT_EOK)
{
LOG_E("read info failed");
return -RT_ERROR;
}
info->range_x = (out_info[2] << 8) | out_info[1];
info->range_y = (out_info[4] << 8) | out_info[3];
info->point_num = out_info[5] & 0x0f;
return RT_EOK;
}
static rt_err_t gt911_soft_reset(struct rt_i2c_client *dev)
{
rt_uint8_t buf[3];
buf[0] = (rt_uint8_t)(GT911_COMMAND_REG >> 8);
buf[1] = (rt_uint8_t)(GT911_COMMAND_REG & 0xFF);
buf[2] = 0x02;
if(gt911_write_reg(dev, buf, 3) != RT_EOK)
{
LOG_E("soft reset failed");
return -RT_ERROR;
}
return RT_EOK;
}
static int16_t pre_x[GT911_MAX_TOUCH] = {-1, -1, -1, -1, -1};
static int16_t pre_y[GT911_MAX_TOUCH] = {-1, -1, -1, -1, -1};
static int16_t pre_w[GT911_MAX_TOUCH] = {-1, -1, -1, -1, -1};
static rt_uint8_t s_tp_dowm[GT911_MAX_TOUCH];
static struct rt_touch_data *read_data;
static void gt911_touch_up(void *buf, int8_t id)
{
read_data = (struct rt_touch_data *)buf;
if(s_tp_dowm[id] == 1)
{
s_tp_dowm[id] = 0;
read_data[id].event = RT_TOUCH_EVENT_UP;
}
else
{
read_data[id].event = RT_TOUCH_EVENT_NONE;
}
read_data[id].timestamp = rt_touch_get_ts();
read_data[id].width = pre_w[id];
read_data[id].x_coordinate = pre_x[id];
read_data[id].y_coordinate = pre_y[id];
read_data[id].track_id = id;
pre_x[id] = -1; /* last point is none */
pre_y[id] = -1;
pre_w[id] = -1;
}
static void gt911_touch_down(void *buf, int8_t id, int16_t x, int16_t y, int16_t w)
{
read_data = (struct rt_touch_data *)buf;
if (s_tp_dowm[id] == 1)
{
read_data[id].event = RT_TOUCH_EVENT_MOVE;
}
else
{
read_data[id].event = RT_TOUCH_EVENT_DOWN;
s_tp_dowm[id] = 1;
}
read_data[id].timestamp = rt_touch_get_ts();
read_data[id].width = w;
read_data[id].x_coordinate = x;
read_data[id].y_coordinate = y;
read_data[id].track_id = id;
pre_x[id] = x; /* save last point */
pre_y[id] = y;
pre_w[id] = w;
}
static rt_size_t gt911_read_point(struct rt_touch_device *touch, void *buf, rt_size_t read_num)
{
rt_uint8_t point_status = 0;
rt_uint8_t touch_num = 0;
rt_uint8_t write_buf[3];
rt_uint8_t cmd[2];
rt_uint8_t read_buf[8 * GT911_MAX_TOUCH] = {0};
rt_uint8_t read_index;
int8_t read_id = 0;
int16_t input_x = 0;
int16_t input_y = 0;
int16_t input_w = 0;
static rt_uint8_t pre_touch = 0;
static int8_t pre_id[GT911_MAX_TOUCH] = {0};
/* point status register */
cmd[0] = (rt_uint8_t)((GT911_READ_STATUS >> 8) & 0xFF);
cmd[1] = (rt_uint8_t)(GT911_READ_STATUS & 0xFF);
if (gt911_read_regs(&gt911_client, cmd, &point_status, 1) != RT_EOK)
{
LOG_D("read point failed\n");
read_num = 0;
goto exit_;
}
if (point_status == 0) /* no data */
{
read_num = 0;
goto exit_;
}
if ((point_status & 0x80) == 0) /* data is not ready */
{
read_num = 0;
goto exit_;
}
touch_num = point_status & 0x0f; /* get point num */
if (touch_num > GT911_MAX_TOUCH) /* point num is not correct */
{
read_num = 0;
goto exit_;
}
cmd[0] = (rt_uint8_t)((GT911_POINT1_REG >> 8) & 0xFF);
cmd[1] = (rt_uint8_t)(GT911_POINT1_REG & 0xFF);
/* read point num is touch_num */
if(gt911_read_regs(&gt911_client, cmd, read_buf, read_num * GT911_POINT_INFO_NUM) !=RT_EOK)
{
LOG_D("read point failed\n");
read_num = 0;
goto exit_;
}
if(pre_touch > touch_num) /* point up */
{
for (read_index = 0; read_index < pre_touch; read_index++)
{
rt_uint8_t j;
for (j = 0; j < touch_num; j++) /* this time touch num */
{
read_id = read_buf[j * 8] & 0x0F;
if (pre_id[read_index] == read_id) /* this id is not free */
{
break;
}
if (j >= touch_num - 1)
{
rt_uint8_t up_id;
up_id = pre_id[read_index];
gt911_touch_up(buf, up_id);
}
}
}
}
if(touch_num) /* point down */
{
rt_uint8_t off_set;
for(read_index = 0; read_index < touch_num; read_index++)
{
off_set = read_index * 8;
read_id = read_buf[off_set] & 0x0f;
pre_id[read_index] = read_id;
input_x = read_buf[off_set + 1] | (read_buf[off_set + 2] << 8); /* x */
input_y = read_buf[off_set + 3] | (read_buf[off_set + 4] << 8); /* y */
input_w = read_buf[off_set + 5] | (read_buf[off_set + 6] << 8); /* size */
gt911_touch_down(buf, read_id, input_x, input_y, input_w);
}
}
else if (pre_touch)
{
for(read_index = 0; read_index < pre_touch; read_index++)
{
gt911_touch_up(buf, pre_id[read_index]);
}
}
pre_touch = touch_num;
exit_:
write_buf[0] = (rt_uint8_t)((GT911_READ_STATUS >> 8) & 0xFF);
write_buf[1] = (rt_uint8_t)(GT911_READ_STATUS & 0xFF);
write_buf[2] = 0x00;
gt911_write_reg(&gt911_client, write_buf, 3);
return read_num;
}
static rt_err_t gt911_control(struct rt_touch_device *touch, int cmd, void *arg)
{
if (cmd == RT_TOUCH_CTRL_GET_ID)
{
return gt911_get_product_id(&gt911_client, arg, 6);
}
if (cmd == RT_TOUCH_CTRL_GET_INFO)
{
return gt911_get_info(&gt911_client, arg);
}
rt_uint8_t buf[4];
rt_uint8_t i = 0;
rt_uint8_t *config = RT_NULL;
config = (rt_uint8_t *)rt_calloc(1, sizeof(GT911_CFG_TBL) + GT911_REGITER_LEN);
if(config == RT_NULL)
{
LOG_D("malloc config memory failed\n");
return -RT_ERROR;
}
config[0] = (rt_uint8_t)((GT911_CONFIG_REG >> 8) & 0xFF);
config[1] = (rt_uint8_t)(GT911_CONFIG_REG & 0xFF);
memcpy(&config[2], GT911_CFG_TBL, sizeof(GT911_CFG_TBL));
switch(cmd)
{
case RT_TOUCH_CTRL_SET_X_RANGE:
{
rt_uint16_t x_range;
x_range = *(rt_uint16_t *)arg;
config[4] = (rt_uint8_t)(x_range >> 8);
config[3] = (rt_uint8_t)(x_range & 0xff);
GT911_CFG_TBL[2] = config[4];
GT911_CFG_TBL[1] = config[3];
break;
}
case RT_TOUCH_CTRL_SET_Y_RANGE:
{
rt_uint16_t y_range;
y_range = *(rt_uint16_t *)arg;
config[6] = (rt_uint8_t)(y_range >> 8);
config[5] = (rt_uint8_t)(y_range & 0xff);
GT911_CFG_TBL[4] = config[6];
GT911_CFG_TBL[3] = config[5];
break;
}
case RT_TOUCH_CTRL_SET_X_TO_Y:
{
config[8] ^= (1 << 3);
break;
}
case RT_TOUCH_CTRL_SET_MODE:
{
rt_uint16_t trig_type;
trig_type = *(rt_uint16_t *)arg;
switch (trig_type)
{
case RT_DEVICE_FLAG_INT_RX:
config[8] &= 0xFC;
break;
case RT_DEVICE_FLAG_RDONLY:
config[8] &= 0xFC;
config[8] |= 0x02;
break;
default:
break;
}
break;
}
default:
{
break;
}
}
if(gt911_write_reg(&gt911_client, config, sizeof(GT911_CFG_TBL) + GT911_ADDR_LEN) != RT_EOK)
{
LOG_D("send config failed");
return -1;
}
buf[0] = (rt_uint8_t)((GT911_CHECK_SUM >> 8) & 0xFF);
buf[1] = (rt_uint8_t)(GT911_CHECK_SUM & 0xFF);
buf[2] = 0;
for(i = GT911_ADDR_LEN; i < sizeof(GT911_CFG_TBL) + GT911_ADDR_LEN; i++)
{
buf[GT911_ADDR_LEN] += config[i];
}
buf[2] = (~buf[2]) + 1;
buf[3] = 1;
gt911_write_reg(&gt911_client, buf, 4);
rt_free(config);
return RT_EOK;
}
static struct rt_touch_ops gt911_touch_ops =
{
.touch_readpoint = gt911_read_point,
.touch_control = gt911_control,
};
int rt_hw_gt911_init(const char *name, struct rt_touch_config *cfg)
{
struct rt_touch_device *touch_device = RT_NULL;
touch_device = (struct rt_touch_device *)rt_malloc(sizeof(struct rt_touch_device));
if(touch_device == RT_NULL)
{
LOG_E("touch device malloc fail");
return -RT_ERROR;
}
rt_memset((void *)touch_device, 0, sizeof(struct rt_touch_device));
/* hw init*/
rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_OUTPUT);
rt_pin_mode(cfg->irq_pin.pin, PIN_MODE_OUTPUT);
rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_LOW);
rt_thread_delay(10);
rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_HIGH);
rt_thread_delay(10);
rt_pin_write(cfg->irq_pin.pin, PIN_MODE_INPUT);
rt_thread_delay(100);
gt911_client.bus = (struct rt_i2c_bus_device *)rt_device_find(cfg->dev_name);
if(gt911_client.bus == RT_NULL)
{
LOG_E("Can't find %s device", cfg->dev_name);
return -RT_ERROR;
}
if(rt_device_open((rt_device_t)gt911_client.bus, RT_DEVICE_FLAG_RDWR) != RT_EOK)
{
LOG_E("open %s device failed", cfg->dev_name);
return -RT_ERROR;
}
gt911_client.client_addr = GT911_ADDRESS_HIGH;
gt911_soft_reset(&gt911_client);
/* register touch device */
touch_device->info.type = RT_TOUCH_TYPE_CAPACITANCE;
touch_device->info.vendor = RT_TOUCH_VENDOR_GT;
rt_memcpy(&touch_device->config, cfg, sizeof(struct rt_touch_config));
touch_device->ops = &gt911_touch_ops;
rt_hw_touch_register(touch_device, name, RT_DEVICE_FLAG_INT_RX, RT_NULL);
LOG_I("touch device gt911 init success");
return RT_EOK;
}
int gt911_init(void)
{
struct rt_touch_config cfg;
rt_uint8_t rst_pin;
rst_pin = RST_PIN;
cfg.dev_name = "i2c3";
cfg.irq_pin.pin = IRQ_PIN;
cfg.irq_pin.mode = PIN_MODE_INPUT_PULLDOWN;
cfg.user_data = &rst_pin;
rt_hw_gt911_init("gt911", &cfg);
return RT_EOK;
}
INIT_DEVICE_EXPORT(gt911_init);

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-13 RiceChen the first version
*/
#ifndef __GT911_H__
#define __GT911_H__
#define GT911_ADDR_LEN 2
#define GT911_REGITER_LEN 2
#define GT911_MAX_TOUCH 5
#define GT911_POINT_INFO_NUM 5
#define GT911_ADDRESS_HIGH 0x5D
#define GT911_ADDRESS_LOW 0x14
#define GT911_COMMAND_REG 0x8040
#define GT911_CONFIG_REG 0x8047
#define GT911_PRODUCT_ID 0x8140
#define GT911_VENDOR_ID 0x814A
#define GT911_READ_STATUS 0x814E
#define GT911_POINT1_REG 0x814F
#define GT911_POINT2_REG 0x8157
#define GT911_POINT3_REG 0x815F
#define GT911_POINT4_REG 0x8167
#define GT911_POINT5_REG 0x816F
#define GT911_CHECK_SUM 0x80FF
int rt_hw_gt911_init(const char *name, struct rt_touch_config *cfg);
#endif /* gt911.h */

View File

@ -0,0 +1,350 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-09 Lyons first version
*/
#include <rtconfig.h>
#ifdef RT_USING_SERIAL
#include "board.h"
#include "drv_uart.h"
#include "drv_common.h"
enum
{
#ifdef BSP_USING_UART1
eDevUart_UART1,
#endif
#ifdef BSP_USING_UART2
eDevUart_UART2,
#endif
#ifdef BSP_USING_UART3
eDevUart_UART3,
#endif
#ifdef BSP_USING_UART4
eDevUart_UART4,
#endif
#ifdef BSP_USING_UART5
eDevUart_UART5,
#endif
#ifdef BSP_USING_UART6
eDevUart_UART6,
#endif
#ifdef BSP_USING_UART7
eDevUart_UART7,
#endif
#ifdef BSP_USING_UART8
eDevUart_UART8,
#endif
eDevUart_Max,
};
_internal_rw struct imx_uart _s_uart[eDevUart_Max] = {
#ifdef BSP_USING_UART1
{
.name = "uart0",
.periph.paddr = IMX6ULL_UART1_BASE,
.irqno = UART1_IRQn,
.gpio = {
{IOMUXC_UART1_TX_DATA_UART1_TX, 0, 0x10B0},
{IOMUXC_UART1_RX_DATA_UART1_RX, 0, 0x10B0},
},
.flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
.param = RT_SERIAL_CONFIG_115200N81,
},
#endif
#ifdef BSP_USING_UART2
{
.name = "uart1",
.periph.paddr = IMX6ULL_UART2_BASE,
.irqno = UART2_IRQn,
.gpio = {
{IOMUXC_UART2_TX_DATA_UART2_TX, 0, 0x10B0},
{IOMUXC_UART2_RX_DATA_UART2_RX, 0, 0x10B0},
},
.flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
.param = RT_SERIAL_CONFIG_DEFAULT,
},
#endif
#ifdef BSP_USING_UART3
{
.name = "uart2",
.periph.paddr = IMX6ULL_UART3_BASE,
.irqno = UART3_IRQn,
.gpio = {
{IOMUXC_UART3_TX_DATA_UART3_TX, 0, 0x10B0},
{IOMUXC_UART3_RX_DATA_UART3_RX, 0, 0x10B0},
},
.flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
.param = RT_SERIAL_CONFIG_DEFAULT,
},
#endif
#ifdef BSP_USING_UART4
{
.name = "uart3",
.periph.paddr = IMX6ULL_UART4_BASE,
.irqno = UART4_IRQn,
.gpio = {
{IOMUXC_UART4_TX_DATA_UART4_TX, 0, 0x10B0},
{IOMUXC_UART4_RX_DATA_UART4_RX, 0, 0x10B0},
},
.flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
.param = RT_SERIAL_CONFIG_DEFAULT,
},
#endif
#ifdef BSP_USING_UART5
{
.name = "uart4",
.periph.paddr = IMX6ULL_UART5_BASE,
.irqno = UART5_IRQn,
.gpio = {
{IOMUXC_UART5_TX_DATA_UART5_TX, 0, 0x10B0},
{IOMUXC_UART5_RX_DATA_UART5_RX, 0, 0x10B0},
},
.flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
.param = RT_SERIAL_CONFIG_DEFAULT,
},
#endif
#ifdef BSP_USING_UART6
{
.name = "uart5",
.periph.paddr = IMX6ULL_UART6_BASE,
.irqno = UART6_IRQn,
.gpio = {
{IOMUXC_ENET2_RX_DATA1_UART6_TX, 0, 0x10B0},
{IOMUXC_ENET2_RX_DATA0_UART6_RX, 0, 0x10B0},
},
.flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
.param = RT_SERIAL_CONFIG_DEFAULT,
},
#endif
#ifdef BSP_USING_UART7
{
.name = "uart6",
.periph.paddr = IMX6ULL_UART7_BASE,
.irqno = UART7_IRQn,
.gpio = {
{IOMUXC_ENET2_TX_DATA0_UART7_TX, 0, 0x10B0},
{IOMUXC_ENET2_RX_EN_UART7_RX, 0, 0x10B0},
},
.flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
.param = RT_SERIAL_CONFIG_DEFAULT,
},
#endif
#ifdef BSP_USING_UART8
{
.name = "uart7",
.periph.paddr = IMX6ULL_UART8_BASE,
.irqno = UART8_IRQn,
.gpio = {
{IOMUXC_ENET2_TX_DATA1_UART8_TX, 0, 0x10B0},
{IOMUXC_ENET2_TX_EN_UART8_RX, 0, 0x10B0},
},
.flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
.param = RT_SERIAL_CONFIG_DEFAULT,
},
#endif
};
static void _uart_gpio_init( struct imx_uart *device )
{
for (int i=0; i<GET_ARRAY_NUM(device->gpio); i++)
{
imx6ull_gpio_init(&device->gpio[i]);
}
}
static rt_err_t _uart_ops_configure( struct rt_serial_device *dev,
struct serial_configure *cfg )
{
struct imx_uart *uart = RT_NULL;
UART_Type *periph = RT_NULL;
rt_uint32_t reg_value;
RT_ASSERT(RT_NULL != dev);
RT_ASSERT(RT_NULL != cfg);
uart = (struct imx_uart*)dev;
periph = (UART_Type*)uart->periph.vaddr;
_uart_gpio_init(uart);
periph->UCR1 &= ~UART_UCR1_UARTEN_MASK;
periph->UFCR &= ~UART_UFCR_RFDIV_MASK;
periph->UFCR |= UART_UFCR_RFDIV(5);
RT_ASSERT(cfg->baud_rate <= BAUD_RATE_921600);
periph->UBIR = UART_UBIR_INC(15);
periph->UBMR = UART_UBMR_MOD(HW_UART_BUS_CLOCK / cfg->baud_rate - 1);
reg_value = 0;
switch (cfg->data_bits)
{
case DATA_BITS_7:
reg_value |= UART_UCR2_WS(0);
break;
default:
reg_value |= UART_UCR2_WS(1);
break;
}
switch (cfg->stop_bits)
{
case STOP_BITS_2:
reg_value |= UART_UCR2_STPB(1);
break;
default:
reg_value |= UART_UCR2_STPB(0);
break;
}
switch (cfg->parity)
{
case PARITY_ODD:
reg_value |= UART_UCR2_PREN(1);
reg_value |= UART_UCR2_PROE(1);
break;
case PARITY_EVEN:
reg_value |= UART_UCR2_PREN(1);
reg_value |= UART_UCR2_PROE(0);
break;
default:
reg_value |= UART_UCR2_PREN(0);
reg_value |= UART_UCR2_PROE(0);
break;
}
periph->UCR3 |= UART_UCR3_RXDMUXSEL(1); //this bit should always be set!
periph->UCR2 |= reg_value | UART_UCR2_IRTS(1) | UART_UCR2_TXEN(1) | UART_UCR2_RXEN(1);
periph->UCR1 |= UART_UCR1_UARTEN(1);
return RT_EOK;
}
static rt_err_t _uart_ops_control( struct rt_serial_device *dev,
int cmd,
void *arg )
{
struct imx_uart *uart = RT_NULL;
UART_Type *periph = RT_NULL;
rt_err_t result;
RT_ASSERT(RT_NULL != dev);
uart = (struct imx_uart*)dev;
periph = (UART_Type*)uart->periph.vaddr;
result = RT_EOK;
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
periph->UCR4 &= ~UART_UCR4_DREN_MASK;
periph->UCR4 |= UART_UCR4_DREN(0);
break;
case RT_DEVICE_CTRL_SET_INT:
periph->UCR4 |= UART_UCR4_DREN(1);
rt_hw_interrupt_umask(uart->irqno);
break;
default:
result = -RT_EINVAL;
break;
}
return result;
}
static int _uart_ops_putc( struct rt_serial_device *dev,
char ch )
{
struct imx_uart *uart = RT_NULL;
UART_Type *periph = RT_NULL;
RT_ASSERT(RT_NULL != dev);
uart = (struct imx_uart*)dev;
periph = (UART_Type*)uart->periph.vaddr;
while (0 == (periph->USR2 & UART_USR2_TXDC_MASK));
periph->UTXD = ch;
return 1;
}
static int _uart_ops_getc( struct rt_serial_device *dev )
{
struct imx_uart *uart = RT_NULL;
UART_Type *periph = RT_NULL;
int ch;
RT_ASSERT(RT_NULL != dev);
uart = (struct imx_uart*)dev;
periph = (UART_Type*)uart->periph.vaddr;
ch = (0 == (periph->USR2 & UART_USR2_RDR_MASK)) ? -1 : periph->URXD;
return ch;
}
_internal_ro struct rt_uart_ops _k_uart_ops =
{
_uart_ops_configure, /* configure */
_uart_ops_control, /* control */
_uart_ops_putc, /* putc */
_uart_ops_getc, /* getc */
RT_NULL, /* dma_transmit */
};
static void _uart_isr( int irqno, void* parameter )
{
struct rt_serial_device *serial;
rt_interrupt_enter();
serial = (struct rt_serial_device *)parameter;
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
rt_interrupt_leave();
}
int rt_hw_uart_init(void)
{
for (int idx=0; idx<GET_ARRAY_NUM(_s_uart); idx++)
{
_s_uart[idx].periph.vaddr = platform_get_periph_vaddr(_s_uart[idx].periph.paddr);
_s_uart[idx].parent.ops = &_k_uart_ops;
rt_memcpy(&_s_uart[idx].parent.config, &_s_uart[idx].param, sizeof(struct serial_configure));
rt_hw_serial_register( &_s_uart[idx].parent,
_s_uart[idx].name,
_s_uart[idx].flag,
RT_NULL );
rt_hw_interrupt_install(_s_uart[idx].irqno, _uart_isr, &_s_uart[idx].parent, _s_uart[idx].name);
}
return RT_EOK;
}
INIT_BOARD_EXPORT(rt_hw_uart_init);
#endif //#ifdef RT_USING_SERIAL

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-09 Lyons first version
*/
#ifndef __DRV_UART_H__
#define __DRV_UART_H__
#include "board.h"
#include "drv_common.h"
#ifdef RT_USING_SERIAL
#ifndef HW_UART_BUS_CLOCK
#define HW_UART_BUS_CLOCK 80000000
#endif
#define RT_SERIAL_CONFIG_115200N81 \
{ \
BAUD_RATE_115200, \
DATA_BITS_8, \
STOP_BITS_1, \
PARITY_NONE, \
BIT_ORDER_LSB, \
NRZ_NORMAL, \
RT_SERIAL_RB_BUFSZ, \
0 \
}
struct imx_periph
{
rt_uint32_t paddr;
rt_uint32_t vaddr;
};
struct imx_uart
{
struct rt_serial_device parent;
const char *name;
struct imx_periph periph;
rt_uint32_t irqno;
//[0]-tx [1]-rx
struct imx6ull_iomuxc gpio[2];
rt_uint32_t flag;
struct serial_configure param;
};
#endif //#ifdef RT_USING_SERIAL
#endif //#ifndef __DRV_UART_H__

View File

@ -0,0 +1,366 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-12-04 ZYH first implementation
*/
#include <usb/include/usb_device_config.h>
#include <usb/include/usb.h>
#include <rtthread.h>
#include <usb/phy/usb_phy.h>
#include <usb/device/usb_device.h>
#include <usb/device/usb_device_dci.h>
#include <rtdevice.h>
#include <imx6ull.h>
#define USB0_IRQNUM 75
/* USB PHY condfiguration */
#define BOARD_USB_PHY_D_CAL (0x0CU)
#define BOARD_USB_PHY_TXCAL45DP (0x06U)
#define BOARD_USB_PHY_TXCAL45DM (0x06U)
#ifdef BSP_USING_USB_DEVICE
static usb_device_handle ehci0_handle;
static struct udcd _fsl_udc_0;
static usb_status_t usb_device_callback(usb_device_handle handle, uint32_t callbackEvent, void *eventParam);
static usb_status_t usb_device_endpoint_callback(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam);
static void USB_DeviceIsrEnable(uint8_t controllerId)
{
uint8_t irqNumber;
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
uint8_t usbDeviceEhciIrq[] = USBHS_IRQS;
irqNumber = usbDeviceEhciIrq[controllerId - kUSB_ControllerEhci0];
#endif
/* Install isr, set priority, and enable IRQ. */
#if defined(__GIC_PRIO_BITS)
GIC_SetPriority((IRQn_Type)irqNumber, 3);
#else
NVIC_SetPriority((IRQn_Type)irqNumber, 3);
#endif
EnableIRQ((IRQn_Type)irqNumber);
}
/*!
* @brief Initializes USB specific setting that was not set by the Clocks tool.
*/
static void USB_DeviceClockInit(uint8_t controllerId)
{
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
usb_phy_config_struct_t phyConfig = {
BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
};
#endif
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
if (controllerId == kUSB_ControllerEhci0)
{
CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
}
else
{
CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
}
USB_EhciPhyInit(controllerId, 0, &phyConfig);
#endif
}
static struct ep_id _ehci0_ep_pool[] =
{
{0x0, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED },
{0x1, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED},
{0x1, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED},
{0x2, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED},
{0x2, USB_EP_ATTR_INT, USB_DIR_OUT, 64, ID_UNASSIGNED},
{0x3, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED},
{0x3, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED},
{0x4, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED},
{0x4, USB_EP_ATTR_INT, USB_DIR_OUT, 64, ID_UNASSIGNED},
{0x5, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED},
{0x5, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED},
{0x6, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED},
{0x6, USB_EP_ATTR_INT, USB_DIR_OUT, 64, ID_UNASSIGNED},
{0x7, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED},
{0x7, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED},
{0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED },
};
/*!
* @brief USB Interrupt service routine.
*
* This function serves as the USB interrupt service routine.
*
* @return None.
*/
static struct rt_workqueue *usb0_wq = NULL;
static struct rt_work usb0_work;
void ehci0_work(struct rt_work *work, void *work_data)
{
USB_DeviceEhciIsrFunction(ehci0_handle);
rt_hw_interrupt_umask(USB0_IRQNUM);
}
void USB_OTG1_IRQHandler(int irq, void *base)
{
// USB_DeviceEhciIsrFunction(ehci0_handle);
rt_hw_interrupt_mask(USB0_IRQNUM);
rt_workqueue_dowork(usb0_wq, &usb0_work);
}
static rt_err_t _ehci0_ep_set_stall(rt_uint8_t address)
{
USB_DeviceStallEndpoint(ehci0_handle, address);
return RT_EOK;
}
static rt_err_t _ehci0_ep_clear_stall(rt_uint8_t address)
{
USB_DeviceUnstallEndpoint(ehci0_handle, address);
return RT_EOK;
}
static rt_err_t _ehci0_set_address(rt_uint8_t address)
{
USB_DeviceSetStatus(ehci0_handle, kUSB_DeviceStatusAddress, &address);
return RT_EOK;
}
static rt_err_t _ehci0_set_config(rt_uint8_t address)
{
return RT_EOK;
}
static rt_err_t _ehci0_ep_enable(uep_t ep)
{
usb_device_endpoint_init_struct_t ep_init;
usb_device_endpoint_callback_struct_t ep_callback;
rt_uint32_t param = ep->ep_desc->bEndpointAddress;
RT_ASSERT(ep != RT_NULL);
RT_ASSERT(ep->ep_desc != RT_NULL);
ep_init.maxPacketSize = ep->ep_desc->wMaxPacketSize;
ep_init.endpointAddress = ep->ep_desc->bEndpointAddress;
ep_init.transferType = ep->ep_desc->bmAttributes;
ep_init.zlt = 0;
ep_callback.callbackFn = usb_device_endpoint_callback;
ep_callback.callbackParam = (void *)param;
ep_callback.isBusy = 0;
USB_DeviceInitEndpoint(ehci0_handle, &ep_init, &ep_callback);
return RT_EOK;
}
static rt_err_t _ehci0_ep_disable(uep_t ep)
{
RT_ASSERT(ep != RT_NULL);
RT_ASSERT(ep->ep_desc != RT_NULL);
USB_DeviceDeinitEndpoint(ehci0_handle, ep->ep_desc->bEndpointAddress);
return RT_EOK;
}
static rt_size_t _ehci0_ep_read(rt_uint8_t address, void *buffer)
{
rt_size_t size = 0;
RT_ASSERT(buffer != RT_NULL);
return size;
}
static rt_size_t _ehci0_ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
{
USB_DeviceRecvRequest(ehci0_handle, address, buffer, size);
return size;
}
static rt_size_t _ehci0_ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
{
USB_DeviceSendRequest(ehci0_handle, address, buffer, size);
return size;
}
static rt_err_t _ehci0_ep0_send_status(void)
{
_ehci0_ep_write(0x00, NULL, 0);
return RT_EOK;
}
static rt_err_t _ehci0_suspend(void)
{
return RT_EOK;
}
static rt_err_t _ehci0_wakeup(void)
{
return RT_EOK;
}
const static struct udcd_ops _ehci0_udc_ops =
{
_ehci0_set_address,
_ehci0_set_config,
_ehci0_ep_set_stall,
_ehci0_ep_clear_stall,
_ehci0_ep_enable,
_ehci0_ep_disable,
_ehci0_ep_read_prepare,
_ehci0_ep_read,
_ehci0_ep_write,
_ehci0_ep0_send_status,
_ehci0_suspend,
_ehci0_wakeup,
};
extern void rt_hw_interrupt_umask(int vector);
static rt_err_t drv_ehci0_usbd_init(rt_device_t device)
{
usb_status_t result;
USB_DeviceClockInit(kUSB_ControllerEhci0);
result = USB_DeviceInit(kUSB_ControllerEhci0, usb_device_callback, &ehci0_handle);
RT_ASSERT(ehci0_handle);
if(result == kStatus_USB_Success)
{
usb0_wq = rt_workqueue_create("u0wq", 4096, 3);
rt_work_init(&usb0_work, ehci0_work, NULL);
rt_hw_interrupt_install(USB0_IRQNUM, USB_OTG1_IRQHandler, (void *)ehci0_handle, "usb1_intr");
rt_hw_interrupt_umask(USB0_IRQNUM);
USB_DeviceRun(ehci0_handle);
}
else
{
rt_kprintf("USB_DeviceInit ehci0 error\r\n");
return RT_ERROR;
}
return RT_EOK;
}
struct rt_device_ops imx6ull_usb_ops =
{
drv_ehci0_usbd_init,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
};
static int rt_usbd_init(void)
{
rt_memset((void *)&_fsl_udc_0, 0, sizeof(struct udcd));
_fsl_udc_0.parent.type = RT_Device_Class_USBDevice;
_fsl_udc_0.parent.ops = &imx6ull_usb_ops;
_fsl_udc_0.ops = &_ehci0_udc_ops;
/* Register endpoint infomation */
_fsl_udc_0.ep_pool = _ehci0_ep_pool;
_fsl_udc_0.ep0.id = &_ehci0_ep_pool[0];
_fsl_udc_0.device_is_hs = RT_FALSE;
rt_device_register((rt_device_t)&_fsl_udc_0, "usbd", 0);
rt_usb_device_init();
return 0;
}
// INIT_DEVICE_EXPORT(rt_usbd_init);
static usb_status_t usb_device_endpoint_callback(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam)
{
rt_uint32_t ep_addr = (rt_uint32_t)callbackParam;
usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
udcd_t udcd = RT_NULL;
uint8_t state;
if(deviceHandle->controllerId == kUSB_ControllerEhci0)
udcd = &_fsl_udc_0;
if(message->isSetup)
{
rt_usbd_ep0_setup_handler(udcd, (struct urequest*)message->buffer);
}
else if(ep_addr == 0x00)
{
USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
if(state == kUSB_DeviceStateAddressing)
{
if (kStatus_USB_Success == USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, NULL))
{
state = kUSB_DeviceStateAddress;
USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
}
}
rt_usbd_ep0_out_handler(udcd, message->length);
}
else if(ep_addr == 0x80)
{
USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
if(state == kUSB_DeviceStateAddressing)
{
if (kStatus_USB_Success == USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, NULL))
{
state = kUSB_DeviceStateAddress;
USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
}
}
rt_usbd_ep0_in_handler(udcd);
}
else if(ep_addr & 0x80)
{
rt_usbd_ep_in_handler(udcd, ep_addr, message->length);
}
else
{
rt_usbd_ep_out_handler(udcd, ep_addr, message->length);
}
return kStatus_USB_Success;
}
static usb_status_t usb_device_callback(usb_device_handle handle, uint32_t callbackEvent, void *eventParam)
{
usb_status_t error = kStatus_USB_Error;
usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
usb_device_endpoint_init_struct_t ep0_init =
{
0x40,
0x00,
USB_EP_ATTR_CONTROL,
0
};
usb_device_endpoint_callback_struct_t ep0_callback =
{
usb_device_endpoint_callback,
0,
0
};
udcd_t udcd = RT_NULL;
if(deviceHandle->controllerId == kUSB_ControllerEhci0)
udcd = &_fsl_udc_0;
switch (callbackEvent)
{
case kUSB_DeviceEventBusReset:
ep0_init.endpointAddress = 0x00;
ep0_callback.callbackParam = (void *)0x00;
USB_DeviceInitEndpoint(deviceHandle, &ep0_init, &ep0_callback);
ep0_init.endpointAddress = 0x80;
ep0_callback.callbackParam = (void *)0x80;
USB_DeviceInitEndpoint(deviceHandle, &ep0_init, &ep0_callback);
rt_usbd_reset_handler(udcd);
break;
case kUSB_DeviceEventAttach:
rt_usbd_connect_handler(udcd);
break;
case kUSB_DeviceEventDetach:
rt_usbd_disconnect_handler(udcd);
break;
}
return error;
}
#endif
/********************* end of file ************************/

View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-07-28 songchao first version
*/
#include <rtconfig.h>
#ifdef RT_USING_WDT
#include <rtthread.h>
#include <rtdbg.h>
#include "drv_wdt.h"
#include "fsl_wdog.h"
#include "imx6ull.h"
enum
{
#ifdef RT_USING_WDT1
DEV_WDT1,
#endif
#ifdef RT_USING_WDT2
DEV_WDT2,
#endif
#ifdef RT_USING_WDT3
DEV_WDT3,
#endif
DEV_MAX,
};
#ifdef RT_USING_WDT1
static wdog_config_t WDOG_1_config =
{
.timeoutValue = 0xffu,
.enablePowerDown = false,
.softwareResetExtension = false,
.softwareAssertion = true,
.softwareResetSignal = true,
.enableWdog = true,
.workMode =
{
.enableWait = false,
.enableStop = false,
.enableDebug = false,
},
.enableInterrupt = false,
.interruptTimeValue = 0x04u,
};
#endif
#ifdef RT_USING_WDT2
static wdog_config_t WDOG_2_config =
{
.timeoutValue = 0xffu,
.enablePowerDown = false,
.softwareResetExtension = false,
.softwareAssertion = true,
.softwareResetSignal = true,
.enableWdog = true,
.workMode =
{
.enableWait = false,
.enableStop = false,
.enableDebug = false,
},
.enableInterrupt = false,
.interruptTimeValue = 0x04u,
};
#endif
#ifdef RT_USING_WDT3
static wdog_config_t WDOG_3_config =
{
.timeoutValue = 0xffu,
.enablePowerDown = false,
.softwareResetExtension = false,
.softwareAssertion = true,
.softwareResetSignal = true,
.enableWdog = true,
.workMode =
{
.enableWait = false,
.enableStop = false,
.enableDebug = false,
},
.enableInterrupt = false,
.interruptTimeValue = 0x04u,
};
#endif
static rt_watchdog_t imx6ull_watchdog[DEV_MAX] =
{
#ifdef RT_USING_WDT1
{
.name = "wdt1",
.paddr = IMX6ULL_WATCHDOG1_BASE,
.config = &WDOG_1_config,
},
#endif
#ifdef RT_USING_WDT2
{
.name = "wdt2",
.paddr = IMX6ULL_WATCHDOG2_BASE,
.config = &WDOG_2_config,
},
#endif
#ifdef RT_USING_WDT3
{
.name = "wdt3",
.paddr = IMX6ULL_WATCHDOG3_BASE,
.config = &WDOG_3_config,
},
#endif
};
static rt_err_t imx6ull_wdog_init(rt_watchdog_t *wdt)
{
WDOG_Type *base = RT_NULL;
base = (WDOG_Type *)wdt->vaddr;
WDOG_Init(base, wdt->config);
WDOG_Disable(base);
return RT_EOK;
}
static rt_err_t imx6ull_wdog_control(rt_watchdog_t *wdt, int cmd, void *args)
{
RT_ASSERT(wdt != NULL);
WDOG_Type *base = RT_NULL;
base = (WDOG_Type *)wdt->vaddr;
switch(cmd)
{
case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
{
*(uint16_t *)args = (base->WCR >> 8) / 2;
}
break;
case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
{
RT_ASSERT(*(uint16_t *)args != 0);
WDOG_SetTimeoutValue(base, (*(uint16_t *)args) * 2);
WDOG_Disable(base);
}
break;
case RT_DEVICE_CTRL_WDT_KEEPALIVE:
{
WDOG_Refresh(base);
}
break;
case RT_DEVICE_CTRL_WDT_START:
{
WDOG_Enable(base);
}
break;
case RT_DEVICE_CTRL_WDT_STOP:
{
WDOG_Disable(base);
}
break;
default:
return RT_EINVAL;
}
return RT_EOK;
}
static struct rt_watchdog_ops imx6ull_wdog_ops =
{
.init = imx6ull_wdog_init,
.control = imx6ull_wdog_control,
};
int rt_hw_wdt_init(void)
{
rt_err_t ret = RT_EOK;
for(int idx = 0; idx < GET_ARRAY_NUM(imx6ull_watchdog); idx++)
{
imx6ull_watchdog[idx].ops = &imx6ull_wdog_ops;
imx6ull_watchdog[idx].vaddr = platform_get_periph_vaddr(imx6ull_watchdog[idx].paddr);
ret = rt_hw_watchdog_register(&imx6ull_watchdog[idx], imx6ull_watchdog[idx].name,
RT_DEVICE_FLAG_DEACTIVATE, RT_NULL);
if (ret != RT_EOK)
{
LOG_E("rt device register failed %d\n", ret);
}
}
return ret;
}
INIT_DEVICE_EXPORT(rt_hw_wdt_init);
#endif

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-07-28 songchao first version
*/
#ifndef __WATCHDOG_H__
#define __WATCHDOG_H__
#include <rtthread.h>
#include "fsl_wdog.h"
#define RT_DEVICE_CTRL_WDT_GET_TIMEOUT (1) /* get timeout(in seconds) */
#define RT_DEVICE_CTRL_WDT_SET_TIMEOUT (2) /* set timeout(in seconds) */
#define RT_DEVICE_CTRL_WDT_GET_TIMELEFT (3) /* get the left time before reboot(in seconds) */
#define RT_DEVICE_CTRL_WDT_KEEPALIVE (4) /* refresh watchdog */
#define RT_DEVICE_CTRL_WDT_START (5) /* start watchdog */
#define RT_DEVICE_CTRL_WDT_STOP (6) /* stop watchdog */
struct rt_watchdog_ops;
struct rt_watchdog_device
{
struct rt_device parent;
const struct rt_watchdog_ops *ops;
const char *name;
rt_uint32_t paddr;
rt_uint32_t vaddr;
rt_uint32_t irqno;
wdog_config_t *config;
};
typedef struct rt_watchdog_device rt_watchdog_t;
struct rt_watchdog_ops
{
rt_err_t (*init)(rt_watchdog_t *wdt);
rt_err_t (*control)(rt_watchdog_t *wdt, int cmd, void *arg);
};
rt_err_t rt_hw_watchdog_register(rt_watchdog_t *wdt,
const char *name,
rt_uint32_t flag,
void *data);
#endif /* __WATCHDOG_H__ */

View File

@ -0,0 +1,386 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-03-22 quanzhao first version
*/
#ifndef __IMX6UL_H__
#define __IMX6UL_H__
#include <rthw.h>
#include <rtthread.h>
#ifdef RT_USING_LWP
#include <lwp.h>
#include <ioremap.h>
#endif
enum _gic_base_offsets
{
kGICDBaseOffset = 0x1000, //!< GIC distributor offset.
kGICCBaseOffset = 0x2000 //!< GIC CPU interface offset.
};
/* SOC-relative definitions */
enum _imx_interrupts
{
SW_INTERRUPT_0 = 0, //!< Software interrupt 0.
SW_INTERRUPT_1 = 1, //!< Software interrupt 1.
SW_INTERRUPT_2 = 2, //!< Software interrupt 2.
SW_INTERRUPT_3 = 3, //!< Software interrupt 3.
SW_INTERRUPT_4 = 4, //!< Software interrupt 4.
SW_INTERRUPT_5 = 5, //!< Software interrupt 5.
SW_INTERRUPT_6 = 6, //!< Software interrupt 6.
SW_INTERRUPT_7 = 7, //!< Software interrupt 7.
SW_INTERRUPT_8 = 8, //!< Software interrupt 8.
SW_INTERRUPT_9 = 9, //!< Software interrupt 9.
SW_INTERRUPT_10 = 10, //!< Software interrupt 10.
SW_INTERRUPT_11 = 11, //!< Software interrupt 11.
SW_INTERRUPT_12 = 12, //!< Software interrupt 12.
SW_INTERRUPT_13 = 13, //!< Software interrupt 13.
SW_INTERRUPT_14 = 14, //!< Software interrupt 14.
SW_INTERRUPT_15 = 15, //!< Software interrupt 15.
RSVD_INTERRUPT_16 = 16, //!< Reserved.
RSVD_INTERRUPT_17 = 17, //!< Reserved.
RSVD_INTERRUPT_18 = 18, //!< Reserved.
RSVD_INTERRUPT_19 = 19, //!< Reserved.
RSVD_INTERRUPT_20 = 20, //!< Reserved.
RSVD_INTERRUPT_21 = 21, //!< Reserved.
RSVD_INTERRUPT_22 = 22, //!< Reserved.
RSVD_INTERRUPT_23 = 23, //!< Reserved.
RSVD_INTERRUPT_24 = 24, //!< Reserved.
RSVD_INTERRUPT_25 = 25, //!< Reserved.
RSVD_INTERRUPT_26 = 26, //!< Reserved.
RSVD_INTERRUPT_27 = 27, //!< Reserved.
RSVD_INTERRUPT_28 = 28, //!< Reserved.
RSVD_INTERRUPT_29 = 29, //!< Reserved.
RSVD_INTERRUPT_30 = 30, //!< Reserved.
RSVD_INTERRUPT_31 = 31, //!< Reserved.
IMX_INT_IOMUXC_GPR = 32, //!< General Purpose Register 1 from IOMUXC. Used to notify cores on exception condition while boot.
IMX_INT_CHEETAH_CSYSPWRUPREQ = 33, //!< @todo Listed as DAP in RM
IMX_INT_SDMA = 34, //!< Logical OR of all 48 SDMA interrupt requests/events from all channels.
IMX_INT_TSC = 35, //!< TSC
IMX_INT_SNVS_LP_SET_PWR_OFF = 36, //!< PMIC power off request.
IMX_INT_LCDIF = 37, //!< LCDIF interrupt request.
IMX_INT_BEE = 38, //!< BEE interrupt request.
IMX_INT_CSI = 39, //!< CMOS Sensor Interface interrupt request.
IMX_INT_PXP = 40, //!< PXP interrupt request.
IMX_INT_SCTR1 = 41, //!< SCTR1
IMX_INT_SCTR2 = 42, //!< SCTR2
IMX_INT_WDOG3 = 43, //!< WDOG3 timer reset interrupt request.
IMX_INT_INTERRUPT_44 = 44, //!< Reserved.
IMX_INT_APBH_DMA = 45, //!< APBH DMA
IMX_INT_EIM = 46, //!< EIM interrupt request.
IMX_INT_NAND_BCH = 47, //!< Reserved.
IMX_INT_NAND_GPMI = 48, //!< Reserved.
IMX_INT_UART6 = 49, //!< Logical OR of UART5 interrupt requests.
IMX_INT_INTERRUPT_50 = 50, //!< Reserved.
IMX_INT_SNVS = 51, //!< SNVS consolidated interrupt.
IMX_INT_SNVS_SEC = 52, //!< SNVS security interrupt.
IMX_INT_CSU = 53, //!< CSU interrupt request 1. Indicates to the processor that one or more alarm inputs were asserted.
IMX_INT_USDHC1 = 54, //!< uSDHC1 (Enhanced SDHC) interrupt request.
IMX_INT_USDHC2 = 55, //!< uSDHC2 (Enhanced SDHC) interrupt request.
IMX_INT_SAI3 = 56, //!< uSDHC3 (Enhanced SDHC) interrupt request.
IMX_INT_SAI4 = 57, //!< uSDHC4 (Enhanced SDHC) interrupt request.
IMX_INT_UART1 = 58, //!< Logical OR of UART1 interrupt requests.
IMX_INT_UART2 = 59, //!< Logical OR of UART2 interrupt requests.
IMX_INT_UART3 = 60, //!< Logical OR of UART3 interrupt requests.
IMX_INT_UART4 = 61, //!< Logical OR of UART4 interrupt requests.
IMX_INT_UART5 = 62, //!< Logical OR of UART5 interrupt requests.
IMX_INT_ECSPI1 = 63, //!< eCSPI1 interrupt request.
IMX_INT_ECSPI2 = 64, //!< eCSPI2 interrupt request.
IMX_INT_ECSPI3 = 65, //!< eCSPI3 interrupt request.
IMX_INT_ECSPI4 = 66, //!< eCSPI4 interrupt request.
IMX_INT_I2C4 = 67, //!< Reserved.
IMX_INT_I2C1 = 68, //!< I2C1 interrupt request.
IMX_INT_I2C2 = 69, //!< I2C2 interrupt request.
IMX_INT_I2C3 = 70, //!< I2C3 interrupt request.
IMX_INT_UART7 = 71, //!< Logical OR of UART5 interrupt requests.
IMX_INT_UART8 = 72, //!< Logical OR of UART5 interrupt requests.
IMX_INT_INTERRUPT_73 = 73, //!< Reserved.
IMX_INT_USB_OTG2 = 74, //!< USB Host 1 interrupt request.
IMX_INT_USB_OTG1 = 75, //!< USB OTG1 interrupt request.
IMX_INT_USB_UTMI0 = 76, //!< UTMI0 interrupt request.
IMX_INT_USB_UTMI1 = 77, //!< UTMI1 interrupt request.
IMX_INT_CAAM_JQ2 = 78, //!< SSI1 interrupt request.
IMX_INT_CAAM_ERR = 79, //!< SSI2 interrupt request.
IMX_INT_CAAM_RTIC = 80, //!< SSI3 interrupt request.
IMX_INT_TEMPERATURE = 81, //!< Temperature Sensor (temp. greater than threshold) interrupt request.
IMX_INT_ASRC = 82, //!< Reserved.
IMX_INT_INTERRUPT_83 = 83, //!< Reserved.
IMX_INT_SPDIF = 84, //!< Logical OR of SPDIF TX and SPDIF RX interrupts.
IMX_INT_INTERRUPT_85 = 85, //!< Reserved.
IMX_INT_PMU_ANA_BO = 86, //!< PMU analog regulator brown-out interrupt request.
IMX_INT_GPT1 = 87, //
IMX_INT_EPIT1 = 88, //!< EPIT1 output compare interrupt.
IMX_INT_EPIT2 = 89, //!< EPIT2 output compare interrupt.
IMX_INT_GPIO1_INT7 = 90, //!< INT7 interrupt request.
IMX_INT_GPIO1_INT6 = 91, //!< INT6 interrupt request.
IMX_INT_GPIO1_INT5 = 92, //!< INT5 interrupt request.
IMX_INT_GPIO1_INT4 = 93, //!< INT4 interrupt request.
IMX_INT_GPIO1_INT3 = 94, //!< INT3 interrupt request.
IMX_INT_GPIO1_INT2 = 95, //!< INT2 interrupt request.
IMX_INT_GPIO1_INT1 = 96, //!< INT1 interrupt request.
IMX_INT_GPIO1_INT0 = 97, //!< INT0 interrupt request.
IMX_INT_GPIO1_INT15_0 = 98, //!< Combined interrupt indication for GPIO1 signals 0 - 15.
IMX_INT_GPIO1_INT31_16 = 99, //!< Combined interrupt indication for GPIO1 signals 16 - 31.
IMX_INT_GPIO2_INT15_0 = 100, //!< Combined interrupt indication for GPIO2 signals 0 - 15.
IMX_INT_GPIO2_INT31_16 = 101, //!< Combined interrupt indication for GPIO2 signals 16 - 31.
IMX_INT_GPIO3_INT15_0 = 102, //!< Combined interrupt indication for GPIO3 signals 0 - 15.
IMX_INT_GPIO3_INT31_16 = 103, //!< Combined interrupt indication for GPIO3 signals 16 - 31.
IMX_INT_GPIO4_INT15_0 = 104, //!< Combined interrupt indication for GPIO4 signals 0 - 15.
IMX_INT_GPIO4_INT31_16 = 105, //!< Combined interrupt indication for GPIO4 signals 16 - 31.
IMX_INT_GPIO5_INT15_0 = 106, //!< Combined interrupt indication for GPIO5 signals 0 - 15.
IMX_INT_GPIO5_INT31_16 = 107, //!< Combined interrupt indication for GPIO5 signals 16 - 31.
IMX_INT_INTERRUPT_108 = 108, //!< Reserved.
IMX_INT_INTERRUPT_109 = 109, //!< Reserved.
IMX_INT_INTERRUPT_110 = 110, //!< Reserved.
IMX_INT_INTERRUPT_111 = 111, //!< Reserved.
IMX_INT_WDOG1 = 112, //!< WDOG1 timer reset interrupt request.
IMX_INT_WDOG2 = 113, //!< WDOG2 timer reset interrupt request.
IMX_INT_KPP = 114, //!< Key Pad interrupt request.
IMX_INT_PWM1 = 115, //!< Cumulative interrupt line for PWM1. Logical OR of rollover, compare, and FIFO waterlevel crossing interrupts.
IMX_INT_PWM2 = 116, //!< Cumulative interrupt line for PWM2. Logical OR of rollover, compare, and FIFO waterlevel crossing interrupts.
IMX_INT_PWM3 = 117, //!< Cumulative interrupt line for PWM3. Logical OR of rollover, compare, and FIFO waterlevel crossing interrupts.
IMX_INT_PWM4 = 118, //!< Cumulative interrupt line for PWM4. Logical OR of rollover, compare, and FIFO waterlevel crossing interrupts.
IMX_INT_CCM_INT1 = 119, //!< CCM interrupt request 1.
IMX_INT_CCM_INT2 = 120, //!< CCM interrupt request 2.
IMX_INT_GPC_INT1 = 121, //!< GPC interrupt request 1.
IMX_INT_INTERRUPT_122 = 122, //!< Reserved.
IMX_INT_SRC = 123, //!< SRC interrupt request.
IMX_INT_INTERRUPT_124 = 124, //!< Logical OR of all L2 interrupt requests.
IMX_INT_INTERRUPT_125 = 125, //!< Parity Check error interrupt request.
IMX_INT_CHEETAH_PERFORM = 126, //!< Logical OR of Performance Unit interrupts.
IMX_INT_CHEETAH_TRIGGER = 127, //!< Logical OR of CTI trigger outputs.
IMX_INT_SRC_CPU_WDOG = 128, //!< Combined CPU wdog interrupts (4x) out of SRC.
IMX_INT_SAI1 = 129, //!< EPDC interrupt request.
IMX_INT_SAI2 = 130, //!< EPDC interrupt request.
IMX_INT_INTERRUPT_131 = 131, //!< DCP general interrupt request.
IMX_INT_ADC1 = 132, //!< DCP channel 0 interrupt request.
IMX_INT_ADC2 = 133, //!< DCP secure interrupt request.
IMX_INT_INTERRUPT_134 = 134, //!< Reserved.
IMX_INT_INTERRUPT_135 = 135, //!< Reserved.
IMX_INT_SJC = 136, //!< SJC interrupt from General Purpose register.
IMX_INT_CAAM_0 = 137, //!< Reserved.
IMX_INT_CAAM_1 = 138, //!< Reserved.
IMX_INT_QSPI = 139, //!< Reserved.
IMX_INT_TZASC1 = 140, //!< ASC1 interrupt request.
IMX_INT_GPT2 = 141, //!< Reserved.
IMX_INT_CAN1 = 142, //!< Reserved.
IMX_INT_CAN2 = 143, //!< Reserved.
IMX_INT_SIM1 = 144, //!< Reserved.
IMX_INT_SIM2 = 145, //!< Reserved.
IMX_INT_PWM5 = 146, //!< Fast Ethernet Controller interrupt request.
IMX_INT_PWM6 = 147, //!< Reserved.
IMX_INT_PWM7 = 148, //!< Reserved.
IMX_INT_PWM8 = 149, //!< Reserved.
IMX_INT_ENET1 = 150, //!< Reserved.
IMX_INT_ENET1_TIMER = 151, //!< Reserved.
IMX_INT_ENET2 = 152, //!< Reserved.
IMX_INT_ENET2_TIMER = 153, //!< Reserved.
IMX_INT_INTERRUPT_154 = 154, //!< Reserved.
IMX_INT_INTERRUPT_155 = 155, //!< Reserved.
IMX_INT_INTERRUPT_156 = 156, //!< Reserved.
IMX_INT_INTERRUPT_157 = 157, //!< Reserved.
IMX_INT_INTERRUPT_158 = 158, //!< Reserved.
IMX_INT_PMU_DIG_BO = 159, //!< //!< PMU digital regulator brown-out interrupt request.
IMX_INTERRUPT_COUNT = 160 //!< Total number of interrupts.
};
/* SOC-relative definitions */
#include "MCIMX6Y2.h"
#include "fsl_cache.h"
#include "fsl_common.h"
#include "fsl_iomuxc.h"
#include "fsl_gpio.h"
#include "fsl_elcdif.h"
#include "fsl_usdhc.h"
#include "fsl_card.h"
#include "fsl_wdog.h"
#include "fsl_i2c.h"
#include "fsl_ecspi.h"
#include "fsl_snvs_hp.h"
#include "fsl_adc.h"
#define IMX6ULL_PERIPH_SIZE (16 * 1024)
/* Interrupt Control Interface */
#define ARM_GIC_CPU_BASE 0x00A00000
/*
* Peripheral addresses
*/
#define IMX6ULL_UART1_BASE UART1_BASE /* UART 1 */
#define IMX6ULL_UART2_BASE UART2_BASE /* UART 2 */
#define IMX6ULL_UART3_BASE UART3_BASE /* UART 3 */
#define IMX6ULL_UART4_BASE UART4_BASE /* UART 4 */
#define IMX6ULL_UART5_BASE UART5_BASE /* UART 5 */
#define IMX6ULL_UART6_BASE UART6_BASE /* UART 6 */
#define IMX6ULL_UART7_BASE UART7_BASE /* UART 7 */
#define IMX6ULL_UART8_BASE UART8_BASE /* UART 8 */
#define IMX6ULL_WATCHDOG1_BASE WDOG1_BASE /* watchdog 1 */
#define IMX6ULL_WATCHDOG2_BASE WDOG2_BASE /* watchdog 2 */
#define IMX6ULL_WATCHDOG3_BASE WDOG3_BASE /* watchdog 3 */
#define IMX6ULL_GPIO1_BASE GPIO1_BASE /* GPIO port 0 */
#define IMX6ULL_GPIO2_BASE GPIO2_BASE /* GPIO port 1 */
#define IMX6ULL_GPIO3_BASE GPIO3_BASE /* GPIO port 2 */
#define IMX6ULL_GPIO4_BASE GPIO4_BASE /* GPIO port 3 */
#define IMX6ULL_GPIO5_BASE GPIO5_BASE /* GPIO port 4 */
#define IMX6ULL_SNVS_BASE SNVS_BASE /* Real Time Clock */
#define IMX6ULL_SCTL_BASE 0x021DC000u /* System Controller */
#define IMX6ULL_CLCD_BASE LCDIF_BASE /* CLCD */
#define IMX6ULL_GIC_DIST_BASE (ARM_GIC_CPU_BASE+kGICDBaseOffset) /* Generic interrupt controller distributor */
#define IMX6ULL_GIC_CPU_BASE (ARM_GIC_CPU_BASE+kGICCBaseOffset) /* Generic interrupt controller CPU interface */
#define IMX6ULL_IOMUXC_BASE IOMUXC_BASE
#define IMX6ULL_IOMUXC_SNVS_BASE IOMUXC_SNVS_BASE
#define IMX6ULL_IOMUXC_GPR_BASE IOMUXC_GPR_BASE
#define IMX6ULL_CCM_BASE 0x20C4000u
#define IMX6ULL_CCM_ANALOGY_BASE 0x20C8000u
#define IMX6ULL_PMU_BASE 0x20C8110u
#define IMX6ULL_ENET1_BASE ENET1_BASE
#define IMX6ULL_ENET2_BASE ENET2_BASE
#define IMX6ULL_GPT1_BASE GPT1_BASE
#define IMX6ULL_GPT2_BASE GPT2_BASE
#define IMX6ULL_ECSPI1_BASE ECSPI1_BASE
#define IMX6ULL_ECSPI2_BASE ECSPI2_BASE
#define IMX6ULL_ECSPI3_BASE ECSPI3_BASE
#define IMX6ULL_ECSPI4_BASE ECSPI4_BASE
#define IMX6ULL_I2C1_BASE I2C1_BASE
#define IMX6ULL_I2C2_BASE I2C2_BASE
#define IMX6ULL_I2C3_BASE I2C3_BASE
#define IMX6ULL_I2C4_BASE I2C4_BASE
#define IMX6ULL_SDMA_BASE SDMAARM_BASE
#define IMX6ULL_USDHC1_BASE USDHC1_BASE
#define IMX6ULL_USDHC2_BASE USDHC2_BASE
#define IMX6ULL_SRC_BASE SRC_BASE
#define IMX6ULL_GPMI_BASE GPMI_BASE
#define IMX6ULL_BCH_BASE BCH_BASE
#define IMX6ULL_APBH_BASE APBH_BASE
#define IMX6ULL_CSI_BASE CSI_BASE
#define IMX6ULL_CAN1_BASE CAN1_BASE
#define IMX6ULL_CAN2_BASE CAN2_BASE
#define IMX6ULL_USBPHY1_BASE 0x20C9000u
#define IMX6ULL_USBPHY2_BASE 0x20CA000u
#define IMX6ULL_USB1_BASE 0x2184000u
#define IMX6ULL_USB2_BASE 0x2184200u
#define IMX6ULL_USB_ANALOG_BASE 0x20C81A0u
/* the maximum number of gic */
#define ARM_GIC_MAX_NR 1
#define _internal_ro static const
#define _internal_rw static
#define _internal_zi static
#define GET_ARRAY_NUM(ins) ((uint32_t)(sizeof(ins)/sizeof(ins[0])))
#include "bsp_clock.h"
/* the maximum number of interrupts */
#define ARM_GIC_NR_IRQS IMX_INTERRUPT_COUNT
/* the maximum entries of the interrupt table */
#define MAX_HANDLERS IMX_INTERRUPT_COUNT
/* the basic constants needed by gic */
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
{
rt_uint32_t gic_base;
asm volatile ("mrc p15, 4, %0, c15, c0, 0" : "=r"(gic_base));
return gic_base + kGICDBaseOffset;
}
rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
{
rt_uint32_t gic_base;
asm volatile ("mrc p15, 4, %0, c15, c0, 0" : "=r"(gic_base));
return gic_base + kGICCBaseOffset;
}
rt_inline rt_uint32_t platform_get_periph_vaddr(rt_uint32_t paddr)
{
#ifdef RT_USING_SMART
rt_uint32_t mask = IMX6ULL_PERIPH_SIZE - 1;
return (rt_uint32_t)rt_ioremap((void*)(paddr&(~mask)), IMX6ULL_PERIPH_SIZE) + (paddr & mask);
#else
return paddr;
#endif
}
#define GIC_IRQ_START 0
#define GIC_ACK_INTID_MASK 0x000003ff
/* the definition needed by gic.c */
#define __REG32(x) (*((volatile unsigned int *)(x)))
/* keep compatible with platform SDK */
typedef enum {
CPU_0,
CPU_1,
CPU_2,
CPU_3,
} cpuid_e;
enum _gicd_sgi_filter
{
//! Forward the interrupt to the CPU interfaces specified in the @a target_list parameter.
kGicSgiFilter_UseTargetList = 0,
//! Forward the interrupt to all CPU interfaces except that of the processor that requested
//! the interrupt.
kGicSgiFilter_AllOtherCPUs = 1,
//! Forward the interrupt only to the CPU interface of the processor that requested the
//! interrupt.
kGicSgiFilter_OnlyThisCPU = 2
};
typedef void (*irq_hdlr_t) (void);
extern void rt_hw_interrupt_mask(int vector);
extern void rt_hw_interrupt_umask(int vector);
extern rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name);
rt_inline void register_interrupt_routine(uint32_t irq_id, irq_hdlr_t isr)
{
rt_hw_interrupt_install(irq_id, (rt_isr_handler_t)isr, RT_NULL, "unknown");
}
rt_inline void enable_interrupt(uint32_t irq_id, uint32_t cpu_id, uint32_t priority)
{
rt_hw_interrupt_umask(irq_id);
}
rt_inline void disable_interrupt(uint32_t irq_id, uint32_t cpu_id)
{
rt_hw_interrupt_mask(irq_id);
}
#endif /* __IMX6UL_H__ */

View File

@ -0,0 +1,59 @@
#ifndef RT_LCD_H__
#define RT_LCD_H__
/* ioctls
0x46 is 'F' */
#define FBIOGET_VSCREENINFO 0x4600
#define FBIOPUT_VSCREENINFO 0x4601
#define FBIOGET_FSCREENINFO 0x4602
#define FBIOGETCMAP 0x4604
#define FBIOPUTCMAP 0x4605
#define FBIOPAN_DISPLAY 0x4606
#define FBIO_CURSOR 0x4608
/* #define FBIOGET_MONITORSPEC 0x460C */
/* #define FBIOPUT_MONITORSPEC 0x460D */
/* #define FBIOSWITCH_MONIBIT 0x460E */
#define FBIOGET_CON2FBMAP 0x460F
#define FBIOPUT_CON2FBMAP 0x4610
#define FBIOBLANK 0x4611 /* arg: 0 or vesa level + 1 */
#define FBIOGET_VBLANK 0x4612
#define FBIO_ALLOC 0x4613
#define FBIO_FREE 0x4614
#define FBIOGET_GLYPH 0x4615
#define FBIOGET_HWCINFO 0x4616
#define FBIOPUT_MODEINFO 0x4617
#define FBIOGET_DISPINFO 0x4618
#define FBIO_WAITFORVSYNC 0x4620
struct fb_bitfield
{
uint32_t offset; /* beginning of bitfield */
uint32_t length; /* length of bitfield */
uint32_t msb_right; /* != 0 : Most significant bit is */
/* right */
};
struct fb_var_screeninfo
{
uint32_t xres;
uint32_t yres;
uint32_t bits_per_pixel;
struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */
};
struct fb_fix_screeninfo
{
char id[16];
unsigned long smem_start;
uint32_t smem_len;
uint32_t line_length;
};
#endif

View File

@ -0,0 +1,644 @@
/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FSL_USB_DEVICE_H__
#define __FSL_USB_DEVICE_H__
/*!
* @addtogroup usb_device_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Defines Get/Set status Types */
typedef enum _usb_device_status
{
kUSB_DeviceStatusTestMode = 1U, /*!< Test mode */
kUSB_DeviceStatusSpeed, /*!< Current speed */
kUSB_DeviceStatusOtg, /*!< OTG status */
kUSB_DeviceStatusDevice, /*!< Device status */
kUSB_DeviceStatusEndpoint, /*!< Endpoint state usb_device_endpoint_status_t */
kUSB_DeviceStatusDeviceState, /*!< Device state */
kUSB_DeviceStatusAddress, /*!< Device address */
kUSB_DeviceStatusSynchFrame, /*!< Current frame */
kUSB_DeviceStatusBus, /*!< Bus status */
kUSB_DeviceStatusBusSuspend, /*!< Bus suspend */
kUSB_DeviceStatusBusSleep, /*!< Bus suspend */
kUSB_DeviceStatusBusResume, /*!< Bus resume */
kUSB_DeviceStatusRemoteWakeup, /*!< Remote wakeup state */
kUSB_DeviceStatusBusSleepResume, /*!< Bus resume */
} usb_device_status_t;
/*! @brief Defines USB 2.0 device state */
typedef enum _usb_device_state
{
kUSB_DeviceStateConfigured = 0U, /*!< Device state, Configured*/
kUSB_DeviceStateAddress, /*!< Device state, Address*/
kUSB_DeviceStateDefault, /*!< Device state, Default*/
kUSB_DeviceStateAddressing, /*!< Device state, Address setting*/
kUSB_DeviceStateTestMode, /*!< Device state, Test mode*/
} usb_device_state_t;
#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
typedef enum _usb_dcd_detection_sequence_status
{
kUSB_DcdDetectionNotEnabled = 0x0U,
kUSB_DcdDataPinDetectionCompleted = 0x01U,
kUSB_DcdChargingPortDetectionCompleted = 0x02U,
kUSB_DcdChargerTypeDetectionCompleted = 0x03U,
} usb_dcd_detection_sequence_status_t;
typedef enum _usb_dcd_detection_sequence_results
{
kUSB_DcdDetectionNoResults = 0x0U,
kUSB_DcdDetectionStandardHost = 0x01U,
kUSB_DcdDetectionChargingPort = 0x02U,
kUSB_DcdDetectionDedicatedCharger = 0x03U,
} usb_dcd_detection_sequence_results_t;
#endif
/*! @brief Defines endpoint state */
typedef enum _usb_endpoint_status
{
kUSB_DeviceEndpointStateIdle = 0U, /*!< Endpoint state, idle*/
kUSB_DeviceEndpointStateStalled, /*!< Endpoint state, stalled*/
} usb_device_endpoint_status_t;
/*! @brief Control endpoint index */
#define USB_CONTROL_ENDPOINT (0U)
/*! @brief Control endpoint maxPacketSize */
#define USB_CONTROL_MAX_PACKET_SIZE (64U)
#if (USB_DEVICE_CONFIG_EHCI && (USB_CONTROL_MAX_PACKET_SIZE != (64U)))
#error For high speed, USB_CONTROL_MAX_PACKET_SIZE must be 64!!!
#endif
/*! @brief The setup packet size of USB control transfer. */
#define USB_SETUP_PACKET_SIZE (8U)
/*! @brief USB endpoint mask */
#define USB_ENDPOINT_NUMBER_MASK (0x0FU)
/*! @brief Default invalid value or the endpoint callback length of cancelled transfer */
#define USB_UNINITIALIZED_VAL_32 (0xFFFFFFFFU)
/*! @brief Available common EVENT types in device callback */
typedef enum _usb_device_event
{
kUSB_DeviceEventBusReset = 1U, /*!< USB bus reset signal detected */
kUSB_DeviceEventSuspend, /*!< USB bus suspend signal detected */
kUSB_DeviceEventResume, /*!< USB bus resume signal detected. The resume signal is driven by itself or a host */
kUSB_DeviceEventSleeped, /*!< USB bus LPM suspend signal detected */
kUSB_DeviceEventLPMResume, /*!< USB bus LPM resume signal detected. The resume signal is driven by itself or a host
*/
kUSB_DeviceEventError, /*!< An error is happened in the bus. */
kUSB_DeviceEventDetach, /*!< USB device is disconnected from a host. */
kUSB_DeviceEventAttach, /*!< USB device is connected to a host. */
kUSB_DeviceEventSetConfiguration, /*!< Set configuration. */
kUSB_DeviceEventSetInterface, /*!< Set interface. */
kUSB_DeviceEventGetDeviceDescriptor, /*!< Get device descriptor. */
kUSB_DeviceEventGetConfigurationDescriptor, /*!< Get configuration descriptor. */
kUSB_DeviceEventGetStringDescriptor, /*!< Get string descriptor. */
kUSB_DeviceEventGetHidDescriptor, /*!< Get HID descriptor. */
kUSB_DeviceEventGetHidReportDescriptor, /*!< Get HID report descriptor. */
kUSB_DeviceEventGetHidPhysicalDescriptor, /*!< Get HID physical descriptor. */
kUSB_DeviceEventGetBOSDescriptor, /*!< Get configuration descriptor. */
kUSB_DeviceEventGetDeviceQualifierDescriptor, /*!< Get device qualifier descriptor. */
kUSB_DeviceEventVendorRequest, /*!< Vendor request. */
kUSB_DeviceEventSetRemoteWakeup, /*!< Enable or disable remote wakeup function. */
kUSB_DeviceEventGetConfiguration, /*!< Get current configuration index */
kUSB_DeviceEventGetInterface, /*!< Get current interface alternate setting value */
kUSB_DeviceEventSetBHNPEnable,
#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
kUSB_DeviceEventDcdTimeOut, /*!< Dcd detect result is timeout */
kUSB_DeviceEventDcdUnknownType, /*!< Dcd detect result is unknown type */
kUSB_DeviceEventSDPDetected, /*!< The SDP facility is detected */
kUSB_DeviceEventChargingPortDetected, /*!< The charging port is detected */
kUSB_DeviceEventChargingHostDetected, /*!< The CDP facility is detected */
kUSB_DeviceEventDedicatedChargerDetected, /*!< The DCP facility is detected */
#endif
} usb_device_event_t;
/*! @brief Endpoint callback message structure */
typedef struct _usb_device_endpoint_callback_message_struct
{
uint8_t *buffer; /*!< Transferred buffer */
uint32_t length; /*!< Transferred data length */
uint8_t isSetup; /*!< Is in a setup phase */
} usb_device_endpoint_callback_message_struct_t;
/*!
* @brief Endpoint callback function typedef.
*
* This callback function is used to notify the upper layer what the transfer result is.
* This callback pointer is passed when a specified endpoint is initialized by calling API #USB_DeviceInitEndpoint.
*
* @param handle The device handle. It equals to the value returned from #USB_DeviceInit.
* @param message The result of a transfer, which includes transfer buffer, transfer length, and whether is in a
* setup phase.
* phase for control pipe.
* @param callbackParam The parameter for this callback. It is same with
* usb_device_endpoint_callback_struct_t::callbackParam.
*
* @return A USB error code or kStatus_USB_Success.
*/
typedef usb_status_t (*usb_device_endpoint_callback_t)(usb_device_handle handle,
usb_device_endpoint_callback_message_struct_t *message,
void *callbackParam);
/*!
* @brief Device callback function typedef.
*
* This callback function is used to notify the upper layer that the device status has changed.
* This callback pointer is passed by calling API #USB_DeviceInit.
*
* @param handle The device handle. It equals the value returned from #USB_DeviceInit.
* @param callbackEvent The callback event type. See enumeration #usb_device_event_t.
* @param eventParam The event parameter for this callback. The parameter type is determined by the callback event.
*
* @return A USB error code or kStatus_USB_Success.
*/
typedef usb_status_t (*usb_device_callback_t)(usb_device_handle handle, uint32_t callbackEvent, void *eventParam);
/*! @brief Endpoint callback structure */
typedef struct _usb_device_endpoint_callback_struct
{
usb_device_endpoint_callback_t callbackFn; /*!< Endpoint callback function*/
void *callbackParam; /*!< Parameter for callback function*/
uint8_t isBusy;
} usb_device_endpoint_callback_struct_t;
/*! @brief Endpoint initialization structure */
typedef struct _usb_device_endpoint_init_struct
{
uint16_t maxPacketSize; /*!< Endpoint maximum packet size */
uint8_t endpointAddress; /*!< Endpoint address*/
uint8_t transferType; /*!< Endpoint transfer type*/
uint8_t zlt; /*!< ZLT flag*/
} usb_device_endpoint_init_struct_t;
/*! @brief Endpoint status structure */
typedef struct _usb_device_endpoint_status_struct
{
uint8_t endpointAddress; /*!< Endpoint address */
uint16_t endpointStatus; /*!< Endpoint status : idle or stalled */
} usb_device_endpoint_status_struct_t;
#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
/*! @brief USB DCD charge timing specification structure */
typedef struct _usb_device_dcd_charging_time
{
uint16_t dcdSeqInitTime; /*!< The dcd sequence init time */
uint16_t dcdDbncTime; /*!< The debounce time period on DP signal */
uint16_t dcdDpSrcOnTime; /*!< The time period comparator enabled */
uint16_t dcdTimeWaitAfterPrD; /*!< The time period between primary and secondary detection */
uint8_t dcdTimeDMSrcOn; /*!< The amount of time that the modules enable the Vdm_src */
} usb_device_dcd_charging_time_t;
#endif
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*!
* @name USB device APIs
* @{
*/
/*******************************************************************************
* API
******************************************************************************/
/*!
* @brief Initializes the USB device stack.
*
* This function initializes the USB device module specified by the controllerId.
*
* @param[in] controllerId The controller ID of the USB IP. See the enumeration #usb_controller_index_t.
* @param[in] deviceCallback Function pointer of the device callback.
* @param[out] handle It is an out parameter used to return the pointer of the device handle to the caller.
*
* @retval kStatus_USB_Success The device is initialized successfully.
* @retval kStatus_USB_InvalidHandle The handle is a NULL pointer.
* @retval kStatus_USB_Busy Cannot allocate a device handle.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller according to the controller id.
* @retval kStatus_USB_InvalidControllerInterface The controller driver interfaces is invalid. There is an empty
* interface entity.
* @retval kStatus_USB_Error The macro USB_DEVICE_CONFIG_ENDPOINTS is more than the IP's endpoint number.
* Or, the device has been initialized.
* Or, the mutex or message queue is created failed.
*/
extern usb_status_t USB_DeviceInit(uint8_t controllerId,
usb_device_callback_t deviceCallback,
usb_device_handle *handle);
/*!
* @brief Enables the device functionality.
*
* The function enables the device functionality, so that the device can be recognized by the host when the device
* detects that it has been connected to a host.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
*
* @retval kStatus_USB_Success The device is run successfully.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
* @retval kStatus_USB_InvalidHandle The device handle is a NULL pointer. Or the controller handle is invalid.
*
*/
extern usb_status_t USB_DeviceRun(usb_device_handle handle);
/*!
* @brief Disables the device functionality.
*
* The function disables the device functionality. After this function called, even if the device is detached to the
* host,
* it can't work.
*
* @param[in] handle The device handle received from #USB_DeviceInit.
*
* @retval kStatus_USB_Success The device is stopped successfully.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
* @retval kStatus_USB_InvalidHandle The device handle is a NULL pointer or the controller handle is invalid.
*/
extern usb_status_t USB_DeviceStop(usb_device_handle handle);
/*!
* @brief De-initializes the device controller.
*
* The function de-initializes the device controller specified by the handle.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
*
* @retval kStatus_USB_Success The device is stopped successfully.
* @retval kStatus_USB_InvalidHandle The device handle is a NULL pointer or the controller handle is invalid.
*/
extern usb_status_t USB_DeviceDeinit(usb_device_handle handle);
/*!
* @brief Sends data through a specified endpoint.
*
* The function is used to send data through a specified endpoint.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
* @param[in] endpointAddress Endpoint index.
* @param[in] buffer The memory address to hold the data need to be sent. The function is not reentrant.
* @param[in] length The data length need to be sent.
*
* @retval kStatus_USB_Success The send request is sent successfully.
* @retval kStatus_USB_InvalidHandle The handle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_Busy Cannot allocate DTDS for current transfer in EHCI driver.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
* @retval kStatus_USB_Error The device is doing reset.
*
* @note The return value indicates whether the sending request is successful or not. The transfer done is notified by
* the
* corresponding callback function.
* Currently, only one transfer request can be supported for one specific endpoint.
* If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
* should implement a queue on the application level.
* The subsequent transfer can begin only when the previous transfer is done (get notification through the endpoint
* callback).
*/
extern usb_status_t USB_DeviceSendRequest(usb_device_handle handle,
uint8_t endpointAddress,
uint8_t *buffer,
uint32_t length);
/*!
* @brief Receives data through a specified endpoint.
*
* The function is used to receive data through a specified endpoint. The function is not reentrant.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
* @param[in] endpointAddress Endpoint index.
* @param[in] buffer The memory address to save the received data.
* @param[in] length The data length want to be received.
*
* @retval kStatus_USB_Success The receive request is sent successfully.
* @retval kStatus_USB_InvalidHandle The handle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_Busy Cannot allocate DTDS for current transfer in EHCI driver.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
* @retval kStatus_USB_Error The device is doing reset.
*
* @note The return value indicates whether the receiving request is successful or not. The transfer done is notified by
* the
* corresponding callback function.
* Currently, only one transfer request can be supported for one specific endpoint.
* If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
* should implement a queue on the application level.
* The subsequent transfer can begin only when the previous transfer is done (get notification through the endpoint
* callback).
*/
extern usb_status_t USB_DeviceRecvRequest(usb_device_handle handle,
uint8_t endpointAddress,
uint8_t *buffer,
uint32_t length);
/*!
* @brief Cancels the pending transfer in a specified endpoint.
*
* The function is used to cancel the pending transfer in a specified endpoint.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
* @param[in] endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, and 0U - OUT.
*
* @retval kStatus_USB_Success The transfer is cancelled.
* @retval kStatus_USB_InvalidHandle The handle is a NULL pointer or the controller handle is invalid.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
*/
extern usb_status_t USB_DeviceCancel(usb_device_handle handle, uint8_t endpointAddress);
/*!
* @brief Initializes a specified endpoint.
*
* The function is used to initialize a specified endpoint. The corresponding endpoint callback is also initialized.
*
* @param[in] handle The device handle received from #USB_DeviceInit.
* @param[in] epInit Endpoint initialization structure. See the structure usb_device_endpoint_init_struct_t.
* @param[in] epCallback Endpoint callback structure. See the structure
* usb_device_endpoint_callback_struct_t.
*
* @retval kStatus_USB_Success The endpoint is initialized successfully.
* @retval kStatus_USB_InvalidHandle The handle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_InvalidParameter The epInit or epCallback is NULL pointer. Or the endpoint number is
* more than USB_DEVICE_CONFIG_ENDPOINTS.
* @retval kStatus_USB_Busy The endpoint is busy in EHCI driver.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
*/
extern usb_status_t USB_DeviceInitEndpoint(usb_device_handle handle,
usb_device_endpoint_init_struct_t *epInit,
usb_device_endpoint_callback_struct_t *epCallback);
/*!
* @brief Deinitializes a specified endpoint.
*
* The function is used to deinitializes a specified endpoint.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
* @param[in] endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, and 0U - OUT.
*
* @retval kStatus_USB_Success The endpoint is de-initialized successfully.
* @retval kStatus_USB_InvalidHandle The handle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_InvalidParameter The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
* @retval kStatus_USB_Busy The endpoint is busy in EHCI driver.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
*/
extern usb_status_t USB_DeviceDeinitEndpoint(usb_device_handle handle, uint8_t endpointAddress);
/*!
* @brief Stalls a specified endpoint.
*
* The function is used to stall a specified endpoint.
*
* @param[in] handle The device handle received from #USB_DeviceInit.
* @param[in] endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, and 0U - OUT.
*
* @retval kStatus_USB_Success The endpoint is stalled successfully.
* @retval kStatus_USB_InvalidHandle The handle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_InvalidParameter The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
*/
extern usb_status_t USB_DeviceStallEndpoint(usb_device_handle handle, uint8_t endpointAddress);
/*!
* @brief Unstalls a specified endpoint.
*
* The function is used to unstall a specified endpoint.
*
* @param[in] handle The device handle received from #USB_DeviceInit.
* @param[in] endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, and 0U - OUT.
*
* @retval kStatus_USB_Success The endpoint is unstalled successfully.
* @retval kStatus_USB_InvalidHandle The handle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_InvalidParameter The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
*/
extern usb_status_t USB_DeviceUnstallEndpoint(usb_device_handle handle, uint8_t endpointAddress);
/*!
* @brief Gets the status of the selected item.
*
* The function is used to get the status of the selected item.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
* @param[in] type The selected item. See the structure #usb_device_status_t.
* @param[out] param The parameter type is determined by the selected item.
*
* @retval kStatus_USB_Success Get status successfully.
* @retval kStatus_USB_InvalidHandle The handle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_InvalidParameter The parameter is NULL pointer.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
* @retval kStatus_USB_Error Unsupported type.
*/
extern usb_status_t USB_DeviceGetStatus(usb_device_handle handle, usb_device_status_t type, void *param);
/*!
* @brief Sets the status of the selected item.
*
* The function is used to set the status of the selected item.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
* @param[in] type The selected item. See the structure #usb_device_status_t.
* @param[in] param The parameter type is determined by the selected item.
*
* @retval kStatus_USB_Success Set status successfully.
* @retval kStatus_USB_InvalidHandle The handle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
* @retval kStatus_USB_Error Unsupported type or the parameter is NULL pointer.
*/
extern usb_status_t USB_DeviceSetStatus(usb_device_handle handle, usb_device_status_t type, void *param);
#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
/*!
* @brief Initializes the device dcd module.
*
* The function initializes the device dcd module.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
* @param[in] time_param The time parameter used to config the dcd timing registers.
*
* @retval kStatus_USB_Success The device is run successfully.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller.
* @retval kStatus_USB_InvalidHandle The device handle is a NULL pointer. Or the controller handle is invalid.
*
*/
extern usb_status_t USB_DeviceDcdInitModule(usb_device_handle handle, void *time_param);
/*!
* @brief De-initializes the device dcd module.
*
* The function de-initializes the device dcd module specified by the handle.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
*
* @retval kStatus_USB_Success The device is stopped successfully.
* @retval kStatus_USB_InvalidHandle The device handle is a NULL pointer or the controller handle is invalid.
*/
extern usb_status_t USB_DeviceDcdDeinitModule(usb_device_handle handle);
#endif
/*!
* @brief Device task function.
*
* The function is used to handle the controller message.
* This function should not be called in the application directly.
*
* @param[in] deviceHandle The device handle got from #USB_DeviceInit.
*/
extern void USB_DeviceTaskFunction(void *deviceHandle);
#if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
/*!
* @brief Device KHCI task function.
*
* The function is used to handle the KHCI controller message.
* In the bare metal environment, this function should be called periodically in the main function.
* In the RTOS environment, this function should be used as a function entry to create a task.
*
* @param[in] deviceHandle The device handle got from #USB_DeviceInit.
*/
#define USB_DeviceKhciTaskFunction(deviceHandle) USB_DeviceTaskFunction(deviceHandle)
#endif
#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
/*!
* @brief Device EHCI task function.
*
* The function is used to handle the EHCI controller message.
* In the bare metal environment, this function should be called periodically in the main function.
* In the RTOS environment, this function should be used as a function entry to create a task.
*
* @param[in] deviceHandle The device handle got from #USB_DeviceInit.
*/
#define USB_DeviceEhciTaskFunction(deviceHandle) USB_DeviceTaskFunction(deviceHandle)
#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
/*!
* @brief Device EHCI DCD ISR function.
*
* The function is the EHCI DCD interrupt service routine.
*
* @param[in] deviceHandle The device handle got from #USB_DeviceInit.
*/
extern void USB_DeviceDcdHSIsrFunction(void *deviceHandle);
#endif
#endif
#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
/*!
* @brief Device LPC ip3511 controller task function.
*
* The function is used to handle the LPC ip3511 controller message.
* In the bare metal environment, this function should be called periodically in the main function.
* In the RTOS environment, this function should be used as a function entry to create a task.
*
* @param[in] deviceHandle The device handle got from #USB_DeviceInit.
*/
#define USB_DeviceLpcIp3511TaskFunction(deviceHandle) USB_DeviceTaskFunction(deviceHandle)
#endif
#if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
/*!
* @brief Device KHCI ISR function.
*
* The function is the KHCI interrupt service routine.
*
* @param[in] deviceHandle The device handle got from #USB_DeviceInit.
*/
extern void USB_DeviceKhciIsrFunction(void *deviceHandle);
#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
/*!
* @brief Device KHCI DCD ISR function.
*
* The function is the KHCI DCD interrupt service routine.
*
* @param[in] deviceHandle The device handle got from #USB_DeviceInit.
*/
extern void USB_DeviceDcdIsrFunction(void *deviceHandle);
#endif
#endif
#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
/*!
* @brief Device EHCI ISR function.
*
* The function is the EHCI interrupt service routine.
*
* @param[in] deviceHandle The device handle got from #USB_DeviceInit.
*/
extern void USB_DeviceEhciIsrFunction(void *deviceHandle);
#endif
#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
/*!
* @brief Device LPC USB ISR function.
*
* The function is the LPC USB interrupt service routine.
*
* @param[in] deviceHandle The device handle got from #USB_DeviceInit.
*/
extern void USB_DeviceLpcIp3511IsrFunction(void *deviceHandle);
#endif
/*!
* @brief Gets the device stack version function.
*
* The function is used to get the device stack version.
*
* @param[out] version The version structure pointer to keep the device stack version.
*
*/
extern void USB_DeviceGetVersion(uint32_t *version);
#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
/*!
* @brief Update the hardware tick.
*
* The function is used to update the hardware tick.
*
* @param[in] handle The device handle got from #USB_DeviceInit.
* @param[in] tick Current hardware tick(uint is ms).
*
*/
extern usb_status_t USB_DeviceUpdateHwTick(usb_device_handle handle, uint64_t tick);
#endif
/*! @}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
#endif /* __USB_DEVICE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __USB_DEVICE_DCI_H__
#define __USB_DEVICE_DCI_H__
/*!
* @addtogroup usb_device_controller_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Macro to define controller handle */
#define usb_device_controller_handle usb_device_handle
/*! @brief Available notify types for device notification */
typedef enum _usb_device_notification
{
kUSB_DeviceNotifyBusReset = 0x10U, /*!< Reset signal detected */
kUSB_DeviceNotifySuspend, /*!< Suspend signal detected */
kUSB_DeviceNotifyResume, /*!< Resume signal detected */
kUSB_DeviceNotifyLPMSleep, /*!< LPM signal detected */
kUSB_DeviceNotifyLPMResume, /*!< Resume signal detected */
kUSB_DeviceNotifyError, /*!< Errors happened in bus */
kUSB_DeviceNotifyDetach, /*!< Device disconnected from a host */
kUSB_DeviceNotifyAttach, /*!< Device connected to a host */
#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
kUSB_DeviceNotifyDcdTimeOut, /*!< Device charger detection timeout */
kUSB_DeviceNotifyDcdUnknownPortType, /*!< Device charger detection unknown port type */
kUSB_DeviceNotifySDPDetected, /*!< The SDP facility is detected */
kUSB_DeviceNotifyChargingPortDetected, /*!< The charging port is detected */
kUSB_DeviceNotifyChargingHostDetected, /*!< The CDP facility is detected */
kUSB_DeviceNotifyDedicatedChargerDetected, /*!< The DCP facility is detected */
#endif
} usb_device_notification_t;
/*! @brief Device notification message structure */
typedef struct _usb_device_callback_message_struct
{
uint8_t *buffer; /*!< Transferred buffer */
uint32_t length; /*!< Transferred data length */
uint8_t code; /*!< Notification code */
uint8_t isSetup; /*!< Is in a setup phase */
} usb_device_callback_message_struct_t;
/*! @brief Control type for controller */
typedef enum _usb_device_control_type
{
kUSB_DeviceControlRun = 0U, /*!< Enable the device functionality */
kUSB_DeviceControlStop, /*!< Disable the device functionality */
kUSB_DeviceControlEndpointInit, /*!< Initialize a specified endpoint */
kUSB_DeviceControlEndpointDeinit, /*!< De-initialize a specified endpoint */
kUSB_DeviceControlEndpointStall, /*!< Stall a specified endpoint */
kUSB_DeviceControlEndpointUnstall, /*!< Unstall a specified endpoint */
kUSB_DeviceControlGetDeviceStatus, /*!< Get device status */
kUSB_DeviceControlGetEndpointStatus, /*!< Get endpoint status */
kUSB_DeviceControlSetDeviceAddress, /*!< Set device address */
kUSB_DeviceControlGetSynchFrame, /*!< Get current frame */
kUSB_DeviceControlResume, /*!< Drive controller to generate a resume signal in USB bus */
kUSB_DeviceControlSleepResume, /*!< Drive controller to generate a LPM resume signal in USB bus */
kUSB_DeviceControlSuspend, /*!< Drive controller to enetr into suspend mode */
kUSB_DeviceControlSleep, /*!< Drive controller to enetr into sleep mode */
kUSB_DeviceControlSetDefaultStatus, /*!< Set controller to default status */
kUSB_DeviceControlGetSpeed, /*!< Get current speed */
kUSB_DeviceControlGetOtgStatus, /*!< Get OTG status */
kUSB_DeviceControlSetOtgStatus, /*!< Set OTG status */
kUSB_DeviceControlSetTestMode, /*!< Drive xCHI into test mode */
kUSB_DeviceControlGetRemoteWakeUp, /*!< Get flag of LPM Remote Wake-up Enabled by USB host. */
#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U))
kUSB_DeviceControlDcdInitModule,
kUSB_DeviceControlDcdDeinitModule,
#endif
} usb_device_control_type_t;
/*! @brief USB device controller initialization function typedef */
typedef usb_status_t (*usb_device_controller_init_t)(uint8_t controllerId,
usb_device_handle handle,
usb_device_controller_handle *controllerHandle);
/*! @brief USB device controller de-initialization function typedef */
typedef usb_status_t (*usb_device_controller_deinit_t)(usb_device_controller_handle controllerHandle);
/*! @brief USB device controller send data function typedef */
typedef usb_status_t (*usb_device_controller_send_t)(usb_device_controller_handle controllerHandle,
uint8_t endpointAddress,
uint8_t *buffer,
uint32_t length);
/*! @brief USB device controller receive data function typedef */
typedef usb_status_t (*usb_device_controller_recv_t)(usb_device_controller_handle controllerHandle,
uint8_t endpointAddress,
uint8_t *buffer,
uint32_t length);
/*! @brief USB device controller cancel transfer function in a specified endpoint typedef */
typedef usb_status_t (*usb_device_controller_cancel_t)(usb_device_controller_handle controllerHandle,
uint8_t endpointAddress);
/*! @brief USB device controller control function typedef */
typedef usb_status_t (*usb_device_controller_control_t)(usb_device_controller_handle controllerHandle,
usb_device_control_type_t command,
void *param);
/*! @brief USB device controller interface structure */
typedef struct _usb_device_controller_interface_struct
{
usb_device_controller_init_t deviceInit; /*!< Controller initialization */
usb_device_controller_deinit_t deviceDeinit; /*!< Controller de-initialization */
usb_device_controller_send_t deviceSend; /*!< Controller send data */
usb_device_controller_recv_t deviceRecv; /*!< Controller receive data */
usb_device_controller_cancel_t deviceCancel; /*!< Controller cancel transfer */
usb_device_controller_control_t deviceControl; /*!< Controller control */
} usb_device_controller_interface_struct_t;
/*! @brief USB device status structure */
typedef struct _usb_device_struct
{
#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
volatile uint64_t hwTick; /*!< Current hw tick(ms)*/
#endif
usb_device_controller_handle controllerHandle; /*!< Controller handle */
const usb_device_controller_interface_struct_t *controllerInterface; /*!< Controller interface handle */
#if USB_DEVICE_CONFIG_USE_TASK
usb_osa_msgq_handle notificationQueue; /*!< Message queue */
#endif
usb_device_callback_t deviceCallback; /*!< Device callback function pointer */
usb_device_endpoint_callback_struct_t
epCallback[USB_DEVICE_CONFIG_ENDPOINTS << 1U]; /*!< Endpoint callback function structure */
uint8_t deviceAddress; /*!< Current device address */
uint8_t controllerId; /*!< Controller ID */
uint8_t state; /*!< Current device state */
#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
uint8_t remotewakeup; /*!< Remote wakeup is enabled or not */
#endif
uint8_t isResetting; /*!< Is doing device reset or not */
#if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
uint8_t epCallbackDirectly; /*!< Whether call ep callback directly when the task is enabled */
#endif
} usb_device_struct_t;
/*******************************************************************************
* API
******************************************************************************/
/*! @}*/
#endif /* __USB_DEVICE_DCI_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,219 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __USB_DEVICE_EHCI_H__
#define __USB_DEVICE_EHCI_H__
#include <usb/include/usb_ehci.h>
/*!
* @addtogroup usb_device_controller_ehci_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief The maximum value of ISO type maximum packet size for HS in USB specification 2.0 */
#define USB_DEVICE_MAX_HS_ISO_MAX_PACKET_SIZE (1024U)
/*! @brief The maximum value of interrupt type maximum packet size for HS in USB specification 2.0 */
#define USB_DEVICE_MAX_HS_INTERUPT_MAX_PACKET_SIZE (1024U)
/*! @brief The maximum value of bulk type maximum packet size for HS in USB specification 2.0 */
#define USB_DEVICE_MAX_HS_BULK_MAX_PACKET_SIZE (512U)
/*! @brief The maximum value of control type maximum packet size for HS in USB specification 2.0 */
#define USB_DEVICE_MAX_HS_CONTROL_MAX_PACKET_SIZE (64U)
/*! @brief EHCI state structure */
typedef struct _usb_device_ehci_state_struct
{
usb_device_struct_t *deviceHandle; /*!< Device handle used to identify the device object is belonged to */
USBHS_Type *registerBase; /*!< The base address of the register */
#if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
USBPHY_Type *registerPhyBase; /*!< The base address of the PHY register */
#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
USBNC_Type *registerNcBase; /*!< The base address of the USBNC register */
#endif
#endif
usb_device_ehci_qh_struct_t *qh; /*!< The QH structure base address */
usb_device_ehci_dtd_struct_t *dtd; /*!< The DTD structure base address */
usb_device_ehci_dtd_struct_t *dtdFree; /*!< The idle DTD list head */
usb_device_ehci_dtd_struct_t
*dtdHard[USB_DEVICE_CONFIG_ENDPOINTS * 2]; /*!< The transferring DTD list head for each endpoint */
usb_device_ehci_dtd_struct_t
*dtdTail[USB_DEVICE_CONFIG_ENDPOINTS * 2]; /*!< The transferring DTD list tail for each endpoint */
int8_t dtdCount; /*!< The idle DTD node count */
uint8_t endpointCount; /*!< The endpoint number of EHCI */
uint8_t isResetting; /*!< Whether a PORT reset is occurring or not */
uint8_t controllerId; /*!< Controller ID */
uint8_t speed; /*!< Current speed of EHCI */
uint8_t isSuspending; /*!< Is suspending of the PORT */
} usb_device_ehci_state_struct_t;
#if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
typedef struct _usb_device_dcd_state_struct
{
usb_device_struct_t *deviceHandle; /*!< Device handle used to identify the device object belongs to */
USBHSDCD_Type *dcdRegisterBase; /*!< The base address of the dcd module */
uint8_t controllerId; /*!< Controller ID */
} usb_device_dcd_state_struct_t;
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name USB device EHCI functions
* @{
*/
/*******************************************************************************
* API
******************************************************************************/
/*!
* @brief Initializes the USB device EHCI instance.
*
* This function initializes the USB device EHCI module specified by the controllerId.
*
* @param[in] controllerId The controller ID of the USB IP. See the enumeration type usb_controller_index_t.
* @param[in] handle Pointer of the device handle used to identify the device object is belonged to.
* @param[out] ehciHandle An out parameter used to return the pointer of the device EHCI handle to the caller.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceEhciInit(uint8_t controllerId,
usb_device_handle handle,
usb_device_controller_handle *ehciHandle);
/*!
* @brief Deinitializes the USB device EHCI instance.
*
* This function deinitializes the USB device EHCI module.
*
* @param[in] ehciHandle Pointer of the device EHCI handle.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceEhciDeinit(usb_device_controller_handle ehciHandle);
/*!
* @brief Sends data through a specified endpoint.
*
* This function sends data through a specified endpoint.
*
* @param[in] ehciHandle Pointer of the device EHCI handle.
* @param[in] endpointAddress Endpoint index.
* @param[in] buffer The memory address to hold the data need to be sent.
* @param[in] length The data length to be sent.
*
* @return A USB error code or kStatus_USB_Success.
*
* @note The return value means whether the sending request is successful or not. The transfer completion is indicated
* by the
* corresponding callback function.
* Currently, only one transfer request can be supported for a specific endpoint.
* If there is a specific requirement to support multiple transfer requests for a specific endpoint, the application
* should implement a queue in the application level.
* The subsequent transfer can begin only when the previous transfer is done (a notification is received through the
* endpoint
* callback).
*/
usb_status_t USB_DeviceEhciSend(usb_device_controller_handle ehciHandle,
uint8_t endpointAddress,
uint8_t *buffer,
uint32_t length);
/*!
* @brief Receive data through a specified endpoint.
*
* This function Receives data through a specified endpoint.
*
* @param[in] ehciHandle Pointer of the device EHCI handle.
* @param[in] endpointAddress Endpoint index.
* @param[in] buffer The memory address to save the received data.
* @param[in] length The data length want to be received.
*
* @return A USB error code or kStatus_USB_Success.
*
* @note The return value just means if the receiving request is successful or not; the transfer done is notified by the
* corresponding callback function.
* Currently, only one transfer request can be supported for one specific endpoint.
* If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
* should implement a queue in the application level.
* The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
* callback).
*/
usb_status_t USB_DeviceEhciRecv(usb_device_controller_handle ehciHandle,
uint8_t endpointAddress,
uint8_t *buffer,
uint32_t length);
/*!
* @brief Cancels the pending transfer in a specified endpoint.
*
* The function is used to cancel the pending transfer in a specified endpoint.
*
* @param[in] ehciHandle Pointer of the device EHCI handle.
* @param[in] ep Endpoint address, bit7 is the direction of endpoint, 1U - IN, 0U - OUT.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceEhciCancel(usb_device_controller_handle ehciHandle, uint8_t ep);
/*!
* @brief Controls the status of the selected item.
*
* The function is used to control the status of the selected item.
*
* @param[in] ehciHandle Pointer of the device EHCI handle.
* @param[in] type The selected item. See enumeration type usb_device_control_type_t.
* @param[in,out] param The parameter type is determined by the selected item.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceEhciControl(usb_device_controller_handle ehciHandle,
usb_device_control_type_t type,
void *param);
/*! @} */
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* __USB_DEVICE_EHCI_H__ */

View File

@ -0,0 +1,726 @@
/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _USB_HOST_H_
#define _USB_HOST_H_
#include <usb/include/usb.h>
#include <usb/include/usb_misc.h>
#include <usb/include/usb_spec.h>
/*******************************************************************************
* Definitions
******************************************************************************/
struct _usb_host_transfer; /* for cross reference */
/*!
* @addtogroup usb_host_drv
* @{
*/
/*! @brief USB host class handle type define */
typedef void *usb_host_class_handle;
/*! @brief USB host controller handle type define */
typedef void *usb_host_controller_handle;
/*! @brief USB host configuration handle type define */
typedef void *usb_host_configuration_handle;
/*! @brief USB host interface handle type define */
typedef void *usb_host_interface_handle;
/*! @brief USB host pipe handle type define */
typedef void *usb_host_pipe_handle;
/*! @brief Event codes for device attach/detach */
typedef enum _usb_host_event
{
kUSB_HostEventAttach = 1U, /*!< Device is attached */
kUSB_HostEventDetach, /*!< Device is detached */
kUSB_HostEventEnumerationDone, /*!< Device's enumeration is done and the device is supported */
kUSB_HostEventNotSupported, /*!< Device's enumeration is done and the device is not supported */
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
kUSB_HostEventNotSuspended, /*!< Suspend failed */
kUSB_HostEventSuspended, /*!< Suspend successful */
kUSB_HostEventNotResumed, /*!< Resume failed */
kUSB_HostEventDetectResume, /*!< Detect resume signal */
kUSB_HostEventResumed, /*!< Resume successful */
kUSB_HostEventL1Sleeped, /*!< L1 Sleep successful,state transition was successful (ACK) */
kUSB_HostEventL1SleepNYET, /*!< Device was unable to enter the L1 state at this time (NYET) */
kUSB_HostEventL1SleepNotSupport, /*!< Device does not support the L1 state (STALL) */
kUSB_HostEventL1SleepError, /*!< Device failed to respond or an error occurred */
kUSB_HostEventL1NotResumed, /*!< Resume failed */
kUSB_HostEventL1DetectResume, /*!< Detect resume signal */
kUSB_HostEventL1Resumed, /*!< Resume successful */
#endif
} usb_host_event_t;
/*! @brief USB host device information code */
typedef enum _usb_host_dev_info
{
kUSB_HostGetDeviceAddress = 1U, /*!< Device's address */
kUSB_HostGetDeviceHubNumber, /*!< Device's first hub address */
kUSB_HostGetDevicePortNumber, /*!< Device's first hub port number */
kUSB_HostGetDeviceSpeed, /*!< Device's speed */
kUSB_HostGetDeviceHSHubNumber, /*!< Device's first high-speed hub address */
kUSB_HostGetDeviceHSHubPort, /*!< Device's first high-speed hub number */
kUSB_HostGetDeviceLevel, /*!< Device's hub level */
kUSB_HostGetHostHandle, /*!< Device's host handle */
kUSB_HostGetDeviceControlPipe, /*!< Device's control pipe handle */
kUSB_HostGetDevicePID, /*!< Device's PID */
kUSB_HostGetDeviceVID, /*!< Device's VID */
kUSB_HostGetHubThinkTime, /*!< Device's hub total think time */
kUSB_HostGetDeviceConfigIndex, /*!< Device's running zero-based config index */
kUSB_HostGetConfigurationDes, /*!< Device's configuration descriptor pointer */
kUSB_HostGetConfigurationLength, /*!< Device's configuration descriptor pointer */
} usb_host_dev_info_t;
/*!
* @brief Host callback function typedef.
*
* This callback function is used to notify application device attach/detach event.
* This callback pointer is passed when initializing the host.
*
* @param deviceHandle The device handle, which indicates the attached device.
* @param configurationHandle The configuration handle contains the attached device's configuration information.
* @param event_code The callback event code; See the enumeration host_event_t.
*
* @return A USB error code or kStatus_USB_Success.
* @retval kStatus_USB_Success Application handles the attached device successfully.
* @retval kStatus_USB_NotSupported Application don't support the attached device.
* @retval kStatus_USB_Error Application handles the attached device falsely.
*/
typedef usb_status_t (*host_callback_t)(usb_device_handle deviceHandle,
usb_host_configuration_handle configurationHandle,
uint32_t eventCode);
/*!
* @brief Transfer callback function typedef.
*
* This callback function is used to notify the upper layer the result of the transfer.
* This callback pointer is passed when calling the send/receive APIs.
*
* @param param The parameter pointer, which is passed when calling the send/receive APIs.
* @param data The data buffer pointer.
* @param data_len The result data length.
* @param status A USB error code or kStatus_USB_Success.
*/
typedef void (*transfer_callback_t)(void *param, uint8_t *data, uint32_t dataLen, usb_status_t status);
/*!
* @brief Host stack inner transfer callback function typedef.
*
* This callback function is used to notify the upper layer the result of a transfer.
* This callback pointer is passed when initializing the structure usb_host_transfer_t.
*
* @param param The parameter pointer, which is passed when calling the send/receive APIs.
* @param transfer The transfer information; See the structure usb_host_transfer_t.
* @param status A USB error code or kStatus_USB_Success.
*/
typedef void (*host_inner_transfer_callback_t)(void *param, struct _usb_host_transfer *transfer, usb_status_t status);
/*! @brief USB host endpoint information structure */
typedef struct _usb_host_ep
{
usb_descriptor_endpoint_t *epDesc; /*!< Endpoint descriptor pointer*/
uint8_t *epExtension; /*!< Endpoint extended descriptor pointer*/
uint16_t epExtensionLength; /*!< Extended descriptor length*/
} usb_host_ep_t;
/*! @brief USB host interface information structure */
typedef struct _usb_host_interface
{
usb_host_ep_t epList[USB_HOST_CONFIG_INTERFACE_MAX_EP]; /*!< Endpoint array*/
usb_descriptor_interface_t *interfaceDesc; /*!< Interface descriptor pointer*/
uint8_t *interfaceExtension; /*!< Interface extended descriptor pointer*/
uint16_t interfaceExtensionLength; /*!< Extended descriptor length*/
uint8_t interfaceIndex; /*!< The interface index*/
uint8_t alternateSettingNumber; /*!< The interface alternate setting value*/
uint8_t epCount; /*!< Interface's endpoint number*/
} usb_host_interface_t;
/*! @brief USB host configuration information structure */
typedef struct _usb_host_configuration
{
usb_host_interface_t interfaceList[USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE]; /*!< Interface array*/
usb_descriptor_configuration_t *configurationDesc; /*!< Configuration descriptor pointer*/
uint8_t *configurationExtension; /*!< Configuration extended descriptor pointer*/
uint16_t configurationExtensionLength; /*!< Extended descriptor length*/
uint8_t interfaceCount; /*!< The configuration's interface number*/
} usb_host_configuration_t;
/*! @brief USB host pipe common structure */
typedef struct _usb_host_pipe
{
struct _usb_host_pipe *next; /*!< Link the idle pipes*/
usb_device_handle deviceHandle; /*!< This pipe's device's handle*/
uint16_t currentCount; /*!< For KHCI transfer*/
uint16_t nakCount; /*!< Maximum NAK count*/
uint16_t maxPacketSize; /*!< Maximum packet size*/
uint16_t interval; /*!< FS/LS: frame unit; HS: micro-frame unit*/
uint8_t open; /*!< 0 - closed, 1 - open*/
uint8_t nextdata01; /*!< Data toggle*/
uint8_t endpointAddress; /*!< Endpoint address*/
uint8_t direction; /*!< Pipe direction*/
uint8_t pipeType; /*!< Pipe type, for example USB_ENDPOINT_BULK*/
uint8_t numberPerUframe; /*!< Transaction number per micro-frame*/
} usb_host_pipe_t;
/*! @brief USB host transfer structure */
typedef struct _usb_host_transfer
{
struct _usb_host_transfer *next; /*!< The next transfer structure*/
uint8_t *transferBuffer; /*!< Transfer data buffer*/
uint32_t transferLength; /*!< Transfer data length*/
uint32_t transferSofar; /*!< Length transferred so far*/
host_inner_transfer_callback_t callbackFn; /*!< Transfer callback function*/
void *callbackParam; /*!< Transfer callback parameter*/
usb_host_pipe_t *transferPipe; /*!< Transfer pipe pointer*/
usb_setup_struct_t *setupPacket; /*!< Set up packet buffer*/
uint8_t direction; /*!< Transfer direction; it's values are USB_OUT or USB_IN*/
uint8_t setupStatus; /*!< Set up the transfer status*/
union
{
uint32_t unitHead; /*!< xTD head for this transfer*/
int32_t transferResult; /*!< KHCI transfer result */
} union1;
union
{
uint32_t unitTail; /*!<xTD tail for this transfer*/
uint32_t frame; /*!< KHCI transfer frame number */
} union2;
#if USB_HOST_CONFIG_KHCI
uint16_t nakTimeout; /*!< KHCI transfer NAK timeout */
uint16_t retry; /*!< KHCI transfer retry */
#endif
} usb_host_transfer_t;
/*! @brief USB host pipe information structure for opening pipe */
typedef struct _usb_host_pipe_init
{
void *devInstance; /*!< Device instance handle*/
uint16_t nakCount; /*!< Maximum NAK retry count. MUST be zero for interrupt*/
uint16_t maxPacketSize; /*!< Pipe's maximum packet size*/
uint8_t interval; /*!< Pipe's interval*/
uint8_t endpointAddress; /*!< Endpoint address*/
uint8_t direction; /*!< Endpoint direction*/
uint8_t pipeType; /*!< Endpoint type, the value is USB_ENDPOINT_INTERRUPT, USB_ENDPOINT_CONTROL,
USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK*/
uint8_t numberPerUframe; /*!< Transaction number for each micro-frame*/
} usb_host_pipe_init_t;
/*! @brief Cancel transfer parameter structure */
typedef struct _usb_host_cancel_param
{
usb_host_pipe_handle pipeHandle; /*!< Cancelling pipe handle*/
usb_host_transfer_t *transfer; /*!< Cancelling transfer*/
} usb_host_cancel_param_t;
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @name USB host APIs Part 1
* The following APIs are recommended for application use.
* @{
*/
/*!
* @brief Initializes the USB host stack.
*
* This function initializes the USB host module specified by the controllerId.
*
* @param[in] controllerId The controller ID of the USB IP. See the enumeration usb_controller_index_t.
* @param[out] hostHandle Returns the host handle.
* @param[in] callbackFn Host callback function notifies device attach/detach.
*
* @retval kStatus_USB_Success The host is initialized successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle is a NULL pointer.
* @retval kStatus_USB_ControllerNotFound Cannot find the controller according to the controller ID.
* @retval kStatus_USB_AllocFail Allocation memory fail.
* @retval kStatus_USB_Error Host mutex create fail; KHCI/EHCI mutex or KHCI/EHCI event create fail,
* or, KHCI/EHCI IP initialize fail.
*/
extern usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, host_callback_t callbackFn);
/*!
* @brief Deinitializes the USB host stack.
*
* This function deinitializes the USB host module specified by the hostHandle.
*
* @param[in] hostHandle The host handle.
*
* @retval kStatus_USB_Success The host is initialized successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle is a NULL pointer.
* @retval kStatus_USB_Error Controller deinitialization fail.
*/
extern usb_status_t USB_HostDeinit(usb_host_handle hostHandle);
/*!
* @brief Gets the device information.
*
* This function gets the device information.
*
* @param[in] deviceHandle Removing device handle.
* @param[in] infoCode See the enumeration host_dev_info_t.
* @param[out] infoValue Return the information value.
*
* @retval kStatus_USB_Success Close successfully.
* @retval kStatus_USB_InvalidParameter The deviceHandle or info_value is a NULL pointer.
* @retval kStatus_USB_Error The info_code is not the host_dev_info_t value.
*/
extern usb_status_t USB_HostHelperGetPeripheralInformation(usb_device_handle deviceHandle,
uint32_t infoCode,
uint32_t *infoValue);
/*!
* @brief Parses the alternate interface descriptor.
*
* This function parses the alternate interface descriptor and returns an interface information through the structure
* usb_host_interface_t.
*
* @param[in] interfaceHandle The whole interface handle.
* @param[in] alternateSetting Alternate setting value.
* @param[out] interface Return interface information.
*
* @retval kStatus_USB_Success Close successfully.
* @retval kStatus_USB_InvalidHandle The interfaceHandle is a NULL pointer.
* @retval kStatus_USB_InvalidParameter The alternateSetting is 0.
* @retval kStatus_USB_Error The interface descriptor is wrong.
*/
extern usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle interfaceHandle,
uint8_t alternateSetting,
usb_host_interface_t *interface);
/*!
* @brief Removes the attached device.
*
* This function removes the attached device.
* This function should not be used all the time.
*
* @param[in] hostHandle The host handle.
* @param[in] deviceHandle Removing device handle.
*
* @retval kStatus_USB_Success Remove successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle or deviceHandle is a NULL pointer.
* @retval kStatus_USB_InvalidParameter The deviceHandle instance don't belong to hostHandle instance.
*/
extern usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle);
/*!
* @brief KHCI task function.
*
* The function is used to handle the KHCI controller message.
* In the bare metal environment, this function should be called periodically in the main function.
* In the RTOS environment, this function should be used as a function entry to create a task.
*
* @param[in] hostHandle The host handle.
*/
extern void USB_HostKhciTaskFunction(void *hostHandle);
/*!
* @brief EHCI task function.
*
* The function is used to handle the EHCI controller message.
* In the bare metal environment, this function should be called periodically in the main function.
* In the RTOS environment, this function should be used as a function entry to create a task.
*
* @param[in] hostHandle The host handle.
*/
extern void USB_HostEhciTaskFunction(void *hostHandle);
/*!
* @brief OHCI task function.
*
* The function is used to handle the OHCI controller message.
* In the bare metal environment, this function should be called periodically in the main function.
* In the RTOS environment, this function should be used as a function entry to create a task.
*
* @param[in] hostHandle The host handle.
*/
extern void USB_HostOhciTaskFunction(void *hostHandle);
/*!
* @brief IP3516HS task function.
*
* The function is used to handle the IP3516HS controller message.
* In the bare metal environment, this function should be called periodically in the main function.
* In the RTOS environment, this function should be used as a function entry to create a task.
*
* @param[in] hostHandle The host handle.
*/
extern void USB_HostIp3516HsTaskFunction(void *hostHandle);
/*!
* @brief Device KHCI ISR function.
*
* The function is the KHCI interrupt service routine.
*
* @param[in] hostHandle The host handle.
*/
extern void USB_HostKhciIsrFunction(void *hostHandle);
/*!
* @brief Device EHCI ISR function.
*
* The function is the EHCI interrupt service routine.
*
* @param[in] hostHandle The host handle.
*/
extern void USB_HostEhciIsrFunction(void *hostHandle);
/*!
* @brief Device OHCI ISR function.
*
* The function is the OHCI interrupt service routine.
*
* @param[in] hostHandle The host handle.
*/
extern void USB_HostOhciIsrFunction(void *hostHandle);
/*!
* @brief Device IP3516HS ISR function.
*
* The function is the IP3516HS interrupt service routine.
*
* @param[in] hostHandle The host handle.
*/
extern void USB_HostIp3516HsIsrFunction(void *hostHandle);
/*! @}*/
/*!
* @name USB host APIs Part 2.
* The following APIs are not recommended for application use. They are mainly used in the class driver.
* @{
*/
/*!
* @brief Opens the USB host pipe.
*
* This function opens a pipe according to the pipe_init_ptr parameter.
*
* @param[in] hostHandle The host handle.
* @param[out] pipeHandle The pipe handle pointer used to return the pipe handle.
* @param[in] pipeInit Used to initialize the pipe.
*
* @retval kStatus_USB_Success The host is initialized successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle or pipe_handle_ptr is a NULL pointer.
* @retval kStatus_USB_Error There is no idle pipe.
* Or, there is no idle QH for EHCI.
* Or, bandwidth allocate fail for EHCI.
*/
extern usb_status_t USB_HostOpenPipe(usb_host_handle hostHandle,
usb_host_pipe_handle *pipeHandle,
usb_host_pipe_init_t *pipeInit);
/*!
* @brief Closes the USB host pipe.
*
* This function closes a pipe and frees the related resources.
*
* @param[in] hostHandle The host handle.
* @param[in] pipeHandle The closing pipe handle.
*
* @retval kStatus_USB_Success The host is initialized successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle or pipeHandle is a NULL pointer.
*/
extern usb_status_t USB_HostClosePipe(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle);
/*!
* @brief Sends data to a pipe.
*
* This function requests to send the transfer to the specified pipe.
*
* @param[in] hostHandle The host handle.
* @param[in] pipeHandle The sending pipe handle.
* @param[in] transfer The transfer information.
*
* @retval kStatus_USB_Success Send successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle, pipeHandle or transfer is a NULL pointer.
* @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
* @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI.
*/
extern usb_status_t USB_HostSend(usb_host_handle hostHandle,
usb_host_pipe_handle pipeHandle,
usb_host_transfer_t *transfer);
/*!
* @brief Sends a setup transfer to the pipe.
*
* This function request to send the setup transfer to the specified pipe.
*
* @param[in] hostHandle The host handle.
* @param[in] pipeHandle The sending pipe handle.
* @param[in] transfer The transfer information.
*
* @retval kStatus_USB_Success Send successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle, pipeHandle or transfer is a NULL pointer.
* @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
* @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI.
*/
extern usb_status_t USB_HostSendSetup(usb_host_handle hostHandle,
usb_host_pipe_handle pipeHandle,
usb_host_transfer_t *transfer);
/*!
* @brief Receives the data from the pipe.
*
* This function requests to receive the transfer from the specified pipe.
*
* @param[in] hostHandle The host handle.
* @param[in] pipeHandle The receiving pipe handle.
* @param[in] transfer The transfer information.
*
* @retval kStatus_USB_Success Receive successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle, pipeHandle or transfer is a NULL pointer.
* @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
* @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI.
*/
extern usb_status_t USB_HostRecv(usb_host_handle hostHandle,
usb_host_pipe_handle pipeHandle,
usb_host_transfer_t *transfer);
/*!
* @brief Cancel the pipe's transfers.
*
* This function cancels all pipe's transfers when the parameter transfer is NULL or cancels the transfers altogether.
*
* @param[in] hostHandle The host handle.
* @param[in] pipeHandle The receiving pipe handle.
* @param[in] transfer The transfer information.
*
* @retval kStatus_USB_Success Cancel successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle or pipeHandle is a NULL pointer.
*/
extern usb_status_t USB_HostCancelTransfer(usb_host_handle hostHandle,
usb_host_pipe_handle pipeHandle,
usb_host_transfer_t *transfer);
/*!
* @brief Allocates a transfer resource.
*
* This function allocates a transfer. This transfer is used to pass data information to a low level stack.
*
* @param[in] hostHandle The host handle.
* @param[out] transfer Return the transfer.
*
* @retval kStatus_USB_Success Allocate successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle or transfer is a NULL pointer.
* @retval kStatus_USB_Error There is no idle transfer.
*/
extern usb_status_t USB_HostMallocTransfer(usb_host_handle hostHandle, usb_host_transfer_t **transfer);
/*!
* @brief Frees a transfer resource.
*
* This function frees a transfer. This transfer is used to pass data information to a low level stack.
*
* @param[in] hostHandle The host handle.
* @param[in] transfer Release the transfer.
*
* @retval kStatus_USB_Success Free successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle or transfer is a NULL pointer.
*/
extern usb_status_t USB_HostFreeTransfer(usb_host_handle hostHandle, usb_host_transfer_t *transfer);
/*!
* @brief Requests the USB standard request.
*
* This function sends the USB standard request packet.
*
* @param[in] deviceHandle The device handle for control transfer.
* @param[in] usbRequest A USB standard request code. Se the usb_spec.h.
* @param[in] transfer The used transfer.
* @param[in] param The parameter structure is different for different request, see
* usb_host_framework.h.
*
* @retval kStatus_USB_Success Send successfully.
* @retval kStatus_USB_InvalidHandle The deviceHandle is a NULL pointer.
* @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
* @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI,
* Or, the request is not standard request.
*/
extern usb_status_t USB_HostRequestControl(usb_device_handle deviceHandle,
uint8_t usbRequest,
usb_host_transfer_t *transfer,
void *param);
/*!
* @brief Opens the interface.
*
* This function opens the interface. It is used to notify the host driver the interface is used by APP or class driver.
*
* @param[in] deviceHandle Removing device handle.
* @param[in] interfaceHandle Opening interface handle.
*
* @retval kStatus_USB_Success Open successfully.
* @retval kStatus_USB_InvalidHandle The deviceHandle or interfaceHandle is a NULL pointer.
*/
extern usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle,
usb_host_interface_handle interfaceHandle);
/*!
* @brief Closes an interface.
*
* This function opens an interface. It is used to notify the host driver the interface is not used by APP or class
* driver.
*
* @param[in] deviceHandle Removing device handle.
* @param[in] interfaceHandle Opening interface handle.
*
* @retval kStatus_USB_Success Close successfully.
* @retval kStatus_USB_InvalidHandle The deviceHandle is a NULL pointer.
*/
extern usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle,
usb_host_interface_handle interfaceHandle);
/*!
* @brief Gets a host stack version function.
*
* The function is used to get the host stack version.
*
* @param[out] version The version structure pointer to keep the host stack version.
*
*/
extern void USB_HostGetVersion(uint32_t *version);
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
/*!
* @brief Send a bus or device suspend request.
*
* This function is used to send a bus or device suspend request.
*
* @param[in] hostHandle The host handle.
* @param[in] deviceHandle The device handle.
*
* @retval kStatus_USB_Success Request successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_Error There is no idle transfer.
* Or, the deviceHandle is invalid.
* Or, the request is invalid.
*/
extern usb_status_t USB_HostSuspendDeviceResquest(usb_host_handle hostHandle, usb_device_handle deviceHandle);
/*!
* @brief Send a bus or device resume request.
*
* This function is used to send a bus or device resume request.
*
* @param[in] hostHandle The host handle.
* @param[in] deviceHandle The device handle.
*
* @retval kStatus_USB_Success Request successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_Error There is no idle transfer.
* Or, the deviceHandle is invalid.
* Or, the request is invalid.
*/
extern usb_status_t USB_HostResumeDeviceResquest(usb_host_handle hostHandle, usb_device_handle deviceHandle);
#if ((defined(USB_HOST_CONFIG_LPM_L1)) && (USB_HOST_CONFIG_LPM_L1 > 0U))
/*!
* @brief Send a bus or device suspend request.
*
* This function is used to send a bus or device suspend request.
*
* @param[in] hostHandle The host handle.
* @param[in] deviceHandle The device handle.
*@param[in] sleeptype Bus suspend or single device suspend.
*
* @retval kStatus_USB_Success Request successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_Error There is no idle transfer.
* Or, the deviceHandle is invalid.
* Or, the request is invalid.
*/
extern usb_status_t USB_HostL1SleepDeviceResquest(usb_host_handle hostHandle,
usb_device_handle deviceHandle,
uint8_t sleeptype);
/*!
* @brief Send a bus or device resume request.
*
* This function is used to send a bus or device resume request.
*
* @param[in] hostHandle The host handle.
* @param[in] deviceHandle The device handle.
* *@param[in] sleeptype Bus suspend or single device suspend.
*
* @retval kStatus_USB_Success Request successfully.
* @retval kStatus_USB_InvalidHandle The hostHandle is a NULL pointer. Or the controller handle is invalid.
* @retval kStatus_USB_Error There is no idle transfer.
* Or, the deviceHandle is invalid.
* Or, the request is invalid.
*/
extern usb_status_t USB_HostL1ResumeDeviceResquest(usb_host_handle hostHandle,
usb_device_handle deviceHandle,
uint8_t sleepType);
/*!
* @brief Update the lpm param.
*
* The function is used to configuure the lpm token.
*
* @param[in] hostHandle The host handle.
* @param[in] lpmParam HIRD vaule and whether enable remotewakeup.
*
*/
extern usb_status_t USB_HostL1SleepDeviceResquestConfig(usb_host_handle hostHandle, uint8_t *lpmParam);
#endif
/*!
* @brief Update the hardware tick.
*
* The function is used to update the hardware tick.
*
* @param[in] hostHandle The host handle.
* @param[in] tick Current hardware tick(uint is ms).
*
*/
extern usb_status_t USB_HostUpdateHwTick(usb_host_handle hostHandle, uint64_t tick);
#endif
/*! @}*/
#ifdef __cplusplus
}
#endif
/*! @}*/
#endif /* _USB_HOST_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,178 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _USB_HOST_DEV_MNG_H_
#define _USB_HOST_DEV_MNG_H_
#include "usb_host.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*!
* @addtogroup usb_host_drv
* @{
*/
/*! @brief States of device instances enumeration */
typedef enum _usb_host_device_enumeration_status
{
kStatus_DEV_Notinit = 0, /*!< Device is invalid */
kStatus_DEV_Initial, /*!< Device has been processed by host driver */
kStatus_DEV_GetDes8, /*!< Enumeration process: get 8 bytes' device descriptor */
kStatus_DEV_SetAddress, /*!< Enumeration process: set device address */
kStatus_DEV_GetDes, /*!< Enumeration process: get device descriptor */
kStatus_DEV_GetCfg9, /*!< Enumeration process: get 9 bytes' configuration descriptor */
kStatus_DEV_GetCfg, /*!< Enumeration process: get configuration descriptor */
kStatus_DEV_SetCfg, /*!< Enumeration process: set configuration */
kStatus_DEV_EnumDone, /*!< Enumeration is done */
kStatus_DEV_AppUsed, /*!< This device has been used by application */
} usb_host_device_enumeration_status_t;
/*! @brief States of device's interface */
typedef enum _usb_host_interface_state
{
kStatus_interface_Attached = 1, /*!< Interface's default status */
kStatus_interface_Opened, /*!< Interface is used by application */
kStatus_interface_Detached, /*!< Interface is not used by application */
} usb_host_interface_state_t;
/*! @brief States of device */
typedef enum _usb_host_device_state
{
kStatus_device_Detached = 0, /*!< Device is used by application */
kStatus_device_Attached, /*!< Device's default status */
} usb_host_device_state_t;
/*! @brief Device instance */
typedef struct _usb_host_device_instance
{
struct _usb_host_device_instance *next; /*!< Next device, or NULL */
usb_host_handle hostHandle; /*!< Host handle */
usb_host_configuration_t configuration; /*!< Parsed configuration information for the device */
usb_descriptor_device_t *deviceDescriptor; /*!< Standard device descriptor */
usb_host_pipe_handle controlPipe; /*!< Device's control pipe */
uint8_t *configurationDesc; /*!< Configuration descriptor pointer */
uint16_t configurationLen; /*!< Configuration descriptor length */
uint16_t configurationValue; /*!< Configuration index */
uint8_t interfaceStatus[USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE]; /*!< Interfaces' status, please reference to
#usb_host_interface_state_t */
uint8_t *enumBuffer; /*!< Buffer for enumeration */
uint8_t state; /*!< Device state for enumeration */
uint8_t enumRetries; /*!< Re-enumeration when error in control transfer */
uint8_t stallRetries; /*!< Re-transfer when stall */
uint8_t speed; /*!< Device speed */
uint8_t allocatedAddress; /*!< Temporary address for the device. When set address request succeeds, setAddress is
a value, 1 - 127 */
uint8_t setAddress; /*!< The address has been set to the device successfully, 1 - 127 */
uint8_t deviceAttachState; /*!< See the usb_host_device_state_t */
#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
/* hub related */
uint8_t hubNumber; /*!< Device's first connected hub address (root hub = 0) */
uint8_t portNumber; /*!< Device's first connected hub's port no (1 - 8) */
uint8_t hsHubNumber; /*!< Device's first connected high-speed hub's address (1 - 8) */
uint8_t hsHubPort; /*!< Device's first connected high-speed hub's port no (1 - 8) */
uint8_t level; /*!< Device's level (root device = 0) */
#endif
} usb_host_device_instance_t;
typedef struct _usb_host_enum_process_entry
{
uint8_t successState; /*!< When the last step is successful, the next state value */
uint8_t retryState; /*!< When the last step need retry, the next state value */
usb_status_t (*process)(usb_host_device_instance_t *deviceInstance); /*!< When the last step transfer is done, the
function is used to process the transfer
data */
} usb_host_enum_process_entry_t;
/*******************************************************************************
* API
******************************************************************************/
/*!
* @brief Calls this function when device attach.
*
* @param hostHandle Host instance handle.
* @param speed Device speed.
* @param hubNumber Device hub no. root device's hub no. is 0.
* @param portNumber Device port no. root device's port no. is 0.
* @param level Device level. root device's level is 1.
* @param deviceHandle Return device handle.
*
* @return kStatus_USB_Success or error codes.
*/
extern usb_status_t USB_HostAttachDevice(usb_host_handle hostHandle,
uint8_t speed,
uint8_t hubNumber,
uint8_t portNumber,
uint8_t level,
usb_device_handle *deviceHandle);
/*!
* @brief Call this function when device detaches.
*
* @param hostHandle Host instance handle.
* @param hubNumber Device hub no. root device's hub no. is 0.
* @param portNumber Device port no. root device's port no. is 0.
*
* @return kStatus_USB_Success or error codes.
*/
extern usb_status_t USB_HostDetachDevice(usb_host_handle hostHandle, uint8_t hubNumber, uint8_t portNumber);
/*!
* @brief Call this function when device detaches.
*
* @param hostHandle Host instance handle.
* @param deviceHandle Device handle.
*
* @return kStatus_USB_Success or error codes.
*/
extern usb_status_t USB_HostDetachDeviceInternal(usb_host_handle hostHandle, usb_device_handle deviceHandle);
/*!
* @brief Gets the device attach/detach state.
*
* @param deviceHandle Device handle.
*
* @return 0x01 - attached; 0x00 - detached.
*/
extern uint8_t USB_HostGetDeviceAttachState(usb_device_handle deviceHandle);
/*!
* @brief Determine whether the device is attached.
*
* @param hostHandle Host instance pointer.
* @param deviceHandle Device handle.
*
* @return kStatus_USB_Success or error codes.
*/
extern usb_status_t USB_HostValidateDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle);
/*! @}*/
#endif /* _USB_HOST_DEV_MNG_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,499 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _USB_HOST_CONTROLLER_EHCI_H_
#define _USB_HOST_CONTROLLER_EHCI_H_
/*******************************************************************************
* KHCI private public structures, enumerations, macros, functions
******************************************************************************/
/*******************************************************************************
* Definitions
******************************************************************************/
/* EHCI host macros */
#define EHCI_HOST_T_INVALID_VALUE (1U)
#define EHCI_HOST_POINTER_TYPE_ITD (0x00U)
#define EHCI_HOST_POINTER_TYPE_QH (0x00000002U)
#define EHCI_HOST_POINTER_TYPE_SITD (0x00000004U)
#define EHCI_HOST_POINTER_TYPE_FSTN (0x00000006U)
#define EHCI_HOST_POINTER_TYPE_MASK (0x00000006U)
#define EHCI_HOST_POINTER_ADDRESS_MASK (0xFFFFFFE0U)
#define EHCI_HOST_PID_OUT (0U)
#define EHCI_HOST_PID_IN (1U)
#define EHCI_HOST_PID_SETUP (2U)
#define EHCI_HOST_QH_RL_SHIFT (28U)
#define EHCI_HOST_QH_RL_MASK (0xF0000000U)
#define EHCI_HOST_QH_C_SHIFT (27U)
#define EHCI_HOST_QH_MAX_PACKET_LENGTH_SHIFT (16U)
#define EHCI_HOST_QH_MAX_PACKET_LENGTH_MASK (0x07FF0000U)
#define EHCI_HOST_QH_H_SHIFT (15U)
#define EHCI_HOST_QH_DTC_SHIFT (14U)
#define EHCI_HOST_QH_EPS_SHIFT (12U)
#define EHCI_HOST_QH_ENDPT_SHIFT (8U)
#define EHCI_HOST_QH_I_SHIFT (7U)
#define EHCI_HOST_QH_DEVICE_ADDRESS_SHIFT (0U)
#define EHCI_HOST_QH_MULT_SHIFT (30U)
#define EHCI_HOST_QH_PORT_NUMBER_SHIFT (23U)
#define EHCI_HOST_QH_HUB_ADDR_SHIFT (16U)
#define EHCI_HOST_QH_UFRAME_CMASK_SHIFT (8U)
#define EHCI_HOST_QH_UFRAME_SMASK_SHIFT (0U)
#define EHCI_HOST_QH_STATUS_ERROR_MASK (0x0000007EU)
#define EHCI_HOST_QH_STATUS_NOSTALL_ERROR_MASK (0x0000003EU)
#define EHCI_HOST_QTD_DT_SHIFT (31U)
#define EHCI_HOST_QTD_DT_MASK (0x80000000U)
#define EHCI_HOST_QTD_TOTAL_BYTES_SHIFT (16U)
#define EHCI_HOST_QTD_TOTAL_BYTES_MASK (0x7FFF0000U)
#define EHCI_HOST_QTD_IOC_MASK (0x00008000U)
#define EHCI_HOST_QTD_C_PAGE_SHIFT (12U)
#define EHCI_HOST_QTD_CERR_SHIFT (10U)
#define EHCI_HOST_QTD_CERR_MAX_VALUE (0x00000003U)
#define EHCI_HOST_QTD_PID_CODE_SHIFT (8U)
#define EHCI_HOST_QTD_STATUS_SHIFT (0U)
#define EHCI_HOST_QTD_CURRENT_OFFSET_MASK (0x00000FFFU)
#define EHCI_HOST_QTD_BUFFER_POINTER_SHIFT (12U)
#define EHCI_HOST_QTD_STATUS_ACTIVE_MASK (0x00000080U)
#define EHCI_HOST_QTD_STATUS_MASK (0x000000ffU)
#define EHCI_HOST_QTD_STATUS_ERROR_MASK (0x0000007EU)
#define EHCI_HOST_QTD_STATUS_STALL_ERROR_MASK (0x00000040U)
#define EHCI_HOST_ITD_STATUS_ACTIVE_MASK (0x80000000U)
#define EHCI_HOST_ITD_TRANSACTION_LEN_SHIFT (16U)
#define EHCI_HOST_ITD_TRANSACTION_LEN_MASK (0x0FFF0000U)
#define EHCI_HOST_ITD_IOC_SHIFT (15U)
#define EHCI_HOST_ITD_PG_SHIFT (12U)
#define EHCI_HOST_ITD_TRANSACTION_OFFSET_SHIFT (0U)
#define EHCI_HOST_ITD_TRANSACTION_OFFSET_MASK (0x00000FFFU)
#define EHCI_HOST_ITD_BUFFER_POINTER_SHIFT (12U)
#define EHCI_HOST_ITD_ENDPT_SHIFT (8U)
#define EHCI_HOST_ITD_DEVICE_ADDRESS_SHIFT (0U)
#define EHCI_HOST_ITD_MAX_PACKET_SIZE_SHIFT (0U)
#define EHCI_HOST_ITD_MULT_SHIFT (0U)
#define EHCI_HOST_ITD_DIRECTION_SHIFT (11U)
#define EHCI_HOST_SITD_STATUS_ACTIVE_MASK (0x00000080U)
#define EHCI_HOST_SITD_DIRECTION_SHIFT (31U)
#define EHCI_HOST_SITD_PORT_NUMBER_SHIFT (24U)
#define EHCI_HOST_SITD_HUB_ADDR_SHIFT (16U)
#define EHCI_HOST_SITD_ENDPT_SHIFT (8U)
#define EHCI_HOST_SITD_DEVICE_ADDRESS_SHIFT (0U)
#define EHCI_HOST_SITD_CMASK_SHIFT (8U)
#define EHCI_HOST_SITD_SMASK_SHIFT (0U)
#define EHCI_HOST_SITD_TOTAL_BYTES_SHIFT (16U)
#define EHCI_HOST_SITD_TOTAL_BYTES_MASK (0x03FF0000U)
#define EHCI_HOST_SITD_TP_SHIFT (3U)
#define EHCI_HOST_SITD_TCOUNT_SHIFT (0U)
#define EHCI_HOST_SITD_IOC_SHIFT (31U)
/* register related MACROs */
#define EHCI_PORTSC1_W1_BITS (0x0000002AU)
#define EHCI_MAX_UFRAME_VALUE (0x00003FFFU)
/* task event */
#define EHCI_TASK_EVENT_DEVICE_ATTACH (0x01U)
#define EHCI_TASK_EVENT_TRANSACTION_DONE (0x02U)
#define EHCI_TASK_EVENT_DEVICE_DETACH (0x04U)
#define EHCI_TASK_EVENT_PORT_CHANGE (0x08U)
#define EHCI_TASK_EVENT_TIMER0 (0x10U)
#define EHCI_TASK_EVENT_TIMER1 (0x20U)
#define USB_HostEhciLock() USB_OsaMutexLock(ehciInstance->ehciMutex)
#define USB_HostEhciUnlock() USB_OsaMutexUnlock(ehciInstance->ehciMutex)
/*******************************************************************************
* KHCI driver public structures, enumerations, macros, functions
******************************************************************************/
/*!
* @addtogroup usb_host_controller_ehci
* @{
*/
/*! @brief The maximum supported ISO pipe number */
#define USB_HOST_EHCI_ISO_NUMBER USB_HOST_CONFIG_EHCI_MAX_ITD
/*! @brief Check the port connect state delay if the state is unstable */
#define USB_HOST_EHCI_PORT_CONNECT_DEBOUNCE_DELAY (101U)
/*! @brief Delay for port reset */
#define USB_HOST_EHCI_PORT_RESET_DELAY (11U)
/*! @brief The SITD inserts a frame interval for putting more SITD continuously.
* There is an interval when an application sends two FS/LS ISO transfers.
* When the interval is less than the macro, the two transfers are continuous in the frame list. Otherwise, the two
* transfers
* are not continuous.
* For example:
* - Use case 1: when inserting the SITD first, the inserted frame = the current frame value + this MACRO value.
* - Use case 2: when inserting SITD is not first, choose between the last inserted frame value and the
* current frame value according to the following criteria:
* If the interval is less than the MACRO value, the new SITD is continuous with the last SITD.
* If not, the new SITD inserting frame = the current frame value + this MACRO value.
*/
#define USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER (2U)
/*! @brief The ITD inserts a micro-frame interval for putting more ITD continuously.
* There is an interval when an application sends two HS ISO transfers.
* When the interval is less than the macro, the two transfers are continuous in the frame list. Otherwise, the two
* transfers
* are not continuous.
* For example:
* - Use case 1: when inserting ITD first, the inserted micro-frame = the current micro-frame value + this MACRO value.
* - Use case 2: when inserting ITD is not first, choose between the last inserted micro-frame value and the
* current micro-frame value according to the following criteria:
* If the interval is less than this MACRO value, the new ITD is continuous with the last ITD.
* If not, the new ITD inserting micro-frame = the current micro-frame value + this MACRO value.
*/
#define USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER (16U)
/*! @brief Control or bulk transaction timeout value (unit: 100 ms) */
#define USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE (20U)
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
typedef enum _bus_ehci_suspend_request_state
{
kBus_EhciIdle = 0U,
kBus_EhciStartSuspend,
kBus_EhciSuspended,
kBus_EhciStartResume,
} bus_ehci_suspend_request_state_t;
#endif
/*! @brief EHCI state for device attachment/detachment. */
typedef enum _host_ehci_device_state_
{
kEHCIDevicePhyAttached = 1, /*!< Device is physically attached */
kEHCIDeviceAttached, /*!< Device is attached and initialized */
kEHCIDeviceDetached, /*!< Device is detached and de-initialized */
} host_ehci_device_state_t;
/*! @brief EHCI pipe structure */
typedef struct _usb_host_ehci_pipe
{
usb_host_pipe_t pipeCommon; /*!< Common pipe information */
void *ehciQh; /*!< Control/bulk/interrupt: QH; ISO: usb_host_ehci_iso_t*/
/* bandwidth */
uint16_t uframeInterval; /*!< Micro-frame interval value */
uint16_t startFrame; /*!<
Bandwidth start frame: its value is from 0 to frame_list.
*/
uint16_t dataTime; /*!<
Bandwidth time value:
- When the host works as HS: it's the data bandwidth value.
- When the host works as FS/LS:
- For FS/LS device, it's the data bandwidth value when transferring the data by FS/LS.
- For HS device, it's the data bandwidth value when transferring the data by HS.
*/
uint16_t startSplitTime; /*!<
Start splitting the bandwidth time value:
- When the host works as HS, it is the start split bandwidth value.
*/
uint16_t completeSplitTime; /*!<
Complete splitting the bandwidth time value:
- When host works as HS, it is the complete split bandwidth value.
*/
uint8_t startUframe; /*!<
Bandwidth start micro-frame: its value is from 0 to 7.
*/
uint8_t uframeSmask; /*!<
Start micro-frame.
- When host works as an HS:
- For FS/LS device, it's the interrupt or ISO transfer start-split mask.
- For HS device, it's the interrupt transfer start micro-frame mask.
- When host works as FS/LS, it's the interrupt and ISO start micro-frame mask
*/
uint8_t uframeCmask; /*!<
Complete micro-frame
- When host works as HS:
- For FS/LS device, it's the interrupt or ISO transfer complete-split mask.
*/
} usb_host_ehci_pipe_t;
/*! @brief EHCI QH structure. See the USB EHCI specification */
typedef struct _usb_host_ehci_qh
{
uint32_t horizontalLinkPointer; /*!< QH specification filed, queue head a horizontal link pointer */
uint32_t
staticEndpointStates[2]; /*!< QH specification filed, static endpoint state and configuration information */
uint32_t currentQtdPointer; /*!< QH specification filed, current qTD pointer */
uint32_t nextQtdPointer; /*!< QH specification filed, next qTD pointer */
uint32_t alternateNextQtdPointer; /*!< QH specification filed, alternate next qTD pointer */
uint32_t
transferOverlayResults[6]; /*!< QH specification filed, transfer overlay configuration and transfer results */
/* reserved space */
usb_host_ehci_pipe_t *ehciPipePointer; /*!< EHCI pipe pointer */
usb_host_transfer_t *ehciTransferHead; /*!< Transfer list head on this QH */
usb_host_transfer_t *ehciTransferTail; /*!< Transfer list tail on this QH */
uint16_t timeOutValue; /*!< Its maximum value is USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE. When the value is
zero, the transfer times out. */
uint16_t timeOutLabel; /*!< It's used to judge the transfer timeout. The EHCI driver maintain the value */
} usb_host_ehci_qh_t;
/*! @brief EHCI QTD structure. See the USB EHCI specification. */
typedef struct _usb_host_ehci_qtd
{
uint32_t nextQtdPointer; /*!< QTD specification filed, the next QTD pointer */
uint32_t alternateNextQtdPointer; /*!< QTD specification filed, alternate next QTD pointer */
uint32_t transferResults[2]; /*!< QTD specification filed, transfer results fields */
uint32_t bufferPointers[4]; /*!< QTD specification filed, transfer buffer fields */
} usb_host_ehci_qtd_t;
/*! @brief EHCI ITD structure. See the USB EHCI specification. */
typedef struct _usb_host_ehci_itd
{
uint32_t nextLinkPointer; /*!< ITD specification filed, the next linker pointer */
uint32_t transactions[8]; /*!< ITD specification filed, transactions information */
uint32_t bufferPointers[7]; /*!< ITD specification filed, transfer buffer fields */
/* add space */
struct _usb_host_ehci_itd *nextItdPointer; /*!< Next ITD pointer */
uint32_t frameEntryIndex; /*!< The ITD inserted frame value */
uint32_t reserved[6]; /*!< Reserved fields for 32 bytes align */
} usb_host_ehci_itd_t;
/*! @brief EHCI SITD structure. See the USB EHCI specification. */
typedef struct _usb_host_ehci_sitd
{
uint32_t nextLinkPointer; /*!< SITD specification filed, the next linker pointer */
uint32_t endpointStates[2]; /*!< SITD specification filed, endpoint configuration information */
uint32_t transferResults[3]; /*!< SITD specification filed, transfer result fields */
uint32_t backPointer; /*!< SITD specification filed, back pointer */
/* reserved space */
uint16_t frameEntryIndex; /*!< The SITD inserted frame value */
uint8_t nextSitdIndex; /*!< The next SITD index; Get the next SITD pointer through adding base address with the
index. 0xFF means invalid. */
uint8_t reserved; /*!< Reserved fields for 32 bytes align */
} usb_host_ehci_sitd_t;
/*! @brief EHCI ISO structure; An ISO pipe has an instance of this structure to keep the ISO pipe-specific information.
*/
typedef struct _usb_host_ehci_iso
{
struct _usb_host_ehci_iso *next; /*!< Next instance pointer */
usb_host_pipe_t *ehciPipePointer; /*!< This ISO's EHCI pipe pointer */
usb_host_transfer_t *ehciTransferHead; /*!< Transfer list head on this ISO pipe */
usb_host_transfer_t *ehciTransferTail; /*!< Transfer list head on this ISO pipe */
uint16_t lastLinkFrame; /*!< It means that the inserted frame for ISO ITD/SITD. 0xFFFF is invalid. For ITD, it is a
micro-frame value. For SITD, it is a frame value */
} usb_host_ehci_iso_t;
/*! @brief EHCI instance structure */
typedef struct _usb_host_ehci_instance
{
usb_host_handle hostHandle; /*!< Related host handle*/
uint32_t *ehciUnitBase; /*!< Keep the QH/QTD/ITD/SITD buffer pointer for release*/
uint8_t *ehciFrameList; /*!< The frame list of the current ehci instance*/
usb_host_ehci_qh_t *ehciQhList; /*!< Idle QH list pointer */
usb_host_ehci_qtd_t *ehciQtdHead; /*!< Idle QTD list pointer head */
usb_host_ehci_qtd_t *ehciQtdTail; /*!< Idle QTD list pointer tail (recently used qTD will be used)*/
usb_host_ehci_itd_t *ehciItdList; /*!< Idle ITD list pointer*/
usb_host_ehci_sitd_t *ehciSitdIndexBase; /*!< SITD buffer's start pointer*/
usb_host_ehci_sitd_t *ehciSitdList; /*!< Idle SITD list pointer*/
usb_host_ehci_iso_t *ehciIsoList; /*!< Idle ISO list pointer*/
USBHS_Type *ehciIpBase; /*!< EHCI IP base address*/
usb_host_ehci_qh_t *shedFirstQh; /*!< First async QH*/
usb_host_ehci_pipe_t *ehciPipeIndexBase; /*!< Pipe buffer's start pointer*/
usb_host_ehci_pipe_t *ehciPipeList; /*!< Idle pipe list pointer*/
usb_host_ehci_pipe_t *ehciRunningPipeList; /*!< Running pipe list pointer*/
usb_osa_mutex_handle ehciMutex; /*!< EHCI mutex*/
usb_osa_event_handle taskEventHandle; /*!< EHCI task event*/
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
uint64_t matchTick;
USBPHY_Type *registerPhyBase; /*!< The base address of the PHY register */
#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
USBNC_Type *registerNcBase; /*!< The base address of the USBNC register */
#endif
#endif
uint8_t controllerId; /*!< EHCI controller ID*/
uint8_t deviceAttached; /*!< Device attach/detach state, see #host_ehci_device_state_t */
uint8_t firstDeviceSpeed; /*!< The first device's speed, the controller's work speed*/
uint8_t ehciItdNumber; /*!< Idle ITD number*/
uint8_t ehciSitdNumber; /*!< Idle SITD number*/
uint8_t ehciQtdNumber; /*!< Idle QTD number*/
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
bus_ehci_suspend_request_state_t busSuspendStatus; /*!< Bus Suspend Status*/
#endif
} usb_host_ehci_instance_t;
/*! @brief EHCI data structure */
typedef struct _usb_host_ehci_data
{
#if ((defined(USB_HOST_CONFIG_EHCI_MAX_QH)) && (USB_HOST_CONFIG_EHCI_MAX_QH > 0U))
usb_host_ehci_qh_t ehciQh[USB_HOST_CONFIG_EHCI_MAX_QH]; /*!< Idle QH list array*/
#endif
#if ((defined(USB_HOST_CONFIG_EHCI_MAX_QTD)) && (USB_HOST_CONFIG_EHCI_MAX_QTD > 0U))
usb_host_ehci_qtd_t ehciQtd[USB_HOST_CONFIG_EHCI_MAX_QTD]; /*!< Idle QTD list array*/
#endif
#if ((defined(USB_HOST_CONFIG_EHCI_MAX_ITD)) && (USB_HOST_CONFIG_EHCI_MAX_ITD > 0U))
usb_host_ehci_itd_t ehciItd[USB_HOST_CONFIG_EHCI_MAX_ITD]; /*!< Idle ITD list array*/
#endif
#if ((defined(USB_HOST_CONFIG_EHCI_MAX_SITD)) && (USB_HOST_CONFIG_EHCI_MAX_SITD > 0U))
usb_host_ehci_sitd_t ehciSitd[USB_HOST_CONFIG_EHCI_MAX_SITD]; /*!< Idle SITD list array*/
#endif
#if ((defined(USB_HOST_EHCI_ISO_NUMBER)) && (USB_HOST_EHCI_ISO_NUMBER > 0U))
usb_host_ehci_iso_t ehciIso[USB_HOST_EHCI_ISO_NUMBER]; /*!< Idle ISO list array*/
#endif
#if ((defined(USB_HOST_CONFIG_MAX_PIPES)) && (USB_HOST_CONFIG_MAX_PIPES > 0U))
usb_host_ehci_pipe_t ehciPipe[USB_HOST_CONFIG_MAX_PIPES]; /*!< Idle pipe list array*/
#endif
} usb_host_ehci_data_t;
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @name USB host EHCI APIs
* @{
*/
/*!
* @brief Creates the USB host EHCI instance.
*
* This function initializes the USB host EHCI controller driver.
*
* @param[in] controllerId The controller ID of the USB IP. Please refer to the enumeration usb_controller_index_t.
* @param[in] upperLayerHandle The host level handle.
* @param[out] controllerHandle return the controller instance handle.
*
* @retval kStatus_USB_Success The host is initialized successfully.
* @retval kStatus_USB_AllocFail Allocating memory failed.
* @retval kStatus_USB_Error Host mutex create fail, KHCI/EHCI mutex or KHCI/EHCI event create fail.
* Or, KHCI/EHCI IP initialize fail.
*/
extern usb_status_t USB_HostEhciCreate(uint8_t controllerId,
usb_host_handle upperLayerHandle,
usb_host_controller_handle *controllerHandle);
/*!
* @brief Destroys the USB host EHCI instance.
*
* This function de-initializes The USB host EHCI controller driver.
*
* @param[in] controllerHandle The controller handle.
*
* @retval kStatus_USB_Success The host is initialized successfully.
*/
extern usb_status_t USB_HostEhciDestory(usb_host_controller_handle controllerHandle);
/*!
* @brief Opens the USB host pipe.
*
* This function opens a pipe according to the pipe_init_ptr parameter.
*
* @param[in] controllerHandle The controller handle.
* @param[out] pipeHandle The pipe handle pointer, it is used to return the pipe handle.
* @param[in] pipeInit It is used to initialize the pipe.
*
* @retval kStatus_USB_Success The host is initialized successfully.
* @retval kStatus_USB_Error There is no idle pipe.
* Or, there is no idle QH for EHCI.
* Or, bandwidth allocate fail for EHCI.
*/
extern usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle,
usb_host_pipe_handle *pipeHandle,
usb_host_pipe_init_t *pipeInit);
/*!
* @brief Closes the USB host pipe.
*
* This function closes a pipe and releases related resources.
*
* @param[in] controllerHandle The controller handle.
* @param[in] pipeHandle The closing pipe handle.
*
* @retval kStatus_USB_Success The host is initialized successfully.
*/
extern usb_status_t USB_HostEhciClosePipe(usb_host_controller_handle controllerHandle, usb_host_pipe_handle pipeHandle);
/*!
* @brief Sends data to the pipe.
*
* This function requests to send the transfer to the specified pipe.
*
* @param[in] controllerHandle The controller handle.
* @param[in] pipeHandle The sending pipe handle.
* @param[in] transfer The transfer information.
*
* @retval kStatus_USB_Success Sent successfully.
* @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
* @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI.
*/
extern usb_status_t USB_HostEhciWritePipe(usb_host_controller_handle controllerHandle,
usb_host_pipe_handle pipeHandle,
usb_host_transfer_t *transfer);
/*!
* @brief Receives data from the pipe.
*
* This function requests to receive the transfer from the specified pipe.
*
* @param[in] controllerHandle The controller handle.
* @param[in] pipeHandle The receiving pipe handle.
* @param[in] transfer The transfer information.
* @retval kStatus_USB_Success Send successfully.
* @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
* @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI.
*/
extern usb_status_t USB_HostEhciReadpipe(usb_host_controller_handle controllerHandle,
usb_host_pipe_handle pipeHandle,
usb_host_transfer_t *transfer);
/*!
* @brief Controls the EHCI.
*
* This function controls the EHCI.
*
* @param[in] controllerHandle The controller handle.
* @param[in] ioctlEvent See enumeration host_bus_control_t.
* @param[in] ioctlParam The control parameter.
*
* @retval kStatus_USB_Success Cancel successfully.
* @retval kStatus_USB_InvalidHandle The controllerHandle is a NULL pointer.
*/
extern usb_status_t USB_HostEhciIoctl(usb_host_controller_handle controllerHandle,
uint32_t ioctlEvent,
void *ioctlParam);
/*! @}*/
#ifdef __cplusplus
}
#endif
/*! @}*/
#endif /* _USB_HOST_CONTROLLER_EHCI_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _USB_HOST_HCI_H_
#define _USB_HOST_HCI_H_
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief USB host lock */
#define USB_HostLock() USB_OsaMutexLock(hostInstance->hostMutex)
/*! @brief USB host unlock */
#define USB_HostUnlock() USB_OsaMutexUnlock(hostInstance->hostMutex)
/*!
* @addtogroup usb_host_controller_driver
* @{
*/
/*! @brief USB host controller control code */
typedef enum _usb_host_controller_control
{
kUSB_HostCancelTransfer = 1U, /*!< Cancel transfer code */
kUSB_HostBusControl, /*!< Bus control code */
kUSB_HostGetFrameNumber, /*!< Get frame number code */
kUSB_HostUpdateControlEndpointAddress, /*!< Update control endpoint address */
kUSB_HostUpdateControlPacketSize, /*!< Update control endpoint maximum packet size */
kUSB_HostPortAttachDisable, /*!< Disable the port attach event */
kUSB_HostPortAttachEnable, /*!< Enable the port attach event */
kUSB_HostL1Config, /*!< L1 suspend Bus control code */
} usb_host_controller_control_t;
/*! @brief USB host controller bus control code */
typedef enum _usb_host_bus_control
{
kUSB_HostBusReset = 1U, /*!< Reset bus */
kUSB_HostBusRestart, /*!< Restart bus */
kUSB_HostBusEnableAttach, /*!< Enable attach */
kUSB_HostBusDisableAttach, /*!< Disable attach */
kUSB_HostBusSuspend, /*!< Suspend BUS */
kUSB_HostBusResume, /*!< Resume BUS */
kUSB_HostBusL1SuspendInit, /*!< L1 Suspend BUS */
kUSB_HostBusL1Sleep, /*!< L1 Suspend BUS */
kUSB_HostBusL1Resume, /*!< L1 Resume BUS */
} usb_host_bus_control_t;
/*! @brief USB host controller interface structure */
typedef struct _usb_host_controller_interface
{
usb_status_t (*controllerCreate)(
uint8_t controllerId,
usb_host_handle upperLayerHandle,
usb_host_controller_handle *controllerHandle); /*!< Create a controller instance function prototype*/
usb_status_t (*controllerDestory)(
usb_host_controller_handle controllerHandle); /*!< Destroy a controller instance function prototype*/
usb_status_t (*controllerOpenPipe)(usb_host_controller_handle controllerHandle,
usb_host_pipe_handle *pipeHandle,
usb_host_pipe_init_t *pipeInit); /*!< Open a controller pipe function prototype*/
usb_status_t (*controllerClosePipe)(
usb_host_controller_handle controllerHandle,
usb_host_pipe_handle pipeHandle); /*!< Close a controller pipe function prototype*/
usb_status_t (*controllerWritePipe)(usb_host_controller_handle controllerHandle,
usb_host_pipe_handle pipeHandle,
usb_host_transfer_t *transfer); /*!< Write data to a pipe function prototype*/
usb_status_t (*controllerReadPipe)(usb_host_controller_handle controllerHandle,
usb_host_pipe_handle pipeHandle,
usb_host_transfer_t *transfer); /*!< Read data from a pipe function prototype*/
usb_status_t (*controllerIoctl)(usb_host_controller_handle controllerHandle,
uint32_t ioctlEvent,
void *ioctlParam); /*!< Control a controller function prototype*/
} usb_host_controller_interface_t;
/*! @}*/
/*!
* @addtogroup usb_host_drv
* @{
*/
/*! @brief USB host instance structure */
typedef struct _usb_host_instance
{
void *controllerHandle; /*!< The low level controller handle*/
host_callback_t deviceCallback; /*!< Device attach/detach callback*/
usb_osa_mutex_handle hostMutex; /*!< Host layer mutex*/
usb_host_transfer_t transferList[USB_HOST_CONFIG_MAX_TRANSFERS]; /*!< Transfer resource*/
usb_host_transfer_t *transferHead; /*!< Idle transfer head*/
const usb_host_controller_interface_t *controllerTable; /*!< KHCI/EHCI interface*/
void *deviceList; /*!< Device list*/
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
void *suspendedDevice; /*!< Suspended device handle*/
volatile uint64_t hwTick; /*!< Current hw tick(ms)*/
uint8_t sleepType; /*!< L1 LPM device handle*/
#endif
uint8_t addressBitMap[16]; /*!< Used for address allocation. The first bit is the address 1, second bit is the
address 2*/
uint8_t occupied; /*!< 0 - the instance is not occupied; 1 - the instance is occupied*/
uint8_t controllerId; /*!< The controller ID*/
} usb_host_instance_t;
/*! @}*/
#endif /* _USB_HOST_HCI_H_ */

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __USB_H__
#define __USB_H__
#include <stdint.h>
#include <stdio.h>
#include <fsl_common.h>
#include "usb_misc.h"
#include "usb_spec.h"
/*!
* @addtogroup usb_drv
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Defines USB stack major version */
#define USB_STACK_VERSION_MAJOR (1U)
/*! @brief Defines USB stack minor version */
#define USB_STACK_VERSION_MINOR (6U)
/*! @brief Defines USB stack bugfix version */
#define USB_STACK_VERSION_BUGFIX (3U)
/*! @brief USB stack version definition */
#define USB_MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
/*! @brief USB error code */
typedef enum _usb_status
{
kStatus_USB_Success = 0x00U, /*!< Success */
kStatus_USB_Error, /*!< Failed */
kStatus_USB_Busy, /*!< Busy */
kStatus_USB_InvalidHandle, /*!< Invalid handle */
kStatus_USB_InvalidParameter, /*!< Invalid parameter */
kStatus_USB_InvalidRequest, /*!< Invalid request */
kStatus_USB_ControllerNotFound, /*!< Controller cannot be found */
kStatus_USB_InvalidControllerInterface, /*!< Invalid controller interface */
kStatus_USB_NotSupported, /*!< Configuration is not supported */
kStatus_USB_Retry, /*!< Enumeration get configuration retry */
kStatus_USB_TransferStall, /*!< Transfer stalled */
kStatus_USB_TransferFailed, /*!< Transfer failed */
kStatus_USB_AllocFail, /*!< Allocation failed */
kStatus_USB_LackSwapBuffer, /*!< Insufficient swap buffer for KHCI */
kStatus_USB_TransferCancel, /*!< The transfer cancelled */
kStatus_USB_BandwidthFail, /*!< Allocate bandwidth failed */
kStatus_USB_MSDStatusFail, /*!< For MSD, the CSW status means fail */
kStatus_USB_EHCIAttached,
kStatus_USB_EHCIDetached,
} usb_status_t;
/*! @brief USB host handle type define */
typedef void *usb_host_handle;
/*! @brief USB device handle type define. For device stack it is the whole device handle; for host stack it is the
* attached device instance handle*/
typedef void *usb_device_handle;
/*! @brief USB OTG handle type define */
typedef void *usb_otg_handle;
/*! @brief USB controller ID */
typedef enum _usb_controller_index
{
kUSB_ControllerKhci0 = 0U, /*!< KHCI 0U */
kUSB_ControllerKhci1 = 1U, /*!< KHCI 1U, Currently, there are no platforms which have two KHCI IPs, this is reserved
to be used in the future. */
kUSB_ControllerEhci0 = 2U, /*!< EHCI 0U */
kUSB_ControllerEhci1 = 3U, /*!< EHCI 1U, Currently, there are no platforms which have two EHCI IPs, this is reserved
to be used in the future. */
kUSB_ControllerLpcIp3511Fs0 = 4U, /*!< LPC USB IP3511 FS controller 0 */
kUSB_ControllerLpcIp3511Fs1 =
5U, /*!< LPC USB IP3511 FS controller 1, there are no platforms which have two IP3511 IPs, this is reserved
to be used in the future. */
kUSB_ControllerLpcIp3511Hs0 = 6U, /*!< LPC USB IP3511 HS controller 0 */
kUSB_ControllerLpcIp3511Hs1 =
7U, /*!< LPC USB IP3511 HS controller 1, there are no platforms which have two IP3511 IPs, this is reserved
to be used in the future. */
kUSB_ControllerOhci0 = 8U, /*!< OHCI 0U */
kUSB_ControllerOhci1 = 9U, /*!< OHCI 1U, Currently, there are no platforms which have two OHCI IPs, this is reserved
to be used in the future. */
kUSB_ControllerIp3516Hs0 = 10U, /*!< IP3516HS 0U */
kUSB_ControllerIp3516Hs1 =
11U, /*!< IP3516HS 1U, Currently, there are no platforms which have two IP3516HS IPs, this is reserved
to be used in the future. */
} usb_controller_index_t;
/**
* @brief USB stack version fields
*/
typedef struct _usb_version
{
uint8_t major; /*!< Major */
uint8_t minor; /*!< Minor */
uint8_t bugfix; /*!< Bug fix */
} usb_version_t;
/*******************************************************************************
* API
******************************************************************************/
/*! @} */
#endif /* __USB_H__ */

View File

@ -0,0 +1,185 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016 - 2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _USB_DEVICE_CONFIG_H_
#define _USB_DEVICE_CONFIG_H_
/*******************************************************************************
* Definitions
******************************************************************************/
/*!
* @addtogroup usb_device_configuration
* @{
*/
/*!
* @name Hardware instance define
* @{
*/
/*! @brief KHCI instance count */
#define USB_DEVICE_CONFIG_KHCI (0U)
/*! @brief EHCI instance count */
#define USB_DEVICE_CONFIG_EHCI (2U)
/*! @brief LPC USB IP3511 FS instance count */
#define USB_DEVICE_CONFIG_LPCIP3511FS (0U)
/*! @brief LPC USB IP3511 HS instance count */
#define USB_DEVICE_CONFIG_LPCIP3511HS (0U)
/*! @brief Device instance count, the sum of KHCI and EHCI instance counts*/
#define USB_DEVICE_CONFIG_NUM \
(USB_DEVICE_CONFIG_KHCI + USB_DEVICE_CONFIG_EHCI + USB_DEVICE_CONFIG_LPCIP3511FS + USB_DEVICE_CONFIG_LPCIP3511HS)
/* @} */
/*!
* @name class instance define
* @{
*/
/*! @brief HID instance count */
#define USB_DEVICE_CONFIG_HID (0U)
/*! @brief CDC ACM instance count */
#define USB_DEVICE_CONFIG_CDC_ACM (1U)
/*! @brief MSC instance count */
#define USB_DEVICE_CONFIG_MSC (0U)
/*! @brief Audio instance count */
#define USB_DEVICE_CONFIG_AUDIO (0U)
/*! @brief PHDC instance count */
#define USB_DEVICE_CONFIG_PHDC (0U)
/*! @brief Video instance count */
#define USB_DEVICE_CONFIG_VIDEO (0U)
/*! @brief CCID instance count */
#define USB_DEVICE_CONFIG_CCID (0U)
/*! @brief Printer instance count */
#define USB_DEVICE_CONFIG_PRINTER (0U)
/*! @brief DFU instance count */
#define USB_DEVICE_CONFIG_DFU (0U)
/* @} */
/*! @brief Whether device is self power. 1U supported, 0U not supported */
#define USB_DEVICE_CONFIG_SELF_POWER (1U)
/*! @brief How many endpoints are supported in the stack. */
#define USB_DEVICE_CONFIG_ENDPOINTS (4U)
/*! @brief Whether the device task is enabled. */
#define USB_DEVICE_CONFIG_USE_TASK (0U)
/*! @brief How many the notification message are supported when the device task is enabled. */
#define USB_DEVICE_CONFIG_MAX_MESSAGES (8U)
/*! @brief Whether test mode enabled. */
#define USB_DEVICE_CONFIG_USB20_TEST_MODE (0U)
/*! @brief Whether device CV test is enabled. */
#define USB_DEVICE_CONFIG_CV_TEST (0U)
/*! @brief Whether device compliance test is enabled. If the macro is enabled,
the test mode and CV test macroes will be set.*/
#define USB_DEVICE_CONFIG_COMPLIANCE_TEST (0U)
#if ((defined(USB_DEVICE_CONFIG_COMPLIANCE_TEST)) && (USB_DEVICE_CONFIG_COMPLIANCE_TEST > 0U))
/*! @brief Undefine the marco USB_DEVICE_CONFIG_USB20_TEST_MODE. */
#undef USB_DEVICE_CONFIG_USB20_TEST_MODE
/*! @brief Undefine the marco USB_DEVICE_CONFIG_CV_TEST. */
#undef USB_DEVICE_CONFIG_CV_TEST
/*! @brief enable the test mode. */
#define USB_DEVICE_CONFIG_USB20_TEST_MODE (1U)
/*! @brief enable the CV test */
#define USB_DEVICE_CONFIG_CV_TEST (1U)
#endif
#if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
/*! @brief The MAX buffer length for the KHCI DMA workaround.*/
#define USB_DEVICE_CONFIG_KHCI_DMA_ALIGN_BUFFER_LENGTH (64U)
#endif
#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
/*! @brief How many the DTD are supported. */
#define USB_DEVICE_CONFIG_EHCI_MAX_DTD (16U)
/*! @brief Whether the EHCI ID pin detect feature enabled. */
#define USB_DEVICE_CONFIG_EHCI_ID_PIN_DETECT (0U)
#endif
/*! @brief Whether the keep alive feature enabled. */
#define USB_DEVICE_CONFIG_KEEP_ALIVE_MODE (0U)
/*! @brief Whether the transfer buffer is cache-enabled or not. */
#define USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE (1U)
/*! @brief Whether the low power mode is enabled or not. */
#define USB_DEVICE_CONFIG_LOW_POWER_MODE (0U)
#if ((defined(USB_DEVICE_CONFIG_LOW_POWER_MODE)) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
/*! @brief Whether device remote wakeup supported. 1U supported, 0U not supported */
#define USB_DEVICE_CONFIG_REMOTE_WAKEUP (0U)
/*! @brief Whether LPM is supported. 1U supported, 0U not supported */
#define USB_DEVICE_CONFIG_LPM_L1 (0U)
#else
/*! @brief The device remote wakeup is unsupported. */
#define USB_DEVICE_CONFIG_REMOTE_WAKEUP (0U)
#endif
/*! @brief Whether the device detached feature is enabled or not. */
#define USB_DEVICE_CONFIG_DETACH_ENABLE (0U)
/*! @brief Whether handle the USB bus error. */
#define USB_DEVICE_CONFIG_ERROR_HANDLING (0U)
/* @} */
/*! @brief rt-thread port alloc */
#include <rtthread.h>
#define USB_OSA_SR_ALLOC(...)
/*! @brief rt-thread port enter critical */
#define USB_OSA_ENTER_CRITICAL rt_enter_critical
/*! @brief rt-thread port exit critical */
#define USB_OSA_EXIT_CRITICAL rt_exit_critical
#endif /* _USB_DEVICE_CONFIG_H_ */

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __USB_EHCI_H__
#define __USB_EHCI_H__
/*******************************************************************************
* Definitions
******************************************************************************/
/* Device QH */
#define USB_DEVICE_EHCI_QH_POINTER_MASK (0xFFFFFFC0U)
#define USB_DEVICE_EHCI_QH_MULT_MASK (0xC0000000U)
#define USB_DEVICE_EHCI_QH_ZLT_MASK (0x20000000U)
#define USB_DEVICE_EHCI_QH_MAX_PACKET_SIZE_MASK (0x07FF0000U)
#define USB_DEVICE_EHCI_QH_MAX_PACKET_SIZE (0x00000800U)
#define USB_DEVICE_EHCI_QH_IOS_MASK (0x00008000U)
/* Device DTD */
#define USB_DEVICE_ECHI_DTD_POINTER_MASK (0xFFFFFFE0U)
#define USB_DEVICE_ECHI_DTD_TERMINATE_MASK (0x00000001U)
#define USB_DEVICE_ECHI_DTD_PAGE_MASK (0xFFFFF000U)
#define USB_DEVICE_ECHI_DTD_PAGE_OFFSET_MASK (0x00000FFFU)
#define USB_DEVICE_ECHI_DTD_PAGE_BLOCK (0x00001000U)
#define USB_DEVICE_ECHI_DTD_TOTAL_BYTES_MASK (0x7FFF0000U)
#define USB_DEVICE_ECHI_DTD_TOTAL_BYTES (0x00004000U)
#define USB_DEVICE_ECHI_DTD_IOC_MASK (0x00008000U)
#define USB_DEVICE_ECHI_DTD_MULTIO_MASK (0x00000C00U)
#define USB_DEVICE_ECHI_DTD_STATUS_MASK (0x000000FFU)
#define USB_DEVICE_EHCI_DTD_STATUS_ERROR_MASK (0x00000068U)
#define USB_DEVICE_ECHI_DTD_STATUS_ACTIVE (0x00000080U)
#define USB_DEVICE_ECHI_DTD_STATUS_HALTED (0x00000040U)
#define USB_DEVICE_ECHI_DTD_STATUS_DATA_BUFFER_ERROR (0x00000020U)
#define USB_DEVICE_ECHI_DTD_STATUS_TRANSACTION_ERROR (0x00000008U)
typedef struct _usb_device_ehci_qh_struct
{
union
{
volatile uint32_t capabilttiesCharacteristics;
struct
{
volatile uint32_t reserved1 : 15;
volatile uint32_t ios : 1;
volatile uint32_t maxPacketSize : 11;
volatile uint32_t reserved2 : 2;
volatile uint32_t zlt : 1;
volatile uint32_t mult : 2;
} capabilttiesCharacteristicsBitmap;
} capabilttiesCharacteristicsUnion;
volatile uint32_t currentDtdPointer;
volatile uint32_t nextDtdPointer;
union
{
volatile uint32_t dtdToken;
struct
{
volatile uint32_t status : 8;
volatile uint32_t reserved1 : 2;
volatile uint32_t multiplierOverride : 2;
volatile uint32_t reserved2 : 3;
volatile uint32_t ioc : 1;
volatile uint32_t totalBytes : 15;
volatile uint32_t reserved3 : 1;
} dtdTokenBitmap;
} dtdTokenUnion;
volatile uint32_t bufferPointerPage[5];
volatile uint32_t reserved1;
uint32_t setupBuffer[2];
uint32_t setupBufferBack[2];
union
{
uint32_t endpointStatus;
struct
{
uint32_t isOpened : 1;
uint32_t : 31;
} endpointStatusBitmap;
} endpointStatusUnion;
uint32_t reserved2;
} usb_device_ehci_qh_struct_t;
typedef struct _usb_device_ehci_dtd_struct
{
volatile uint32_t nextDtdPointer;
union
{
volatile uint32_t dtdToken;
struct
{
volatile uint32_t status : 8;
volatile uint32_t reserved1 : 2;
volatile uint32_t multiplierOverride : 2;
volatile uint32_t reserved2 : 3;
volatile uint32_t ioc : 1;
volatile uint32_t totalBytes : 15;
volatile uint32_t reserved3 : 1;
} dtdTokenBitmap;
} dtdTokenUnion;
volatile uint32_t bufferPointerPage[5];
union
{
volatile uint32_t reserved;
struct
{
uint32_t originalBufferOffest : 12;
uint32_t originalBufferLength : 19;
uint32_t dtdInvalid : 1;
} originalBufferInfo;
} reservedUnion;
} usb_device_ehci_dtd_struct_t;
#endif /* __USB_EHCI_H__ */

View File

@ -0,0 +1,454 @@
/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __USB_MISC_H__
#define __USB_MISC_H__
#define ENDIANNESS USB_LITTLE_ENDIAN
#ifndef ENDIANNESS
#error ENDIANNESS should be defined, and then rebulid the project.
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Define USB printf */
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
extern int DbgConsole_Printf(const char *fmt_s, ...);
#if defined(__cplusplus)
}
#endif /* __cplusplus */
#if defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE < 1)
#define usb_echo printf
#else
#define usb_echo DbgConsole_Printf
#endif
#if defined(__ICCARM__)
#ifndef STRUCT_PACKED
#define STRUCT_PACKED __packed
#endif
#ifndef STRUCT_UNPACKED
#define STRUCT_UNPACKED
#endif
#elif defined(__GNUC__)
#ifndef STRUCT_PACKED
#define STRUCT_PACKED
#endif
#ifndef STRUCT_UNPACKED
#define STRUCT_UNPACKED __attribute__((__packed__))
#endif
#elif defined(__CC_ARM)
#ifndef STRUCT_PACKED
#define STRUCT_PACKED _Pragma("pack(1U)")
#endif
#ifndef STRUCT_UNPACKED
#define STRUCT_UNPACKED _Pragma("pack()")
#endif
#endif
#define USB_SHORT_GET_LOW(x) (((uint16_t)x) & 0xFFU)
#define USB_SHORT_GET_HIGH(x) ((uint8_t)(((uint16_t)x) >> 8U) & 0xFFU)
#define USB_LONG_GET_BYTE0(x) ((uint8_t)(((uint32_t)(x))) & 0xFFU)
#define USB_LONG_GET_BYTE1(x) ((uint8_t)(((uint32_t)(x)) >> 8U) & 0xFFU)
#define USB_LONG_GET_BYTE2(x) ((uint8_t)(((uint32_t)(x)) >> 16U) & 0xFFU)
#define USB_LONG_GET_BYTE3(x) ((uint8_t)(((uint32_t)(x)) >> 24U) & 0xFFU)
#define USB_MEM4_ALIGN_MASK (0x03U)
/* accessory macro */
#define USB_MEM4_ALIGN(n) ((n + 3U) & (0xFFFFFFFCu))
#define USB_MEM32_ALIGN(n) ((n + 31U) & (0xFFFFFFE0u))
#define USB_MEM64_ALIGN(n) ((n + 63U) & (0xFFFFFFC0u))
/* big/little endian */
#define SWAP2BYTE_CONST(n) ((((n)&0x00FFU) << 8U) | (((n)&0xFF00U) >> 8U))
#define SWAP4BYTE_CONST(n) \
((((n)&0x000000FFU) << 24U) | (((n)&0x0000FF00U) << 8U) | (((n)&0x00FF0000U) >> 8U) | (((n)&0xFF000000U) >> 24U))
#define USB_ASSIGN_VALUE_ADDRESS_LONG_BY_BYTE(n, m) \
{ \
*((uint8_t *)&(n)) = *((uint8_t *)&(m)); \
*((uint8_t *)&(n) + 1) = *((uint8_t *)&(m) + 1); \
*((uint8_t *)&(n) + 2) = *((uint8_t *)&(m) + 2); \
*((uint8_t *)&(n) + 3) = *((uint8_t *)&(m) + 3); \
}
#define USB_ASSIGN_VALUE_ADDRESS_SHORT_BY_BYTE(n, m) \
{ \
*((uint8_t *)&(n)) = *((uint8_t *)&(m)); \
*((uint8_t *)&(n) + 1) = *((uint8_t *)&(m) + 1); \
}
#define USB_ASSIGN_MACRO_VALUE_ADDRESS_LONG_BY_BYTE(n, m) \
{ \
*((uint8_t *)&(n)) = (uint8_t)m; \
*((uint8_t *)&(n) + 1) = (uint8_t)(m >> 8); \
*((uint8_t *)&(n) + 2) = (uint8_t)(m >> 16); \
*((uint8_t *)&(n) + 3) = (uint8_t)(m >> 24); \
}
#define USB_ASSIGN_MACRO_VALUE_ADDRESS_SHORT_BY_BYTE(n, m) \
{ \
*((uint8_t *)&(n)) = (uint8_t)m; \
*((uint8_t *)&(n) + 1) = (uint8_t)(m >> 8); \
}
//#if (ENDIANNESS == USB_BIG_ENDIAN)
#if 0
#define USB_SHORT_TO_LITTLE_ENDIAN(n) SWAP2BYTE_CONST(n)
#define USB_LONG_TO_LITTLE_ENDIAN(n) SWAP4BYTE_CONST(n)
#define USB_SHORT_FROM_LITTLE_ENDIAN(n) SWAP2BYTE_CONST(n)
#define USB_LONG_FROM_LITTLE_ENDIAN(n) SWAP2BYTE_CONST(n)
#define USB_SHORT_TO_BIG_ENDIAN(n) (n)
#define USB_LONG_TO_BIG_ENDIAN(n) (n)
#define USB_SHORT_FROM_BIG_ENDIAN(n) (n)
#define USB_LONG_FROM_BIG_ENDIAN(n) (n)
#define USB_LONG_TO_LITTLE_ENDIAN_ADDRESS(n, m) \
{ \
m[3] = ((n >> 24U) & 0xFFU); \
m[2] = ((n >> 16U) & 0xFFU); \
m[1] = ((n >> 8U) & 0xFFU); \
m[0] = (n & 0xFFU); \
}
#define USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(n) \
((uint32_t)((((uint8_t)n[3]) << 24U) | (((uint8_t)n[2]) << 16U) | (((uint8_t)n[1]) << 8U) | \
(((uint8_t)n[0]) << 0U)))
#define USB_LONG_TO_BIG_ENDIAN_ADDRESS(n, m) \
{ \
m[0] = ((n >> 24U) & 0xFFU); \
m[1] = ((n >> 16U) & 0xFFU); \
m[2] = ((n >> 8U) & 0xFFU); \
m[3] = (n & 0xFFU); \
}
#define USB_LONG_FROM_BIG_ENDIAN_ADDRESS(n) \
((uint32_t)((((uint8_t)n[0]) << 24U) | (((uint8_t)n[1]) << 16U) | (((uint8_t)n[2]) << 8U) | \
(((uint8_t)n[3]) << 0U)))
#define USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(n, m) \
{ \
m[1] = ((n >> 8U) & 0xFFU); \
m[0] = (n & 0xFFU); \
}
#define USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[1]) << 8U) | (((uint8_t)n[0]) << 0U)))
#define USB_SHORT_TO_BIG_ENDIAN_ADDRESS(n, m) \
{ \
m[0] = ((n >> 8U) & 0xFFU); \
m[1] = (n & 0xFFU); \
}
#define USB_SHORT_FROM_BIG_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[0]) << 8U) | (((uint8_t)n[1]) << 0U)))
#define USB_LONG_TO_LITTLE_ENDIAN_DATA(n, m) \
{ \
*((uint8_t *)&(m) + 3) = ((n >> 24U) & 0xFFU); \
*((uint8_t *)&(m) + 2) = ((n >> 16U) & 0xFFU); \
*((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU); \
*((uint8_t *)&(m) + 0) = (n & 0xFFU); \
}
#define USB_LONG_FROM_LITTLE_ENDIAN_DATA(n) \
((uint32_t)(((*((uint8_t *)&(n) + 3)) << 24U) | ((*((uint8_t *)&(n) + 2)) << 16U) | \
((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n))) << 0U)))
#define USB_SHORT_TO_LITTLE_ENDIAN_DATA(n, m) \
{ \
*((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU); \
*((uint8_t *)&(m)) = ((n)&0xFFU); \
}
#define USB_SHORT_FROM_LITTLE_ENDIAN_DATA(n) ((uint32_t)(((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n))))))
#else
#define USB_SHORT_TO_LITTLE_ENDIAN(n) (n)
#define USB_LONG_TO_LITTLE_ENDIAN(n) (n)
#define USB_SHORT_FROM_LITTLE_ENDIAN(n) (n)
#define USB_LONG_FROM_LITTLE_ENDIAN(n) (n)
#define USB_SHORT_TO_BIG_ENDIAN(n) SWAP2BYTE_CONST(n)
#define USB_LONG_TO_BIG_ENDIAN(n) SWAP4BYTE_CONST(n)
#define USB_SHORT_FROM_BIG_ENDIAN(n) SWAP2BYTE_CONST(n)
#define USB_LONG_FROM_BIG_ENDIAN(n) SWAP4BYTE_CONST(n)
#define USB_LONG_TO_LITTLE_ENDIAN_ADDRESS(n, m) \
{ \
m[3] = ((n >> 24U) & 0xFFU); \
m[2] = ((n >> 16U) & 0xFFU); \
m[1] = ((n >> 8U) & 0xFFU); \
m[0] = (n & 0xFFU); \
}
#define USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(n) \
((uint32_t)((((uint8_t)n[3]) << 24U) | (((uint8_t)n[2]) << 16U) | (((uint8_t)n[1]) << 8U) | \
(((uint8_t)n[0]) << 0U)))
#define USB_LONG_TO_BIG_ENDIAN_ADDRESS(n, m) \
{ \
m[0] = ((n >> 24U) & 0xFFU); \
m[1] = ((n >> 16U) & 0xFFU); \
m[2] = ((n >> 8U) & 0xFFU); \
m[3] = (n & 0xFFU); \
}
#define USB_LONG_FROM_BIG_ENDIAN_ADDRESS(n) \
((uint32_t)((((uint8_t)n[0]) << 24U) | (((uint8_t)n[1]) << 16U) | (((uint8_t)n[2]) << 8U) | \
(((uint8_t)n[3]) << 0U)))
#define USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(n, m) \
{ \
m[1] = ((n >> 8U) & 0xFFU); \
m[0] = (n & 0xFFU); \
}
#define USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[1]) << 8U) | (((uint8_t)n[0]) << 0U)))
#define USB_SHORT_TO_BIG_ENDIAN_ADDRESS(n, m) \
{ \
m[0] = ((n >> 8U) & 0xFFU); \
m[1] = (n & 0xFFU); \
}
#define USB_SHORT_FROM_BIG_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[0]) << 8U) | (((uint8_t)n[1]) << 0U)))
#define USB_LONG_TO_LITTLE_ENDIAN_DATA(n, m) \
{ \
*((uint8_t *)&(m) + 3) = ((n >> 24U) & 0xFFU); \
*((uint8_t *)&(m) + 2) = ((n >> 16U) & 0xFFU); \
*((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU); \
*((uint8_t *)&(m) + 0) = (n & 0xFFU); \
}
#define USB_LONG_FROM_LITTLE_ENDIAN_DATA(n) \
((uint32_t)(((*((uint8_t *)&(n) + 3)) << 24U) | ((*((uint8_t *)&(n) + 2)) << 16U) | \
((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n))) << 0U)))
#define USB_SHORT_TO_LITTLE_ENDIAN_DATA(n, m) \
{ \
*((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU); \
*((uint8_t *)&(m)) = ((n)&0xFFU); \
}
#define USB_SHORT_FROM_LITTLE_ENDIAN_DATA(n) ((uint32_t)(((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n))))))
#endif
/*
* The following MACROs (USB_GLOBAL, USB_BDT, USB_RAM_ADDRESS_ALIGNMENT, etc) are only used for USB device stack.
* The USB device global variables are put into the section m_usb_global and m_usb_bdt or the section
* .bss.m_usb_global and .bss.m_usb_bdt by using the MACRO USB_GLOBAL and USB_BDT. In this way, the USB device
* global variables can be linked into USB dedicated RAM by USB_STACK_USE_DEDICATED_RAM.
* The MACRO USB_STACK_USE_DEDICATED_RAM is used to decide the USB stack uses dedicated RAM or not. The value of
* the marco can be set as 0, USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL, or USB_STACK_DEDICATED_RAM_TYPE_BDT.
* The MACRO USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL means USB device global variables, including USB_BDT and
* USB_GLOBAL, are put into the USB dedicated RAM. This feature can only be enabled when the USB dedicated RAM
* is not less than 2K Bytes.
* The MACRO USB_STACK_DEDICATED_RAM_TYPE_BDT means USB device global variables, only including USB_BDT, are put
* into the USB dedicated RAM, the USB_GLOBAL will be put into .bss section. This feature is used for some SOCs,
* the USB dedicated RAM size is not more than 512 Bytes.
*/
#define USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL 1
#define USB_STACK_DEDICATED_RAM_TYPE_BDT 2
#if defined(__ICCARM__)
#define USB_WEAK_VAR __attribute__((weak))
#define USB_WEAK_FUN __attribute__((weak))
/* disable misra 19.13 */
_Pragma("diag_suppress=Pm120")
#define USB_ALIGN_PRAGMA(x) _Pragma(#x)
_Pragma("diag_default=Pm120")
#define USB_RAM_ADDRESS_ALIGNMENT(n) USB_ALIGN_PRAGMA(data_alignment = n)
_Pragma("diag_suppress=Pm120")
#define USB_LINK_SECTION_PART(str) _Pragma(#str)
#define USB_LINK_SECTION_SUB(sec) USB_LINK_SECTION_PART(location = #sec)
#define USB_LINK_USB_GLOBAL _Pragma("location = \"m_usb_global\"")
#define USB_LINK_USB_BDT _Pragma("location = \"m_usb_bdt\"")
#define USB_LINK_USB_GLOBAL_BSS _Pragma("location = \".bss.m_usb_global\"")
#define USB_LINK_USB_BDT_BSS _Pragma("location = \".bss.m_usb_bdt\"")
_Pragma("diag_default=Pm120")
#define USB_LINK_DMA_NONINIT_DATA _Pragma("location = \"m_usb_dma_noninit_data\"")
#define USB_LINK_NONCACHE_NONINIT_DATA _Pragma("location = \"NonCacheable\"")
#elif defined(__CC_ARM)
#define USB_WEAK_VAR __attribute__((weak))
#define USB_WEAK_FUN __weak
#define USB_RAM_ADDRESS_ALIGNMENT(n) __attribute__((aligned(n)))
#define USB_LINK_SECTION_SUB(sec) __attribute__((section(#sec)))
#define USB_LINK_USB_GLOBAL __attribute__((section("m_usb_global"))) __attribute__((zero_init))
#define USB_LINK_USB_BDT __attribute__((section("m_usb_bdt"))) __attribute__((zero_init))
#define USB_LINK_USB_GLOBAL_BSS __attribute__((section(".bss.m_usb_global"))) __attribute__((zero_init))
#define USB_LINK_USB_BDT_BSS __attribute__((section(".bss.m_usb_bdt"))) __attribute__((zero_init))
#define USB_LINK_DMA_NONINIT_DATA __attribute__((section("m_usb_dma_noninit_data"))) __attribute__((zero_init))
#define USB_LINK_NONCACHE_NONINIT_DATA __attribute__((section("NonCacheable"))) __attribute__((zero_init))
#elif defined(__GNUC__)
#define USB_WEAK_VAR __attribute__((weak))
#define USB_WEAK_FUN __attribute__((weak))
#define USB_RAM_ADDRESS_ALIGNMENT(n) __attribute__((aligned(n)))
#define USB_LINK_SECTION_SUB(sec) __attribute__((section(#sec)))
#define USB_LINK_USB_GLOBAL __attribute__((section("m_usb_global, \"aw\", %nobits @")))
#define USB_LINK_USB_BDT __attribute__((section("m_usb_bdt, \"aw\", %nobits @")))
#define USB_LINK_USB_GLOBAL_BSS __attribute__((section(".bss.m_usb_global, \"aw\", %nobits @")))
#define USB_LINK_USB_BDT_BSS __attribute__((section(".bss.m_usb_bdt, \"aw\", %nobits @")))
#define USB_LINK_DMA_NONINIT_DATA __attribute__((section("m_usb_dma_noninit_data, \"aw\", %nobits @")))
#define USB_LINK_NONCACHE_NONINIT_DATA __attribute__((section("NonCacheable, \"aw\", %nobits @")))
#else
#error The tool-chain is not supported.
#endif
#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \
(defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
#if ((defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)) && (defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)))
#define USB_CACHE_LINESIZE MAX(FSL_FEATURE_L2CACHE_LINESIZE_BYTE, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#elif(defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE))
#define USB_CACHE_LINESIZE MAX(FSL_FEATURE_L2CACHE_LINESIZE_BYTE, 0)
#elif(defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE))
#define USB_CACHE_LINESIZE MAX(0, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#else
#define USB_CACHE_LINESIZE 4
#endif
#else
#define USB_CACHE_LINESIZE 4
#endif
#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
#define USB_DATA_ALIGN 64
#else
#define USB_DATA_ALIGN 4
#endif
#define USB_DATA_ALIGN_SIZE MAX(USB_CACHE_LINESIZE, USB_DATA_ALIGN)
#define USB_DATA_ALIGN_SIZE_MULTIPLE(n) ((n + USB_DATA_ALIGN_SIZE - 1) & (~(USB_DATA_ALIGN_SIZE - 1)))
#if defined(USB_STACK_USE_DEDICATED_RAM) && (USB_STACK_USE_DEDICATED_RAM == USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL)
#define USB_GLOBAL USB_LINK_USB_GLOBAL
#define USB_BDT USB_LINK_USB_BDT
#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \
(defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
#define USB_DMA_DATA_NONINIT_SUB USB_LINK_DMA_NONINIT_DATA
#define USB_DMA_DATA_INIT_SUB USB_LINK_SECTION_SUB(m_usb_dma_init_data)
#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA
#else
#define USB_DMA_DATA_NONINIT_SUB
#define USB_DMA_DATA_INIT_SUB
#define USB_CONTROLLER_DATA USB_LINK_USB_GLOBAL
#endif
#elif defined(USB_STACK_USE_DEDICATED_RAM) && (USB_STACK_USE_DEDICATED_RAM == USB_STACK_DEDICATED_RAM_TYPE_BDT)
#define USB_BDT USB_LINK_USB_BDT
#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \
(defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
#define USB_GLOBAL USB_LINK_DMA_NONINIT_DATA
#define USB_DMA_DATA_NONINIT_SUB USB_LINK_DMA_NONINIT_DATA
#define USB_DMA_DATA_INIT_SUB USB_LINK_SECTION_SUB(m_usb_dma_init_data)
#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA
#else
#define USB_GLOBAL USB_LINK_USB_GLOBAL_BSS
#define USB_DMA_DATA_NONINIT_SUB
#define USB_DMA_DATA_INIT_SUB
#define USB_CONTROLLER_DATA
#endif
#else
#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \
(defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
#define USB_GLOBAL USB_LINK_DMA_NONINIT_DATA
#define USB_BDT USB_LINK_NONCACHE_NONINIT_DATA
#define USB_DMA_DATA_NONINIT_SUB USB_LINK_DMA_NONINIT_DATA
#define USB_DMA_DATA_INIT_SUB USB_LINK_SECTION_SUB(m_usb_dma_init_data)
#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA
#else
#define USB_GLOBAL USB_LINK_USB_GLOBAL_BSS
#define USB_BDT USB_LINK_USB_BDT_BSS
#define USB_DMA_DATA_NONINIT_SUB
#define USB_DMA_DATA_INIT_SUB
#define USB_CONTROLLER_DATA
#endif
#endif
#define USB_DMA_NONINIT_DATA_ALIGN(n) USB_RAM_ADDRESS_ALIGNMENT(n) USB_DMA_DATA_NONINIT_SUB
#define USB_DMA_INIT_DATA_ALIGN(n) USB_RAM_ADDRESS_ALIGNMENT(n) USB_DMA_DATA_INIT_SUB
#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \
(defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
#define USB_DMA_DATA_NONCACHEABLE USB_LINK_NONCACHE_NONINIT_DATA
#else
#define USB_DMA_DATA_NONCACHEABLE
#endif
#define USB_GLOBAL_DEDICATED_RAM USB_LINK_USB_GLOBAL
/* #define USB_RAM_ADDRESS_NONCACHEREG_ALIGNMENT(n, var) AT_NONCACHEABLE_SECTION_ALIGN(var, n) */
/* #define USB_RAM_ADDRESS_NONCACHEREG(var) AT_NONCACHEABLE_SECTION(var) */
#endif /* __USB_MISC_H__ */

View File

@ -0,0 +1,296 @@
/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __USB_SPEC_H__
#define __USB_SPEC_H__
/*******************************************************************************
* Definitions
******************************************************************************/
/* USB speed (the value cannot be changed because EHCI QH use the value directly)*/
#define USB_SPEED_FULL (0x00U)
#define USB_SPEED_LOW (0x01U)
#define USB_SPEED_HIGH (0x02U)
/* Set up packet structure */
typedef struct _usb_setup_struct
{
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} usb_setup_struct_t;
/* USB standard descriptor endpoint type */
#define USB_ENDPOINT_CONTROL (0x00U)
#define USB_ENDPOINT_ISOCHRONOUS (0x01U)
#define USB_ENDPOINT_BULK (0x02U)
#define USB_ENDPOINT_INTERRUPT (0x03U)
/* USB standard descriptor transfer direction (cannot change the value because iTD use the value directly) */
#define USB_OUT (0U)
#define USB_IN (1U)
/* USB standard descriptor length */
#define USB_DESCRIPTOR_LENGTH_DEVICE (0x12U)
#define USB_DESCRIPTOR_LENGTH_CONFIGURE (0x09U)
#define USB_DESCRIPTOR_LENGTH_INTERFACE (0x09U)
#define USB_DESCRIPTOR_LENGTH_ENDPOINT (0x07U)
#define USB_DESCRIPTOR_LENGTH_DEVICE_QUALITIER (0x0AU)
#define USB_DESCRIPTOR_LENGTH_OTG_DESCRIPTOR (5U)
#define USB_DESCRIPTOR_LENGTH_BOS_DESCRIPTOR (5U)
/* USB Device Capability Type Codes */
#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY_WIRELESS (0x01U)
#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY_USB20_EXTENSION (0x02U)
#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY_SUPERSPEED (0x03U)
/* USB standard descriptor type */
#define USB_DESCRIPTOR_TYPE_DEVICE (0x01U)
#define USB_DESCRIPTOR_TYPE_CONFIGURE (0x02U)
#define USB_DESCRIPTOR_TYPE_STRING (0x03U)
#define USB_DESCRIPTOR_TYPE_INTERFACE (0x04U)
#define USB_DESCRIPTOR_TYPE_ENDPOINT (0x05U)
#define USB_DESCRIPTOR_TYPE_DEVICE_QUALITIER (0x06U)
#define USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION (0x07U)
#define USB_DESCRIPTOR_TYPE_INTERFAACE_POWER (0x08U)
#define USB_DESCRIPTOR_TYPE_OTG (0x09U)
#define USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION (0x0BU)
#define USB_DESCRIPTOR_TYPE_BOS (0x0F)
#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY (0x10)
#define USB_DESCRIPTOR_TYPE_HID (0x21U)
#define USB_DESCRIPTOR_TYPE_HID_REPORT (0x22U)
#define USB_DESCRIPTOR_TYPE_HID_PHYSICAL (0x23U)
/* USB standard request type */
#define USB_REQUEST_TYPE_DIR_MASK (0x80U)
#define USB_REQUEST_TYPE_DIR_SHIFT (7U)
#define USB_REQUEST_TYPE_DIR_OUT (0x00U)
#define USB_REQUEST_TYPE_DIR_IN (0x80U)
#define USB_REQUEST_TYPE_TYPE_MASK (0x60U)
#define USB_REQUEST_TYPE_TYPE_SHIFT (5U)
#define USB_REQUEST_TYPE_TYPE_STANDARD (0U)
#define USB_REQUEST_TYPE_TYPE_CLASS (0x20U)
#define USB_REQUEST_TYPE_TYPE_VENDOR (0x40U)
#define USB_REQUEST_TYPE_RECIPIENT_MASK (0x1FU)
#define USB_REQUEST_TYPE_RECIPIENT_SHIFT (0U)
#define USB_REQUEST_TYPE_RECIPIENT_DEVICE (0x00U)
#define USB_REQUEST_TYPE_RECIPIENT_INTERFACE (0x01U)
#define USB_REQUEST_TYPE_RECIPIENT_ENDPOINT (0x02U)
#define USB_REQUEST_TYPE_RECIPIENT_OTHER (0x03U)
/* USB standard request */
#define USB_REQUEST_STANDARD_GET_STATUS (0x00U)
#define USB_REQUEST_STANDARD_CLEAR_FEATURE (0x01U)
#define USB_REQUEST_STANDARD_SET_FEATURE (0x03U)
#define USB_REQUEST_STANDARD_SET_ADDRESS (0x05U)
#define USB_REQUEST_STANDARD_GET_DESCRIPTOR (0x06U)
#define USB_REQUEST_STANDARD_SET_DESCRIPTOR (0x07U)
#define USB_REQUEST_STANDARD_GET_CONFIGURATION (0x08U)
#define USB_REQUEST_STANDARD_SET_CONFIGURATION (0x09U)
#define USB_REQUEST_STANDARD_GET_INTERFACE (0x0AU)
#define USB_REQUEST_STANDARD_SET_INTERFACE (0x0BU)
#define USB_REQUEST_STANDARD_SYNCH_FRAME (0x0CU)
/* USB standard request GET Status */
#define USB_REQUEST_STANDARD_GET_STATUS_DEVICE_SELF_POWERED_SHIFT (0U)
#define USB_REQUEST_STANDARD_GET_STATUS_DEVICE_REMOTE_WARKUP_SHIFT (1U)
#define USB_REQUEST_STANDARD_GET_STATUS_ENDPOINT_HALT_MASK (0x01U)
#define USB_REQUEST_STANDARD_GET_STATUS_ENDPOINT_HALT_SHIFT (0U)
#define USB_REQUEST_STANDARD_GET_STATUS_OTG_STATUS_SELECTOR (0xF000U)
/* USB standard request CLEAR/SET feature */
#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT (0U)
#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP (1U)
#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_TEST_MODE (2U)
#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_B_HNP_ENABLE (3U)
#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_A_HNP_SUPPORT (4U)
#define USB_REQUEST_STANDARD_FEATURE_SELECTOR_A_ALT_HNP_SUPPORT (5U)
/* USB standard descriptor configure bmAttributes */
#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_D7_MASK (0x80U)
#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_D7_SHIFT (7U)
#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_SELF_POWERED_MASK (0x40U)
#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_SELF_POWERED_SHIFT (6U)
#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_REMOTE_WAKEUP_MASK (0x20U)
#define USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_REMOTE_WAKEUP_SHIFT (5U)
/* USB standard descriptor endpoint bmAttributes */
#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK (0x80U)
#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT (7U)
#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT (0U)
#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN (0x80U)
#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK (0x0FU)
#define USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_SHFIT (0U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK (0x03U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_NUMBER_SHFIT (0U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_MASK (0x0CU)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_SHFIT (2U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_NO_SYNC (0x00U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_ASYNC (0x04U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_ADAPTIVE (0x08U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_SYNC_TYPE_SYNC (0x0CU)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_USAGE_TYPE_MASK (0x30U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_USAGE_TYPE_SHFIT (4U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_USAGE_TYPE_DATA_ENDPOINT (0x00U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_USAGE_TYPE_FEEDBACK_ENDPOINT (0x10U)
#define USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_USAGE_TYPE_IMPLICIT_FEEDBACK_DATA_ENDPOINT (0x20U)
#define USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK (0x07FFu)
#define USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK (0x1800u)
#define USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_SHFIT (11U)
/* USB standard descriptor otg bmAttributes */
#define USB_DESCRIPTOR_OTG_ATTRIBUTES_SRP_MASK (0x01u)
#define USB_DESCRIPTOR_OTG_ATTRIBUTES_HNP_MASK (0x02u)
#define USB_DESCRIPTOR_OTG_ATTRIBUTES_ADP_MASK (0x04u)
/* USB standard descriptor device capability usb20 extension bmAttributes */
#define USB_DESCRIPTOR_DEVICE_CAPABILITY_USB20_EXTENSION_LPM_MASK (0x02U)
#define USB_DESCRIPTOR_DEVICE_CAPABILITY_USB20_EXTENSION_LPM_SHIFT (1U)
#define USB_DESCRIPTOR_DEVICE_CAPABILITY_USB20_EXTENSION_BESL_MASK (0x04U)
#define USB_DESCRIPTOR_DEVICE_CAPABILITY_USB20_EXTENSION_BESL_SHIFT (2U)
/* Language structure */
typedef struct _usb_language
{
uint8_t **string; /* The Strings descriptor array */
uint32_t *length; /* The strings descriptor length array */
uint16_t languageId; /* The language id of current language */
} usb_language_t;
typedef struct _usb_language_list
{
uint8_t *languageString; /* The String 0U pointer */
uint32_t stringLength; /* The String 0U Length */
usb_language_t *languageList; /* The language list */
uint8_t count; /* The language count */
} usb_language_list_t;
typedef struct _usb_descriptor_common
{
uint8_t bLength; /* Size of this descriptor in bytes */
uint8_t bDescriptorType; /* DEVICE Descriptor Type */
uint8_t bData[1]; /* Data */
} usb_descriptor_common_t;
typedef struct _usb_descriptor_device
{
uint8_t bLength; /* Size of this descriptor in bytes */
uint8_t bDescriptorType; /* DEVICE Descriptor Type */
uint8_t bcdUSB[2]; /* UUSB Specification Release Number in Binary-Coded Decimal, e.g. 0x0200U */
uint8_t bDeviceClass; /* Class code */
uint8_t bDeviceSubClass; /* Sub-Class code */
uint8_t bDeviceProtocol; /* Protocol code */
uint8_t bMaxPacketSize0; /* Maximum packet size for endpoint zero */
uint8_t idVendor[2]; /* Vendor ID (assigned by the USB-IF) */
uint8_t idProduct[2]; /* Product ID (assigned by the manufacturer) */
uint8_t bcdDevice[2]; /* Device release number in binary-coded decimal */
uint8_t iManufacturer; /* Index of string descriptor describing manufacturer */
uint8_t iProduct; /* Index of string descriptor describing product */
uint8_t iSerialNumber; /* Index of string descriptor describing the device serial number */
uint8_t bNumConfigurations; /* Number of possible configurations */
} usb_descriptor_device_t;
typedef struct _usb_descriptor_configuration
{
uint8_t bLength; /* Descriptor size in bytes = 9U */
uint8_t bDescriptorType; /* CONFIGURATION type = 2U or 7U */
uint8_t wTotalLength[2]; /* Length of concatenated descriptors */
uint8_t bNumInterfaces; /* Number of interfaces, this configuration. */
uint8_t bConfigurationValue; /* Value to set this configuration. */
uint8_t iConfiguration; /* Index to configuration string */
uint8_t bmAttributes; /* Configuration characteristics */
uint8_t bMaxPower; /* Maximum power from bus, 2 mA units */
} usb_descriptor_configuration_t;
typedef struct _usb_descriptor_interface
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} usb_descriptor_interface_t;
typedef struct _usb_descriptor_endpoint
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint8_t wMaxPacketSize[2];
uint8_t bInterval;
} usb_descriptor_endpoint_t;
typedef struct _usb_descriptor_binary_device_object_store
{
uint8_t bLength; /* Descriptor size in bytes = 5U */
uint8_t bDescriptorType; /* BOS Descriptor type = 0FU*/
uint8_t wTotalLength[2]; /*Length of this descriptor and all of its sub descriptors*/
uint8_t bNumDeviceCaps; /*The number of separate device capability descriptors in the BOS*/
} usb_descriptor_bos_t;
typedef struct _usb_descriptor_usb20_extension
{
uint8_t bLength; /* Descriptor size in bytes = 7U */
uint8_t bDescriptorType; /* DEVICE CAPABILITY Descriptor type = 0x10U*/
uint8_t bDevCapabilityType; /*Length of this descriptor and all of its sub descriptors*/
uint8_t bmAttributes[4]; /*Bitmap encoding of supported device level features.*/
} usb_descriptor_usb20_extension_t;
typedef union _usb_descriptor_union
{
usb_descriptor_common_t common; /* Common descriptor */
usb_descriptor_device_t device; /* Device descriptor */
usb_descriptor_configuration_t configuration; /* Configuration descriptor */
usb_descriptor_interface_t interface; /* Interface descriptor */
usb_descriptor_endpoint_t endpoint; /* Endpoint descriptor */
} usb_descriptor_union_t;
#endif /* __USB_SPEC_H__ */

View File

@ -0,0 +1,240 @@
/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016 - 2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <usb/include/usb.h>
#include "fsl_device_registers.h"
#include <usb/phy/usb_phy.h>
void *USB_EhciPhyGetBase(uint8_t controllerId)
{
void *usbPhyBase = NULL;
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
uint32_t instance;
uint32_t newinstance = 0;
uint32_t usbphy_base_temp[] = USBPHY_BASE_ADDRS;
uint32_t usbphy_base[] = USBPHY_BASE_ADDRS;
if (controllerId < kUSB_ControllerEhci0)
{
return NULL;
}
controllerId = controllerId - kUSB_ControllerEhci0;
for (instance = 0; instance < (sizeof(usbphy_base_temp) / sizeof(usbphy_base_temp[0])); instance++)
{
if (usbphy_base_temp[instance])
{
usbphy_base[newinstance++] = usbphy_base_temp[instance];
}
}
if (controllerId > newinstance)
{
return NULL;
}
usbPhyBase = (void *)usbphy_base[controllerId];
#endif
return usbPhyBase;
}
/*!
* @brief ehci phy initialization.
*
* This function initialize ehci phy IP.
*
* @param[in] controllerId ehci controller id, please reference to #usb_controller_index_t.
* @param[in] freq the external input clock.
* for example: if the external input clock is 16M, the parameter freq should be 16000000.
*
* @retval kStatus_USB_Success cancel successfully.
* @retval kStatus_USB_Error the freq value is incorrect.
*/
uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
{
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
USBPHY_Type *usbPhyBase;
usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
if (NULL == usbPhyBase)
{
return kStatus_USB_Error;
}
#if ((defined FSL_FEATURE_SOC_ANATOP_COUNT) && (FSL_FEATURE_SOC_ANATOP_COUNT > 0U))
ANATOP->HW_ANADIG_REG_3P0.RW =
(ANATOP->HW_ANADIG_REG_3P0.RW &
(~(ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x1F) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_ILIMIT_MASK))) |
ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x17) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_LINREG_MASK;
ANATOP->HW_ANADIG_USB2_CHRG_DETECT.SET =
ANATOP_HW_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B_MASK | ANATOP_HW_ANADIG_USB2_CHRG_DETECT_EN_B_MASK;
#endif
#if (defined USB_ANALOG)
USB_ANALOG->INSTANCE[controllerId - kUSB_ControllerEhci0].CHRG_DETECT_SET = USB_ANALOG_CHRG_DETECT_CHK_CHRG_B(1) | USB_ANALOG_CHRG_DETECT_EN_B(1);
#endif
#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
#endif
usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
/* PWD register provides overall control of the PHY power state */
usbPhyBase->PWD = 0U;
/* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
usbPhyBase->TX =
((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
(USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
#endif
return kStatus_USB_Success;
}
/*!
* @brief ehci phy initialization for suspend and resume.
*
* This function initialize ehci phy IP for suspend and resume.
*
* @param[in] controllerId ehci controller id, please reference to #usb_controller_index_t.
* @param[in] freq the external input clock.
* for example: if the external input clock is 16M, the parameter freq should be 16000000.
*
* @retval kStatus_USB_Success cancel successfully.
* @retval kStatus_USB_Error the freq value is incorrect.
*/
uint32_t USB_EhciLowPowerPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
{
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
USBPHY_Type *usbPhyBase;
usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
if (NULL == usbPhyBase)
{
return kStatus_USB_Error;
}
#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
#endif
#if ((defined USBPHY_CTRL_AUTORESUME_EN_MASK) && (USBPHY_CTRL_AUTORESUME_EN_MASK > 0U))
usbPhyBase->CTRL |= USBPHY_CTRL_AUTORESUME_EN_MASK;
#else
usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTO_PWRON_PLL_MASK;
#endif
usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK;
usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
/* PWD register provides overall control of the PHY power state */
usbPhyBase->PWD = 0U;
#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
/* now the 480MHz USB clock is up, then configure fractional divider after PLL with PFD
* pfd clock = 480MHz*18/N, where N=18~35
* Please note that USB1PFDCLK has to be less than 180MHz for RUN or HSRUN mode
*/
usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_FRAC(24); /* N=24 */
usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_CLK_SEL(1); /* div by 4 */
usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_DEV_PULLDOWN_MASK;
usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK;
while (!(usbPhyBase->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK))
{
}
#endif
/* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
usbPhyBase->TX =
((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
(USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
#endif
return kStatus_USB_Success;
}
/*!
* @brief ehci phy de-initialization.
*
* This function de-initialize ehci phy IP.
*
* @param[in] controllerId ehci controller id, please reference to #usb_controller_index_t.
*/
void USB_EhciPhyDeinit(uint8_t controllerId)
{
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
USBPHY_Type *usbPhyBase;
usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
if (NULL == usbPhyBase)
{
return;
}
#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK; /* power down PLL */
usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* disable USB clock output from USB PHY PLL */
#endif
usbPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* set to 1U to gate clocks */
#endif
}
/*!
* @brief ehci phy disconnect detection enable or disable.
*
* This function enable/disable host ehci disconnect detection.
*
* @param[in] controllerId ehci controller id, please reference to #usb_controller_index_t.
* @param[in] enable
* 1U - enable;
* 0U - disable;
*/
void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable)
{
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
USBPHY_Type *usbPhyBase;
usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
if (NULL == usbPhyBase)
{
return;
}
if (enable)
{
usbPhyBase->CTRL |= USBPHY_CTRL_ENHOSTDISCONDETECT_MASK;
}
else
{
usbPhyBase->CTRL &= (~USBPHY_CTRL_ENHOSTDISCONDETECT_MASK);
}
#endif
}

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016 - 2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __USB_PHY_H__
#define __USB_PHY_H__
/*******************************************************************************
* Definitions
******************************************************************************/
typedef struct _usb_phy_config_struct
{
uint8_t D_CAL; /* Decode to trim the nominal 17.78mA current source */
uint8_t TXCAL45DP; /* Decode to trim the nominal 45-Ohm series termination resistance to the USB_DP output pin */
uint8_t TXCAL45DM; /* Decode to trim the nominal 45-Ohm series termination resistance to the USB_DM output pin */
} usb_phy_config_struct_t;
#if defined(__cplusplus)
extern "C" {
#endif
/*******************************************************************************
* API
******************************************************************************/
/*!
* @brief EHCI PHY get USB phy bass address.
*
* This function is used to get USB phy bass address.
*
* @param[in] controllerId EHCI controller ID; See the #usb_controller_index_t.
*
* @retval USB phy bass address.
*/
extern void *USB_EhciPhyGetBase(uint8_t controllerId);
/*!
* @brief EHCI PHY initialization.
*
* This function initializes the EHCI PHY IP.
*
* @param[in] controllerId EHCI controller ID; See the #usb_controller_index_t.
* @param[in] freq The external input clock.
*
* @retval kStatus_USB_Success Cancel successfully.
* @retval kStatus_USB_Error The freq value is incorrect.
*/
extern uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig);
/*!
* @brief ehci phy initialization for suspend and resume.
*
* This function initialize ehci phy IP for suspend and resume.
*
* @param[in] controllerId ehci controller id, please reference to #usb_controller_index_t.
* @param[in] freq the external input clock.
* for example: if the external input clock is 16M, the parameter freq should be 16000000.
*
* @retval kStatus_USB_Success cancel successfully.
* @retval kStatus_USB_Error the freq value is incorrect.
*/
extern uint32_t USB_EhciLowPowerPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig);
/*!
* @brief EHCI PHY deinitialization.
*
* This function deinitializes the EHCI PHY IP.
*
* @param[in] controllerId EHCI controller ID; See #usb_controller_index_t.
*/
extern void USB_EhciPhyDeinit(uint8_t controllerId);
/*!
* @brief EHCI PHY disconnect detection enable or disable.
*
* This function enable/disable the host EHCI disconnect detection.
*
* @param[in] controllerId EHCI controller ID; See #usb_controller_index_t.
* @param[in] enable
* 1U - enable;
* 0U - disable;
*/
extern void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable);
#if defined(__cplusplus)
}
#endif
#endif /* __USB_PHY_H__ */

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

View File

@ -0,0 +1,15 @@
# RT-Thread building script for bridge
import os
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
from building import *
cwd = GetCurrentDir()
src = []
path = [cwd + '/Include']
group = DefineGroup('libraries', src, depend = [''], CPPPATH = path)
Return('group')

View File

@ -0,0 +1,50 @@
/* Copyright (c) 2009 - 2015 ARM LIMITED
Copyright (c) 2016, Freescale Semiconductor, Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CORE_CA_H
#define __CORE_CA_H
/*------------------ GNU Compiler ----------------------*/
#if defined ( __GNUC__ )
#include "cortexa_gcc.h"
/*------------------ ICC Compiler ----------------------*/
#elif defined ( __ICCARM__ )
#include "cortexa_iar.h"
#endif
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
#endif /* __CORE_CA_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __CORTEXA_GCC_H
#define __CORTEXA_GCC_H
#include "cmsis_gcc.h"
#define __STRINGIFY(x) #x
#define __MCR(coproc, opcode_1, src, CRn, CRm, opcode_2) \
__ASM volatile ("MCR " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \
"%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " \
__STRINGIFY(opcode_2) \
: : "r" (src) )
#define __MRC(coproc, opcode_1, CRn, CRm, opcode_2) \
({ \
uint32_t __dst; \
__ASM volatile ("MRC " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \
"%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " \
__STRINGIFY(opcode_2) \
: "=r" (__dst) ); \
__dst; \
})
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_APSR(uint32_t apsr)
{
__ASM volatile ("MSR apsr, %0" : : "r" (apsr) : "cc");
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, cpsr" : "=r" (result) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
{
__ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc");
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPEXC(void)
{
uint32_t result;
__ASM volatile ("VMRS %0, fpexc" : "=r" (result) );
return result;
}
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
{
__ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc));
}
#endif /* __CORTEXA_GCC_H */

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __CORTEXA_IAR_H
#define __CORTEXA_IAR_H
#ifdef __cplusplus
/* FIXME: work around the IAR CPP compiling issue in Cortex-A support */
#define __get_PSR() 0
#endif
#include <cmsis_iar.h>
static inline uint32_t __get_FPEXC(void)
{
uint32_t result;
__ASM volatile ("VMRS %0, fpexc" : "=r" (result) );
return result;
}
static inline void __set_FPEXC(uint32_t fpexc)
{
__ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc));
}
#endif /* __CORTEXA_IAR_H */

View File

@ -0,0 +1,10 @@
from building import *
cwd = GetCurrentDir()
src = []
path = [cwd + '/Include']
group = DefineGroup('libraries', src, depend = [''], CPPPATH = path)
Return('group')

View File

@ -0,0 +1,15 @@
# RT-Thread building script for bridge
import os
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')

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,801 @@
/*
** ###################################################################
** Version: rev. 3.0, 2017-02-28
** Build: b170422
**
** Abstract:
** Chip specific module features.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2017 NXP
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
**
** o Redistributions of source code must retain the above copyright notice, this list
** of conditions and the following disclaimer.
**
** o Redistributions in binary form must reproduce the above copyright notice, this
** list of conditions and the following disclaimer in the documentation and/or
** other materials provided with the distribution.
**
** o Neither the name of the copyright holder nor the names of its
** contributors may be used to endorse or promote products derived from this
** software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 1.0 (2015-12-18)
** Initial version.
** - rev. 2.0 (2016-08-02)
** Rev.B Header GA
** - rev. 3.0 (2017-02-28)
** Rev.1 Header GA
**
** ###################################################################
*/
#ifndef _MCIMX6Y2_FEATURES_H_
#define _MCIMX6Y2_FEATURES_H_
/* SOC module features */
/* @brief ACMP availability on the SoC. */
#define FSL_FEATURE_SOC_ACMP_COUNT (0)
/* @brief ADC availability on the SoC. */
#define FSL_FEATURE_SOC_ADC_COUNT (1)
/* @brief ADC12 availability on the SoC. */
#define FSL_FEATURE_SOC_ADC12_COUNT (0)
/* @brief ADC16 availability on the SoC. */
#define FSL_FEATURE_SOC_ADC16_COUNT (0)
/* @brief ADC_5HC availability on the SoC. */
#define FSL_FEATURE_SOC_ADC_5HC_COUNT (1)
/* @brief AES availability on the SoC. */
#define FSL_FEATURE_SOC_AES_COUNT (0)
/* @brief AFE availability on the SoC. */
#define FSL_FEATURE_SOC_AFE_COUNT (0)
/* @brief AGC availability on the SoC. */
#define FSL_FEATURE_SOC_AGC_COUNT (0)
/* @brief AIPS availability on the SoC. */
#define FSL_FEATURE_SOC_AIPS_COUNT (0)
/* @brief AIPSTZ availability on the SoC. */
#define FSL_FEATURE_SOC_AIPSTZ_COUNT (3)
/* @brief ANATOP availability on the SoC. */
#define FSL_FEATURE_SOC_ANATOP_COUNT (0)
/* @brief AOI availability on the SoC. */
#define FSL_FEATURE_SOC_AOI_COUNT (0)
/* @brief APBH availability on the SoC. */
#define FSL_FEATURE_SOC_APBH_COUNT (1)
/* @brief ASMC availability on the SoC. */
#define FSL_FEATURE_SOC_ASMC_COUNT (0)
/* @brief ASRC availability on the SoC. */
#define FSL_FEATURE_SOC_ASRC_COUNT (1)
/* @brief ASYNC_SYSCON availability on the SoC. */
#define FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT (0)
/* @brief ATX availability on the SoC. */
#define FSL_FEATURE_SOC_ATX_COUNT (0)
/* @brief AXBS availability on the SoC. */
#define FSL_FEATURE_SOC_AXBS_COUNT (0)
/* @brief BCH availability on the SoC. */
#define FSL_FEATURE_SOC_BCH_COUNT (1)
/* @brief BLEDP availability on the SoC. */
#define FSL_FEATURE_SOC_BLEDP_COUNT (0)
/* @brief BOD availability on the SoC. */
#define FSL_FEATURE_SOC_BOD_COUNT (0)
/* @brief CAAM availability on the SoC. */
#define FSL_FEATURE_SOC_CAAM_COUNT (0)
/* @brief CADC availability on the SoC. */
#define FSL_FEATURE_SOC_CADC_COUNT (0)
/* @brief CALIB availability on the SoC. */
#define FSL_FEATURE_SOC_CALIB_COUNT (0)
/* @brief CAN availability on the SoC. */
#define FSL_FEATURE_SOC_CAN_COUNT (0)
/* @brief CAU availability on the SoC. */
#define FSL_FEATURE_SOC_CAU_COUNT (0)
/* @brief CAU3 availability on the SoC. */
#define FSL_FEATURE_SOC_CAU3_COUNT (0)
/* @brief CCM availability on the SoC. */
#define FSL_FEATURE_SOC_CCM_COUNT (1)
/* @brief CCM_ANALOG availability on the SoC. */
#define FSL_FEATURE_SOC_CCM_ANALOG_COUNT (1)
/* @brief CHRG availability on the SoC. */
#define FSL_FEATURE_SOC_CHRG_COUNT (0)
/* @brief CMP availability on the SoC. */
#define FSL_FEATURE_SOC_CMP_COUNT (0)
/* @brief CMT availability on the SoC. */
#define FSL_FEATURE_SOC_CMT_COUNT (0)
/* @brief CNC availability on the SoC. */
#define FSL_FEATURE_SOC_CNC_COUNT (0)
/* @brief COP availability on the SoC. */
#define FSL_FEATURE_SOC_COP_COUNT (0)
/* @brief CRC availability on the SoC. */
#define FSL_FEATURE_SOC_CRC_COUNT (0)
/* @brief CS availability on the SoC. */
#define FSL_FEATURE_SOC_CS_COUNT (0)
/* @brief CSI availability on the SoC. */
#define FSL_FEATURE_SOC_CSI_COUNT (1)
/* @brief CT32B availability on the SoC. */
#define FSL_FEATURE_SOC_CT32B_COUNT (0)
/* @brief CTI availability on the SoC. */
#define FSL_FEATURE_SOC_CTI_COUNT (0)
/* @brief CTIMER availability on the SoC. */
#define FSL_FEATURE_SOC_CTIMER_COUNT (0)
/* @brief DAC availability on the SoC. */
#define FSL_FEATURE_SOC_DAC_COUNT (0)
/* @brief DAC32 availability on the SoC. */
#define FSL_FEATURE_SOC_DAC32_COUNT (0)
/* @brief DCDC availability on the SoC. */
#define FSL_FEATURE_SOC_DCDC_COUNT (0)
/* @brief DCP availability on the SoC. */
#define FSL_FEATURE_SOC_DCP_COUNT (1)
/* @brief DDR availability on the SoC. */
#define FSL_FEATURE_SOC_DDR_COUNT (0)
/* @brief DDRC availability on the SoC. */
#define FSL_FEATURE_SOC_DDRC_COUNT (0)
/* @brief DDRC_MP availability on the SoC. */
#define FSL_FEATURE_SOC_DDRC_MP_COUNT (0)
/* @brief DDR_PHY availability on the SoC. */
#define FSL_FEATURE_SOC_DDR_PHY_COUNT (0)
/* @brief DMA availability on the SoC. */
#define FSL_FEATURE_SOC_DMA_COUNT (0)
/* @brief DMAMUX availability on the SoC. */
#define FSL_FEATURE_SOC_DMAMUX_COUNT (0)
/* @brief DMIC availability on the SoC. */
#define FSL_FEATURE_SOC_DMIC_COUNT (0)
/* @brief DRY availability on the SoC. */
#define FSL_FEATURE_SOC_DRY_COUNT (0)
/* @brief DSPI availability on the SoC. */
#define FSL_FEATURE_SOC_DSPI_COUNT (0)
/* @brief ECSPI availability on the SoC. */
#define FSL_FEATURE_SOC_ECSPI_COUNT (4)
/* @brief EDMA availability on the SoC. */
#define FSL_FEATURE_SOC_EDMA_COUNT (0)
/* @brief EEPROM availability on the SoC. */
#define FSL_FEATURE_SOC_EEPROM_COUNT (0)
/* @brief EIM availability on the SoC. */
#define FSL_FEATURE_SOC_EIM_COUNT (1)
/* @brief EMC availability on the SoC. */
#define FSL_FEATURE_SOC_EMC_COUNT (0)
/* @brief EMVSIM availability on the SoC. */
#define FSL_FEATURE_SOC_EMVSIM_COUNT (0)
/* @brief ENC availability on the SoC. */
#define FSL_FEATURE_SOC_ENC_COUNT (0)
/* @brief ENET availability on the SoC. */
#define FSL_FEATURE_SOC_ENET_COUNT (2)
/* @brief EPDC availability on the SoC. */
#define FSL_FEATURE_SOC_EPDC_COUNT (0)
/* @brief EPIT availability on the SoC. */
#define FSL_FEATURE_SOC_EPIT_COUNT (2)
/* @brief ESAI availability on the SoC. */
#define FSL_FEATURE_SOC_ESAI_COUNT (1)
/* @brief EWM availability on the SoC. */
#define FSL_FEATURE_SOC_EWM_COUNT (0)
/* @brief FB availability on the SoC. */
#define FSL_FEATURE_SOC_FB_COUNT (0)
/* @brief FGPIO availability on the SoC. */
#define FSL_FEATURE_SOC_FGPIO_COUNT (0)
/* @brief FLASH availability on the SoC. */
#define FSL_FEATURE_SOC_FLASH_COUNT (0)
/* @brief FLEXCAN availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXCAN_COUNT (2)
/* @brief FLEXCOMM availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXCOMM_COUNT (0)
/* @brief FLEXIO availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXIO_COUNT (0)
/* @brief FLEXRAM availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXRAM_COUNT (0)
/* @brief FLEXSPI availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXSPI_COUNT (0)
/* @brief FMC availability on the SoC. */
#define FSL_FEATURE_SOC_FMC_COUNT (0)
/* @brief FSKDT availability on the SoC. */
#define FSL_FEATURE_SOC_FSKDT_COUNT (0)
/* @brief FSP availability on the SoC. */
#define FSL_FEATURE_SOC_FSP_COUNT (0)
/* @brief FTFA availability on the SoC. */
#define FSL_FEATURE_SOC_FTFA_COUNT (0)
/* @brief FTFE availability on the SoC. */
#define FSL_FEATURE_SOC_FTFE_COUNT (0)
/* @brief FTFL availability on the SoC. */
#define FSL_FEATURE_SOC_FTFL_COUNT (0)
/* @brief FTM availability on the SoC. */
#define FSL_FEATURE_SOC_FTM_COUNT (0)
/* @brief FTMRA availability on the SoC. */
#define FSL_FEATURE_SOC_FTMRA_COUNT (0)
/* @brief FTMRE availability on the SoC. */
#define FSL_FEATURE_SOC_FTMRE_COUNT (0)
/* @brief FTMRH availability on the SoC. */
#define FSL_FEATURE_SOC_FTMRH_COUNT (0)
/* @brief GINT availability on the SoC. */
#define FSL_FEATURE_SOC_GINT_COUNT (0)
/* @brief GPC availability on the SoC. */
#define FSL_FEATURE_SOC_GPC_COUNT (1)
/* @brief GPC_PGC availability on the SoC. */
#define FSL_FEATURE_SOC_GPC_PGC_COUNT (0)
/* @brief GPIO availability on the SoC. */
#define FSL_FEATURE_SOC_GPIO_COUNT (0)
/* @brief GPMI availability on the SoC. */
#define FSL_FEATURE_SOC_GPMI_COUNT (1)
/* @brief GPT availability on the SoC. */
#define FSL_FEATURE_SOC_GPT_COUNT (2)
/* @brief HSADC availability on the SoC. */
#define FSL_FEATURE_SOC_HSADC_COUNT (0)
/* @brief I2C availability on the SoC. */
#define FSL_FEATURE_SOC_I2C_COUNT (0)
/* @brief I2S availability on the SoC. */
#define FSL_FEATURE_SOC_I2S_COUNT (3)
/* @brief ICS availability on the SoC. */
#define FSL_FEATURE_SOC_ICS_COUNT (0)
/* @brief IEE availability on the SoC. */
#define FSL_FEATURE_SOC_IEE_COUNT (0)
/* @brief IEER availability on the SoC. */
#define FSL_FEATURE_SOC_IEER_COUNT (0)
/* @brief IGPIO availability on the SoC. */
#define FSL_FEATURE_SOC_IGPIO_COUNT (5)
/* @brief II2C availability on the SoC. */
#define FSL_FEATURE_SOC_II2C_COUNT (4)
/* @brief INPUTMUX availability on the SoC. */
#define FSL_FEATURE_SOC_INPUTMUX_COUNT (0)
/* @brief INTMUX availability on the SoC. */
#define FSL_FEATURE_SOC_INTMUX_COUNT (0)
/* @brief IOCON availability on the SoC. */
#define FSL_FEATURE_SOC_IOCON_COUNT (0)
/* @brief IOMUXC availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_COUNT (1)
/* @brief IOMUXC_GPR availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_GPR_COUNT (1)
/* @brief IOMUXC_LPSR availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_LPSR_COUNT (0)
/* @brief IOMUXC_LPSR_GPR availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_LPSR_GPR_COUNT (0)
/* @brief IOMUXC_SNVS availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_SNVS_COUNT (1)
/* @brief IPWM availability on the SoC. */
#define FSL_FEATURE_SOC_IPWM_COUNT (8)
/* @brief IRQ availability on the SoC. */
#define FSL_FEATURE_SOC_IRQ_COUNT (0)
/* @brief IUART availability on the SoC. */
#define FSL_FEATURE_SOC_IUART_COUNT (8)
/* @brief KBI availability on the SoC. */
#define FSL_FEATURE_SOC_KBI_COUNT (0)
/* @brief KPP availability on the SoC. */
#define FSL_FEATURE_SOC_KPP_COUNT (1)
/* @brief L2CACHEC availability on the SoC. */
#define FSL_FEATURE_SOC_L2CACHEC_COUNT (0)
/* @brief LCD availability on the SoC. */
#define FSL_FEATURE_SOC_LCD_COUNT (0)
/* @brief LCDC availability on the SoC. */
#define FSL_FEATURE_SOC_LCDC_COUNT (0)
/* @brief LCDIF availability on the SoC. */
#define FSL_FEATURE_SOC_LCDIF_COUNT (1)
/* @brief LDO availability on the SoC. */
#define FSL_FEATURE_SOC_LDO_COUNT (0)
/* @brief LLWU availability on the SoC. */
#define FSL_FEATURE_SOC_LLWU_COUNT (0)
/* @brief LMEM availability on the SoC. */
#define FSL_FEATURE_SOC_LMEM_COUNT (0)
/* @brief LPADC availability on the SoC. */
#define FSL_FEATURE_SOC_LPADC_COUNT (0)
/* @brief LPCMP availability on the SoC. */
#define FSL_FEATURE_SOC_LPCMP_COUNT (0)
/* @brief LPDAC availability on the SoC. */
#define FSL_FEATURE_SOC_LPDAC_COUNT (0)
/* @brief LPI2C availability on the SoC. */
#define FSL_FEATURE_SOC_LPI2C_COUNT (0)
/* @brief LPIT availability on the SoC. */
#define FSL_FEATURE_SOC_LPIT_COUNT (0)
/* @brief LPSCI availability on the SoC. */
#define FSL_FEATURE_SOC_LPSCI_COUNT (0)
/* @brief LPSPI availability on the SoC. */
#define FSL_FEATURE_SOC_LPSPI_COUNT (0)
/* @brief LPTMR availability on the SoC. */
#define FSL_FEATURE_SOC_LPTMR_COUNT (0)
/* @brief LPTPM availability on the SoC. */
#define FSL_FEATURE_SOC_LPTPM_COUNT (0)
/* @brief LPUART availability on the SoC. */
#define FSL_FEATURE_SOC_LPUART_COUNT (0)
/* @brief LTC availability on the SoC. */
#define FSL_FEATURE_SOC_LTC_COUNT (0)
/* @brief MAILBOX availability on the SoC. */
#define FSL_FEATURE_SOC_MAILBOX_COUNT (0)
/* @brief MC availability on the SoC. */
#define FSL_FEATURE_SOC_MC_COUNT (0)
/* @brief MCG availability on the SoC. */
#define FSL_FEATURE_SOC_MCG_COUNT (0)
/* @brief MCGLITE availability on the SoC. */
#define FSL_FEATURE_SOC_MCGLITE_COUNT (0)
/* @brief MCM availability on the SoC. */
#define FSL_FEATURE_SOC_MCM_COUNT (0)
/* @brief MIPI_CSI2 availability on the SoC. */
#define FSL_FEATURE_SOC_MIPI_CSI2_COUNT (0)
/* @brief MIPI_DSI availability on the SoC. */
#define FSL_FEATURE_SOC_MIPI_DSI_COUNT (0)
/* @brief MIPI_DSI_HOST availability on the SoC. */
#define FSL_FEATURE_SOC_MIPI_DSI_HOST_COUNT (0)
/* @brief MMAU availability on the SoC. */
#define FSL_FEATURE_SOC_MMAU_COUNT (0)
/* @brief MMCAU availability on the SoC. */
#define FSL_FEATURE_SOC_MMCAU_COUNT (0)
/* @brief MMDC availability on the SoC. */
#define FSL_FEATURE_SOC_MMDC_COUNT (1)
/* @brief MMDVSQ availability on the SoC. */
#define FSL_FEATURE_SOC_MMDVSQ_COUNT (0)
/* @brief MPU availability on the SoC. */
#define FSL_FEATURE_SOC_MPU_COUNT (0)
/* @brief MRT availability on the SoC. */
#define FSL_FEATURE_SOC_MRT_COUNT (0)
/* @brief MSCAN availability on the SoC. */
#define FSL_FEATURE_SOC_MSCAN_COUNT (0)
/* @brief MSCM availability on the SoC. */
#define FSL_FEATURE_SOC_MSCM_COUNT (0)
/* @brief MTB availability on the SoC. */
#define FSL_FEATURE_SOC_MTB_COUNT (0)
/* @brief MTBDWT availability on the SoC. */
#define FSL_FEATURE_SOC_MTBDWT_COUNT (0)
/* @brief MU availability on the SoC. */
#define FSL_FEATURE_SOC_MU_COUNT (0)
/* @brief NFC availability on the SoC. */
#define FSL_FEATURE_SOC_NFC_COUNT (0)
/* @brief OCOTP availability on the SoC. */
#define FSL_FEATURE_SOC_OCOTP_COUNT (1)
/* @brief OPAMP availability on the SoC. */
#define FSL_FEATURE_SOC_OPAMP_COUNT (0)
/* @brief OSC availability on the SoC. */
#define FSL_FEATURE_SOC_OSC_COUNT (0)
/* @brief OSC32 availability on the SoC. */
#define FSL_FEATURE_SOC_OSC32_COUNT (0)
/* @brief OTFAD availability on the SoC. */
#define FSL_FEATURE_SOC_OTFAD_COUNT (0)
/* @brief PCC availability on the SoC. */
#define FSL_FEATURE_SOC_PCC_COUNT (0)
/* @brief PCIE_PHY_CMN availability on the SoC. */
#define FSL_FEATURE_SOC_PCIE_PHY_CMN_COUNT (0)
/* @brief PCIE_PHY_TRSV availability on the SoC. */
#define FSL_FEATURE_SOC_PCIE_PHY_TRSV_COUNT (0)
/* @brief PDB availability on the SoC. */
#define FSL_FEATURE_SOC_PDB_COUNT (0)
/* @brief PGA availability on the SoC. */
#define FSL_FEATURE_SOC_PGA_COUNT (0)
/* @brief PINT availability on the SoC. */
#define FSL_FEATURE_SOC_PINT_COUNT (0)
/* @brief PIT availability on the SoC. */
#define FSL_FEATURE_SOC_PIT_COUNT (0)
/* @brief PMC availability on the SoC. */
#define FSL_FEATURE_SOC_PMC_COUNT (0)
/* @brief PMU availability on the SoC. */
#define FSL_FEATURE_SOC_PMU_COUNT (1)
/* @brief PORT availability on the SoC. */
#define FSL_FEATURE_SOC_PORT_COUNT (0)
/* @brief PROP availability on the SoC. */
#define FSL_FEATURE_SOC_PROP_COUNT (0)
/* @brief PWM availability on the SoC. */
#define FSL_FEATURE_SOC_PWM_COUNT (0)
/* @brief PWT availability on the SoC. */
#define FSL_FEATURE_SOC_PWT_COUNT (0)
/* @brief PXP availability on the SoC. */
#define FSL_FEATURE_SOC_PXP_COUNT (1)
/* @brief QDEC availability on the SoC. */
#define FSL_FEATURE_SOC_QDEC_COUNT (0)
/* @brief QuadSPI availability on the SoC. */
#define FSL_FEATURE_SOC_QuadSPI_COUNT (1)
/* @brief RCM availability on the SoC. */
#define FSL_FEATURE_SOC_RCM_COUNT (0)
/* @brief RDC availability on the SoC. */
#define FSL_FEATURE_SOC_RDC_COUNT (0)
/* @brief RDC_SEMAPHORE availability on the SoC. */
#define FSL_FEATURE_SOC_RDC_SEMAPHORE_COUNT (0)
/* @brief RFSYS availability on the SoC. */
#define FSL_FEATURE_SOC_RFSYS_COUNT (0)
/* @brief RFVBAT availability on the SoC. */
#define FSL_FEATURE_SOC_RFVBAT_COUNT (0)
/* @brief RIT availability on the SoC. */
#define FSL_FEATURE_SOC_RIT_COUNT (0)
/* @brief RNG availability on the SoC. */
#define FSL_FEATURE_SOC_RNG_COUNT (1)
/* @brief RNGB availability on the SoC. */
#define FSL_FEATURE_SOC_RNGB_COUNT (0)
/* @brief ROM availability on the SoC. */
#define FSL_FEATURE_SOC_ROM_COUNT (0)
/* @brief ROMC availability on the SoC. */
#define FSL_FEATURE_SOC_ROMC_COUNT (1)
/* @brief RSIM availability on the SoC. */
#define FSL_FEATURE_SOC_RSIM_COUNT (0)
/* @brief RTC availability on the SoC. */
#define FSL_FEATURE_SOC_RTC_COUNT (0)
/* @brief SCG availability on the SoC. */
#define FSL_FEATURE_SOC_SCG_COUNT (0)
/* @brief SCI availability on the SoC. */
#define FSL_FEATURE_SOC_SCI_COUNT (0)
/* @brief SCT availability on the SoC. */
#define FSL_FEATURE_SOC_SCT_COUNT (0)
/* @brief SDHC availability on the SoC. */
#define FSL_FEATURE_SOC_SDHC_COUNT (0)
/* @brief SDIF availability on the SoC. */
#define FSL_FEATURE_SOC_SDIF_COUNT (0)
/* @brief SDIO availability on the SoC. */
#define FSL_FEATURE_SOC_SDIO_COUNT (0)
/* @brief SDMA availability on the SoC. */
#define FSL_FEATURE_SOC_SDMA_COUNT (1)
/* @brief SDMAARM availability on the SoC. */
#define FSL_FEATURE_SOC_SDMAARM_COUNT (0)
/* @brief SDMABP availability on the SoC. */
#define FSL_FEATURE_SOC_SDMABP_COUNT (0)
/* @brief SDMACORE availability on the SoC. */
#define FSL_FEATURE_SOC_SDMACORE_COUNT (0)
/* @brief SDMCORE availability on the SoC. */
#define FSL_FEATURE_SOC_SDMCORE_COUNT (0)
/* @brief SDRAM availability on the SoC. */
#define FSL_FEATURE_SOC_SDRAM_COUNT (0)
/* @brief SEMA4 availability on the SoC. */
#define FSL_FEATURE_SOC_SEMA4_COUNT (0)
/* @brief SEMA42 availability on the SoC. */
#define FSL_FEATURE_SOC_SEMA42_COUNT (0)
/* @brief SHA availability on the SoC. */
#define FSL_FEATURE_SOC_SHA_COUNT (0)
/* @brief SIM availability on the SoC. */
#define FSL_FEATURE_SOC_SIM_COUNT (0)
/* @brief SIMDGO availability on the SoC. */
#define FSL_FEATURE_SOC_SIMDGO_COUNT (0)
/* @brief SJC availability on the SoC. */
#define FSL_FEATURE_SOC_SJC_COUNT (0)
/* @brief SLCD availability on the SoC. */
#define FSL_FEATURE_SOC_SLCD_COUNT (0)
/* @brief SMARTCARD availability on the SoC. */
#define FSL_FEATURE_SOC_SMARTCARD_COUNT (0)
/* @brief SMC availability on the SoC. */
#define FSL_FEATURE_SOC_SMC_COUNT (0)
/* @brief SNVS availability on the SoC. */
#define FSL_FEATURE_SOC_SNVS_COUNT (1)
/* @brief SPBA availability on the SoC. */
#define FSL_FEATURE_SOC_SPBA_COUNT (1)
/* @brief SPDIF availability on the SoC. */
#define FSL_FEATURE_SOC_SPDIF_COUNT (1)
/* @brief SPI availability on the SoC. */
#define FSL_FEATURE_SOC_SPI_COUNT (0)
/* @brief SPIFI availability on the SoC. */
#define FSL_FEATURE_SOC_SPIFI_COUNT (0)
/* @brief SPM availability on the SoC. */
#define FSL_FEATURE_SOC_SPM_COUNT (0)
/* @brief SRC availability on the SoC. */
#define FSL_FEATURE_SOC_SRC_COUNT (1)
/* @brief SYSCON availability on the SoC. */
#define FSL_FEATURE_SOC_SYSCON_COUNT (0)
/* @brief TEMPMON availability on the SoC. */
#define FSL_FEATURE_SOC_TEMPMON_COUNT (1)
/* @brief TMR availability on the SoC. */
#define FSL_FEATURE_SOC_TMR_COUNT (0)
/* @brief TPM availability on the SoC. */
#define FSL_FEATURE_SOC_TPM_COUNT (0)
/* @brief TRGMUX availability on the SoC. */
#define FSL_FEATURE_SOC_TRGMUX_COUNT (0)
/* @brief TRIAMP availability on the SoC. */
#define FSL_FEATURE_SOC_TRIAMP_COUNT (0)
/* @brief TRNG availability on the SoC. */
#define FSL_FEATURE_SOC_TRNG_COUNT (0)
/* @brief TSC availability on the SoC. */
#define FSL_FEATURE_SOC_TSC_COUNT (1)
/* @brief TSI availability on the SoC. */
#define FSL_FEATURE_SOC_TSI_COUNT (0)
/* @brief TSTMR availability on the SoC. */
#define FSL_FEATURE_SOC_TSTMR_COUNT (0)
/* @brief UART availability on the SoC. */
#define FSL_FEATURE_SOC_UART_COUNT (0)
/* @brief USART availability on the SoC. */
#define FSL_FEATURE_SOC_USART_COUNT (0)
/* @brief USB availability on the SoC. */
#define FSL_FEATURE_SOC_USB_COUNT (0)
/* @brief USBHS availability on the SoC. */
#define FSL_FEATURE_SOC_USBHS_COUNT (2)
/* @brief USBDCD availability on the SoC. */
#define FSL_FEATURE_SOC_USBDCD_COUNT (0)
/* @brief USBFSH availability on the SoC. */
#define FSL_FEATURE_SOC_USBFSH_COUNT (0)
/* @brief USBHSD availability on the SoC. */
#define FSL_FEATURE_SOC_USBHSD_COUNT (0)
/* @brief USBHSDCD availability on the SoC. */
#define FSL_FEATURE_SOC_USBHSDCD_COUNT (0)
/* @brief USBHSH availability on the SoC. */
#define FSL_FEATURE_SOC_USBHSH_COUNT (0)
/* @brief USBNC availability on the SoC. */
#define FSL_FEATURE_SOC_USBNC_COUNT (2)
/* @brief USBPHY availability on the SoC. */
#define FSL_FEATURE_SOC_USBPHY_COUNT (2)
/* @brief USB_HSIC availability on the SoC. */
#define FSL_FEATURE_SOC_USB_HSIC_COUNT (0)
/* @brief USB_OTG availability on the SoC. */
#define FSL_FEATURE_SOC_USB_OTG_COUNT (0)
/* @brief USDHC availability on the SoC. */
#define FSL_FEATURE_SOC_USDHC_COUNT (2)
/* @brief UTICK availability on the SoC. */
#define FSL_FEATURE_SOC_UTICK_COUNT (0)
/* @brief VIU availability on the SoC. */
#define FSL_FEATURE_SOC_VIU_COUNT (0)
/* @brief VREF availability on the SoC. */
#define FSL_FEATURE_SOC_VREF_COUNT (0)
/* @brief VFIFO availability on the SoC. */
#define FSL_FEATURE_SOC_VFIFO_COUNT (0)
/* @brief WDOG availability on the SoC. */
#define FSL_FEATURE_SOC_WDOG_COUNT (3)
/* @brief WKPU availability on the SoC. */
#define FSL_FEATURE_SOC_WKPU_COUNT (0)
/* @brief WWDT availability on the SoC. */
#define FSL_FEATURE_SOC_WWDT_COUNT (0)
/* @brief XBAR availability on the SoC. */
#define FSL_FEATURE_SOC_XBAR_COUNT (0)
/* @brief XBARA availability on the SoC. */
#define FSL_FEATURE_SOC_XBARA_COUNT (0)
/* @brief XBARB availability on the SoC. */
#define FSL_FEATURE_SOC_XBARB_COUNT (0)
/* @brief XCVR availability on the SoC. */
#define FSL_FEATURE_SOC_XCVR_COUNT (0)
/* @brief XRDC availability on the SoC. */
#define FSL_FEATURE_SOC_XRDC_COUNT (0)
/* @brief XTALOSC availability on the SoC. */
#define FSL_FEATURE_SOC_XTALOSC_COUNT (0)
/* @brief XTALOSC24M availability on the SoC. */
#define FSL_FEATURE_SOC_XTALOSC24M_COUNT (1)
/* @brief ZLL availability on the SoC. */
#define FSL_FEATURE_SOC_ZLL_COUNT (0)
/* ADC module features */
/* @brief Remove Hardware Trigger feature. */
#define FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE (1)
/* @brief Remove ALT Clock selection feature. */
#define FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE (1)
/* CACHEC module features */
/* @brief L1 ICACHE line size in byte. */
#define FSL_FEATURE_L1ICACHE_LINESIZE_BYTE (32)
/* @brief L1 DCACHE line size in byte. */
#define FSL_FEATURE_L1DCACHE_LINESIZE_BYTE (64)
/* FLEXCAN module features */
/* @brief Message buffer size */
#define FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(x) (64)
/* @brief Has doze mode support (register bit field MCR[DOZE]). */
#define FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT (0)
/* @brief Has a glitch filter on the receive pin (register bit field MCR[WAKSRC]). */
#define FSL_FEATURE_FLEXCAN_HAS_GLITCH_FILTER (1)
/* @brief Has extended interrupt mask and flag register (register IMASK2, IFLAG2). */
#define FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER (1)
/* @brief Has extended bit timing register (register CBT). */
#define FSL_FEATURE_FLEXCAN_HAS_EXTENDED_TIMING_REGISTER (0)
/* @brief Has a receive FIFO DMA feature (register bit field MCR[DMA]). */
#define FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA (0)
/* @brief Remove CAN Engine Clock Source Selection from unsupported part. */
#define FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE (1)
/* @brief Is affected by errata with ID 5641 (Module does not transmit a message that is enabled to be transmitted at a specific moment during the arbitration process). */
#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641 (0)
/* @brief Has CAN with Flexible Data rate (CAN FD) protocol. */
#define FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE (0)
/* @brief Has extra MB interrupt or common one. */
#define FSL_FEATURE_FLEXCAN_HAS_EXTRA_MB_INT (0)
/* ECSPI module features */
/* @brief ECSPI Tx FIFO Size. */
#define FSL_FEATURE_ECSPI_TX_FIFO_SIZEn(x) (64)
/* ENET module features */
/* @brief Support Interrupt Coalesce */
#define FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE (1)
/* @brief Queue Size. */
#define FSL_FEATURE_ENET_QUEUE (1)
/* @brief Has AVB Support. */
#define FSL_FEATURE_ENET_HAS_AVB (0)
/* @brief Has Timer Pulse Width control. */
#define FSL_FEATURE_ENET_HAS_TIMER_PWCONTROL (1)
/* @brief Has Extend MDIO Support. */
#define FSL_FEATURE_ENET_HAS_EXTEND_MDIO (1)
/* @brief Has Additional 1588 Timer Channel Interrupt. */
#define FSL_FEATURE_ENET_HAS_ADD_1588_TIMER_CHN_INT (1)
/* ESAI module features */
/* @brief ESAI FIFO Size. */
#define FSL_FEATURE_ESAI_FIFO_SIZEn(x) (128)
/* GPC module features */
/* @brief Has No DVFS0 Change Request. */
#define FSL_FEATURE_GPC_HAS_NO_CNTR_DVFS0CR (1)
/* SAI module features */
/* @brief Receive/transmit FIFO size in item count (register bit fields TCSR[FRDE], TCSR[FRIE], TCSR[FRF], TCR1[TFW], RCSR[FRDE], RCSR[FRIE], RCSR[FRF], RCR1[RFW], registers TFRn, RFRn). */
#define FSL_FEATURE_SAI_FIFO_COUNT (32)
/* @brief Receive/transmit channel number (register bit fields TCR3[TCE], RCR3[RCE], registers TDRn and RDRn). */
#define FSL_FEATURE_SAI_CHANNEL_COUNT (1)
/* @brief Maximum words per frame (register bit fields TCR3[WDFL], TCR4[FRSZ], TMR[TWM], RCR3[WDFL], RCR4[FRSZ], RMR[RWM]). */
#define FSL_FEATURE_SAI_MAX_WORDS_PER_FRAME (32)
/* @brief Has support of combining multiple data channel FIFOs into single channel FIFO (register bit fields TCR3[CFR], TCR4[FCOMB], TFR0[WCP], TFR1[WCP], RCR3[CFR], RCR4[FCOMB], RFR0[RCP], RFR1[RCP]). */
#define FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE (0)
/* @brief Has packing of 8-bit and 16-bit data into each 32-bit FIFO word (register bit fields TCR4[FPACK], RCR4[FPACK]). */
#define FSL_FEATURE_SAI_HAS_FIFO_PACKING (0)
/* @brief Configures when the SAI will continue transmitting after a FIFO error has been detected (register bit fields TCR4[FCONT], RCR4[FCONT]). */
#define FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR (0)
/* @brief Configures if the frame sync is generated internally, a frame sync is only generated when the FIFO warning flag is clear or continuously (register bit fields TCR4[ONDEM], RCR4[ONDEM]). */
#define FSL_FEATURE_SAI_HAS_ON_DEMAND_MODE (0)
/* @brief Simplified bit clock source and asynchronous/synchronous mode selection (register bit fields TCR2[CLKMODE], RCR2[CLKMODE]), in comparison with the exclusively implemented TCR2[SYNC,BCS,BCI,MSEL], RCR2[SYNC,BCS,BCI,MSEL]. */
#define FSL_FEATURE_SAI_HAS_CLOCKING_MODE (0)
/* @brief Has register for configuration of the MCLK divide ratio (register bit fields MDR[FRACT], MDR[DIVIDE]). */
#define FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER (0)
/* @brief Interrupt source number */
#define FSL_FEATURE_SAI_INT_SOURCE_NUM (2)
/* @brief Has register of MCR. */
#define FSL_FEATURE_SAI_HAS_MCR (0)
/* @brief Has register of MDR */
#define FSL_FEATURE_SAI_HAS_MDR (0)
/* MMDC module features */
/* @brief MMDC module has CLK32 clock source gate. */
#define FSL_FEATURE_MMDC_HAS_CLK32_GATE (1)
/* @brief MMDC module has arbitration and reordering control. */
#define FSL_FEATURE_MMDC_HAS_ARB_REO_CONTROL (0)
/* PXP module features */
/* @brief PXP module has dither engine. */
#define FSL_FEATURE_PXP_HAS_DITHER (1)
/* @brief PXP module supports repeat run */
#define FSL_FEATURE_PXP_HAS_EN_REPEAT (0)
/* QSPI module features */
/* @brief QSPI lookup table depth. */
#define FSL_FEATURE_QSPI_LUT_DEPTH (64)
/* @brief QSPI Tx FIFO depth. */
#define FSL_FEATURE_QSPI_TXFIFO_DEPTH (16)
/* @brief QSPI Rx FIFO depth. */
#define FSL_FEATURE_QSPI_RXFIFO_DEPTH (16)
/* @brief QSPI AHB buffer count. */
#define FSL_FEATURE_QSPI_AHB_BUFFER_COUNT (4)
/* @brief QSPI has command usage error flag. */
#define FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR (1)
/* @brief QSPI support parallel mode. */
#define FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE (1)
/* @brief QSPI support dual die. */
#define FSL_FEATURE_QSPI_SUPPORT_DUAL_DIE (1)
/* @brief there is no SCLKCFG bit in MCR register. */
#define FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL (1)
/* @brief there is no AITEF bit in FR register. */
#define FSL_FEATURE_QSPI_HAS_NO_AITEF (1)
/* @brief there is no AIBSEF bit in FR register. */
#define FSL_FEATURE_QSPI_HAS_NO_AIBSEF (1)
/* @brief there is no TXDMA and TXWA bit in SR register. */
#define FSL_FEATURE_QSPI_HAS_NO_TXDMA (1)
/* @brief there is no SFACR register. */
#define FSL_FEATURE_QSPI_HAS_NO_SFACR (1)
/* @brief there is no TDH bit in FLSHCR register. */
#define FSL_FEATURE_QSPI_HAS_NO_TDH (1)
/* @brief QSPI AMBA base address. */
#define FSL_FEATURE_QSPI_AMBA_BASE (0x60000000U)
/* @brief QSPI AHB buffer ARDB base address. */
#define FSL_FEATURE_QSPI_ARDB_BASE (0x0C000000U)
/* SDMA module features */
/* @brief SDMA module channel number. */
#define FSL_FEATURE_SDMA_MODULE_CHANNEL (32)
/* @brief SDMA module event number. */
#define FSL_FEATURE_SDMA_EVENT_NUM (48)
/* @brief SDMA ROM memory to memory script start address. */
#define FSL_FEATURE_SDMA_M2M_ADDR (642)
/* @brief SDMA ROM peripheral to memory script start address. */
#define FSL_FEATURE_SDMA_P2M_ADDR (683)
/* @brief SDMA ROM memory to peripheral script start address. */
#define FSL_FEATURE_SDMA_M2P_ADDR (747)
/* @brief SDMA ROM uart to memory script start address. */
#define FSL_FEATURE_SDMA_UART2M_ADDR (817)
/* @brief SDMA ROM peripheral on SPBA to memory script start address. */
#define FSL_FEATURE_SDMA_SHP2M_ADDR (891)
/* @brief SDMA ROM memory to peripheral on SPBA script start address. */
#define FSL_FEATURE_SDMA_M2SHP_ADDR (960)
/* @brief SDMA ROM UART on SPBA to memory script start address. */
#define FSL_FEATURE_SDMA_UARTSH2M_ADDR (1032)
/* @brief SDMA ROM SPDIF to memory script start address. */
#define FSL_FEATURE_SDMA_SPDIF2M_ADDR (1100)
/* @brief SDMA ROM memory to SPDIF script start address. */
#define FSL_FEATURE_SDMA_M2SPDIF_ADDR (1134)
/* SNVS module features */
/* @brief Has Secure Real Time Counter Enabled and Valid (bit field LPCR[SRTC_ENV]). */
#define FSL_FEATURE_SNVS_HAS_SRTC (0)
/* SPBA module features */
/* @brief SPBA module start address. */
#define FSL_FEATURE_SPBA_START (0x02000000U)
/* @brief SPBA module end address. */
#define FSL_FEATURE_SPBA_END (0x0203FFFFU)
/* SRC module features */
/* @brief There is MASK_WDOG3_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_MASK_WDOG3_RST (1)
/* @brief There is MIX_RST_STRCH bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_MIX_RST_STRCH (1)
/* @brief There is DBG_RST_MSK_PG bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_DBG_RST_MSK_PG (1)
/* @brief There is WDOG3_RST_OPTN bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_WDOG3_RST_OPTN (1)
/* @brief There is CORES_DBG_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_CORES_DBG_RST (1)
/* @brief There is MTSR bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_MTSR (0)
/* @brief There is CORE0_DBG_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_CORE0_DBG_RST (1)
/* @brief There is CORE0_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_CORE0_RST (1)
/* @brief There is SWRC bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_SWRC (0)
/* @brief There is EIM_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_EIM_RST (1)
/* @brief There is LUEN bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_LUEN (0)
/* @brief There is SISR register. */
#define FSL_FEATURE_SRC_HAS_SISR (1)
/* @brief There is RESET_OUT bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_RESET_OUT (0)
/* @brief There is WDOG3_RST_B bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_WDOG3_RST_B (1)
/* @brief There is SW bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_SW (0)
/* @brief There is IPP_USER_RESET_B bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_IPP_USER_RESET_B (1)
/* @brief There is SNVS bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_SNVS (0)
/* @brief There is CSU_RESET_B bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_CSU_RESET_B (1)
/* @brief There is LOCKUP bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_LOCKUP (0)
/* @brief There is POR bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_POR (0)
/* @brief There is IPP_RESET_B bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_IPP_RESET_B (1)
/* IUART module features */
/* @brief UART Transmit/Receive FIFO Size */
#define FSL_FEATURE_IUART_FIFO_SIZEn(x) (32)
/* @brief UART RX MUXed input selected option */
#define FSL_FEATURE_IUART_RXDMUXSEL (1)
/* USBHS module features */
/* @brief EHCI module instance count */
#define FSL_FEATURE_USBHS_EHCI_COUNT (2)
/* @brief Number of endpoints supported */
#define FSL_FEATURE_USBHS_ENDPT_COUNT (8)
/* USDHC module features */
/* @brief Has external DMA support (VEND_SPEC[EXT_DMA_EN]) */
#define FSL_FEATURE_USDHC_HAS_EXT_DMA (1)
/* @brief Has HS400 mode (MIX_CTRL[HS400_MODE]) */
#define FSL_FEATURE_USDHC_HAS_HS400_MODE (0)
/* @brief Has SDR50 support (HOST_CTRL_CAP[SDR50_SUPPORT]) */
#define FSL_FEATURE_USDHC_HAS_SDR50_MODE (1)
/* @brief Has SDR104 support (HOST_CTRL_CAP[SDR104_SUPPORT]) */
#define FSL_FEATURE_USDHC_HAS_SDR104_MODE (1)
#endif /* _MCIMX6Y2_FEATURES_H_ */

View File

@ -0,0 +1,13 @@
from building import *
cwd = GetCurrentDir()
src = ['system_MCIMX6Y2.c'] + Glob('drivers/*.c')
CPPDEFINES = ['CHIP_MX6UL', 'CPU_MCIMX6Y2DVM09']
path = [cwd, cwd + '/drivers']
src += Glob('drivers/usdhc/*.c')
path.append(cwd + '/drivers/usdhc')
group = DefineGroup('libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
Return('group')

View File

@ -0,0 +1,285 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_adc.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.adc_12b1msps_sar"
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for ADC module.
*
* @param base ADC peripheral base address
*/
static uint32_t ADC_GetInstance(ADC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to ADC bases for each instance. */
static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to ADC clocks for each instance. */
static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t ADC_GetInstance(ADC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_adcBases); instance++)
{
if (s_adcBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_adcBases));
return instance;
}
void ADC_Init(ADC_Type *base, const adc_config_t *config)
{
assert(NULL != config);
uint32_t tmp32;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock. */
CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* ADCx_CFG */
tmp32 = base->CFG & (ADC_CFG_AVGS_MASK | ADC_CFG_ADTRG_MASK); /* Reserve AVGS and ADTRG bits. */
tmp32 |= ADC_CFG_REFSEL(config->referenceVoltageSource) | ADC_CFG_ADSTS(config->samplePeriodMode) |
ADC_CFG_ADICLK(config->clockSource) | ADC_CFG_ADIV(config->clockDriver) | ADC_CFG_MODE(config->resolution);
if (config->enableOverWrite)
{
tmp32 |= ADC_CFG_OVWREN_MASK;
}
if (config->enableLongSample)
{
tmp32 |= ADC_CFG_ADLSMP_MASK;
}
if (config->enableLowPower)
{
tmp32 |= ADC_CFG_ADLPC_MASK;
}
if (config->enableHighSpeed)
{
tmp32 |= ADC_CFG_ADHSC_MASK;
}
base->CFG = tmp32;
/* ADCx_GC */
tmp32 = base->GC & ~(ADC_GC_ADCO_MASK | ADC_GC_ADACKEN_MASK);
if (config->enableContinuousConversion)
{
tmp32 |= ADC_GC_ADCO_MASK;
}
if (config->enableAsynchronousClockOutput)
{
tmp32 |= ADC_GC_ADACKEN_MASK;
}
base->GC = tmp32;
}
void ADC_Deinit(ADC_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the clock. */
CLOCK_DisableClock(s_adcClocks[ADC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void ADC_GetDefaultConfig(adc_config_t *config)
{
assert(NULL != config);
config->enableAsynchronousClockOutput = true;
config->enableOverWrite = false;
config->enableContinuousConversion = false;
config->enableHighSpeed = false;
config->enableLowPower = false;
config->enableLongSample = false;
config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0;
config->samplePeriodMode = kADC_SamplePeriod2or12Clocks;
config->clockSource = kADC_ClockSourceAD;
config->clockDriver = kADC_ClockDriver1;
config->resolution = kADC_Resolution12Bit;
}
void ADC_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc_channel_config_t *config)
{
assert(NULL != config);
assert(channelGroup < ADC_HC_COUNT);
uint32_t tmp32;
tmp32 = ADC_HC_ADCH(config->channelNumber);
if (config->enableInterruptOnConversionCompleted)
{
tmp32 |= ADC_HC_AIEN_MASK;
}
base->HC[channelGroup] = tmp32;
}
/*
*To complete calibration, the user must follow the below procedure:
* 1. Configure ADC_CFG with actual operating values for maximum accuracy.
* 2. Configure the ADC_GC values along with CAL bit.
* 3. Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC.
* 4. When CAL bit becomes '0' then check the CALF status and COCO[0] bit status.
*/
status_t ADC_DoAutoCalibration(ADC_Type *base)
{
status_t status = kStatus_Success;
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
bool bHWTrigger = false;
/* The calibration would be failed when in hardwar mode.
* Remember the hardware trigger state here and restore it later if the hardware trigger is enabled.*/
if (0U != (ADC_CFG_ADTRG_MASK & base->CFG))
{
bHWTrigger = true;
ADC_EnableHardwareTrigger(base, false);
}
#endif
/* Clear the CALF and launch the calibration. */
base->GS = ADC_GS_CALF_MASK; /* Clear the CALF. */
base->GC |= ADC_GC_CAL_MASK; /* Launch the calibration. */
/* Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC. */
while (0U != (base->GC & ADC_GC_CAL_MASK))
{
/* Check the CALF when the calibration is active. */
if (0U != (ADC_GetStatusFlags(base) & kADC_CalibrationFailedFlag))
{
status = kStatus_Fail;
break;
}
}
/* When CAL bit becomes '0' then check the CALF status and COCO[0] bit status. */
if (0U == ADC_GetChannelStatusFlags(base, 0U)) /* Check the COCO[0] bit status. */
{
status = kStatus_Fail;
}
if (0U != (ADC_GetStatusFlags(base) & kADC_CalibrationFailedFlag)) /* Check the CALF status. */
{
status = kStatus_Fail;
}
/* Clear conversion done flag. */
ADC_GetChannelConversionValue(base, 0U);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
/* Restore original trigger mode. */
if (true == bHWTrigger)
{
ADC_EnableHardwareTrigger(base, true);
}
#endif
return status;
}
void ADC_SetOffsetConfig(ADC_Type *base, const adc_offest_config_t *config)
{
assert(NULL != config);
uint32_t tmp32;
tmp32 = ADC_OFS_OFS(config->offsetValue);
if (config->enableSigned)
{
tmp32 |= ADC_OFS_SIGN_MASK;
}
base->OFS = tmp32;
}
void ADC_SetHardwareCompareConfig(ADC_Type *base, const adc_hardware_compare_config_t *config)
{
uint32_t tmp32;
tmp32 = base->GC & ~(ADC_GC_ACFE_MASK | ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK);
if (NULL == config) /* Pass "NULL" to disable the feature. */
{
base->GC = tmp32;
return;
}
/* Enable the feature. */
tmp32 |= ADC_GC_ACFE_MASK;
/* Select the hardware compare working mode. */
switch (config->hardwareCompareMode)
{
case kADC_HardwareCompareMode0:
break;
case kADC_HardwareCompareMode1:
tmp32 |= ADC_GC_ACFGT_MASK;
break;
case kADC_HardwareCompareMode2:
tmp32 |= ADC_GC_ACREN_MASK;
break;
case kADC_HardwareCompareMode3:
tmp32 |= ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK;
break;
default:
break;
}
base->GC = tmp32;
/* Load the compare values. */
tmp32 = ADC_CV_CV1(config->value1) | ADC_CV_CV2(config->value2);
base->CV = tmp32;
}
void ADC_SetHardwareAverageConfig(ADC_Type *base, adc_hardware_average_mode_t mode)
{
uint32_t tmp32;
if (mode == kADC_HardwareAverageDiasable)
{
base->GC &= ~ADC_GC_AVGE_MASK;
}
else
{
tmp32 = base->CFG & ~ADC_CFG_AVGS_MASK;
tmp32 |= ADC_CFG_AVGS(mode);
base->CFG = tmp32;
base->GC |= ADC_GC_AVGE_MASK; /* Enable the hardware compare. */
}
}
void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask)
{
uint32_t tmp32 = 0;
if (0U != (mask & kADC_CalibrationFailedFlag))
{
tmp32 |= ADC_GS_CALF_MASK;
}
if (0U != (mask & kADC_ConversionActiveFlag))
{
tmp32 |= ADC_GS_ADACT_MASK;
}
base->GS = tmp32;
}

View File

@ -0,0 +1,420 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_ADC_H_
#define _FSL_ADC_H_
#include "fsl_common.h"
/*!
* @addtogroup adc_12b1msps_sar
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief ADC driver version */
#define FSL_ADC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*!< Version 2.0.1. */
/*!
* @brief Converter's status flags.
*/
typedef enum _adc_status_flags
{
kADC_ConversionActiveFlag = ADC_GS_ADACT_MASK, /*!< Conversion is active,not support w1c. */
kADC_CalibrationFailedFlag = ADC_GS_CALF_MASK, /*!< Calibration is failed,support w1c. */
kADC_AsynchronousWakeupInterruptFlag =
ADC_GS_AWKST_MASK, /*!< Asynchronous wakeup interrupt occured, support w1c. */
} adc_status_flags_t;
/*!
* @brief Reference voltage source.
*/
typedef enum _adc_reference_voltage_source
{
kADC_ReferenceVoltageSourceAlt0 = 0U, /*!< For external pins pair of VrefH and VrefL. */
} adc_reference_voltage_source_t;
/*!
* @brief Sample time duration.
*/
typedef enum _adc_sample_period_mode
{
/* This group of enumeration is for internal use which is related to register setting. */
kADC_SamplePeriod2or12Clocks = 0U, /*!< Long sample 12 clocks or short sample 2 clocks. */
kADC_SamplePeriod4or16Clocks = 1U, /*!< Long sample 16 clocks or short sample 4 clocks. */
kADC_SamplePeriod6or20Clocks = 2U, /*!< Long sample 20 clocks or short sample 6 clocks. */
kADC_SamplePeriod8or24Clocks = 3U, /*!< Long sample 24 clocks or short sample 8 clocks. */
/* This group of enumeration is for a public user. */
/* For long sample mode. */
kADC_SamplePeriodLong12Clcoks = kADC_SamplePeriod2or12Clocks, /*!< Long sample 12 clocks. */
kADC_SamplePeriodLong16Clcoks = kADC_SamplePeriod4or16Clocks, /*!< Long sample 16 clocks. */
kADC_SamplePeriodLong20Clcoks = kADC_SamplePeriod6or20Clocks, /*!< Long sample 20 clocks. */
kADC_SamplePeriodLong24Clcoks = kADC_SamplePeriod8or24Clocks, /*!< Long sample 24 clocks. */
/* For short sample mode. */
kADC_SamplePeriodShort2Clocks = kADC_SamplePeriod2or12Clocks, /*!< Short sample 2 clocks. */
kADC_SamplePeriodShort4Clocks = kADC_SamplePeriod4or16Clocks, /*!< Short sample 4 clocks. */
kADC_SamplePeriodShort6Clocks = kADC_SamplePeriod6or20Clocks, /*!< Short sample 6 clocks. */
kADC_SamplePeriodShort8Clocks = kADC_SamplePeriod8or24Clocks, /*!< Short sample 8 clocks. */
} adc_sample_period_mode_t;
/*!
* @brief Clock source.
*/
typedef enum _adc_clock_source
{
kADC_ClockSourceIPG = 0U, /*!< Select IPG clock to generate ADCK. */
kADC_ClockSourceIPGDiv2 = 1U, /*!< Select IPG clock divided by 2 to generate ADCK. */
#if !(defined(FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE) && FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE)
kADC_ClockSourceALT = 2U, /*!< Select alternate clock to generate ADCK. */
#endif
kADC_ClockSourceAD = 3U, /*!< Select Asynchronous clock to generate ADCK. */
} adc_clock_source_t;
/*!
* @brief Clock divider for the converter.
*/
typedef enum _adc_clock_drvier
{
kADC_ClockDriver1 = 0U, /*!< For divider 1 from the input clock to the module. */
kADC_ClockDriver2 = 1U, /*!< For divider 2 from the input clock to the module. */
kADC_ClockDriver4 = 2U, /*!< For divider 4 from the input clock to the module. */
kADC_ClockDriver8 = 3U, /*!< For divider 8 from the input clock to the module. */
} adc_clock_driver_t;
/*!
* @brief Converter's resolution.
*/
typedef enum _adc_resolution
{
kADC_Resolution8Bit = 0U, /*!< Single End 8-bit resolution. */
kADC_Resolution10Bit = 1U, /*!< Single End 10-bit resolution. */
kADC_Resolution12Bit = 2U, /*!< Single End 12-bit resolution. */
} adc_resolution_t;
/*!
* @brief Converter hardware compare mode.
*/
typedef enum _adc_hardware_compare_mode
{
kADC_HardwareCompareMode0 = 0U, /*!< Compare true if the result is less than the value1. */
kADC_HardwareCompareMode1 = 1U, /*!< Compare true if the result is greater than or equal to value1. */
kADC_HardwareCompareMode2 = 2U, /*!< Value1 <= Value2, compare true if the result is less than value1 Or
the result is Greater than value2.
Value1 > Value2, compare true if the result is less than value1 And the
result is greater than value2*/
kADC_HardwareCompareMode3 = 3U, /*!< Value1 <= Value2, compare true if the result is greater than or equal
to value1 And the result is less than or equal to value2.
Value1 > Value2, compare true if the result is greater than or equal to
value1 Or the result is less than or equal to value2. */
} adc_hardware_compare_mode_t;
/*!
* @brief Converter hardware average mode.
*/
typedef enum _adc_hardware_average_mode
{
kADC_HardwareAverageCount4 = 0U, /*!< For hardware average with 4 samples. */
kADC_HardwareAverageCount8 = 1U, /*!< For hardware average with 8 samples. */
kADC_HardwareAverageCount16 = 2U, /*!< For hardware average with 16 samples. */
kADC_HardwareAverageCount32 = 3U, /*!< For hardware average with 32 samples. */
kADC_HardwareAverageDiasable = 4U, /*!< Disable the hardware average function. */
} adc_hardware_average_mode_t;
/*!
* @brief Converter configuration.
*/
typedef struct _adc_config
{
bool enableOverWrite; /*!< Enable the overwriting. */
bool enableContinuousConversion; /*!< Enable the continuous conversion mode. */
bool enableHighSpeed; /*!< Enable the high-speed mode. */
bool enableLowPower; /*!< Enable the low power mode. */
bool enableLongSample; /*!< Enable the long sample mode. */
bool enableAsynchronousClockOutput; /*!< Enable the asynchronous clock output. */
adc_reference_voltage_source_t referenceVoltageSource; /*!< Select the reference voltage source. */
adc_sample_period_mode_t samplePeriodMode; /*!< Select the sample period in long sample mode or short mode. */
adc_clock_source_t clockSource; /*!< Select the input clock source to generate the internal clock ADCK. */
adc_clock_driver_t clockDriver; /*!< Select the divide ratio used by the ADC to generate the internal clock ADCK. */
adc_resolution_t resolution; /*!< Select the ADC resolution mode. */
} adc_config_t;
/*!
* @brief Converter Offset configuration.
*/
typedef struct _adc_offest_config
{
bool enableSigned; /*!< if false,The offset value is added with the raw result.
if true,The offset value is subtracted from the raw converted value. */
uint32_t offsetValue; /*!< User configurable offset value(0-4095). */
} adc_offest_config_t;
/*!
* @brief ADC hardware compare configuration.
*
* In kADC_HardwareCompareMode0, compare true if the result is less than the value1.
* In kADC_HardwareCompareMode1, compare true if the result is greater than or equal to value1.
* In kADC_HardwareCompareMode2, Value1 <= Value2, compare true if the result is less than value1 Or the result is
* Greater than value2.
* Value1 > Value2, compare true if the result is less than value1 And the result is
* Greater than value2.
* In kADC_HardwareCompareMode3, Value1 <= Value2, compare true if the result is greater than or equal to value1 And the
* result is less than or equal to value2.
* Value1 > Value2, compare true if the result is greater than or equal to value1 Or the
* result is less than or equal to value2.
*/
typedef struct _adc_hardware_compare_config
{
adc_hardware_compare_mode_t hardwareCompareMode; /*!< Select the hardware compare mode.
See "adc_hardware_compare_mode_t". */
uint16_t value1; /*!< Setting value1(0-4095) for hardware compare mode. */
uint16_t value2; /*!< Setting value2(0-4095) for hardware compare mode. */
} adc_hardware_compare_config_t;
/*!
* @brief ADC channel conversion configuration.
*/
typedef struct _adc_channel_config
{
uint32_t channelNumber; /*!< Setting the conversion channel number. The available range is 0-31.
See channel connection information for each chip in Reference
Manual document. */
bool enableInterruptOnConversionCompleted; /*!< Generate an interrupt request once the conversion is completed. */
} adc_channel_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization
* @{
*/
/*!
* @brief Initialize the ADC module.
*
* @param base ADC peripheral base address.
* @param config Pointer to "adc_config_t" structure.
*/
void ADC_Init(ADC_Type *base, const adc_config_t *config);
/*!
* @brief De-initializes the ADC module.
*
* @param base ADC peripheral base address.
*/
void ADC_Deinit(ADC_Type *base);
/*!
* @brief Gets an available pre-defined settings for the converter's configuration.
*
* This function initializes the converter configuration structure with available settings. The default values are:
* @code
* config->enableAsynchronousClockOutput = true;
* config->enableOverWrite = false;
* config->enableContinuousConversion = false;
* config->enableHighSpeed = false;
* config->enableLowPower = false;
* config->enableLongSample = false;
* config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0;
* config->samplePeriodMode = kADC_SamplePeriod2or12Clocks;
* config->clockSource = kADC_ClockSourceAD;
* config->clockDriver = kADC_ClockDriver1;
* config->resolution = kADC_Resolution12Bit;
* @endcode
* @param base ADC peripheral base address.
* @param config Pointer to the configuration structure.
*/
void ADC_GetDefaultConfig(adc_config_t *config);
/*!
* @brief Configures the conversion channel.
*
* This operation triggers the conversion when in software trigger mode. When in hardware trigger mode, this API
* configures the channel while the external trigger source helps to trigger the conversion.
*
* Note that the "Channel Group" has a detailed description.
* To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC has more than one
* group of status and control registers, one for each conversion. The channel group parameter indicates which group of
* registers are used, for example channel group 0 is for Group A registers and channel group 1 is for Group B
* registers. The
* channel groups are used in a "ping-pong" approach to control the ADC operation. At any point, only one of
* the channel groups is actively controlling ADC conversions. The channel group 0 is used for both software and
* hardware
* trigger modes. Channel groups 1 and greater indicate potentially multiple channel group registers for
* use only in hardware trigger mode. See the chip configuration information in the appropriate MCU reference manual
* about the
* number of SC1n registers (channel groups) specific to this device. None of the channel groups 1 or greater are used
* for software trigger operation. Therefore, writing to these channel groups does not initiate a new conversion.
* Updating the channel group 0 while a different channel group is actively controlling a conversion is allowed and
* vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a
* conversion aborts the current conversion.
*
* @param base ADC peripheral base address.
* @param channelGroup Channel group index.
* @param config Pointer to the "adc_channel_config_t" structure for the conversion channel.
*/
void ADC_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc_channel_config_t *config);
/*!
* @brief Gets the conversion value.
*
* @param base ADC peripheral base address.
* @param channelGroup Channel group index.
*
* @return Conversion value.
*/
static inline uint32_t ADC_GetChannelConversionValue(ADC_Type *base, uint32_t channelGroup)
{
assert(channelGroup < ADC_R_COUNT);
return base->R[channelGroup];
}
/*!
* @brief Gets the status flags of channel.
*
* A conversion is completed when the result of the conversion is transferred into the data
* result registers. (provided the compare function & hardware averaging is disabled), this is
* indicated by the setting of COCOn. If hardware averaging is enabled, COCOn sets only,
* if the last of the selected number of conversions is complete. If the compare function is
* enabled, COCOn sets and conversion result data is transferred only if the compare
* condition is true. If both hardware averaging and compare functions are enabled, then
* COCOn sets only if the last of the selected number of conversions is complete and the
* compare condition is true.
*
* @param base ADC peripheral base address.
* @param channelGroup Channel group index.
*
* @return Status flags of channel.return 0 means COCO flag is 0,return 1 means COCOflag is 1.
*/
static inline uint32_t ADC_GetChannelStatusFlags(ADC_Type *base, uint32_t channelGroup)
{
assert(channelGroup < ADC_HC_COUNT);
/* If flag is set,return 1,otherwise, return 0. */
return (((base->HS) & (1U << channelGroup)) >> channelGroup);
}
/*!
* @brief Automates the hardware calibration.
*
* This auto calibration helps to adjust the plus/minus side gain automatically.
* Execute the calibration before using the converter. Note that the software trigger should be used
* during calibration.
*
* @param base ADC peripheral base address.
*
* @return Execution status.
* @retval kStatus_Success Calibration is done successfully.
* @retval kStatus_Fail Calibration has failed.
*/
status_t ADC_DoAutoCalibration(ADC_Type *base);
/*!
* @brief Set user defined offset.
*
* @param base ADC peripheral base address.
* @param config Pointer to "adc_offest_config_t" structure.
*/
void ADC_SetOffsetConfig(ADC_Type *base, const adc_offest_config_t *config);
/*!
* @brief Enables generating the DMA trigger when the conversion is complete.
*
* @param base ADC peripheral base address.
* @param enable Switcher of the DMA feature. "true" means enabled, "false" means not enabled.
*/
static inline void ADC_EnableDMA(ADC_Type *base, bool enable)
{
if (enable)
{
base->GC |= ADC_GC_DMAEN_MASK;
}
else
{
base->GC &= ~ADC_GC_DMAEN_MASK;
}
}
/*!
* @brief Enables the hardware trigger mode.
*
* @param base ADC peripheral base address.
* @param enable Switcher of the trigger mode. "true" means hardware tirgger mode,"false" means software mode.
*/
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
static inline void ADC_EnableHardwareTrigger(ADC_Type *base, bool enable)
{
if (enable)
{
base->CFG |= ADC_CFG_ADTRG_MASK;
}
else
{
base->CFG &= ~ADC_CFG_ADTRG_MASK;
}
}
#endif
/*!
* @brief Configures the hardware compare mode.
*
* The hardware compare mode provides a way to process the conversion result automatically by using hardware. Only the
* result
* in the compare range is available. To compare the range, see "adc_hardware_compare_mode_t" or the appopriate
* reference
* manual for more information.
*
* @param base ADC peripheral base address.
* @param Pointer to "adc_hardware_compare_config_t" structure.
*
*/
void ADC_SetHardwareCompareConfig(ADC_Type *base, const adc_hardware_compare_config_t *config);
/*!
* @brief Configures the hardware average mode.
*
* The hardware average mode provides a way to process the conversion result automatically by using hardware. The
* multiple
* conversion results are accumulated and averaged internally making them easier to read.
*
* @param base ADC peripheral base address.
* @param mode Setting the hardware average mode. See "adc_hardware_average_mode_t".
*/
void ADC_SetHardwareAverageConfig(ADC_Type *base, adc_hardware_average_mode_t mode);
/*!
* @brief Gets the converter's status flags.
*
* @param base ADC peripheral base address.
*
* @return Flags' mask if indicated flags are asserted. See "adc_status_flags_t".
*/
static inline uint32_t ADC_GetStatusFlags(ADC_Type *base)
{
return base->GS;
}
/*!
* @brief Clears the converter's status falgs.
*
* @param base ADC peripheral base address.
* @param mask Mask value for the cleared flags. See "adc_status_flags_t".
*/
void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask);
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_ADC_H_ */

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_cache.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
void ICACHE_InvalidateByRange(uint32_t address, uint32_t size_byte)
{
L1CACHE_InvalidateICacheByRange(address, size_byte);
}
void DCACHE_InvalidateByRange(uint32_t address, uint32_t size_byte)
{
L1CACHE_InvalidateDCacheByRange(address, size_byte);
}
void DCACHE_CleanByRange(uint32_t address, uint32_t size_byte)
{
L1CACHE_CleanDCacheByRange(address, size_byte);
}
void DCACHE_CleanInvalidateByRange(uint32_t address, uint32_t size_byte)
{
L1CACHE_CleanInvalidateDCacheByRange(address, size_byte);
}

View File

@ -0,0 +1,253 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_CACHE_H_
#define _FSL_CACHE_H_
#include "fsl_common.h"
/*!
* @addtogroup cache
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief cache driver version 2.0.0. */
#define FSL_CACHE_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Cache Control for Cortex-a L1 cache
*@{
*/
/*!
* @brief Enables L1 instruction cache.
*
*/
static inline void L1CACHE_EnableICache(void)
{
L1C_EnableInstructionCache();
}
/*!
* @brief Disables L1 instruction cache.
*
*/
static inline void L1CACHE_DisableICache(void)
{
L1C_DisableInstructionCache();
}
/*!
* @brief Invalidates L1 instruction cache all.
*
*/
static inline void L1CACHE_InvalidateICache(void)
{
L1C_InvalidateInstructionCacheAll();
}
/*!
* @brief Invalidates L1 instruction cache by range.
*
* @param startAddr The start startAddr of the memory to be invalidated.
* @param size_byte The memory size.
* @note The start startAddr and size_byte should be 32-byte(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE) aligned due to the
* cache operation unit is one L1 I-cache line. The startAddr here will be forced
* to align to L1 I-cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
static inline void L1CACHE_InvalidateICacheByRange(uint32_t startAddr, uint32_t size_byte)
{
L1C_InvalidateInstructionCacheRange((void *)startAddr, size_byte);
}
/*!
* @brief Enables L1 data cache.
*
*/
static inline void L1CACHE_EnableDCache(void)
{
L1C_EnableDataCache();
}
/*!
* @brief Disables L1 data cache.
*
*/
static inline void L1CACHE_DisableDCache(void)
{
L1C_DisableDataCache();
}
/*!
* @brief Invalidates L1 data cache all.
*
*/
static inline void L1CACHE_InvalidateDCache(void)
{
L1C_InvalidateDataCacheAll();
}
/*!
* @brief Invalidates L1 data cache by range.
*
* @param startAddr The start startAddr of the memory to be invalidated.
* @param size_byte The memory size.
* @note The start startAddr and size_byte should be 64-byte(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) aligned due to the
* cache operation unit is one L1 D-cache line. The startAddr here will be forced
* to align to L1 D-cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
static inline void L1CACHE_InvalidateDCacheByRange(uint32_t startAddr, uint32_t size_byte)
{
L1C_InvalidateDataCacheRange((void *)startAddr, size_byte);
}
/*!
* @brief Clean L1 data cache all.
*
*/
static inline void L1CACHE_CleanDCache(void)
{
L1C_CleanDataCacheAll();
}
/*!
* @brief Cleans L1 data cache by range.
*
* @param startAddr The start startAddr of the memory to be cleaned.
* @param size_byte The memory size.
* @note The start startAddr and size_byte should be 64-byte(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) aligned due to the
* cache operation unit is one L1 D-cache line. The startAddr here will be forced
* to align to L1 D-cache line size if startAddr is not aligned. For size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
static inline void L1CACHE_CleanDCacheByRange(uint32_t startAddr, uint32_t size_byte)
{
L1C_CleanDataCacheRange((void *)startAddr, size_byte);
}
/*!
* @brief Cleans and invalidates L1 data cache all.
*
*/
static inline void L1CACHE_CleanInvalidateDCache(void)
{
L1C_CleanInvalidateDataCacheAll();
}
/*!
* @brief Cleans and invalidates L1 data cache by range.
*
* @param startAddr The start startAddr of the memory to be clean and invalidated.
* @param size_byte The memory size.
* @note The start startAddr and size_byte should be 64-byte(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) aligned due to the
* cache operation unit is one L1 D-cache line. The startAddr here will be forced
* to align to L1 D-cache line size if startAddr is not aligned. For size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
static inline void L1CACHE_CleanInvalidateDCacheByRange(uint32_t startAddr, uint32_t size_byte)
{
L1C_CleanInvalidateDataCacheRange((void *)startAddr, size_byte);
}
/*@}*/
/*!
* @name Unified Cache Control for all caches which is mainly used for
* SDK Driver easy use cache driver
*@{
*/
/*!
* @brief Invalidates instruction cache by range.
*
* Cortex-a L1 instruction cache line length is 32-byte.
*
* @param address The physical address.
* @param size_byte size of the memory to be invalidated.
* @note Address and size should be aligned to cache line size
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void ICACHE_InvalidateByRange(uint32_t address, uint32_t size_byte);
/*!
* @brief Invalidates data cache by range.
*
* Cortex-a L1 data cache line length is 64-byte.
*
* @param address The physical address.
* @param size_byte size of the memory to be invalidated.
* @note Address and size should be aligned to cache line size
* 64-byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void DCACHE_InvalidateByRange(uint32_t address, uint32_t size_byte);
/*!
* @brief Cleans data cache by range.
*
* Cortex-a L1 data cache line length is 64-byte.
*
* @param address The physical address.
* @param size_byte size of the memory to be cleaned.
* @note Address and size should be aligned to cache line size
* 64-byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void DCACHE_CleanByRange(uint32_t address, uint32_t size_byte);
/*!
* @brief Cleans and Invalidates data cache by range.
*
* Cortex-a L1 data cache line length is 64-byte.
*
* @param address The physical address.
* @param size_byte size of the memory to be cleaned and invalidated.
* @note Address and size should be aligned to cache line size
* 64-byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void DCACHE_CleanInvalidateByRange(uint32_t address, uint32_t size_byte);
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_CACHE_H_*/

View File

@ -0,0 +1,915 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright (c) 2016 - 2017 , NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_common.h"
#include "fsl_clock.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/* External XTAL (OSC) clock frequency. */
uint32_t g_xtalFreq;
/* External RTC XTAL clock frequency. */
uint32_t g_rtcXtalFreq;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t CLOCK_GetPeriphClkFreq(void)
{
uint32_t freq;
/* Periph_clk2_clk ---> Periph_clk */
if (CCM->CBCDR & CCM_CBCDR_PERIPH_CLK_SEL_MASK)
{
switch (CCM->CBCMR & CCM_CBCMR_PERIPH_CLK2_SEL_MASK)
{
/* Pll3_sw_clk ---> Periph_clk2_clk ---> Periph_clk */
case CCM_CBCMR_PERIPH_CLK2_SEL(0U):
freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
break;
/* Osc_clk ---> Periph_clk2_clk ---> Periph_clk */
case CCM_CBCMR_PERIPH_CLK2_SEL(1U):
freq = CLOCK_GetOscFreq();
break;
case CCM_CBCMR_PERIPH_CLK2_SEL(2U):
case CCM_CBCMR_PERIPH_CLK2_SEL(3U):
default:
freq = 0U;
break;
}
freq /= (((CCM->CBCDR & CCM_CBCDR_PERIPH_CLK2_PODF_MASK) >> CCM_CBCDR_PERIPH_CLK2_PODF_SHIFT) + 1U);
}
/* Pll2_main_clk ---> Periph_clk */
else
{
switch (CCM->CBCMR & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
{
/* PLL2 ---> Pll2_main_clk ---> Periph_clk */
case CCM_CBCMR_PRE_PERIPH_CLK_SEL(0U):
freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
break;
/* PLL2 PFD2 ---> Pll2_main_clk ---> Periph_clk */
case CCM_CBCMR_PRE_PERIPH_CLK_SEL(1U):
freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
break;
/* PLL2 PFD0 ---> Pll2_main_clk ---> Periph_clk */
case CCM_CBCMR_PRE_PERIPH_CLK_SEL(2U):
freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0);
break;
/* PLL2 PFD2 divided(/2) ---> Pll2_main_clk ---> Periph_clk */
case CCM_CBCMR_PRE_PERIPH_CLK_SEL(3U):
freq = (CLOCK_GetSysPfdFreq(kCLOCK_Pfd2) >> 1U);
break;
default:
freq = 0U;
break;
}
}
return freq;
}
void CLOCK_InitExternalClk(bool bypassXtalOsc)
{
/* This device does not support bypass XTAL OSC. */
assert(!bypassXtalOsc);
CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power up */
while ((PMU->LOWPWR_CTRL & PMU_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_MASK) == 0)
{
}
CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; /* detect freq */
while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_OSC_XTALOK_MASK) == 0)
{
}
CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK;
}
void CLOCK_DeinitExternalClk(void)
{
CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power down */
}
void CLOCK_SwitchOsc(clock_osc_t osc)
{
if (osc == kCLOCK_RcOsc)
PMU->LOWPWR_CTRL_SET = PMU_LOWPWR_CTRL_OSC_SEL_MASK;
else
PMU->LOWPWR_CTRL_CLR = PMU_LOWPWR_CTRL_OSC_SEL_MASK;
}
void CLOCK_InitRcOsc24M(void)
{
PMU->LOWPWR_CTRL |= PMU_LOWPWR_CTRL_RC_OSC_EN_MASK;
}
void CLOCK_DeinitRcOsc24M(void)
{
PMU->LOWPWR_CTRL &= ~PMU_LOWPWR_CTRL_RC_OSC_EN_MASK;
}
uint32_t CLOCK_GetFreq(clock_name_t name)
{
uint32_t freq;
switch (name)
{
case kCLOCK_CpuClk:
switch (CCM->CCSR & (CCM_CCSR_STEP_SEL_MASK | CCM_CCSR_SECONDARY_CLK_SEL_MASK | CCM_CCSR_PLL1_SW_CLK_SEL_MASK))
{
/* ARM PLL ---> CPU Clock */
case 0U:
freq = CLOCK_GetPllFreq(kCLOCK_PllArm);
break;
/* Osc_clk (24M) ---> Step Clock ---> CPU Clock */
case (CCM_CCSR_PLL1_SW_CLK_SEL_MASK):
freq = CLOCK_GetOscFreq();
break;
/* PLL2 PFD2 ---> Secondary_clk ---> Step Clock ---> CPU Clock */
case (CCM_CCSR_PLL1_SW_CLK_SEL_MASK | CCM_CCSR_STEP_SEL_MASK):
freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
break;
/* PLL2 ---> Secondary_clk ---> Step Clock ---> CPU Clock */
case (CCM_CCSR_STEP_SEL_MASK | CCM_CCSR_SECONDARY_CLK_SEL_MASK | CCM_CCSR_PLL1_SW_CLK_SEL_MASK):
freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
break;
default:
freq = 0U;
break;
}
freq /= (((CCM->CACRR & CCM_CACRR_ARM_PODF_MASK) >> CCM_CACRR_ARM_PODF_SHIFT) + 1U);
break;
case kCLOCK_AxiClk:
/* AXI alternative clock ---> AXI Clock */
if (CCM->CBCDR & CCM_CBCDR_AXI_SEL_MASK)
{
/* PLL3 PFD1 ---> AXI alternative clock ---> AXI Clock */
if (CCM->CBCDR & CCM_CBCDR_AXI_ALT_SEL_MASK)
{
freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1);
}
/* PLL2 PFD2 ---> AXI alternative clock ---> AXI Clock */
else
{
freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
}
}
/* Periph_clk ---> AXI Clock */
else
{
freq = CLOCK_GetPeriphClkFreq();
}
freq /= (((CCM->CBCDR & CCM_CBCDR_AXI_PODF_MASK) >> CCM_CBCDR_AXI_PODF_SHIFT) + 1U);
break;
case kCLOCK_AhbClk:
/* Periph_clk ---> AHB Clock */
freq = CLOCK_GetPeriphClkFreq() / (((CCM->CBCDR & CCM_CBCDR_AHB_PODF_MASK) >> CCM_CBCDR_AHB_PODF_SHIFT) + 1U);
break;
case kCLOCK_IpgClk:
/* Periph_clk ---> AHB Clock ---> IPG Clock */
freq = CLOCK_GetPeriphClkFreq() / (((CCM->CBCDR & CCM_CBCDR_AHB_PODF_MASK) >> CCM_CBCDR_AHB_PODF_SHIFT) + 1U);
freq /= (((CCM->CBCDR & CCM_CBCDR_IPG_PODF_MASK) >> CCM_CBCDR_IPG_PODF_SHIFT) + 1U);
break;
case kCLOCK_MmdcClk:
/* periph2_clk2 ---> MMDC Clock */
if (CCM->CBCDR & CCM_CBCDR_PERIPH2_CLK_SEL_MASK)
{
/* OSC ---> periph2_clk2 ---> MMDC Clock */
if (CCM->CBCMR & CCM_CBCMR_PERIPH2_CLK2_SEL_MASK)
{
freq = CLOCK_GetOscFreq();
}
/* pll3_sw_clk ---> periph2_clk2 ---> MMDC Clock */
else
{
freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
}
freq /= (((CCM->CBCDR & CCM_CBCDR_PERIPH2_CLK2_PODF_MASK) >> CCM_CBCDR_PERIPH2_CLK2_PODF_SHIFT) + 1U);
}
/* pll2_main_clk ---> MMDC Clock */
else
{
switch (CCM->CBCMR & CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK)
{
/* PLL2 ---> pll2_main_clk ---> MMDC Clock */
case CCM_CBCMR_PRE_PERIPH2_CLK_SEL(0U):
freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
break;
/* PLL2 PFD2 ---> pll2_main_clk ---> MMDC Clock */
case CCM_CBCMR_PRE_PERIPH2_CLK_SEL(1U):
freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
break;
/* PLL2 PFD0 ---> pll2_main_clk ---> MMDC Clock */
case CCM_CBCMR_PRE_PERIPH2_CLK_SEL(2U):
freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0);
break;
/* PLL4 ---> pll2_main_clk ---> MMDC Clock */
case CCM_CBCMR_PRE_PERIPH2_CLK_SEL(3U):
freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
break;
default:
freq = 0U;
break;
}
}
freq /= (((CCM->CBCDR & CCM_CBCDR_FABRIC_MMDC_PODF_MASK) >> CCM_CBCDR_FABRIC_MMDC_PODF_SHIFT) + 1U);
break;
case kCLOCK_OscClk:
freq = CLOCK_GetOscFreq();
break;
case kCLOCK_RtcClk:
freq = CLOCK_GetRtcFreq();
break;
case kCLOCK_ArmPllClk:
freq = CLOCK_GetPllFreq(kCLOCK_PllArm);
break;
case kCLOCK_Usb1PllClk:
freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
break;
case kCLOCK_Usb1PllPfd0Clk:
freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd0);
break;
case kCLOCK_Usb1PllPfd1Clk:
freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1);
break;
case kCLOCK_Usb1PllPfd2Clk:
freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd2);
break;
case kCLOCK_Usb1PllPfd3Clk:
freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd3);
break;
case kCLOCK_Usb2PllClk:
freq = CLOCK_GetPllFreq(kCLOCK_PllUsb2);
break;
case kCLOCK_SysPllClk:
freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
break;
case kCLOCK_SysPllPfd0Clk:
freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0);
break;
case kCLOCK_SysPllPfd1Clk:
freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd1);
break;
case kCLOCK_SysPllPfd2Clk:
freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
break;
case kCLOCK_SysPllPfd3Clk:
freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd3);
break;
case kCLOCK_EnetPll0Clk:
freq = CLOCK_GetPllFreq(kCLOCK_PllEnet0);
break;
case kCLOCK_EnetPll1Clk:
freq = CLOCK_GetPllFreq(kCLOCK_PllEnet1);
break;
case kCLOCK_EnetPll2Clk:
freq = CLOCK_GetPllFreq(kCLOCK_PllEnet2);
break;
case kCLOCK_AudioPllClk:
freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
break;
case kCLOCK_VideoPllClk:
freq = CLOCK_GetPllFreq(kCLOCK_PllVideo);
break;
default:
freq = 0U;
break;
}
return freq;
}
void CLOCK_InitArmPll(const clock_arm_pll_config_t *config)
{
CCM_ANALOG->PLL_ARM = CCM_ANALOG_PLL_ARM_ENABLE_MASK |
CCM_ANALOG_PLL_ARM_DIV_SELECT(config->loopDivider);
while ((CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_LOCK_MASK) == 0)
{
}
}
void CLOCK_DeinitArmPll(void)
{
CCM_ANALOG->PLL_ARM = CCM_ANALOG_PLL_ARM_POWERDOWN_MASK;
}
void CLOCK_InitSysPll(const clock_sys_pll_config_t *config)
{
CCM_ANALOG->PLL_SYS = CCM_ANALOG_PLL_SYS_ENABLE_MASK |
CCM_ANALOG_PLL_SYS_DIV_SELECT(config->loopDivider);
while ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_LOCK_MASK) == 0)
{
}
}
void CLOCK_DeinitSysPll(void)
{
CCM_ANALOG->PLL_SYS = CCM_ANALOG_PLL_SYS_POWERDOWN_MASK;
}
void CLOCK_InitUsb1Pll(const clock_usb_pll_config_t *config)
{
CCM_ANALOG->PLL_USB1 = CCM_ANALOG_PLL_USB1_ENABLE_MASK |
CCM_ANALOG_PLL_USB1_POWER_MASK |
CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK |
CCM_ANALOG_PLL_USB1_DIV_SELECT(config->loopDivider);
while ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_LOCK_MASK) == 0)
{
}
}
void CLOCK_DeinitUsb1Pll(void)
{
CCM_ANALOG->PLL_USB1 = 0U;
}
void CLOCK_InitUsb2Pll(const clock_usb_pll_config_t *config)
{
CCM_ANALOG->PLL_USB2 = CCM_ANALOG_PLL_USB2_ENABLE_MASK |
CCM_ANALOG_PLL_USB2_POWER_MASK |
CCM_ANALOG_PLL_USB2_EN_USB_CLKS_MASK |
CCM_ANALOG_PLL_USB2_DIV_SELECT(config->loopDivider);
while ((CCM_ANALOG->PLL_USB2 & CCM_ANALOG_PLL_USB2_LOCK_MASK) == 0)
{
}
}
void CLOCK_DeinitUsb2Pll(void)
{
CCM_ANALOG->PLL_USB2 = 0U;
}
void CLOCK_InitAudioPll(const clock_audio_pll_config_t *config)
{
uint32_t pllAudio;
uint32_t misc2 = 0;
CCM_ANALOG->PLL_AUDIO_NUM = CCM_ANALOG_PLL_AUDIO_NUM_A(config->numerator);
CCM_ANALOG->PLL_AUDIO_DENOM = CCM_ANALOG_PLL_AUDIO_DENOM_B(config->denominator);
/*
* Set post divider:
*
* ------------------------------------------------------------------------
* | config->postDivider | PLL_AUDIO[POST_DIV_SELECT] | MISC2[AUDIO_DIV] |
* ------------------------------------------------------------------------
* | 1 | 2 | 0 |
* ------------------------------------------------------------------------
* | 2 | 1 | 0 |
* ------------------------------------------------------------------------
* | 4 | 2 | 3 |
* ------------------------------------------------------------------------
* | 8 | 1 | 3 |
* ------------------------------------------------------------------------
* | 16 | 0 | 3 |
* ------------------------------------------------------------------------
*/
pllAudio = CCM_ANALOG_PLL_AUDIO_ENABLE_MASK | CCM_ANALOG_PLL_AUDIO_DIV_SELECT(config->loopDivider);
switch (config->postDivider)
{
case 16:
pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0);
misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
break;
case 8:
pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1);
misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
break;
case 4:
pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2);
misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
break;
case 2:
pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1);
break;
default:
pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2);
break;
}
CCM_ANALOG->MISC2 = (CCM_ANALOG->MISC2 & ~(CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK))
| misc2;
CCM_ANALOG->PLL_AUDIO = pllAudio;
while ((CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK_MASK) == 0)
{
}
}
void CLOCK_DeinitAudioPll(void)
{
CCM_ANALOG->PLL_AUDIO = CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK;
}
void CLOCK_InitVideoPll(const clock_video_pll_config_t *config)
{
uint32_t pllVideo;
uint32_t misc2 = 0;
CCM_ANALOG->PLL_VIDEO_NUM = CCM_ANALOG_PLL_VIDEO_NUM_A(config->numerator);
CCM_ANALOG->PLL_VIDEO_DENOM = CCM_ANALOG_PLL_VIDEO_DENOM_B(config->denominator);
/*
* Set post divider:
*
* ------------------------------------------------------------------------
* | config->postDivider | PLL_VIDEO[POST_DIV_SELECT] | MISC2[VIDEO_DIV] |
* ------------------------------------------------------------------------
* | 1 | 2 | 0 |
* ------------------------------------------------------------------------
* | 2 | 1 | 0 |
* ------------------------------------------------------------------------
* | 4 | 2 | 3 |
* ------------------------------------------------------------------------
* | 8 | 1 | 3 |
* ------------------------------------------------------------------------
* | 16 | 0 | 3 |
* ------------------------------------------------------------------------
*/
pllVideo = CCM_ANALOG_PLL_VIDEO_ENABLE_MASK | CCM_ANALOG_PLL_VIDEO_DIV_SELECT(config->loopDivider);
switch (config->postDivider)
{
case 16:
pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(0);
misc2 = CCM_ANALOG_MISC2_VIDEO_DIV(3);
break;
case 8:
pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1);
misc2 = CCM_ANALOG_MISC2_VIDEO_DIV(3);
break;
case 4:
pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(2);
misc2 = CCM_ANALOG_MISC2_VIDEO_DIV(3);
break;
case 2:
pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1);
break;
default:
pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(2);
break;
}
CCM_ANALOG->MISC2 = (CCM_ANALOG->MISC2 & ~CCM_ANALOG_MISC2_VIDEO_DIV_MASK) | misc2;
CCM_ANALOG->PLL_VIDEO = pllVideo;
while ((CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_LOCK_MASK) == 0)
{
}
}
void CLOCK_DeinitVideoPll(void)
{
CCM_ANALOG->PLL_VIDEO = CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK;
}
void CLOCK_InitEnetPll(const clock_enet_pll_config_t *config)
{
uint32_t enet_pll = CCM_ANALOG_PLL_ENET_ENET1_DIV_SELECT(config->loopDivider1) |
CCM_ANALOG_PLL_ENET_ENET0_DIV_SELECT(config->loopDivider0);
if (config->enableClkOutput0)
{
enet_pll |= CCM_ANALOG_PLL_ENET_ENET1_125M_EN_MASK;
}
if (config->enableClkOutput1)
{
enet_pll |= CCM_ANALOG_PLL_ENET_ENET2_125M_EN_MASK;
}
if (config->enableClkOutput2)
{
enet_pll |= CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_MASK;
}
CCM_ANALOG->PLL_ENET = enet_pll;
/* Wait for stable */
while ((CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_LOCK_MASK) == 0)
{
}
}
void CLOCK_DeinitEnetPll(void)
{
CCM_ANALOG->PLL_ENET = CCM_ANALOG_PLL_ENET_POWERDOWN_MASK;
}
uint32_t CLOCK_GetPllFreq(clock_pll_t pll)
{
uint32_t freq;
uint32_t divSelect;
uint64_t freqTmp;
const uint32_t enetRefClkFreq[] = {
25000000U, /* 25M */
50000000U, /* 50M */
100000000U, /* 100M */
125000000U /* 125M */
};
switch (pll)
{
case kCLOCK_PllArm:
freq = ((CLOCK_GetOscFreq() * ((CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK) >>
CCM_ANALOG_PLL_ARM_DIV_SELECT_SHIFT)) >> 1U);
break;
case kCLOCK_PllSys:
freq = CLOCK_GetOscFreq();
/* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
freqTmp = ((uint64_t)freq * ((uint64_t)(CCM_ANALOG->PLL_SYS_NUM))) / ((uint64_t)(CCM_ANALOG->PLL_SYS_DENOM));
if (CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK)
{
freq *= 22U;
}
else
{
freq *= 20U;
}
freq += (uint32_t)freqTmp;
break;
case kCLOCK_PllUsb1:
freq = (CLOCK_GetOscFreq() * ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK) ? 22U : 20U));
break;
case kCLOCK_PllAudio:
freq = CLOCK_GetOscFreq();
/* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
divSelect = (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_AUDIO_DIV_SELECT_SHIFT;
freqTmp = ((uint64_t)freq * ((uint64_t)(CCM_ANALOG->PLL_AUDIO_NUM))) / ((uint64_t)(CCM_ANALOG->PLL_AUDIO_DENOM));
freq = freq * divSelect + (uint32_t)freqTmp;
/* AUDIO PLL output = PLL output frequency / POSTDIV. */
/*
* Post divider:
*
* PLL_AUDIO[POST_DIV_SELECT]:
* 0x00: 4
* 0x01: 2
* 0x02: 1
*
* MISC2[AUDO_DIV]:
* 0x00: 1
* 0x01: 2
* 0x02: 1
* 0x03: 4
*/
switch (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT_MASK)
{
case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0U):
freq = freq >> 2U;
break;
case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1U):
freq = freq >> 1U;
break;
default:
break;
}
switch (CCM_ANALOG->MISC2 & (CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK))
{
case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(1) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1):
freq >>= 2U;
break;
case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(0) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1):
freq >>= 1U;
break;
default:
break;
}
break;
case kCLOCK_PllVideo:
freq = CLOCK_GetOscFreq();
/* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
divSelect = (CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_VIDEO_DIV_SELECT_SHIFT;
freqTmp = ((uint64_t)freq * ((uint64_t)(CCM_ANALOG->PLL_VIDEO_NUM))) / ((uint64_t)(CCM_ANALOG->PLL_VIDEO_DENOM));
freq = freq * divSelect + (uint32_t)freqTmp;
/* VIDEO PLL output = PLL output frequency / POSTDIV. */
/*
* Post divider:
*
* PLL_VIDEO[POST_DIV_SELECT]:
* 0x00: 4
* 0x01: 2
* 0x02: 1
*
* MISC2[VIDEO_DIV]:
* 0x00: 1
* 0x01: 2
* 0x02: 1
* 0x03: 4
*/
switch (CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT_MASK)
{
case CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(0U):
freq = freq >> 2U;
break;
case CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1U):
freq = freq >> 1U;
break;
default:
break;
}
switch (CCM_ANALOG->MISC2 & CCM_ANALOG_MISC2_VIDEO_DIV_MASK)
{
case CCM_ANALOG_MISC2_VIDEO_DIV(3):
freq >>= 2U;
break;
case CCM_ANALOG_MISC2_VIDEO_DIV(1):
freq >>= 1U;
break;
default:
break;
}
break;
case kCLOCK_PllEnet0:
divSelect = (CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_ENET0_DIV_SELECT_MASK)
>> CCM_ANALOG_PLL_ENET_ENET0_DIV_SELECT_SHIFT;
freq = enetRefClkFreq[divSelect];
break;
case kCLOCK_PllEnet1:
divSelect = (CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_ENET1_DIV_SELECT_MASK)
>> CCM_ANALOG_PLL_ENET_ENET1_DIV_SELECT_SHIFT;
freq = enetRefClkFreq[divSelect];
break;
case kCLOCK_PllEnet2:
/* ref_enetpll2 if fixed at 25MHz. */
freq = 25000000UL;
break;
case kCLOCK_PllUsb2:
freq = (CLOCK_GetOscFreq() * ((CCM_ANALOG->PLL_USB2 & CCM_ANALOG_PLL_USB2_DIV_SELECT_MASK) ? 22U : 20U));
break;
default:
freq = 0U;
break;
}
return freq;
}
void CLOCK_InitSysPfd(clock_pfd_t pfd, uint8_t pfdFrac)
{
uint32_t pfdIndex = (uint32_t)pfd;
uint32_t pfd528;
pfd528 = CCM_ANALOG->PFD_528 & ~((CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK | CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) << (8 * pfdIndex));
/* Disable the clock output first. */
CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8 * pfdIndex));
/* Set the new value and enable output. */
CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_FRAC(pfdFrac) << (8 * pfdIndex));
}
void CLOCK_DeinitSysPfd(clock_pfd_t pfd)
{
CCM_ANALOG->PFD_528 |= CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8 * pfd);
}
void CLOCK_InitUsb1Pfd(clock_pfd_t pfd, uint8_t pfdFrac)
{
uint32_t pfdIndex = (uint32_t)pfd;
uint32_t pfd480;
pfd480 = CCM_ANALOG->PFD_480 & ~((CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK | CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) << (8 * pfdIndex));
/* Disable the clock output first. */
CCM_ANALOG->PFD_480 = pfd480 | (CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8 * pfdIndex));
/* Set the new value and enable output. */
CCM_ANALOG->PFD_480 = pfd480 | (CCM_ANALOG_PFD_480_PFD0_FRAC(pfdFrac) << (8 * pfdIndex));
}
void CLOCK_DeinitUsb1Pfd(clock_pfd_t pfd)
{
CCM_ANALOG->PFD_480 |= CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8 * pfd);
}
uint32_t CLOCK_GetSysPfdFreq(clock_pfd_t pfd)
{
uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
switch (pfd)
{
case kCLOCK_Pfd0:
freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD0_FRAC_SHIFT);
break;
case kCLOCK_Pfd1:
freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD1_FRAC_SHIFT);
break;
case kCLOCK_Pfd2:
freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD2_FRAC_SHIFT);
break;
case kCLOCK_Pfd3:
freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD3_FRAC_SHIFT);
break;
default:
freq = 0U;
break;
}
freq *= 18U;
return freq;
}
uint32_t CLOCK_GetUsb1PfdFreq(clock_pfd_t pfd)
{
uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
switch (pfd)
{
case kCLOCK_Pfd0:
freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
break;
case kCLOCK_Pfd1:
freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD1_FRAC_SHIFT);
break;
case kCLOCK_Pfd2:
freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD2_FRAC_SHIFT);
break;
case kCLOCK_Pfd3:
freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD3_FRAC_SHIFT);
break;
default:
freq = 0U;
break;
}
freq *= 18U;
return freq;
}
bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq)
{
CCM->CCGR6 |= CCM_CCGR6_CG0_MASK ;
USB1->USBCMD |= USBHS_USBCMD_RST_MASK;
PMU->REG_3P0 = (PMU->REG_3P0 & (~PMU_REG_3P0_OUTPUT_TRG_MASK)) | (PMU_REG_3P0_OUTPUT_TRG(0x17) | PMU_REG_3P0_ENABLE_LINREG_MASK);
return true;
}
bool CLOCK_EnableUsbhs1Clock(clock_usb_src_t src, uint32_t freq)
{
CCM->CCGR6 |= CCM_CCGR6_CG0_MASK ;
USB1->USBCMD |= USBHS_USBCMD_RST_MASK;
PMU->REG_3P0 = (PMU->REG_3P0 & (~PMU_REG_3P0_OUTPUT_TRG_MASK)) | (PMU_REG_3P0_OUTPUT_TRG(0x17) | PMU_REG_3P0_ENABLE_LINREG_MASK);
return true;
}
bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
{
const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U};
CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll);
USBPHY1->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */
USBPHY1->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK;
USBPHY1->PWD = 0;
USBPHY1->CTRL |=
USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK |
USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK |
USBPHY_CTRL_ENUTMILEVEL2_MASK |
USBPHY_CTRL_ENUTMILEVEL3_MASK;
return true;
}
bool CLOCK_EnableUsbhs1PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
{
const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U};
CLOCK_InitUsb2Pll(&g_ccmConfigUsbPll);
USBPHY2->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */
USBPHY2->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK;
USBPHY2->PWD = 0;
USBPHY2->CTRL |=
USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK |
USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK |
USBPHY_CTRL_ENUTMILEVEL2_MASK |
USBPHY_CTRL_ENUTMILEVEL3_MASK;
return true;
}
void CLOCK_DisableUsbhs0PhyPllClock(void)
{
CLOCK_DeinitUsb1Pll();
USBPHY1->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
}
void CLOCK_DisableUsbhs1PhyPllClock(void)
{
CLOCK_DeinitUsb2Pll();
USBPHY2->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,207 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_common.h"
#include <rtthread.h>
#define PRINTF rt_kprintf
#define SDK_MEM_MAGIC_NUMBER 12345U
typedef struct _mem_align_control_block
{
uint16_t identifier; /*!< Identifier for the memory control block. */
uint16_t offset; /*!< offset from aligned adress to real address */
} mem_align_cb_t;
#ifndef NDEBUG
#if (defined(__CC_ARM)) || (defined(__ICCARM__))
void __aeabi_assert(const char *failedExpr, const char *file, int line)
{
PRINTF("ASSERT ERROR \" %s \": file \"%s\" Line \"%d\" \n", failedExpr, file, line);
for (;;)
{
__BKPT(0);
}
}
#elif(defined(__GNUC__))
void __assert_func(const char *file, int line, const char *func, const char *failedExpr)
{
PRINTF("ASSERT ERROR \" %s \": file \"%s\" Line \"%d\" function name \"%s\" \n", failedExpr, file, line, func);
for (;;)
{
__BKPT(0);
}
}
#endif /* (defined(__CC_ARM)) || (defined (__ICCARM__)) */
#endif /* NDEBUG */
#ifndef __GIC_PRIO_BITS
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler)
{
/* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
#if defined(__CC_ARM)
extern uint32_t Image$$VECTOR_ROM$$Base[];
extern uint32_t Image$$VECTOR_RAM$$Base[];
extern uint32_t Image$$RW_m_data$$Base[];
#define __VECTOR_TABLE Image$$VECTOR_ROM$$Base
#define __VECTOR_RAM Image$$VECTOR_RAM$$Base
#define __RAM_VECTOR_TABLE_SIZE (((uint32_t)Image$$RW_m_data$$Base - (uint32_t)Image$$VECTOR_RAM$$Base))
#elif defined(__ICCARM__)
extern uint32_t __RAM_VECTOR_TABLE_SIZE[];
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
#elif defined(__GNUC__)
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
extern uint32_t __RAM_VECTOR_TABLE_SIZE_BYTES[];
uint32_t __RAM_VECTOR_TABLE_SIZE = (uint32_t)(__RAM_VECTOR_TABLE_SIZE_BYTES);
#endif /* defined(__CC_ARM) */
uint32_t n;
uint32_t ret;
uint32_t irqMaskValue;
irqMaskValue = DisableGlobalIRQ();
if (SCB->VTOR != (uint32_t)__VECTOR_RAM)
{
/* Copy the vector table from ROM to RAM */
for (n = 0; n < ((uint32_t)__RAM_VECTOR_TABLE_SIZE) / sizeof(uint32_t); n++)
{
__VECTOR_RAM[n] = __VECTOR_TABLE[n];
}
/* Point the VTOR to the position of vector table */
SCB->VTOR = (uint32_t)__VECTOR_RAM;
}
ret = __VECTOR_RAM[irq + 16];
/* make sure the __VECTOR_RAM is noncachable */
__VECTOR_RAM[irq + 16] = irqHandler;
EnableGlobalIRQ(irqMaskValue);
return ret;
}
#endif
#ifndef CPU_QN908X
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
void EnableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t index = 0;
uint32_t intNumber = (uint32_t)interrupt;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
SYSCON->STARTERSET[index] = 1u << intNumber;
EnableIRQ(interrupt); /* also enable interrupt at NVIC */
}
void DisableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t index = 0;
uint32_t intNumber = (uint32_t)interrupt;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
DisableIRQ(interrupt); /* also disable interrupt at NVIC */
SYSCON->STARTERCLR[index] = 1u << intNumber;
}
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
#else
void EnableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t index = 0;
uint32_t intNumber = (uint32_t)interrupt;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
/* SYSCON->STARTERSET[index] = 1u << intNumber; */
EnableIRQ(interrupt); /* also enable interrupt at NVIC */
}
void DisableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t index = 0;
uint32_t intNumber = (uint32_t)interrupt;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
DisableIRQ(interrupt); /* also disable interrupt at NVIC */
/* SYSCON->STARTERCLR[index] = 1u << intNumber; */
}
#endif /*CPU_QN908X */
void *SDK_Malloc(size_t size, size_t alignbytes)
{
mem_align_cb_t *p_cb = NULL;
uint32_t alignedsize = SDK_SIZEALIGN(size, alignbytes) + alignbytes + sizeof(mem_align_cb_t);
void *p_align_addr, *p_addr = malloc(alignedsize);
if (!p_addr)
{
return NULL;
}
p_align_addr = (void *)SDK_SIZEALIGN((uint32_t)p_addr + sizeof(mem_align_cb_t), alignbytes);
p_cb = (mem_align_cb_t *)((uint32_t)p_align_addr - 4);
p_cb->identifier = SDK_MEM_MAGIC_NUMBER;
p_cb->offset = (uint32_t)p_align_addr - (uint32_t)p_addr;
return (void *)p_align_addr;
}
void SDK_Free(void *ptr)
{
mem_align_cb_t *p_cb = (mem_align_cb_t *)((uint32_t)ptr - 4);
if (p_cb->identifier != SDK_MEM_MAGIC_NUMBER)
{
return;
}
free((void *)((uint32_t)ptr - p_cb->offset));
}

View File

@ -0,0 +1,487 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_COMMON_H_
#define _FSL_COMMON_H_
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#if defined(__ICCARM__)
#include <stddef.h>
#endif
#include "fsl_device_registers.h"
/*!
* @addtogroup ksdk_common
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Construct a status code value from a group and code number. */
#define MAKE_STATUS(group, code) ((((group)*100) + (code)))
/*! @brief Construct the version number for drivers. */
#define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
/* Debug console type definition. */
#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */
#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */
#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console base on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console base on i.MX UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_VUSART 7U /*!< Debug console base on LPC_USART. */
/*! @brief Status group numbers. */
enum _status_groups
{
kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */
kStatusGroup_FLASH = 1, /*!< Group number for FLASH status codes. */
kStatusGroup_LPSPI = 4, /*!< Group number for LPSPI status codes. */
kStatusGroup_FLEXIO_SPI = 5, /*!< Group number for FLEXIO SPI status codes. */
kStatusGroup_DSPI = 6, /*!< Group number for DSPI status codes. */
kStatusGroup_FLEXIO_UART = 7, /*!< Group number for FLEXIO UART status codes. */
kStatusGroup_FLEXIO_I2C = 8, /*!< Group number for FLEXIO I2C status codes. */
kStatusGroup_LPI2C = 9, /*!< Group number for LPI2C status codes. */
kStatusGroup_UART = 10, /*!< Group number for UART status codes. */
kStatusGroup_I2C = 11, /*!< Group number for UART status codes. */
kStatusGroup_LPSCI = 12, /*!< Group number for LPSCI status codes. */
kStatusGroup_LPUART = 13, /*!< Group number for LPUART status codes. */
kStatusGroup_SPI = 14, /*!< Group number for SPI status code.*/
kStatusGroup_XRDC = 15, /*!< Group number for XRDC status code.*/
kStatusGroup_SEMA42 = 16, /*!< Group number for SEMA42 status code.*/
kStatusGroup_SDHC = 17, /*!< Group number for SDHC status code */
kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */
kStatusGroup_SAI = 19, /*!< Group number for SAI status code */
kStatusGroup_MCG = 20, /*!< Group number for MCG status codes. */
kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */
kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */
kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */
kStatusGroup_FLEXIO_MCULCD = 24, /*!< Group number for FLEXIO LCD status codes */
kStatusGroup_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */
kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */
kStatusGroup_I2S = 27, /*!< Group number for I2S status codes */
kStatusGroup_IUART = 28, /*!< Group number for IUART status codes */
kStatusGroup_CSI = 29, /*!< Group number for CSI status codes */
kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */
kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */
kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */
kStatusGroup_PHY = 41, /*!< Group number for PHY status codes. */
kStatusGroup_TRGMUX = 42, /*!< Group number for TRGMUX status codes. */
kStatusGroup_SMARTCARD = 43, /*!< Group number for SMARTCARD status codes. */
kStatusGroup_LMEM = 44, /*!< Group number for LMEM status codes. */
kStatusGroup_QSPI = 45, /*!< Group number for QSPI status codes. */
kStatusGroup_DMA = 50, /*!< Group number for DMA status codes. */
kStatusGroup_EDMA = 51, /*!< Group number for EDMA status codes. */
kStatusGroup_DMAMGR = 52, /*!< Group number for DMAMGR status codes. */
kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */
kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */
kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */
kStatusGroup_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */
kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */
kStatusGroup_DMIC = 58, /*!< Group number for DMIC status codes. */
kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/
kStatusGroup_SPIFI = 60, /*!< Group number for SPIFI status codes. */
kStatusGroup_OTP = 61, /*!< Group number for OTP status codes. */
kStatusGroup_MCAN = 62, /*!< Group number for MCAN status codes. */
kStatusGroup_CAAM = 63, /*!< Group number for CAAM status codes. */
kStatusGroup_ECSPI = 64, /*!< Group number for ECSPI status codes. */
kStatusGroup_USDHC = 65, /*!< Group number for USDHC status codes.*/
kStatusGroup_LPC_I2C = 66, /*!< Group number for LPC_I2C status codes.*/
kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */
kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */
kStatusGroup_MMDC = 71, /*!< Group number for MMDC status codes. */
kStatusGroup_MICFIL = 72, /*!< Group number for MIC status codes. */
kStatusGroup_SDMA = 73, /*!< Group number for SDMA status codes. */
kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */
kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */
kStatusGroup_ApplicationRangeStart = 100, /*!< Starting number for application groups. */
};
/*! @brief Generic status return codes. */
enum _generic_status
{
kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0),
kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1),
kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2),
kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3),
kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4),
kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5),
kStatus_NoTransferInProgress = MAKE_STATUS(kStatusGroup_Generic, 6),
};
/*! @brief Type used for all status and error return values. */
typedef int32_t status_t;
/*
* The fsl_clock.h is included here because it needs MAKE_VERSION/MAKE_STATUS/status_t
* defined in previous of this file.
*/
#include "fsl_clock.h"
/*
* Chip level peripheral reset API, for MCUs that implement peripheral reset control external to a peripheral
*/
#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \
(defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0)))
#include "fsl_reset.h"
#endif
/*! @name Min/max macros */
/* @{ */
#if !defined(MIN)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#if !defined(MAX)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
/* @} */
/*! @brief Computes the number of elements in an array. */
#if !defined(ARRAY_SIZE)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
/*! @name UINT16_MAX/UINT32_MAX value */
/* @{ */
#if !defined(UINT16_MAX)
#define UINT16_MAX ((uint16_t)-1)
#endif
#if !defined(UINT32_MAX)
#define UINT32_MAX ((uint32_t)-1)
#endif
/* @} */
/*! @name Timer utilities */
/* @{ */
/*! Macro to convert a microsecond period to raw count value */
#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)((uint64_t)us * clockFreqInHz / 1000000U)
/*! Macro to convert a raw count value to microsecond */
#define COUNT_TO_USEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000000U / clockFreqInHz)
/*! Macro to convert a millisecond period to raw count value */
#define MSEC_TO_COUNT(ms, clockFreqInHz) (uint64_t)((uint64_t)ms * clockFreqInHz / 1000U)
/*! Macro to convert a raw count value to millisecond */
#define COUNT_TO_MSEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000U / clockFreqInHz)
/* @} */
/*! @name Alignment variable definition macros */
/* @{ */
#if (defined(__ICCARM__))
/**
* Workaround to disable MISRA C message suppress warnings for IAR compiler.
* http://supp.iar.com/Support/?note=24725
*/
_Pragma("diag_suppress=Pm120")
#define SDK_PRAGMA(x) _Pragma(#x)
_Pragma("diag_error=Pm120")
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) SDK_PRAGMA(data_alignment = FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) var
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) SDK_PRAGMA(data_alignment = FSL_FEATURE_L2CACHE_LINESIZE_BYTE) var
#endif
#elif defined(__CC_ARM)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) __align(alignbytes) var
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) __align(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) var
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) __align(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) var
#endif
#elif defined(__GNUC__)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) var __attribute__((aligned(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)))
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) var __attribute__((aligned(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)))
#endif
#else
#error Toolchain not supported
#define SDK_ALIGN(var, alignbytes) var
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) var
#endif
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) var
#endif
#endif
/*! Macro to change a value to a given size aligned value */
#define SDK_SIZEALIGN(var, alignbytes) \
((unsigned int)((var) + ((alignbytes)-1)) & (unsigned int)(~(unsigned int)((alignbytes)-1)))
/* @} */
/*! Function to allocate/free L1 cache aligned memory using the malloc/free. */
void *SDK_Malloc(size_t size, size_t alignbytes);
void SDK_Free(void *ptr);
/* @} */
/*! @name Non-cacheable region definition macros */
/* @{ */
#if (defined(__ICCARM__))
#if defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)
#define AT_NONCACHEABLE_SECTION(var) var @"NonCacheable"
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable"
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
#endif
#elif(defined(__CC_ARM))
#if defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable"), zero_init)) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable"), zero_init)) __align(alignbytes) var
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) __align(alignbytes) var
#endif
#elif(defined(__GNUC__))
/* For GCC, when the non-cacheable section is required, please define "__STARTUP_INITIALIZE_NONCACHEDATA"
* in your projects to make sure the non-cacheable section variables will be initialized in system startup.
*/
#if defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable"))) var __attribute__((aligned(alignbytes)))
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
#endif
#else
#error Toolchain not supported.
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) var
#endif
/* @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C"
{
#endif
/*!
* @brief Enable specific interrupt.
*
* Enable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only enables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt enabled successfully
* @retval kStatus_Fail Failed to enable the interrupt
*/
static inline status_t EnableIRQ(IRQn_Type interrupt)
{
if (NotAvail_IRQn == interrupt)
{
return kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
if (interrupt >= FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
return kStatus_Fail;
}
#endif
#if defined(__GIC_PRIO_BITS)
extern void rt_hw_interrupt_umask(int vector);
rt_hw_interrupt_umask(interrupt);
#else
NVIC_EnableIRQ(interrupt);
#endif
return kStatus_Success;
}
/*!
* @brief Disable specific interrupt.
*
* Disable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only disables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt disabled successfully
* @retval kStatus_Fail Failed to disable the interrupt
*/
static inline status_t DisableIRQ(IRQn_Type interrupt)
{
if (NotAvail_IRQn == interrupt)
{
return kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
if (interrupt >= FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
return kStatus_Fail;
}
#endif
#if defined(__GIC_PRIO_BITS)
extern void rt_hw_interrupt_mask(int vector);
rt_hw_interrupt_mask(interrupt);
#else
NVIC_DisableIRQ(interrupt);
#endif
return kStatus_Success;
}
/*!
* @brief Disable the global IRQ
*
* Disable the global interrupt and return the current primask register. User is required to provided the primask
* register for the EnableGlobalIRQ().
*
* @return Current primask value.
*/
static inline uint32_t DisableGlobalIRQ(void)
{
#if defined(CPSR_I_Msk)
uint32_t cpsr = __get_CPSR() & CPSR_I_Msk;
__disable_irq();
return cpsr;
#else
uint32_t regPrimask = __get_PRIMASK();
__disable_irq();
return regPrimask;
#endif
}
/*!
* @brief Enaable the global IRQ
*
* Set the primask register with the provided primask value but not just enable the primask. The idea is for the
* convinience of integration of RTOS. some RTOS get its own management mechanism of primask. User is required to
* use the EnableGlobalIRQ() and DisableGlobalIRQ() in pair.
*
* @param primask value of primask register to be restored. The primask value is supposed to be provided by the
* DisableGlobalIRQ().
*/
static inline void EnableGlobalIRQ(uint32_t primask)
{
#if defined(CPSR_I_Msk)
__set_CPSR((__get_CPSR() & ~CPSR_I_Msk) | primask);
#else
__set_PRIMASK(primask);
#endif
}
/*!
* @brief install IRQ handler
*
* @param irq IRQ number
* @param irqHandler IRQ handler address
* @return The old IRQ handler address
*/
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler);
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
/*!
* @brief Enable specific interrupt for wake-up from deep-sleep mode.
*
* Enable the interrupt for wake-up from deep sleep mode.
* Some interrupts are typically used in sleep mode only and will not occur during
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
* those clocks (significantly increasing power consumption in the reduced power mode),
* making these wake-ups possible.
*
* @note This function also enables the interrupt in the NVIC (EnableIRQ() is called internally).
*
* @param interrupt The IRQ number.
*/
void EnableDeepSleepIRQ(IRQn_Type interrupt);
/*!
* @brief Disable specific interrupt for wake-up from deep-sleep mode.
*
* Disable the interrupt for wake-up from deep sleep mode.
* Some interrupts are typically used in sleep mode only and will not occur during
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
* those clocks (significantly increasing power consumption in the reduced power mode),
* making these wake-ups possible.
*
* @note This function also disables the interrupt in the NVIC (DisableIRQ() is called internally).
*
* @param interrupt The IRQ number.
*/
void DisableDeepSleepIRQ(IRQn_Type interrupt);
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_COMMON_H_ */

View File

@ -0,0 +1,778 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_ecspi.h"
/*******************************************************************************
* Definitons
******************************************************************************/
/*! @brief ECSPI transfer state, which is used for ECSPI transactiaonl APIs' internal state. */
enum _ecspi_transfer_states_t
{
kECSPI_Idle = 0x0, /*!< ECSPI is idle state */
kECSPI_Busy /*!< ECSPI is busy tranferring data. */
};
/*! @brief Typedef for ecspi master interrupt handler. ecspi master and slave handle is the same. */
typedef void (*ecspi_isr_t)(ECSPI_Type *base, ecspi_master_handle_t *ecspiHandle);
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get the instance for ECSPI module.
*
* @param base ECSPI base address
*/
uint32_t ECSPI_GetInstance(ECSPI_Type *base);
/*!
* @brief Sends a buffer of data bytes in non-blocking way.
*
* @param base ECSPI base pointer
* @param buffer The data bytes to send
* @param size The number of data bytes to send
*/
static void ECSPI_WriteNonBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size);
/*!
* @brief Receive a buffer of data bytes in non-blocking way.
*
* @param base ECSPI base pointer
* @param buffer The data bytes to send
* @param size The number of data bytes to send
*/
static void ECSPI_ReadNonBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size);
/*!
* @brief Send a piece of data for ECSPI.
*
* This function computes the number of data to be written into D register or Tx FIFO,
* and write the data into it. At the same time, this function updates the values in
* master handle structure.
*
* @param base ECSPI base pointer
* @param handle Pointer to ECSPI master handle structure.
*/
static void ECSPI_SendTransfer(ECSPI_Type *base, ecspi_master_handle_t *handle);
/*!
* @brief Receive a piece of data for ECSPI master.
*
* This function computes the number of data to receive from D register or Rx FIFO,
* and write the data to destination address. At the same time, this function updates
* the values in master handle structure.
*
* @param base ECSPI base pointer
* @param handle Pointer to ECSPI master handle structure.
*/
static void ECSPI_ReceiveTransfer(ECSPI_Type *base, ecspi_master_handle_t *handle);
/*!
* @brief Sets the ECSPI channel configuration structure to default values.
*
* This function is to get the channel configuration structure initialized for use in ECSPI_SetChannelConfig().
* User may use the initialized structure unchanged in ECSPI_SetChannelConfig(), or modify
* some fields of the structure before calling ECSPI_SetChannelConfig().
*
* @param config pointer to config structure
*/
static void ECSPI_GetDefaultChannelConfig(ecspi_channel_config_t *config);
/*!
* @brief Common IRQ handler for SPI.
*
* @param base SPI base pointer.
* @param instance SPI instance number.
*/
static void ECSPI_CommonIRQHandler(ECSPI_Type *base, ecspi_master_handle_t *handle);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Base pointer array */
static ECSPI_Type *const s_ecspiBases[] = ECSPI_BASE_PTRS;
/*! @brief ECSPI internal handle pointer array */
static ecspi_master_handle_t *s_ecspiHandle[ARRAY_SIZE(s_ecspiBases)];
/*! @brief IRQ name array */
static const IRQn_Type s_ecspiIRQ[] = ECSPI_IRQS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Clock array name */
static const clock_ip_name_t s_ecspiClock[] = ECSPI_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*! @brief Pointer to master IRQ handler for each instance. */
static ecspi_isr_t s_ecspiMasterIsr;
/*! @brief Pointer to slave IRQ handler for each instance. */
static ecspi_isr_t s_ecspiSlaveIsr;
/*******************************************************************************
* Code
******************************************************************************/
uint32_t ECSPI_GetInstance(ECSPI_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_ecspiBases); instance++)
{
if (s_ecspiBases[instance] == base)
{
break;
}
}
assert(instance <= ARRAY_SIZE(s_ecspiBases));
return instance;
}
static void ECSPI_WriteNonBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size)
{
size_t i = 0U;
for (i = 0U; i < size; i++)
{
if (buffer != NULL)
{
base->TXDATA = *buffer++;
}
else
{
ECSPI_WriteData(base, ECSPI_DUMMYDATA);
}
}
}
static void ECSPI_ReadNonBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size)
{
if (NULL != buffer)
{
while (size--)
{
*buffer++ = ECSPI_ReadData(base);
}
}
else
{
while (size--)
{
(void)ECSPI_ReadData(base);
}
}
}
static void ECSPI_SendTransfer(ECSPI_Type *base, ecspi_master_handle_t *handle)
{
assert(base);
assert(handle);
uint32_t dataCounts = 0U;
/* Caculate the data size to send */
dataCounts = (FSL_FEATURE_ECSPI_TX_FIFO_SIZEn(base) - ECSPI_GetTxFifoCount(base)) < (handle->txRemainingBytes) ?
(FSL_FEATURE_ECSPI_TX_FIFO_SIZEn(base) - ECSPI_GetTxFifoCount(base)) :
(handle->txRemainingBytes);
while (dataCounts--)
{
ECSPI_WriteNonBlocking(base, handle->txData, 1);
if (NULL != handle->txData)
{
handle->txData += 1U;
}
handle->txRemainingBytes -= 1U;
}
}
static void ECSPI_ReceiveTransfer(ECSPI_Type *base, ecspi_master_handle_t *handle)
{
assert(base);
uint32_t dataCounts = 0U;
/* Caculate the data size need to receive */
dataCounts =
(ECSPI_GetRxFifoCount(base) < handle->rxRemainingBytes) ? ECSPI_GetRxFifoCount(base) : handle->rxRemainingBytes;
ECSPI_ReadNonBlocking(base, handle->rxData, dataCounts);
if (NULL != handle->rxData)
{
handle->rxData += dataCounts;
}
handle->rxRemainingBytes -= dataCounts;
}
static void ECSPI_GetDefaultChannelConfig(ecspi_channel_config_t *config)
{
config->channelMode = kECSPI_Slave; /*!< ECSPI peripheral operates in slave mode.*/
config->clockInactiveState = kECSPI_ClockInactiveStateLow; /*!< Clock line (SCLK) inactive state */
config->dataLineInactiveState = kECSPI_DataLineInactiveStateLow; /*!< Data line (MOSI&MISO) inactive state */
config->chipSlectActiveState = kECSPI_ChipSelectActiveStateLow; /*!< Chip select(SS) line active state */
config->waveForm = kECSPI_WaveFormSingle; /*!< ECSPI SS wave form */
config->polarity = kECSPI_PolarityActiveHigh; /*!< Clock polarity */
config->phase = kECSPI_ClockPhaseFirstEdge; /*!< clock phase */
}
void ECSPI_MasterGetDefaultConfig(ecspi_master_config_t *config)
{
config->channel = kECSPI_Channel0;
config->burstLength = 8;
config->samplePeriodClock = kECSPI_spiClock;
config->baudRate_Bps = 500000;
config->chipSelectDelay = 0;
config->samplePeriod = 0;
config->txFifoThreshold = 1;
config->rxFifoThreshold = 0;
/* Default configuration of channel */
ECSPI_GetDefaultChannelConfig(&config->channelConfig);
/*!< ECSPI peripheral operates in slave mode.*/
config->channelConfig.channelMode = kECSPI_Master;
}
void ECSPI_MasterInit(ECSPI_Type *base, const ecspi_master_config_t *config, uint32_t srcClock_Hz)
{
assert(config && srcClock_Hz);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Open clock gate for SPI and open interrupt */
CLOCK_EnableClock(s_ecspiClock[ECSPI_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Reset control register to default value */
ECSPI_SoftwareReset(base);
/* Config CONREG register */
base->CONREG = ECSPI_CONREG_BURST_LENGTH(config->burstLength - 1) | ECSPI_CONREG_SMC(1) | ECSPI_CONREG_EN(1);
/* Config CONFIGREG register */
ECSPI_SetChannelConfig(base, config->channel, &config->channelConfig);
/* Config DMAREG register */
base->DMAREG |=
ECSPI_DMAREG_TX_THRESHOLD(config->txFifoThreshold) | ECSPI_DMAREG_RX_THRESHOLD(config->rxFifoThreshold);
/* Config PERIODREG register */
base->PERIODREG |= ECSPI_PERIODREG_CSRC(config->samplePeriodClock) |
ECSPI_PERIODREG_SAMPLE_PERIOD(config->samplePeriod) |
ECSPI_PERIODREG_CSD_CTL(config->chipSelectDelay);
/* Set baud rate */
ECSPI_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
}
void ECSPI_SlaveGetDefaultConfig(ecspi_slave_config_t *config)
{
/* Default configuration of channel nember */
config->channel = kECSPI_Channel0;
config->burstLength = 8;
config->txFifoThreshold = 1;
config->rxFifoThreshold = 0;
/* Set default channel configuration */
ECSPI_GetDefaultChannelConfig(&config->channelConfig);
/* ECSPI peripheral operates in slave mode.*/
config->channelConfig.channelMode = kECSPI_Slave;
}
void ECSPI_SlaveInit(ECSPI_Type *base, const ecspi_slave_config_t *config)
{
assert(base && config);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Open clock gate for SPI and open interrupt */
CLOCK_EnableClock(s_ecspiClock[ECSPI_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Reset control register to default value */
ECSPI_SoftwareReset(base);
/* Config CONREG register */
base->CONREG = ECSPI_CONREG_BURST_LENGTH(config->burstLength - 1) | ECSPI_CONREG_EN(1);
/* Config DMAREG register */
base->DMAREG |=
ECSPI_DMAREG_TX_THRESHOLD(config->txFifoThreshold) | ECSPI_DMAREG_RX_THRESHOLD(config->rxFifoThreshold);
/* Setup channel configuration */
ECSPI_SetChannelConfig(base, config->channel, &config->channelConfig);
}
void ECSPI_Deinit(ECSPI_Type *base)
{
/* Disable ECSPI module before shutting down */
base->CONREG &= ~ECSPI_CONREG_EN_MASK;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Gate the clock */
CLOCK_DisableClock(s_ecspiClock[ECSPI_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void ECSPI_SetBaudRate(ECSPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
{
assert(base);
uint8_t bestPreDividerValue = 0U, preDividerValue = 0U;
uint8_t bestPostDividerValue = 0U, postDividerValue = 0U;
uint32_t realBaudrate = 0U;
uint32_t diff = 0xFFFFFFFFU;
uint32_t min_diff = 0xFFFFFFFFU;
for (preDividerValue = 0; (preDividerValue < 16) && diff; preDividerValue++)
{
for (postDividerValue = 0; (postDividerValue < 16) && diff; postDividerValue++)
{
realBaudrate = (srcClock_Hz / (preDividerValue + 1)) >> postDividerValue;
if (realBaudrate > baudRate_Bps)
{
diff = realBaudrate - baudRate_Bps;
if (diff < min_diff)
{
min_diff = diff;
bestPreDividerValue = preDividerValue;
bestPostDividerValue = postDividerValue;
}
}
else
{
diff = baudRate_Bps - realBaudrate;
if (diff < min_diff)
{
min_diff = diff;
bestPreDividerValue = preDividerValue;
bestPostDividerValue = postDividerValue;
}
}
}
}
base->CONREG |= ECSPI_CONREG_PRE_DIVIDER(bestPreDividerValue) | ECSPI_CONREG_POST_DIVIDER(bestPostDividerValue);
}
void ECSPI_SetChannelConfig(ECSPI_Type *base, ecspi_channel_source_t channel, const ecspi_channel_config_t *config)
{
switch (channel)
{
case kECSPI_Channel0:
base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode);
base->CONFIGREG |=
(ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) |
ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) |
ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) | ECSPI_CONFIGREG_SS_CTL(config->waveForm) |
ECSPI_CONFIGREG_SCLK_POL(config->polarity) | ECSPI_CONFIGREG_SCLK_PHA(config->phase));
break;
case kECSPI_Channel1:
base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode) << 1;
base->CONFIGREG |=
((ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) << 1) |
(ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) << 1) |
(ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) << 1) |
(ECSPI_CONFIGREG_SS_CTL(config->waveForm) << 1) | (ECSPI_CONFIGREG_SCLK_POL(config->polarity) << 1) |
(ECSPI_CONFIGREG_SCLK_PHA(config->phase) << 1));
break;
case kECSPI_Channel2:
base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode) << 2;
base->CONFIGREG |=
((ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) << 2) |
(ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) << 2) |
(ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) << 2) |
(ECSPI_CONFIGREG_SS_CTL(config->waveForm) << 2) | (ECSPI_CONFIGREG_SCLK_POL(config->polarity) << 2) |
(ECSPI_CONFIGREG_SCLK_PHA(config->phase) << 2));
break;
case kECSPI_Channel3:
base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode) << 3;
base->CONFIGREG |=
((ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) << 3) |
(ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) << 3) |
(ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) << 3) |
(ECSPI_CONFIGREG_SS_CTL(config->waveForm) << 3) | (ECSPI_CONFIGREG_SCLK_POL(config->polarity) << 3) |
(ECSPI_CONFIGREG_SCLK_PHA(config->phase) << 3));
break;
default:
break;
}
}
void ECSPI_WriteBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size)
{
size_t i = 0U;
while (i < size)
{
/* Wait for TX fifo buffer empty */
while (!(base->STATREG & ECSPI_STATREG_TE_MASK))
{
}
/* Write data to tx register */
if (NULL != buffer)
{
ECSPI_WriteData(base, *buffer++);
}
else
{
ECSPI_WriteData(base, ECSPI_DUMMYDATA);
}
i++;
}
}
static status_t ECSPI_ReadBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size)
{
assert(base);
uint32_t state = 0U;
size_t i = 0U;
while (i < size)
{
/* Wait for RX FIFO buffer ready */
while (!(base->STATREG & ECSPI_STATREG_RR_MASK))
{
/* Get status flags of ECSPI */
state = ECSPI_GetStatusFlags(base);
/* If hardware overflow happen */
if (ECSPI_STATREG_RO_MASK & state)
{
/* Clear overflow flag for next transfer */
ECSPI_ClearStatusFlags(base, kECSPI_RxFifoOverFlowFlag);
return kStatus_ECSPI_HardwareOverFlow;
}
}
/* Read data from rx register */
if (NULL != buffer)
{
*buffer++ = ECSPI_ReadData(base);
}
else
{
(void)ECSPI_ReadData(base);
}
i++;
}
return kStatus_Success;
}
void ECSPI_MasterTransferCreateHandle(ECSPI_Type *base,
ecspi_master_handle_t *handle,
ecspi_master_callback_t callback,
void *userData)
{
assert(base);
assert(handle);
uint8_t instance = ECSPI_GetInstance(base);
/* Initialize the handle */
s_ecspiHandle[instance] = handle;
handle->callback = callback;
handle->userData = userData;
s_ecspiMasterIsr = ECSPI_MasterTransferHandleIRQ;
/* Enable ECSPI NVIC */
EnableIRQ(s_ecspiIRQ[instance]);
}
status_t ECSPI_MasterTransferBlocking(ECSPI_Type *base, ecspi_transfer_t *xfer)
{
assert(base && xfer);
status_t state;
uint32_t burstLength = 0U;
uint32_t dataCounts = 0U;
/* Check if the argument is legal */
if ((xfer->txData == NULL) && (xfer->rxData == NULL))
{
return kStatus_InvalidArgument;
}
/* Select ECSPI channel to current channel
* Note:
* xfer.channel must be configured before transfer, because every channel has
* it's own configuration,if don't configure this parameter, transfer channel
* will use the default channel0.
*/
ECSPI_SetChannelSelect(base, xfer->channel);
/* Caculate the data size need to be send for one burst */
burstLength = ((base->CONREG & ECSPI_CONREG_BURST_LENGTH_MASK) >> ECSPI_CONREG_BURST_LENGTH_SHIFT) + 1;
dataCounts = (burstLength % 32) ? (burstLength / 32 + 1) : (burstLength / 32);
while (xfer->dataSize > 0)
{
/* ECSPI will transmit and receive at the same time, if txData is NULL,
* instance will transmit dummy data, the dummy data can be set by user.
* if rxData is NULL, data will be read from RX FIFO buffer, but the
* data will be ignored by driver.
* Note that, txData and rxData can not be both NULL.
*/
ECSPI_WriteBlocking(base, xfer->txData, dataCounts);
if (NULL != xfer->txData)
{
xfer->txData += dataCounts;
}
state = ECSPI_ReadBlocking(base, xfer->rxData, dataCounts);
if ((kStatus_Success == state) && (NULL != xfer->rxData))
{
xfer->rxData += dataCounts;
}
if (kStatus_ECSPI_HardwareOverFlow == state)
{
return kStatus_ECSPI_HardwareOverFlow;
}
xfer->dataSize -= dataCounts;
}
return kStatus_Success;
}
status_t ECSPI_MasterTransferNonBlocking(ECSPI_Type *base, ecspi_master_handle_t *handle, ecspi_transfer_t *xfer)
{
assert(base && handle && xfer);
/* Check if ECSPI is busy */
if (handle->state == kECSPI_Busy)
{
return kStatus_ECSPI_Busy;
}
/* Check if the input arguments valid */
if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
/* Set the handle information */
handle->channel = xfer->channel;
handle->txData = xfer->txData;
handle->rxData = xfer->rxData;
handle->transferSize = xfer->dataSize;
handle->txRemainingBytes = xfer->dataSize;
handle->rxRemainingBytes = xfer->dataSize;
/* Set the ECSPI state to busy */
handle->state = kECSPI_Busy;
/* Select ECSPI channel to current channel
* Note:
* xfer.channel must be configured before transferfer, because every channel has
* it's own configuration, if don't configure this parameter, transfer channel
* will use the default channel0.
*/
ECSPI_SetChannelSelect(base, xfer->channel);
/* First send data to Tx FIFO to start a ECSPI transfer */
ECSPI_SendTransfer(base, handle);
if (NULL != xfer->rxData)
{
/* Enable Rx data request interrupt and receive overflow interrupt, when data in RX FIFO buffer is greater
* than the RX_THRESHOLD, then a interrupt occurred. Only enable Rx interrupt,
* use rx interrupt to driver ECSPI transfer.
*/
ECSPI_EnableInterrupts(base, kECSPI_RxFifoReadyInterruptEnable | kECSPI_RxFifoOverFlowInterruptEnable);
}
else
{
/* Enable Tx data request interrupt, when data in TX FIFO buffer is greater
* than the TX_THRESHOLD, then a interrupt occurred.
*/
ECSPI_EnableInterrupts(base, kECSPI_TxFifoDataRequstInterruptEnable);
}
return kStatus_Success;
}
status_t ECSPI_MasterTransferGetCount(ECSPI_Type *base, ecspi_master_handle_t *handle, size_t *count)
{
assert(handle);
status_t status = kStatus_Success;
if (handle->state != kStatus_ECSPI_Busy)
{
status = kStatus_NoTransferInProgress;
}
else
{
/* Return remaing bytes in different cases */
if (handle->rxData)
{
*count = handle->transferSize - handle->rxRemainingBytes;
}
else
{
*count = handle->transferSize - handle->txRemainingBytes;
}
}
return status;
}
void ECSPI_MasterTransferAbort(ECSPI_Type *base, ecspi_master_handle_t *handle)
{
assert(handle);
/* Stop interrupts */
if (NULL != handle->rxData)
{
ECSPI_DisableInterrupts(base, kECSPI_RxFifoReadyInterruptEnable | kECSPI_RxFifoOverFlowInterruptEnable);
}
else
{
ECSPI_DisableInterrupts(base, kECSPI_TxFifoDataRequstInterruptEnable);
}
/* Transfer finished, set the state to Done*/
handle->state = kECSPI_Idle;
/* Clear the internal state */
handle->rxRemainingBytes = 0;
handle->txRemainingBytes = 0;
}
void ECSPI_MasterTransferHandleIRQ(ECSPI_Type *base, ecspi_master_handle_t *handle)
{
assert(handle);
/* If hardware overflow happens */
if (base->STATREG & ECSPI_STATREG_RO_MASK)
{
/* Clear overflow flag for next transfer */
ECSPI_ClearStatusFlags(base, kECSPI_RxFifoOverFlowFlag);
if (handle->callback)
{
(handle->callback)(base, handle, kStatus_ECSPI_HardwareOverFlow, handle->userData);
}
}
/* If need to receive data, do a receive */
if (handle->rxRemainingBytes)
{
ECSPI_ReceiveTransfer(base, handle);
}
/* We always need to send a data to make the ECSPI run */
if (handle->txRemainingBytes)
{
ECSPI_SendTransfer(base, handle);
}
/* All the transfer finished */
if ((handle->txRemainingBytes == 0) && (handle->rxRemainingBytes == 0))
{
/* Complete the transfer */
ECSPI_MasterTransferAbort(base, handle);
if (handle->callback)
{
(handle->callback)(base, handle, kStatus_Success, handle->userData);
}
}
}
void ECSPI_SlaveTransferCreateHandle(ECSPI_Type *base,
ecspi_slave_handle_t *handle,
ecspi_slave_callback_t callback,
void *userData)
{
assert(handle);
/* Slave create handle share same logic with master create handle, the only difference
is the Isr pointer. */
ECSPI_MasterTransferCreateHandle(base, handle, callback, userData);
s_ecspiSlaveIsr = ECSPI_SlaveTransferHandleIRQ;
}
void ECSPI_SlaveTransferHandleIRQ(ECSPI_Type *base, ecspi_slave_handle_t *handle)
{
assert(handle);
/* If hardware overflow happens */
if (base->STATREG & ECSPI_STATREG_RO_MASK)
{
/* Clear overflow flag for next transfer */
ECSPI_ClearStatusFlags(base, kECSPI_RxFifoOverFlowFlag);
if (handle->callback)
{
(handle->callback)(base, handle, kStatus_ECSPI_HardwareOverFlow, handle->userData);
}
}
/* If needs to receive data, do a receive */
if (handle->rxRemainingBytes)
{
ECSPI_ReceiveTransfer(base, handle);
}
/* We always need to send a data to make the ECSPI run */
if (handle->txRemainingBytes)
{
ECSPI_SendTransfer(base, handle);
}
/* All the transfer finished */
if ((handle->txRemainingBytes == 0) && (handle->rxRemainingBytes == 0))
{
/* Complete the transfer */
ECSPI_SlaveTransferAbort(base, handle);
if (handle->callback)
{
(handle->callback)(base, handle, kStatus_Success, handle->userData);
}
}
}
static void ECSPI_CommonIRQHandler(ECSPI_Type *base, ecspi_master_handle_t *handle)
{
if (ECSPI_IsMaster(base, handle->channel))
{
s_ecspiMasterIsr(base, handle);
}
else
{
s_ecspiSlaveIsr(base, handle);
}
}
#if defined(ECSPI1)
void ECSPI1_DriverIRQHandler(void)
{
assert(s_ecspiHandle[1]);
ECSPI_CommonIRQHandler(ECSPI1, s_ecspiHandle[1]);
}
#endif /* ECSPI1 */
#if defined(ECSPI2)
void ECSPI2_DriverIRQHandler(void)
{
assert(s_ecspiHandle[2]);
ECSPI_CommonIRQHandler(ECSPI2, s_ecspiHandle[2]);
}
#endif /* ECSPI2 */
#if defined(ECSPI3)
void ECSPI3_DriverIRQHandler(void)
{
assert(s_ecspiHandle[3]);
ECSPI_CommonIRQHandler(ECSPI3, s_ecspiHandle[3]);
}
#endif /* ECSPI3 */
#if defined(ECSPI4)
void ECSPI4_DriverIRQHandler(void)
{
assert(s_ecspiHandle[4]);
ECSPI_CommonIRQHandler(ECSPI4, s_ecspiHandle[4]);
}
#endif /* ECSPI4 */

View File

@ -0,0 +1,749 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_ECSPI_H_
#define _FSL_ECSPI_H_
#include "fsl_common.h"
/*!
* @addtogroup ecspi_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief ECSPI driver version 2.0.0. */
#define FSL_ECSPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
#ifndef ECSPI_DUMMYDATA
/*! @brief ECSPI dummy transfer data, the data is sent while txBuff is NULL. */
#define ECSPI_DUMMYDATA (0xFFFFFFFFU)
#endif
/*! @brief Return status for the ECSPI driver. */
enum _ecspi_status
{
kStatus_ECSPI_Busy = MAKE_STATUS(kStatusGroup_ECSPI, 0), /*!< ECSPI bus is busy */
kStatus_ECSPI_Idle = MAKE_STATUS(kStatusGroup_ECSPI, 1), /*!< ECSPI is idle */
kStatus_ECSPI_Error = MAKE_STATUS(kStatusGroup_ECSPI, 2), /*!< ECSPI error */
kStatus_ECSPI_HardwareOverFlow = MAKE_STATUS(kStatusGroup_ECSPI, 3), /*!< ECSPI hardware overflow */
};
/*! @brief ECSPI clock polarity configuration. */
typedef enum _ecspi_clock_polarity
{
kECSPI_PolarityActiveHigh = 0x0U, /*!< Active-high ECSPI polarity high (idles low). */
kECSPI_PolarityActiveLow, /*!< Active-low ECSPI polarity low (idles high). */
} ecspi_clock_polarity_t;
/*! @brief ECSPI clock phase configuration. */
typedef enum _ecspi_clock_phase
{
kECSPI_ClockPhaseFirstEdge =
0x0U, /*!< First edge on SPSCK occurs at the middle of the first cycle of a data transfer. */
kECSPI_ClockPhaseSecondEdge, /*!< First edge on SPSCK occurs at the start of the first cycle of a data transfer. */
} ecspi_clock_phase_t;
/*! @brief ECSPI interrupt sources. */
enum _ecspi_interrupt_enable
{
kECSPI_TxfifoEmptyInterruptEnable = ECSPI_INTREG_TEEN_MASK, /*!< Transmit FIFO buffer empty interrupt */
kECSPI_TxFifoDataRequstInterruptEnable = ECSPI_INTREG_TDREN_MASK, /*!< Transmit FIFO data requst interrupt */
kECSPI_TxFifoFullInterruptEnable = ECSPI_INTREG_TFEN_MASK, /*!< Transmit FIFO full interrupt */
kECSPI_RxFifoReadyInterruptEnable = ECSPI_INTREG_RREN_MASK, /*!< Receiver FIFO ready interrupt */
kECSPI_RxFifoDataRequstInterruptEnable = ECSPI_INTREG_RDREN_MASK, /*!< Receiver FIFO data requst interrupt */
kECSPI_RxFifoFullInterruptEnable = ECSPI_INTREG_RFEN_MASK, /*!< Receiver FIFO full interrupt */
kECSPI_RxFifoOverFlowInterruptEnable = ECSPI_INTREG_ROEN_MASK, /*!< Receiver FIFO buffer overflow interrupt */
kECSPI_TransferCompleteInterruptEnable = ECSPI_INTREG_TCEN_MASK, /*!< Transfer complete interrupt */
kECSPI_AllInterruptEnable = (ECSPI_INTREG_TEEN_MASK | ECSPI_INTREG_TDREN_MASK | ECSPI_INTREG_TFEN_MASK |
ECSPI_INTREG_RREN_MASK | ECSPI_INTREG_RDREN_MASK | ECSPI_INTREG_RFEN_MASK |
ECSPI_INTREG_ROEN_MASK | ECSPI_INTREG_TCEN_MASK), /*!< All interrupt */
};
/*! @brief ECSPI status flags. */
enum _ecspi_flags
{
kECSPI_TxfifoEmptyFlag = ECSPI_STATREG_TE_MASK, /*!< Transmit FIFO buffer empty flag */
kECSPI_TxFifoDataRequstFlag = ECSPI_STATREG_TDR_MASK, /*!< Transmit FIFO data requst flag */
kECSPI_TxFifoFullFlag = ECSPI_STATREG_TF_MASK, /*!< Transmit FIFO full flag */
kECSPI_RxFifoReadyFlag = ECSPI_STATREG_RR_MASK, /*!< Receiver FIFO ready flag */
kECSPI_RxFifoDataRequstFlag = ECSPI_STATREG_RDR_MASK, /*!< Receiver FIFO data requst flag */
kECSPI_RxFifoFullFlag = ECSPI_STATREG_RF_MASK, /*!< Receiver FIFO full flag */
kECSPI_RxFifoOverFlowFlag = ECSPI_STATREG_RO_MASK, /*!< Receiver FIFO buffer overflow flag */
kECSPI_TransferCompleteFlag = ECSPI_STATREG_TC_MASK, /*!< Transfer complete flag */
};
/*! @brief ECSPI DMA enable.*/
enum _ecspi_dma_enable_t
{
kECSPI_TxDmaEnable = ECSPI_DMAREG_TEDEN_MASK, /*!< Tx DMA request source */
kECSPI_RxDmaEnable = ECSPI_DMAREG_RXDEN_MASK, /*!< Rx DMA request source */
kECSPI_DmaAllEnable = (ECSPI_DMAREG_TEDEN_MASK | ECSPI_DMAREG_RXDEN_MASK) /*!< All DMA request source*/
};
/*! @brief ECSPI SPI_RDY signal configuration. */
typedef enum _ecspi_data_ready
{
kECSPI_DataReadyIgnore = 0x0U, /*!< SPI_RDY signal is ignored */
kECSPI_DataReadyFallingEdge, /*!< SPI_RDY signal will be triggerd by the falling edge */
kECSPI_DataReadyLowLevel, /*!< SPI_RDY signal will be triggerd by a low level */
} ecspi_Data_ready_t;
/*! @brief ECSPI channel select source. */
typedef enum _ecspi_channel_source
{
kECSPI_Channel0 = 0x0U, /*!< Channel 0 is selectd */
kECSPI_Channel1, /*!< Channel 1 is selectd */
kECSPI_Channel2, /*!< Channel 2 is selectd */
kECSPI_Channel3, /*!< Channel 3 is selectd */
} ecspi_channel_source_t;
/*! @brief ECSPI master or slave mode configuration. */
typedef enum _ecspi_master_slave_mode
{
kECSPI_Slave = 0U, /*!< ECSPI peripheral operates in slave mode.*/
kECSPI_Master, /*!< ECSPI peripheral operates in master mode.*/
} ecspi_master_slave_mode_t;
/*! @brief ECSPI data line inactive state configuration. */
typedef enum _ecspi_data_line_inactive_state_t
{
kECSPI_DataLineInactiveStateHigh = 0x0U, /*!< The data line inactive state stays high. */
kECSPI_DataLineInactiveStateLow, /*!< The data line inactive state stays low. */
} ecspi_data_line_inactive_state_t;
/*! @brief ECSPI clock inactive state configuration. */
typedef enum _ecspi_clock_inactive_state_t
{
kECSPI_ClockInactiveStateLow = 0x0U, /*!< The SCLK inactive state stays low. */
kECSPI_ClockInactiveStateHigh, /*!< The SCLK inactive state stays high. */
} ecspi_clock_inactive_state_t;
/*! @brief ECSPI active state configuration.*/
typedef enum _ecspi_chip_select_active_state_t
{
kECSPI_ChipSelectActiveStateLow = 0x0U, /*!< The SS signal line active stays low. */
kECSPI_ChipSelectActiveStateHigh, /*!< The SS signal line active stays high. */
} ecspi_chip_select_active_state_t;
/*! @brief ECSPI wave form configuration.*/
typedef enum _ecspi_wave_form_t
{
kECSPI_WaveFormSingle = 0x0U, /*!< The wave form for signal burst */
kECSPI_WaveFormMultiple, /*!< The wave form for multiple burst */
} ecspi_wave_form_t;
/*! @brief ECSPI sample period clock configuration.*/
typedef enum _ecspi_sample_period_clock_source
{
kECSPI_spiClock = 0x0U, /*!< The sample period clock source is SCLK. */
kECSPI_lowFreqClock, /*!< The sample seriod clock source is low_frequency reference clock(32.768 kHz). */
} ecspi_sample_period_clock_source_t;
/*! @brief ECSPI user channel configure structure.*/
typedef struct _ecspi_channel_config
{
ecspi_master_slave_mode_t channelMode; /*!< Channel mode */
ecspi_clock_inactive_state_t clockInactiveState; /*!< Clock line (SCLK) inactive state */
ecspi_data_line_inactive_state_t dataLineInactiveState; /*!< Data line (MOSI&MISO) inactive state */
ecspi_chip_select_active_state_t chipSlectActiveState; /*!< Chip select(SS) line active state */
ecspi_wave_form_t waveForm; /*!< Wave form */
ecspi_clock_polarity_t polarity; /*!< Clock polarity */
ecspi_clock_phase_t phase; /*!< Clock phase */
} ecspi_channel_config_t;
/*! @brief ECSPI master configure structure.*/
typedef struct _ecspi_master_config
{
ecspi_channel_source_t channel; /*!< Channel number */
ecspi_channel_config_t channelConfig; /*!< Channel configuration */
ecspi_sample_period_clock_source_t samplePeriodClock; /*!< Sample period clock source */
uint8_t burstLength; /*!< Burst length */
uint8_t chipSelectDelay; /*!< SS delay time */
uint16_t samplePeriod; /*!< Sample period */
uint8_t txFifoThreshold; /*!< TX Threshold */
uint8_t rxFifoThreshold; /*!< RX Threshold */
uint32_t baudRate_Bps; /*!< ECSPI baud rate for master mode */
} ecspi_master_config_t;
/*! @brief ECSPI slave configure structure.*/
typedef struct _ecspi_slave_config
{
ecspi_channel_source_t channel; /*Channel number */
uint8_t burstLength; /*!< Burst length */
uint8_t txFifoThreshold; /*!< TX Threshold */
uint8_t rxFifoThreshold; /*!< RX Threshold */
ecspi_channel_config_t channelConfig; /*!< Channel configuration */
} ecspi_slave_config_t;
/*! @brief ECSPI transfer structure */
typedef struct _ecspi_transfer
{
uint32_t *txData; /*!< Send buffer */
uint32_t *rxData; /*!< Receive buffer */
size_t dataSize; /*!< Transfer bytes */
ecspi_channel_source_t channel; /*!< ECSPI channel select */
} ecspi_transfer_t;
typedef struct _ecspi_master_handle ecspi_master_handle_t;
/*! @brief Slave handle is the same with master handle */
typedef ecspi_master_handle_t ecspi_slave_handle_t;
/*! @brief ECSPI master callback for finished transmit */
typedef void (*ecspi_master_callback_t)(ECSPI_Type *base,
ecspi_master_handle_t *handle,
status_t status,
void *userData);
/*! @brief ECSPI slave callback for finished transmit */
typedef void (*ecspi_slave_callback_t)(ECSPI_Type *base, ecspi_slave_handle_t *handle, status_t status, void *userData);
/*! @brief ECSPI master handle structure */
struct _ecspi_master_handle
{
ecspi_channel_source_t channel; /*!< Channel number */
uint32_t *volatile txData; /*!< Transfer buffer */
uint32_t *volatile rxData; /*!< Receive buffer */
volatile size_t txRemainingBytes; /*!< Send data remaining in bytes */
volatile size_t rxRemainingBytes; /*!< Receive data remaining in bytes */
volatile uint32_t state; /*!< ECSPI internal state */
size_t transferSize; /*!< Bytes to be transferred */
ecspi_master_callback_t callback; /*!< ECSPI callback */
void *userData; /*!< Callback parameter */
};
#if defined(__cplusplus)
extern "C" {
#endif
/*******************************************************************************
* APIs
******************************************************************************/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Sets the ECSPI configuration structure to default values.
*
* The purpose of this API is to get the configuration structure initialized for use in ECSPI_MasterInit().
* User may use the initialized structure unchanged in ECSPI_MasterInit, or modify
* some fields of the structure before calling ECSPI_MasterInit. After calling this API,
* the master is ready to transfer.
* Example:
@code
ecspi_master_config_t config;
ECSPI_MasterGetDefaultConfig(&config);
@endcode
*
* @param config pointer to config structure
*/
void ECSPI_MasterGetDefaultConfig(ecspi_master_config_t *config);
/*!
* @brief Initializes the ECSPI with configuration.
*
* The configuration structure can be filled by user from scratch, or be set with default
* values by ECSPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer.
* Example
@code
ecspi_master_config_t config = {
.baudRate_Bps = 400000,
...
};
ECSPI_MasterInit(ECSPI0, &config);
@endcode
*
* @param base ECSPI base pointer
* @param config pointer to master configuration structure
* @param srcClock_Hz Source clock frequency.
*/
void ECSPI_MasterInit(ECSPI_Type *base, const ecspi_master_config_t *config, uint32_t srcClock_Hz);
/*!
* @brief Sets the ECSPI configuration structure to default values.
*
* The purpose of this API is to get the configuration structure initialized for use in ECSPI_SlaveInit().
* User may use the initialized structure unchanged in ECSPI_SlaveInit(), or modify
* some fields of the structure before calling ECSPI_SlaveInit(). After calling this API,
* the master is ready to transfer.
* Example:
@code
ecspi_Slaveconfig_t config;
ECSPI_SlaveGetDefaultConfig(&config);
@endcode
*
* @param config pointer to config structure
*/
void ECSPI_SlaveGetDefaultConfig(ecspi_slave_config_t *config);
/*!
* @brief Initializes the ECSPI with configuration.
*
* The configuration structure can be filled by user from scratch, or be set with default
* values by ECSPI_SlaveGetDefaultConfig(). After calling this API, the slave is ready to transfer.
* Example
@code
ecspi_Salveconfig_t config = {
.baudRate_Bps = 400000,
...
};
ECSPI_SlaveInit(ECSPI1, &config);
@endcode
*
* @param base ECSPI base pointer
* @param config pointer to master configuration structure
*/
void ECSPI_SlaveInit(ECSPI_Type *base, const ecspi_slave_config_t *config);
/*!
* @brief De-initializes the ECSPI.
*
* Calling this API resets the ECSPI module, gates the ECSPI clock.
* The ECSPI module can't work unless calling the ECSPI_MasterInit/ECSPI_SlaveInit to initialize module.
*
* @param base ECSPI base pointer
*/
void ECSPI_Deinit(ECSPI_Type *base);
/*!
* @brief Enables or disables the ECSPI.
*
* @param base ECSPI base pointer
* @param enable pass true to enable module, false to disable module
*/
static inline void ECSPI_Enable(ECSPI_Type *base, bool enable)
{
if (enable)
{
base->CONREG |= ECSPI_CONREG_EN_MASK;
}
else
{
base->CONREG &= ~ECSPI_CONREG_EN_MASK;
}
}
/*! @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets the status flag.
*
* @param base ECSPI base pointer
* @return ECSPI Status, use status flag to AND #_ecspi_flags could get the related status.
*/
static inline uint32_t ECSPI_GetStatusFlags(ECSPI_Type *base)
{
return (base->STATREG);
}
/*!
* @brief Clear the status flag.
*
* @param base ECSPI base pointer
* @param mask ECSPI Status, use status flag to AND #_ecspi_flags could get the related status.
*/
static inline void ECSPI_ClearStatusFlags(ECSPI_Type *base, uint32_t mask)
{
base->STATREG |= mask;
}
/*! @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the interrupt for the ECSPI.
*
* @param base ECSPI base pointer
* @param mask ECSPI interrupt source. The parameter can be any combination of the following values:
* @arg kECSPI_TxfifoEmptyInterruptEnable
* @arg kECSPI_TxFifoDataRequstInterruptEnable
* @arg kECSPI_TxFifoFullInterruptEnable
* @arg kECSPI_RxFifoReadyInterruptEnable
* @arg kECSPI_RxFifoDataRequstInterruptEnable
* @arg kECSPI_RxFifoFullInterruptEnable
* @arg kECSPI_RxFifoOverFlowInterruptEnable
* @arg kECSPI_TransferCompleteInterruptEnable
* @arg kECSPI_AllInterruptEnable
*/
static inline void ECSPI_EnableInterrupts(ECSPI_Type *base, uint32_t mask)
{
base->INTREG |= mask;
}
/*!
* @brief Disables the interrupt for the ECSPI.
*
* @param base ECSPI base pointer
* @param mask ECSPI interrupt source. The parameter can be any combination of the following values:
* @arg kECSPI_TxfifoEmptyInterruptEnable
* @arg kECSPI_TxFifoDataRequstInterruptEnable
* @arg kECSPI_TxFifoFullInterruptEnable
* @arg kECSPI_RxFifoReadyInterruptEnable
* @arg kECSPI_RxFifoDataRequstInterruptEnable
* @arg kECSPI_RxFifoFullInterruptEnable
* @arg kECSPI_RxFifoOverFlowInterruptEnable
* @arg kECSPI_TransferCompleteInterruptEnable
* @arg kECSPI_AllInterruptEnable
*/
static inline void ECSPI_DisableInterrupts(ECSPI_Type *base, uint32_t mask)
{
base->INTREG &= ~(mask);
}
/*! @} */
/*!
* @name Software Reset
* @{
*/
/*!
* @brief Software reset.
*
* @param base ECSPI base pointer
*/
static inline void ECSPI_SoftwareReset(ECSPI_Type *base)
{
/* Disables the block and resets the internal logic with the exception of the ECSPI control register */
base->CONREG &= ~ECSPI_CONREG_EN_MASK;
/* Software reset can not reset the control register, so clear the control register manually */
base->CONREG = 0x0U;
}
/*! @} */
/*!
* @name Channel mode check
* @{
*/
/*!
* @brief Mode check
*
* @param base ECSPI base pointer
* @param channel ECSPI channel source
* @return mode of channel
*/
static inline bool ECSPI_IsMaster(ECSPI_Type *base, ecspi_channel_source_t channel)
{
return (bool)(((base->CONREG & ECSPI_CONREG_CHANNEL_MODE_MASK) >> (ECSPI_CONREG_CHANNEL_MODE_SHIFT + channel)) &
0x1U);
}
/*! @} */
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Enables the DMA source for ECSPI.
*
* @param base ECSPI base pointer
* @param source ECSPI DMA source.
* @param enable True means enable DMA, false means disable DMA
*/
static inline void ECSPI_EnableDMA(ECSPI_Type *base, uint32_t mask, bool enable)
{
if (enable)
{
base->DMAREG |= mask;
}
else
{
base->DMAREG &= ~mask;
}
}
/*! @} */
/*!
* @name FIFO Operation
* @{
*/
/*!
* @brief Get the Tx FIFO data count.
*
* @param base ECSPI base pointer.
* @return the number of words in Tx FIFO buffer.
*/
static inline uint8_t ECSPI_GetTxFifoCount(ECSPI_Type *base)
{
return (uint8_t)((base->TESTREG & ECSPI_TESTREG_TXCNT_MASK) >> ECSPI_TESTREG_TXCNT_SHIFT);
}
/*!
* @brief Get the Rx FIFO data count.
*
* @param base ECSPI base pointer.
* @return the number of words in Rx FIFO buffer.
*/
static inline uint8_t ECSPI_GetRxFifoCount(ECSPI_Type *base)
{
return (uint8_t)((base->TESTREG & ECSPI_TESTREG_RXCNT_MASK) >> ECSPI_TESTREG_RXCNT_SHIFT);
}
/*! @} */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Set channel select for transfer.
*
* @param base ECSPI base pointer
* @param channel Channel source.
*/
static inline void ECSPI_SetChannelSelect(ECSPI_Type *base, ecspi_channel_source_t channel)
{
/* Clear Channel select bits in CONREG register */
uint32_t temp = base->CONREG & (~(ECSPI_CONREG_CHANNEL_SELECT_MASK));
/* Set channel select bits */
base->CONREG = (temp | ECSPI_CONREG_CHANNEL_SELECT(channel));
}
/*!
* @brief Set channel select configuration for transfer.
*
* The purpose of this API is to set the channel will be use to transfer.
* User may use this API after instance has been initialized or before transfer start.
* The configuration structure #_ecspi_channel_config_ can be filled by user from scratch.
* After calling this API, user can select this channel as transfer channel.
*
* @param base ECSPI base pointer
* @param channel Channel source.
* @param config Configuration struct of channel
*/
void ECSPI_SetChannelConfig(ECSPI_Type *base, ecspi_channel_source_t channel, const ecspi_channel_config_t *config);
/*!
* @brief Sets the baud rate for ECSPI transfer. This is only used in master.
*
* @param base ECSPI base pointer
* @param baudRate_Bps baud rate needed in Hz.
* @param srcClock_Hz ECSPI source clock frequency in Hz.
*/
void ECSPI_SetBaudRate(ECSPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
/*!
* @brief Sends a buffer of data bytes using a blocking method.
*
* @note This function blocks via polling until all bytes have been sent.
*
* @param base ECSPI base pointer
* @param buffer The data bytes to send
* @param size The number of data bytes to send
*/
void ECSPI_WriteBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size);
/*!
* @brief Writes a data into the ECSPI data register.
*
* @param base ECSPI base pointer
* @param data Data needs to be write.
*/
static inline void ECSPI_WriteData(ECSPI_Type *base, uint32_t data)
{
base->TXDATA = data;
}
/*!
* @brief Gets a data from the ECSPI data register.
*
* @param base ECSPI base pointer
* @return Data in the register.
*/
static inline uint32_t ECSPI_ReadData(ECSPI_Type *base)
{
return (uint32_t)(base->RXDATA);
}
/*! @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the ECSPI master handle.
*
* This function initializes the ECSPI master handle which can be used for other ECSPI master transactional APIs.
* Usually,
* for a specified ECSPI instance, call this API once to get the initialized handle.
*
* @param base ECSPI peripheral base address.
* @param handle ECSPI handle pointer.
* @param callback Callback function.
* @param userData User data.
*/
void ECSPI_MasterTransferCreateHandle(ECSPI_Type *base,
ecspi_master_handle_t *handle,
ecspi_master_callback_t callback,
void *userData);
/*!
* @brief Transfers a block of data using a polling method.
*
* @param base SPI base pointer
* @param xfer pointer to spi_xfer_config_t structure
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
*/
status_t ECSPI_MasterTransferBlocking(ECSPI_Type *base, ecspi_transfer_t *xfer);
/*!
* @brief Performs a non-blocking ECSPI interrupt transfer.
*
* @note The API immediately returns after transfer initialization is finished.
* @note If ECSPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
*
* @param base ECSPI peripheral base address.
* @param handle pointer to ecspi_master_handle_t structure which stores the transfer state
* @param xfer pointer to ecspi_transfer_t structure
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_ECSPI_Busy ECSPI is not idle, is running another transfer.
*/
status_t ECSPI_MasterTransferNonBlocking(ECSPI_Type *base, ecspi_master_handle_t *handle, ecspi_transfer_t *xfer);
/*!
* @brief Gets the bytes of the ECSPI interrupt transferred.
*
* @param base ECSPI peripheral base address.
* @param handle Pointer to ECSPI transfer handle, this should be a static variable.
* @param count Transferred bytes of ECSPI master.
* @retval kStatus_ECSPI_Success Succeed get the transfer count.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
*/
status_t ECSPI_MasterTransferGetCount(ECSPI_Type *base, ecspi_master_handle_t *handle, size_t *count);
/*!
* @brief Aborts an ECSPI transfer using interrupt.
*
* @param base ECSPI peripheral base address.
* @param handle Pointer to ECSPI transfer handle, this should be a static variable.
*/
void ECSPI_MasterTransferAbort(ECSPI_Type *base, ecspi_master_handle_t *handle);
/*!
* @brief Interrupts the handler for the ECSPI.
*
* @param base ECSPI peripheral base address.
* @param handle pointer to ecspi_master_handle_t structure which stores the transfer state.
*/
void ECSPI_MasterTransferHandleIRQ(ECSPI_Type *base, ecspi_master_handle_t *handle);
/*!
* @brief Initializes the ECSPI slave handle.
*
* This function initializes the ECSPI slave handle which can be used for other ECSPI slave transactional APIs. Usually,
* for a specified ECSPI instance, call this API once to get the initialized handle.
*
* @param base ECSPI peripheral base address.
* @param handle ECSPI handle pointer.
* @param callback Callback function.
* @param userData User data.
*/
void ECSPI_SlaveTransferCreateHandle(ECSPI_Type *base,
ecspi_slave_handle_t *handle,
ecspi_slave_callback_t callback,
void *userData);
/*!
* @brief Performs a non-blocking ECSPI slave interrupt transfer.
*
* @note The API returns immediately after the transfer initialization is finished.
*
* @param base ECSPI peripheral base address.
* @param handle pointer to ecspi_master_handle_t structure which stores the transfer state
* @param xfer pointer to ecspi_transfer_t structure
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_ECSPI_Busy ECSPI is not idle, is running another transfer.
*/
static inline status_t ECSPI_SlaveTransferNonBlocking(ECSPI_Type *base,
ecspi_slave_handle_t *handle,
ecspi_transfer_t *xfer)
{
return ECSPI_MasterTransferNonBlocking(base, handle, xfer);
}
/*!
* @brief Gets the bytes of the ECSPI interrupt transferred.
*
* @param base ECSPI peripheral base address.
* @param handle Pointer to ECSPI transfer handle, this should be a static variable.
* @param count Transferred bytes of ECSPI slave.
* @retval kStatus_ECSPI_Success Succeed get the transfer count.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
*/
static inline status_t ECSPI_SlaveTransferGetCount(ECSPI_Type *base, ecspi_slave_handle_t *handle, size_t *count)
{
return ECSPI_MasterTransferGetCount(base, handle, count);
}
/*!
* @brief Aborts an ECSPI slave transfer using interrupt.
*
* @param base ECSPI peripheral base address.
* @param handle Pointer to ECSPI transfer handle, this should be a static variable.
*/
static inline void ECSPI_SlaveTransferAbort(ECSPI_Type *base, ecspi_slave_handle_t *handle)
{
ECSPI_MasterTransferAbort(base, handle);
}
/*!
* @brief Interrupts a handler for the ECSPI slave.
*
* @param base ECSPI peripheral base address.
* @param handle pointer to ecspi_slave_handle_t structure which stores the transfer state
*/
void ECSPI_SlaveTransferHandleIRQ(ECSPI_Type *base, ecspi_slave_handle_t *handle);
/*! @} */
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_ECSPI_H_*/

View File

@ -0,0 +1,250 @@
/*
* Copyright (c) 2017, NXP Semiconductors, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_elcdif.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for ELCDIF module.
*
* @param base ELCDIF peripheral base address
*/
static uint32_t ELCDIF_GetInstance(LCDIF_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to ELCDIF bases for each instance. */
static LCDIF_Type *const s_elcdifBases[] = LCDIF_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to eLCDIF apb_clk for each instance. */
static const clock_ip_name_t s_elcdifApbClocks[] = LCDIF_CLOCKS;
#if defined(LCDIF_PERIPH_CLOCKS)
/*! @brief Pointers to eLCDIF pix_clk for each instance. */
static const clock_ip_name_t s_elcdifPixClocks[] = LCDIF_PERIPH_CLOCKS;
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*! @brief The control register value to select different pixel format. */
elcdif_pixel_format_reg_t s_pixelFormatReg[] = {
/* kELCDIF_PixelFormatRAW8 */
{/* Register CTRL. */
LCDIF_CTRL_WORD_LENGTH(1U),
/* Register CTRL1. */
LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0FU)},
/* kELCDIF_PixelFormatRGB565 */
{/* Register CTRL. */
LCDIF_CTRL_WORD_LENGTH(0U) | LCDIF_CTRL_DATA_FORMAT_16_BIT(1U),
/* Register CTRL1. */
LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0FU)},
/* kELCDIF_PixelFormatRGB666 */
{/* Register CTRL. */
LCDIF_CTRL_WORD_LENGTH(3U) | LCDIF_CTRL_DATA_FORMAT_24_BIT(1U),
/* Register CTRL1. */
LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x07U)},
/* kELCDIF_PixelFormatRGB888 */
{/* Register CTRL. 24-bit. */
LCDIF_CTRL_WORD_LENGTH(3U),
/* Register CTRL1. */
LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x07U)},
};
/*******************************************************************************
* Codes
******************************************************************************/
static uint32_t ELCDIF_GetInstance(LCDIF_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_elcdifBases); instance++)
{
if (s_elcdifBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_elcdifBases));
return instance;
}
void ELCDIF_RgbModeInit(LCDIF_Type *base, const elcdif_rgb_mode_config_t *config)
{
assert(config);
assert(config->pixelFormat < ARRAY_SIZE(s_pixelFormatReg));
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
uint32_t instance = ELCDIF_GetInstance(base);
/* Enable the clock. */
CLOCK_EnableClock(s_elcdifApbClocks[instance]);
#if defined(LCDIF_PERIPH_CLOCKS)
CLOCK_EnableClock(s_elcdifPixClocks[instance]);
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Reset. */
ELCDIF_Reset(base);
base->CTRL = s_pixelFormatReg[(uint32_t)config->pixelFormat].regCtrl | (uint32_t)(config->dataBus) |
LCDIF_CTRL_DOTCLK_MODE_MASK | /* RGB mode. */
LCDIF_CTRL_BYPASS_COUNT_MASK | /* Keep RUN bit set. */
LCDIF_CTRL_MASTER_MASK;
base->CTRL1 = s_pixelFormatReg[(uint32_t)config->pixelFormat].regCtrl1;
base->TRANSFER_COUNT = ((uint32_t)config->panelHeight << LCDIF_TRANSFER_COUNT_V_COUNT_SHIFT) |
((uint32_t)config->panelWidth << LCDIF_TRANSFER_COUNT_H_COUNT_SHIFT);
base->VDCTRL0 = LCDIF_VDCTRL0_ENABLE_PRESENT_MASK | /* Data enable signal. */
LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT_MASK | /* VSYNC period in the unit of display clock. */
LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT_MASK | /* VSYNC pulse width in the unit of display clock. */
(uint32_t)config->polarityFlags | (uint32_t)config->vsw;
base->VDCTRL1 = config->vsw + config->panelHeight + config->vfp + config->vbp;
base->VDCTRL2 = ((uint32_t)config->hsw << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_SHIFT) |
((uint32_t)(config->hfp + config->hbp + config->panelWidth + config->hsw))
<< LCDIF_VDCTRL2_HSYNC_PERIOD_SHIFT;
base->VDCTRL3 = (((uint32_t)config->hbp + config->hsw) << LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_SHIFT) |
(((uint32_t)config->vbp + config->vsw) << LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_SHIFT);
base->VDCTRL4 = LCDIF_VDCTRL4_SYNC_SIGNALS_ON_MASK |
((uint32_t)config->panelWidth << LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_SHIFT);
base->CUR_BUF = config->bufferAddr;
base->NEXT_BUF = config->bufferAddr;
}
void ELCDIF_RgbModeGetDefaultConfig(elcdif_rgb_mode_config_t *config)
{
assert(config);
config->panelWidth = 480U;
config->panelHeight = 272U;
config->hsw = 41;
config->hfp = 4;
config->hbp = 8;
config->vsw = 10;
config->vfp = 4;
config->vbp = 2;
config->polarityFlags = kELCDIF_VsyncActiveLow | kELCDIF_HsyncActiveLow | kELCDIF_DataEnableActiveLow |
kELCDIF_DriveDataOnFallingClkEdge;
config->bufferAddr = 0U;
config->pixelFormat = kELCDIF_PixelFormatRGB888;
config->dataBus = kELCDIF_DataBus24Bit;
}
void ELCDIF_Deinit(LCDIF_Type *base)
{
ELCDIF_Reset(base);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
uint32_t instance = ELCDIF_GetInstance(base);
/* Disable the clock. */
#if defined(LCDIF_PERIPH_CLOCKS)
CLOCK_DisableClock(s_elcdifPixClocks[instance]);
#endif
CLOCK_DisableClock(s_elcdifApbClocks[instance]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void ELCDIF_RgbModeStop(LCDIF_Type *base)
{
base->CTRL_CLR = LCDIF_CTRL_DOTCLK_MODE_MASK;
/* Wait for data transfer finished. */
while (base->CTRL & LCDIF_CTRL_DOTCLK_MODE_MASK)
{
}
}
void ELCDIF_Reset(LCDIF_Type *base)
{
volatile uint32_t i = 0x100;
/* Disable the clock gate. */
base->CTRL_CLR = LCDIF_CTRL_CLKGATE_MASK;
/* Confirm the clock gate is disabled. */
while (base->CTRL & LCDIF_CTRL_CLKGATE_MASK)
{
}
/* Reset the block. */
base->CTRL_SET = LCDIF_CTRL_SFTRST_MASK;
/* Confirm the reset bit is set. */
while (!(base->CTRL & LCDIF_CTRL_SFTRST_MASK))
{
}
/* Delay for the reset. */
while (i--)
{
}
/* Bring the module out of reset. */
base->CTRL_CLR = LCDIF_CTRL_SFTRST_MASK;
/* Disable the clock gate. */
base->CTRL_CLR = LCDIF_CTRL_CLKGATE_MASK;
}
void ELCDIF_SetAlphaSurfaceBufferConfig(LCDIF_Type *base, const elcdif_as_buffer_config_t *config)
{
assert(config);
base->AS_CTRL = (base->AS_CTRL & ~LCDIF_AS_CTRL_FORMAT_MASK) | LCDIF_AS_CTRL_FORMAT(config->pixelFormat);
base->AS_BUF = config->bufferAddr;
base->AS_NEXT_BUF = config->bufferAddr;
}
void ELCDIF_SetAlphaSurfaceBlendConfig(LCDIF_Type *base, const elcdif_as_blend_config_t *config)
{
assert(config);
uint32_t reg;
reg = base->AS_CTRL;
reg &= ~(LCDIF_AS_CTRL_ALPHA_INVERT_MASK | LCDIF_AS_CTRL_ROP_MASK | LCDIF_AS_CTRL_ALPHA_MASK |
LCDIF_AS_CTRL_ALPHA_CTRL_MASK);
reg |= (LCDIF_AS_CTRL_ROP(config->ropMode) | LCDIF_AS_CTRL_ALPHA(config->alpha) |
LCDIF_AS_CTRL_ALPHA_CTRL(config->alphaMode));
if (config->invertAlpha)
{
reg |= LCDIF_AS_CTRL_ALPHA_INVERT_MASK;
}
base->AS_CTRL = reg;
}

View File

@ -0,0 +1,659 @@
/*
* Copyright (c) 2017, NXP Semiconductors, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_ELCDIF_H_
#define _FSL_ELCDIF_H_
#include "fsl_common.h"
/*!
* @addtogroup elcdif
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief eLCDIF driver version */
#define FSL_ELCDIF_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */
/*@}*/
/* All IRQ flags in CTRL1 register. */
#define ELCDIF_CTRL1_IRQ_MASK \
(LCDIF_CTRL1_BM_ERROR_IRQ_MASK | LCDIF_CTRL1_OVERFLOW_IRQ_MASK | LCDIF_CTRL1_UNDERFLOW_IRQ_MASK | \
LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_MASK | LCDIF_CTRL1_VSYNC_EDGE_IRQ_MASK)
/* All IRQ enable control bits in CTRL1 register. */
#define ELCDIF_CTRL1_IRQ_EN_MASK \
(LCDIF_CTRL1_BM_ERROR_IRQ_EN_MASK | LCDIF_CTRL1_OVERFLOW_IRQ_EN_MASK | LCDIF_CTRL1_UNDERFLOW_IRQ_EN_MASK | \
LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN_MASK | LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN_MASK)
/* All IRQ flags in AS_CTRL register. */
#define ELCDIF_AS_CTRL_IRQ_MASK (LCDIF_AS_CTRL_CSI_SYNC_ON_IRQ_MASK)
/* All IRQ enable control bits in AS_CTRL register. */
#define ELCDIF_AS_CTRL_IRQ_EN_MASK (LCDIF_AS_CTRL_CSI_SYNC_ON_IRQ_EN_MASK)
#if ((ELCDIF_CTRL1_IRQ_MASK & ELCDIF_AS_CTRL_IRQ_MASK) || (ELCDIF_AS_CTRL_IRQ_MASK & ELCDIF_AS_CTRL_IRQ_EN_MASK))
#error Interrupt bits overlap, need to update the interrupt functions.
#endif
/*!
* @brief eLCDIF signal polarity flags
*/
enum _elcdif_polarity_flags
{
kELCDIF_VsyncActiveLow = 0U, /*!< VSYNC active low. */
kELCDIF_VsyncActiveHigh = LCDIF_VDCTRL0_VSYNC_POL_MASK, /*!< VSYNC active high. */
kELCDIF_HsyncActiveLow = 0U, /*!< HSYNC active low. */
kELCDIF_HsyncActiveHigh = LCDIF_VDCTRL0_HSYNC_POL_MASK, /*!< HSYNC active high. */
kELCDIF_DataEnableActiveLow = 0U, /*!< Data enable line active low. */
kELCDIF_DataEnableActiveHigh = LCDIF_VDCTRL0_ENABLE_POL_MASK, /*!< Data enable line active high. */
kELCDIF_DriveDataOnFallingClkEdge = 0U, /*!< Drive data on falling clock edge, capture data
on rising clock edge. */
kELCDIF_DriveDataOnRisingClkEdge = LCDIF_VDCTRL0_DOTCLK_POL_MASK, /*!< Drive data on falling
clock edge, capture data
on rising clock edge. */
};
/*!
* @brief The eLCDIF interrupts to enable.
*/
enum _elcdif_interrupt_enable
{
kELCDIF_BusMasterErrorInterruptEnable = LCDIF_CTRL1_BM_ERROR_IRQ_EN_MASK, /*!< Bus master error interrupt. */
kELCDIF_TxFifoOverflowInterruptEnable = LCDIF_CTRL1_OVERFLOW_IRQ_EN_MASK, /*!< TXFIFO overflow interrupt. */
kELCDIF_TxFifoUnderflowInterruptEnable = LCDIF_CTRL1_UNDERFLOW_IRQ_EN_MASK, /*!< TXFIFO underflow interrupt. */
kELCDIF_CurFrameDoneInterruptEnable =
LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN_MASK, /*!< Interrupt when hardware enters vertical blanking state. */
kELCDIF_VsyncEdgeInterruptEnable =
LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN_MASK, /*!< Interrupt when hardware encounters VSYNC edge. */
kELCDIF_SciSyncOnInterruptEnable =
LCDIF_AS_CTRL_CSI_SYNC_ON_IRQ_EN_MASK, /*!< Interrupt when eLCDIF lock with CSI input. */
};
/*!
* @brief The eLCDIF interrupt status flags.
*/
enum _elcdif_interrupt_flags
{
kELCDIF_BusMasterError = LCDIF_CTRL1_BM_ERROR_IRQ_MASK, /*!< Bus master error interrupt. */
kELCDIF_TxFifoOverflow = LCDIF_CTRL1_OVERFLOW_IRQ_MASK, /*!< TXFIFO overflow interrupt. */
kELCDIF_TxFifoUnderflow = LCDIF_CTRL1_UNDERFLOW_IRQ_MASK, /*!< TXFIFO underflow interrupt. */
kELCDIF_CurFrameDone =
LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_MASK, /*!< Interrupt when hardware enters vertical blanking state. */
kELCDIF_VsyncEdge = LCDIF_CTRL1_VSYNC_EDGE_IRQ_MASK, /*!< Interrupt when hardware encounters VSYNC edge. */
kELCDIF_SciSyncOn = LCDIF_AS_CTRL_CSI_SYNC_ON_IRQ_MASK, /*!< Interrupt when eLCDIF lock with CSI input. */
};
/*!
* @brief eLCDIF status flags
*/
enum _elcdif_status_flags
{
kELCDIF_LFifoFull = LCDIF_STAT_LFIFO_FULL_MASK, /*!< LFIFO full. */
kELCDIF_LFifoEmpty = LCDIF_STAT_LFIFO_EMPTY_MASK, /*!< LFIFO empty. */
kELCDIF_TxFifoFull = LCDIF_STAT_TXFIFO_FULL_MASK, /*!< TXFIFO full. */
kELCDIF_TxFifoEmpty = LCDIF_STAT_TXFIFO_EMPTY_MASK, /*!< TXFIFO empty. */
kELCDIF_LcdControllerBusy = LCDIF_STAT_BUSY_MASK, /*!< The external LCD controller busy signal. */
kELCDIF_CurDviField2 = LCDIF_STAT_DVI_CURRENT_FIELD_MASK, /*!< Current DVI filed, if set, then current filed is 2,
otherwise current filed is 1. */
};
/*!
* @brief The pixel format.
*
* This enumerator should be defined together with the array s_pixelFormatReg.
* To support new pixel format, enhance this enumerator and s_pixelFormatReg.
*/
typedef enum _elcdif_pixel_format
{
kELCDIF_PixelFormatRAW8 = 0, /*!< RAW 8 bit, four data use 32 bits. */
kELCDIF_PixelFormatRGB565 = 1, /*!< RGB565, two pixel use 32 bits. */
kELCDIF_PixelFormatRGB666 = 2, /*!< RGB666 unpacked, one pixel uses 32 bits, high byte unused,
upper 2 bits of other bytes unused. */
kELCDIF_PixelFormatRGB888 = 3, /*!< RGB888 unpacked, one pixel uses 32 bits, high byte unused. */
} elcdif_pixel_format_t;
/*! @brief The LCD data bus type. */
typedef enum _elcdif_lcd_data_bus
{
kELCDIF_DataBus8Bit = LCDIF_CTRL_LCD_DATABUS_WIDTH(1), /*!< 8-bit data bus. */
kELCDIF_DataBus16Bit = LCDIF_CTRL_LCD_DATABUS_WIDTH(0), /*!< 16-bit data bus, support RGB565. */
kELCDIF_DataBus18Bit = LCDIF_CTRL_LCD_DATABUS_WIDTH(2), /*!< 18-bit data bus, support RGB666. */
kELCDIF_DataBus24Bit = LCDIF_CTRL_LCD_DATABUS_WIDTH(3), /*!< 24-bit data bus, support RGB888. */
} elcdif_lcd_data_bus_t;
/*!
* @brief The register value when using different pixel format.
*
* These register bits control the pixel format:
* - CTRL[DATA_FORMAT_24_BIT]
* - CTRL[DATA_FORMAT_18_BIT]
* - CTRL[DATA_FORMAT_16_BIT]
* - CTRL[WORD_LENGTH]
* - CTRL1[BYTE_PACKING_FORMAT]
*/
typedef struct _elcdif_pixel_format_reg
{
uint32_t regCtrl; /*!< Value of register CTRL. */
uint32_t regCtrl1; /*!< Value of register CTRL1. */
} elcdif_pixel_format_reg_t;
/*!
* @brief eLCDIF configure structure for RGB mode (DOTCLK mode).
*/
typedef struct _elcdif_rgb_mode_config
{
uint16_t panelWidth; /*!< Display panel width, pixels per line. */
uint16_t panelHeight; /*!< Display panel height, how many lines per panel. */
uint8_t hsw; /*!< HSYNC pulse width. */
uint8_t hfp; /*!< Horizontal front porch. */
uint8_t hbp; /*!< Horizontal back porch. */
uint8_t vsw; /*!< VSYNC pulse width. */
uint8_t vfp; /*!< Vrtical front porch. */
uint8_t vbp; /*!< Vertical back porch. */
uint32_t polarityFlags; /*!< OR'ed value of @ref _elcdif_polarity_flags, used to contol the signal polarity. */
uint32_t bufferAddr; /*!< Frame buffer address. */
elcdif_pixel_format_t pixelFormat; /*!< Pixel format. */
elcdif_lcd_data_bus_t dataBus; /*!< LCD data bus. */
} elcdif_rgb_mode_config_t;
/*!
* @brief eLCDIF alpha surface pixel format.
*/
typedef enum _elcdif_as_pixel_format
{
kELCDIF_AsPixelFormatARGB8888 = 0x0, /*!< 32-bit pixels with alpha. */
kELCDIF_AsPixelFormatRGB888 = 0x4, /*!< 32-bit pixels without alpha (unpacked 24-bit format) */
kELCDIF_AsPixelFormatARGB1555 = 0x8, /*!< 16-bit pixels with alpha. */
kELCDIF_AsPixelFormatARGB4444 = 0x9, /*!< 16-bit pixels with alpha. */
kELCDIF_AsPixelFormatRGB555 = 0xC, /*!< 16-bit pixels without alpha. */
kELCDIF_AsPixelFormatRGB444 = 0xD, /*!< 16-bit pixels without alpha. */
kELCDIF_AsPixelFormatRGB565 = 0xE, /*!< 16-bit pixels without alpha. */
} elcdif_as_pixel_format_t;
/*!
* @brief eLCDIF alpha surface buffer configuration.
*/
typedef struct _elcdif_as_buffer_config
{
uint32_t bufferAddr; /*!< Buffer address. */
elcdif_as_pixel_format_t pixelFormat; /*!< Pixel format. */
} elcdif_as_buffer_config_t;
/*!
* @brief eLCDIF alpha mode during blending.
*/
typedef enum _elcdif_alpha_mode
{
kELCDIF_AlphaEmbedded, /*!< The alpha surface pixel alpha value will be used for blend. */
kELCDIF_AlphaOverride, /*!< The user defined alpha value will be used for blend directly. */
kELCDIF_AlphaMultiply, /*!< The alpha surface pixel alpha value scaled the user defined
alpha value will be used for blend, for example, pixel alpha set
set to 200, user defined alpha set to 100, then the reault alpha
is 200 * 100 / 255. */
kELCDIF_AlphaRop /*!< Raster operation. */
} elcdif_alpha_mode_t;
/*!
* @brief eLCDIF ROP mode during blending.
*
* Explanation:
* - AS: Alpha surface
* - PS: Process surface
* - nAS: Alpha surface NOT value
* - nPS: Process surface NOT value
*/
typedef enum _elcdif_rop_mode
{
kELCDIF_RopMaskAs = 0x0, /*!< AS AND PS. */
kELCDIF_RopMaskNotAs = 0x1, /*!< nAS AND PS. */
kELCDIF_RopMaskAsNot = 0x2, /*!< AS AND nPS. */
kELCDIF_RopMergeAs = 0x3, /*!< AS OR PS. */
kELCDIF_RopMergeNotAs = 0x4, /*!< nAS OR PS. */
kELCDIF_RopMergeAsNot = 0x5, /*!< AS OR nPS. */
kELCDIF_RopNotCopyAs = 0x6, /*!< nAS. */
kELCDIF_RopNot = 0x7, /*!< nPS. */
kELCDIF_RopNotMaskAs = 0x8, /*!< AS NAND PS. */
kELCDIF_RopNotMergeAs = 0x9, /*!< AS NOR PS. */
kELCDIF_RopXorAs = 0xA, /*!< AS XOR PS. */
kELCDIF_RopNotXorAs = 0xB /*!< AS XNOR PS. */
} elcdif_rop_mode_t;
/*!
* @brief eLCDIF alpha surface blending configuration.
*/
typedef struct _elcdif_as_blend_config
{
uint8_t alpha; /*!< User defined alpha value, only used when @ref alphaMode is @ref kELCDIF_AlphaOverride or @ref
kELCDIF_AlphaRop. */
bool invertAlpha; /*!< Set true to invert the alpha. */
elcdif_alpha_mode_t alphaMode; /*!< Alpha mode. */
elcdif_rop_mode_t ropMode; /*!< ROP mode, only valid when @ref alphaMode is @ref kELCDIF_AlphaRop. */
} elcdif_as_blend_config_t;
/*******************************************************************************
* APIs
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name eLCDIF initialization and de-initialization
* @{
*/
/*!
* @brief Initializes the eLCDIF to work in RGB mode (DOTCLK mode).
*
* This function ungates the eLCDIF clock and configures the eLCDIF peripheral according
* to the configuration structure.
*
* @param base eLCDIF peripheral base address.
* @param config Pointer to the configuration structure.
*/
void ELCDIF_RgbModeInit(LCDIF_Type *base, const elcdif_rgb_mode_config_t *config);
/*!
* @brief Gets the eLCDIF default configuration structure for RGB (DOTCLK) mode.
*
* This function sets the configuration structure to default values.
* The default configuration is set to the following values.
* @code
config->panelWidth = 480U;
config->panelHeight = 272U;
config->hsw = 41;
config->hfp = 4;
config->hbp = 8;
config->vsw = 10;
config->vfp = 4;
config->vbp = 2;
config->polarityFlags = kELCDIF_VsyncActiveLow |
kELCDIF_HsyncActiveLow |
kELCDIF_DataEnableActiveLow |
kELCDIF_DriveDataOnFallingClkEdge;
config->bufferAddr = 0U;
config->pixelFormat = kELCDIF_PixelFormatRGB888;
config->dataBus = kELCDIF_DataBus24Bit;
@code
*
* @param config Pointer to the eLCDIF configuration structure.
*/
void ELCDIF_RgbModeGetDefaultConfig(elcdif_rgb_mode_config_t *config);
/*!
* @brief Deinitializes the eLCDIF peripheral.
*
* @param base eLCDIF peripheral base address.
*/
void ELCDIF_Deinit(LCDIF_Type *base);
/* @} */
/*!
* @name Module operation
* @{
*/
/*!
* @brief Start to display in RGB (DOTCLK) mode.
*
* @param base eLCDIF peripheral base address.
*/
static inline void ELCDIF_RgbModeStart(LCDIF_Type *base)
{
base->CTRL_SET = LCDIF_CTRL_RUN_MASK | LCDIF_CTRL_DOTCLK_MODE_MASK;
}
/*!
* @brief Stop display in RGB (DOTCLK) mode and wait until finished.
*
* @param base eLCDIF peripheral base address.
*/
void ELCDIF_RgbModeStop(LCDIF_Type *base);
/*!
* @brief Set the next frame buffer address to display.
*
* @param base eLCDIF peripheral base address.
* @param bufferAddr The frame buffer address to set.
*/
static inline void ELCDIF_SetNextBufferAddr(LCDIF_Type *base, uint32_t bufferAddr)
{
base->NEXT_BUF = bufferAddr;
}
/*!
* @brief Reset the eLCDIF peripheral.
*
* @param base eLCDIF peripheral base address.
*/
void ELCDIF_Reset(LCDIF_Type *base);
/*!
* @brief Pull up or down the reset pin for the externel LCD controller.
*
* @param base eLCDIF peripheral base address.
* @param pullUp True to pull up reset pin, false to pull down.
*/
static inline void ELCDIF_PullUpResetPin(LCDIF_Type *base, bool pullUp)
{
if (pullUp)
{
base->CTRL1_SET = LCDIF_CTRL1_RESET_MASK;
}
else
{
base->CTRL1_CLR = LCDIF_CTRL1_RESET_MASK;
}
}
/*!
* @brief Enable or disable the hand shake with PXP.
*
* @param base eLCDIF peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void ELCDIF_EnablePxpHandShake(LCDIF_Type *base, bool enable)
{
if (enable)
{
base->CTRL_SET = LCDIF_CTRL_ENABLE_PXP_HANDSHAKE_MASK;
}
else
{
base->CTRL_CLR = LCDIF_CTRL_ENABLE_PXP_HANDSHAKE_MASK;
}
}
/* @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Get the CRC value of the frame sent out.
*
* When a frame is sent complete (the interrupt @ref kELCDIF_CurFrameDone assert), this function
* can be used to get the CRC value of the frame sent.
*
* @param base eLCDIF peripheral base address.
* @return The CRC value.
*
* @note The CRC value is dependent on the LCD_DATABUS_WIDTH.
*/
static inline uint32_t ELCDIF_GetCrcValue(LCDIF_Type *base)
{
return base->CRC_STAT;
}
/*!
* @brief Get the bus master error virtual address.
*
* When bus master error occurs (the interrupt kELCDIF_BusMasterError assert), this function
* can get the virtual address at which the AXI master received an error
* response from the slave.
*
* @param base eLCDIF peripheral base address.
* @return The error virtual address.
*/
static inline uint32_t ELCDIF_GetBusMasterErrorAddr(LCDIF_Type *base)
{
return base->BM_ERROR_STAT;
}
/*!
* @brief Get the eLCDIF status.
*
* The status flags are returned as a mask value, application could check the
* corresponding bit. Example:
*
* @code
uint32_t statusFlags;
statusFlags = ELCDIF_GetStatus(LCDIF);
// If LFIFO is full.
if (kELCDIF_LFifoFull & statusFlags)
{
// ...;
}
// If TXFIFO is empty.
if (kELCDIF_TxFifoEmpty & statusFlags)
{
// ...;
}
@endcode
*
* @param base eLCDIF peripheral base address.
* @return The mask value of status flags, it is OR'ed value of @ref _elcdif_status_flags.
*/
static inline uint32_t ELCDIF_GetStatus(LCDIF_Type *base)
{
return base->STAT & (LCDIF_STAT_LFIFO_FULL_MASK | LCDIF_STAT_LFIFO_EMPTY_MASK | LCDIF_STAT_TXFIFO_FULL_MASK |
LCDIF_STAT_TXFIFO_EMPTY_MASK | LCDIF_STAT_BUSY_MASK | LCDIF_STAT_DVI_CURRENT_FIELD_MASK);
}
/*!
* @brief Get current count in Latency buffer (LFIFO).
*
* @param base eLCDIF peripheral base address.
* @return The LFIFO current count
*/
static inline uint32_t ELCDIF_GetLFifoCount(LCDIF_Type *base)
{
return (base->STAT & LCDIF_STAT_LFIFO_COUNT_MASK) >> LCDIF_STAT_LFIFO_COUNT_SHIFT;
}
/* @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables eLCDIF interrupt requests.
*
* @param base eLCDIF peripheral base address.
* @param mask interrupt source, OR'ed value of _elcdif_interrupt_enable.
*/
static inline void ELCDIF_EnableInterrupts(LCDIF_Type *base, uint32_t mask)
{
base->CTRL1_SET = (mask & ELCDIF_CTRL1_IRQ_EN_MASK);
base->AS_CTRL |= (mask & ELCDIF_AS_CTRL_IRQ_EN_MASK);
}
/*!
* @brief Disables eLCDIF interrupt requests.
*
* @param base eLCDIF peripheral base address.
* @param mask interrupt source, OR'ed value of _elcdif_interrupt_enable.
*/
static inline void ELCDIF_DisableInterrupts(LCDIF_Type *base, uint32_t mask)
{
base->CTRL1_CLR = (mask & ELCDIF_CTRL1_IRQ_EN_MASK);
base->AS_CTRL &= ~(mask & ELCDIF_AS_CTRL_IRQ_EN_MASK);
}
/*!
* @brief Get eLCDIF interrupt peding status.
*
* @param base eLCDIF peripheral base address.
* @return Interrupt pending status, OR'ed value of _elcdif_interrupt_flags.
*/
static inline uint32_t ELCDIF_GetInterruptStatus(LCDIF_Type *base)
{
uint32_t flags;
flags = (base->CTRL1 & ELCDIF_CTRL1_IRQ_MASK);
flags |= (base->AS_CTRL & ELCDIF_AS_CTRL_IRQ_MASK);
return flags;
}
/*!
* @brief Clear eLCDIF interrupt peding status.
*
* @param base eLCDIF peripheral base address.
* @param mask of the flags to clear, OR'ed value of _elcdif_interrupt_flags.
*/
static inline void ELCDIF_ClearInterruptStatus(LCDIF_Type *base, uint32_t mask)
{
base->CTRL1_CLR = (mask & ELCDIF_CTRL1_IRQ_MASK);
base->AS_CTRL &= ~(mask & ELCDIF_AS_CTRL_IRQ_MASK);
}
/* @} */
/*!
* @name Alpha surface
* @{
*/
/*!
* @brief Set the configuration for alpha surface buffer.
*
* @param base eLCDIF peripheral base address.
* @param config Pointer to the configuration structure.
*/
void ELCDIF_SetAlphaSurfaceBufferConfig(LCDIF_Type *base, const elcdif_as_buffer_config_t *config);
/*!
* @brief Set the alpha surface blending configuration.
*
* @param base eLCDIF peripheral base address.
* @param config Pointer to the configuration structure.
*/
void ELCDIF_SetAlphaSurfaceBlendConfig(LCDIF_Type *base, const elcdif_as_blend_config_t *config);
/*!
* @brief Set the next alpha surface buffer address.
*
* @param base eLCDIF peripheral base address.
* @param bufferAddr Alpha surface buffer address.
*/
static inline void ELCDIF_SetNextAlphaSurfaceBufferAddr(LCDIF_Type *base, uint32_t bufferAddr)
{
base->AS_NEXT_BUF = bufferAddr;
}
/*!
* @brief Set the overlay color key.
*
* If a pixel in the current overlay image with a color that falls in the range
* from the @p colorKeyLow to @p colorKeyHigh range, it will use the process surface
* pixel value for that location.
*
* @param base eLCDIF peripheral base address.
* @param colorKeyLow Color key low range.
* @param colorKeyHigh Color key high range.
*
* @note Colorkey operations are higher priority than alpha or ROP operations
*/
static inline void ELCDIF_SetOverlayColorKey(LCDIF_Type *base, uint32_t colorKeyLow, uint32_t colorKeyHigh)
{
base->AS_CLRKEYLOW = colorKeyLow;
base->AS_CLRKEYHIGH = colorKeyHigh;
}
/*!
* @brief Enable or disable the color key.
*
* @param base eLCDIF peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void ELCDIF_EnableOverlayColorKey(LCDIF_Type *base, bool enable)
{
if (enable)
{
base->AS_CTRL |= LCDIF_AS_CTRL_ENABLE_COLORKEY_MASK;
}
else
{
base->AS_CTRL &= ~LCDIF_AS_CTRL_ENABLE_COLORKEY_MASK;
}
}
/*!
* @brief Enable or disable the alpha surface.
*
* @param base eLCDIF peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void ELCDIF_EnableAlphaSurface(LCDIF_Type *base, bool enable)
{
if (enable)
{
base->AS_CTRL |= LCDIF_AS_CTRL_AS_ENABLE_MASK;
}
else
{
base->AS_CTRL &= ~LCDIF_AS_CTRL_AS_ENABLE_MASK;
}
}
/*!
* @brief Enable or disable the process surface.
*
* Process surface is the normal frame buffer. The process surface content
* is controlled by @ref ELCDIF_SetNextBufferAddr.
*
* @param base eLCDIF peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void ELCDIF_EnableProcessSurface(LCDIF_Type *base, bool enable)
{
if (enable)
{
base->AS_CTRL &= ~LCDIF_AS_CTRL_PS_DISABLE_MASK;
}
else
{
base->AS_CTRL |= LCDIF_AS_CTRL_PS_DISABLE_MASK;
}
}
/* @} */
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/* @} */
#endif /*_FSL_ELCDIF_H_*/

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,122 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_epit.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the instance from the base address to be used to gate or ungate the module clock
*
* @param base EPIT peripheral base address
*
* @return The EPIT instance
*/
static uint32_t EPIT_GetInstance(EPIT_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to EPIT bases for each instance. */
static EPIT_Type *const s_epitBases[] = EPIT_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to EPIT clocks for each instance. */
static const clock_ip_name_t s_epitClocks[] = EPIT_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t EPIT_GetInstance(EPIT_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_epitBases); instance++)
{
if (s_epitBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_epitBases));
return instance;
}
void EPIT_Init(EPIT_Type *base, const epit_config_t *config)
{
assert(config);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate the EPIT clock*/
CLOCK_EnableClock(s_epitClocks[EPIT_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
base->CR = 0U;
EPIT_SoftwareReset(base);
base->CR =
(config->enableRunInStop ? EPIT_CR_STOPEN_MASK : 0U) | (config->enableRunInWait ? EPIT_CR_WAITEN_MASK : 0U) |
(config->enableRunInDbg ? EPIT_CR_DBGEN_MASK : 0U) | (config->enableCounterOverwrite ? EPIT_CR_IOVW_MASK : 0U) |
(config->enableFreeRun ? 0U : EPIT_CR_RLD_MASK) | (config->enableResetMode ? EPIT_CR_ENMOD_MASK : 0U);
EPIT_SetClockSource(base, config->clockSource);
EPIT_SetClockDivider(base, config->divider);
}
void EPIT_Deinit(EPIT_Type *base)
{
/* Disable EPIT timers */
base->CR = 0U;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Gate the EPIT clock*/
CLOCK_DisableClock(s_epitClocks[EPIT_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void EPIT_GetDefaultConfig(epit_config_t *config)
{
assert(config);
config->clockSource = kEPIT_ClockSource_Periph;
config->divider = 1U;
config->enableRunInStop = true;
config->enableRunInWait = true;
config->enableRunInDbg = false;
config->enableCounterOverwrite = false;
config->enableFreeRun = false;
config->enableResetMode = true;
}

View File

@ -0,0 +1,397 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_EPIT_H_
#define _FSL_EPIT_H_
#include "fsl_common.h"
/*!
* @addtogroup epit
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_EPIT_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
/*@}*/
/*!
* @brief List of clock sources
* @note Actual number of clock sources is SoC dependent
*/
typedef enum _epit_clock_source
{
kEPIT_ClockSource_Off = 0U, /*!< EPIT Clock Source Off.*/
kEPIT_ClockSource_Periph = 1U, /*!< EPIT Clock Source from Peripheral Clock.*/
kEPIT_ClockSource_HighFreq = 2U, /*!< EPIT Clock Source from High Frequency Reference Clock.*/
kEPIT_ClockSource_LowFreq = 3U, /*!< EPIT Clock Source from Low Frequency Reference Clock.*/
} epit_clock_source_t;
/*!
* @brief List of output compare operation mode
*/
typedef enum _epit_output_operation_mode
{
kEPIT_OutputOperation_Disconnected = 0U, /*!< EPIT Output Operation: Disconnected from pad.*/
kEPIT_OutputOperation_Toggle = 1U, /*!< EPIT Output Operation: Toggle output pin.*/
kEPIT_OutputOperation_Clear = 2U, /*!< EPIT Output Operation: Clear output pin.*/
kEPIT_OutputOperation_Set = 3U, /*!< EPIT Output Operation: Set putput pin.*/
} epit_output_operation_mode_t;
/*! @brief List of EPIT interrupts */
typedef enum _epit_interrupt_enable
{
kEPIT_OutputCompareInterruptEnable = EPIT_CR_OCIEN_MASK, /*!< Output Compare interrupt enable*/
} epit_interrupt_enable_t;
/*! @brief List of EPIT status flags */
typedef enum _epit_status_flags
{
kEPIT_OutputCompareFlag = EPIT_SR_OCIF_MASK, /*!< Output Compare flag */
} epit_status_flags_t;
/*! @brief Structure to configure the running mode. */
typedef struct _epit_config
{
epit_clock_source_t clockSource; /*!< clock source for EPIT module. */
uint32_t divider; /*!< clock divider (prescaler+1) from clock source to counter. */
bool enableRunInStop; /*!< EPIT enabled in stop mode. */
bool enableRunInWait; /*!< EPIT enabled in wait mode. */
bool enableRunInDbg; /*!< EPIT enabled in debug mode. */
bool enableCounterOverwrite; /*!< set timer period results in counter value being overwritten. */
bool enableFreeRun; /*!< true: free-running mode, counter will be reset to 0xFFFFFFFF when timer expires;
false: set-and-forget mode, counter will be reloaded from set timer periods. */
bool enableResetMode; /*!< true: counter is reset to timer periods in set-and-forget mode or 0xFFFFFFFF in
free-running mode when enabled;
false: counter restores the value that it was disabled when enabled. */
} epit_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Software Reset
* @{
*/
/*!
* @brief Software reset of EPIT module.
*
* @param base EPIT peripheral base address.
*/
static inline void EPIT_SoftwareReset(EPIT_Type *base)
{
base->CR |= EPIT_CR_SWR_MASK;
/* Wait reset finished. */
while ((base->CR & EPIT_CR_SWR_MASK) == EPIT_CR_SWR_MASK)
{
}
}
/* @} */
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the EPIT clock and configures the peripheral for a basic operation.
*
* This function issues a software reset to reset all the registers to their reset values,
* except for the EN, ENMOD, STOPEN, WAITEN and DBGEN bits in Control register.
*
* @note This API should be called at the beginning of the application using the EPIT driver.
*
* @param base EPIT peripheral base address.
* @param config Pointer to the user configuration structure.
*/
void EPIT_Init(EPIT_Type *base, const epit_config_t *config);
/*!
* @brief Disables the module and gates the EPIT clock.
*
* @param base EPIT peripheral base address.
*/
void EPIT_Deinit(EPIT_Type *base);
/*!
* @brief Fills in the EPIT configuration structure with default settings.
*
* The default values are:
* @code
* config->clockSource = kEPIT_ClockSource_Periph;
* config->divider = 1U;
* config->enableRunInStop = true;
* config->enableRunInWait = true;
* config->enableRunInDbg = false;
* config->enableCounterOverwrite = false;
* config->enableFreeRun = false;
* config->enableResetMode = true;
* @endcode
* @param config Pointer to the user configuration structure.
*/
void EPIT_GetDefaultConfig(epit_config_t *config);
/*! @}*/
/*!
* @name Clock source and frequency control
* @{
*/
/*!
* @brief Set clock source of EPIT.
*
* @param base EPIT peripheral base address.
* @param source clock source to switch to.
*/
static inline void EPIT_SetClockSource(EPIT_Type *base, epit_clock_source_t source)
{
base->CR = (base->CR & ~EPIT_CR_CLKSRC_MASK) | EPIT_CR_CLKSRC(source);
}
/*!
* @brief Set clock divider inside EPIT module.
*
* @param base EPIT peripheral base address.
* @param divider Clock divider in EPIT module (1-4096, divider = prescaler + 1).
*/
static inline void EPIT_SetClockDivider(EPIT_Type *base, uint32_t divider)
{
assert((divider > 0) && (divider <= (EPIT_CR_PRESCALAR_MASK >> EPIT_CR_PRESCALAR_SHIFT) + 1));
base->CR = (base->CR & ~EPIT_CR_PRESCALAR_MASK) | EPIT_CR_PRESCALAR(divider - 1);
}
/*!
* @brief Get clock divider inside EPIT module.
*
* @param base EPIT base pointer.
* @return clock divider in EPIT module (1-4096).
*/
static inline uint32_t EPIT_GetClockDivider(EPIT_Type *base)
{
return ((base->CR & EPIT_CR_PRESCALAR_MASK) >> EPIT_CR_PRESCALAR_SHIFT) + 1;
}
/*! @}*/
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Start EPIT timer.
*
* @param base EPIT peripheral base address.
*/
static inline void EPIT_StartTimer(EPIT_Type *base)
{
base->CR |= EPIT_CR_EN_MASK;
}
/*!
* @brief Stop EPIT timer.
*
* @param base EPIT peripheral base address.
*/
static inline void EPIT_StopTimer(EPIT_Type *base)
{
base->CR &= ~EPIT_CR_EN_MASK;
}
/*! @}*/
/*!
* @name Read and Write the timer period
* @{
*/
/*!
* @brief Sets the timer period in units of count.
*
* Timers begin counting down from the value set by this function until it reaches 0, at which point
* it generates an interrupt and loads this register value again.
* When enableCounterOverwrite is false, writing a new value to this register does not restart the timer,
* and the value is loaded after the timer expires. When enableCounterOverwrite is true, the counter
* will be set immediately and starting counting down from that value.
*
* @note User can call the utility macros provided in fsl_common.h to convert to ticks.
*
* @param base EPIT peripheral base address.
* @param ticks Timer period in units of ticks.
*/
static inline void EPIT_SetTimerPeriod(EPIT_Type *base, uint32_t ticks)
{
base->LR = ticks;
}
/*!
* @brief Reads the current timer counting value.
*
* This function returns the real-time timer counting value, in a range from 0 to a
* timer period.
*
* @note User can call the utility macros provided in fsl_common.h to convert ticks to microseconds or milliseconds.
*
* @param base EPIT peripheral base address.
*
* @return Current timer counting value in ticks.
*/
static inline uint32_t EPIT_GetCurrentTimerCount(EPIT_Type *base)
{
return base->CNR;
}
/*@}*/
/*!
* @name Output Signal Control
* @{
*/
/*!
* @brief Set EPIT output compare operation mode.
*
* @param base EPIT peripheral base address.
* @param mode EPIT output compare operation mode.
*/
static inline void EPIT_SetOutputOperationMode(EPIT_Type *base, epit_output_operation_mode_t mode)
{
base->CR = (base->CR & ~EPIT_CR_OM_MASK) | EPIT_CR_OM(mode);
}
/*!
* @brief Set EPIT output compare value.
*
* @param base EPIT peripheral base address.
* @param value EPIT output compare value.
*/
static inline void EPIT_SetOutputCompareValue(EPIT_Type *base, uint32_t value)
{
base->CMPR = value;
}
/*@}*/
/*!
* @name Interrupt Interface
* @{
*/
/*!
* @brief Enables the selected EPIT interrupts.
*
* @param base EPIT peripheral base address.
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::epit_interrupt_enable_t
*/
static inline void EPIT_EnableInterrupts(EPIT_Type *base, uint32_t mask)
{
base->CR |= mask;
}
/*!
* @brief Disables the selected EPIT interrupts.
*
* @param base EPIT peripheral base address
* @param mask The interrupts to disable. This is a logical OR of members of the
* enumeration ::epit_interrupt_enable_t
*/
static inline void EPIT_DisableInterrupts(EPIT_Type *base, uint32_t mask)
{
base->CR &= ~mask;
}
/*!
* @brief Gets the enabled EPIT interrupts.
*
* @param base EPIT peripheral base address
*
* @return The enabled interrupts. This is the logical OR of members of the
* enumeration ::epit_interrupt_enable_t
*/
static inline uint32_t EPIT_GetEnabledInterrupts(EPIT_Type *base)
{
return (base->CR & EPIT_CR_OCIEN_MASK);
}
/*! @}*/
/*!
* @name Status Interface
* @{
*/
/*!
* @brief Gets the EPIT status flags.
*
* @param base EPIT peripheral base address
*
* @return The status flags. This is the logical OR of members of the
* enumeration ::epit_status_flags_t
*/
static inline uint32_t EPIT_GetStatusFlags(EPIT_Type *base)
{
return (base->SR & EPIT_SR_OCIF_MASK);
}
/*!
* @brief Clears the EPIT status flags.
*
* @param base EPIT peripheral base address
* @param mask The status flags to clear. This is a logical OR of members of the
* enumeration ::epit_status_flags_t
*/
static inline void EPIT_ClearStatusFlags(EPIT_Type *base, uint32_t mask)
{
base->SR = mask;
}
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /*_FSL_EPIT_H_*/

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