soft-SPI driver for edu-riscv64,which mainly for SDcard. edu-riscv64 examples including filesystem/RS485/gpio/loraE220/RTC from Wu_zheng

it is OK
This commit is contained in:
xuedongliang 2022-11-16 15:22:09 +08:00
commit 992b8f62ab
47 changed files with 3938 additions and 39 deletions

View File

@ -26,6 +26,131 @@ menu "test app"
endif
endif
menuconfig USER_TEST_FS
bool "Config test fs with sd or usb"
default n
if USER_TEST_FS
if ADD_XIZI_FETURES
config FPATH
string "Set test file path"
default "/test_file"
endif
endif
menuconfig USER_TEST_GPIO
select BSP_USING_GPIO
select RESOURCES_PIN
select BSP_USING_LED
select BSP_USING_KEY
bool "Config test gpio with led and key"
default n
if USER_TEST_GPIO
if ADD_XIZI_FETURES
config GPIO_DEV_DRIVER
string "Set gpio dev path"
default "/dev/pin_dev"
endif
endif
menuconfig USER_TEST_LORA
select BSP_USING_UART
select BSP_USING_GPIO
select RESOURCES_PIN
select BSP_USING_UART2
select BSP_USING_LORA
bool "Config test uart(loraE220)"
default n
if USER_TEST_LORA
if ADD_XIZI_FETURES
config LORA_UART_DEV_DRIVER
string "Set uart dev path"
default "/dev/uart2_dev2"
config LORA_PIN_DEV_DRIVER
string "Set pin dev path"
default "/dev/pin_dev"
endif
endif
menuconfig USER_TEST_RS485
select BSP_USING_UART
select BSP_USING_GPIO
select RESOURCES_PIN
select BSP_USING_UART1
bool "Config test uart(RS485)"
default n
if USER_TEST_RS485
if ADD_XIZI_FETURES
config RS485_UART_DEV_DRIVER
string "Set uart dev path"
default "/dev/uart1_dev1"
config RS485_PIN_DEV_DRIVER
string "Set pin dev path"
default "/dev/pin_dev"
endif
endif
menuconfig USER_TEST_RTC
select BSP_USING_RTC
bool "Config test rtc"
default n
if USER_TEST_RTC
if ADD_XIZI_FETURES
config RTC_DEV_DRIVER
string "Set rtc dev path"
default "/dev/rtc_dev"
endif
endif
menuconfig USER_TEST_HWTIMER
select BSP_USING_HWTIMER
select BSP_USING_GPIO
bool "Config test hwtimer"
default n
if USER_TEST_HWTIMER
if ADD_XIZI_FETURES
config HWTIMER_PIN_DEV_DRIVER
string "Set pin dev path"
default "/dev/pin_dev"
endif
endif
menuconfig USER_TEST_WDT
select BSP_USING_WDT0
bool "Config test watchdog"
default n
if USER_TEST_WDT
if ADD_XIZI_FETURES
config WDT0_DEV_DRIVER
string "Set wdt dev path"
default "/dev/wdt0_dev0"
endif
endif
menuconfig USER_TEST_LCD_EDU
select BSP_USING_LCD
bool "Config test lcd in PrivOpen"
default n
if USER_TEST_LCD_EDU
if ADD_XIZI_FETURES
config EDU_LCD_DEV_DRIVER
string "Set lcd dev path"
default "/dev/lcd_dev"
endif
endif
menuconfig USER_TEST_I2C
select BSP_USING_I2C
bool "Config test i2c"
default n
if USER_TEST_I2C
if ADD_XIZI_FETURES
config I2C_DEV_DRIVER
string "Set i2c dev path"
default "/dev/i2c1_dev0"
endif
endif
config USER_TEST_SEMC
bool "Config test semc sdram"
default n
@ -33,5 +158,7 @@ menu "test app"
config USER_TEST_LCD
bool "Config test lcd device"
default n
endif
endmenu

View File

@ -25,6 +25,10 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
SRC_FILES += test_dac.c
endif
ifeq ($(CONFIG_USER_TEST_FS),y)
SRC_FILES += test_fs.c
endif
ifeq ($(CONFIG_USER_TEST_SEMC),y)
SRC_FILES += test_extsram.c
endif
@ -33,5 +37,37 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
SRC_FILES +=
endif
ifeq ($(CONFIG_USER_TEST_I2C),y)
SRC_FILES += test_i2c.c
endif
ifeq ($(CONFIG_USER_TEST_GPIO),y)
SRC_FILES += test_gpio.c
endif
ifeq ($(CONFIG_USER_TEST_LORA),y)
SRC_FILES += test_loraE220.c
endif
ifeq ($(CONFIG_USER_TEST_RTC),y)
SRC_FILES += test_rtc.c
endif
ifeq ($(CONFIG_USER_TEST_RS485),y)
SRC_FILES += test_rs485.c
endif
ifeq ($(CONFIG_USER_TEST_HWTIMER),y)
SRC_FILES += test_hwtimer.c
endif
ifeq ($(CONFIG_USER_TEST_LCD_EDU),y)
SRC_FILES += test_lcd_edu.c
endif
ifeq ($(CONFIG_USER_TEST_WDT),y)
SRC_FILES += test_wdt.c
endif
include $(KERNEL_ROOT)/compiler.mk
endif

View File

@ -56,4 +56,4 @@ void TestAdc(void)
return;
}
PRIV_SHELL_CMD_FUNCTION(TestAdc, a adc test sample, PRIV_SHELL_CMD_MAIN_ATTR);
PRIV_SHELL_CMD_FUNCTION(TestAdc, a adc test sample, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,62 @@
#include <stdio.h>
#include <string.h>
#include <transform.h>
#define MAX_READ_LENGTH 1000
// sd card here is loaded as "/"
void TestFs(void)
{
//open the file in sdcard
int fd = open(FPATH,O_RDWR|O_CREAT);
if(fd<0){
printf("fs fd open error:%d\n",fd);
return;
}
char filewords[MAX_READ_LENGTH];
memset(filewords,0,MAX_READ_LENGTH);
const char *input_words = "these words are going to write in fs\n";
//read and write then close file
int err_flag = read(fd,filewords,MAX_READ_LENGTH);
if(err_flag<0){
printf("read failed,error:%d\n",err_flag);
return;
}
printf("read data is \n%s\n",filewords);
err_flag = write(fd,input_words,strlen(input_words));
if(err_flag<0){
printf("write failed,error:%d\n",err_flag);
return;
}
err_flag = close(fd);
if(err_flag<0){
printf("close failed,error %d\n",err_flag);
return ;
}
//re-open the file and re-read the file
fd = open(FPATH,O_RDWR);
if(fd<0){
printf("fs fd open error:%d\n",fd);
return;
}
err_flag = read(fd,filewords,MAX_READ_LENGTH);
if(err_flag<0){
printf("read failed,error:%d\n",err_flag);
return;
}
printf("read data is \n%s\n",filewords);
err_flag = close(fd);
if(err_flag<0){
printf("close failed,error:%d\n",err_flag);
return;
}
return;
}
PRIV_SHELL_CMD_FUNCTION(TestFs, a sd or usb filesystem test sample, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,73 @@
#include <stdio.h>
#include <string.h>
#include <transform.h>
#define BSP_LED_PIN 29
#define BSP_KEY_PIN 31
#define NULL_PARAMETER 0
void TestGpio(void)
{
int pin_fd = PrivOpen(GPIO_DEV_DRIVER, O_RDWR);
if(pin_fd<0){
printf("open pin fd error:%d\n",pin_fd);
return;
}
//config led pin in board
struct PinParam parameter;
parameter.cmd = GPIO_CONFIG_MODE;
parameter.pin = BSP_LED_PIN;
parameter.mode = GPIO_CFG_OUTPUT;
struct PrivIoctlCfg ioctl_cfg;
ioctl_cfg.ioctl_driver_type = PIN_TYPE;
ioctl_cfg.args = (void *)&parameter;
if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) {
printf("ioctl pin fd error %d\n", pin_fd);
PrivClose(pin_fd);
return;
}
//config key pin in board
parameter.pin = BSP_KEY_PIN;
parameter.mode = GPIO_CFG_INPUT;
if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) {
printf("ioctl pin fd error %d\n", pin_fd);
PrivClose(pin_fd);
return;
}
struct PinStat pin_led;
struct PinStat pin_key;
pin_led.pin = BSP_LED_PIN;
pin_key.pin = BSP_KEY_PIN;
//recycle read pin and write pin until key break
while(1){
if(0>PrivRead(pin_fd,&pin_key,NULL_PARAMETER)){
printf("read pin fd error %d\n", pin_fd);
PrivClose(pin_fd);
return;
}
//led on if key pressed,or led off
if(pin_key.val){
pin_led.val = GPIO_HIGH;
}else{
pin_led.val = GPIO_LOW;
}
if(0>PrivWrite(pin_fd,&pin_led,NULL_PARAMETER)){
printf("write pin fd error %d\n", pin_fd);
PrivClose(pin_fd);
return;
}
}
}
PRIV_SHELL_CMD_FUNCTION(TestGpio, a gpio test sample, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,62 @@
#include <stdio.h>
#include <string.h>
#include <transform.h>
#define BSP_LED_PIN 29
#define NULL_PARAMETER 0
static uint16_t pinval=0;
void ledflip(void *parameter)
{
int tmp_fd = *(int*)parameter;
struct PinStat pin_led;
pin_led.pin = BSP_LED_PIN;
pin_led.val = !pinval;
pinval = !pinval;
PrivWrite(tmp_fd,&pin_led,NULL_PARAMETER);
printf("Timer has callback once\n");
}
void TestHwTimer(int argc, char *argv[])
{
x_ticks_t period = 100;//uint:10ms
if(argc>1){
period = (x_ticks_t)atoi(argv[1]);
}
int pin_fd = PrivOpen(HWTIMER_PIN_DEV_DRIVER, O_RDWR);
if(pin_fd<0){
printf("open pin fd error:%d\n",pin_fd);
return;
}
//config led pin in board
struct PinParam parameter;
parameter.cmd = GPIO_CONFIG_MODE;
parameter.pin = BSP_LED_PIN;
parameter.mode = GPIO_CFG_OUTPUT;
struct PrivIoctlCfg ioctl_cfg;
ioctl_cfg.ioctl_driver_type = PIN_TYPE;
ioctl_cfg.args = (void *)&parameter;
if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) {
printf("ioctl pin fd error %d\n", pin_fd);
PrivClose(pin_fd);
return;
}
int32 timer_handle = KCreateTimer("LED on and off by 1s",&ledflip,&pin_fd,period,TIMER_TRIGGER_PERIODIC);
KTimerStartRun(timer_handle);
PrivTaskDelay(10000);
KTimerQuitRun(timer_handle);
KDeleteTimer(timer_handle);
}
PRIV_SHELL_CMD_FUNCTION(TestHwTimer, a timer test sample, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,50 @@
#include <stdio.h>
#include <string.h>
#include <transform.h>
#define I2C_SLAVE_ADDRESS 0x0012U
void TestI2C(void)
{
// config IIC pin(SCL:34.SDA:35) in menuconfig
int iic_fd = PrivOpen(I2C_DEV_DRIVER, O_RDWR);
if (iic_fd < 0)
{
printf("open iic_fd fd error:%d\n", iic_fd);
return;
}
printf("IIC open successful!\n");
// init iic
uint16 iic_address = I2C_SLAVE_ADDRESS;
struct PrivIoctlCfg ioctl_cfg;
ioctl_cfg.ioctl_driver_type = I2C_TYPE;
ioctl_cfg.args = (void *)&iic_address;
if (0 != PrivIoctl(iic_fd, OPE_INT, &ioctl_cfg))
{
printf("ioctl iic fd error %d\n", iic_fd);
PrivClose(iic_fd);
return;
}
printf("IIC configure successful!\n");
// I2C read and write
char tmp_buff[100];
while (1)
{
PrivTaskDelay(1000);
PrivWrite(iic_fd, "Hello World!\n", sizeof("Hello World!\n"));
printf("msg send:%s\n", "Hello World!\n");
PrivTaskDelay(1000);
memset(tmp_buff, 0, sizeof(tmp_buff));
PrivRead(iic_fd, tmp_buff, sizeof(tmp_buff));
printf("msg recv:%s\n", tmp_buff);
}
PrivClose(iic_fd);
return;
}
PRIV_SHELL_CMD_FUNCTION(TestI2C, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,50 @@
#include <stdio.h>
#include <string.h>
#include <transform.h>
#define GRAPHIC_CTRL_RECT_UPDATE 0x00
#define LCD_STRING_TYPE 0
#define LCD_DOT_TYPE 1
#define LCD_FONT_RECT_WIDTH 150
#define LCD_FONT_RECT_HEIGHT 50
#define NULL_PARAMETER 0
void TestLcd(void)
{
int lcd_fd = PrivOpen(EDU_LCD_DEV_DRIVER, O_RDWR);
if (lcd_fd < 0)
{
printf("open lcd fd error:%d\n", lcd_fd);
return;
}
// draw text
LcdWriteParam graph_param;
graph_param.type = LCD_STRING_TYPE;
graph_param.string_info.x_pos = 0;
graph_param.string_info.y_pos = 0;
graph_param.string_info.width = 250;
graph_param.string_info.height = 24;
graph_param.string_info.font_size = 24;
graph_param.string_info.back_color = 0xFFFF;
graph_param.string_info.font_color = 0x0000;
graph_param.string_info.addr = "hello_world!";
PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER);
uint16 color_select = 0xF800;
for (int i = 0; i < 5; i++)
{
graph_param.type = LCD_DOT_TYPE;
graph_param.pixel_info.x_startpos = 0;
graph_param.pixel_info.y_startpos = 50 * i;
graph_param.pixel_info.x_endpos = 320;
graph_param.pixel_info.y_endpos = 50 * i;
graph_param.pixel_info.pixel_color = &color_select;
PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER);
}
PrivClose(lcd_fd);
}
PRIV_SHELL_CMD_FUNCTION(TestLcd, a lcd test sample, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,147 @@
#include <stdio.h>
#include <string.h>
#include <transform.h>
#define NULL_PARAMETER 0
#define E220_CFG_LENGTH
#define GPIOSET(fd, buf, bit) \
{ \
buf.val = bit; \
if (0 > PrivWrite(fd, &buf, NULL_PARAMETER)) \
{ \
printf("write pin fd error %d\n", fd); \
PrivClose(fd); \
return; \
} \
}
#define BSP_E220_M0_PIN 32
#define BSP_E220_M1_PIN 33
void TestLora(int argc, char *argv[])
{
char uart_recvbuff[100];
memset(uart_recvbuff, 0, sizeof(uart_recvbuff));
int pin_fd = PrivOpen(LORA_PIN_DEV_DRIVER, O_RDWR);
if (pin_fd < 0)
{
printf("open pin fd error:%d\n", pin_fd);
return;
}
int uart_fd = PrivOpen(LORA_UART_DEV_DRIVER, O_RDWR);
if (uart_fd < 0)
{
printf("open pin fd error:%d\n", uart_fd);
return;
}
printf("uart and pin fopen success\n");
struct PinStat pin_m0;
struct PinStat pin_m1;
pin_m0.pin = BSP_E220_M0_PIN;
pin_m1.pin = BSP_E220_M1_PIN;
// config led pin in board
struct PrivIoctlCfg ioctl_cfg;
struct PinParam pin_param;
pin_param.cmd = GPIO_CONFIG_MODE;
pin_param.mode = GPIO_CFG_OUTPUT;
pin_param.pin = BSP_E220_M0_PIN;
ioctl_cfg.ioctl_driver_type = PIN_TYPE;
ioctl_cfg.args = &pin_param;
if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg))
{
printf("ioctl pin fd error %d\n", pin_fd);
PrivClose(pin_fd);
return;
}
pin_param.pin = BSP_E220_M1_PIN;
if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg))
{
printf("ioctl pin fd error %d\n", pin_fd);
PrivClose(pin_fd);
return;
}
printf("pin configure success\n");
struct SerialDataCfg uart_cfg;
memset(&uart_cfg, 0, sizeof(struct SerialDataCfg));
// loraE220 support only 9600bps with 8N1 during initializing
uart_cfg.serial_baud_rate = BAUD_RATE_9600;
uart_cfg.serial_data_bits = DATA_BITS_8;
uart_cfg.serial_stop_bits = STOP_BITS_1;
uart_cfg.serial_parity_mode = PARITY_NONE;
uart_cfg.serial_bit_order = BIT_ORDER_LSB;
uart_cfg.serial_invert_mode = NRZ_NORMAL;
uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
uart_cfg.serial_timeout = 1000;
uart_cfg.is_ext_uart = 0;
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
ioctl_cfg.args = (void *)&uart_cfg;
if (0 != PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg))
{
printf("ioctl uart fd error %d\n", uart_fd);
PrivClose(uart_fd);
return;
}
printf("uart configure success\n");
GPIOSET(pin_fd, pin_m0, GPIO_HIGH);
GPIOSET(pin_fd, pin_m1, GPIO_HIGH);
printf("lora configure into sleep(configure) mode\n");
// send configure data, and receive the same length of data
char sendbuff[] = {0xC0, 0x00, 0x05, 0x19, 0x49, 0xE6, 0x00, 0x17}; // config as address 1949 CH17 36.8kps
PrivTaskDelay(2000);
printf("Sending lora configure information(SIZE:%d)\n", sizeof(sendbuff));
PrivWrite(uart_fd, sendbuff, sizeof(sendbuff));
printf("lora configure information send\n");
PrivTaskDelay(2000);
PrivRead(uart_fd, uart_recvbuff, sizeof(sendbuff));
printf("%x %x %x %x", uart_recvbuff[0], uart_recvbuff[1], uart_recvbuff[2], uart_recvbuff[3]);
printf("lora configure success\n");
// error when all bytes are 0xff
if (0xFF == (uart_recvbuff[0] & uart_recvbuff[1] & uart_recvbuff[2]))
{
printf("from lora receive error:%d\n", 0xff);
return;
}
uart_cfg.serial_baud_rate = BAUD_RATE_115200;
if (0 != PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg))
{
printf("ioctl uart fd error %d\n", uart_fd);
PrivClose(uart_fd);
return;
}
// into transparent transmission mode
GPIOSET(pin_fd, pin_m0, GPIO_LOW);
GPIOSET(pin_fd, pin_m1, GPIO_LOW);
// receive and send "Hello World"
while (1)
{
PrivTaskDelay(500);
PrivWrite(uart_fd, "Hello_World!", sizeof("Hello_World!"));
printf("Data Send:\n%s\n", "Hello_World!");
PrivTaskDelay(500);
memset(uart_recvbuff, 0, sizeof(uart_recvbuff));
PrivRead(uart_fd, uart_recvbuff, sizeof(uart_recvbuff));
printf("Receive Data is :\n%s\n", uart_recvbuff);
}
PrivClose(pin_fd);
PrivClose(uart_fd);
}
PRIV_SHELL_CMD_FUNCTION(TestLora, a lora test sample, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,86 @@
#include <stdio.h>
#include <string.h>
#include <transform.h>
#define BSP_485_DIR_PIN 24
void Test485(void)
{
int pin_fd = PrivOpen(RS485_PIN_DEV_DRIVER, O_RDWR);
if (pin_fd < 0)
{
printf("open pin fd error:%d\n", pin_fd);
return;
}
int uart_fd = PrivOpen(RS485_UART_DEV_DRIVER, O_RDWR);
if (uart_fd < 0)
{
printf("open pin fd error:%d\n", uart_fd);
return;
}
printf("uart and pin fopen success\n");
//config led pin in board
struct PinParam pin_parameter;
memset(&pin_parameter, 0, sizeof(struct PinParam));
pin_parameter.cmd = GPIO_CONFIG_MODE;
pin_parameter.pin = BSP_485_DIR_PIN;
pin_parameter.mode = GPIO_CFG_OUTPUT;
struct PrivIoctlCfg ioctl_cfg;
ioctl_cfg.ioctl_driver_type = PIN_TYPE;
ioctl_cfg.args = (void *)&pin_parameter;
if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) {
printf("ioctl pin fd error %d\n", pin_fd);
PrivClose(pin_fd);
return;
}
struct SerialDataCfg uart_cfg;
memset(&uart_cfg, 0, sizeof(struct SerialDataCfg));
uart_cfg.serial_baud_rate = BAUD_RATE_115200;
uart_cfg.serial_data_bits = DATA_BITS_8;
uart_cfg.serial_stop_bits = STOP_BITS_1;
uart_cfg.serial_parity_mode = PARITY_NONE;
uart_cfg.serial_bit_order = BIT_ORDER_LSB;
uart_cfg.serial_invert_mode = NRZ_NORMAL;
uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
uart_cfg.serial_timeout = 1000;
uart_cfg.is_ext_uart = 0;
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
ioctl_cfg.args = (void *)&uart_cfg;
if (0 != PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg))
{
printf("ioctl uart fd error %d\n", uart_fd);
PrivClose(uart_fd);
return;
}
struct PinStat pin_dir;
pin_dir.pin = BSP_485_DIR_PIN;
while (1)
{
pin_dir.val = GPIO_HIGH;
PrivWrite(pin_fd,&pin_dir,0);
PrivWrite(uart_fd,"Hello world!\n",sizeof("Hello world!\n"));
PrivTaskDelay(100);
pin_dir.val = GPIO_LOW;
PrivWrite(pin_fd,&pin_dir,0);
char recv_buff[100];
memset(recv_buff,0,sizeof(recv_buff));
PrivRead(uart_fd,recv_buff,20);
printf("%s",recv_buff);
PrivTaskDelay(100);
}
PrivClose(pin_fd);
PrivClose(uart_fd);
return;
}
PRIV_SHELL_CMD_FUNCTION(Test485, a RS485 test sample, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,38 @@
#include <stdio.h>
#include <string.h>
#include <transform.h>
void TestRTC(int argc,char *argv[])
{
int rtc_fd = PrivOpen(RTC_DEV_DRIVER, O_RDWR);
if(rtc_fd<0){
printf("open rtc fd error:%d\n",rtc_fd);
return;
}
if(argc>1){
int times = atoi(argv[1]);
printf("Time will be printf %d times\n",times);
struct RtcDrvConfigureParam rtc_para;
rtc_para.rtc_operation_cmd = OPER_RTC_SET_TIME;
*(rtc_para.time) = 0;
struct PrivIoctlCfg ioctl_cfg;
ioctl_cfg.ioctl_driver_type = RTC_TYPE;
ioctl_cfg.args = (void *)&rtc_para;
PrivIoctl(rtc_fd,0,&ioctl_cfg);
rtc_para.rtc_operation_cmd = OPER_RTC_GET_TIME;
for(size_t i=0;i<times;i++){
PrivIoctl(rtc_fd,0,&ioctl_cfg);
printf("The time now is %d\n",*(rtc_para.time));
PrivTaskDelay(5000);
}
}
PrivClose(rtc_fd);
return;
}
PRIV_SHELL_CMD_FUNCTION(TestRTC, a rtc test sample, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,45 @@
#include <stdio.h>
#include <string.h>
#include <transform.h>
void TestWDT(int argc, char *agrv[])
{
int wdt_fd = PrivOpen(WDT0_DEV_DRIVER, O_RDWR);
if (wdt_fd < 0)
{
printf("open wdt_fd fd error:%d\n", wdt_fd);
return;
}
printf("hw watchdog open!\n");
// init watchdog
int wdt_time = 1000;
struct PrivIoctlCfg ioctl_cfg;
ioctl_cfg.ioctl_driver_type = WDT_TYPE;
ioctl_cfg.args = (void *)&wdt_time;
if (0 != PrivIoctl(wdt_fd, OPER_WDT_SET_TIMEOUT, &ioctl_cfg))
{
printf("ioctl wdt fd error %d\n", wdt_fd);
PrivClose(wdt_fd);
return;
}
int test_counter = 100;
// wdt feed or not according to argc,if argc!=1 then dog won't be feed
while (test_counter--)
{
if (1 == argc)
{
printf("dog is feed\n");
PrivIoctl(wdt_fd, OPER_WDT_KEEPALIVE, &ioctl_cfg); // feed dog
}
PrivTaskDelay(100);
}
PrivClose(wdt_fd);
return;
}
PRIV_SHELL_CMD_FUNCTION(TestWDT, a wdt test sample, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -169,6 +169,7 @@ int PrivIoctl(int fd, int cmd, void *args)
case LCD_TYPE:
ret = PrivLcdIoctl(fd, cmd, ioctl_cfg->args);
break;
case RTC_TYPE:
case ADC_TYPE:
case DAC_TYPE:
case WDT_TYPE:

View File

@ -149,6 +149,7 @@ enum IoctlDriverType
ADC_TYPE,
DAC_TYPE,
WDT_TYPE,
RTC_TYPE,
DEFAULT_TYPE,
};
@ -193,6 +194,12 @@ typedef struct
uint16_t press;
}TouchDataParam;
struct RtcDrvConfigureParam
{
int rtc_operation_cmd;
time_t *time;
};
#define PRIV_SYSTICK_GET (CurrentTicksGain())
#define PRIV_LCD_DEV "/dev/lcd_dev"
#define MY_DISP_HOR_RES BSP_LCD_Y_MAX

View File

@ -32,16 +32,16 @@ CONFIG_BSP_USING_UART_HS=y
#
# General Purpose UARTs
#
CONFIG_BSP_USING_UART1=y
CONFIG_BSP_UART1_TXD_PIN=20
CONFIG_BSP_UART1_RXD_PIN=21
CONFIG_BSP_USING_UART2=y
CONFIG_BSP_UART2_TXD_PIN=28
CONFIG_BSP_UART2_RXD_PIN=27
CONFIG_BSP_USING_UART3=y
CONFIG_BSP_UART3_TXD_PIN=22
CONFIG_BSP_UART3_RXD_PIN=23
CONFIG___STACKSIZE__=4096
# CONFIG_BSP_USING_UART1=y
# CONFIG_BSP_UART1_TXD_PIN=20
# CONFIG_BSP_UART1_RXD_PIN=21
# CONFIG_BSP_USING_UART2=y
# CONFIG_BSP_UART2_TXD_PIN=28
# CONFIG_BSP_UART2_RXD_PIN=27
# CONFIG_BSP_USING_UART3=y
# CONFIG_BSP_UART3_TXD_PIN=22
# CONFIG_BSP_UART3_RXD_PIN=23
# CONFIG___STACKSIZE__=4096
#
# Hardware feature

View File

@ -44,10 +44,14 @@ Modification:
#include "fpioa.h"
#include "dmac.h"
#include "connect_gpio.h"
#include "connect_soft_spi.h"
#include "connect_rtc.h"
#include "connect_hwtimer.h"
#include "connect_wdt.h"
#if defined(FS_VFS)
#include <iot-vfs.h>
#endif
// #if defined(FS_VFS)
// #include <iot-vfs.h>
// #endif
#define CPU0 (0)
#define CPU1 (1)
@ -60,8 +64,8 @@ extern int HwTouchInit(void);
extern int HwCh376Init(void);
extern int HwLcdInit(void);
extern int HwSpiInit(void);
extern int HwSoftSPIInit(void);
#ifdef FS_CH376
#include <iot-vfs.h>
#ifdef MOUNT_USB
/**
@ -78,23 +82,34 @@ int MountUsb(void)
return 0;
}
#endif
#ifdef MOUNT_SDCARD
#if defined(FS_VFS) && defined (MOUNT_SDCARD)
#include <iot-vfs.h>
#include <sd_spi.h>
extern SpiSdDeviceType SpiSdInit(struct Bus *bus, const char *dev_name, const char *drv_name, const char *sd_name);
/**
* @description: Mount SD card
* @return 0
*/
int MountSDCard(void)
int MountSDCard(void)
{
if (MountFilesystem(SDIO_BUS_NAME,SDIO_DEVICE_NAME ,SDIO_DRIVER_NAME , FSTYPE_CH376, "/") == 0)
KPrintf("sd card mount to '/'\n");
else
KPrintf("sd card mount to '/' failed!\n");
return 0;
struct Bus *spi_bus;
spi_bus = BusFind(SOFT_SPI_BUS_NAME);
if (NONE == SpiSdInit(spi_bus, SOFT_SPI_DEVICE_NAME, SOFT_SPI_DRV_NAME, SPI_SD_NAME)) {
KPrintf("MountSDCard SpiSdInit error!\n");
return -1;
}
if (EOK != MountFilesystem(SOFT_SPI_BUS_NAME, SPI_SD_NAME, SOFT_SPI_DRV_NAME, FSTYPE_FATFS, "/")) {
return -1;
}
KPrintf("SPI SD card fatfs mounted\n");
return 0;
}
#endif
#endif
void InitBss(void)
{
@ -172,6 +187,9 @@ struct InitSequenceDesc _board_init[] =
#ifdef BSP_USING_I2C
{ "hw_i2c", HwI2cInit },
#endif
#ifdef BSP_USING_RTC
{ "hw_rtc", HwRtcInit },
#endif
#ifdef BSP_USING_SPI
{ "hw_spi", HwSpiInit },
#endif
@ -183,10 +201,20 @@ struct InitSequenceDesc _board_init[] =
#endif
#ifdef BSP_USING_TOUCH
{"touch", HwTouchInit },
#endif
#ifdef BSP_USING_SOFT_SPI
{"soft_spi", HwSoftSPIInit },
#endif
#ifdef BSP_USING_HWTIMER
{"hw_timer", HwTimerInit },
#endif
#ifdef BSP_USING_WDT
{"hw_wdt", HwWdtInit },
#endif
{ " NONE ",NONE },
};
void InitBoardHardware(void)
{
int i = 0;

View File

@ -16,6 +16,16 @@ menuconfig BSP_USING_SPI
source "$BSP_DIR/third_party_driver/spi/Kconfig"
endif
menuconfig BSP_USING_SOFT_SPI
bool "Using SOFT_SPI device"
default n
select BSP_USING_SPI
select MOUNT_SDCARD
select FS_VFS
if BSP_USING_SOFT_SPI
source "$BSP_DIR/third_party_driver/soft_spi/Kconfig"
endif
menuconfig BSP_USING_LCD
bool "Using LCD device"
default n
@ -78,3 +88,27 @@ menuconfig BSP_USING_UART
if BSP_USING_UART
source "$BSP_DIR/third_party_driver/uart/Kconfig"
endif
menuconfig BSP_USING_RTC
bool "Using RTC device"
default y
select RESOURCES_RTC
if BSP_USING_RTC
source "$BSP_DIR/third_party_driver/rtc/Kconfig"
endif
menuconfig BSP_USING_HWTIMER
bool "Using TIMER device"
default y
select RESOURCES_HWTIMER
if BSP_USING_HWTIMER
source "$BSP_DIR/third_party_driver/timer/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

View File

@ -40,4 +40,21 @@ ifeq ($(CONFIG_BSP_USING_LCD),y)
SRC_DIR += lcd
endif
ifeq ($(CONFIG_BSP_USING_SOFT_SPI),y)
SRC_DIR += soft_spi
endif
ifeq ($(CONFIG_BSP_USING_RTC),y)
SRC_DIR += rtc
endif
ifeq ($(CONFIG_BSP_USING_HWTIMER),y)
SRC_DIR += timer
endif
ifeq ($(CONFIG_BSP_USING_WDT),y)
SRC_DIR += watchdog
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -75,7 +75,7 @@ static struct io_config
IOCONFIG(BSP_UART3_TXD_PIN, FUNC_UART3_RX),
IOCONFIG(BSP_UART3_RXD_PIN, FUNC_UART3_TX),
#endif
#ifdef BSP_USING_I2C1
#ifdef BSP_USING_I2C
IOCONFIG(BSP_I2C_SDA, FUNC_GPIO3),
IOCONFIG(BSP_I2C_SCL, FUNC_GPIO4),
#endif
@ -95,7 +95,31 @@ static struct io_config
IOCONFIG(BSP_CH438_D4_PIN, HS_GPIO(FPIOA_CH438_D4)),
IOCONFIG(BSP_CH438_D5_PIN, HS_GPIO(FPIOA_CH438_D5)),
IOCONFIG(BSP_CH438_D6_PIN, HS_GPIO(FPIOA_CH438_D6)),
IOCONFIG(BSP_CH438_D7_PIN, HS_GPIO(FPIOA_CH438_D7))
IOCONFIG(BSP_CH438_D7_PIN, HS_GPIO(FPIOA_CH438_D7)),
#endif
#ifdef BSP_USING_SOFT_SPI
IOCONFIG(BSP_SOFT_SPI_SCK_PIN, HS_GPIO(FPIOA_SOFT_SPI_SCK)),
IOCONFIG(BSP_SOFT_SPI_MIOS_PIN, HS_GPIO(FPIOA_SOFT_SPI_MIOS)),
IOCONFIG(BSP_SOFT_SPI_MSOI_PIN, HS_GPIO(FPIOA_SOFT_SPI_MSOI)),
IOCONFIG(BSP_SOFT_SPI_NCS_PIN, HS_GPIO(FPIOA_SOFT_SPI_NCS)),
#endif
#ifdef BSP_USING_LORA
IOCONFIG(BSP_E220_M0_PIN, HS_GPIO(FUNC_GPIOHS10)),
IOCONFIG(BSP_E220_M1_PIN, HS_GPIO(FUNC_GPIOHS11)),
#endif
#ifdef BSP_USING_RS485
IOCONFIG(BSP_485_DIR_PIN,HS_GPIO(FUNC_GPIOHS12));
#endif
#ifdef BSP_USING_LED
IOCONFIG(BSP_LED_PIN,FUNC_GPIO5);
#endif
#ifdef BSP_USING_KEY
IOCONFIG(BSP_KEY_PIN,FUNC_GPIO6);
#endif
};

View File

@ -12,6 +12,6 @@ if BSP_USING_I2C
string "i2c bus 1 driver name"
default "i2c1_drv"
config I2C_1_DEVICE_NAME_0
string "i2c bus 1 device 0 name"
default "i2c1_dev0"
string "i2c bus 1 device 0 name"
default "i2c1_dev0"
endif

View File

@ -0,0 +1,37 @@
/*
* 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.h
* @brief define aiit-riscv64-board hwtimer function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_HWTIMER_H
#define CONNECT_HWTIMER_H
#include <device.h>
#include "hardware_hwtimer.h"
#ifdef __cplusplus
extern "C" {
#endif
int HwTimerInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,36 @@
/*
* 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.h
* @brief define aiit-riscv64-board rtc function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_RTC_H
#define CONNECT_RTC_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
int HwRtcInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,14 @@
#ifndef CONNECT_TF_H
#define CONNECT_TF_H
#ifdef __cplusplus
extern "C" {
#endif
int HwSoftSPIInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,36 @@
/*
* 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.h
* @brief define aiit-riscv64-board wdt function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_WDT_H
#define CONNECT_WDT_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
int HwWdtInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -78,6 +78,36 @@ enum HS_GPIO_CONFIG
#define BSP_CH438_INT_PIN 35
#endif
#ifdef BSP_USING_SOFT_SPI
#define FPIOA_SOFT_SPI_SCK 26
#define FPIOA_SOFT_SPI_MIOS 25
#define FPIOA_SOFT_SPI_MSOI 27
#define FPIOA_SOFT_SPI_NCS 28
#define BSP_SOFT_SPI_SCK_PIN 26
#define BSP_SOFT_SPI_MIOS_PIN 25
#define BSP_SOFT_SPI_MSOI_PIN 27
#define BSP_SOFT_SPI_NCS_PIN 28
#endif
#ifdef BSP_USING_LED
#define BSP_LED_PIN 29
#endif
#ifdef BSP_USING_KEY
#define BSP_KEY_PIN 31
#endif
#ifdef BSP_USING_LORA
#define BSP_E220_M0_PIN 32
#define BSP_E220_M1_PIN 33
#endif
#ifdef BSP_USING_RS485
#define BSP_485_DIR_PIN 24
#endif
extern int IoConfigInit(void);
#endif

View File

@ -0,0 +1,171 @@
/* 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.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __HARDWARE_HWTIMER_H__
#define __HARDWARE_HWTIMER_H__
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
typedef struct _timer_channel
{
/* TIMER_N Load Count Register (0x00+(N-1)*0x14) */
volatile uint32_t load_count;
/* TIMER_N Current Value Register (0x04+(N-1)*0x14) */
volatile uint32_t current_value;
/* TIMER_N Control Register (0x08+(N-1)*0x14) */
volatile uint32_t control;
/* TIMER_N Interrupt Clear Register (0x0c+(N-1)*0x14) */
volatile uint32_t eoi;
/* TIMER_N Interrupt Status Register (0x10+(N-1)*0x14) */
volatile uint32_t intr_stat;
} __attribute__((packed, aligned(4))) timer_channel_t;
typedef struct _kendryte_timer
{
/* TIMER_N Register (0x00-0x4c) */
volatile timer_channel_t channel[4];
/* reserverd (0x50-0x9c) */
volatile uint32_t resv1[20];
/* TIMER Interrupt Status Register (0xa0) */
volatile uint32_t intr_stat;
/* TIMER Interrupt Clear Register (0xa4) */
volatile uint32_t eoi;
/* TIMER Raw Interrupt Status Register (0xa8) */
volatile uint32_t raw_intr_stat;
/* TIMER Component Version Register (0xac) */
volatile uint32_t comp_version;
/* TIMER_N Load Count2 Register (0xb0-0xbc) */
volatile uint32_t load_count2[4];
} __attribute__((packed, aligned(4))) kendryte_timer_t;
typedef enum _timer_deivce_number
{
TIMER_DEVICE_0,
TIMER_DEVICE_1,
TIMER_DEVICE_2,
TIMER_DEVICE_MAX,
} timer_device_number_t;
typedef enum _timer_channel_number
{
TIMER_CHANNEL_0,
TIMER_CHANNEL_1,
TIMER_CHANNEL_2,
TIMER_CHANNEL_3,
TIMER_CHANNEL_MAX,
} timer_channel_number_t;
/* TIMER Control Register */
#define TIMER_CR_ENABLE 0x00000001
#define TIMER_CR_MODE_MASK 0x00000002
#define TIMER_CR_FREE_MODE 0x00000000
#define TIMER_CR_USER_MODE 0x00000002
#define TIMER_CR_INTERRUPT_MASK 0x00000004
#define TIMER_CR_PWM_ENABLE 0x00000008
/* clang-format on */
extern volatile kendryte_timer_t *const timer[3];
/**
* @brief Definitions for the timer callbacks
*/
typedef int (*timer_callback_t)(void *ctx);
/**
* @brief Set timer timeout
*
* @param[in] timer timer
* @param[in] channel channel
* @param[in] nanoseconds timeout
*
* @return the real timeout
*/
size_t timer_set_interval(timer_device_number_t timer_number, timer_channel_number_t channel, size_t nanoseconds);
/**
* @brief Init timer
*
* @param[in] timer timer
*/
void timer_init(timer_device_number_t timer_number);
/**
* @brief [DEPRECATED] Set timer timeout function
*
* @param[in] timer timer
* @param[in] channel channel
* @param[in] func timeout function
* @param[in] priority interrupt priority
*
*/
void timer_set_irq(timer_device_number_t timer_number, timer_channel_number_t channel, void(*func)(), uint32_t priority);
/**
* @brief Register timer interrupt user callback function
*
* @param[in] device The timer device number
* @param[in] channel The channel
* @param[in] is_one_shot Indicates if single shot
* @param[in] priority The priority
* @param[in] callback The callback function
* @param[in] ctx The context
*
* @return result
* - 0 Success
* - Other Fail
*/
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);
/**
* @brief Deregister timer interrupt user callback function
*
* @param[in] device The timer device number
* @param[in] channel The channel
*
* @return result
* - 0 Success
* - Other Fail
*/
int timer_irq_unregister(timer_device_number_t device, timer_channel_number_t channel);
/**
* @brief Enable timer
*
* @param[in] timer timer
* @param[in] channel channel
* @param[in] enable Enable or disable
*
*/
void timer_set_enable(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t enable);
#ifdef __cplusplus
}
#endif
#endif /* __TIMER_H__ */

View File

@ -0,0 +1,448 @@
/* 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
* @brief A real-time clock (RTC) is a computer clock that keeps track of
* the current time.
*/
/**
* @file hardware_rtc.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __HARDWARE_RTC_H__
#define __HARDWARE_RTC_H__
#include <platform.h>
#include <stdint.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief RTC timer mode
*
* Timer mode selector
* | Mode | Description |
* |------|------------------------|
* | 0 | Timer pause |
* | 1 | Timer time running |
* | 2 | Timer time setting |
*/
typedef enum _rtc_timer_mode_e
{
/* 0: Timer pause */
RTC_TIMER_PAUSE,
/* 1: Timer time running */
RTC_TIMER_RUNNING,
/* 2: Timer time setting */
RTC_TIMER_SETTING,
/* Max count of this enum*/
RTC_TIMER_MAX
} rtc_timer_mode_t;
/*
* @brief RTC tick interrupt mode
*
* Tick interrupt mode selector
* | Mode | Description |
* |------|------------------------|
* | 0 | Interrupt every second |
* | 1 | Interrupt every minute |
* | 2 | Interrupt every hour |
* | 3 | Interrupt every day |
*/
typedef enum _rtc_tick_interrupt_mode_e
{
/* 0: Interrupt every second */
RTC_INT_SECOND,
/* 1: Interrupt every minute */
RTC_INT_MINUTE,
/* 2: Interrupt every hour */
RTC_INT_HOUR,
/* 3: Interrupt every day */
RTC_INT_DAY,
/* Max count of this enum*/
RTC_INT_MAX
} rtc_tick_interrupt_mode_t;
/**
* @brief RTC mask structure
*
* RTC mask structure for common use
*/
typedef struct _rtc_mask
{
/* Reserved */
uint32_t resv : 1;
/* Second mask */
uint32_t second : 1;
/* Minute mask */
uint32_t minute : 1;
/* Hour mask */
uint32_t hour : 1;
/* Week mask */
uint32_t week : 1;
/* Day mask */
uint32_t day : 1;
/* Month mask */
uint32_t month : 1;
/* Year mask */
uint32_t year : 1;
} __attribute__((packed, aligned(1))) rtc_mask_t;
/**
* @brief RTC register
*
* @note RTC register table
*
* | Offset | Name | Description |
* |-----------|----------------|-------------------------------------|
* | 0x00 | date | Timer date information |
* | 0x04 | time | Timer time information |
* | 0x08 | alarm_date | Alarm date information |
* | 0x0c | alarm_time | Alarm time information |
* | 0x10 | initial_count | Timer counter initial value |
* | 0x14 | current_count | Timer counter current value |
* | 0x18 | interrupt_ctrl | RTC interrupt settings |
* | 0x1c | register_ctrl | RTC register settings |
* | 0x20 | reserved0 | Reserved |
* | 0x24 | reserved1 | Reserved |
* | 0x28 | extended | Timer extended information |
*
*/
/**
* @brief Timer date information
*
* No. 0 Register (0x00)
*/
typedef struct _rtc_date
{
/* Week. Range [0,6]. 0 is Sunday. */
uint32_t week : 3;
/* Reserved */
uint32_t resv0 : 5;
/* Day. Range [1,31] or [1,30] or [1,29] or [1,28] */
uint32_t day : 5;
/* Reserved */
uint32_t resv1 : 3;
/* Month. Range [1,12] */
uint32_t month : 4;
/* Year. Range [0,99] */
uint32_t year : 12;
} __attribute__((packed, aligned(4))) rtc_date_t;
/**
* @brief Timer time information
*
* No. 1 Register (0x04)
*/
typedef struct _rtc_time
{
/* Reserved */
uint32_t resv0 : 10;
/* Second. Range [0,59] */
uint32_t second : 6;
/* Minute. Range [0,59] */
uint32_t minute : 6;
/* Reserved */
uint32_t resv1 : 2;
/* Hour. Range [0,23] */
uint32_t hour : 5;
/* Reserved */
uint32_t resv2 : 3;
} __attribute__((packed, aligned(4))) rtc_time_t;
/**
* @brief Alarm date information
*
* No. 2 Register (0x08)
*/
typedef struct _rtc_alarm_date
{
/* Alarm Week. Range [0,6]. 0 is Sunday. */
uint32_t week : 3;
/* Reserved */
uint32_t resv0 : 5;
/* Alarm Day. Range [1,31] or [1,30] or [1,29] or [1,28] */
uint32_t day : 5;
/* Reserved */
uint32_t resv1 : 3;
/* Alarm Month. Range [1,12] */
uint32_t month : 4;
/* Alarm Year. Range [0,99] */
uint32_t year : 12;
} __attribute__((packed, aligned(4))) rtc_alarm_date_t;
/**
* @brief Alarm time information
*
* No. 3 Register (0x0c)
*/
typedef struct _rtc_alarm_time
{
/* Reserved */
uint32_t resv0 : 10;
/* Alarm Second. Range [0,59] */
uint32_t second : 6;
/* Alarm Minute. Range [0,59] */
uint32_t minute : 6;
/* Reserved */
uint32_t resv1 : 2;
/* Alarm Hour. Range [0,23] */
uint32_t hour : 5;
/* Reserved */
uint32_t resv2 : 3;
} __attribute__((packed, aligned(4))) rtc_alarm_time_t;
/**
* @brief Timer counter initial value
*
* No. 4 Register (0x10)
*/
typedef struct _rtc_initial_count
{
/* RTC counter initial value */
uint32_t count : 32;
} __attribute__((packed, aligned(4))) rtc_initial_count_t;
/**
* @brief Timer counter current value
*
* No. 5 Register (0x14)
*/
typedef struct _rtc_current_count
{
/* RTC counter current value */
uint32_t count : 32;
} __attribute__((packed, aligned(4))) rtc_current_count_t;
/**
* @brief RTC interrupt settings
*
* No. 6 Register (0x18)
*/
typedef struct _rtc_interrupt_ctrl
{
/* Reserved */
uint32_t tick_enable : 1;
/* Alarm interrupt enable */
uint32_t alarm_enable : 1;
/* Tick interrupt enable */
uint32_t tick_int_mode : 2;
/* Reserved */
uint32_t resv : 20;
/* Alarm compare mask for interrupt */
uint32_t alarm_compare_mask : 8;
} __attribute__((packed, aligned(4))) rtc_interrupt_ctrl_t;
/**
* @brief RTC register settings
*
* No. 7 Register (0x1c)
*/
typedef struct _rtc_register_ctrl
{
/* RTC timer read enable */
uint32_t read_enable : 1;
/* RTC timer write enable */
uint32_t write_enable : 1;
/* Reserved */
uint32_t resv0 : 11;
/* RTC timer mask */
uint32_t TimerMask : 8;
/* RTC alarm mask */
uint32_t alarm_mask : 8;
/* RTC counter initial count value mask */
uint32_t initial_count_mask : 1;
/* RTC interrupt register mask */
uint32_t interrupt_register_mask : 1;
/* Reserved */
uint32_t resv1 : 1;
} __attribute__((packed, aligned(4))) rtc_register_ctrl_t;
/**
* @brief Reserved
*
* No. 8 Register (0x20)
*/
typedef struct _rtc_reserved0
{
/* Reserved */
uint32_t resv : 32;
} __attribute__((packed, aligned(4))) rtc_reserved0_t;
/**
* @brief Reserved
*
* No. 9 Register (0x24)
*/
typedef struct _rtc_reserved1
{
/* Reserved */
uint32_t resv : 32;
} __attribute__((packed, aligned(4))) rtc_reserved1_t;
/**
* @brief Timer extended information
*
* No. 10 Register (0x28)
*/
typedef struct _rtc_extended
{
/* Century. Range [0,31] */
uint32_t century : 5;
/* Is leap year. 1 is leap year, 0 is not leap year */
uint32_t leap_year : 1;
/* Reserved */
uint32_t resv : 26;
} __attribute__((packed, aligned(4))) rtc_extended_t;
/**
* @brief Real-time clock struct
*
* A real-time clock (RTC) is a computer clock that keeps track of
* the current time.
*/
typedef struct _rtc
{
/* No. 0 (0x00): Timer date information */
rtc_date_t date;
/* No. 1 (0x04): Timer time information */
rtc_time_t time;
/* No. 2 (0x08): Alarm date information */
rtc_alarm_date_t alarm_date;
/* No. 3 (0x0c): Alarm time information */
rtc_alarm_time_t alarm_time;
/* No. 4 (0x10): Timer counter initial value */
rtc_initial_count_t initial_count;
/* No. 5 (0x14): Timer counter current value */
rtc_current_count_t current_count;
/* No. 6 (0x18): RTC interrupt settings */
rtc_interrupt_ctrl_t interrupt_ctrl;
/* No. 7 (0x1c): RTC register settings */
rtc_register_ctrl_t register_ctrl;
/* No. 8 (0x20): Reserved */
rtc_reserved0_t reserved0;
/* No. 9 (0x24): Reserved */
rtc_reserved1_t reserved1;
/* No. 10 (0x28): Timer extended information */
rtc_extended_t extended;
} __attribute__((packed, aligned(4))) rtc_t;
/**
* @brief Real-time clock object
*/
extern volatile rtc_t *const rtc;
extern volatile uint32_t *const rtc_base;
/**
* @brief Set date time to RTC
*
* @param[in] year The year
* @param[in] month The month
* @param[in] day The day
* @param[in] hour The hour
* @param[in] minute The minute
* @param[in] second The second
*
* @return result
* - 0 Success
* - Other Fail
*/
int rtc_timer_set(int year, int month, int day, int hour, int minute, int second);
/**
* @brief Get date time from RTC
*
* @param year The year
* @param month The month
* @param day The day
* @param hour The hour
* @param minute The minute
* @param second The second
*
* @return result
* - 0 Success
* - Other Fail
*/
int rtc_timer_get(int *year, int *month, int *day, int *hour, int *minute, int *second);
/**
* @brief Initialize RTC
*
* @return Result
* - 0 Success
* - Other Fail
*/
int rtc_init(void);
/**
* @brief Set RTC in protect mode or not
*
* @param enable Enable flag
*
* @return result
* - 0 Success
* - Other Fail
*/
int rtc_protect_set(int enable);
/**
* @brief Set RTC timer mode
*
* @param timer_mode Timer mode
*
*/
void rtc_timer_set_mode(rtc_timer_mode_t timer_mode);
/**
* @brief Set RTC timer clock frequency
*
* @param frequency Frequency
*
* @return result
* - 0 Success
* - Other Fail
*/
int rtc_timer_set_clock_frequency(unsigned int frequency);
/**
* @brief Set RTC timer clock count value
*
* @param count Count
*
* @return result
* - 0 Success
* - Other Fail
*/
int rtc_timer_set_clock_count_value(unsigned int count);
#ifdef __cplusplus
}
#endif
#endif /* _DRIVER_RTC_H */

View File

@ -0,0 +1,180 @@
/* 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.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __WDT_H__
#define __WDT_H__
#include <stdint.h>
#include <stddef.h>
#include <plic.h>
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
typedef struct _wdt
{
/* WDT Control Register (0x00) */
volatile uint32_t cr;
/* WDT Timeout Range Register (0x04) */
volatile uint32_t torr;
/* WDT Current Counter Value Register (0x08) */
volatile uint32_t ccvr;
/* WDT Counter Restart Register (0x0c) */
volatile uint32_t crr;
/* WDT Interrupt Status Register (0x10) */
volatile uint32_t stat;
/* WDT Interrupt Clear Register (0x14) */
volatile uint32_t eoi;
/* reserverd (0x18) */
volatile uint32_t resv1;
/* WDT Protection level Register (0x1c) */
volatile uint32_t prot_level;
/* reserved (0x20-0xe0) */
volatile uint32_t resv4[49];
/* WDT Component Parameters Register 5 (0xe4) */
volatile uint32_t comp_param_5;
/* WDT Component Parameters Register 4 (0xe8) */
volatile uint32_t comp_param_4;
/* WDT Component Parameters Register 3 (0xec) */
volatile uint32_t comp_param_3;
/* WDT Component Parameters Register 2 (0xf0) */
volatile uint32_t comp_param_2;
/* WDT Component Parameters Register 1 (0xf4) */
volatile uint32_t comp_param_1;
/* WDT Component Version Register (0xf8) */
volatile uint32_t comp_version;
/* WDT Component Type Register (0xfc) */
volatile uint32_t comp_type;
} __attribute__((packed, aligned(4))) wdt_t;
typedef enum _wdt_device_number
{
WDT_DEVICE_0,
WDT_DEVICE_1,
WDT_DEVICE_MAX,
} wdt_device_number_t;
#define WDT_RESET_ALL 0x00000000U
#define WDT_RESET_CPU 0x00000001U
/* WDT Control Register */
#define WDT_CR_ENABLE 0x00000001U
#define WDT_CR_RMOD_MASK 0x00000002U
#define WDT_CR_RMOD_RESET 0x00000000U
#define WDT_CR_RMOD_INTERRUPT 0x00000002U
#define WDT_CR_RPL_MASK 0x0000001CU
#define WDT_CR_RPL(x) ((x) << 2)
/* WDT Timeout Range Register */
#define WDT_TORR_TOP_MASK 0x000000FFU
#define WDT_TORR_TOP(x) ((x) << 4 | (x) << 0)
/* WDT Current Counter Value Register */
#define WDT_CCVR_MASK 0xFFFFFFFFU
/* WDT Counter Restart Register */
#define WDT_CRR_MASK 0x00000076U
/* WDT Interrupt Status Register */
#define WDT_STAT_MASK 0x00000001U
/* WDT Interrupt Clear Register */
#define WDT_EOI_MASK 0x00000001U
/* WDT Protection level Register */
#define WDT_PROT_LEVEL_MASK 0x00000007U
/* WDT Component Parameter Register 5 */
#define WDT_COMP_PARAM_5_CP_WDT_USER_TOP_MAX_MASK 0xFFFFFFFFU
/* WDT Component Parameter Register 4 */
#define WDT_COMP_PARAM_4_CP_WDT_USER_TOP_INIT_MAX_MASK 0xFFFFFFFFU
/* WDT Component Parameter Register 3 */
#define WDT_COMP_PARAM_3_CD_WDT_TOP_RST_MASK 0xFFFFFFFFU
/* WDT Component Parameter Register 2 */
#define WDT_COMP_PARAM_3_CP_WDT_CNT_RST_MASK 0xFFFFFFFFU
/* WDT Component Parameter Register 1 */
#define WDT_COMP_PARAM_1_WDT_ALWAYS_EN_MASK 0x00000001U
#define WDT_COMP_PARAM_1_WDT_DFLT_RMOD_MASK 0x00000002U
#define WDT_COMP_PARAM_1_WDT_DUAL_TOP_MASK 0x00000004U
#define WDT_COMP_PARAM_1_WDT_HC_RMOD_MASK 0x00000008U
#define WDT_COMP_PARAM_1_WDT_HC_RPL_MASK 0x00000010U
#define WDT_COMP_PARAM_1_WDT_HC_TOP_MASK 0x00000020U
#define WDT_COMP_PARAM_1_WDT_USE_FIX_TOP_MASK 0x00000040U
#define WDT_COMP_PARAM_1_WDT_PAUSE_MASK 0x00000080U
#define WDT_COMP_PARAM_1_APB_DATA_WIDTH_MASK 0x00000300U
#define WDT_COMP_PARAM_1_WDT_DFLT_RPL_MASK 0x00001C00U
#define WDT_COMP_PARAM_1_WDT_DFLT_TOP_MASK 0x000F0000U
#define WDT_COMP_PARAM_1_WDT_DFLT_TOP_INIT_MASK 0x00F00000U
#define WDT_COMP_PARAM_1_WDT_CNT_WIDTH_MASK 0x1F000000U
/* WDT Component Version Register */
#define WDT_COMP_VERSION_MASK 0xFFFFFFFFU
/* WDT Component Type Register */
#define WDT_COMP_TYPE_MASK 0xFFFFFFFFU
/* clang-format on */
/**
* @brief Feed wdt
*/
void wdt_feed(wdt_device_number_t id);
/**
* @brief Start wdt
*
* @param[in] id Wdt id 0 or 1
* @param[in] time_out_ms Wdt trigger time
* @param[in] on_irq Wdt interrupt callback
*
*/
void wdt_start(wdt_device_number_t id, uint64_t time_out_ms, plic_irq_callback_t on_irq);
/**
* @brief Start wdt
*
* @param[in] id Wdt id 0 or 1
* @param[in] time_out_ms Wdt trigger time
* @param[in] on_irq Wdt interrupt callback
* @param[in] ctx Param of callback
*
* @return Wdt time
*
*/
uint32_t wdt_init(wdt_device_number_t id, uint64_t time_out_ms, plic_irq_callback_t on_irq, void *ctx);
/**
* @brief Stop wdt
*
* @param[in] id Wdt id 0 or 1
*
*/
void wdt_stop(wdt_device_number_t id);
/**
* @brief Clear wdt interrupt
*
* @param[in] id Wdt id 0 or 1
*
*/
void wdt_clear_interrupt(wdt_device_number_t id);
#ifdef __cplusplus
}
#endif
#endif /* __WDT_H__ */

View File

@ -0,0 +1,11 @@
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

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_rtc.c hardware_rtc.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,183 @@
/*
* 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 aiit-riscv64-board rtc function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <connect_rtc.h>
#include <hardware_rtc.h>
#include <stdint.h>
#include <stdlib.h>
#include <sysctl.h>
#include <time.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);
}
rtc_init();
return ret;
}

View File

@ -0,0 +1,597 @@
/* 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 2021-04-25
*/
#include <encoding.h>
#include <hardware_rtc.h>
#include <stdint.h>
#include <stdlib.h>
#include <sysctl.h>
#include <time.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;
}

View File

@ -0,0 +1,43 @@
if BSP_USING_SOFT_SPI
config SOFT_SPI_BUS_NAME
string "soft spi bus 1 name"
default "soft_spi1_bus1"
config SOFT_SPI_DEVICE_NAME
string "soft spi dev 1 name"
default "soft_spi1_dev1"
config SOFT_SPI_DRV_NAME
string "soft spi drv 1 name"
default "soft_spi1_drv1"
config SOFT_SPI_SCK
int "soft spi sck pin"
default 26
config SOFT_SPI_MOSI
int "soft spi mosi pin"
default 27
config SOFT_SPI_MISO
int "soft spi miso pin"
default 25
config SOFT_SPI_CS0_PIN
int "soft spi cs pin"
default 28
config SOFT_SPI_DEVICE_SLAVE_ID
int "soft spi slave id"
default 0
config SOFT_SPI_CHIP_SELECT
int "soft spi chip selected"
default 0
config SOFT_SPI_CLK_DELAY
int "clk in microsecond"
default 0
endif

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_soft_spi.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,295 @@
#include <xizi.h>
#include <device.h>
#include <fpioa.h>
#include <gpiohs.h>
#include "drv_io_config.h"
#include <plic.h>
#include <utils.h>
#include <connect_soft_spi.h>
#include <sleep.h>
#include <sd_spi.h>
#include <dev_spi.h>
#include <bus_spi.h>
static x_err_t softSPIinit(struct SpiDriver *spi_drv, struct BusConfigureInfo *cfg)
{
NULL_PARAM_CHECK(spi_drv);
NULL_PARAM_CHECK(cfg);
// mode CPOL = 0 CPHA = 0
gpiohs_set_drive_mode(SOFT_SPI_CS0_PIN, GPIO_DM_OUTPUT);
gpiohs_set_pin(SOFT_SPI_CS0_PIN, GPIO_PV_HIGH); // set the cs gpio high
gpiohs_set_drive_mode(SOFT_SPI_SCK, GPIO_DM_OUTPUT);
gpiohs_set_drive_mode(SOFT_SPI_MOSI, GPIO_DM_OUTPUT);
gpiohs_set_drive_mode(SOFT_SPI_MISO, GPIO_DM_INPUT);
gpiohs_set_pin(SOFT_SPI_SCK, GPIO_PV_LOW);
KPrintf("%s init done\n", SOFT_SPI_BUS_NAME);
return EOK;
}
static uint32 softSpiDrvConfigure(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:
softSPIinit(spi_drv, configure_info);
break;
case OPE_CFG:
break;
default:
break;
}
return ret;
}
static void soft_spi_writebyte(struct SpiHardwareDevice *spi_dev, uint8_t data)
{
int8_t i = 0;
uint8_t temp = 0;
for (i = 0; i < 8; i++)
{
temp = ((data & 0x80) == 0x80) ? 1 : 0;
data = data << 1;
gpiohs_set_pin(SOFT_SPI_SCK, GPIO_PV_LOW);
usleep(SOFT_SPI_CLK_DELAY);
if (0 == temp)
{
gpiohs_set_pin(SOFT_SPI_MOSI, GPIO_PV_LOW);
}
else
{
gpiohs_set_pin(SOFT_SPI_MOSI, GPIO_PV_HIGH);
}
gpiohs_set_pin(SOFT_SPI_SCK, GPIO_PV_HIGH);
usleep(SOFT_SPI_CLK_DELAY);
}
gpiohs_set_pin(SOFT_SPI_SCK, GPIO_PV_LOW);
}
/* 读一个字节 */
static uint8_t soft_spi_readbyte(struct SpiHardwareDevice *spi_dev)
{
uint8_t i = 0;
uint8_t read_data = 0xFF;
for (i = 0; i < 8; i++)
{
read_data = read_data << 1;
gpiohs_set_pin(SOFT_SPI_SCK, GPIO_PV_LOW);
usleep(SOFT_SPI_CLK_DELAY);
gpiohs_set_pin(SOFT_SPI_SCK, GPIO_PV_HIGH);
usleep(SOFT_SPI_CLK_DELAY);
if (1 == gpiohs_get_pin(SOFT_SPI_MISO))
{
read_data = read_data | 0x01;
}
}
return read_data;
}
/* 读写一个字节 */
// this funcition is unverify until now!
static uint8_t soft_spi_readwritebyte(struct SpiHardwareDevice *spi_dev, uint8_t data)
{
uint8_t i = 0;
uint8_t temp = 0;
uint8_t read_data = 0xFF;
for (i = 0; i < 8; i++)
{
temp = ((data & 0x80) == 0x80) ? 1 : 0;
data = data << 1;
read_data = read_data << 1;
if (temp == 0)
{
gpiohs_set_pin(SOFT_SPI_MOSI, GPIO_PV_LOW);
}
else
{
gpiohs_set_pin(SOFT_SPI_MOSI, GPIO_PV_HIGH);
}
usleep(SOFT_SPI_CLK_DELAY);
gpiohs_set_pin(SOFT_SPI_SCK, GPIO_PV_HIGH);
usleep(SOFT_SPI_CLK_DELAY);
if (gpiohs_get_pin(SOFT_SPI_MISO) == 1)
{
read_data = read_data + 1;
}
}
return read_data;
}
static uint32 softSpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg)
{
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data);
uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
const uint8_t *data_buff = spi_datacfg->tx_buff;
int data_length = spi_datacfg->length;
if (NONE == spi_datacfg->tx_buff)
{
data_length = 0;
}
if (spi_datacfg->spi_chip_select)
{
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_LOW);
}
for (size_t i = 0; i < data_length; i++)
{
soft_spi_writebyte(spi_dev, data_buff[i]);
}
if (spi_datacfg->spi_cs_release)
{
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH);
}
spi_datacfg = spi_datacfg->next;
return EOK;
}
static uint32 softSpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg)
{
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data);
uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
uint8_t *recv_buff = spi_datacfg->rx_buff;
int recv_length = spi_datacfg->length;
if (NONE == spi_datacfg->rx_buff)
{
recv_length = 0;
}
if (spi_datacfg->spi_chip_select)
{
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_LOW);
}
for (size_t i = 0; i < recv_length; i++)
{
recv_buff[i] = soft_spi_readbyte(spi_dev);
}
if (spi_datacfg->spi_cs_release)
{
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH);
}
spi_datacfg = spi_datacfg->next;
return spi_datacfg->length;
}
const struct SpiDevDone soft_spi_dev_done = {
.dev_close = NONE,
.dev_open = NONE,
.dev_read = softSpiReadData,
.dev_write = softSpiWriteData};
static int BoardSoftSpiBusInit(struct SpiBus *spi_bus, struct SpiDriver *spi_driver)
{
x_err_t ret = EOK;
/*Init the spi bus */
ret = SpiBusInit(spi_bus, SOFT_SPI_BUS_NAME);
if (EOK != ret)
{
KPrintf("Board_Spi_init SpiBusInit error %d\n", ret);
return ERROR;
}
/*Init the spi driver*/
ret = SpiDriverInit(spi_driver, SOFT_SPI_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(SOFT_SPI_DRV_NAME, SOFT_SPI_BUS_NAME);
if (EOK != ret)
{
KPrintf("Board_Spi_init SpiDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
static int BoardSoftSpiDevBend(void)
{
x_err_t ret = EOK;
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 = SOFT_SPI_DEVICE_SLAVE_ID;
spi_slaveparam0.spi_cs_gpio_pin = SOFT_SPI_CS0_PIN;
spi_slaveparam0.spi_cs_select_id = SOFT_SPI_CHIP_SELECT;
spi_device0.spi_param.spi_dma_param = NONE;
spi_device0.spi_param.spi_slave_param = &spi_slaveparam0;
spi_device0.spi_dev_done = &(soft_spi_dev_done);
ret = SpiDeviceRegister(&spi_device0, (void *)(&spi_device0.spi_param), SOFT_SPI_DEVICE_NAME);
if (EOK != ret)
{
KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SOFT_SPI_DEVICE_NAME, ret);
return ERROR;
}
ret = SpiDeviceAttachToBus(SOFT_SPI_DEVICE_NAME, SOFT_SPI_BUS_NAME);
if (EOK != ret)
{
KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SOFT_SPI_DEVICE_NAME, ret);
return ERROR;
}
return ret;
}
int HwSoftSPIInit(void)
{
x_err_t ret = EOK;
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_driver.configure = &(softSpiDrvConfigure);
ret = BoardSoftSpiBusInit(&spi_bus, &spi_driver);
if (EOK != ret)
{
KPrintf("Board_Spi_Init error ret %u\n", ret);
return ERROR;
}
ret = BoardSoftSpiDevBend();
if (EOK != ret)
{
KPrintf("Board_Spi_Init error ret %u\n", ret);
return ERROR;
}
return ret;
}

View File

@ -0,0 +1,19 @@
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

View File

@ -0,0 +1,5 @@
SRC_FILES := hardware_hwtimer.c connect_hwtimer.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,153 @@
/*
* 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 aiit-riscv64-board hwtimer function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <board.h>
#include <connect_hwtimer.h>
#include <fpioa.h>
#include <plic.h>
#include <stdio.h>
#include <sysctl.h>
#include <syslog.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("BoardHwtimerDevBend HwtimerDeviceRegister 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("BoardHwtimerDevBend 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;
}

View File

@ -0,0 +1,407 @@
/* 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 2021-04-25
*/
#include <hardware_hwtimer.h>
#include <io.h>
#include <plic.h>
#include <stddef.h>
#include <sysctl.h>
#include <syslog.h>
#include <xs_isr.h>
#include <utils.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;
}

View File

@ -0,0 +1,34 @@
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

View File

@ -0,0 +1,6 @@
SRC_FILES := wdt.c connect_wdt.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,176 @@
/*
* 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 aiit-riscv64-board watchdog function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <connect_wdt.h>
#include <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;
}

View File

@ -0,0 +1,125 @@
/* 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 2021-04-25
*/
#include <math.h>
#include <platform.h>
#include <plic.h>
#include <stddef.h>
#include <sysctl.h>
#include <utils.h>
#include <wdt.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);
}

View File

@ -62,4 +62,7 @@ menuconfig KERNEL_TEST
config KERNEL_TEST_SPI_FLASH
bool "Config test spi flash"
default n
config KERNEL_TEST_SOFT_SPI_SD
bool "Config test soft spi sd"
default n
endif

View File

@ -157,7 +157,6 @@ void EnvInitKTask(void *parameter)
_InitSubCmpts(components_init);
_InitSubCmpts(env_init);
ENABLE_INTERRUPT(lock);
_InitSubCmpts(communication_init);
#ifdef ARCH_SMP

View File

@ -28,11 +28,11 @@
extern "C" {
#endif
#define SPI_SD_FREQUENCY 400000
#define SPI_SD_FREQUENCY 400000
#define SPI_SD_TIMEOUT_NUM 100
#define SD_CMD_RESPONE_LENGTH 5
#define SD_CMD_CSD_LENGTH 16
#define SD_BLOCK_LENGTH 512
#define SD_BLOCK_LENGTH 512
#define SD_TIMEOUT(cnt, time) \
do \

View File

@ -96,9 +96,8 @@ static uint32 SdSendCmdByte(SpiSdDeviceType spi_sd_dev, struct SdCmdParam *sd_cm
if ((SD_CMD_17 == sd_cmd_param->sd_cmd_type) || (SD_CMD_18 == sd_cmd_param->sd_cmd_type)) {
MdelayKTask(100);
}
SD_TIMEOUT(start_time, 2 * SPI_SD_TIMEOUT_NUM);
}while((0 != (read[0] & 0x80)));
}while(0 != (read[0] & 0x80));
switch (sd_cmd_param->sd_respone_type)
{
@ -672,7 +671,7 @@ static uint32 SdHwReadCSD(SpiSdDeviceType spi_sd_dev)
g_sd_cmd_param.sd_cmd_type = SD_CMD_9;
g_sd_cmd_param.sd_cmd_args = 0x00;
g_sd_cmd_param.sd_cmd_crc = 0x00;
g_sd_cmd_param.sd_respone_type = SD_RESPONE_2;
g_sd_cmd_param.sd_respone_type = SD_RESPONE_1;
/*pull down the cs pin*/
SpiDevConfigureCs(&spi_sd_dev->spi_dev->haldev, 1, 0);
@ -691,7 +690,7 @@ static uint32 SdHwReadCSD(SpiSdDeviceType spi_sd_dev)
if (0xFE != g_sd_cmd_param.sd_respone_data[1]) {
/*Step2 : SPI write data 0xFF until read 0xFE*/
uint8 data = 0xFF;
uint8 read_spi;
uint8 read_spi=0x00;
uint32 start_time;
write_param.buffer = (void *)&data;
@ -705,7 +704,6 @@ static uint32 SdHwReadCSD(SpiSdDeviceType spi_sd_dev)
{
BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param);
BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param);
SD_TIMEOUT(start_time, 10 * SPI_SD_TIMEOUT_NUM);
}while(0xFE != read_spi);
}
@ -768,7 +766,7 @@ static uint32 SdReadSingleBlock(SpiSdDeviceType spi_sd_dev, uint32 id, uint8 *re
return ERROR;
}
/*Step2 : SPI write data 0xFF until read 0xFE*/
/*Step2 : SPI read until 0xFE*/
uint8 data = 0xFF;
uint8 read[2];
uint32 start_time;
@ -782,7 +780,6 @@ static uint32 SdReadSingleBlock(SpiSdDeviceType spi_sd_dev, uint32 id, uint8 *re
do
{
BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param);
BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param);
SD_TIMEOUT(start_time, 100 * SPI_SD_TIMEOUT_NUM);
@ -1077,6 +1074,7 @@ static uint32 SdWriteMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const voi
}
/*Step8 : SPI write 0xFD, multi block write data done*/
data = 0xFD;
write_param.buffer = (void *)&data;
write_param.size = 1;
BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param);