delete useless config on riscv-board
This commit is contained in:
parent
afe2a7766d
commit
76017d0d0d
|
@ -1,13 +1,5 @@
|
|||
SRC_FILES := sleep.c
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_AUDIO),y)
|
||||
SRC_DIR += audio
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_CAMERA),y)
|
||||
SRC_DIR += camera
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_CH376),y)
|
||||
SRC_DIR += ch376
|
||||
endif
|
||||
|
@ -32,14 +24,6 @@ ifeq ($(CONFIG_BSP_USING_I2C),y)
|
|||
SRC_DIR += i2c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_I2S),y)
|
||||
SRC_DIR += i2s
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_KPU),y)
|
||||
SRC_DIR += kpu
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_LCD),y)
|
||||
SRC_DIR += lcd
|
||||
endif
|
||||
|
@ -48,18 +32,10 @@ ifeq ($(CONFIG_BSP_USING_PLIC),y)
|
|||
SRC_DIR += plic
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_PWM),y)
|
||||
SRC_DIR += pwm
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_RTC),y)
|
||||
SRC_DIR += rtc
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SECURITY),y)
|
||||
SRC_DIR += security
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SPI),y)
|
||||
SRC_DIR += spi
|
||||
endif
|
||||
|
@ -80,10 +56,6 @@ ifeq ($(CONFIG_BSP_USING_UART),y)
|
|||
SRC_DIR += uart
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_VIDEO),y)
|
||||
SRC_DIR += video
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_WDT),y)
|
||||
SRC_DIR += watchdog
|
||||
endif
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
SRC_FILES := sleep.c
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_AUDIO),y)
|
||||
SRC_DIR += audio
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_CAMERA),y)
|
||||
SRC_DIR += camera
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_DMA),y)
|
||||
SRC_DIR += dma
|
||||
endif
|
||||
|
@ -20,10 +12,6 @@ ifeq ($(CONFIG_BSP_USING_I2C),y)
|
|||
SRC_DIR += i2c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_I2S),y)
|
||||
SRC_DIR += i2s
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_PLIC),y)
|
||||
SRC_DIR += plic
|
||||
endif
|
||||
|
@ -32,10 +20,6 @@ ifeq ($(CONFIG_BSP_USING_RTC),y)
|
|||
SRC_DIR += rtc
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SECURITY),y)
|
||||
SRC_DIR += security
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SPI),y)
|
||||
SRC_DIR += spi
|
||||
endif
|
||||
|
|
|
@ -55,13 +55,9 @@ extern x_base cpu2_boot_flag;
|
|||
extern void entry(void);
|
||||
extern void SecondaryCpuCStart(void);
|
||||
extern int IoConfigInit(void);
|
||||
extern int HwSpiInit(void);
|
||||
extern int HwI2cInit(void);
|
||||
extern int HwRtcInit(void);
|
||||
extern int HwWdtInit(void);
|
||||
extern int HwLcdInit(void);
|
||||
extern int HwTouchInit(void);
|
||||
extern int HwTimerInit(void);
|
||||
|
||||
#if defined(FS_VFS) && defined (MOUNT_SDCARD)
|
||||
#include <iot-vfs.h>
|
||||
|
@ -162,24 +158,12 @@ struct InitSequenceDesc _board_init[] =
|
|||
{ "hw_pin", HwGpioInit },
|
||||
{ "io_config", IoConfigInit },
|
||||
#endif
|
||||
#ifdef BSP_USING_SPI
|
||||
{ "hw_spi", HwSpiInit },
|
||||
#endif
|
||||
#ifdef BSP_USING_I2C
|
||||
{ "hw_i2c", HwI2cInit },
|
||||
#endif
|
||||
#ifdef BSP_USING_LCD
|
||||
{ "hw_lcd", HwLcdInit },
|
||||
#endif
|
||||
#ifdef BSP_USING_HWTIMER
|
||||
{ "hw_timer" , HwTimerInit },
|
||||
#endif
|
||||
#ifdef BSP_USING_WDT
|
||||
{ "hw_wdt", HwWdtInit },
|
||||
#endif
|
||||
#ifdef BSP_USING_RTC
|
||||
{"hw_rtc", HwRtcInit },
|
||||
#endif
|
||||
#ifdef BSP_USING_TOUCH
|
||||
{"touch", HwTouchInit },
|
||||
#endif
|
||||
|
|
|
@ -32,28 +32,11 @@ endif
|
|||
|
||||
menuconfig BSP_USING_PLIC
|
||||
bool "Using PLIC device"
|
||||
default y
|
||||
default n
|
||||
if BSP_USING_PLIC
|
||||
source "$BSP_DIR/third_party_driver/plic/Kconfig"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_RTC
|
||||
bool "Using RTC device"
|
||||
default n
|
||||
select RESOURCES_RTC
|
||||
if BSP_USING_RTC
|
||||
source "$BSP_DIR/third_party_driver/rtc/Kconfig"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_SPI
|
||||
bool "Using SPI device"
|
||||
default n
|
||||
select RESOURCES_SPI
|
||||
select BSP_USING_DMA
|
||||
if BSP_USING_SPI
|
||||
source "$BSP_DIR/third_party_driver/spi/Kconfig"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_SYSCLOCK
|
||||
bool "Using SYSCLOCK device"
|
||||
default y
|
||||
|
@ -61,14 +44,6 @@ if BSP_USING_SYSCLOCK
|
|||
source "$BSP_DIR/third_party_driver/sys_clock/Kconfig"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_HWTIMER
|
||||
bool "Using HWTIMER device"
|
||||
default n
|
||||
select RESOURCES_HWTIMER
|
||||
if BSP_USING_HWTIMER
|
||||
source "$BSP_DIR/third_party_driver/timer/Kconfig"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_UART
|
||||
bool "Using UART device"
|
||||
default y
|
||||
|
@ -76,11 +51,3 @@ select RESOURCES_SERIAL
|
|||
if BSP_USING_UART
|
||||
source "$BSP_DIR/third_party_driver/uart/Kconfig"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_WDT
|
||||
bool "Using WATCHDOG device"
|
||||
default y
|
||||
select RESOURCES_WDT
|
||||
if BSP_USING_WDT
|
||||
source "$BSP_DIR/third_party_driver/watchdog/Kconfig"
|
||||
endif
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
SRC_FILES := sleep.c
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_AUDIO),y)
|
||||
SRC_DIR += audio
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_CAMERA),y)
|
||||
SRC_DIR += camera
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_DMA),y)
|
||||
SRC_DIR += dma
|
||||
endif
|
||||
|
@ -24,44 +16,16 @@ ifeq ($(CONFIG_BSP_USING_TOUCH),y)
|
|||
SRC_DIR += touch
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_I2S),y)
|
||||
SRC_DIR += i2s
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_PLIC),y)
|
||||
SRC_DIR += plic
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_RTC),y)
|
||||
SRC_DIR += rtc
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SECURITY),y)
|
||||
SRC_DIR += security
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SPI),y)
|
||||
SRC_DIR += spi
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SYSCLOCK),y)
|
||||
SRC_DIR += sys_clock
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_HWTIMER),y)
|
||||
SRC_DIR += timer
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_UART),y)
|
||||
SRC_DIR += uart
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_VIDEO),y)
|
||||
SRC_DIR += video
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_WDT),y)
|
||||
SRC_DIR += watchdog
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
if BSP_USING_RTC
|
||||
config RTC_BUS_NAME
|
||||
string "rtc bus name"
|
||||
default "rtc"
|
||||
config RTC_DRV_NAME
|
||||
string "rtc bus driver name"
|
||||
default "rtc_drv"
|
||||
config RTC_DEVICE_NAME
|
||||
string "rtc bus device name"
|
||||
default "rtc_dev"
|
||||
endif
|
|
@ -1,3 +0,0 @@
|
|||
SRC_FILES := connect_rtc.c hardware_rtc.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_rtc.c
|
||||
* @brief support xidatong-riscv64-board rtc function and register to bus framework
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-07-25
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include "sysctl.h"
|
||||
#include "connect_rtc.h"
|
||||
#include "hardware_rtc.h"
|
||||
|
||||
static int GetWeekDay(int year, int month, int day)
|
||||
{
|
||||
/* Magic method to get weekday */
|
||||
int weekday = (day += month < 3 ? year-- : year - 2,
|
||||
23 * month / 9 + day + 4 + year / 4 - year / 100 + year / 400) % 7;
|
||||
return weekday;
|
||||
}
|
||||
|
||||
static uint32 RtcConfigure(void *drv, struct BusConfigureInfo *configure_info)
|
||||
{
|
||||
NULL_PARAM_CHECK(drv);
|
||||
|
||||
struct RtcDriver *rtc_drv = (struct RtcDriver *)drv;
|
||||
struct RtcDrvConfigureParam *drv_param = (struct RtcDrvConfigureParam *)configure_info->private_data;
|
||||
|
||||
int cmd = drv_param->rtc_operation_cmd;
|
||||
time_t *time = drv_param->time;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case OPER_RTC_GET_TIME:
|
||||
{
|
||||
struct tm ct;
|
||||
int year,month,day,hour,minute,second;
|
||||
memset(&ct,0,sizeof(struct tm));
|
||||
|
||||
rtc_timer_get(&year, &month, &day, &hour, &minute, &second);
|
||||
|
||||
ct.tm_year = year - 1900;
|
||||
ct.tm_mon = month - 1;
|
||||
ct.tm_mday = day;
|
||||
ct.tm_wday = GetWeekDay(year, month, day);
|
||||
|
||||
ct.tm_hour = hour;
|
||||
ct.tm_min = minute;
|
||||
ct.tm_sec = second;
|
||||
|
||||
*time = mktime(&ct);
|
||||
}
|
||||
break;
|
||||
case OPER_RTC_SET_TIME:
|
||||
{
|
||||
struct tm *ct;
|
||||
struct tm tm_new;
|
||||
x_base lock;
|
||||
|
||||
lock = CriticalAreaLock();
|
||||
ct = localtime(time);
|
||||
memcpy(&tm_new, ct, sizeof(struct tm));
|
||||
CriticalAreaUnLock(lock);
|
||||
|
||||
sysctl_reset(SYSCTL_RESET_RTC);
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_RTC);
|
||||
rtc_protect_set(0);
|
||||
rtc_timer_set_clock_frequency(SysctlClockGetFreq(SYSCTL_CLOCK_IN0));
|
||||
rtc_timer_set_clock_count_value(1);
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
|
||||
if (rtc_timer_set(tm_new.tm_year+1900,tm_new.tm_mon+1,tm_new.tm_mday,
|
||||
tm_new.tm_hour,tm_new.tm_min,tm_new.tm_sec)==-1)
|
||||
return ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return EOK;
|
||||
}
|
||||
|
||||
/*manage the rtc device operations*/
|
||||
static const struct RtcDevDone dev_done =
|
||||
{
|
||||
.open = NONE,
|
||||
.close = NONE,
|
||||
.write = NONE,
|
||||
.read = NONE,
|
||||
};
|
||||
|
||||
static int BoardRtcBusInit(struct RtcBus *rtc_bus, struct RtcDriver *rtc_driver)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
/*Init the rtc bus */
|
||||
ret = RtcBusInit(rtc_bus, RTC_BUS_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("HwRtcInit RtcBusInit error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*Init the rtc driver*/
|
||||
ret = RtcDriverInit(rtc_driver, RTC_DRV_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("HwRtcInit RtcDriverInit error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*Attach the rtc driver to the rtc bus*/
|
||||
ret = RtcDriverAttachToBus(RTC_DRV_NAME, RTC_BUS_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("HwRtcInit RtcDriverAttachToBus error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Attach the rtc device to the rtc bus*/
|
||||
static int BoardRtcDevBend(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
static struct RtcHardwareDevice rtc_device;
|
||||
memset(&rtc_device, 0, sizeof(struct RtcHardwareDevice));
|
||||
|
||||
rtc_device.dev_done = &(dev_done);
|
||||
|
||||
ret = RtcDeviceRegister(&rtc_device, NONE, RTC_DEVICE_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("HwRtcInit RtcDeviceInit device %s error %d\n", RTC_DEVICE_NAME, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = RtcDeviceAttachToBus(RTC_DEVICE_NAME, RTC_BUS_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("HwRtcInit RtcDeviceAttachToBus device %s error %d\n", RTC_DEVICE_NAME, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int HwRtcInit(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
static struct RtcBus rtc_bus;
|
||||
memset(&rtc_bus, 0, sizeof(struct RtcBus));
|
||||
|
||||
static struct RtcDriver rtc_driver;
|
||||
memset(&rtc_driver, 0, sizeof(struct RtcDriver));
|
||||
|
||||
rtc_driver.configure = &(RtcConfigure);
|
||||
|
||||
ret = BoardRtcBusInit(&rtc_bus, &rtc_driver);
|
||||
if (EOK != ret) {
|
||||
KPrintf("HwRtcInit error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = BoardRtcDevBend();
|
||||
if (EOK != ret) {
|
||||
KPrintf("HwRtcInit error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
rtc_init();
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,597 +0,0 @@
|
|||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hardware_rtc.c
|
||||
* @brief add from Canaan k210 SDK
|
||||
* https://canaan-creative.com/developer
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-07-25
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include "encoding.h"
|
||||
#include "sysctl.h"
|
||||
#include "hardware_rtc.h"
|
||||
|
||||
volatile rtc_t *const rtc = (volatile rtc_t *)RTC_BASE_ADDR;
|
||||
|
||||
struct tm rtc_date_time;
|
||||
|
||||
void rtc_timer_set_mode(rtc_timer_mode_t timer_mode)
|
||||
{
|
||||
rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
|
||||
|
||||
switch (timer_mode)
|
||||
{
|
||||
case RTC_TIMER_PAUSE:
|
||||
register_ctrl.read_enable = 0;
|
||||
register_ctrl.write_enable = 0;
|
||||
break;
|
||||
case RTC_TIMER_RUNNING:
|
||||
register_ctrl.read_enable = 1;
|
||||
register_ctrl.write_enable = 0;
|
||||
break;
|
||||
case RTC_TIMER_SETTING:
|
||||
register_ctrl.read_enable = 0;
|
||||
register_ctrl.write_enable = 1;
|
||||
break;
|
||||
default:
|
||||
register_ctrl.read_enable = 0;
|
||||
register_ctrl.write_enable = 0;
|
||||
break;
|
||||
}
|
||||
rtc->register_ctrl = register_ctrl;
|
||||
}
|
||||
|
||||
rtc_timer_mode_t rtc_timer_get_mode(void)
|
||||
{
|
||||
rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
|
||||
rtc_timer_mode_t timer_mode = RTC_TIMER_PAUSE;
|
||||
|
||||
if ((!register_ctrl.read_enable) && (!register_ctrl.write_enable))
|
||||
{
|
||||
/* RTC_TIMER_PAUSE */
|
||||
timer_mode = RTC_TIMER_PAUSE;
|
||||
}
|
||||
else if ((register_ctrl.read_enable) && (!register_ctrl.write_enable))
|
||||
{
|
||||
/* RTC_TIMER_RUNNING */
|
||||
timer_mode = RTC_TIMER_RUNNING;
|
||||
}
|
||||
else if ((!register_ctrl.read_enable) && (register_ctrl.write_enable)) {
|
||||
/* RTC_TIMER_SETTING */
|
||||
timer_mode = RTC_TIMER_SETTING;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something is error, reset timer mode */
|
||||
rtc_timer_set_mode(timer_mode);
|
||||
}
|
||||
|
||||
return timer_mode;
|
||||
}
|
||||
|
||||
static inline int rtc_in_range(int value, int min, int max)
|
||||
{
|
||||
return ((value >= min) && (value <= max));
|
||||
}
|
||||
|
||||
int rtc_timer_set_tm(const struct tm *tm)
|
||||
{
|
||||
rtc_date_t timer_date;
|
||||
rtc_time_t timer_time;
|
||||
rtc_extended_t timer_extended;
|
||||
|
||||
if (tm)
|
||||
{
|
||||
/*
|
||||
* Range of tm->tm_sec could be [0,61]
|
||||
*
|
||||
* Range of tm->tm_sec allows for a positive leap second. Two
|
||||
* leap seconds in the same minute are not allowed (the C90
|
||||
* range 0..61 was a defect)
|
||||
*/
|
||||
if (rtc_in_range(tm->tm_sec, 0, 59))
|
||||
timer_time.second = tm->tm_sec;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_min could be [0,59] */
|
||||
if (rtc_in_range(tm->tm_min, 0, 59))
|
||||
timer_time.minute = tm->tm_min;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_hour could be [0, 23] */
|
||||
if (rtc_in_range(tm->tm_hour, 0, 23))
|
||||
timer_time.hour = tm->tm_hour;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_mday could be [1, 31] */
|
||||
if (rtc_in_range(tm->tm_mday, 1, 31))
|
||||
timer_date.day = tm->tm_mday;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Range of tm->tm_mon could be [0, 11]
|
||||
* But in this RTC, date.month should be [1, 12]
|
||||
*/
|
||||
if (rtc_in_range(tm->tm_mon, 0, 11))
|
||||
timer_date.month = tm->tm_mon + 1;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Range of tm->tm_year is the years since 1900
|
||||
* But in this RTC, year is split into year and century
|
||||
* In this RTC, century range is [0,31], year range is [0,99]
|
||||
*/
|
||||
int human_year = tm->tm_year + 1900;
|
||||
int rtc_year = human_year % 100;
|
||||
int rtc_century = human_year / 100;
|
||||
|
||||
if (rtc_in_range(rtc_year, 0, 99) &&
|
||||
rtc_in_range(rtc_century, 0, 31))
|
||||
{
|
||||
timer_date.year = rtc_year;
|
||||
timer_extended.century = rtc_century;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_wday could be [0, 6] */
|
||||
if (rtc_in_range(tm->tm_wday, 0, 6))
|
||||
timer_date.week = tm->tm_wday;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Set RTC mode to timer setting mode */
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
/* Write value to RTC */
|
||||
rtc->date = timer_date;
|
||||
rtc->time = timer_time;
|
||||
rtc->extended = timer_extended;
|
||||
/* Get CPU current freq */
|
||||
unsigned long freq = SysctlClockGetFreq(SYSCTL_CLOCK_CPU);
|
||||
/* Set threshold to 1/26000000 s */
|
||||
freq = freq / 26000000;
|
||||
/* Get current CPU cycle */
|
||||
unsigned long start_cycle = read_cycle();
|
||||
/* Wait for 1/26000000 s to sync data */
|
||||
while (read_cycle() - start_cycle < freq)
|
||||
continue;
|
||||
/* Set RTC mode to timer running mode */
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_timer_set_alarm_tm(const struct tm *tm)
|
||||
{
|
||||
rtc_alarm_date_t alarm_date;
|
||||
rtc_alarm_time_t alarm_time;
|
||||
|
||||
if (tm) {
|
||||
/*
|
||||
* Range of tm->tm_sec could be [0,61]
|
||||
*
|
||||
* Range of tm->tm_sec allows for a positive leap second. Two
|
||||
* leap seconds in the same minute are not allowed (the C90
|
||||
* range 0..61 was a defect)
|
||||
*/
|
||||
if (rtc_in_range(tm->tm_sec, 0, 59))
|
||||
alarm_time.second = tm->tm_sec;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_min could be [0,59] */
|
||||
if (rtc_in_range(tm->tm_min, 0, 59))
|
||||
alarm_time.minute = tm->tm_min;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_hour could be [0, 23] */
|
||||
if (rtc_in_range(tm->tm_hour, 0, 23))
|
||||
alarm_time.hour = tm->tm_hour;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_mday could be [1, 31] */
|
||||
if (rtc_in_range(tm->tm_mday, 1, 31))
|
||||
alarm_date.day = tm->tm_mday;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Range of tm->tm_mon could be [0, 11]
|
||||
* But in this RTC, date.month should be [1, 12]
|
||||
*/
|
||||
if (rtc_in_range(tm->tm_mon, 0, 11))
|
||||
alarm_date.month = tm->tm_mon + 1;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Range of tm->tm_year is the years since 1900
|
||||
* But in this RTC, year is split into year and century
|
||||
* In this RTC, century range is [0,31], year range is [0,99]
|
||||
*/
|
||||
int human_year = tm->tm_year + 1900;
|
||||
int rtc_year = human_year % 100;
|
||||
int rtc_century = human_year / 100;
|
||||
|
||||
if (rtc_in_range(rtc_year, 0, 99) &&
|
||||
rtc_in_range(rtc_century, 0, 31))
|
||||
{
|
||||
alarm_date.year = rtc_year;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
/* Range of tm->tm_wday could be [0, 6] */
|
||||
if (rtc_in_range(tm->tm_wday, 0, 6))
|
||||
alarm_date.week = tm->tm_wday;
|
||||
else
|
||||
return -1;
|
||||
|
||||
/* Write value to RTC */
|
||||
rtc->alarm_date = alarm_date;
|
||||
rtc->alarm_time = alarm_time;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtc_year_is_leap(int year)
|
||||
{
|
||||
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
|
||||
}
|
||||
|
||||
static int rtc_get_yday(int year, int month, int day)
|
||||
{
|
||||
static const int days[2][13] =
|
||||
{
|
||||
{0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
|
||||
{0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
|
||||
};
|
||||
int leap = rtc_year_is_leap(year);
|
||||
|
||||
return days[leap][month] + day;
|
||||
}
|
||||
|
||||
static int rtc_get_wday(int year, int month, int day)
|
||||
{
|
||||
/* Magic method to get weekday */
|
||||
int weekday = (day += month < 3 ? year-- : year - 2, 23 * month / 9 + day + 4 + year / 4 - year / 100 + year / 400) % 7;
|
||||
return weekday;
|
||||
}
|
||||
|
||||
struct tm *rtc_timer_get_tm(void)
|
||||
{
|
||||
if (rtc_timer_get_mode() != RTC_TIMER_RUNNING)
|
||||
return NULL;
|
||||
|
||||
rtc_date_t timer_date = rtc->date;
|
||||
rtc_time_t timer_time = rtc->time;
|
||||
rtc_extended_t timer_extended = rtc->extended;
|
||||
|
||||
struct tm *tm = &rtc_date_time;
|
||||
|
||||
tm->tm_sec = timer_time.second % 60;
|
||||
tm->tm_min = timer_time.minute % 60;
|
||||
tm->tm_hour = timer_time.hour % 24;
|
||||
tm->tm_mday = (timer_date.day - 1) % 31 + 1;
|
||||
tm->tm_mon = (timer_date.month - 1)% 12;
|
||||
tm->tm_year = (timer_date.year % 100) + (timer_extended.century * 100) - 1900;
|
||||
tm->tm_wday = timer_date.week;
|
||||
tm->tm_yday = rtc_get_yday(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
tm->tm_isdst = -1;
|
||||
|
||||
return tm;
|
||||
}
|
||||
|
||||
struct tm *rtc_timer_get_alarm_tm(void)
|
||||
{
|
||||
if (rtc_timer_get_mode() != RTC_TIMER_RUNNING)
|
||||
return NULL;
|
||||
|
||||
rtc_alarm_date_t alarm_date = rtc->alarm_date;
|
||||
rtc_alarm_time_t alarm_time = rtc->alarm_time;
|
||||
rtc_extended_t timer_extended = rtc->extended;
|
||||
|
||||
struct tm *tm = &rtc_date_time;
|
||||
|
||||
tm->tm_sec = alarm_time.second % 60;
|
||||
tm->tm_min = alarm_time.minute % 60;
|
||||
tm->tm_hour = alarm_time.hour % 24;
|
||||
tm->tm_mday = alarm_date.day % 31;
|
||||
tm->tm_mon = (alarm_date.month % 12) - 1;
|
||||
/* Alarm and Timer use same timer_extended.century */
|
||||
tm->tm_year = (alarm_date.year % 100) + (timer_extended.century * 100) - 1900;
|
||||
tm->tm_wday = alarm_date.week;
|
||||
tm->tm_yday = rtc_get_yday(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
tm->tm_isdst = -1;
|
||||
|
||||
return tm;
|
||||
}
|
||||
|
||||
int rtc_timer_set(int year, int month, int day, int hour, int minute, int second)
|
||||
{
|
||||
struct tm date_time =
|
||||
{
|
||||
.tm_sec = second,
|
||||
.tm_min = minute,
|
||||
.tm_hour = hour,
|
||||
.tm_mday = day,
|
||||
.tm_mon = month - 1,
|
||||
.tm_year = year - 1900,
|
||||
.tm_wday = rtc_get_wday(year, month, day),
|
||||
.tm_yday = rtc_get_yday(year, month, day),
|
||||
.tm_isdst = -1,
|
||||
};
|
||||
return rtc_timer_set_tm(&date_time);
|
||||
}
|
||||
|
||||
int rtc_timer_get(int *year, int *month, int *day, int *hour, int *minute, int *second)
|
||||
{
|
||||
struct tm *tm = rtc_timer_get_tm();
|
||||
|
||||
if (tm)
|
||||
{
|
||||
if (year)
|
||||
*year = tm->tm_year + 1900;
|
||||
if (month)
|
||||
*month = tm->tm_mon + 1;
|
||||
if (day)
|
||||
*day = tm->tm_mday;
|
||||
if (hour)
|
||||
*hour = tm->tm_hour;
|
||||
if (minute)
|
||||
*minute = tm->tm_min;
|
||||
if (second)
|
||||
*second = tm->tm_sec;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_timer_set_alarm(int year, int month, int day, int hour, int minute, int second)
|
||||
{
|
||||
struct tm date_time = {
|
||||
.tm_sec = second,
|
||||
.tm_min = minute,
|
||||
.tm_hour = hour,
|
||||
.tm_mday = day,
|
||||
.tm_mon = month - 1,
|
||||
.tm_year = year - 1900,
|
||||
.tm_wday = rtc_get_wday(year, month, day),
|
||||
.tm_yday = rtc_get_yday(year, month, day),
|
||||
.tm_isdst = -1,
|
||||
};
|
||||
|
||||
return rtc_timer_set_alarm_tm(&date_time);
|
||||
}
|
||||
|
||||
int rtc_timer_get_alarm(int *year, int *month, int *day, int *hour, int *minute, int *second)
|
||||
{
|
||||
struct tm *tm = rtc_timer_get_alarm_tm();
|
||||
|
||||
if (tm) {
|
||||
if (year)
|
||||
*year = tm->tm_year + 1900;
|
||||
if (month)
|
||||
*month = tm->tm_mon + 1;
|
||||
if (day)
|
||||
*day = tm->tm_mday;
|
||||
if (hour)
|
||||
*hour = tm->tm_hour;
|
||||
if (minute)
|
||||
*minute = tm->tm_min;
|
||||
if (second)
|
||||
*second = tm->tm_sec;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_timer_set_clock_frequency(unsigned int frequency)
|
||||
{
|
||||
|
||||
rtc_initial_count_t initial_count;
|
||||
|
||||
initial_count.count = frequency;
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
rtc->initial_count = initial_count;
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int rtc_timer_get_clock_frequency(void)
|
||||
{
|
||||
return rtc->initial_count.count;
|
||||
}
|
||||
|
||||
int rtc_timer_set_clock_count_value(unsigned int count)
|
||||
{
|
||||
|
||||
rtc_current_count_t current_count;
|
||||
|
||||
current_count.count = count;
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
rtc->current_count = current_count;
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int rtc_timer_get_clock_count_value(void)
|
||||
{
|
||||
return rtc->current_count.count;
|
||||
}
|
||||
|
||||
int rtc_tick_interrupt_set(int enable)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
interrupt_ctrl.tick_enable = enable;
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
rtc->interrupt_ctrl = interrupt_ctrl;
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_tick_interrupt_get(void)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
return interrupt_ctrl.tick_enable;
|
||||
}
|
||||
|
||||
int rtc_tick_interrupt_mode_set(rtc_tick_interrupt_mode_t mode)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
interrupt_ctrl.tick_int_mode = mode;
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
rtc->interrupt_ctrl = interrupt_ctrl;
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtc_tick_interrupt_mode_t rtc_tick_interrupt_mode_get(void)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
return interrupt_ctrl.tick_int_mode;
|
||||
}
|
||||
|
||||
int rtc_alarm_interrupt_set(int enable)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
interrupt_ctrl.alarm_enable = enable;
|
||||
rtc->interrupt_ctrl = interrupt_ctrl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_alarm_interrupt_get(void)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
return interrupt_ctrl.alarm_enable;
|
||||
}
|
||||
|
||||
int rtc_alarm_interrupt_mask_set(rtc_mask_t mask)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
interrupt_ctrl.alarm_compare_mask = *(uint8_t *)&mask;
|
||||
rtc->interrupt_ctrl = interrupt_ctrl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtc_mask_t rtc_alarm_interrupt_mask_get(void)
|
||||
{
|
||||
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
|
||||
|
||||
uint8_t compare_mask = interrupt_ctrl.alarm_compare_mask;
|
||||
|
||||
return *(rtc_mask_t *)&compare_mask;
|
||||
}
|
||||
|
||||
int rtc_protect_set(int enable)
|
||||
{
|
||||
rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
|
||||
|
||||
rtc_mask_t mask =
|
||||
{
|
||||
.second = 1,
|
||||
/* Second mask */
|
||||
.minute = 1,
|
||||
/* Minute mask */
|
||||
.hour = 1,
|
||||
/* Hour mask */
|
||||
.week = 1,
|
||||
/* Week mask */
|
||||
.day = 1,
|
||||
/* Day mask */
|
||||
.month = 1,
|
||||
/* Month mask */
|
||||
.year = 1,
|
||||
};
|
||||
|
||||
rtc_mask_t unmask =
|
||||
{
|
||||
.second = 0,
|
||||
/* Second mask */
|
||||
.minute = 0,
|
||||
/* Minute mask */
|
||||
.hour = 0,
|
||||
/* Hour mask */
|
||||
.week = 0,
|
||||
/* Week mask */
|
||||
.day = 0,
|
||||
/* Day mask */
|
||||
.month = 0,
|
||||
/* Month mask */
|
||||
.year = 0,
|
||||
};
|
||||
|
||||
if (enable)
|
||||
{
|
||||
/* Turn RTC in protect mode, no one can write time */
|
||||
register_ctrl.TimerMask = *(uint8_t *)&unmask;
|
||||
register_ctrl.alarm_mask = *(uint8_t *)&unmask;
|
||||
register_ctrl.initial_count_mask = 0;
|
||||
register_ctrl.interrupt_register_mask = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Turn RTC in unprotect mode, everyone can write time */
|
||||
register_ctrl.TimerMask = *(uint8_t *)&mask;
|
||||
register_ctrl.alarm_mask = *(uint8_t *)&mask;
|
||||
register_ctrl.initial_count_mask = 1;
|
||||
register_ctrl.interrupt_register_mask = 1;
|
||||
}
|
||||
rtc_timer_set_mode(RTC_TIMER_SETTING);
|
||||
rtc->register_ctrl = register_ctrl;
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtc_init(void)
|
||||
{
|
||||
/* Reset RTC */
|
||||
sysctl_reset(SYSCTL_RESET_RTC);
|
||||
/* Enable RTC */
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_RTC);
|
||||
/* Unprotect RTC */
|
||||
rtc_protect_set(0);
|
||||
/* Set RTC clock frequency */
|
||||
rtc_timer_set_clock_frequency(
|
||||
SysctlClockGetFreq(SYSCTL_CLOCK_IN0)
|
||||
);
|
||||
rtc_timer_set_clock_count_value(1);
|
||||
|
||||
/* Set RTC mode to timer running mode */
|
||||
rtc_timer_set_mode(RTC_TIMER_RUNNING);
|
||||
return 0;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
config BSP_USING_SPI1
|
||||
bool "Using spi1 "
|
||||
default y
|
||||
|
||||
|
||||
if BSP_USING_SPI1
|
||||
config SPI_BUS_NAME_1
|
||||
string "spi bus 1 name"
|
||||
default "spi1"
|
||||
config SPI_1_DRV_NAME
|
||||
string "spi bus 1 driver name"
|
||||
default "spi1_drv"
|
||||
config BSP_SPI1_CLK_PIN
|
||||
int "spi1 clk pin number"
|
||||
default 9
|
||||
config BSP_SPI1_D0_PIN
|
||||
int "spi1 MOSI d0 pin number"
|
||||
default 11
|
||||
config BSP_SPI1_D1_PIN
|
||||
int "spi1 MISO d1 pin number"
|
||||
default 10
|
||||
menuconfig BSP_SPI1_USING_SS0
|
||||
bool "SPI1 Enable SS0"
|
||||
default y
|
||||
if BSP_SPI1_USING_SS0
|
||||
config SPI_1_DEVICE_NAME_0
|
||||
string "spi bus 1 device 0 name"
|
||||
default "spi1_dev0"
|
||||
config BSP_SPI1_SS0_PIN
|
||||
int "spi1 ss0 pin number"
|
||||
default 12
|
||||
endif
|
||||
endif
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
SRC_FILES := connect_spi.c hardware_spi.c
|
||||
|
||||
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -1,474 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-03-18 ZYH first version
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_spi.c
|
||||
* @brief support xidatong-riscv64-board spi function and register to bus framework
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-07-25
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: connect_spi.c
|
||||
Description: support xidatong-riscv64-board spi configure and spi bus register function
|
||||
Others: take RT-Thread v4.0.2/bsp/k210/driver/drv_spi.c for references
|
||||
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
|
||||
History:
|
||||
1. Date: 2022-07-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. support xidatong-riscv64-board spi configure, write and read
|
||||
2. support xidatong-riscv64-board spi bus device and driver register
|
||||
*************************************************/
|
||||
|
||||
#include <dmac.h>
|
||||
#include <sysctl.h>
|
||||
#include <gpiohs.h>
|
||||
#include <string.h>
|
||||
#include "connect_spi.h"
|
||||
#include "hardware_spi.h"
|
||||
|
||||
#include <drv_io_config.h>
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef BSP_SPI1_USING_SS0
|
||||
#define SPI_DEVICE_SLAVE_ID_0 0
|
||||
#endif
|
||||
|
||||
#ifdef BSP_SPI1_USING_SS1
|
||||
#define SPI_DEVICE_SLAVE_ID_1 1
|
||||
#endif
|
||||
|
||||
#ifdef BSP_SPI1_USING_SS2
|
||||
#define SPI_DEVICE_SLAVE_ID_2 2
|
||||
#endif
|
||||
|
||||
#ifdef BSP_SPI1_USING_SS3
|
||||
#define SPI_DEVICE_SLAVE_ID_3 3
|
||||
#endif
|
||||
|
||||
static volatile spi_t *const spi_instance[4] =
|
||||
{
|
||||
(volatile spi_t *)SPI0_BASE_ADDR,
|
||||
(volatile spi_t *)SPI1_BASE_ADDR,
|
||||
(volatile spi_t *)SPI_SLAVE_BASE_ADDR,
|
||||
(volatile spi_t *)SPI3_BASE_ADDR
|
||||
};
|
||||
|
||||
void __spi_set_tmod(uint8_t spi_num, uint32_t tmod)
|
||||
{
|
||||
CHECK(spi_num < SPI_DEVICE_MAX);
|
||||
volatile spi_t *spi_handle = spi[spi_num];
|
||||
uint8_t tmod_offset = 0;
|
||||
switch (spi_num)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
tmod_offset = 8;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
tmod_offset = 10;
|
||||
break;
|
||||
}
|
||||
set_bit(&spi_handle->ctrlr0, 3 << tmod_offset, tmod << tmod_offset);
|
||||
}
|
||||
|
||||
/*Init the spi sdk intetface */
|
||||
static uint32 SpiSdkInit(struct SpiDriver *spi_drv)
|
||||
{
|
||||
NULL_PARAM_CHECK(spi_drv);
|
||||
uint8 cs_gpio_pin, cs_select_id;
|
||||
uint32 max_frequency;
|
||||
|
||||
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data);
|
||||
|
||||
cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
|
||||
cs_select_id = dev_param->spi_slave_param->spi_cs_select_id;
|
||||
|
||||
gpiohs_set_drive_mode(cs_select_id, GPIO_DM_OUTPUT);//Set the cs pin as output
|
||||
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH);//set the cs gpio high
|
||||
|
||||
spi_init(dev_param->spi_dma_param->spi_master_id,
|
||||
dev_param->spi_master_param->spi_work_mode & SPI_MODE_3,
|
||||
dev_param->spi_master_param->spi_frame_format,
|
||||
dev_param->spi_master_param->spi_data_bit_width,
|
||||
dev_param->spi_master_param->spi_data_endian);
|
||||
|
||||
max_frequency = (dev_param->spi_master_param->spi_maxfrequency < SPI_MAX_CLOCK) ? dev_param->spi_master_param->spi_maxfrequency : SPI_MAX_CLOCK;
|
||||
|
||||
uint32 real_freq = spi_set_clk_rate(dev_param->spi_dma_param->spi_master_id, max_frequency);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 SpiSdkCfg(struct SpiDriver *spi_drv, struct SpiMasterParam *spi_param)
|
||||
{
|
||||
NULL_PARAM_CHECK(spi_drv);
|
||||
NULL_PARAM_CHECK(spi_param);
|
||||
|
||||
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data);
|
||||
|
||||
dev_param->spi_master_param = spi_param;
|
||||
dev_param->spi_master_param->spi_work_mode = dev_param->spi_master_param->spi_work_mode & SPI_MODE_MASK;
|
||||
dev_param->spi_master_param->spi_frame_format = SPI_FF_STANDARD;
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
/*Configure the spi device param, make sure struct (configure_info->private_data) = (SpiMasterParam)*/
|
||||
static uint32 SpiDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
|
||||
{
|
||||
NULL_PARAM_CHECK(drv);
|
||||
NULL_PARAM_CHECK(configure_info);
|
||||
|
||||
x_err_t ret = EOK;
|
||||
struct SpiDriver *spi_drv = (struct SpiDriver *)drv;
|
||||
struct SpiMasterParam *spi_param;
|
||||
|
||||
switch (configure_info->configure_cmd)
|
||||
{
|
||||
case OPE_INT:
|
||||
ret = SpiSdkInit(spi_drv);
|
||||
break;
|
||||
case OPE_CFG:
|
||||
spi_param = (struct SpiMasterParam *)configure_info->private_data;
|
||||
ret = SpiSdkCfg(spi_drv, spi_param);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32 SpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg)
|
||||
{
|
||||
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data);
|
||||
|
||||
uint8 device_id = dev_param->spi_slave_param->spi_slave_id;
|
||||
uint8 device_master_id = dev_param->spi_dma_param->spi_master_id;
|
||||
uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
|
||||
|
||||
while (NONE != spi_datacfg) {
|
||||
uint32_t * tx_buff = NONE;
|
||||
int i;
|
||||
x_ubase dummy = 0xFFFFFFFFU;
|
||||
|
||||
__spi_set_tmod(device_master_id, SPI_TMOD_TRANS_RECV);
|
||||
|
||||
if (spi_datacfg->spi_chip_select) {
|
||||
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_LOW);
|
||||
}
|
||||
|
||||
if (spi_datacfg->length) {
|
||||
spi_instance[device_master_id]->dmacr = 0x3;
|
||||
spi_instance[device_master_id]->ssienr = 0x01;
|
||||
|
||||
sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_txchannel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + device_master_id * 2);
|
||||
sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_rxchannel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + device_master_id* 2);
|
||||
|
||||
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), &dummy, DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
|
||||
|
||||
if (!spi_datacfg->tx_buff) {
|
||||
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_txchannel, &dummy, (void *)(&spi_instance[device_master_id]->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
|
||||
} else {
|
||||
tx_buff = x_malloc(spi_datacfg->length * 4);
|
||||
if (!tx_buff) {
|
||||
goto transfer_done;
|
||||
}
|
||||
|
||||
for (i = 0; i < spi_datacfg->length; i++) {
|
||||
tx_buff[i] = ((uint8_t *)spi_datacfg->tx_buff)[i];
|
||||
}
|
||||
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_txchannel, tx_buff, (void *)(&spi_instance[device_master_id]->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
|
||||
}
|
||||
|
||||
spi_instance[device_master_id]->ser = 1U << dev_param->spi_slave_param->spi_cs_select_id;
|
||||
dmac_wait_done(dev_param->spi_dma_param->spi_dmac_txchannel);
|
||||
dmac_wait_done(dev_param->spi_dma_param->spi_dmac_rxchannel);
|
||||
spi_instance[device_master_id]->ser = 0x00;
|
||||
spi_instance[device_master_id]->ssienr = 0x00;
|
||||
|
||||
transfer_done:
|
||||
if (tx_buff) {
|
||||
x_free(tx_buff);
|
||||
}
|
||||
}
|
||||
|
||||
if (spi_datacfg->spi_cs_release) {
|
||||
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH);
|
||||
}
|
||||
|
||||
spi_datacfg = spi_datacfg->next;
|
||||
}
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 SpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg)
|
||||
{
|
||||
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data);
|
||||
|
||||
uint32 spi_read_length = 0;
|
||||
uint8 device_id = dev_param->spi_slave_param->spi_slave_id;
|
||||
uint8 device_master_id = dev_param->spi_dma_param->spi_master_id;
|
||||
uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
|
||||
|
||||
while (NONE != spi_datacfg) {
|
||||
uint32_t * rx_buff = NONE;
|
||||
int i;
|
||||
x_ubase dummy = 0xFFFFFFFFU;
|
||||
|
||||
__spi_set_tmod(device_master_id, SPI_TMOD_TRANS_RECV);
|
||||
|
||||
if (spi_datacfg->spi_chip_select) {
|
||||
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_LOW);
|
||||
}
|
||||
if (spi_datacfg->length) {
|
||||
spi_instance[device_master_id]->dmacr = 0x3;
|
||||
spi_instance[device_master_id]->ssienr = 0x01;
|
||||
|
||||
sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_txchannel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + device_master_id * 2);
|
||||
sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_rxchannel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + device_master_id* 2);
|
||||
|
||||
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_txchannel, &dummy, (void *)(&spi_instance[device_master_id]->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
|
||||
|
||||
if (!spi_datacfg->rx_buff) {
|
||||
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), &dummy, DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
|
||||
} else {
|
||||
rx_buff = x_calloc(spi_datacfg->length * 4, 1);
|
||||
if (!rx_buff) {
|
||||
goto transfer_done;
|
||||
}
|
||||
|
||||
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
|
||||
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
|
||||
}
|
||||
|
||||
spi_instance[device_master_id]->ser = 1U << dev_param->spi_slave_param->spi_cs_select_id;
|
||||
dmac_wait_done(dev_param->spi_dma_param->spi_dmac_txchannel);
|
||||
dmac_wait_done(dev_param->spi_dma_param->spi_dmac_rxchannel);
|
||||
spi_instance[device_master_id]->ser = 0x00;
|
||||
spi_instance[device_master_id]->ssienr = 0x00;
|
||||
|
||||
if (spi_datacfg->rx_buff) {
|
||||
for (i = 0; i < spi_datacfg->length; i++) {
|
||||
((uint8_t *)spi_datacfg->rx_buff)[i] = (uint8_t)rx_buff[i];
|
||||
}
|
||||
}
|
||||
|
||||
transfer_done:
|
||||
if (rx_buff) {
|
||||
x_free(rx_buff);
|
||||
}
|
||||
}
|
||||
|
||||
if (spi_datacfg->spi_cs_release) {
|
||||
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH);
|
||||
}
|
||||
|
||||
spi_read_length += spi_datacfg->length;
|
||||
spi_datacfg = spi_datacfg->next;
|
||||
}
|
||||
|
||||
return spi_read_length;
|
||||
}
|
||||
|
||||
/*manage the spi device operations*/
|
||||
static const struct SpiDevDone spi_dev_done =
|
||||
{
|
||||
.dev_open = NONE,
|
||||
.dev_close = NONE,
|
||||
.dev_write = SpiWriteData,
|
||||
.dev_read = SpiReadData,
|
||||
};
|
||||
|
||||
static int BoardSpiBusInit(struct SpiBus *spi_bus, struct SpiDriver *spi_driver)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
/*Init the spi bus */
|
||||
ret = SpiBusInit(spi_bus, SPI_BUS_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiBusInit error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*Init the spi driver*/
|
||||
ret = SpiDriverInit(spi_driver, SPI_1_DRV_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDriverInit error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*Attach the spi driver to the spi bus*/
|
||||
ret = SpiDriverAttachToBus(SPI_1_DRV_NAME, SPI_BUS_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDriverAttachToBus error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Attach the spi device to the spi bus*/
|
||||
static int BoardSpiDevBend(struct SpiDmaParam *spi_initparam)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
#ifdef BSP_SPI1_USING_SS0
|
||||
static struct SpiHardwareDevice spi_device0;
|
||||
memset(&spi_device0, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
static struct SpiSlaveParam spi_slaveparam0;
|
||||
memset(&spi_slaveparam0, 0, sizeof(struct SpiSlaveParam));
|
||||
|
||||
spi_slaveparam0.spi_slave_id = SPI_DEVICE_SLAVE_ID_0;
|
||||
spi_slaveparam0.spi_cs_gpio_pin = SPI1_CS0_PIN;
|
||||
spi_slaveparam0.spi_cs_select_id = SPI_CHIP_SELECT_0;
|
||||
|
||||
spi_device0.spi_param.spi_dma_param = spi_initparam;
|
||||
spi_device0.spi_param.spi_slave_param = &spi_slaveparam0;
|
||||
|
||||
spi_device0.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
ret = SpiDeviceRegister(&spi_device0, (void *)(&spi_device0.spi_param), SPI_1_DEVICE_NAME_0);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_0, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_0, SPI_BUS_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_0, ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_SPI1_USING_SS1
|
||||
static struct SpiHardwareDevice spi_device1;
|
||||
memset(&spi_device1, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
static struct SpiSlaveParam spi_slaveparam1;
|
||||
memset(&spi_slaveparam1, 0, sizeof(struct SpiSlaveParam));
|
||||
|
||||
spi_slaveparam1.spi_slave_id = SPI_DEVICE_SLAVE_ID_1;
|
||||
spi_slaveparam1.spi_cs_gpio_pin = SPI1_CS1_PIN;
|
||||
spi_slaveparam1.spi_cs_select_id = SPI_CHIP_SELECT_1;
|
||||
|
||||
spi_device1.spi_param.spi_dma_param = spi_initparam;
|
||||
spi_device1.spi_param.spi_slave_param = &spi_slaveparam1;
|
||||
|
||||
spi_device1.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
ret = SpiDeviceRegister(&spi_device1, (void *)(&spi_device1.spi_param), SPI_1_DEVICE_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_1, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_1, SPI_BUS_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_1, ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_SPI1_USING_SS2
|
||||
static struct SpiHardwareDevice spi_device2;
|
||||
memset(&spi_device2, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_2] = SPI_DEVICE_SLAVE_ID_2;
|
||||
spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_2] = SPI1_CS2_PIN;
|
||||
spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_2] = SPI_CHIP_SELECT_2;
|
||||
|
||||
spi_device2.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
ret = SpiDeviceRegister(&spi_device2, (void *)(&spi_device2.spi_param), SPI_1_DEVICE_NAME_2);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_2, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_2, SPI_BUS_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_2, ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_SPI1_USING_SS3
|
||||
static struct SpiHardwareDevice spi_device3;
|
||||
memset(&spi_device3, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_3] = SPI_DEVICE_SLAVE_ID_3;
|
||||
spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_3] = SPI1_CS3_PIN;
|
||||
spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_3] = SPI_CHIP_SELECT_3;
|
||||
|
||||
spi_device3.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
ret = SpiDeviceRegister(&spi_device3, (void *)(&spi_device3.spi_param), SPI_1_DEVICE_NAME_3);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_3, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_3, SPI_BUS_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_3, ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*RISC-V 64 BOARD SPI INIT*/
|
||||
int HwSpiInit(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
static struct SpiDmaParam spi_initparam;
|
||||
memset(&spi_initparam, 0, sizeof(struct SpiDmaParam));
|
||||
|
||||
#ifdef BSP_USING_SPI1
|
||||
|
||||
static struct SpiBus spi_bus;
|
||||
memset(&spi_bus, 0, sizeof(struct SpiBus));
|
||||
|
||||
static struct SpiDriver spi_driver;
|
||||
memset(&spi_driver, 0, sizeof(struct SpiDriver));
|
||||
|
||||
spi_initparam.spi_master_id = SPI_DEVICE_1;
|
||||
spi_initparam.spi_dmac_txchannel = DMAC_CHANNEL1;
|
||||
spi_initparam.spi_dmac_rxchannel = DMAC_CHANNEL2;
|
||||
|
||||
spi_driver.configure = &(SpiDrvConfigure);
|
||||
|
||||
ret = BoardSpiBusInit(&spi_bus, &spi_driver);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_Init error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = BoardSpiDevBend(&spi_initparam);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_Init error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,19 +0,0 @@
|
|||
if BSP_USING_HWTIMER
|
||||
config HWTIMER_BUS_NAME_1
|
||||
string "hwtimer bus name"
|
||||
default "hwtim1"
|
||||
|
||||
menuconfig ENABLE_TIM1
|
||||
bool "enable TIM1"
|
||||
default y
|
||||
|
||||
if ENABLE_TIM1
|
||||
config HWTIMER_1_DEVICE_NAME_1
|
||||
string "TIM1 dev name"
|
||||
default "hwtim1_dev1"
|
||||
|
||||
config HWTIMER_DRIVER_NAME_1
|
||||
string "TIM1 drv name"
|
||||
default "hwtim1_drv"
|
||||
endif
|
||||
endif
|
|
@ -1,3 +0,0 @@
|
|||
SRC_FILES := hardware_hwtimer.c connect_hwtimer.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_hwtimer.c
|
||||
* @brief support xidatong-riscv64-board hwtimer function and register to bus framework
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-07-25
|
||||
*/
|
||||
|
||||
#include <board.h>
|
||||
#include <xizi.h>
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
#include <plic.h>
|
||||
#include <sysctl.h>
|
||||
#include <fpioa.h>
|
||||
#include "connect_hwtimer.h"
|
||||
|
||||
static struct HwtimerCallBackInfo *ptim2_cb_info = NULL;
|
||||
|
||||
int timer_callback(void *ctx)
|
||||
{
|
||||
if (ptim2_cb_info) {
|
||||
if (ptim2_cb_info->timeout_callback) {
|
||||
ptim2_cb_info->timeout_callback(ptim2_cb_info->param);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 HwtimerOpen(void *dev)
|
||||
{
|
||||
struct HwtimerHardwareDevice *hwtimer_dev = dev;
|
||||
|
||||
ptim2_cb_info = &hwtimer_dev->hwtimer_param.cb_info;
|
||||
|
||||
plic_init();
|
||||
sysctl_enable_irq();
|
||||
timer_init(TIMER_DEVICE_1);
|
||||
|
||||
size_t real_time = timer_set_interval(TIMER_DEVICE_1, TIMER_CHANNEL_1, hwtimer_dev->hwtimer_param.period_millisecond *1000);
|
||||
KPrintf("timer_set_interval -- real_time : %ld\n", real_time);
|
||||
timer_irq_register(TIMER_DEVICE_1, TIMER_CHANNEL_1, !hwtimer_dev->hwtimer_param.repeat, 1, timer_callback, NULL);
|
||||
|
||||
timer_set_enable(TIMER_DEVICE_1, TIMER_CHANNEL_1, 1);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
uint32 HwtimerClose(void *dev)
|
||||
{
|
||||
timer_set_enable(TIMER_DEVICE_1, TIMER_CHANNEL_1, 0);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
/*manage the hwtimer device operations*/
|
||||
static const struct HwtimerDevDone dev_done =
|
||||
{
|
||||
.open = HwtimerOpen,
|
||||
.close = HwtimerClose,
|
||||
.write = NONE,
|
||||
.read = NONE,
|
||||
};
|
||||
|
||||
/*Init hwtimer bus*/
|
||||
static int BoardHwtimerBusInit(struct HwtimerBus *hwtimer_bus, struct HwtimerDriver *hwtimer_driver)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
/*Init the hwtimer bus */
|
||||
ret = HwtimerBusInit(hwtimer_bus, HWTIMER_BUS_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("board_hwtimer_init HwtimerBusInit error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*Init the hwtimer driver*/
|
||||
hwtimer_driver->configure = NONE;
|
||||
ret = HwtimerDriverInit(hwtimer_driver, HWTIMER_DRIVER_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("board_hwtimer_init HwtimerDriverInit error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*Attach the hwtimer driver to the hwtimer bus*/
|
||||
ret = HwtimerDriverAttachToBus(HWTIMER_DRIVER_NAME_1, HWTIMER_BUS_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("board_hwtimer_init USEDriverAttachToBus error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Attach the hwtimer device to the hwtimer bus*/
|
||||
static int BoardHwtimerDevBend(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
static struct HwtimerHardwareDevice hwtimer_device_0;
|
||||
memset(&hwtimer_device_0, 0, sizeof(struct HwtimerHardwareDevice));
|
||||
|
||||
hwtimer_device_0.dev_done = &dev_done;
|
||||
|
||||
ret = HwtimerDeviceRegister(&hwtimer_device_0, NONE, HWTIMER_1_DEVICE_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("board_hwtimer_init HWTIMERDeviceInit device %s error %d\n", HWTIMER_1_DEVICE_NAME_1, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = HwtimerDeviceAttachToBus(HWTIMER_1_DEVICE_NAME_1, HWTIMER_BUS_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("board_hwtimer_init HwtimerDeviceAttachToBus device %s error %d\n", HWTIMER_1_DEVICE_NAME_1, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*K210 BOARD HWTIMER INIT*/
|
||||
int HwTimerInit(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
static struct HwtimerBus hwtimer_bus;
|
||||
memset(&hwtimer_bus, 0, sizeof(struct HwtimerBus));
|
||||
|
||||
static struct HwtimerDriver hwtimer_driver;
|
||||
memset(&hwtimer_driver, 0, sizeof(struct HwtimerDriver));
|
||||
|
||||
|
||||
ret = BoardHwtimerBusInit(&hwtimer_bus, &hwtimer_driver);
|
||||
if (EOK != ret) {
|
||||
KPrintf("board_hwtimer_Init error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = BoardHwtimerDevBend();
|
||||
if (EOK != ret) {
|
||||
KPrintf("board_hwtimer_Init error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,406 +0,0 @@
|
|||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hardware_hwtimer.c
|
||||
* @brief add from Canaan k210 SDK
|
||||
* https://canaan-creative.com/developer
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-07-25
|
||||
*/
|
||||
|
||||
#include <syslog.h>
|
||||
#include "hardware_hwtimer.h"
|
||||
#include "sysctl.h"
|
||||
#include "stddef.h"
|
||||
#include "utils.h"
|
||||
#include "plic.h"
|
||||
#include "io.h"
|
||||
#include "xs_isr.h"
|
||||
/**
|
||||
* @brief Private definitions for the timer instance
|
||||
*/
|
||||
typedef struct timer_instance
|
||||
{
|
||||
timer_callback_t callback;
|
||||
void *ctx;
|
||||
bool single_shot;
|
||||
} timer_instance_t;
|
||||
|
||||
typedef void(*irq_manager_callback_t)(int irq, void* arg);
|
||||
|
||||
volatile timer_instance_t timer_instance[TIMER_DEVICE_MAX][TIMER_CHANNEL_MAX];
|
||||
|
||||
volatile kendryte_timer_t *const timer[3] =
|
||||
{
|
||||
(volatile kendryte_timer_t *)TIMER0_BASE_ADDR,
|
||||
(volatile kendryte_timer_t *)TIMER1_BASE_ADDR,
|
||||
(volatile kendryte_timer_t *)TIMER2_BASE_ADDR
|
||||
};
|
||||
|
||||
void timer_init(timer_device_number_t timer_number)
|
||||
{
|
||||
for(size_t i = 0; i < TIMER_CHANNEL_MAX; i++)
|
||||
timer_instance[timer_number][i] = (const timer_instance_t) {
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
.single_shot = 0,
|
||||
};
|
||||
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_TIMER0 + timer_number);
|
||||
}
|
||||
|
||||
void timer_set_clock_div(timer_device_number_t timer_number, uint32_t div)
|
||||
{
|
||||
sysctl_clock_set_threshold(timer_number == 0 ? SYSCTL_THRESHOLD_TIMER0 :
|
||||
timer_number == 1 ? SYSCTL_THRESHOLD_TIMER1 :
|
||||
SYSCTL_THRESHOLD_TIMER2, div);
|
||||
}
|
||||
|
||||
void timer_enable(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control |= TIMER_CR_ENABLE;
|
||||
}
|
||||
|
||||
void timer_disable(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control &= (~TIMER_CR_ENABLE);
|
||||
}
|
||||
|
||||
void timer_enable_pwm(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control |= TIMER_CR_PWM_ENABLE;
|
||||
}
|
||||
|
||||
void timer_disable_pwm(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control &= (~TIMER_CR_PWM_ENABLE);
|
||||
}
|
||||
|
||||
void timer_enable_interrupt(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control &= (~TIMER_CR_INTERRUPT_MASK);
|
||||
}
|
||||
|
||||
void timer_disable_interrupt(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control |= TIMER_CR_INTERRUPT_MASK;
|
||||
}
|
||||
|
||||
void timer_set_mode(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t mode)
|
||||
{
|
||||
timer[timer_number]->channel[channel].control &= (~TIMER_CR_MODE_MASK);
|
||||
timer[timer_number]->channel[channel].control |= mode;
|
||||
}
|
||||
|
||||
void timer_set_reload(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t count)
|
||||
{
|
||||
timer[timer_number]->channel[channel].load_count = count;
|
||||
}
|
||||
|
||||
void timer_set_reload2(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t count)
|
||||
{
|
||||
timer[timer_number]->load_count2[channel] = count;
|
||||
}
|
||||
|
||||
uint32_t timer_get_count(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
return timer[timer_number]->channel[channel].current_value;
|
||||
}
|
||||
|
||||
uint32_t timer_get_reload(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
return timer[timer_number]->channel[channel].load_count;
|
||||
}
|
||||
|
||||
uint32_t timer_get_reload2(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
return timer[timer_number]->load_count2[channel];
|
||||
}
|
||||
|
||||
uint32_t timer_get_interrupt_status(timer_device_number_t timer_number)
|
||||
{
|
||||
return timer[timer_number]->intr_stat;
|
||||
}
|
||||
|
||||
uint32_t timer_get_raw_interrupt_status(timer_device_number_t timer_number)
|
||||
{
|
||||
return timer[timer_number]->raw_intr_stat;
|
||||
}
|
||||
|
||||
uint32_t timer_channel_get_interrupt_status(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
return timer[timer_number]->channel[channel].intr_stat;
|
||||
}
|
||||
|
||||
void timer_clear_interrupt(timer_device_number_t timer_number)
|
||||
{
|
||||
timer[timer_number]->eoi = timer[timer_number]->eoi;
|
||||
}
|
||||
|
||||
void timer_channel_clear_interrupt(timer_device_number_t timer_number, timer_channel_number_t channel)
|
||||
{
|
||||
timer[timer_number]->channel[channel].eoi = timer[timer_number]->channel[channel].eoi;
|
||||
}
|
||||
|
||||
void timer_set_enable(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t enable)
|
||||
{
|
||||
if (enable)
|
||||
timer[timer_number]->channel[channel].control = TIMER_CR_USER_MODE | TIMER_CR_ENABLE;
|
||||
else
|
||||
timer[timer_number]->channel[channel].control = TIMER_CR_INTERRUPT_MASK;
|
||||
}
|
||||
|
||||
size_t timer_set_interval(timer_device_number_t timer_number, timer_channel_number_t channel, size_t useconds)
|
||||
{
|
||||
uint32_t clk_freq = SysctlClockGetFreq(SYSCTL_CLOCK_TIMER0 + timer_number);
|
||||
|
||||
double min_step = 1e6 / clk_freq;
|
||||
size_t value = (size_t)(useconds / min_step);
|
||||
configASSERT(value > 0 && value < UINT32_MAX);
|
||||
timer[timer_number]->channel[channel].load_count = (uint32_t)value;
|
||||
return (size_t)(min_step * value);
|
||||
}
|
||||
|
||||
typedef void(*timer_ontick)();
|
||||
timer_ontick time_irq[3][4] = { NULL };
|
||||
|
||||
static int timer_isr(void *parm)
|
||||
{
|
||||
uint32_t timer_number;
|
||||
for (timer_number = 0; timer_number < 3; timer_number++)
|
||||
{
|
||||
if (parm == timer[timer_number])
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t channel = timer[timer_number]->intr_stat;
|
||||
size_t i = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (channel & 1)
|
||||
{
|
||||
if (time_irq[timer_number][i])
|
||||
(time_irq[timer_number][i])();
|
||||
break;
|
||||
}
|
||||
|
||||
channel >>= 1;
|
||||
}
|
||||
|
||||
readl(&timer[timer_number]->eoi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void timer_set_irq(timer_device_number_t timer_number, timer_channel_number_t channel, void(*func)(), uint32_t priority)
|
||||
{
|
||||
time_irq[timer_number][channel] = func;
|
||||
if (channel < 2)
|
||||
{
|
||||
plic_set_priority(IRQN_TIMER0A_INTERRUPT + timer_number * 2, priority);
|
||||
plic_irq_register(IRQN_TIMER0A_INTERRUPT + timer_number * 2, timer_isr, (void *)timer[timer_number]);
|
||||
plic_irq_enable(IRQN_TIMER0A_INTERRUPT + timer_number * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
plic_set_priority(IRQN_TIMER0B_INTERRUPT + timer_number * 2, priority);
|
||||
plic_irq_register(IRQN_TIMER0B_INTERRUPT + timer_number * 2, timer_isr, (void *)timer[timer_number]);
|
||||
plic_irq_enable(IRQN_TIMER0B_INTERRUPT + timer_number * 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the timer irqn by device and channel object
|
||||
*
|
||||
* @note Internal function, not public
|
||||
* @param device The device
|
||||
* @param channel The channel
|
||||
* @return plic_irq_t IRQ number
|
||||
*/
|
||||
static plic_irq_t get_timer_irqn_by_device_and_channel(timer_device_number_t device, timer_channel_number_t channel)
|
||||
{
|
||||
if (device < TIMER_DEVICE_MAX && channel < TIMER_CHANNEL_MAX) {
|
||||
/*
|
||||
* Select timer interrupt part
|
||||
* Hierarchy of Timer interrupt to PLIC
|
||||
* +---------+ +-----------+
|
||||
* | 0+----+ | |
|
||||
* | | +--+0A |
|
||||
* | 1+----+ | |
|
||||
* | TIMER0 | | |
|
||||
* | 2+----+ | |
|
||||
* | | +--+0B |
|
||||
* | 3+----+ | |
|
||||
* +---------+ | |
|
||||
* | |
|
||||
* +---------+ | |
|
||||
* | 0+----+ | |
|
||||
* | | +--+1A |
|
||||
* | 1+----+ | |
|
||||
* | TIMER1 | | PLIC |
|
||||
* | 2+----+ | |
|
||||
* | | +--+1B |
|
||||
* | 3+----+ | |
|
||||
* +---------+ | |
|
||||
* | |
|
||||
* +---------+ | |
|
||||
* | 0+----+ | |
|
||||
* | | +--+2A |
|
||||
* | 1+----+ | |
|
||||
* | TIMER2 | | |
|
||||
* | 2+----+ | |
|
||||
* | | +--+2B |
|
||||
* | 3+----+ | |
|
||||
* +---------+ +-----------+
|
||||
*
|
||||
*/
|
||||
if (channel < 2) {
|
||||
/* It is part A interrupt, offset + 0 */
|
||||
return IRQN_TIMER0A_INTERRUPT + device * 2;
|
||||
}
|
||||
else {
|
||||
/* It is part B interrupt, offset + 1 */
|
||||
return IRQN_TIMER0B_INTERRUPT + device * 2;
|
||||
}
|
||||
}
|
||||
return IRQN_NO_INTERRUPT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process user callback function
|
||||
*
|
||||
* @note Internal function, not public
|
||||
* @param device The timer device
|
||||
* @param ctx The context
|
||||
* @return int The callback result
|
||||
*/
|
||||
static int timer_interrupt_handler(timer_device_number_t device, void *ctx)
|
||||
{
|
||||
uint32_t channel_int_stat = timer[device]->intr_stat;
|
||||
|
||||
for (size_t i = 0; i < TIMER_CHANNEL_MAX; i++)
|
||||
{
|
||||
/* Check every bit for interrupt status */
|
||||
if (channel_int_stat & 1)
|
||||
{
|
||||
if (timer_instance[device][i].callback) {
|
||||
/* Process user callback function */
|
||||
timer_instance[device][i].callback(timer_instance[device][i].ctx);
|
||||
/* Check if this timer is a single shot timer */
|
||||
if (timer_instance[device][i].single_shot) {
|
||||
/* Single shot timer, disable it */
|
||||
timer_set_enable(device, i, 0);
|
||||
}
|
||||
}
|
||||
/* Clear timer interrupt flag for specific channel */
|
||||
readl(&timer[device]->channel[i].eoi);
|
||||
}
|
||||
channel_int_stat >>= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
* Don't read timer[device]->eoi here, or you will lost some interrupt
|
||||
* readl(&timer[device]->eoi);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function bus for timer interrupt
|
||||
*
|
||||
* @note Internal function, not public
|
||||
* @param ctx The context
|
||||
* @return int The callback result
|
||||
*/
|
||||
static void timer0_interrupt_callback(int irq, void *ctx)
|
||||
{
|
||||
timer_interrupt_handler(TIMER_DEVICE_0, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function bus for timer interrupt
|
||||
*
|
||||
* @note Internal function, not public
|
||||
* @param ctx The context
|
||||
* @return int The callback result
|
||||
*/
|
||||
static void timer1_interrupt_callback(int irq, void *ctx)
|
||||
{
|
||||
timer_interrupt_handler(TIMER_DEVICE_1, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function bus for timer interrupt
|
||||
*
|
||||
* @note Internal function, not public
|
||||
* @param ctx The context
|
||||
* @return int The callback result
|
||||
*/
|
||||
static void timer2_interrupt_callback(int irq, void *ctx)
|
||||
{
|
||||
timer_interrupt_handler(TIMER_DEVICE_2, ctx);
|
||||
}
|
||||
|
||||
int timer_irq_register(timer_device_number_t device, timer_channel_number_t channel, int is_single_shot, uint32_t priority, timer_callback_t callback, void *ctx)
|
||||
{
|
||||
if (device < TIMER_DEVICE_MAX && channel < TIMER_CHANNEL_MAX) {
|
||||
plic_irq_t irq_number = get_timer_irqn_by_device_and_channel(device, channel);
|
||||
irq_manager_callback_t plic_irq_callback[TIMER_DEVICE_MAX] = {
|
||||
timer0_interrupt_callback,
|
||||
timer1_interrupt_callback,
|
||||
timer2_interrupt_callback,
|
||||
};
|
||||
|
||||
timer_instance[device][channel] = (const timer_instance_t) {
|
||||
.callback = callback,
|
||||
.ctx = ctx,
|
||||
.single_shot = is_single_shot,
|
||||
};
|
||||
|
||||
// plic_set_priority(irq_number, priority);
|
||||
// plic_irq_register(irq_number, plic_irq_callback[device], (void *)&timer_instance[device]);
|
||||
// plic_irq_enable(irq_number);
|
||||
|
||||
isrManager.done->registerIrq(irq_number, plic_irq_callback[device], NULL);
|
||||
isrManager.done->enableIrq(irq_number);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int timer_irq_unregister(timer_device_number_t device, timer_channel_number_t channel)
|
||||
{
|
||||
if (device < TIMER_DEVICE_MAX && channel < TIMER_CHANNEL_MAX) {
|
||||
timer_instance[device][channel] = (const timer_instance_t) {
|
||||
.callback = NULL,
|
||||
.ctx = NULL,
|
||||
.single_shot = 0,
|
||||
};
|
||||
|
||||
/* Combine 0 and 1 to A interrupt, 2 and 3 to B interrupt */
|
||||
if ((!(timer_instance[device][TIMER_CHANNEL_0].callback ||
|
||||
timer_instance[device][TIMER_CHANNEL_1].callback)) ||
|
||||
(!(timer_instance[device][TIMER_CHANNEL_2].callback ||
|
||||
timer_instance[device][TIMER_CHANNEL_3].callback))) {
|
||||
plic_irq_t irq_number = get_timer_irqn_by_device_and_channel(device, channel);
|
||||
plic_irq_unregister(irq_number);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
menuconfig BSP_USING_WDT0
|
||||
bool "Using watchdog 0 "
|
||||
default n
|
||||
if BSP_USING_WDT0
|
||||
config WDT_BUS_NAME_0
|
||||
string "watchdog bus 0 name"
|
||||
default "wdt0"
|
||||
|
||||
config WDT_DRIVER_NAME_0
|
||||
string "watchdog driver 0 name"
|
||||
default "wdt0_drv"
|
||||
|
||||
config WDT_0_DEVICE_NAME_0
|
||||
string "watchdog device 0 name"
|
||||
default "wdt0_dev0"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_WDT1
|
||||
bool "Using watchdog 1 "
|
||||
default n
|
||||
if BSP_USING_WDT1
|
||||
config WDT_BUS_NAME_1
|
||||
string "watchdog bus 1 name"
|
||||
default "wdt1"
|
||||
|
||||
config WDT_DRIVER_NAME_1
|
||||
string "watchdog driver 1 name"
|
||||
default "wdt1_drv"
|
||||
|
||||
config WDT_1_DEVICE_NAME_1
|
||||
string "watchdog device 1 name"
|
||||
default "wdt1_dev1"
|
||||
endif
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
SRC_FILES := wdt.c connect_wdt.c
|
||||
|
||||
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_wdt.c
|
||||
* @brief support kd233-board watchdog function and register to bus framework
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-07-25
|
||||
*/
|
||||
|
||||
#include "wdt.h"
|
||||
#include "connect_wdt.h"
|
||||
|
||||
static uint32 WdtOpen(void *dev)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
|
||||
wdt_device_number_t id;
|
||||
struct WdtHardwareDevice *wdt = (struct WdtHardwareDevice *)dev;
|
||||
id = *(wdt_device_number_t *)wdt->private_data;
|
||||
|
||||
wdt_init(id, 4095, NONE, NONE);
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 WdtConfigure(void *drv, struct BusConfigureInfo *args)
|
||||
{
|
||||
NULL_PARAM_CHECK(drv);
|
||||
NULL_PARAM_CHECK(args);
|
||||
|
||||
struct WdtDriver *wdt = (struct WdtDriver *)drv;
|
||||
wdt_device_number_t id = *(wdt_device_number_t *)wdt->private_data;
|
||||
|
||||
switch (args->configure_cmd)
|
||||
{
|
||||
case OPER_WDT_SET_TIMEOUT:
|
||||
if (wdt_init(id, (uint64_t)*(int *)args->private_data, NONE, NONE) == 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
break;
|
||||
case OPER_WDT_KEEPALIVE:
|
||||
wdt_feed(id);
|
||||
break;
|
||||
default:
|
||||
return ERROR;
|
||||
}
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static const struct WdtDevDone dev_done =
|
||||
{
|
||||
WdtOpen,
|
||||
NONE,
|
||||
NONE,
|
||||
NONE,
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: Watchdog function
|
||||
* @return success: EOK, failure: other
|
||||
*/
|
||||
int StartWatchdog(void)
|
||||
{
|
||||
//add feed watchdog task function
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
int HwWdtInit(void)
|
||||
{
|
||||
wdt_device_number_t id;
|
||||
|
||||
x_err_t ret = EOK;
|
||||
|
||||
#ifdef BSP_USING_WDT0
|
||||
{
|
||||
static struct WdtBus wdt0;
|
||||
|
||||
ret = WdtBusInit(&wdt0, WDT_BUS_NAME_0);
|
||||
if(ret != EOK)
|
||||
{
|
||||
KPrintf("Watchdog bus init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
static struct WdtDriver drv0;
|
||||
drv0.configure = WdtConfigure;
|
||||
id = WDT_DEVICE_0;
|
||||
drv0.private_data = &id;
|
||||
|
||||
ret = WdtDriverInit(&drv0, WDT_DRIVER_NAME_0);
|
||||
if(ret != EOK)
|
||||
{
|
||||
KPrintf("Watchdog driver init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
ret = WdtDriverAttachToBus(WDT_DRIVER_NAME_0, WDT_BUS_NAME_0);
|
||||
if(ret != EOK)
|
||||
{
|
||||
KPrintf("Watchdog driver attach error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
static struct WdtHardwareDevice dev0;
|
||||
dev0.dev_done = &dev_done;
|
||||
dev0.private_data = &id;
|
||||
|
||||
ret = WdtDeviceRegister(&dev0, WDT_0_DEVICE_NAME_0);
|
||||
if(ret != EOK)
|
||||
{
|
||||
KPrintf("Watchdog device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
ret = WdtDeviceAttachToBus(WDT_0_DEVICE_NAME_0, WDT_BUS_NAME_0);
|
||||
if(ret != EOK)
|
||||
{
|
||||
KPrintf("Watchdog device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_WDT1
|
||||
{
|
||||
static struct WdtBus wdt1;
|
||||
|
||||
ret = WdtBusInit(&wdt1, WDT_BUS_NAME_1);
|
||||
if(ret != EOK)
|
||||
{
|
||||
KPrintf("Watchdog bus init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
static struct WdtDriver drv1;
|
||||
drv1.configure = WdtConfigure;
|
||||
id = WDT_DEVICE_1;
|
||||
drv1.private_data = &id;
|
||||
|
||||
ret = WdtDriverInit(&drv1, WDT_DRIVER_NAME_1);
|
||||
if(ret != EOK)
|
||||
{
|
||||
KPrintf("Watchdog driver init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
ret = WdtDriverAttachToBus(WDT_DRIVER_NAME_1, WDT_BUS_NAME_1);
|
||||
if(ret != EOK)
|
||||
{
|
||||
KPrintf("Watchdog driver attach error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
static struct WdtHardwareDevice dev1;
|
||||
dev1.dev_done = &dev_done;
|
||||
dev1.private_data = &id;
|
||||
|
||||
ret = WdtDeviceRegister(&dev1, WDT_1_DEVICE_NAME_1);
|
||||
if(ret != EOK)
|
||||
{
|
||||
KPrintf("Watchdog device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
ret = WdtDeviceAttachToBus(WDT_1_DEVICE_NAME_1, WDT_BUS_NAME_1);
|
||||
if(ret != EOK)
|
||||
{
|
||||
KPrintf("Watchdog device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file wdt.c
|
||||
* @brief add from Canaan k210 SDK
|
||||
* https://canaan-creative.com/developer
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-07-25
|
||||
*/
|
||||
|
||||
#include "wdt.h"
|
||||
#include "platform.h"
|
||||
#include "stddef.h"
|
||||
#include "utils.h"
|
||||
#include "sysctl.h"
|
||||
#include "plic.h"
|
||||
#include "math.h"
|
||||
|
||||
volatile wdt_t *const wdt[2] =
|
||||
{
|
||||
(volatile wdt_t *)WDT0_BASE_ADDR,
|
||||
(volatile wdt_t *)WDT1_BASE_ADDR
|
||||
};
|
||||
|
||||
static void wdt_enable(wdt_device_number_t id)
|
||||
{
|
||||
wdt[id]->crr = WDT_CRR_MASK;
|
||||
wdt[id]->cr |= WDT_CR_ENABLE;
|
||||
}
|
||||
|
||||
static void wdt_disable(wdt_device_number_t id)
|
||||
{
|
||||
wdt[id]->crr = WDT_CRR_MASK;
|
||||
wdt[id]->cr &= (~WDT_CR_ENABLE);
|
||||
}
|
||||
|
||||
static void wdt_set_timeout(wdt_device_number_t id, uint8_t timeout)
|
||||
{
|
||||
wdt[id]->torr = WDT_TORR_TOP(timeout);
|
||||
}
|
||||
|
||||
static void wdt_response_mode(wdt_device_number_t id, uint8_t mode)
|
||||
{
|
||||
wdt[id]->cr &= (~WDT_CR_RMOD_MASK);
|
||||
wdt[id]->cr |= mode;
|
||||
}
|
||||
|
||||
static uint64_t wdt_get_pclk(wdt_device_number_t id)
|
||||
{
|
||||
return id ? SysctlClockGetFreq(SYSCTL_CLOCK_WDT1) : SysctlClockGetFreq(SYSCTL_CLOCK_WDT0);
|
||||
}
|
||||
|
||||
static uint8_t wdt_get_top(wdt_device_number_t id, uint64_t timeout_ms)
|
||||
{
|
||||
uint64_t wdt_clk = wdt_get_pclk(id);
|
||||
uint64_t ret = (timeout_ms * wdt_clk / 1000) >> 16;
|
||||
if (ret)
|
||||
ret = (uint32_t)log2(ret);
|
||||
if (ret > 0xf)
|
||||
ret = 0xf;
|
||||
return (uint8_t)ret;
|
||||
}
|
||||
|
||||
void wdt_feed(wdt_device_number_t id)
|
||||
{
|
||||
wdt[id]->crr = WDT_CRR_MASK;
|
||||
}
|
||||
|
||||
void wdt_clear_interrupt(wdt_device_number_t id)
|
||||
{
|
||||
wdt[id]->eoi = wdt[id]->eoi;
|
||||
}
|
||||
|
||||
void wdt_start(wdt_device_number_t id, uint64_t time_out_ms, plic_irq_callback_t on_irq)
|
||||
{
|
||||
sysctl_reset(id ? SYSCTL_RESET_WDT1 : SYSCTL_RESET_WDT0);
|
||||
sysctl_clock_set_threshold(id ? SYSCTL_THRESHOLD_WDT1 : SYSCTL_THRESHOLD_WDT0, 0);
|
||||
sysctl_clock_enable(id ? SYSCTL_CLOCK_WDT1 : SYSCTL_CLOCK_WDT0);
|
||||
|
||||
plic_set_priority(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT, 1);
|
||||
plic_irq_enable(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT);
|
||||
plic_irq_register(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT, on_irq, NULL);
|
||||
|
||||
wdt_response_mode(id, WDT_CR_RMOD_INTERRUPT);
|
||||
uint8_t m_top = wdt_get_top(id, time_out_ms);
|
||||
wdt_set_timeout(id, m_top);
|
||||
wdt_enable(id);
|
||||
}
|
||||
|
||||
uint32_t wdt_init(wdt_device_number_t id, uint64_t time_out_ms, plic_irq_callback_t on_irq, void *ctx)
|
||||
{
|
||||
sysctl_reset(id ? SYSCTL_RESET_WDT1 : SYSCTL_RESET_WDT0);
|
||||
sysctl_clock_set_threshold(id ? SYSCTL_THRESHOLD_WDT1 : SYSCTL_THRESHOLD_WDT0, 0);
|
||||
sysctl_clock_enable(id ? SYSCTL_CLOCK_WDT1 : SYSCTL_CLOCK_WDT0);
|
||||
|
||||
plic_set_priority(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT, 1);
|
||||
plic_irq_enable(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT);
|
||||
plic_irq_register(id ? IRQN_WDT1_INTERRUPT : IRQN_WDT0_INTERRUPT, on_irq, ctx);
|
||||
|
||||
wdt_response_mode(id, WDT_CR_RMOD_INTERRUPT);
|
||||
uint8_t m_top = wdt_get_top(id, time_out_ms);
|
||||
wdt_set_timeout(id, m_top);
|
||||
wdt_enable(id);
|
||||
return (1UL << (m_top + 16 + 1)) * 1000UL / wdt_get_pclk(id);
|
||||
}
|
||||
|
||||
void wdt_stop(wdt_device_number_t id)
|
||||
{
|
||||
wdt_disable(id);
|
||||
}
|
||||
|
Loading…
Reference in New Issue