support OK1052-C ADC SPI I2C RTC codes ; support PLC control framework from Wang_linyu

This commit is contained in:
xuedongliang 2022-03-11 13:38:00 +08:00
commit 73d10380ea
111 changed files with 14410 additions and 1033 deletions

View File

@ -56,5 +56,6 @@ void test_adc()
return; return;
} }
// SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
// test_adc, test_adc, read 3.3 voltage data from adc); SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
adc, test_adc, read 3.3 voltage data from adc);

View File

@ -17,6 +17,7 @@
* @author AIIT XUOS Lab * @author AIIT XUOS Lab
* @date 2021-05-29 * @date 2021-05-29
*/ */
#include <transform.h> #include <transform.h>
#include <xizi.h> #include <xizi.h>
#include "board.h" #include "board.h"
@ -24,27 +25,13 @@
#include <lwip/sockets.h> #include <lwip/sockets.h>
#include "lwip/sys.h" #include "lwip/sys.h"
/******************************************************************************* #define TCP_DEMO_BUF_SIZE 65535
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
char tcp_socket_ip[] = {192, 168, 250, 252}; char tcp_socket_ip[] = {192, 168, 250, 252};
#define TCP_DEMO_BUF_SIZE 65535 /******************************************************************************/
/******************************************************************************* static void TCPSocketRecvTask(void *arg)
* Code
******************************************************************************/
static void tcp_recv_demo(void *arg)
{ {
int fd = -1, clientfd; int fd = -1, clientfd;
int recv_len; int recv_len;
@ -80,7 +67,7 @@ static void tcp_recv_demo(void *arg)
} }
lw_print("tcp bind success, start to receive.\n"); lw_print("tcp bind success, start to receive.\n");
lw_print("\n\nLocal Port:%d\n\n", LWIP_LOCAL_PORT); lw_pr_info("\n\nLocal Port:%d\n\n", LWIP_LOCAL_PORT);
// setup socket fd as listening mode // setup socket fd as listening mode
if (listen(fd, 5) != 0 ) if (listen(fd, 5) != 0 )
@ -91,7 +78,7 @@ static void tcp_recv_demo(void *arg)
// accept client connection // accept client connection
clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len); clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len);
lw_print("client %s connected\n", inet_ntoa(tcp_addr.sin_addr)); lw_pr_info("client %s connected\n", inet_ntoa(tcp_addr.sin_addr));
while(1) while(1)
{ {
@ -114,7 +101,7 @@ static void tcp_recv_demo(void *arg)
} }
} }
void tcp_socket_recv_run(int argc, char *argv[]) void TCPSocketRecvTest(int argc, char *argv[])
{ {
int result = 0; int result = 0;
pthread_t th_id; pthread_t th_id;
@ -126,15 +113,14 @@ void tcp_socket_recv_run(int argc, char *argv[])
sscanf(argv[1], "%d.%d.%d.%d", &tcp_socket_ip[0], &tcp_socket_ip[1], &tcp_socket_ip[2], &tcp_socket_ip[3]); sscanf(argv[1], "%d.%d.%d.%d", &tcp_socket_ip[0], &tcp_socket_ip[1], &tcp_socket_ip[2], &tcp_socket_ip[3]);
} }
ETH_BSP_Config();
lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
sys_thread_new("tcp_recv_demo", tcp_recv_demo, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); sys_thread_new("TCPSocketRecvTask", TCPSocketRecvTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
} }
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
TCPSocketRecv, tcp_socket_recv_run, TCP recv echo); TCPSocketRecv, TCPSocketRecvTest, TCP recv echo);
static void tcp_send_demo(void *arg) static void TCPSocketSendTask(void *arg)
{ {
int cnt = LWIP_DEMO_TIMES; int cnt = LWIP_DEMO_TIMES;
int fd = -1; int fd = -1;
@ -163,7 +149,7 @@ static void tcp_send_demo(void *arg)
} }
lw_print("tcp connect success, start to send.\n"); lw_print("tcp connect success, start to send.\n");
lw_pr_info("\n\nTarget Port:%d\n\n", tcp_sock.sin_port); lw_pr_info("\n\nTarget Port:%d\n\n", LWIP_TARGET_PORT);
while (cnt --) while (cnt --)
{ {
@ -182,7 +168,7 @@ __exit:
} }
void tcp_socket_send_run(int argc, char *argv[]) void TCPSocketSendTest(int argc, char *argv[])
{ {
if(argc == 2) if(argc == 2)
{ {
@ -190,11 +176,10 @@ void tcp_socket_send_run(int argc, char *argv[])
sscanf(argv[1], "%d.%d.%d.%d", &tcp_socket_ip[0], &tcp_socket_ip[1], &tcp_socket_ip[2], &tcp_socket_ip[3]); sscanf(argv[1], "%d.%d.%d.%d", &tcp_socket_ip[0], &tcp_socket_ip[1], &tcp_socket_ip[2], &tcp_socket_ip[3]);
} }
ETH_BSP_Config();
lwip_config_tcp(lwip_ipaddr, lwip_netmask, tcp_socket_ip); lwip_config_tcp(lwip_ipaddr, lwip_netmask, tcp_socket_ip);
sys_thread_new("tcp socket", tcp_send_demo, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); sys_thread_new("tcp socket", TCPSocketSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
} }
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
TCPSocketSend, tcp_socket_send_run, TCP send demo); TCPSocketSend, TCPSocketSendTest, TCP send demo);

View File

@ -23,36 +23,20 @@
#include "sys_arch.h" #include "sys_arch.h"
#include "lwip/udp.h" #include "lwip/udp.h"
#include "lwip/opt.h" #include "lwip/opt.h"
#include <lwip/sockets.h>
#include "lwip/sys.h"
/******************************************************************************* #define UDP_BUF_SIZE 65536
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
extern char udp_target[]; extern char udp_target[];
static struct udp_pcb *udpecho_raw_pcb; static struct udp_pcb *udpecho_raw_pcb;
char udp_socket_ip[] = {192, 168, 250, 252}; char udp_socket_ip[] = {192, 168, 250, 252};
/******************************************************************************* /******************************************************************************/
* Code
******************************************************************************/
#include <lwip/sockets.h> static void UdpSocketRecvTask(void *arg)
#include "lwip/sys.h"
#define LWIP_UDP_TASK_STACK 4096
#define LWIP_UDP_TASK_PRIO 25
#define UDP_BUF_SIZE 1024
static void udp_recv_demo(void *arg)
{ {
lw_print("udp_recv_demo start.\n"); lw_print("UdpSocketRecvTask start.\n");
int socket_fd = -1; int socket_fd = -1;
char *recv_buf; char *recv_buf;
@ -63,14 +47,14 @@ static void udp_recv_demo(void *arg)
while(1) while(1)
{ {
recv_buf = (char *)malloc(UDP_BUF_SIZE); recv_buf = (char *)malloc(UDP_BUF_SIZE);
if (recv_buf == NULL) if(recv_buf == NULL)
{ {
lw_print("No memory\n"); lw_print("No memory\n");
goto __exit; goto __exit;
} }
socket_fd = socket(AF_INET, SOCK_DGRAM, 0); socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_fd < 0) if(socket_fd < 0)
{ {
lw_print("Socket error\n"); lw_print("Socket error\n");
goto __exit; goto __exit;
@ -81,7 +65,7 @@ static void udp_recv_demo(void *arg)
udp_addr.sin_port = htons(LWIP_LOCAL_PORT); udp_addr.sin_port = htons(LWIP_LOCAL_PORT);
memset(&(udp_addr.sin_zero), 0, sizeof(udp_addr.sin_zero)); memset(&(udp_addr.sin_zero), 0, sizeof(udp_addr.sin_zero));
if (bind(socket_fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1) if(bind(socket_fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1)
{ {
lw_print("Unable to bind\n"); lw_print("Unable to bind\n");
goto __exit; goto __exit;
@ -94,28 +78,25 @@ static void udp_recv_demo(void *arg)
{ {
memset(recv_buf, 0, UDP_BUF_SIZE); memset(recv_buf, 0, UDP_BUF_SIZE);
recv_len = recvfrom(socket_fd, recv_buf, UDP_BUF_SIZE, 0, (struct sockaddr *)&server_addr, &addr_len); recv_len = recvfrom(socket_fd, recv_buf, UDP_BUF_SIZE, 0, (struct sockaddr *)&server_addr, &addr_len);
lw_print("Receive from : %s\n", inet_ntoa(server_addr.sin_addr)); lw_pr_info("Receive from : %s\n", inet_ntoa(server_addr.sin_addr));
lw_print("Receive data : %s\n\n", recv_buf); lw_pr_info("Receive data : %s\n\n", recv_buf);
sendto(socket_fd, recv_buf, recv_len, 0, (struct sockaddr*)&server_addr, addr_len); sendto(socket_fd, recv_buf, recv_len, 0, (struct sockaddr*)&server_addr, addr_len);
} }
__exit: __exit:
if (socket_fd >= 0) if(socket_fd >= 0)
{
closesocket(socket_fd); closesocket(socket_fd);
}
if (recv_buf) if(recv_buf)
{
free(recv_buf); free(recv_buf);
} }
}
} }
static void udp_recv_demo_thread(void* param) void UdpSocketRecvTask(int argc, char *argv[])
{
ETH_BSP_Config();
lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
sys_thread_new("udp_recv_demo", udp_recv_demo, NULL, LWIP_UDP_TASK_STACK, LWIP_UDP_TASK_PRIO);
}
void udp_socket_recv_run(int argc, char *argv[])
{ {
int result = 0; int result = 0;
pthread_t th_id; pthread_t th_id;
@ -127,24 +108,25 @@ void udp_socket_recv_run(int argc, char *argv[])
sscanf(argv[1], "%d.%d.%d.%d", &udp_socket_ip[0], &udp_socket_ip[1], &udp_socket_ip[2], &udp_socket_ip[3]); sscanf(argv[1], "%d.%d.%d.%d", &udp_socket_ip[0], &udp_socket_ip[1], &udp_socket_ip[2], &udp_socket_ip[3]);
} }
sys_thread_new("udp socket send", udp_recv_demo_thread, NULL, 4096, 15); lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
sys_thread_new("UdpSocketRecvTask", UdpSocketRecvTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
} }
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
UDPSocketRecv, udp_socket_recv_run, UDP recv echo); UDPSocketRecv, UdpSocketRecvTask, UDP recv echo);
static void udp_send_demo(void *arg) static void UdpSocketSendTask(void *arg)
{ {
int cnt = LWIP_DEMO_TIMES; int cnt = LWIP_DEMO_TIMES;
char send_str[128]; char send_str[128];
lw_print("udp_send_demo start.\n"); lw_print("UdpSocketSendTask start.\n");
int socket_fd = -1; int socket_fd = -1;
memset(send_str, 0, sizeof(send_str)); memset(send_str, 0, sizeof(send_str));
socket_fd = socket(AF_INET, SOCK_DGRAM, 0); socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_fd < 0) if(socket_fd < 0)
{ {
lw_print("Socket error\n"); lw_print("Socket error\n");
goto __exit; goto __exit;
@ -153,10 +135,10 @@ static void udp_send_demo(void *arg)
struct sockaddr_in udp_sock; struct sockaddr_in udp_sock;
udp_sock.sin_family = AF_INET; udp_sock.sin_family = AF_INET;
udp_sock.sin_port = htons(LWIP_TARGET_PORT); udp_sock.sin_port = htons(LWIP_TARGET_PORT);
udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_target[0],udp_target[1],udp_target[2],udp_target[3])); udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_target[0], udp_target[1], udp_target[2], udp_target[3]));
memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero)); memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero));
if (connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr))) if(connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr)))
{ {
lw_print("Unable to connect\n"); lw_print("Unable to connect\n");
goto __exit; goto __exit;
@ -174,7 +156,7 @@ static void udp_send_demo(void *arg)
} }
__exit: __exit:
if (socket_fd >= 0) if(socket_fd >= 0)
{ {
closesocket(socket_fd); closesocket(socket_fd);
} }
@ -182,14 +164,7 @@ __exit:
return; return;
} }
static void udp_send_demo_thread(void* param) void UdpSocketSendTest(int argc, char *argv[])
{
ETH_BSP_Config();
lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
sys_thread_new("udp_send_demo", udp_send_demo, NULL, LWIP_UDP_TASK_STACK, LWIP_UDP_TASK_PRIO);
}
void udp_socket_send_run(int argc, char *argv[])
{ {
int result = 0; int result = 0;
pthread_t th_id; pthread_t th_id;
@ -201,9 +176,10 @@ void udp_socket_send_run(int argc, char *argv[])
sscanf(argv[1], "%d.%d.%d.%d", &udp_socket_ip[0], &udp_socket_ip[1], &udp_socket_ip[2], &udp_socket_ip[3]); sscanf(argv[1], "%d.%d.%d.%d", &udp_socket_ip[0], &udp_socket_ip[1], &udp_socket_ip[2], &udp_socket_ip[3]);
} }
sys_thread_new("udp socket send", udp_send_demo_thread, NULL, 4096, 15); lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
sys_thread_new("UdpSocketSendTask", UdpSocketSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
} }
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
UDPSocketSend, udp_socket_send_run, UDP send echo); UDPSocketSend, UdpSocketSendTest, UDP send echo);

View File

@ -3,7 +3,7 @@ SRC_DIR :=
ifeq ($(CONFIG_RESOURCES_LWIP),y) ifeq ($(CONFIG_RESOURCES_LWIP),y)
ifeq ($(CONFIG_USING_CONTROL_PLC_OPCUA), y) ifeq ($(CONFIG_USING_CONTROL_PLC_OPCUA), y)
SRC_DIR += opcua_demo SRC_DIR += opcua_demo plc_demo
endif endif
endif endif

View File

@ -31,6 +31,8 @@
#define TCP_LOCAL_PORT 4840 #define TCP_LOCAL_PORT 4840
#define UA_URL_SIZE 100 #define UA_URL_SIZE 100
#define UA_STACK_SIZE 4096
#define UA_TASK_PRIO 15
/******************************************************************************* /*******************************************************************************
* Prototypes * Prototypes
@ -40,80 +42,71 @@
* Variables * Variables
******************************************************************************/ ******************************************************************************/
char test_ua_ip[] = {192, 168, 250, 5}; char test_ua_ip[] = {192, 168, 250, 2};
/******************************************************************************* /*******************************************************************************
* Code * Code
******************************************************************************/ ******************************************************************************/
static void test_ua_connect(void *arg) static void UaConnectTestTask(void* arg)
{ {
struct netif net; struct netif net;
UA_StatusCode retval; UA_StatusCode retval;
char ua_uri[UA_URL_SIZE]; char ua_uri[UA_URL_SIZE];
memset(ua_uri, 0, sizeof(ua_uri)); memset(ua_uri, 0, sizeof(ua_uri));
UA_Client* client = UA_Client_new();
UA_Client *client = UA_Client_new(); if(client == NULL)
if (client == NULL)
{ {
ua_print("ua: [%s] tcp client null\n", __func__); ua_print("ua: [%s] tcp client null\n", __func__);
return; return;
} }
UA_ClientConfig *config = UA_Client_getConfig(client); UA_ClientConfig* config = UA_Client_getConfig(client);
UA_ClientConfig_setDefault(config); UA_ClientConfig_setDefault(config);
snprintf(ua_uri, sizeof(ua_uri), "opc.tcp://%d.%d.%d.%d:4840",
snprintf(ua_uri, UA_URL_SIZE, "opc.tcp://%d.%d.%d.%d:4840",
test_ua_ip[0], test_ua_ip[1], test_ua_ip[2], test_ua_ip[3]); test_ua_ip[0], test_ua_ip[1], test_ua_ip[2], test_ua_ip[3]);
ua_pr_info("ua uri: %d %s\n", strlen(ua_uri), ua_uri);
retval = UA_Client_connect(client,ua_uri);
retval = UA_Client_connect(client, ua_uri); if(retval != UA_STATUSCODE_GOOD)
if (retval != UA_STATUSCODE_GOOD)
{ {
ua_print("ua: [%s] ret %x\n", __func__, retval); ua_pr_info("ua: [%s] connected failed %x\n", __func__, retval);
UA_Client_delete(client);
return;
} }
ua_print("ua: [%s] start Ua Test!\n", __func__); ua_pr_info("ua: [%s] connected ok!\n", __func__);
UA_Client_disconnect(client); UA_Client_disconnect(client);
UA_Client_delete(client); UA_Client_delete(client);
} }
void test_ua_connect_thr(void *arg) void UaConnectTest(void* arg)
{ {
ETH_BSP_Config();
lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip);
test_ua_connect(NULL); sys_thread_new("ua test", UaConnectTestTask, NULL, UA_STACK_SIZE, UA_TASK_PRIO);
}
void test_sh_ua_connect(void)
{
int result = 0;
pthread_t th_id;
pthread_attr_t attr;
sys_thread_new("ua test", test_ua_connect_thr, NULL, 4096, 15);
} }
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
UaConnect, test_sh_ua_connect, Test Opc UA connection); UaConnect, UaConnectTest, Test Opc UA connection);
void test_ua_browser_objects(void *param) void UaBrowserObjectsTestTask(void* param)
{ {
UA_Client *client = UA_Client_new(); UA_Client* client = UA_Client_new();
ua_pr_info("ua: [%s] start ...\n", __func__); ua_pr_info("ua: [%s] start ...\n", __func__);
if (client == NULL) if(client == NULL)
{ {
ua_print("ua: [%s] tcp client null\n", __func__); ua_print("ua: [%s] tcp client null\n", __func__);
return; return;
} }
UA_ClientConfig *config = UA_Client_getConfig(client); UA_ClientConfig* config = UA_Client_getConfig(client);
UA_ClientConfig_setDefault(config); UA_ClientConfig_setDefault(config);
UA_StatusCode retval = UA_Client_connect(client, opc_server_url);
UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER); if(retval != UA_STATUSCODE_GOOD)
if(retval != UA_STATUSCODE_GOOD) { {
ua_print("ua: [%s] connect failed %#x\n", __func__, retval); ua_print("ua: [%s] connect failed %#x\n", __func__, retval);
UA_Client_delete(client); UA_Client_delete(client);
return; return;
@ -121,18 +114,15 @@ void test_ua_browser_objects(void *param)
ua_print("ua: [%s] connect ok!\n", __func__); ua_print("ua: [%s] connect ok!\n", __func__);
ua_pr_info("--- start read time ---\n", __func__); ua_pr_info("--- start read time ---\n", __func__);
ua_read_time(client); ua_read_time(client);
ua_pr_info("--- get server info ---\n", __func__); ua_pr_info("--- get server info ---\n", __func__);
ua_browser_objects(client); ua_test_browser_objects(client);
/* Clean up */ /* Clean up */
UA_Client_disconnect(client); UA_Client_disconnect(client);
UA_Client_delete(client); /* Disconnects the client internally */ UA_Client_delete(client); /* Disconnects the client internally */
} }
void *test_sh_ua_brower_objects(int argc, char *argv[]) void* UaBrowserObjectsTest(int argc, char* argv[])
{ {
if(argc == 2) if(argc == 2)
{ {
@ -146,47 +136,45 @@ void *test_sh_ua_brower_objects(int argc, char *argv[])
} }
} }
ETH_BSP_Config();
lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip);
sys_thread_new("ua object", test_ua_browser_objects, NULL, 4096, 15); sys_thread_new("ua object", UaBrowserObjectsTestTask, NULL, UA_STACK_SIZE, UA_TASK_PRIO);
return NULL; return NULL;
} }
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
UaObj, test_sh_ua_brower_objects, UaObj [IP]); UaObj, UaBrowserObjectsTest, UaObj [IP]);
void test_ua_get_info(void *param) void UaGetInfoTestTask(void* param)
{ {
UA_Client *client = UA_Client_new(); UA_Client* client = UA_Client_new();
ua_pr_info("ua: [%s] start ...\n", __func__); ua_pr_info("ua: [%s] start ...\n", __func__);
if (client == NULL) if(client == NULL)
{ {
ua_print("ua: [%s] tcp client null\n", __func__); ua_print("ua: [%s] tcp client null\n", __func__);
return; return;
} }
UA_ClientConfig *config = UA_Client_getConfig(client); UA_ClientConfig* config = UA_Client_getConfig(client);
UA_ClientConfig_setDefault(config); UA_ClientConfig_setDefault(config);
UA_StatusCode retval = UA_Client_connect(client, opc_server_url);
UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER); if(retval != UA_STATUSCODE_GOOD)
if(retval != UA_STATUSCODE_GOOD) { {
ua_print("ua: [%s] connect failed %#x\n", __func__, retval); ua_print("ua: [%s] connect failed %#x\n", __func__, retval);
UA_Client_delete(client); UA_Client_delete(client);
return; return;
} }
ua_print("ua: [%s] connect ok!\n", __func__); ua_print("ua: [%s] connect ok!\n", __func__);
ua_pr_info("--- get server info ---\n", __func__); ua_pr_info("--- interactive server ---\n", __func__);
ua_get_server_info(client); ua_test_interact_server(client);
/* Clean up */ /* Clean up */
UA_Client_disconnect(client); UA_Client_disconnect(client);
UA_Client_delete(client); /* Disconnects the client internally */ UA_Client_delete(client); /* Disconnects the client internally */
} }
void *test_sh_ua_get_info(int argc, char *argv[]) void* UaGetInfoTest(int argc, char* argv[])
{ {
if(argc == 2) if(argc == 2)
{ {
@ -200,12 +188,63 @@ void *test_sh_ua_get_info(int argc, char *argv[])
} }
} }
ETH_BSP_Config();
lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip);
sys_thread_new("ua object", test_ua_browser_objects, NULL, 4096, 15); sys_thread_new("ua info", UaGetInfoTestTask, NULL, UA_STACK_SIZE, UA_TASK_PRIO);
return NULL; return NULL;
} }
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
UaInfo, test_sh_ua_get_info, UaInfo [IP]); UaInfo, UaGetInfoTest, UaInfo [IP]);
void UaAddNodesTask(void* param)
{
UA_Client* client = UA_Client_new();
ua_pr_info("ua: [%s] start ...\n", __func__);
if(client == NULL)
{
ua_print("ua: [%s] tcp client null\n", __func__);
return;
}
UA_ClientConfig* config = UA_Client_getConfig(client);
UA_ClientConfig_setDefault(config);
UA_StatusCode retval = UA_Client_connect(client, opc_server_url);
if(retval != UA_STATUSCODE_GOOD)
{
ua_print("ua: [%s] connect failed %#x\n", __func__, retval);
UA_Client_delete(client);
return;
}
ua_print("ua: [%s] connect ok!\n", __func__);
ua_pr_info("--- add nodes ---\n", __func__);
ua_add_nodes(client);
/* Clean up */
UA_Client_disconnect(client);
UA_Client_delete(client); /* Disconnects the client internally */
}
void* UaAddNodesTest(int argc, char* argv[])
{
if(argc == 2)
{
if(isdigit(argv[1][0]))
{
if(sscanf(argv[1], "%d.%d.%d.%d", &test_ua_ip[0], &test_ua_ip[1], &test_ua_ip[2], &test_ua_ip[3]) == EOF)
{
lw_pr_info("input wrong ip\n");
return NULL;
}
}
}
lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip);
sys_thread_new("ua add nodes", UaAddNodesTask, NULL, UA_STACK_SIZE, UA_TASK_PRIO);
return NULL;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
UaAdd, UaAddNodesTest, UA Add Nodes);

View File

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

View File

@ -0,0 +1,221 @@
/*
* Copyright (c) 2022 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 plc_control_demo.c
* @brief Demo for PLC control
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022.2.22
*/
#include "transform.h"
#include "open62541.h"
#include "ua_api.h"
#include "sys_arch.h"
#include "plc_demo.h"
#define PLC_NS_FORMAT "n%d,%s"
struct PlcChannel plc_demo_ch;
struct PlcDriver plc_demo_drv;
struct PlcDevice plc_demo_dev;
PlcCtrlParamType plc_ctrl_param;
UA_NodeId test_nodeid = {4, UA_NODEIDTYPE_NUMERIC, 5};
/******************************************************************************/
void PlcDemoChannelDrvInit(void)
{
static uint8_t init_flag = 0;
if(init_flag)
return;
init_flag = 1;
lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip);
PlcChannelInit(&plc_demo_ch, PLC_CH_NAME);
if(PlcDriverInit(&plc_demo_drv, PLC_DRV_NAME) == EOK)
{
PlcDriverAttachToChannel(PLC_DRV_NAME, PLC_CH_NAME);
}
memset(&plc_demo_dev, 0, sizeof(plc_demo_dev));
}
static void PlcCtrlDemoInit(void)
{
static uint8_t init_flag = 0;
PlcDemoChannelDrvInit();
// register plc device
plc_demo_dev.state = CHDEV_INIT;
strcpy(plc_demo_dev.name, "UA Demo");
plc_demo_dev.info.product = "CPU 1215C";
plc_demo_dev.info.vendor = "SIEMENS";
plc_demo_dev.info.model = "S7-1200";
plc_demo_dev.info.id = 123;
plc_demo_dev.net = PLC_IND_ENET_OPCUA;
// register UA parameter
if(!plc_demo_dev.priv_data)
{
plc_demo_dev.priv_data = (UaParamType*)malloc(sizeof(UaParamType));
}
UaParamType* ua_ptr = plc_demo_dev.priv_data;
memset(ua_ptr, 0, sizeof(UaParamType));
strcpy(ua_ptr->ua_remote_ip, opc_server_url);
ua_ptr->act = UA_ACT_ATTR;
memcpy(&ua_ptr->ua_id, &test_nodeid, sizeof(test_nodeid));
if(init_flag)
return;
init_flag = 1;
if(PlcDevRegister(&plc_demo_dev, NULL, plc_demo_dev.name) != EOK)
{
return;
}
PlcDeviceAttachToChannel(plc_demo_dev.name, PLC_CH_NAME);
}
void PlcReadUATask(void* arg)
{
int ret = 0;
struct PlcOps* ops = NULL;
char buf[PLC_BUF_SIZE];
memset(buf, 0, sizeof(buf));
PlcCtrlDemoInit();
ops = plc_demo_dev.ops;
ret = ops->open(&plc_demo_dev);
if(EOK != ret)
{
plc_print("plc: [%s] open failed %#x\n", __func__, ret);
// free(plc_demo_dev.priv_data);
// plc_demo_dev.priv_data = NULL;
return;
}
ret = ops->read(&plc_demo_dev, buf, PLC_BUF_SIZE);
if(EOK != ret)
{
plc_print("plc: [%s] read failed %x\n", __func__, ret);
}
ops->close(&plc_demo_dev);
}
void PlcReadTest(int argc, char* argv[])
{
static char node_str[UA_NODE_LEN];
memset(node_str, 0, sizeof(node_str));
if(argc > 1)
{
plc_print("plc: arg %s\n", argv[1]);
if(sscanf(argv[1], PLC_NS_FORMAT, &test_nodeid.namespaceIndex, node_str) != EOF)
{
if(isdigit(node_str[0]))
{
test_nodeid.identifierType = UA_NODEIDTYPE_NUMERIC;
test_nodeid.identifier.numeric = atoi(node_str);
plc_print("ns %d num %d\n", test_nodeid.namespaceIndex, test_nodeid.identifier.numeric);
}
else
{
test_nodeid.identifierType = UA_NODEIDTYPE_STRING;
test_nodeid.identifier.string.length = strlen(node_str);
test_nodeid.identifier.string.data = node_str;
plc_print("ns %d str %s\n", test_nodeid.namespaceIndex, test_nodeid.identifier.string.data);
}
}
}
sys_thread_new("plc read", PlcReadUATask, NULL, PLC_STACK_SIZE, PLC_TASK_PRIO);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
PlcRead, PlcReadTest, Read PLC);
void PlcWriteUATask(void* arg)
{
int ret = 0;
struct PlcOps* ops = NULL;
char buf[PLC_BUF_SIZE];
memset(buf, 0, sizeof(buf));
PlcCtrlDemoInit();
ops = plc_demo_dev.ops;
ret = ops->open(&plc_demo_dev);
if(EOK != ret)
{
plc_print("plc: [%s] open failed %#x\n", __func__, ret);
// free(plc_demo_dev.priv_data);
// plc_demo_dev.priv_data = NULL;
return;
}
ret = ops->write(&plc_demo_dev, arg, PLC_BUF_SIZE);
if(EOK != ret)
{
plc_print("plc: [%s] read failed\n", __func__);
}
ops->close(&plc_demo_dev);
}
void PlcWriteTest(int argc, char* argv[])
{
static char node_str[UA_NODE_LEN];
static char val_param[UA_NODE_LEN];
memset(node_str, 0, sizeof(node_str));
memset(val_param, 0, sizeof(val_param));
if(argc > 1)
{
plc_print("plc: arg %s\n", argv[1]);
if(sscanf(argv[1], PLC_NS_FORMAT, &test_nodeid.namespaceIndex, node_str) != EOF)
{
if(isdigit(node_str[0]))
{
test_nodeid.identifierType = UA_NODEIDTYPE_NUMERIC;
test_nodeid.identifier.numeric = atoi(node_str);
plc_print("ns %d num %d\n", test_nodeid.namespaceIndex, test_nodeid.identifier.numeric);
}
else
{
test_nodeid.identifierType = UA_NODEIDTYPE_STRING;
test_nodeid.identifier.string.length = strlen(node_str);
test_nodeid.identifier.string.data = node_str;
plc_print("ns %d str %s\n", test_nodeid.namespaceIndex, test_nodeid.identifier.string.data);
}
}
if(argc > 2)
{
strcpy(val_param, argv[2]);
plc_print("write value %s\n", val_param);
}
}
sys_thread_new("plc write", PlcWriteUATask, val_param, PLC_STACK_SIZE, PLC_TASK_PRIO);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
PlcWrite, PlcWriteTest, Read PLC);

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2022 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 plc_show_demo.c
* @brief Demo for PLC information show
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022.02.24
*/
#ifndef __PLC_DEMO_H_
#define __PLC_DEMO_H_
#include "plc_channel.h"
#include "plc_device.h"
#define PLC_CH_NAME "PLC"
#define PLC_DRV_NAME "OPCUA"
#define PLC_BUF_SIZE 128
#define PLC_STACK_SIZE 4096
#define PLC_TASK_PRIO 15
extern struct PlcChannel plc_demo_ch;
extern struct PlcDriver plc_demo_drv;
extern struct PlcDevice plc_demo_dev;
void PlcDemoChannelDrvInit(void);
#endif

View File

@ -0,0 +1,257 @@
/*
* Copyright (c) 2022 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 plc_show_demo.c
* @brief Demo for PLC information show
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022.02.24
*/
#include "transform.h"
#include "list.h"
#include "open62541.h"
#include "ua_api.h"
#include "sys_arch.h"
#include "plc_demo.h"
#define PLC_DEMO_NUM 5
struct PlcDevice plc_demo_array[PLC_DEMO_NUM];
typedef struct PlcShowParam
{
int id;
char* vector;
char* model;
char* product;
} PlcShowParamType;
PlcShowParamType plc_demo_param[PLC_NAME_SIZE] =
{
{1, "SIEMENS", "S7-1500", "CPU 1512SP-1PN"},
{2, "SIEMENS", "S7-1200", "CPU 1215C"},
{3, "SIEMSNS", "S7-200", "CPU SR60"},
{4, "B&R", "X20", "X20 CP1586"},
{5, "B&R", "X20", "X20 CP1381"}
};
static char* const channel_type_str[] =
{
"PLC_Channel",
"Unknown"
};
extern DoublelistType plcdev_list;
extern DoublelistType ch_linklist;
/**********************************************************************************************************************/
void PlcShowTitle(const char* item_array[])
{
int i = 0, max_len = 65;
KPrintf(" %-15s%-15s%-15s%-15s%-20s\n", item_array[0], item_array[1], item_array[2], item_array[3], item_array[4]);
while(i < max_len)
{
i++;
if(max_len == i)
{
KPrintf("-\n");
}
else
{
KPrintf("-");
}
}
}
static ChDrvType ShowChannelFindDriver(struct Channel* ch)
{
struct ChDrv* driver = NONE;
DoublelistType* node = NONE;
DoublelistType* head = &ch->ch_drvlink;
for(node = head->node_next; node != head; node = node->node_next)
{
driver = DOUBLE_LIST_ENTRY(node, struct ChDrv, driver_link);
return driver;
}
return NONE;
}
static void PlcShowDemoInit(void)
{
static uint8_t init_flag = 0;
int i;
PlcDemoChannelDrvInit();
for(i = 0; i < PLC_DEMO_NUM; i++)
{
// register plc device
plc_demo_array[i].state = CHDEV_INIT;
snprintf(plc_demo_array[i].name, PLC_NAME_SIZE, "PLC Demo %d", i);
plc_demo_array[i].info.vendor = plc_demo_param[i].vector;
plc_demo_array[i].info.model = plc_demo_param[i].model;
plc_demo_array[i].info.id = plc_demo_param[i].id;
plc_demo_array[i].info.product = plc_demo_param[i].product;
plc_demo_array[i].net = PLC_IND_ENET_OPCUA;
}
if(init_flag)
return;
init_flag = 1;
for(i = 0; i < PLC_DEMO_NUM; i++)
{
if(PlcDevRegister(&plc_demo_array[i], NULL, plc_demo_array[i].name) == EOK)
{
PlcDeviceAttachToChannel(plc_demo_array[i].name, PLC_CH_NAME);
}
}
}
void PlcShowChannel(void)
{
ChannelType ch;
ChDrvType driver;
ChDevType device;
int dev_cnt;
DoublelistType* ch_node = NONE;
DoublelistType* ch_head = &ch_linklist;
const char* item_array[] = {"ch_type", "ch_name", "drv_name", "dev_name", "cnt"};
PlcShowDemoInit();
PlcShowTitle(item_array);
ch_node = ch_head->node_next;
do
{
ch = DOUBLE_LIST_ENTRY(ch_node, struct Channel, ch_link);
if((ch) && (ch->ch_type == CH_PLC_TYPE))
{
KPrintf("%s", " ");
KPrintf("%-15s%-15s",
channel_type_str[ch->ch_type],
ch->ch_name);
driver = ShowChannelFindDriver(ch);
if(driver)
{
KPrintf("%-15s", driver->drv_name);
}
else
{
KPrintf("%-15s", "nil");
}
if(ch->haldev_cnt)
{
DoublelistType* dev_node = NONE;
DoublelistType* dev_head = &ch->ch_devlink;
dev_node = dev_head->node_next;
dev_cnt = 1;
while(dev_node != dev_head)
{
device = DOUBLE_LIST_ENTRY(dev_node, struct ChDev, dev_link);
if(1 == dev_cnt)
{
if(device)
{
KPrintf("%-16s%-4d\n", device->dev_name, dev_cnt);
}
else
{
KPrintf("%-16s%-4d\n", "nil", dev_cnt);
}
}
else
{
KPrintf("%46s", " ");
if(device)
{
KPrintf("%-16s%-4d\n", device->dev_name, dev_cnt);
}
else
{
KPrintf("%-16s%-4d\n", "nil", dev_cnt);
}
}
dev_cnt++;
dev_node = dev_node->node_next;
}
}
else
{
KPrintf("\n");
}
}
ch_node = ch_node->node_next;
}
while(ch_node != ch_head);
return;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
ShowChannel, PlcShowChannel, Show PLC information);
void PlcShowDev(void)
{
PlcDeviceType* plc_dev;
ChDrvType driver;
ChDevType device;
DoublelistType* plc_node = NONE;
DoublelistType* plc_head = &plcdev_list;
const char* item_array[] = {"device", "vendor", "model", "product", "id"};
PlcShowDemoInit();
PlcShowTitle(item_array);
plc_node = plc_head->node_next;
do
{
plc_dev = DOUBLE_LIST_ENTRY(plc_node, struct PlcDevice, link);
if(plc_dev)
{
KPrintf("%s", " ");
KPrintf("%-15s%-15s%-15s%-15s%-20d",
plc_dev->name,
plc_dev->info.vendor,
plc_dev->info.model,
plc_dev->info.product,
plc_dev->info.id);
KPrintf("\n");
}
plc_node = plc_node->node_next;
}
while(plc_node != plc_head);
return;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
ShowPlc, PlcShowDev, Show PLC information);

View File

@ -1,3 +1,3 @@
SRC_FILES := ua_data.c open62541.c ua_client.c ua_server.c SRC_FILES := ua_data.c open62541.c ua_client.c ua_server.c ua_api.c ua_test.c
include $(KERNEL_ROOT)/compiler.mk include $(KERNEL_ROOT)/compiler.mk

View File

@ -15,18 +15,6 @@
* A PARTICULAR PURPOSE. * A PARTICULAR PURPOSE.
*/ */
/*
* Copyright (c) 2021 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 open62541.c * @file open62541.c
* @brief Support OPCUA protocol * @brief Support OPCUA protocol
@ -44256,7 +44244,7 @@ UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) {
client->sessionState < UA_SESSIONSTATE_ACTIVATED) { client->sessionState < UA_SESSIONSTATE_ACTIVATED) {
retval = connectIterate(client, timeout); retval = connectIterate(client, timeout);
notifyClientState(client); notifyClientState(client);
lw_print("lw: [%s] ret %d timeout %d state %d ch %d\n", __func__, retval, timeout, ua_print("lw: [%s] ret %d timeout %d state %d ch %d\n", __func__, retval, timeout,
client->sessionState, client->channel.state); client->sessionState, client->channel.state);
return retval; return retval;
} }
@ -45299,7 +45287,7 @@ connectIterate(UA_Client *client, UA_UInt32 timeout) {
break; break;
} }
lw_print("lw: [%s] sess %d conn %d\n", __func__, client->sessionState, client->connectStatus); ua_print("ua: [%s] sess %d conn %d\n", __func__, client->sessionState, client->connectStatus);
return client->connectStatus; return client->connectStatus;
} }

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2021 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 ua_api.c
* @brief Demo for OpcUa function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#include "open62541.h"
#include <stdlib.h>
#include "ua_api.h"
int ua_open(void *dev)
{
UaParamType *param = (UaParamType *)dev;
param->client = UA_Client_new();
ua_pr_info("ua: [%s] start ...\n", __func__);
if (param->client == NULL)
{
ua_print("ua: [%s] tcp client null\n", __func__);
return EEMPTY;
}
UA_ClientConfig *config = UA_Client_getConfig(param->client);
UA_ClientConfig_setDefault(config);
ua_pr_info("ua: [%s] %d %s\n", __func__, strlen(param->ua_remote_ip), param->ua_remote_ip);
UA_StatusCode retval = UA_Client_connect(param->client, param->ua_remote_ip);
if(retval != UA_STATUSCODE_GOOD) {
ua_pr_info("ua: [%s] deleted ret %x!\n", __func__, retval);
return (int)retval;
}
return EOK;
}
void ua_close(void *dev)
{
UaParamType *param = (UaParamType *)dev;
UA_Client_disconnect(param->client);
UA_Client_delete(param->client); /* Disconnects the client internally */
}
int ua_read(void *dev, void *buf, size_t len)
{
UaParamType *param = (UaParamType *)dev;
switch(param->act)
{
case UA_ACT_ATTR:
ua_read_nodeid_value(param->client, param->ua_id, buf);
break;
case UA_ACT_OBJ:
ua_test_browser_objects(param->client);
break;
default:
break;
}
return EOK;
}
int ua_write(void *dev, const void *buf, size_t len)
{
UaParamType *param = (UaParamType *)dev;
switch(param->act)
{
case UA_ACT_ATTR:
ua_write_nodeid_value(param->client, param->ua_id, (char *)buf);
break;
case UA_ACT_OBJ:
ua_test_browser_objects(param->client);
break;
default:
break;
}
return EOK;
}
int ua_ioctl(void *dev, int cmd, void *arg)
{
return EOK;
}

View File

@ -9,23 +9,64 @@
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details. * See the Mulan PSL v2 for more details.
*/ */
/**
* @file ua_api.h
* @brief API for OpcUa function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#ifndef __UA_API_H__ #ifndef __UA_API_H__
#define __UA_API_H__ #define __UA_API_H__
#include "open62541.h" #include "open62541.h"
#define OPC_SERVER "opc.tcp://192.168.250.5:4840" #define UA_DEV_IP_LEN 48
#define UA_NODE_LEN 32
#define ua_print //printf enum UaAction_e
#define ua_trace() //printf("ua: [%s] line %d checked!\n", __func__, __LINE__) {
UA_ACT_ATTR,
UA_ACT_OBJ,
};
typedef struct UaParam
{
enum UaAction_e act;
UA_NodeId ua_id;
char ua_remote_ip[UA_DEV_IP_LEN];
char ua_node[UA_NODE_LEN];
UA_Client *client;
}UaParamType;
#define ua_print //KPrintf
#define ua_trace() //KPrintf("ua: [%s] line %d checked!\n", __func__, __LINE__)
#define ua_pr_info KPrintf #define ua_pr_info KPrintf
#define ua_debug #define ua_debug //KPrintf
extern const char *opc_server_url;
extern char test_ua_ip[];
int ua_server_connect(void); int ua_server_connect(void);
int ua_get_server_info(UA_Client *client);
void ua_browser_objects(UA_Client *client);
void ua_browser_nodes(UA_Client *client); void ua_browser_nodes(UA_Client *client);
void ua_browser_id(UA_Client *client, UA_NodeId id);
void ua_read_time(UA_Client *client); void ua_read_time(UA_Client *client);
int16 ua_test(void); void ua_add_nodes(UA_Client *client);
int ua_open(void *dev); // open and connect PLC device
void ua_close(void* dev); // close and disconnect PLC device
int ua_read(void* dev, void *buf, size_t len); // read data from PLC
int ua_write(void* dev, const void *buf, size_t len); // write data from PLC
int ua_ioctl(void* dev, int cmd, void *arg); // send control command to PLC
char *ua_get_nodeid_str(UA_NodeId *node_id);
void ua_read_nodeid_value(UA_Client *client, UA_NodeId id, UA_Int32 *value);
void ua_write_nodeid_value(UA_Client *client, UA_NodeId id, char* value);
void ua_test_attr(UA_Client *client);
UA_StatusCode ua_read_array_value(UA_Client *client, int array_size, UA_ReadValueId *array);
void ua_test_browser_objects(UA_Client *client);
int ua_test_interact_server(UA_Client *client);
#endif #endif

View File

@ -10,81 +10,164 @@
* See the Mulan PSL v2 for more details. * See the Mulan PSL v2 for more details.
*/ */
#include "open62541.h" /**
* @file ua_client.c
* @brief Client for OpcUa function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#include <stdlib.h> #include <stdlib.h>
#include "open62541.h"
#include "ua_api.h" #include "ua_api.h"
#define UA_RESPONSE_TIMEOUT 10000
const char *opc_server_url = {"opc.tcp://192.168.250.2:4840"};
#ifdef UA_ENABLE_SUBSCRIPTIONS #ifdef UA_ENABLE_SUBSCRIPTIONS
static void handler_TheAnswerChanged(UA_Client *client, UA_UInt32 subId, void *subContext, static void handler_TheAnswerChanged(UA_Client* client, UA_UInt32 subId, void* subContext,
UA_UInt32 monId, void *monContext, UA_DataValue *value) UA_UInt32 monId, void* monContext, UA_DataValue* value)
{ {
ua_print("The Answer has changed!\n"); ua_print("The Answer has changed!\n");
} }
#endif #endif
static UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle) static UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void* handle)
{ {
if(isInverse) if(isInverse)
{ {
return UA_STATUSCODE_GOOD; return UA_STATUSCODE_GOOD;
} }
UA_NodeId *parent = (UA_NodeId *)handle; UA_NodeId* parent = (UA_NodeId*)handle;
ua_pr_info("%d, %d --- %d ---> NodeId %d, %d\n", ua_pr_info("%d, %d --- %d ---> NodeId %d, %d\n",
parent->namespaceIndex, parent->identifier.numeric, parent->namespaceIndex, parent->identifier.numeric,
referenceTypeId.identifier.numeric, childId.namespaceIndex, referenceTypeId.identifier.numeric, childId.namespaceIndex,
childId.identifier.numeric); childId.identifier.numeric);
return UA_STATUSCODE_GOOD; return UA_STATUSCODE_GOOD;
} }
int ua_get_points(UA_Client *client) int ua_get_points(UA_Client* client)
{ {
/* Listing endpoints */ /* Listing endpoints */
UA_EndpointDescription* endpointArray = NULL; UA_EndpointDescription* endpointArray = NULL;
size_t endpointArraySize = 0; size_t endpointArraySize = 0;
UA_StatusCode retval = UA_Client_getEndpoints(client, OPC_SERVER, UA_StatusCode ret = UA_Client_getEndpoints(client, opc_server_url,
&endpointArraySize, &endpointArray); &endpointArraySize, &endpointArray);
if(retval != UA_STATUSCODE_GOOD)
if(ret != UA_STATUSCODE_GOOD)
{ {
UA_Array_delete(endpointArray, endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); UA_Array_delete(endpointArray, endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
ua_print("%i endpoints found\n", (int)endpointArraySize); ua_print("%i endpoints found\n", (int)endpointArraySize);
for(size_t i=0;i<endpointArraySize;i++)
for(size_t i=0; i<endpointArraySize; i++)
{ {
ua_print("URL of endpoint %i is %.*s\n", (int)i, ua_print("URL of endpoint %i is %.*s\n", (int)i,
(int)endpointArray[i].endpointUrl.length, (int)endpointArray[i].endpointUrl.length,
endpointArray[i].endpointUrl.data); endpointArray[i].endpointUrl.data);
} }
UA_Array_delete(endpointArray,endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); UA_Array_delete(endpointArray,endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void ua_browser_objects(UA_Client *client) void ua_print_value(UA_Variant* val)
{ {
/* Browse some objects */ if(val->type == &UA_TYPES[UA_TYPES_LOCALIZEDTEXT])
ua_pr_info("Browsing nodes in objects folder:\n"); {
UA_LocalizedText* ptr = (UA_LocalizedText*)val->data;
ua_pr_info("%.*s (Text)\n", ptr->text.length, ptr->text.data);
}
else if(val->type == &UA_TYPES[UA_TYPES_UINT32])
{
UA_UInt32* ptr = (UA_UInt32*)val->data;
ua_pr_info("%d (UInt32)\n", *ptr);
}
else if(val->type == &UA_TYPES[UA_TYPES_BOOLEAN])
{
UA_Boolean* ptr = (UA_Boolean*)val->data;
ua_pr_info("%i (BOOL)\n", *ptr);
}
else if(val->type == &UA_TYPES[UA_TYPES_INT32])
{
UA_Int32* ptr = (UA_Int32*)val->data;
ua_pr_info("%d (Int32)\n", *ptr);
}
else if(val->type == &UA_TYPES[UA_TYPES_INT16])
{
UA_Int16* ptr = (UA_Int16*)val->data;
ua_pr_info("%d (Int16)\n", *ptr);
}
else if(val->type == &UA_TYPES[UA_TYPES_STRING])
{
UA_String* ptr = (UA_String*)val->data;
ua_pr_info("%*.s (String)\n", ptr->length, ptr->data);
}
else if(val->type == &UA_TYPES[UA_TYPES_DATETIME])
{
UA_DateTime* ptr = (UA_DateTime*)val->data;
UA_DateTimeStruct dts = UA_DateTime_toStruct(*ptr);
ua_pr_info("%d-%d-%d %d:%d:%d.%03d (Time)\n",
dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
}
}
UA_BrowseRequest bReq; char *ua_get_nodeid_str(UA_NodeId *node_id)
UA_BrowseRequest_init(&bReq); {
static char nodeid_str[UA_NODE_LEN] = {0};
bReq.requestedMaxReferencesPerNode = 0; switch(node_id->identifierType)
bReq.nodesToBrowse = UA_BrowseDescription_new(); {
bReq.nodesToBrowseSize = 1; case UA_NODEIDTYPE_NUMERIC:
bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); /* browse objects folder */ snprintf(nodeid_str, UA_NODE_LEN, "n%d,%d", node_id->namespaceIndex, node_id->identifier.numeric);
bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; /* return everything */ break;
case UA_NODEIDTYPE_STRING:
snprintf(nodeid_str, UA_NODE_LEN, "n%d,%.*s", node_id->namespaceIndex, node_id->identifier.string.length,
node_id->identifier.string.data);
break;
case UA_NODEIDTYPE_BYTESTRING:
snprintf(nodeid_str, UA_NODE_LEN, "n%d,%s", node_id->namespaceIndex, node_id->identifier.byteString.data);
break;
default:
break;
}
return nodeid_str;
}
UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq); void ua_print_nodeid(UA_NodeId *node_id)
{
switch(node_id->identifierType)
{
case UA_NODEIDTYPE_NUMERIC:
ua_pr_info(" NodeID n%d,%d ", node_id->namespaceIndex, node_id->identifier.numeric);
break;
case UA_NODEIDTYPE_STRING:
ua_pr_info(" NodeID n%d,%.*s ", node_id->namespaceIndex, node_id->identifier.string.length,
node_id->identifier.string.data);
break;
case UA_NODEIDTYPE_BYTESTRING:
ua_pr_info(" NodeID n%d,%s ", node_id->namespaceIndex, node_id->identifier.byteString.data);
break;
default:
break;
}
}
void ua_print_object(UA_BrowseResponse* res)
{
ua_pr_info("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME"); ua_pr_info("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME");
for(size_t i = 0; i < bResp.resultsSize; ++i) for(size_t i = 0; i < res->resultsSize; ++i)
{ {
for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) for(size_t j = 0; j < res->results[i].referencesSize; ++j)
{ {
UA_ReferenceDescription *ref = &(bResp.results[i].references[j]); UA_ReferenceDescription* ref = &(res->results[i].references[j]);
if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC) if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC)
{ {
ua_pr_info("%-9d %-16d %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex, ua_pr_info("%-9d %-16d %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
@ -100,95 +183,194 @@ void ua_browser_objects(UA_Client *client)
(int)ref->browseName.name.length, ref->browseName.name.data, (int)ref->browseName.name.length, ref->browseName.name.data,
(int)ref->displayName.text.length, ref->displayName.text.data); (int)ref->displayName.text.length, ref->displayName.text.data);
} }
/* TODO: distinguish further types */ /* TODO: distinguish further types */
} }
} }
ua_pr_info("\n"); ua_pr_info("\n");
UA_BrowseRequest_clear(&bReq);
UA_BrowseResponse_clear(&bResp);
} }
void ua_browser_nodes(UA_Client *client) UA_StatusCode ua_read_array_value(UA_Client* client, int array_size, UA_ReadValueId* array)
{ {
/* Same thing, this time using the node iterator... */ UA_ReadRequest request;
UA_NodeId *parent = UA_NodeId_new(); UA_ReadRequest_init(&request);
request.nodesToRead = array;
request.nodesToReadSize = array_size;
UA_ReadResponse response = UA_Client_Service_read(client, request);
if((response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
|| (response.resultsSize != array_size))
{
UA_ReadResponse_clear(&response);
ua_pr_info("ua: [%s] read failed 0x%x\n", __func__,
response.responseHeader.serviceResult);
return UA_STATUSCODE_BADUNEXPECTEDERROR;
}
UA_StatusCode* arr_ret = malloc(array_size * sizeof(UA_StatusCode));
for(int i = 0; i < array_size; ++i)
{
if((response.results[i].status == UA_STATUSCODE_GOOD)
&& (response.results[i].hasValue))
{
ua_pr_info("node %s: ", ua_get_nodeid_str(&array[i].nodeId));
ua_print_value(&response.results[i].value);
}
}
ua_pr_info("\n");
free(arr_ret);
UA_ReadResponse_clear(&response);
return UA_STATUSCODE_GOOD;
}
void ua_browser_id(UA_Client* client, UA_NodeId id)
{
/* Browse some objects */
ua_pr_info("Browsing nodes in objects folder:\n");
UA_BrowseRequest bReq;
UA_BrowseRequest_init(&bReq);
bReq.requestedMaxReferencesPerNode = 0;
bReq.nodesToBrowse = UA_BrowseDescription_new();
bReq.nodesToBrowseSize = 1;
bReq.nodesToBrowse[0].nodeId = id; /* browse objects folder */
bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; /* return everything */
UA_BrowseResponse res = UA_Client_Service_browse(client, bReq);
ua_print_object(&res);
UA_BrowseResponse_clear(&res);
// UA_BrowseRequest_clear(&bReq);
}
void ua_browser_nodes(UA_Client* client)
{
UA_NodeId* parent = UA_NodeId_new();
*parent = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); *parent = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIter, (void*) parent);
nodeIter, (void *) parent);
UA_NodeId_delete(parent); UA_NodeId_delete(parent);
} }
UA_UInt32 ua_start_sub(UA_Client *client) UA_UInt32 ua_start_sub(UA_Client* client, UA_NodeId node_id)
{ {
/* Create a subscription */ /* Create a subscription */
UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default(); UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default();
UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create(client, request, UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create(client, request,
NULL, NULL, NULL); NULL, NULL, NULL);
UA_UInt32 subId = response.subscriptionId; UA_UInt32 subId = response.subscriptionId;
if(response.responseHeader.serviceResult == UA_STATUSCODE_GOOD) if(response.responseHeader.serviceResult == UA_STATUSCODE_GOOD)
{
ua_print("Create subscription succeeded, id %u\n", subId); ua_print("Create subscription succeeded, id %u\n", subId);
}
else
{
ua_print("Create subscription failed, id %u\n", response.responseHeader.serviceResult);
return response.responseHeader.serviceResult;
}
UA_MonitoredItemCreateRequest monRequest = UA_MonitoredItemCreateRequest monRequest =
UA_MonitoredItemCreateRequest_default(UA_NODEID_STRING(1, "the.answer")); UA_MonitoredItemCreateRequest_default(node_id);
UA_MonitoredItemCreateResult monResponse = UA_MonitoredItemCreateResult monResponse =
UA_Client_MonitoredItems_createDataChange(client, response.subscriptionId, UA_Client_MonitoredItems_createDataChange(client, response.subscriptionId,
UA_TIMESTAMPSTORETURN_BOTH, UA_TIMESTAMPSTORETURN_BOTH,
monRequest, NULL, handler_TheAnswerChanged, NULL); monRequest, NULL, handler_TheAnswerChanged, NULL);
if(monResponse.statusCode == UA_STATUSCODE_GOOD)
ua_print("Monitoring 'the.answer', id %u\n", monResponse.monitoredItemId);
if(monResponse.statusCode == UA_STATUSCODE_GOOD)
{
ua_print("Monitoring 'the.answer', id %u\n", monResponse.monitoredItemId);
}
else
{
ua_print("%s return 0x%x\n", __func__, monResponse.statusCode);
}
/* The first publish request should return the initial value of the variable */ /* The first publish request should return the initial value of the variable */
UA_Client_run_iterate(client, 1000); UA_Client_run_iterate(client, UA_RESPONSE_TIMEOUT);
return subId; return subId;
} }
void ua_read_attr(UA_Client *client) void ua_write_nodeid_value(UA_Client* client, UA_NodeId id, char* value)
{ {
/* Read attribute */ UA_Boolean bool_val;
UA_Int32 value = 0; uint32_t integer_val;
ua_print("\nReading the value of node (1, \"the.answer\"):\n");
UA_Variant *val = UA_Variant_new();
UA_StatusCode retval = UA_Client_readValueAttribute(client, UA_NODEID_STRING(1, "the.answer"), val);
if(retval == UA_STATUSCODE_GOOD && UA_Variant_isScalar(val) &&
val->type == &UA_TYPES[UA_TYPES_INT32]) {
value = *(UA_Int32*)val->data;
ua_print("the value is: %i\n", value);
}
UA_Variant_delete(val);
/* Write node attribute */
value++;
ua_print("\nWriting a value of node (1, \"the.answer\"):\n");
UA_WriteRequest wReq; UA_WriteRequest wReq;
UA_WriteRequest_init(&wReq); UA_WriteRequest_init(&wReq);
wReq.nodesToWrite = UA_WriteValue_new(); wReq.nodesToWrite = UA_WriteValue_new();
wReq.nodesToWriteSize = 1; wReq.nodesToWriteSize = 1;
wReq.nodesToWrite[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer");
if(strncmp(value, "1b", 2) == 0)
{
wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
bool_val = 1;
wReq.nodesToWrite[0].value.value.data = &bool_val;
}
else if(strncmp(value, "0b", 2) == 0)
{
wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
bool_val = 0;
wReq.nodesToWrite[0].value.value.data = &bool_val;
}
else
{
wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_INT16];
sscanf(value, "%d", &integer_val);
wReq.nodesToWrite[0].value.value.data = &integer_val;
}
wReq.nodesToWrite[0].nodeId = id;
wReq.nodesToWrite[0].attributeId = UA_ATTRIBUTEID_VALUE; wReq.nodesToWrite[0].attributeId = UA_ATTRIBUTEID_VALUE;
wReq.nodesToWrite[0].value.hasValue = true; wReq.nodesToWrite[0].value.hasValue = true;
wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_INT32];
wReq.nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA_NODELETE; /* do not free the integer on deletion */ wReq.nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA_NODELETE; /* do not free the integer on deletion */
wReq.nodesToWrite[0].value.value.data = &value;
UA_WriteResponse wResp = UA_Client_Service_write(client, wReq); UA_WriteResponse wResp = UA_Client_Service_write(client, wReq);
if(wResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD) if(wResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD)
ua_print("the new value is: %i\n", value); {
ua_pr_info("write new value is: %s\n", value);
}
UA_WriteRequest_clear(&wReq); UA_WriteRequest_clear(&wReq);
UA_WriteResponse_clear(&wResp); UA_WriteResponse_clear(&wResp);
/* Write node attribute (using the highlevel API) */ // /* Write node attribute (using the highlevel API) */
value++; // value++;
UA_Variant *myVariant = UA_Variant_new(); // UA_Variant *myVariant = UA_Variant_new();
UA_Variant_setScalarCopy(myVariant, &value, &UA_TYPES[UA_TYPES_INT32]); // UA_Variant_setScalarCopy(myVariant, &value, &UA_TYPES[UA_TYPES_INT32]);
UA_Client_writeValueAttribute(client, UA_NODEID_STRING(1, "the.answer"), myVariant); // UA_Client_writeValueAttribute(client, UA_NODEID_STRING(1, UA_NODE_STR), myVariant);
UA_Variant_delete(myVariant); // UA_Variant_delete(myVariant);
} }
void ua_call_remote(UA_Client *client) /* Read attribute */
void ua_read_nodeid_value(UA_Client* client, UA_NodeId id, UA_Int32 *value)
{
UA_Variant* val = UA_Variant_new();
UA_StatusCode ret = UA_Client_readValueAttribute(client, id, val);
if(ret == UA_STATUSCODE_GOOD)
{
ua_print_value(val);
if(UA_Variant_isScalar(val))
{
if(val->type == &UA_TYPES[UA_TYPES_BOOLEAN])
{
*value = *(UA_Boolean *)val->data;
}
else if(val->type == &UA_TYPES[UA_TYPES_INT32])
{
*value = *(UA_Int32 *)val->data;
}
else if(val->type == &UA_TYPES[UA_TYPES_INT16])
{
*value = *(UA_Int16 *)val->data;
}
}
}
UA_Variant_delete(val);
}
void ua_call_remote(UA_Client* client)
{ {
/* Call a remote method */ /* Call a remote method */
UA_Variant input; UA_Variant input;
@ -196,10 +378,11 @@ void ua_call_remote(UA_Client *client)
UA_Variant_init(&input); UA_Variant_init(&input);
UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]); UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]);
size_t outputSize; size_t outputSize;
UA_Variant *output; UA_Variant* output;
UA_StatusCode retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_StatusCode ret = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output); UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output);
if(retval == UA_STATUSCODE_GOOD)
if(ret == UA_STATUSCODE_GOOD)
{ {
ua_print("Method call was successful, and %lu returned values available.\n", ua_print("Method call was successful, and %lu returned values available.\n",
(unsigned long)outputSize); (unsigned long)outputSize);
@ -207,13 +390,14 @@ void ua_call_remote(UA_Client *client)
} }
else else
{ {
ua_print("Method call was unsuccessful, and %x returned values available.\n", retval); ua_print("Method call was unsuccessful, and %x returned values available.\n", ret);
} }
UA_Variant_clear(&input); UA_Variant_clear(&input);
} }
void ua_add_nodes(UA_Client *client) void ua_add_nodes(UA_Client* client)
{ {
/* Add new nodes*/ /* Add new nodes*/
/* New ReferenceType */ /* New ReferenceType */
@ -222,43 +406,52 @@ void ua_add_nodes(UA_Client *client)
ref_attr.displayName = UA_LOCALIZEDTEXT("en-US", "NewReference"); ref_attr.displayName = UA_LOCALIZEDTEXT("en-US", "NewReference");
ref_attr.description = UA_LOCALIZEDTEXT("en-US", "References something that might or might not exist"); ref_attr.description = UA_LOCALIZEDTEXT("en-US", "References something that might or might not exist");
ref_attr.inverseName = UA_LOCALIZEDTEXT("en-US", "IsNewlyReferencedBy"); ref_attr.inverseName = UA_LOCALIZEDTEXT("en-US", "IsNewlyReferencedBy");
UA_StatusCode retval = UA_Client_addReferenceTypeNode(client, UA_StatusCode ret = UA_Client_addReferenceTypeNode(client,
UA_NODEID_NUMERIC(1, 12133), UA_NODEID_NUMERIC(1, 12133),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(1, "NewReference"), UA_QUALIFIEDNAME(1, "NewReference"),
ref_attr, &ref_id); ref_attr, &ref_id);
if(retval == UA_STATUSCODE_GOOD )
if(ret == UA_STATUSCODE_GOOD)
{
ua_print("Created 'NewReference' with numeric NodeID %u\n", ref_id.identifier.numeric); ua_print("Created 'NewReference' with numeric NodeID %u\n", ref_id.identifier.numeric);
}
/* New ObjectType */ /* New ObjectType */
UA_NodeId objt_id; UA_NodeId objt_id;
UA_ObjectTypeAttributes objt_attr = UA_ObjectTypeAttributes_default; UA_ObjectTypeAttributes objt_attr = UA_ObjectTypeAttributes_default;
objt_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewObjectType"); objt_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewObjectType");
objt_attr.description = UA_LOCALIZEDTEXT("en-US", "Put innovative description here"); objt_attr.description = UA_LOCALIZEDTEXT("en-US", "Put innovative description here");
retval = UA_Client_addObjectTypeNode(client, ret = UA_Client_addObjectTypeNode(client,
UA_NODEID_NUMERIC(1, 12134), UA_NODEID_NUMERIC(1, 12134),
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(1, "NewObjectType"), UA_QUALIFIEDNAME(1, "NewObjectType"),
objt_attr, &objt_id); objt_attr, &objt_id);
if(retval == UA_STATUSCODE_GOOD)
if(ret == UA_STATUSCODE_GOOD)
{
ua_print("Created 'NewObjectType' with numeric NodeID %u\n", objt_id.identifier.numeric); ua_print("Created 'NewObjectType' with numeric NodeID %u\n", objt_id.identifier.numeric);
}
/* New Object */ /* New Object */
UA_NodeId obj_id; UA_NodeId obj_id;
UA_ObjectAttributes obj_attr = UA_ObjectAttributes_default; UA_ObjectAttributes obj_attr = UA_ObjectAttributes_default;
obj_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewGreatNode"); obj_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewGreatNode");
obj_attr.description = UA_LOCALIZEDTEXT("de-DE", "Hier koennte Ihre Webung stehen!"); obj_attr.description = UA_LOCALIZEDTEXT("de-DE", "Hier koennte Ihre Webung stehen!");
retval = UA_Client_addObjectNode(client, ret = UA_Client_addObjectNode(client,
UA_NODEID_NUMERIC(1, 0), UA_NODEID_NUMERIC(1, 0),
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, "TheGreatNode"), UA_QUALIFIEDNAME(1, "TheGreatNode"),
UA_NODEID_NUMERIC(1, 12134), UA_NODEID_NUMERIC(1, 12134),
obj_attr, &obj_id); obj_attr, &obj_id);
if(retval == UA_STATUSCODE_GOOD )
if(ret == UA_STATUSCODE_GOOD)
{
ua_print("Created 'NewObject' with numeric NodeID %u\n", obj_id.identifier.numeric); ua_print("Created 'NewObject' with numeric NodeID %u\n", obj_id.identifier.numeric);
}
/* New Integer Variable */ /* New Integer Variable */
UA_NodeId var_id; UA_NodeId var_id;
@ -270,68 +463,36 @@ void ua_add_nodes(UA_Client *client)
/* This does not copy the value */ /* This does not copy the value */
UA_Variant_setScalar(&var_attr.value, &int_value, &UA_TYPES[UA_TYPES_INT32]); UA_Variant_setScalar(&var_attr.value, &int_value, &UA_TYPES[UA_TYPES_INT32]);
var_attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId; var_attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
retval = UA_Client_addVariableNode(client, ret = UA_Client_addVariableNode(client,
UA_NODEID_NUMERIC(1, 0), // Assign new/random NodeID UA_NODEID_NUMERIC(1, 0), // Assign new/random NodeID
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(0, "VariableNode"), UA_QUALIFIEDNAME(0, "VariableNode"),
UA_NODEID_NULL, // no variable type UA_NODEID_NULL, // no variable type
var_attr, &var_id); var_attr, &var_id);
if(retval == UA_STATUSCODE_GOOD )
if(ret == UA_STATUSCODE_GOOD)
{
ua_print("Created 'NewVariable' with numeric NodeID %u\n", var_id.identifier.numeric); ua_print("Created 'NewVariable' with numeric NodeID %u\n", var_id.identifier.numeric);
}
} }
int ua_get_server_info(UA_Client *client) void ua_read_time(UA_Client* client)
{ {
ua_browser_objects(client); UA_Variant value;
/* Same thing, this time using the node iterator... */
ua_browser_nodes(client);
#ifdef UA_ENABLE_SUBSCRIPTIONS
UA_Int32 subId = ua_start_sub(client);
#endif
ua_read_attr(client);
#ifdef UA_ENABLE_SUBSCRIPTIONS
/* Take another look at the.answer */
UA_Client_run_iterate(client, 100);
/* Delete the subscription */
if(UA_Client_Subscriptions_deleteSingle(client, subId) == UA_STATUSCODE_GOOD)
ua_print("Subscription removed\n");
#endif
#ifdef UA_ENABLE_METHODCALLS
ua_call_remote(client);
#endif
#ifdef UA_ENABLE_NODEMANAGEMENT
ua_add_nodes(client);
#endif
return EXIT_SUCCESS;
}
void ua_read_time(UA_Client *client)
{
/* Read the value attribute of the node. UA_Client_readValueAttribute is a
* wrapper for the raw read service available as UA_Client_Service_read. */
UA_Variant value; /* Variants can hold scalar values and arrays of any type */
UA_Variant_init(&value); UA_Variant_init(&value);
/* NodeId of the variable holding the current time */
const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME); const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
UA_StatusCode retval = UA_Client_readValueAttribute(client, nodeId, &value); UA_StatusCode ret = UA_Client_readValueAttribute(client, nodeId, &value);
if(retval == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) if(ret == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME]))
{ {
UA_DateTime raw_date = *(UA_DateTime *) value.data; UA_DateTime raw_date = *(UA_DateTime*) value.data;
UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date); UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date);
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n", ua_pr_info("date is: %d-%d-%d %d:%d:%d.%03d\n",
dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec); dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
} }
/* Clean up */ /* Clean up */
UA_Variant_clear(&value); UA_Variant_clear(&value);
} }

View File

@ -10,17 +10,85 @@
* See the Mulan PSL v2 for more details. * See the Mulan PSL v2 for more details.
*/ */
/**
* @file ua_test.c
* @brief Test for OpcUa function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#include <stdlib.h>
#include "open62541.h"
#include "ua_api.h"
//for target NODEID
#define UA_TEST_BROWSER_NODEID UA_NODEID_STRING(3, "ServerInterfaces")
#define UA_TEST_BROWSER_NODEID1 UA_NODEID_NUMERIC(4, 1)
#define UA_TEST_WRITE_NODEID UA_NODEID_NUMERIC(4, 5)
static UA_StatusCode ua_test_read_array(UA_Client *client)
{
const int item_size = 4;
UA_ReadValueId test_item[item_size];
for (int i = 0; i < item_size; i++)
{
UA_ReadValueId_init(&test_item[i]);
test_item[i].attributeId = UA_ATTRIBUTEID_VALUE;
}
test_item[0].nodeId = UA_NODEID_NUMERIC(4, 2);
test_item[1].nodeId = UA_NODEID_NUMERIC(4, 3);
test_item[2].nodeId = UA_NODEID_NUMERIC(4, 4);
test_item[3].nodeId = UA_NODEID_NUMERIC(4, 5);
return ua_read_array_value(client, item_size, test_item);
}
void ua_test_browser_objects(UA_Client *client)
{
UA_NodeId test_id;
ua_browser_id(client, UA_TEST_BROWSER_NODEID);
ua_browser_id(client, UA_TEST_BROWSER_NODEID1);
test_id = UA_TEST_BROWSER_NODEID1;
ua_pr_info("Show values in %s:\n", ua_get_nodeid_str(&test_id));
ua_test_read_array(client);
return;
}
void ua_test_write_attr(UA_Client *client)
{
UA_Int32 value;
char val_str[UA_NODE_LEN];
UA_NodeId id = UA_TEST_WRITE_NODEID;
ua_pr_info("--- Test write %s ---\n", ua_get_nodeid_str(&id));
ua_read_nodeid_value(client, id, &value);
ua_write_nodeid_value(client, id, itoa(value + 1, val_str, 10));
ua_read_nodeid_value(client, id, &value);
ua_pr_info("\n");
}
int ua_test_interact_server(UA_Client *client)
{
ua_read_time(client);
ua_test_browser_objects(client);
ua_test_write_attr(client);
return EXIT_SUCCESS;
}
int16 ua_test(void) int16 ua_test(void)
{ {
UA_Client *client = UA_Client_new(); UA_Client *client = UA_Client_new();
UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER); UA_StatusCode retval = UA_Client_connect(client, opc_server_url);
if(retval != UA_STATUSCODE_GOOD) { if(retval != UA_STATUSCODE_GOOD) {
UA_Client_delete(client); UA_Client_delete(client);
return (int)retval; return (int)retval;
} }
ua_read_time(client); ua_read_time(client);
ua_run_test(client);
/* Clean up */ /* Clean up */
UA_Client_disconnect(client); UA_Client_disconnect(client);

View File

@ -1,4 +1,4 @@
SRC_FILES := plc.c SRC_FILES := plc_device.c plc_channel.c plc_driver.c
include $(KERNEL_ROOT)/compiler.mk include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2021 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 plc.c
* @brief plc relative activities
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.12.15
*/
#ifdef USING_CONTROL_PLC_OPCUA
#include "../interoperability/opcua/open62541.h"
#endif
#include "plc.h"
struct PlcDevice plc_device;
// open and connect PLC device
void plc_open(struct PlcDevice *pdev)
{
}
// close and disconnect PLC device
void plc_close(struct PlcDevice *pdev)
{
}
// read data from PLC
void plc_read(struct PlcDevice *pdev, void *buf, size_t len)
{
}
// write data from PLC
void plc_write(struct PlcDevice *pdev, const void *buf, size_t len)
{
}
// send control command to PLC
void plc_ioctl(struct PlcDevice *pdev, int cmd, void *arg)
{
}
void plc_init(struct PlcDevice *plc_dev)
{
}

View File

@ -0,0 +1,538 @@
/*
* 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 plc_ch.c
* @brief Support channel driver framework provide ch API version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include "string.h"
#include "plc_channel.h"
#include "plc_device.h"
#include "transform.h"
DoublelistType ch_linklist;
/*Create the ch linklist*/
static void ChannelLinkInit(struct Channel *ch)
{
static uint8 ch_link_flag = RET_FALSE;
if(!ch_link_flag) {
AppInitDoubleList(&ch_linklist);
ch_link_flag = RET_TRUE;
ch->ch_link_flag = RET_TRUE;
}
/*Create the driver of the ch linklist*/
if(!ch->ch_drvlink_flag) {
AppInitDoubleList(&ch->ch_drvlink);
ch->ch_drvlink_flag = RET_TRUE;
}
/*Create the hardware device of the ch linklist*/
if(!ch->ch_devlink_flag) {
AppInitDoubleList(&ch->ch_devlink);
ch->ch_devlink_flag = RET_TRUE;
}
}
static int ChannelMatchDrvDev(struct ChDrv *driver, struct ChDev *device)
{
CHECK_CH_PARAM(driver);
CHECK_CH_PARAM(device);
if(!strncmp(driver->owner_ch->ch_name, device->owner_ch->ch_name, NAME_NUM_MAX)) {
KPrintf("ChannelMatchDrvDev match successfully, ch name %s\n", driver->owner_ch->ch_name);
driver->private_data = device->private_data;//driver get the device param
device->owner_ch->owner_driver = driver;
driver->owner_ch->owner_haldev = device;
return EOK;
}
return ERROR;
}
/**
* @Description: support to obtain ch for a certain dev if necessary, then configure and init its drv
* @param ch - ch pointer
* @param dev - dev pointer
* @param drv_name - drv name
* @param config - ChConfigInfo pointer
* @return successful:EOK,failed:ERROR
*/
int DeviceObtainChannel(struct Channel *ch, struct ChDev *dev, const char *drv_name, struct ChConfigInfo *cfg)
{
CHECK_CH_PARAM(ch);
CHECK_CH_PARAM(dev);
int32 ret = EOK;
ret = PrivMutexObtain(&ch->ch_lock);
if(EOK != ret) {
KPrintf("DevObtainChannel ch_lock error %d!\n", ret);
return ret;
}
if(ch->owner_haldev != dev) {
struct ChDrv *drv = ChannelFindDriver(ch, drv_name);
cfg->configure_cmd = OPE_CFG;
drv->configure(drv, cfg);
cfg->configure_cmd = OPE_INT;
drv->configure(drv, cfg);
ch->owner_haldev = dev;
}
return ret;
}
/**
* @Description: support to register ch pointer with linklist
* @param ch - ch pointer
* @return successful:EOK,failed:NONE
*/
int ChannelRegister(struct Channel *ch)
{
int ret = EOK;
CHECK_CH_PARAM(ch);
ch->match = ChannelMatchDrvDev;
ChannelLinkInit(ch);
PrivMutexCreate(&ch->ch_lock, NULL);
AppDoubleListInsertNodeAfter(&ch_linklist, &(ch->ch_link));
return ret;
}
/**
* @Description: support to release ch pointer in linklist
* @param ch - ch pointer
* @return successful:EOK,failed:NONE
*/
int ChannelRelease(struct Channel *ch)
{
CHECK_CH_PARAM(ch);
PrivMutexAbandon(&ch->ch_lock);
ch->ch_cnt = 0;
ch->driver_cnt = 0;
ch->haldev_cnt = 0;
ch->ch_link_flag = RET_FALSE;
ch->ch_drvlink_flag = RET_FALSE;
ch->ch_devlink_flag = RET_FALSE;
return EOK;
}
/**
* @Description: support to unregister ch pointer and delete its linklist node
* @param ch - ch pointer
* @return successful:EOK,failed:NONE
*/
int ChannelUnregister(struct Channel *ch)
{
CHECK_CH_PARAM(ch);
ch->ch_cnt--;
AppDoubleListRmNode(&(ch->ch_link));
return EOK;
}
/**
* @Description: support to register driver pointer to ch pointer
* @param ch - ch pointer
* @param driver - driver pointer
* @return successful:EOK,failed:NONE
*/
int DriverRegisterToChannel(struct Channel *ch, struct ChDrv *driver)
{
CHECK_CH_PARAM(ch);
CHECK_CH_PARAM(driver);
driver->owner_ch = ch;
ch->driver_cnt++;
AppDoubleListInsertNodeAfter(&ch->ch_drvlink, &(driver->driver_link));
return EOK;
}
/**
* @Description: support to register dev pointer to ch pointer
* @param ch - ch pointer
* @param device - device pointer
* @return successful:EOK,failed:NONE
*/
int DeviceRegisterToChannel(struct Channel *ch, struct ChDev *device)
{
CHECK_CH_PARAM(ch);
CHECK_CH_PARAM(device);
device->owner_ch = ch;
ch->haldev_cnt++;
AppDoubleListInsertNodeAfter(&ch->ch_devlink, &(device->dev_link));
return EOK;
}
/**
* @Description: support to delete driver pointer from ch pointer
* @param ch - ch pointer
* @param driver - driver pointer
* @return successful:EOK,failed:NONE
*/
int DriverDeleteFromChannel(struct Channel *ch, struct ChDrv *driver)
{
CHECK_CH_PARAM(ch);
CHECK_CH_PARAM(driver);
ch->driver_cnt--;
AppDoubleListRmNode(&(driver->driver_link));
free(driver);
return EOK;
}
/**
* @Description: support to delete dev pointer from ch pointer
* @param ch - ch pointer
* @param device - device pointer
* @return successful:EOK,failed:NONE
*/
int DeviceDeleteFromChannel(struct Channel *ch, struct ChDev *device)
{
CHECK_CH_PARAM(ch);
CHECK_CH_PARAM(device);
ch->haldev_cnt--;
AppDoubleListRmNode(&(device->dev_link));
free(device);
return EOK;
}
/**
* @Description: support to find ch pointer by ch name
* @param ch_name - ch name
* @return successful:ch pointer,failed:NONE
*/
ChannelType ChannelFind(const char *ch_name)
{
struct Channel *ch = NONE;
DoublelistType *node = NONE;
DoublelistType *head = &ch_linklist;
for (node = head->node_next; node != head; node = node->node_next)
{
ch = DOUBLE_LIST_ENTRY(node, struct Channel, ch_link);
if(!strcmp(ch->ch_name, ch_name)) {
return ch;
}
}
KPrintf("ChannelFind cannot find the %s ch.return NULL\n", ch_name);
return NONE;
}
/**
* @Description: support to find driver pointer of certain ch by driver name
* @param ch - ch pointer
* @param driver_name - driver name
* @return successful:EOK,failed:NONE
*/
ChDrvType ChannelFindDriver(struct Channel *ch, const char *driver_name)
{
CHECK_CH_PARAM(ch);
struct ChDrv *driver = NONE;
DoublelistType *node = NONE;
DoublelistType *head = &ch->ch_drvlink;
for (node = head->node_next; node != head; node = node->node_next)
{
driver = DOUBLE_LIST_ENTRY(node, struct ChDrv, driver_link);
if(!strcmp(driver->drv_name, driver_name)) {
return driver;
}
}
KPrintf("ChannelFindDriver cannot find the %s driver.return NULL\n", driver_name);
return NONE;
}
/**
* @Description: support to find device pointer of certain ch by device name
* @param ch - ch pointer
* @param device_name - device name
* @return successful:EOK,failed:NONE
*/
ChDevType ChannelFindDevice(struct Channel *ch, const char *device_name)
{
CHECK_CH_PARAM(ch);
struct ChDev *device = NONE;
DoublelistType *node = NONE;
DoublelistType *head = &ch->ch_devlink;
for (node = head->node_next; node != head; node = node->node_next)
{
device = DOUBLE_LIST_ENTRY(node, struct ChDev, dev_link);
if(!strcmp(device->dev_name, device_name)) {
return device;
}
}
KPrintf("ChannelFindDevice cannot find the %s device.return NULL\n", device_name);
return NONE;
}
/**
* @Description: support to set dev receive function callback
* @param dev - dev pointer
* @param dev_recv_callback - callback function
* @return successful:EOK,failed:ERROR
*/
uint32 ChannelDevRecvCallback(struct ChDev *dev, int (*dev_recv_callback) (void *dev, x_size_t length))
{
CHECK_CH_PARAM(dev );
dev->dev_recv_callback = dev_recv_callback;
return EOK;
}
/**
* @Description: support to open dev
* @param dev - dev pointer
* @return successful:EOK,failed:ERROR
*/
uint32 ChannelDevOpen(struct ChDev *dev)
{
CHECK_CH_PARAM(dev);
int ret = EOK;
if (dev->dev_done->open) {
ret = dev->dev_done->open(dev);
if(ret) {
KPrintf("ChannelDevOpen error ret %u\n", ret);
return ERROR;
}
}
return ret;
}
/**
* @Description: support to close dev
* @param dev - dev pointer
* @return successful:EOK,failed:ERROR
*/
uint32 ChannelDevClose(struct ChDev *dev)
{
CHECK_CH_PARAM(dev);
int ret = EOK;
if (dev->dev_done->close) {
ret = dev->dev_done->close(dev);
if(ret) {
KPrintf("ChannelDevClose error ret %u\n", ret);
return ERROR;
}
}
return ret;
}
/**
* @Description: support to write data to dev
* @param dev - dev pointer
* @param write_param - ChWriteParam
* @return successful:EOK,failed:NONE
*/
uint32 ChannelDevWriteData(struct ChDev *dev, struct ChWriteParam *write_param)
{
CHECK_CH_PARAM(dev);
if (dev->dev_done->write) {
return dev->dev_done->write(dev, write_param);
}
return EOK;
}
/**
* @Description: support to read data from dev
* @param dev - dev pointer
* @param read_param - ChReadParam
* @return successful:EOK,failed:NONE
*/
uint32 ChannelDevReadData(struct ChDev *dev, struct ChReadParam *read_param)
{
CHECK_CH_PARAM(dev);
if (dev->dev_done->read) {
return dev->dev_done->read(dev, read_param);
}
return EOK;
}
/**
* @Description: support to configure drv, include OPE_CFG and OPE_INT
* @param drv - drv pointer
* @param config - ChConfigInfo
* @return successful:EOK,failed:NONE
*/
uint32 ChannelDrvConfigure(struct ChDrv *drv, struct ChConfigInfo *config)
{
CHECK_CH_PARAM(drv);
CHECK_CH_PARAM(config);
int ret = EOK;
if (drv->configure) {
ret = drv->configure(drv, config);
if(ret) {
KPrintf("ChannelDrvCfg error, ret %u\n", ret);
return ERROR;
}
}
return ret;
}
int PlcChannelInit(struct PlcChannel* plc_ch, const char* ch_name)
{
CHECK_CH_PARAM(plc_ch);
CHECK_CH_PARAM(ch_name);
int ret = EOK;
if(CHANNEL_INSTALL != plc_ch->ch.ch_state)
{
strncpy(plc_ch->ch.ch_name, ch_name, NAME_NUM_MAX);
plc_ch->ch.ch_type = CH_PLC_TYPE;
plc_ch->ch.ch_state = CHANNEL_INSTALL;
plc_ch->ch.private_data = plc_ch->private_data;
ret = ChannelRegister(&plc_ch->ch);
if(EOK != ret)
{
KPrintf("PlcChannelInit ChannelRegister error %u\n", ret);
return ret;
}
}
else
{
KPrintf("PlcChannelInit ChannelRegister channel has been register state %u\n",
plc_ch->ch.ch_state);
}
return ret;
}
int PlcDriverInit(struct PlcDriver* plc_driver, const char* driver_name)
{
CHECK_CH_PARAM(plc_driver);
CHECK_CH_PARAM(driver_name);
int ret = EOK;
if(CHDRV_INSTALL != plc_driver->driver.driver_state)
{
plc_driver->driver.driver_type = CHDRV_PLC_TYPE;
plc_driver->driver.driver_state = CHDRV_INSTALL;
strncpy(plc_driver->driver.drv_name, driver_name, NAME_NUM_MAX);
plc_driver->driver.configure = plc_driver->configure;
ret = PlcDriverRegister(&plc_driver->driver);
if(EOK != ret)
{
KPrintf("PlcDriverInit DriverRegister error %u\n", ret);
return ret;
}
}
else
{
KPrintf("PlcDriverInit Driver %s has been register state %u\n",
driver_name, plc_driver->driver.driver_state);
}
return ret;
}
int PlcReleaseChannel(struct PlcChannel* plc_ch)
{
CHECK_CH_PARAM(plc_ch);
return ChannelRelease(&plc_ch->ch);
}
int PlcDriverAttachToChannel(const char* drv_name, const char* ch_name)
{
CHECK_CH_PARAM(drv_name);
CHECK_CH_PARAM(ch_name);
int ret = EOK;
struct Channel* ch;
struct ChDrv* driver;
ch = ChannelFind(ch_name);
if(NONE == ch)
{
KPrintf("PlcDriverAttachToChannel find plc channel error!name %s\n", ch_name);
return ERROR;
}
if(CH_PLC_TYPE == ch->ch_type)
{
driver = PlcDriverFind(drv_name, CHDRV_PLC_TYPE);
if(NONE == driver)
{
KPrintf("PlcDriverAttachToChannel find plc driver error!name %s\n", drv_name);
return ERROR;
}
if(CHDRV_PLC_TYPE == driver->driver_type)
{
ret = DriverRegisterToChannel(ch, driver);
if(EOK != ret)
{
KPrintf("PlcDriverAttachToChannel DriverRegisterToBus error %u\n", ret);
return ERROR;
}
}
}
return ret;
}

View File

@ -0,0 +1,278 @@
/*
* Copyright (c) 2022 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 plc_channel.h
* @brief define ch driver framework function and common API
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
#ifndef __PLC_CHANNEL_H_
#define __PLC_CHANNEL_H_
#include "list.h"
#define x_OffPos uint32
#define x_size_t size_t
#ifdef __cplusplus
extern "C" {
#endif
#define OPE_INT 0x0000
#define OPE_CFG 0x0001
#define OPER_WDT_SET_TIMEOUT 0x0002
#define OPER_WDT_KEEPALIVE 0x0003
#define CHECK_CH_PARAM(param) \
do \
{ \
if(param == NONE) { \
KPrintf("PARAM CHECK FAILED ...%s %d %s is NULL.\n",__FUNCTION__,__LINE__,#param); \
while(RET_TRUE); \
} \
}while (0)
typedef struct Channel *ChannelType;
typedef struct ChDev *ChDevType;
typedef struct ChDrv *ChDrvType;
/* need to add new ch type in ../tool/shell/letter-shell/cmd.c, ensure ShowBus cmd supported*/
enum ChType_e
{
CH_PLC_TYPE,
CH_END_TYPE,
};
enum ChState_e
{
CHANNEL_INIT = 0,
CHANNEL_INSTALL,
CHANNEL_UNINSTALL,
};
enum ChDevType_e
{
CHDEV_PLC_TYPE,
CHDEV_END_TYPE,
};
enum ChDevState_e
{
CHDEV_INIT = 0,
CHDEV_INSTALL,
CHDEV_UNINSTALL,
};
enum ChDrvType_e
{
CHDRV_PLC_TYPE,
CHDRV_END_TYPE,
};
enum ChDrvState_e
{
CHDRV_INIT = 0,
CHDRV_INSTALL,
CHDRV_UNINSTALL,
};
struct ChConfigInfo
{
int configure_cmd;
void *private_data;
};
struct ChReadParam
{
x_OffPos pos;
void* buffer;
x_size_t size;
x_size_t read_length;
};
struct ChWriteParam
{
x_OffPos pos;
const void* buffer;
x_size_t size;
};
//struct ChHalDevBlockParam
//{
// uint32 cmd;
////tst by wly
//// struct DeviceBlockArrange dev_block;
//// struct DeviceBlockAddr *dev_addr;
//};
struct ChHalDevDone
{
uint32 (*open) (void *dev);
uint32 (*close) (void *dev);
uint32 (*write) (void *dev, struct ChWriteParam *write_param);
uint32 (*read) (void *dev, struct ChReadParam *read_param);
};
struct ChDev
{
int8 dev_name[NAME_NUM_MAX];
enum ChDevType_e dev_type;
enum ChDevState_e dev_state;
const struct ChHalDevDone *dev_done;
int (*dev_recv_callback) (void *dev, x_size_t length);
// int (*dev_block_control) (struct ChDev *dev, struct ChHalDevBlockParam *block_param);
struct Channel *owner_ch;
void *private_data;
int32 dev_sem;
DoublelistType dev_link;
};
struct ChDrv
{
int8 drv_name[NAME_NUM_MAX];
enum ChDrvType_e driver_type;
enum ChDrvState_e driver_state;
uint32 (*configure)(void *drv, struct ChConfigInfo *config);
struct Channel *owner_ch;
void *private_data;
DoublelistType driver_link;
};
struct Channel
{
int8 ch_name[NAME_NUM_MAX];
enum ChType_e ch_type;
enum ChState_e ch_state;
int32 (*match)(struct ChDrv *driver, struct ChDev *device);
int ch_lock;
struct ChDev *owner_haldev;
struct ChDrv *owner_driver;
void *private_data;
/*manage the drv of the channel*/
uint8 driver_cnt;
uint8 ch_drvlink_flag;
DoublelistType ch_drvlink;
/*manage the dev of the channel*/
uint8 haldev_cnt;
uint8 ch_devlink_flag;
DoublelistType ch_devlink;
uint8 ch_cnt;
uint8 ch_link_flag;
DoublelistType ch_link;
};
/*Register the BUS,manage with the double linklist*/
int ChannelRegister(struct Channel *ch);
/*Release the BUS framework*/
int ChannelRelease(struct Channel *ch);
/*Unregister a certain kind of BUS*/
int ChannelUnregister(struct Channel *ch);
/*Register the driver to the channel*/
int DriverRegisterToChannel(struct Channel *ch, struct ChDrv *driver);
/*Register the device to the channel*/
int DeviceRegisterToChannel(struct Channel *ch, struct ChDev *device);
/*Delete the driver from the channel*/
int DriverDeleteFromChannel(struct Channel *ch, struct ChDrv *driver);
/*Delete the device from the channel*/
int DeviceDeleteFromChannel(struct Channel *ch, struct ChDev *device);
/*Find the ch with ch name*/
ChannelType ChannelFind(const char *ch_name);
/*Find the driver of cetain channel*/
ChDrvType ChannelFindDriver(struct Channel *ch, const char *driver_name);
/*Find the device of certain channel*/
ChDevType ChannelFindDevice(struct Channel *ch, const char *device_name);
/*Dev receive data callback function*/
uint32 ChannelDevRecvCallback(struct ChDev *dev, int (*dev_recv_callback) (void *dev, x_size_t length));
/*Open the device of the channel*/
uint32 ChannelDevOpen(struct ChDev *dev);
/*Close the device of the channel*/
uint32 ChannelDevClose(struct ChDev *dev);
/*Write data to the device*/
uint32 ChannelDevWriteData(struct ChDev *dev, struct ChWriteParam *write_param);
/*Read data from the device*/
uint32 ChannelDevReadData(struct ChDev *dev, struct ChReadParam *read_param);
/*Configure the driver of the channel*/
uint32 ChannelDrvConfigure(struct ChDrv *drv, struct ChConfigInfo *config);
/*Obtain the ch using a certain dev*/
int DeviceObtainChannel(struct Channel *ch, struct ChDev *dev, const char *drv_name, struct ChConfigInfo *config);
struct PlcDriver
{
struct ChDrv driver;
uint32 (*configure) (void *drv, struct ChConfigInfo *cfg);
};
struct PlcChannel
{
struct Channel ch;
void *private_data;
};
/*Register the plc bus*/
int PlcChannelInit(struct PlcChannel *plc_ch, const char *ch_name);
/*Register the plc driver*/
int PlcDriverInit(struct PlcDriver *plc_driver, const char *driver_name);
/*Release the plc device*/
int PlcReleaseChannel(struct PlcChannel *plc_ch);
/*Register the plc driver to the plc bus*/
int PlcDriverAttachToChannel(const char *drv_name, const char *ch_name);
/*Register the driver, manage with the double linklist*/
int PlcDriverRegister(struct ChDrv *driver);
/*Find the register driver*/
ChDrvType PlcDriverFind(const char *drv_name, enum ChDrvType_e drv_type);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,189 @@
/*
* Copyright (c) 2021 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 plc.c
* @brief plc relative activities
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.12.15
*/
#include "ua_api.h"
#include "plc_channel.h"
#include "plc_device.h"
DoublelistType plcdev_list;
/******************************************************************************/
/*Create the plc device linklist*/
static void PlcDeviceLinkInit()
{
AppInitDoubleList(&plcdev_list);
}
static int PlcDeviceOpen(void *dev)
{
CHECK_CH_PARAM(dev);
struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
if(plc_dev->net == PLC_IND_ENET_OPCUA)
{
return ua_open(plc_dev->priv_data);
}
return EOK;
}
static void PlcDeviceClose(void *dev)
{
CHECK_CH_PARAM(dev);
struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
if(plc_dev->net == PLC_IND_ENET_OPCUA)
{
ua_close(plc_dev->priv_data);
}
}
static int PlcDeviceWrite(void *dev, const void *buf, size_t len)
{
CHECK_CH_PARAM(dev);
int ret;
struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
if(plc_dev->net == PLC_IND_ENET_OPCUA)
{
ret = ua_write(plc_dev->priv_data, buf, len);
}
return ret;
}
static int PlcDeviceRead(void *dev, void *buf, size_t len)
{
CHECK_CH_PARAM(dev);
CHECK_CH_PARAM(buf);
int ret;
struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
if(plc_dev->net == PLC_IND_ENET_OPCUA)
{
ret = ua_read(plc_dev->priv_data, buf, len);
}
return ret;
}
static struct PlcOps plc_done =
{
.open = PlcDeviceOpen,
.close = PlcDeviceClose,
.write = PlcDeviceWrite,
.read = PlcDeviceRead,
};
/* find PLC device with device name */
struct ChDev *PlcDevFind(const char *dev_name)
{
CHECK_CH_PARAM(dev_name);
struct PlcDevice *device = NONE;
struct ChDev *haldev = NONE;
DoublelistType *node = NONE;
DoublelistType *head = &plcdev_list;
for (node = head->node_next; node != head; node = node->node_next) {
device = DOUBLE_LIST_ENTRY(node, struct PlcDevice, link);
if (!strcmp(device->name, dev_name)) {
haldev = &device->haldev;
return haldev;
}
}
plc_print("plc: [%s] cannot find the %s device\n", __func__, dev_name);
return NONE;
}
int PlcDevRegister(struct PlcDevice *plc_device, void *plc_param, const char *device_name)
{
CHECK_CH_PARAM(plc_device);
CHECK_CH_PARAM(device_name);
int ret = EOK;
static uint8_t dev_link_flag = 0;
if (!dev_link_flag) {
PlcDeviceLinkInit();
dev_link_flag = 1;
}
if (CHDEV_INSTALL != plc_device->state) {
strncpy(plc_device->haldev.dev_name, device_name, NAME_NUM_MAX);
plc_device->haldev.dev_type = CHDEV_PLC_TYPE;
plc_device->haldev.dev_state = CHDEV_INSTALL;
strncpy(plc_device->name, device_name, strlen(device_name));
plc_device->ops = &plc_done;
AppDoubleListInsertNodeAfter(&plcdev_list, &(plc_device->link));
plc_device->state = CHDEV_INSTALL;
} else {
KPrintf("PlcDevRegister device %s has been register state%u\n", device_name, plc_device->state);
ret = ERROR;
}
return ret;
}
int PlcDeviceAttachToChannel(const char *dev_name, const char *ch_name)
{
CHECK_CH_PARAM(dev_name);
CHECK_CH_PARAM(ch_name);
int ret = EOK;
struct Channel *ch;
struct ChDev *device;
ch = ChannelFind(ch_name);
if (NONE == ch) {
KPrintf("PlcDeviceAttachToChannel find plc ch error!name %s\n", ch_name);
return ERROR;
}
if (CH_PLC_TYPE == ch->ch_type) {
device = PlcDevFind(dev_name);
if (NONE == device) {
KPrintf("PlcDeviceAttachToChannel find plc device %s error!\n", dev_name);
return ERROR;
}
if (CHDEV_PLC_TYPE == device->dev_type) {
ret = DeviceRegisterToChannel(ch, device);
if (EOK != ret) {
KPrintf("PlcDeviceAttachToChannel DeviceRegisterToChannel error %u\n", ret);
return ERROR;
}
}
}
return EOK;
}

View File

@ -11,28 +11,38 @@
*/ */
/** /**
* @file plc.h * @file plc_dev.h
* @brief plc relative definition and structure * @brief plc relative definition and structure
* @version 1.0 * @version 1.0
* @author AIIT XUOS Lab * @author AIIT XUOS Lab
* @date 2021.12.15 * @date 2022-01-24
*/ */
#include "xs_klist.h" #ifndef __PLC_DEV_H_
#define __PLC_DEV_H_
#include "list.h"
#include "plc_channel.h"
#undef open
#undef close
#undef read
#undef write
#define IP_ADDR_SIZE 32 #define IP_ADDR_SIZE 32
#define PLC_NAME_SIZE 32 #define PLC_NAME_SIZE 32
// PLC device information // PLC device information
struct PlcInfo { typedef struct PlcInfo {
uint32_t ability; // PLC ability uint32_t ability; // PLC ability
uint32_t id; // PLC Device ID uint32_t id; // PLC Device ID
uint32_t soft_version; // software version uint32_t soft_version; // software version
uint32_t hard_version; // hardware version uint32_t hard_version; // hardware version
uint32_t date; // manufact date uint32_t date; // manufact date
const char *vendor; // vendor const char *vendor; // vendor
const char *model; // product model const char *model; // model
}; const char *product; // product
}PlcInfoType;
enum PlcSerialType { enum PlcSerialType {
PLC_SERIAL_232, PLC_SERIAL_232,
@ -55,13 +65,13 @@ union PlcCfg {
struct PlcDevice; struct PlcDevice;
// operation API // operation API
struct PlcOps { typedef struct PlcOps {
int (*open)(struct PlcDevice *pdev); // open and connect PLC device int (*open)(void *dev); // open and connect PLC device
void (*close)(struct PlcDevice*pdev); // close and disconnect PLC device void (*close)(void* dev); // close and disconnect PLC device
int (*read)(struct PlcDevice* pdev, void *buf, size_t len); // read data from PLC int (*read)(void* dev, void *buf, size_t len); // read data from PLC
int (*write)(struct PlcDevice* pdev, const void *buf, size_t len); // write data from PLC int (*write)(void* dev, const void *buf, size_t len); // write data from PLC
int (*ioctl)(struct PlcDevice* pdev, int cmd, void *arg); // send control command to PLC int (*ioctl)(void* dev, int cmd, void *arg); // send control command to PLC
}; }PlcOpsType;
enum PlcCtlType { enum PlcCtlType {
PLC_CTRL_TYPE_HSC, PLC_CTRL_TYPE_HSC,
@ -69,15 +79,13 @@ enum PlcCtlType {
PLC_CTRL_TYPE_PHASING PLC_CTRL_TYPE_PHASING
}; };
#define PLC_ABILITY_HSC ((uint32_t)(1 << PLC_CTRL_TYPE_HSC)) #define PLC_ABILITY_HSC ((uint32_t)(1 << PLC_CTRL_TYPE_HSC))
#define PLC_ABILITY_PID ((uint32_t)(1 << PLC_CTRL_TYPE_PID)) #define PLC_ABILITY_PID ((uint32_t)(1 << PLC_CTRL_TYPE_PID))
#define PLC_ABILITY_PHASING ((uint32_t)(1 << PLC_CTRL_TYPE_PHASING)) #define PLC_ABILITY_PHASING ((uint32_t)(1 << PLC_CTRL_TYPE_PHASING))
enum PlcIndHybridNet enum PlcIndHybridNet
{ {
//PLC Field Bus // PLC Field Bus
PLC_IND_FIELD_MODBUS_485, PLC_IND_FIELD_MODBUS_485,
PLC_IND_FIELD_PROFIBUS, PLC_IND_FIELD_PROFIBUS,
PLC_IND_FIELD_CANOPEN, PLC_IND_FIELD_CANOPEN,
@ -91,7 +99,7 @@ enum PlcIndHybridNet
PLC_IND_ENET_SERCOS, PLC_IND_ENET_SERCOS,
PLC_IND_ENET_OPCUA, PLC_IND_ENET_OPCUA,
//PLC wireless net // PLC wireless net
PLC_IND_WIRELESS PLC_IND_WIRELESS
}; };
@ -103,22 +111,43 @@ enum PlcTransType
}; };
//communication interface //communication interface
struct PlcInterface typedef struct PlcInterface
{ {
enum PlcIndHybridNet net;
enum PlcTransType trans;
char ip_addr[IP_ADDR_SIZE]; char ip_addr[IP_ADDR_SIZE];
char attrib; char attrib;
}; }PlcInterfaceType;
// identify PLC device // identify PLC device
struct PlcDevice { typedef struct PlcDevice {
const char name[PLC_NAME_SIZE]; /* name of the device */ struct ChDev haldev; /* hardware device driver for channel */
enum ChDevState_e state;
char name[PLC_NAME_SIZE]; /* name of the device */
enum PlcCtlType type; /* PLC Control Type */ enum PlcCtlType type; /* PLC Control Type */
enum PlcIndHybridNet net;
enum PlcTransType trans;
struct PlcInfo info;/* Plc info, such as vendor name and model name */ struct PlcInfo info;/* Plc info, such as vendor name and model name */
union PlcCfg cfg; union PlcCfg cfg;
struct PlcOps ops; /* filesystem-like APIs for data transferring */ struct PlcOps *ops; /* filesystem-like APIs for data transferring */
struct PlcInterface interface; /* protocols used for transferring data from program to plc */ struct PlcInterface interface; /* protocols used for transferring data from program to plc */
DoubleLinklistType link;/* link list node */
};
void *priv_data; /* private data for different PLC*/
DoublelistType link;/* link list node */
}PlcDeviceType;
typedef struct PlcCtrlParam {
void *node_id; // for node ID
int value;
}PlcCtrlParamType;
#define plc_print KPrintf
/******************************************************************************/
int PlcDevRegister(struct PlcDevice *plc_device, void *plc_param, const char *device_name);
int PlcDeviceAttachToChannel(const char *dev_name, const char *ch_name);
/******************************************************************************/
#endif

View File

@ -0,0 +1,71 @@
/*
* 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 drv_plc.c
* @brief register plc drv function using bus driver framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-01-24
*/
#include "transform.h"
#include "plc_channel.h"
#include "plc_device.h"
static DoublelistType plcdrv_linklist;
/******************************************************************************/
/*Create the driver linklist*/
static void PlcDrvLinkInit()
{
AppInitDoubleList(&plcdrv_linklist);
}
ChDrvType PlcDriverFind(const char *drv_name, enum ChDrvType_e drv_type)
{
CHECK_CH_PARAM(drv_name);
struct ChDrv *driver = NONE;
DoublelistType *node = NONE;
DoublelistType *head = &plcdrv_linklist;
for (node = head->node_next; node != head; node = node->node_next) {
driver = DOUBLE_LIST_ENTRY(node, struct ChDrv, driver_link);
if ((!strcmp(driver->drv_name, drv_name)) && (drv_type == driver->driver_type)) {
return driver;
}
}
KPrintf("PlcDriverFind cannot find the %s driver.return NULL\n", drv_name);
return NONE;
}
int PlcDriverRegister(struct ChDrv *driver)
{
CHECK_CH_PARAM(driver);
int ret = EOK;
static uint8_t driver_link_flag = 0;
if (!driver_link_flag) {
PlcDrvLinkInit();
driver_link_flag = 1;
}
AppDoubleListInsertNodeAfter(&plcdrv_linklist, &(driver->driver_link));
return ret;
}

View File

@ -1,5 +1,4 @@
SRC_DIR := SRC_FILES := control.c
include $(KERNEL_ROOT)/compiler.mk include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,38 @@
{
"siemens plc":
{
"device type": "PLC",
"control type": "HSC",
"info":
{
"plc ability" : 1,
"plc device id": 1,
"soft version" : 1,
"hardware version": 1,
"date": "2022-1-28",
"vendor": "siemens",
"model":"S300"
},
"serial config":
{
"serial type":"485",
"station id" : "station1",
"serial port" : 1
},
"network config":
{
"ip addr" : "192.168.250.5",
"ip port" : 4840
},
"interface":
{
"inhybridnet":"OPCUA",
"transport":"TCP",
"ip address": "192.168.250.5",
"attribute" : "1"
}
}
}

View File

@ -1,4 +1,8 @@
#include "cJSON.h"
void control_init(void) void control_init(void)
{ {
@ -6,6 +10,12 @@ void control_init(void)
void control_read_file() void control_read_file()
{ {
} }

View File

@ -171,9 +171,6 @@ int PrivMutexDelete(pthread_mutex_t *p_mutex);
int PrivMutexObtain(pthread_mutex_t *p_mutex); int PrivMutexObtain(pthread_mutex_t *p_mutex);
int PrivMutexAbandon(pthread_mutex_t *p_mutex); int PrivMutexAbandon(pthread_mutex_t *p_mutex);
/*********************semaphore**********************/ /*********************semaphore**********************/
int PrivSemaphoreCreate(sem_t *sem, int pshared, unsigned int value); int PrivSemaphoreCreate(sem_t *sem, int pshared, unsigned int value);

@ -1 +0,0 @@
Subproject commit 562239ecb2d84dd9de2dd206da41df19602e20cb

@ -1 +0,0 @@
Subproject commit 3fede42098e5883f336d846ac30edfe749899494

View File

@ -23,6 +23,7 @@ Author: AIIT XUOS Lab
Modification: Modification:
1. support imxrt1052-board MPUclockmemory init 1. support imxrt1052-board MPUclockmemory init
2. support imxrt1052-board uartsemcsdio driver init 2. support imxrt1052-board uartsemcsdio driver init
3. support imxrt1052-board I2C, SPI, ADC, RTC driver init
*************************************************/ *************************************************/
#include "fsl_common.h" #include "fsl_common.h"
@ -67,6 +68,9 @@ int MountSDCard(void)
#include <connect_ethernet.h> #include <connect_ethernet.h>
#include <connect_uart.h> #include <connect_uart.h>
#include <connect_adc.h>
#include <connect_spi.h>
#include <connect_rtc.h>
#define NVIC_PRIORITYGROUP_0 0x00000007U /*!< 0 bits for pre-emption priority #define NVIC_PRIORITYGROUP_0 0x00000007U /*!< 0 bits for pre-emption priority
4 bits for subpriority */ 4 bits for subpriority */
@ -660,6 +664,18 @@ void InitBoardHardware()
Imrt1052HwUartInit(); Imrt1052HwUartInit();
#endif #endif
#ifdef BSP_USING_ADC
Imrt1052HwAdcInit();
#endif
#ifdef BSP_USING_SPI
Imrt1052HwSpiInit();
#endif
#ifdef BSP_USING_RTC
Imrt1052HwRtcInit();
#endif
InstallConsole(KERNEL_CONSOLE_BUS_NAME, KERNEL_CONSOLE_DRV_NAME, KERNEL_CONSOLE_DEVICE_NAME); InstallConsole(KERNEL_CONSOLE_BUS_NAME, KERNEL_CONSOLE_DRV_NAME, KERNEL_CONSOLE_DEVICE_NAME);
#ifdef BSP_USING_SDIO #ifdef BSP_USING_SDIO

View File

@ -2,7 +2,15 @@ export CROSS_COMPILE ?=/usr/bin/arm-none-eabi-
export CFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb export CFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb
export AFLAGS := -c -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -x assembler-with-cpp -Wa,-mimplicit-it=thumb -gdwarf-2 export AFLAGS := -c -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -x assembler-with-cpp -Wa,-mimplicit-it=thumb -gdwarf-2
### if use USB function, use special lds file because USB uses ITCM
ifeq ($(CONFIG_BSP_USING_USB),y)
export LFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi_ok1052-c.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link-usb.lds
else
export LFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi_ok1052-c.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link.lds export LFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi_ok1052-c.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link.lds
endif
export CXXFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g export CXXFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g
export APPLFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi_app.map,-cref,-u, -T $(BSP_ROOT)/link_userspace.lds export APPLFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi_app.map,-cref,-u, -T $(BSP_ROOT)/link_userspace.lds

View File

@ -5,19 +5,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* 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 board.h * @file board.h
* @brief define imxrt1052-board init configure and start-up function * @brief define imxrt1052-board init configure and start-up function

View File

@ -71,6 +71,8 @@ void BOARD_InitBootPins(void);
* *
*/ */
void BOARD_InitPins(void); void BOARD_InitPins(void);
void BOARD_InitI2C1Pins(void);
void BOARD_InitSPIPins(void);
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View File

@ -0,0 +1,250 @@
/*
** ###################################################################
** Processors: MIMXRT1052CVJ5B
** MIMXRT1052CVL5B
** MIMXRT1052DVJ6B
** MIMXRT1052DVL6B
**
** Compiler: GNU C Compiler
** Reference manual: IMXRT1050RM Rev.1, 03/2018
** Version: rev. 1.0, 2018-09-21
** Build: b180921
**
** Abstract:
** Linker file for the GNU C Compiler
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2018 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** ###################################################################
*/
/**
* @file link.lds
* @brief ok1052-c Linker script
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-05-28
*/
/*************************************************
File name: link.lds
Description: ok1052-c Linker script
Others: take MIMXRT1052xxxxx_flexspi_nor.ld for references
History:
1. Date: 2021-05-28
Author: AIIT XUOS Lab
Modification:
1. add shell cmd table and g_service_table
*************************************************/
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x1000;
/* Specify the memory areas */
MEMORY
{
m_interrupts (RX) : ORIGIN = 0x60002000, LENGTH = 0x00000400
m_text (RX) : ORIGIN = 0x60002400, LENGTH = 0x03FFDC00
m_data (RW) : ORIGIN = 0x20000000, LENGTH = 0x00020000
m_data2 (RW) : ORIGIN = 0x20200000, LENGTH = 0x00060000
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into internal RAM */
.interrupts :
{
__VECTOR_TABLE = .;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} > m_interrupts
__VECTOR_RAM = __VECTOR_TABLE;
__RAM_VECTOR_TABLE_SIZE_BYTES = 0x0;
/* The program code and other data goes into internal RAM */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
/* section information for shell */
. = ALIGN(4);
_shell_command_start = .;
KEEP (*(shellCommand))
_shell_command_end = .;
. = ALIGN(4);
__isrtbl_idx_start = .;
KEEP(*(.isrtbl.idx))
__isrtbl_start = .;
KEEP(*(.isrtbl))
__isrtbl_end = .;
. = ALIGN(4);
PROVIDE(g_service_table_start = ABSOLUTE(.));
KEEP(*(.g_service_table))
PROVIDE(g_service_table_end = ABSOLUTE(.));
} > m_text
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > m_text
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > m_text
.ctors :
{
__CTOR_LIST__ = .;
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
} > m_text
.dtors :
{
__DTOR_LIST__ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
} > m_text
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} > m_text
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} > m_text
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} > m_text
__etext = .; /* define a global symbol at end of code */
__DATA_ROM = .; /* Symbol is used by startup for data initialization */
.data : AT(__DATA_ROM)
{
. = ALIGN(4);
__DATA_RAM = .;
__data_start__ = .; /* create a global symbol at data start */
*(m_usb_dma_init_data)
*(.data) /* .data sections */
*(.data*) /* .data* sections */
KEEP(*(.jcr*))
. = ALIGN(4);
__data_end__ = .; /* define a global symbol at data end */
} > m_data
__NDATA_ROM = __DATA_ROM + (__data_end__ - __data_start__);
.ncache.init : AT(__NDATA_ROM)
{
__noncachedata_start__ = .; /* create a global symbol at ncache data start */
*(NonCacheable.init)
. = ALIGN(4);
__noncachedata_init_end__ = .; /* create a global symbol at initialized ncache data end */
} > m_data
. = __noncachedata_init_end__;
.ncache :
{
*(NonCacheable)
. = ALIGN(4);
__noncachedata_end__ = .; /* define a global symbol at ncache data end */
} > m_data
__DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__);
text_end = ORIGIN(m_text) + LENGTH(m_text);
ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data")
/* Uninitialized data section */
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
. = ALIGN(4);
__START_BSS = .;
__bss_start__ = .;
*(m_usb_dma_noninit_data)
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
__END_BSS = .;
} > m_data
.stack :
{
. = ALIGN(8);
stack_start = .;
. += STACK_SIZE;
stack_end = .;
__StackTop = .;
heap_start = .;
} > m_data
PROVIDE(heap_end = ORIGIN(m_data) + LENGTH(m_data));
.ARM.attributes 0 : { *(.ARM.attributes) }
}

View File

@ -241,9 +241,9 @@ SECTIONS
stack_end = .; stack_end = .;
__StackTop = .; __StackTop = .;
heap_start = .; heap_start = .;
} > m_data } > m_data2
PROVIDE(heap_end = ORIGIN(m_data) + LENGTH(m_data)); PROVIDE(heap_end = ORIGIN(m_data2) + LENGTH(m_data2));
.ARM.attributes 0 : { *(.ARM.attributes) } .ARM.attributes 0 : { *(.ARM.attributes) }
} }

View File

@ -11,6 +11,50 @@ menuconfig BSP_USING_LWIP
default n default n
select RESOURCES_LWIP select RESOURCES_LWIP
menuconfig BSP_USING_GPIO
bool "Using GPIO device "
default y
select RESOURCES_PIN
if BSP_USING_GPIO
source "$BSP_DIR/third_party_driver/gpio/Kconfig"
endif
menuconfig BSP_USING_I2C
bool "Using I2C device"
default y
select RESOURCES_I2C
if BSP_USING_I2C
source "$BSP_DIR/third_party_driver/i2c/Kconfig"
endif
menuconfig BSP_USING_ADC
bool "Using ADC device"
default y
select RESOURCES_ADC
if BSP_USING_ADC
source "$BSP_DIR/third_party_driver/adc/Kconfig"
endif
menuconfig BSP_USING_SPI
bool "Using SPI device"
default y
select RESOURCES_SPI
if BSP_USING_SPI
source "$BSP_DIR/third_party_driver/spi/Kconfig"
endif
menuconfig BSP_USING_RTC
bool "Using RTC device"
default n
select RESOURCES_RTC
if BSP_USING_RTC
source "$BSP_DIR/third_party_driver/rtc/Kconfig"
endif
menuconfig BSP_USING_SEMC menuconfig BSP_USING_SEMC
bool "Using SEMC device" bool "Using SEMC device"
default n default n

View File

@ -8,10 +8,27 @@ ifeq ($(CONFIG_BSP_USING_LWIP),y)
SRC_DIR += ethernet SRC_DIR += ethernet
endif endif
ifeq ($(CONFIG_BSP_USING_I2C),y)
SRC_DIR += i2c
endif
ifeq ($(CONFIG_BSP_USING_ADC),y)
SRC_DIR += adc
endif
ifeq ($(CONFIG_BSP_USING_SPI),y)
SRC_DIR += spi
endif
ifeq ($(CONFIG_BSP_USING_SEMC),y) ifeq ($(CONFIG_BSP_USING_SEMC),y)
SRC_DIR += semc SRC_DIR += semc
endif endif
ifeq ($(CONFIG_BSP_USING_RTC),y)
SRC_DIR += rtc
endif
ifeq ($(CONFIG_BSP_USING_SDIO),y) ifeq ($(CONFIG_BSP_USING_SDIO),y)
SRC_DIR += sdio SRC_DIR += sdio
endif endif

View File

@ -0,0 +1,29 @@
config BSP_USING_ADC1
bool "Enable ADC1"
default y
if BSP_USING_ADC1
config ADC_BUS_NAME_1
string "adc bus 1 name"
default "adc1"
config ADC_DRV_NAME_1
string "adc bus 1 driver name"
default "adc1_drv"
config ADC_1_DEVICE_NAME_0
string "adc bus 1 device name"
default "adc1_dev"
endif
config BSP_USING_ADC2
bool "Enable ADC2"
default y
if BSP_USING_ADC2
config ADC_BUS_NAME_2
string "adc bus 2 name"
default "adc2"
config ADC_DRV_NAME_2
string "adc bus 2 driver name"
default "adc2_drv"
config ADC_2_DEVICE_NAME_0
string "adc bus 2 device name"
default "adc2_dev"
endif

View File

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

View File

@ -0,0 +1,295 @@
/*
* Copyright (c) 2022 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_adc.c
* @brief Demo for ADC function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022.1.18
*/
#include "board.h"
#include "fsl_adc.h"
#include "fsl_common.h"
#include "dev_adc.h"
#include "bus_adc.h"
#include "connect_adc.h"
#define ADC1_BASE_ADDR ADC1
#define ADC1_IRQ ADC1_IRQn
#define ADC1_USER_CHANNEL 3U
#define ADC1_CHANNEL_GROUP 0U
#define ADC2_BASE_ADDR ADC2
#define ADC2_IRQ ADC2_IRQn
#define ADC2_USER_CHANNEL 4U
#define ADC2_CHANNEL_GROUP 0U
#define adc_print KPrintf
volatile bool adc1_flag;
volatile uint32_t adc1_val;
volatile uint32_t adc1_irq_cnt;
volatile bool adc2_flag;
volatile uint32_t adc2_val;
volatile uint32_t adc2_irq_cnt;
/*******************************************************************************
* Code
******************************************************************************/
void ADC1_IRQHandler(int vector, void *param)
{
adc1_flag = true;
/* Read conversion result to clear the conversion completed flag. */
adc1_val = ADC_GetChannelConversionValue(ADC1_BASE_ADDR, ADC1_CHANNEL_GROUP);
adc1_irq_cnt++;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
DECLARE_HW_IRQ(ADC1_IRQn, ADC1_IRQHandler, NONE);
void ADC2_IRQHandler(int vector, void *param)
{
adc2_flag = true;
/* Read conversion result to clear the conversion completed flag. */
adc2_val = ADC_GetChannelConversionValue(ADC2_BASE_ADDR, ADC2_CHANNEL_GROUP);
adc2_irq_cnt++;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
DECLARE_HW_IRQ(ADC2_IRQn, ADC2_IRQHandler, NONE);
uint32 Imrt1052AdcOpen(void *dev)
{
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev;
adc_config_t adc_cfg;
#ifdef BSP_USING_ADC1
if (0 == strncmp(adc_dev->haldev.dev_name, ADC_1_DEVICE_NAME_0, NAME_NUM_MAX)) {
EnableIRQ(ADC1_IRQn);
ADC_GetDefaultConfig(&adc_cfg);
ADC_Init(ADC1, &adc_cfg);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
ADC_EnableHardwareTrigger(ADC1, false);
#endif
/* Do auto hardware calibration. */
if (kStatus_Success == ADC_DoAutoCalibration(ADC1))
{
adc_print("ADC_DoAntoCalibration() Done.\r\n");
}
else
{
adc_print("ADC_DoAutoCalibration() Failed.\r\n");
}
}
#endif
#ifdef BSP_USING_ADC2
if (0 == strncmp(adc_dev->haldev.dev_name, ADC_2_DEVICE_NAME_0, NAME_NUM_MAX)) {
EnableIRQ(ADC2_IRQn);
ADC_GetDefaultConfig(&adc_cfg);
ADC_Init(ADC2, &adc_cfg);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
ADC_EnableHardwareTrigger(ADC2, false);
#endif
/* Do auto hardware calibration. */
if (kStatus_Success == ADC_DoAutoCalibration(ADC2))
{
adc_print("ADC_DoAntoCalibration() Done.\r\n");
}
else
{
adc_print("ADC_DoAutoCalibration() Failed.\r\n");
}
}
#endif
return EOK;
}
uint32 Imrt1052AdcClose(void *dev)
{
return EOK;
}
uint32 Imrt1052AdcRead(void *dev, struct BusBlockReadParam *read_param)
{
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev;
adc_channel_config_t ch_cfg;
#ifdef BSP_USING_ADC1
if (0 == strncmp(adc_dev->haldev.dev_name, ADC_1_DEVICE_NAME_0, NAME_NUM_MAX)) {
/* Configure the user channel and interrupt. */
ch_cfg.channelNumber = ADC1_USER_CHANNEL;
ch_cfg.enableInterruptOnConversionCompleted = true;
adc1_irq_cnt = 0U; /* Clear the interrupt counter. */
adc1_flag = false;
ADC_SetChannelConfig(ADC1, ADC1_CHANNEL_GROUP, &ch_cfg);
while (adc1_flag == false);
adc_print("ADC Value: %d\r\n", adc1_val);
adc_print("ADC Interrupt Counter: %d\r\n", adc1_irq_cnt);
}
#endif
#ifdef BSP_USING_ADC2
if (0 == strncmp(adc_dev->haldev.dev_name, ADC_2_DEVICE_NAME_0, NAME_NUM_MAX)) {
/* Configure the user channel and interrupt. */
ch_cfg.channelNumber = ADC2_USER_CHANNEL;
ch_cfg.enableInterruptOnConversionCompleted = true;
adc2_irq_cnt = 0U; /* Clear the interrupt counter. */
adc2_flag = false;
ADC_SetChannelConfig(ADC2, ADC2_CHANNEL_GROUP, &ch_cfg);
while (adc2_flag == false);
adc_print("ADC Value: %d\r\n", adc2_val);
adc_print("ADC Interrupt Counter: %d\r\n", adc2_irq_cnt);
}
#endif
return adc1_val;
}
static uint32 Imrt1052AdcDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
uint8 adc_channel;
struct AdcDriver *adc_drv = (struct AdcDriver *)drv;
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)adc_drv->driver.owner_bus->owner_haldev;
struct Imrt1052HwAdc *adc_cfg = (struct Imrt1052HwAdc *)adc_dev->haldev.private_data;
switch (configure_info->configure_cmd)
{
case OPE_CFG:
adc_cfg->adc_channel = *(uint8 *)configure_info->private_data;
if (adc_cfg->adc_channel > 18) {
KPrintf("Imrt1052AdcDrvConfigure set adc channel(0-18) %u error!", adc_cfg->adc_channel);
adc_cfg->adc_channel = 0;
ret = ERROR;
}
break;
default:
break;
}
return ret;
}
static const struct AdcDevDone dev_done =
{
Imrt1052AdcOpen,
Imrt1052AdcClose,
NONE,
Imrt1052AdcRead,
};
int Imrt1052HwAdcInit(void)
{
x_err_t ret = EOK;
#ifdef BSP_USING_ADC1
static struct AdcBus adc1_bus;
static struct AdcDriver adc1_drv;
static struct AdcHardwareDevice adc1_dev;
static struct Imrt1052HwAdc adc1_cfg;
adc1_drv.configure = Imrt1052AdcDrvConfigure;
ret = AdcBusInit(&adc1_bus, ADC_BUS_NAME_1);
if (ret != EOK) {
KPrintf("ADC1 bus init error %d\n", ret);
return ERROR;
}
ret = AdcDriverInit(&adc1_drv, ADC_DRV_NAME_1);
if (ret != EOK) {
KPrintf("ADC1 driver init error %d\n", ret);
return ERROR;
}
ret = AdcDriverAttachToBus(ADC_DRV_NAME_1, ADC_BUS_NAME_1);
if (ret != EOK) {
KPrintf("ADC1 driver attach error %d\n", ret);
return ERROR;
}
adc1_dev.adc_dev_done = &dev_done;
ret = AdcDeviceRegister(&adc1_dev, (void *)&adc1_cfg, ADC_1_DEVICE_NAME_0);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
ret = AdcDeviceAttachToBus(ADC_1_DEVICE_NAME_0, ADC_BUS_NAME_1);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
#endif
#ifdef BSP_USING_ADC2
static struct AdcBus adc2_bus;
static struct AdcDriver adc2_drv;
static struct AdcHardwareDevice adc2_dev;
static struct Imrt1052HwAdc adc2_cfg;
adc2_drv.configure = Imrt1052AdcDrvConfigure;
ret = AdcBusInit(&adc2_bus, ADC_BUS_NAME_2);
if (ret != EOK) {
KPrintf("ADC2 bus init error %d\n", ret);
return ERROR;
}
ret = AdcDriverInit(&adc2_drv, ADC_DRV_NAME_2);
if (ret != EOK) {
KPrintf("ADC2 driver init error %d\n", ret);
return ERROR;
}
ret = AdcDriverAttachToBus(ADC_DRV_NAME_2, ADC_BUS_NAME_2);
if (ret != EOK) {
KPrintf("ADC2 driver attach error %d\n", ret);
return ERROR;
}
adc2_dev.adc_dev_done = &dev_done;
ret = AdcDeviceRegister(&adc2_dev, (void *)&adc2_cfg, ADC_2_DEVICE_NAME_0);
if (ret != EOK) {
KPrintf("ADC2 device register error %d\n", ret);
return ERROR;
}
ret = AdcDeviceAttachToBus(ADC_2_DEVICE_NAME_0, ADC_BUS_NAME_2);
if (ret != EOK) {
KPrintf("ADC2 device register error %d\n", ret);
return ERROR;
}
#endif
return ret;
}

View File

@ -0,0 +1,394 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_adc.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.adc_12b1msps_sar"
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for ADC module.
*
* @param base ADC peripheral base address
*/
static uint32_t ADC_GetInstance(ADC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to ADC bases for each instance. */
static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to ADC clocks for each instance. */
static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t ADC_GetInstance(ADC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_adcBases); instance++)
{
if (s_adcBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_adcBases));
return instance;
}
/*!
* brief Initialize the ADC module.
*
* param base ADC peripheral base address.
* param config Pointer to "adc_config_t" structure.
*/
void ADC_Init(ADC_Type *base, const adc_config_t *config)
{
assert(NULL != config);
uint32_t tmp32;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock. */
CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* ADCx_CFG */
tmp32 = base->CFG & (ADC_CFG_AVGS_MASK | ADC_CFG_ADTRG_MASK); /* Reserve AVGS and ADTRG bits. */
tmp32 |= ADC_CFG_REFSEL(config->referenceVoltageSource) | ADC_CFG_ADSTS(config->samplePeriodMode) |
ADC_CFG_ADICLK(config->clockSource) | ADC_CFG_ADIV(config->clockDriver) | ADC_CFG_MODE(config->resolution);
if (config->enableOverWrite)
{
tmp32 |= ADC_CFG_OVWREN_MASK;
}
if (config->enableLongSample)
{
tmp32 |= ADC_CFG_ADLSMP_MASK;
}
if (config->enableLowPower)
{
tmp32 |= ADC_CFG_ADLPC_MASK;
}
if (config->enableHighSpeed)
{
tmp32 |= ADC_CFG_ADHSC_MASK;
}
base->CFG = tmp32;
/* ADCx_GC */
tmp32 = base->GC & ~(ADC_GC_ADCO_MASK | ADC_GC_ADACKEN_MASK);
if (config->enableContinuousConversion)
{
tmp32 |= ADC_GC_ADCO_MASK;
}
if (config->enableAsynchronousClockOutput)
{
tmp32 |= ADC_GC_ADACKEN_MASK;
}
base->GC = tmp32;
}
/*!
* brief De-initializes the ADC module.
*
* param base ADC peripheral base address.
*/
void ADC_Deinit(ADC_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the clock. */
CLOCK_DisableClock(s_adcClocks[ADC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* brief Gets an available pre-defined settings for the converter's configuration.
*
* This function initializes the converter configuration structure with available settings. The default values are:
* code
* config->enableAsynchronousClockOutput = true;
* config->enableOverWrite = false;
* config->enableContinuousConversion = false;
* config->enableHighSpeed = false;
* config->enableLowPower = false;
* config->enableLongSample = false;
* config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0;
* config->samplePeriodMode = kADC_SamplePeriod2or12Clocks;
* config->clockSource = kADC_ClockSourceAD;
* config->clockDriver = kADC_ClockDriver1;
* config->resolution = kADC_Resolution12Bit;
* endcode
* param base ADC peripheral base address.
* param config Pointer to the configuration structure.
*/
void ADC_GetDefaultConfig(adc_config_t *config)
{
assert(NULL != config);
/* Initializes the configure structure to zero. */
memset(config, 0, sizeof(*config));
config->enableAsynchronousClockOutput = true;
config->enableOverWrite = false;
config->enableContinuousConversion = false;
config->enableHighSpeed = false;
config->enableLowPower = false;
config->enableLongSample = false;
config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0;
config->samplePeriodMode = kADC_SamplePeriod2or12Clocks;
config->clockSource = kADC_ClockSourceAD;
config->clockDriver = kADC_ClockDriver1;
config->resolution = kADC_Resolution12Bit;
}
/*!
* brief Configures the conversion channel.
*
* This operation triggers the conversion when in software trigger mode. When in hardware trigger mode, this API
* configures the channel while the external trigger source helps to trigger the conversion.
*
* Note that the "Channel Group" has a detailed description.
* To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC has more than one
* group of status and control registers, one for each conversion. The channel group parameter indicates which group of
* registers are used, for example channel group 0 is for Group A registers and channel group 1 is for Group B
* registers. The
* channel groups are used in a "ping-pong" approach to control the ADC operation. At any point, only one of
* the channel groups is actively controlling ADC conversions. The channel group 0 is used for both software and
* hardware
* trigger modes. Channel groups 1 and greater indicate potentially multiple channel group registers for
* use only in hardware trigger mode. See the chip configuration information in the appropriate MCU reference manual
* about the
* number of SC1n registers (channel groups) specific to this device. None of the channel groups 1 or greater are used
* for software trigger operation. Therefore, writing to these channel groups does not initiate a new conversion.
* Updating the channel group 0 while a different channel group is actively controlling a conversion is allowed and
* vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a
* conversion aborts the current conversion.
*
* param base ADC peripheral base address.
* param channelGroup Channel group index.
* param config Pointer to the "adc_channel_config_t" structure for the conversion channel.
*/
void ADC_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc_channel_config_t *config)
{
assert(NULL != config);
assert(channelGroup < FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT);
uint32_t tmp32;
tmp32 = ADC_HC_ADCH(config->channelNumber);
if (config->enableInterruptOnConversionCompleted)
{
tmp32 |= ADC_HC_AIEN_MASK;
}
base->HC[channelGroup] = tmp32;
}
/*
*To complete calibration, the user must follow the below procedure:
* 1. Configure ADC_CFG with actual operating values for maximum accuracy.
* 2. Configure the ADC_GC values along with CAL bit.
* 3. Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC.
* 4. When CAL bit becomes '0' then check the CALF status and COCO[0] bit status.
*/
/*!
* brief Automates the hardware calibration.
*
* This auto calibration helps to adjust the plus/minus side gain automatically.
* Execute the calibration before using the converter. Note that the software trigger should be used
* during calibration.
*
* param base ADC peripheral base address.
*
* return Execution status.
* retval kStatus_Success Calibration is done successfully.
* retval kStatus_Fail Calibration has failed.
*/
status_t ADC_DoAutoCalibration(ADC_Type *base)
{
status_t status = kStatus_Success;
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
bool bHWTrigger = false;
/* The calibration would be failed when in hardwar mode.
* Remember the hardware trigger state here and restore it later if the hardware trigger is enabled.*/
if (0U != (ADC_CFG_ADTRG_MASK & base->CFG))
{
bHWTrigger = true;
ADC_EnableHardwareTrigger(base, false);
}
#endif
/* Clear the CALF and launch the calibration. */
base->GS = ADC_GS_CALF_MASK; /* Clear the CALF. */
base->GC |= ADC_GC_CAL_MASK; /* Launch the calibration. */
/* Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC. */
while (0U != (base->GC & ADC_GC_CAL_MASK))
{
/* Check the CALF when the calibration is active. */
if (0U != (ADC_GetStatusFlags(base) & kADC_CalibrationFailedFlag))
{
status = kStatus_Fail;
break;
}
}
/* When CAL bit becomes '0' then check the CALF status and COCO[0] bit status. */
if (0U == ADC_GetChannelStatusFlags(base, 0U)) /* Check the COCO[0] bit status. */
{
status = kStatus_Fail;
}
if (0U != (ADC_GetStatusFlags(base) & kADC_CalibrationFailedFlag)) /* Check the CALF status. */
{
status = kStatus_Fail;
}
/* Clear conversion done flag. */
ADC_GetChannelConversionValue(base, 0U);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
/* Restore original trigger mode. */
if (true == bHWTrigger)
{
ADC_EnableHardwareTrigger(base, true);
}
#endif
return status;
}
/*!
* brief Set user defined offset.
*
* param base ADC peripheral base address.
* param config Pointer to "adc_offest_config_t" structure.
*/
void ADC_SetOffsetConfig(ADC_Type *base, const adc_offest_config_t *config)
{
assert(NULL != config);
uint32_t tmp32;
tmp32 = ADC_OFS_OFS(config->offsetValue);
if (config->enableSigned)
{
tmp32 |= ADC_OFS_SIGN_MASK;
}
base->OFS = tmp32;
}
/*!
* brief Configures the hardware compare mode.
*
* The hardware compare mode provides a way to process the conversion result automatically by using hardware. Only the
* result
* in the compare range is available. To compare the range, see "adc_hardware_compare_mode_t" or the appopriate
* reference
* manual for more information.
*
* param base ADC peripheral base address.
* param Pointer to "adc_hardware_compare_config_t" structure.
*
*/
void ADC_SetHardwareCompareConfig(ADC_Type *base, const adc_hardware_compare_config_t *config)
{
uint32_t tmp32;
tmp32 = base->GC & ~(ADC_GC_ACFE_MASK | ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK);
if (NULL == config) /* Pass "NULL" to disable the feature. */
{
base->GC = tmp32;
return;
}
/* Enable the feature. */
tmp32 |= ADC_GC_ACFE_MASK;
/* Select the hardware compare working mode. */
switch (config->hardwareCompareMode)
{
case kADC_HardwareCompareMode0:
break;
case kADC_HardwareCompareMode1:
tmp32 |= ADC_GC_ACFGT_MASK;
break;
case kADC_HardwareCompareMode2:
tmp32 |= ADC_GC_ACREN_MASK;
break;
case kADC_HardwareCompareMode3:
tmp32 |= ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK;
break;
default:
break;
}
base->GC = tmp32;
/* Load the compare values. */
tmp32 = ADC_CV_CV1(config->value1) | ADC_CV_CV2(config->value2);
base->CV = tmp32;
}
/*!
* brief Configures the hardware average mode.
*
* The hardware average mode provides a way to process the conversion result automatically by using hardware. The
* multiple
* conversion results are accumulated and averaged internally making them easier to read.
*
* param base ADC peripheral base address.
* param mode Setting the hardware average mode. See "adc_hardware_average_mode_t".
*/
void ADC_SetHardwareAverageConfig(ADC_Type *base, adc_hardware_average_mode_t mode)
{
uint32_t tmp32;
if (mode == kADC_HardwareAverageDiasable)
{
base->GC &= ~ADC_GC_AVGE_MASK;
}
else
{
tmp32 = base->CFG & ~ADC_CFG_AVGS_MASK;
tmp32 |= ADC_CFG_AVGS(mode);
base->CFG = tmp32;
base->GC |= ADC_GC_AVGE_MASK; /* Enable the hardware compare. */
}
}
/*!
* brief Clears the converter's status falgs.
*
* param base ADC peripheral base address.
* param mask Mask value for the cleared flags. See "adc_status_flags_t".
*/
void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask)
{
uint32_t tmp32 = 0;
if (0U != (mask & kADC_CalibrationFailedFlag))
{
tmp32 |= ADC_GS_CALF_MASK;
}
if (0U != (mask & kADC_ConversionActiveFlag))
{
tmp32 |= ADC_GS_ADACT_MASK;
}
base->GS = tmp32;
}

View File

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

View File

@ -6,18 +6,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_cache.c * @file fsl_cache.c
* @brief cache drivers * @brief cache drivers
@ -45,9 +33,9 @@
#define L2CACHE_1KBCOVERTOB 1024U #define L2CACHE_1KBCOVERTOB 1024U
#define L2CACHE_SAMLLWAYS_SIZE 16U #define L2CACHE_SAMLLWAYS_SIZE 16U
#define L2CACHE_LOCKDOWN_REGNUM 8 /*!< Lock down register numbers.*/ #define L2CACHE_LOCKDOWN_REGNUM 8 /*!< Lock down register numbers.*/
/******************************************************************************* /*******************************************************************************
* Prototypes * Prototypes
******************************************************************************/ ******************************************************************************/
/*! /*!
* @brief Set for all ways and waiting for the operation finished. * @brief Set for all ways and waiting for the operation finished.
* This is provided for all the background operations. * This is provided for all the background operations.

View File

@ -5,18 +5,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_clock.c * @file fsl_clock.c
* @brief clock drivers * @brief clock drivers

View File

@ -7,18 +7,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_common.c * @file fsl_common.c
* @brief common drivers * @brief common drivers

View File

@ -749,6 +749,115 @@ BOARD_InitPins:
* Description : Configures pin routing and optionally pin electrical features. * Description : Configures pin routing and optionally pin electrical features.
* *
* END ****************************************************************************************************************/ * END ****************************************************************************************************************/
void BOARD_InitSPIPins ( void )
{
IOMUXC_SetPinMux (
IOMUXC_GPIO_AD_B1_15_LPSPI3_SCK, /* GPIO_AD_B0_00 is configured as LPSPI3_SCK */
0U ); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinMux (
IOMUXC_GPIO_AD_B1_14_LPSPI3_SDO, /* GPIO_AD_B0_01 is configured as LPSPI3_SDO */
0U ); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinMux (
IOMUXC_GPIO_AD_B1_13_LPSPI3_SDI, /* GPIO_AD_B0_02 is configured as LPSPI3_SDI */
0U ); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinMux (
IOMUXC_GPIO_AD_B1_12_LPSPI3_PCS0, /* GPIO_AD_B0_03 is configured as LPSPI3_PCS0 */
0U ); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinMux (
IOMUXC_GPIO_SD_B0_00_LPSPI1_SCK, /* GPIO_SD_B0_00 is configured as LPSPI1_SCK */
0U ); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinMux (
IOMUXC_GPIO_SD_B0_01_LPSPI1_PCS0, /* GPIO_SD_B0_01 is configured as LPSPI1_PCS0 */
0U ); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinMux (
IOMUXC_GPIO_SD_B0_02_LPSPI1_SDO, /* GPIO_SD_B0_02 is configured as LPSPI1_SDO */
0U ); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinMux (
IOMUXC_GPIO_SD_B0_03_LPSPI1_SDI, /* GPIO_SD_B0_03 is configured as LPSPI1_SDI */
0U ); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinConfig (
IOMUXC_GPIO_SD_B0_00_LPSPI1_SCK, /* GPIO_AD_B0_00 PAD functional properties : */
0x10B0u ); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Disabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 100K Ohm Pull Down
Hyst. Enable Field: Hysteresis Disabled */
IOMUXC_SetPinConfig (
IOMUXC_GPIO_AD_B1_14_LPSPI3_SDO, /* GPIO_AD_B0_01 PAD functional properties : */
0x10B0u ); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Disabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 100K Ohm Pull Down
Hyst. Enable Field: Hysteresis Disabled */
IOMUXC_SetPinConfig (
IOMUXC_GPIO_AD_B1_13_LPSPI3_SDI, /* GPIO_AD_B0_02 PAD functional properties : */
0x10B0u ); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Disabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 100K Ohm Pull Down
Hyst. Enable Field: Hysteresis Disabled */
IOMUXC_SetPinConfig (
IOMUXC_GPIO_AD_B1_12_LPSPI3_PCS0, /* GPIO_AD_B0_03 PAD functional properties : */
0x10B0u ); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Disabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 100K Ohm Pull Down
Hyst. Enable Field: Hysteresis Disabled */
IOMUXC_SetPinConfig (
IOMUXC_GPIO_SD_B0_00_LPSPI1_SCK, /* GPIO_SD_B0_00 PAD functional properties : */
0x10B0u ); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Disabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 100K Ohm Pull Down
Hyst. Enable Field: Hysteresis Disabled */
IOMUXC_SetPinConfig (
IOMUXC_GPIO_SD_B0_01_LPSPI1_PCS0, /* GPIO_SD_B0_01 PAD functional properties : */
0x10B0u ); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Disabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 100K Ohm Pull Down
Hyst. Enable Field: Hysteresis Disabled */
IOMUXC_SetPinConfig (
IOMUXC_GPIO_SD_B0_02_LPSPI1_SDO, /* GPIO_SD_B0_02 PAD functional properties : */
0x10B0u ); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Disabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 100K Ohm Pull Down
Hyst. Enable Field: Hysteresis Disabled */
IOMUXC_SetPinConfig (
IOMUXC_GPIO_SD_B0_03_LPSPI1_SDI, /* GPIO_SD_B0_03 PAD functional properties : */
0x10B0u ); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Disabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 100K Ohm Pull Down
Hyst. Enable Field: Hysteresis Disabled */
}
void BOARD_InitPins(void) { void BOARD_InitPins(void) {
CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */ CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
@ -964,6 +1073,36 @@ void BOARD_InitPins(void) {
Hyst. Enable Field: Hysteresis Disabled */ Hyst. Enable Field: Hysteresis Disabled */
} }
void BOARD_InitI2C1Pins ( void )
{
CLOCK_EnableClock ( kCLOCK_Iomuxc ); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
IOMUXC_SetPinMux (
IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL, /* GPIO_AD_B1_00 is configured as LPI2C1_SCL */
1U ); /* Software Input On Field: Force input path of pad GPIO_AD_B1_00 */
IOMUXC_SetPinMux (
IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA, /* GPIO_AD_B1_01 is configured as LPI2C1_SDA */
1U ); /* Software Input On Field: Force input path of pad GPIO_AD_B1_01 */
IOMUXC_SetPinConfig (
IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL, /* GPIO_AD_B1_00 PAD functional properties : */
0xD8B0u ); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Enabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 22K Ohm Pull Up
Hyst. Enable Field: Hysteresis Disabled */
IOMUXC_SetPinConfig (
IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA, /* GPIO_AD_B1_01 PAD functional properties : */
0xD8B0u ); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Enabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 22K Ohm Pull Up
Hyst. Enable Field: Hysteresis Disabled */
}
/*********************************************************************************************************************** /***********************************************************************************************************************
* EOF * EOF
**********************************************************************************************************************/ **********************************************************************************************************************/

View File

@ -38,18 +38,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 enet_ethernetif.c * @file enet_ethernetif.c
* @brief ethernet drivers * @brief ethernet drivers
@ -90,7 +78,6 @@
* Definitions * Definitions
******************************************************************************/ ******************************************************************************/
/******************************************************************************* /*******************************************************************************
* Code * Code
******************************************************************************/ ******************************************************************************/

View File

@ -38,18 +38,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 enet_ethernetif_kinetis.c * @file enet_ethernetif_kinetis.c
* @brief ethernet drivers * @brief ethernet drivers

View File

@ -38,18 +38,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 enet_ethernetif_lpc.c * @file enet_ethernetif_lpc.c
* @brief ethernet drivers * @brief ethernet drivers

View File

@ -6,18 +6,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_enet.c * @file fsl_enet.c
* @brief ethernet drivers * @brief ethernet drivers

View File

@ -6,18 +6,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_phy.c * @file fsl_phy.c
* @brief phy drivers for ksz8081 * @brief phy drivers for ksz8081

View File

@ -6,18 +6,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_phy.h * @file fsl_phy.h
* @brief phy drivers for ksz8081 * @brief phy drivers for ksz8081

View File

@ -0,0 +1,12 @@
config PIN_BUS_NAME
string "pin bus name"
default "pin"
config PIN_DRIVER_NAME
string "pin driver name"
default "pin_drv"
config PIN_DEVICE_NAME
string "pin device name"
default "pin_dev"

View File

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

View File

@ -0,0 +1,544 @@
/*
* Copyright (c) 2020 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-06 balanceTWK first version
* 2019-04-23 WillianChan Fix GPIO serial number disorder
*/
/**
* @file connect_gpio.c
* @brief support gpio function using bus driver framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: connect_gpio.c
Description: support gpio configure and register to bus framework
Others: take RT-Thread v4.0.2/bsp/stm32/libraries/HAL_Drivers/drv_gpio.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification: add bus driver framework support for gpio
*************************************************/
#include <device.h>
#include <board.h>
#define STM32_PIN_NUMBERS 100 // [48, 64, 100, 144]
#define ITEM_NUM(items) sizeof(items)/sizeof(items[0])
struct PinIndex
{
int index;
GPIO_Type *gpio;
uint32_t pin;
};
struct PinIrq
{
uint8 port_source;
uint8 pin_source;
enum IRQn irq_exti_channel;
uint32 exti_line;
};
static const struct PinIndex pins[] = {
{0, GPIO1, 0},
{1, GPIO1, 1},
{2, GPIO1, 2},
{3, GPIO1, 3},
{4, GPIO1, 4},
{5, GPIO1, 5},
{6, GPIO1, 6},
{7, GPIO1, 7},
{8, GPIO1, 8},
{9, GPIO1, 9},
{10, GPIO1, 10},
{11, GPIO1, 11},
{12, GPIO1, 12},
{13, GPIO1, 13},
{14, GPIO1, 14},
{15, GPIO1, 15},
{16, GPIO2, 0},
{17, GPIO2, 1},
{18, GPIO2, 2},
{19, GPIO2, 3},
{20, GPIO2, 4},
{21, GPIO2, 5},
{22, GPIO2, 6},
{23, GPIO2, 7},
{24, GPIO2, 8},
{25, GPIO2, 9},
{26, GPIO2, 10},
{27, GPIO2, 11},
{28, GPIO2, 12},
{29, GPIO2, 13},
{30, GPIO2, 14},
{31, GPIO2, 15},
{32, GPIO3, 0},
{33, GPIO3, 1},
{34, GPIO3, 2},
{35, GPIO3, 3},
{36, GPIO3, 4},
{37, GPIO3, 5},
{38, GPIO3, 6},
{39, GPIO3, 7},
{40, GPIO3, 8},
{41, GPIO3, 9},
{42, GPIO3, 10},
{43, GPIO3, 11},
{44, GPIO3, 12},
{45, GPIO3, 13},
{46, GPIO3, 14},
{47, GPIO3, 15},
{-1, 0u, -1}
};
struct PinIrqHdr pin_irq_hdr_tab[] = {};
const struct PinIndex *GetPin(uint8_t pin)
{
const struct PinIndex *index;
if (pin < ITEM_NUM(pins)){
index = &pins[pin];
if (index->index == -1)
index = NONE;
}
else{
index = NONE;
}
return index;
}
static int32 GpioConfigMode(int mode, const struct PinIndex* index)
{
gpio_pin_config_t gpio_config;
NULL_PARAM_CHECK(index);
switch (mode)
{
case GPIO_CFG_OUTPUT:
gpio_config.direction = kGPIO_DigitalOutput;
gpio_config.interruptMode = kGPIO_NoIntmode;
break;
case GPIO_CFG_INPUT:
gpio_config.direction = kGPIO_DigitalInput;
gpio_config.interruptMode = kGPIO_NoIntmode;
break;
case GPIO_CFG_INPUT_PULLUP:
gpio_config.direction = kGPIO_DigitalInput;
gpio_config.interruptMode = kGPIO_IntRisingEdge;
break;
case GPIO_CFG_INPUT_PULLDOWN:
gpio_config.direction = kGPIO_DigitalInput;
gpio_config.interruptMode = kGPIO_IntFallingEdge;
break;
case GPIO_CFG_OUTPUT_OD:
gpio_config.direction = kGPIO_DigitalOutput;
break;
default:
break;
}
GPIO_PinInit(index->gpio, index->pin, &gpio_config);
return EOK;
}
static __inline int32 Bit2Bitnum(uint32 bit)
{
for (int i = 0; i < 32; i++){
if ((1UL << i) == bit){
return i;
}
}
return -1;
}
static __inline int32 Bitno2Bit(uint32 bitno)
{
if (bitno <= 32) {
return 1UL << bitno;
}
else {
return 0;
}
}
static const struct PinIrq *GetPinIrq(uint16_t pin)
{
static struct PinIrq irq;
const struct PinIndex* index = GetPin(pin);
if (index == NONE) {
return NONE;
}
irq.exti_line = index->pin;
irq.pin_source = Bit2Bitnum(index->pin);
irq.port_source = ((uint32_t)index->gpio - GPIO1_BASE) / (GPIO2_BASE - GPIO1_BASE);
switch (irq.pin_source)
{
case 0 :
irq.irq_exti_channel = GPIO1_INT0_IRQn;
break;
case 1 :
irq.irq_exti_channel = GPIO1_INT1_IRQn;
break;
case 2 :
irq.irq_exti_channel = GPIO1_INT2_IRQn;
break;
case 3 :
irq.irq_exti_channel = GPIO1_INT3_IRQn;
break;
case 4 :
irq.irq_exti_channel = GPIO1_INT4_IRQn;
break;
case 5 :
irq.irq_exti_channel = GPIO1_INT5_IRQn;
break;
case 6 :
irq.irq_exti_channel = GPIO1_INT6_IRQn;
break;
case 7 :
irq.irq_exti_channel = GPIO1_INT7_IRQn;
break;
default :
return NONE;
}
return &irq;
};
static int32 GpioIrqRegister(int32 pin, int32 mode, void (*hdr)(void *args), void *args)
{
const struct PinIndex* index = GetPin(pin);
int32 irqindex = -1;
irqindex = Bit2Bitnum(index->pin);
if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_hdr_tab)) {
return -ENONESYS;
}
x_base level = CriticalAreaLock();
if (pin_irq_hdr_tab[irqindex].pin == pin &&
pin_irq_hdr_tab[irqindex].hdr == hdr &&
pin_irq_hdr_tab[irqindex].mode == mode &&
pin_irq_hdr_tab[irqindex].args == args
)
{
CriticalAreaUnLock(level);
return EOK;
}
if (pin_irq_hdr_tab[irqindex].pin != -1) {
CriticalAreaUnLock(level);
return -EDEV_BUSY;
}
pin_irq_hdr_tab[irqindex].pin = pin;
pin_irq_hdr_tab[irqindex].hdr = hdr;
pin_irq_hdr_tab[irqindex].mode = mode;
pin_irq_hdr_tab[irqindex].args = args;
CriticalAreaUnLock(level);
return EOK;
}
static uint32 GpioIrqFree(int32 pin)
{
const struct PinIndex* index = GetPin(pin);
int32 irqindex = -1;
irqindex = Bit2Bitnum(index->pin);
if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_hdr_tab)) {
return -ENONESYS;
}
x_base level = CriticalAreaLock();
if (pin_irq_hdr_tab[irqindex].pin == -1){
CriticalAreaUnLock(level);
return EOK;
}
pin_irq_hdr_tab[irqindex].pin = -1;
pin_irq_hdr_tab[irqindex].hdr = NONE;
pin_irq_hdr_tab[irqindex].mode = 0;
pin_irq_hdr_tab[irqindex].args = NONE;
CriticalAreaUnLock(level);
return EOK;
}
static int32 GpioIrqEnable(x_base pin)
{
const struct PinIndex* index = GetPin(pin);
int32 irqindex = -1;
const struct PinIrq *irq;
gpio_pin_config_t gpio_config;
irqindex = Bit2Bitnum(index->pin);
if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_hdr_tab)){
return -ENONESYS;
}
x_base level = CriticalAreaLock();
if (pin_irq_hdr_tab[irqindex].pin == -1) {
CriticalAreaUnLock(level);
return -ENONESYS;
}
irq = GetPinIrq(pin);
if (irq == NONE){
CriticalAreaUnLock(level);
return -ENONESYS;
}
switch (pin_irq_hdr_tab[irqindex].mode)
{
case GPIO_IRQ_EDGE_RISING:
gpio_config.direction = kGPIO_DigitalInput;
gpio_config.interruptMode = kGPIO_IntRisingEdge;
break;
case GPIO_IRQ_EDGE_FALLING:
gpio_config.direction = kGPIO_DigitalInput;
gpio_config.interruptMode = kGPIO_IntFallingEdge;
break;
case GPIO_IRQ_EDGE_BOTH:
gpio_config.direction = kGPIO_DigitalInput;
gpio_config.interruptMode = kGPIO_IntRisingOrFallingEdge;
break;
}
GPIO_PinInit(index->gpio, index->pin, &gpio_config);
GPIO_PortEnableInterrupts(index->gpio, index->pin);
CriticalAreaUnLock(level);
return EOK;
}
static int32 GpioIrqDisable(x_base pin)
{
const struct PinIndex* index = GetPin(pin);
const struct PinIrq *irq;
irq = GetPinIrq(index->pin);
NULL_PARAM_CHECK(irq);
GPIO_PortDisableInterrupts(index->gpio, index->pin);
return EOK;
}
static uint32 Stm32PinConfigure(struct PinParam *param)
{
NULL_PARAM_CHECK(param);
int ret = EOK;
const struct PinIndex *index = GetPin(param->pin);
switch(param->cmd)
{
case GPIO_CONFIG_MODE:
GpioConfigMode(param->mode, index);
break;
case GPIO_IRQ_REGISTER:
ret = GpioIrqRegister(param->pin,param->irq_set.irq_mode,param->irq_set.hdr,param->irq_set.args);
break;
case GPIO_IRQ_FREE:
ret = GpioIrqFree(param->pin);
break;
case GPIO_IRQ_ENABLE:
ret = GpioIrqEnable(param->pin);
break;
case GPIO_IRQ_DISABLE:
ret = GpioIrqDisable(param->pin);
break;
default:
ret = -EINVALED;
break;
}
return ret;
}
static uint32 Stm32PinInit(void)
{
static x_bool pin_init_flag = RET_FALSE;
if (!pin_init_flag) {
pin_init_flag = RET_TRUE;
}
return EOK;
}
static uint32 Stm32GpioDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
struct PinParam *param;
switch (configure_info->configure_cmd)
{
case OPE_INT:
ret = Stm32PinInit();
break;
case OPE_CFG:
param = (struct PinParam *)configure_info->private_data;
ret = Stm32PinConfigure(param);
break;
default:
break;
}
return ret;
}
uint32 Stm32PinWrite(void *dev, struct BusBlockWriteParam *write_param)
{
NULL_PARAM_CHECK(dev);
NULL_PARAM_CHECK(write_param);
struct PinStat *pinstat = (struct PinStat *)write_param->buffer;
const struct PinIndex* index = GetPin(pinstat->pin);
NULL_PARAM_CHECK(index);
if (GPIO_LOW == pinstat->val) {
GPIO_PinWrite(index->gpio, index->pin, 0);
} else {
GPIO_PinWrite(index->gpio, index->pin, 1);
}
return EOK;
}
uint32 Stm32PinRead(void *dev, struct BusBlockReadParam *read_param)
{
NULL_PARAM_CHECK(dev);
NULL_PARAM_CHECK(read_param);
struct PinStat *pinstat = (struct PinStat *)read_param->buffer;
const struct PinIndex* index = GetPin(pinstat->pin);
NULL_PARAM_CHECK(index);
if(GPIO_PinRead(index->gpio, index->pin) == GPIO_LOW) {
pinstat->val = GPIO_LOW;
} else {
pinstat->val = GPIO_HIGH;
}
return pinstat->val;
}
static const struct PinDevDone dev_done =
{
.open = NONE,
.close = NONE,
.write = Stm32PinWrite,
.read = Stm32PinRead,
};
int Stm32HwGpioInit(void)
{
x_err_t ret = EOK;
static struct PinBus pin;
ret = PinBusInit(&pin, PIN_BUS_NAME);
if (ret != EOK) {
KPrintf("gpio bus init error %d\n", ret);
return ERROR;
}
static struct PinDriver drv;
drv.configure = &Stm32GpioDrvConfigure;
ret = PinDriverInit(&drv, PIN_DRIVER_NAME, NONE);
if (ret != EOK) {
KPrintf("pin driver init error %d\n", ret);
return ERROR;
}
ret = PinDriverAttachToBus(PIN_DRIVER_NAME, PIN_BUS_NAME);
if (ret != EOK) {
KPrintf("pin driver attach error %d\n", ret);
return ERROR;
}
static struct PinHardwareDevice dev;
dev.dev_done = &dev_done;
ret = PinDeviceRegister(&dev, NONE, PIN_DEVICE_NAME);
if (ret != EOK) {
KPrintf("pin device register error %d\n", ret);
return ERROR;
}
ret = PinDeviceAttachToBus(PIN_DEVICE_NAME, PIN_BUS_NAME);
if (ret != EOK) {
KPrintf("pin device register error %d\n", ret);
return ERROR;
}
return ret;
}
static __inline void PinIrqHdr(int irqno)
{
const struct PinIndex* index = GetPin(irqno);
const struct PinIrq *irq;
irq = GetPinIrq(index->pin);
NULL_PARAM_CHECK(irq);
GPIO_ClearPinsInterruptFlags(index->gpio, index->pin);
if (pin_irq_hdr_tab[irqno].hdr){
pin_irq_hdr_tab[irqno].hdr(pin_irq_hdr_tab[irqno].args);
}
}
void EXTI0_IRQHandler(int irq_num, void *arg)
{
PinIrqHdr(0);
}
DECLARE_HW_IRQ(GPIO1_INT0_IRQn, EXTI0_IRQHandler, NONE);
void EXTI1_IRQHandler(int irq_num, void *arg)
{
PinIrqHdr(1);
}
DECLARE_HW_IRQ(GPIO1_INT1_IRQn, EXTI1_IRQHandler, NONE);
void EXTI2_IRQHandler(int irq_num, void *arg)
{
PinIrqHdr(2);
}
DECLARE_HW_IRQ(GPIO1_INT2_IRQn, EXTI2_IRQHandler, NONE);
void EXTI3_IRQHandler(int irq_num, void *arg)
{
PinIrqHdr(3);
}
DECLARE_HW_IRQ(GPIO1_INT3_IRQn, EXTI3_IRQHandler, NONE);
void EXTI4_IRQHandler(int irq_num, void *arg)
{
PinIrqHdr(4);
}
DECLARE_HW_IRQ(GPIO1_INT4_IRQn, EXTI4_IRQHandler, NONE);
void EXTI5_IRQHandler(int irq_num, void *arg)
{
PinIrqHdr(5);
}
DECLARE_HW_IRQ(GPIO1_INT5_IRQn, EXTI5_IRQHandler, NONE);
void EXTI6_IRQHandler(int irq_num, void *arg)
{
PinIrqHdr(6);
}
DECLARE_HW_IRQ(GPIO1_INT6_IRQn, EXTI6_IRQHandler, NONE);
void EXTI7_IRQHandler(int irq_num, void *arg)
{
PinIrqHdr(7);
}
DECLARE_HW_IRQ(GPIO1_INT7_IRQn, EXTI7_IRQHandler, NONE);

View File

@ -0,0 +1,12 @@
if BSP_USING_I2C
config I2C_BUS_NAME_1
string "i2c bus 1 name"
default "i2c1"
config I2C_DRV_NAME_1
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"
endif

View File

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

View File

@ -0,0 +1,194 @@
/*
* Copyright (c) 2020 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2012-04-25 weety first version
*/
/**
* @file connect_i2c.c
* @brief support ok1052-c i2c function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
/*************************************************
File name: connect_i2c.c
Description: support ok1052-c i2c configure and i2c bus register function
Others: take RT-Thread v4.0.2/components/drivers/i2c/i2c-bit-ops.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2022-03-01
Author: AIIT XUOS Lab
Modification:
1. support ok1052-c i2c bit configure, write and read
2. support ok1052-c i2c bus device and driver register
*************************************************/
#include <board.h>
#include "bus_serial.h"
#include "connect_i2c.h"
#include "fsl_lpi2c.h"
#ifndef BSP_USING_I2C1
#define BSP_USING_I2C1
#endif
static uint32 I2cWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
{
status_t ret;
Stm32I2cType *param = (Stm32I2cType *)i2c_dev->haldev.private_data;
ret = I2cHardwareWrite(param->base, param->slave_addr, param->sub_addr, msg->buf, msg->len);
if(kStatus_Success == ret)
return 1;
return 0;
}
static uint32 I2cReadData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
{
status_t ret;
Stm32I2cType *param = (Stm32I2cType *)i2c_dev->haldev.private_data;
ret = I2cHardwareRead(param->base, i2c_dev->i2c_dev_addr, param->sub_addr, msg->buf, msg->len);
if(kStatus_Success == ret)
return 1;
return 0;
}
static uint32 I2cInit(struct I2cDriver *i2c_drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(i2c_drv);
struct I2cHardwareDevice *i2c_dev = (struct I2cHardwareDevice *)i2c_drv->driver.owner_bus->owner_haldev;
if (configure_info->private_data) {
i2c_dev->i2c_dev_addr = *((uint16 *)configure_info->private_data);
return EOK;
}
i2c_print("I2cInit need set i2c dev addr\n");
return ERROR;
}
static uint32 I2cDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
struct I2cDriver *i2c_drv = (struct I2cDriver *)drv;
switch (configure_info->configure_cmd)
{
case OPE_INT:
ret = I2cInit(i2c_drv, configure_info);
break;
default:
break;
}
return ret;
}
/*manage the i2c device operations*/
static const struct I2cDevDone i2c_dev_done =
{
.dev_open = NONE,
.dev_close = NONE,
.dev_write = I2cWriteData,
.dev_read = I2cReadData,
};
/*Init i2c bus*/
static int BoardI2cBusInit(struct I2cBus *i2c_bus, struct I2cDriver *i2c_driver)
{
x_err_t ret = EOK;
/*Init the i2c bus */
i2c_bus->private_data = (void *)NULL;
ret = I2cBusInit(i2c_bus, I2C_BUS_NAME_1);
if (EOK != ret) {
i2c_print("BoardI2cBusInit I2cBusInit error %d\n", ret);
return ERROR;
}
/*Init the i2c driver*/
i2c_driver->private_data = (void *)NULL;
ret = I2cDriverInit(i2c_driver, I2C_DRV_NAME_1);
if (EOK != ret) {
i2c_print("BoardI2cBusInit I2cDriverInit error %d\n", ret);
return ERROR;
}
/*Attach the i2c driver to the i2c bus*/
ret = I2cDriverAttachToBus(I2C_DRV_NAME_1, I2C_BUS_NAME_1);
if (EOK != ret) {
i2c_print("BoardI2cBusInit I2cDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/*Attach the i2c device to the i2c bus*/
static int BoardI2cDevBend(void)
{
x_err_t ret = EOK;
static struct I2cHardwareDevice i2c_device0;
memset(&i2c_device0, 0, sizeof(struct I2cHardwareDevice));
i2c_device0.i2c_dev_done = &i2c_dev_done;
ret = I2cDeviceRegister(&i2c_device0, NONE, I2C_1_DEVICE_NAME_0);
if (EOK != ret) {
i2c_print("BoardI2cDevBend I2cDeviceInit device %s error %d\n", I2C_1_DEVICE_NAME_0, ret);
return ERROR;
}
ret = I2cDeviceAttachToBus(I2C_1_DEVICE_NAME_0, I2C_BUS_NAME_1);
if (EOK != ret) {
i2c_print("BoardI2cDevBend I2cDeviceAttachToBus device %s error %d\n", I2C_1_DEVICE_NAME_0, ret);
return ERROR;
}
return ret;
}
/*BOARD I2C INIT*/
int Stm32HwI2cInit(void)
{
static int init_flag = 0;
x_err_t ret = EOK;
if(init_flag)
{
return ret;
}
init_flag = 1;
static struct I2cBus i2c_bus;
memset(&i2c_bus, 0, sizeof(struct I2cBus));
static struct I2cDriver i2c_driver;
memset(&i2c_driver, 0, sizeof(struct I2cDriver));
#ifdef BSP_USING_I2C1
i2c_driver.configure = I2cDrvConfigure;
ret = BoardI2cBusInit(&i2c_bus, &i2c_driver);
if (EOK != ret) {
i2c_print("board_i2c_Init error ret %u\n", ret);
return ERROR;
}
ret = BoardI2cDevBend();
if (EOK != ret) {
i2c_print("board_i2c_Init error ret %u\n", ret);
return ERROR;
}
#endif
return ret;
}

View File

@ -0,0 +1,99 @@
/*
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
* that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file connect_i2c_eeprom.h
* @brief ok1052-c eeprom relative codes
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
#include "board.h"
#include "connect_i2c.h"
#include "fsl_lpi2c.h"
#include "pin_mux.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define I2C_EEPROM_BASE LPI2C1
#define I2C_EEPROM_ADDR (0xA0 >> 1)
/*******************************************************************************
* Code
******************************************************************************/
void I2cEEpromTestWrite(void)
{
uint8_t dat[8] = {0};
if(I2cHardwareRead(I2C_EEPROM_BASE, I2C_EEPROM_ADDR, 0, dat, 8) == kStatus_Success)
{
i2c_print("Read from EEPROM %d %d %d %d %d %d %d %d\r\n",
dat[0], dat[1], dat[2], dat[3], dat[4], dat[5], dat[6], dat[7]);
}
for(uint8_t i = 0; i < 8; i++)
{
dat[i] ++;
}
if(I2cHardwareWrite(I2C_EEPROM_BASE, I2C_EEPROM_ADDR, 0, dat, 8) == kStatus_Success)
{
i2c_print("Write to EEPROM %d %d %d %d %d %d %d %d\r\n",
dat[0], dat[1], dat[2], dat[3], dat[4], dat[5], dat[6], dat[7]);
}
memset(dat, 0, 8);
if(I2cHardwareRead(I2C_EEPROM_BASE, I2C_EEPROM_ADDR, 0, dat, 8) == kStatus_Success)
{
i2c_print("Read from EEPROM %d %d %d %d %d %d %d %d\r\n",
dat[0], dat[1], dat[2], dat[3], dat[4], dat[5], dat[6], dat[7]);
}
}
int I2cEEpromTest(void)
{
Stm32HwI2cInit();
BOARD_InitI2C1Pins();
I2cHardwareInit();
I2cEEpromTestWrite();
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)| SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)| SHELL_CMD_PARAM_NUM(0),
eeprom, I2cEEpromTest, test i2c eeprom);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,94 @@
/*
* The Clear BSD License
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
* that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file hardware_i2c.c
* @brief ok1052-c i2c relative codes
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
#include "fsl_common.h"
#include "fsl_lpi2c.h"
#define I2C_BASE LPI2C1
/* Select USB1 PLL (480 MHz) as master lpi2c clock source */
#define LPI2C_CLOCK_SOURCE_SELECT (0U)
/* Clock divider for master lpi2c clock source */
#define LPI2C_CLOCK_SOURCE_DIVIDER (5U)
#define I2C_CLOCK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER + 1U))
#define I2C_BAUDRATE 100000U
void I2cHardwareInit(void)
{
lpi2c_master_config_t masterConfig = {0};
LPI2C_MasterGetDefaultConfig(&masterConfig);
/* Change the default baudrate configuration */
masterConfig.baudRate_Hz = I2C_BAUDRATE;
/* Initialize the LPI2C master peripheral */
LPI2C_MasterInit(I2C_BASE, &masterConfig, I2C_CLOCK_FREQ);
}
status_t I2cHardwareWrite(LPI2C_Type* base, uint16_t slave_addr, uint32_t subAdd, uint8_t* dataBuff, uint16_t dataLen)
{
lpi2c_master_transfer_t xfer;
xfer.slaveAddress = slave_addr;
xfer.direction = kLPI2C_Write;
xfer.subaddress = subAdd;
xfer.subaddressSize = 0x01;
xfer.data = dataBuff;
xfer.dataSize = dataLen;
xfer.flags = kLPI2C_TransferDefaultFlag;
return LPI2C_MasterTransferBlocking(base, &xfer);
}
status_t I2cHardwareRead(LPI2C_Type* base, uint16_t slave_addr, uint32_t subAdd, uint8_t* dataBuffer, uint16_t dataLen)
{
lpi2c_master_transfer_t masterXfer = {0};
masterXfer.slaveAddress = slave_addr;
masterXfer.direction = kLPI2C_Read;
masterXfer.subaddress = subAdd;
masterXfer.subaddressSize = 0x01;
masterXfer.data = dataBuffer;
masterXfer.dataSize = dataLen;
masterXfer.flags = kLPI2C_TransferDefaultFlag;
return LPI2C_MasterTransferBlocking(base, &masterXfer);
}

View File

@ -144,6 +144,8 @@
#define FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE (0) #define FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE (0)
/* @brief Remove ALT Clock selection feature. */ /* @brief Remove ALT Clock selection feature. */
#define FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE (1) #define FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE (1)
/* @brief Conversion control count (related to number of registers HCn and Rn). */
#define FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT (8)
/* ADC_ETC module features */ /* ADC_ETC module features */

View File

@ -0,0 +1,34 @@
/*
* 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_adc.h
* @brief define stm32f407-st-discovery adc function and struct
* @version 1.1
* @author AIIT XUOS Lab
* @date 2021-12-28
*/
#ifndef CONNECT_ADC_H
#define CONNECT_ADC_H
#include <device.h>
struct Imrt1052HwAdc
{
void *ADCx;
uint8 adc_channel;
};
int Imrt1052HwAdcInit(void);
#endif

View File

@ -1,26 +1,5 @@
/** /*
****************************************************************************** * Copyright (c) 2021 AIIT XUOS Lab
* @file connect_ethernet.h
* @author MCD Application Team
* @version V1.0.0
* @date 31-October-2011
* @brief STM32F4x7 Ethernet hardware configuration.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2. * XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the 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: * You may obtain a copy of Mulan PSL v2 at:
@ -39,37 +18,22 @@
* @date 2021-12-7 * @date 2021-12-7
*/ */
/* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __CONNECT_ETHERNET_H_
#ifndef __ETH_BSP_H #define __CONNECT_ETHERNET_H_
#define __ETH_BSP_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
#ifndef sourceClock #ifndef sourceClock
#define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk) #define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk)
#endif #endif
/* Exported functions ------------------------------------------------------- */
void enet_delay(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* __STM32F4x7_ETH_BSP_H */ #endif
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2022 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_gpio.h
* @brief define ok1052-c gpio function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
#ifndef __CONNECT_GPIO_H_
#define __CONNECT_GPIO_H_
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
int Stm32HwGpioInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,46 @@
/*
* 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_i2c.h
* @brief define stm32f407-st-discovery-board i2c function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_I2C_H
#define CONNECT_I2C_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct Stm32I2c
{
LPI2C_Type* base;
uint16_t slave_addr;
uint32_t sub_addr;
}Stm32I2cType;
#define i2c_print KPrintf
int Stm32HwI2cInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2022 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 ok1052-c rtc function and structure
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
#ifndef __CONNECT_RTC_H_
#define __CONNECT_RTC_H_
#include "fsl_common.h"
#include "fsl_lpi2c.h"
#define I2C_RTC_BASE LPI2C1
#define I2C_RTC_ADDR 0x32
void RtcI2cInit(void);
status_t RtcI2cWrite(LPI2C_Type *base, uint32_t sub_addr, uint8_t *buf, uint16_t size);
uint32_t RtcI2cRead(LPI2C_Type *base, uint32_t sub_addr, uint8_t *buf, uint16_t size);
int Imrt1052HwRtcInit(void);
#endif

View File

@ -0,0 +1,55 @@
/*
* 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_spi.h
* @brief define stm32f407-st-discovery-board spi function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_SPI_H
#define CONNECT_SPI_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SPI_USING_RX_DMA_FLAG (1<<0)
#define SPI_USING_TX_DMA_FLAG (1<<1)
struct Stm32HwSpi
{
LPSPI_Type *base;
uint8_t irq;
uint8_t mode;
void *priv_data;
};
struct Stm32Spi
{
LPSPI_Type *instance;
char *bus_name;
struct SpiBus spi_bus;
};
int Imrt1052HwSpiInit(void);
x_err_t HwSpiDeviceAttach(const char *bus_name, const char *device_name);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -38,18 +38,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 enet_ethernetif.h * @file enet_ethernetif.h
* @brief ethernet drivers * @brief ethernet drivers

View File

@ -5,18 +5,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 enet_ethernetif_priv.h * @file enet_ethernetif_priv.h
* @brief ethernet drivers * @brief ethernet drivers

View File

@ -6,18 +6,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_cache.h * @file fsl_cache.h
* @brief cache drivers * @brief cache drivers

View File

@ -5,18 +5,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_clock.h * @file fsl_clock.h
* @brief clock drivers * @brief clock drivers

View File

@ -23,7 +23,7 @@
#define _FSL_DEBUGCONSOLE_H_ #define _FSL_DEBUGCONSOLE_H_
#include "fsl_common.h" #include "fsl_common.h"
//#include "serial_manager.h" #include "serial_manager.h"
/*! /*!
* @addtogroup debugconsole * @addtogroup debugconsole

View File

@ -6,18 +6,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_enet.h * @file fsl_enet.h
* @brief ethernet drivers * @brief ethernet drivers

View File

@ -6,18 +6,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_iomuxc.h * @file fsl_iomuxc.h
* @brief io mux drivers * @brief io mux drivers

File diff suppressed because it is too large Load Diff

View File

@ -6,18 +6,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_lpuart.h * @file fsl_lpuart.h
* @brief fsl uart drivers * @brief fsl uart drivers

View File

@ -0,0 +1,548 @@
/*
* Copyright 2018 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SERIAL_MANAGER_H__
#define __SERIAL_MANAGER_H__
/*!
* @addtogroup serialmanager
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
/*! @brief Enable or disable serial manager non-blocking mode (1 - enable, 0 - disable) */
#define SERIAL_MANAGER_NON_BLOCKING_MODE (1U)
#else
#ifndef SERIAL_MANAGER_NON_BLOCKING_MODE
#define SERIAL_MANAGER_NON_BLOCKING_MODE (0U)
#endif
#endif
/*! @brief Enable or disable uart port (1 - enable, 0 - disable) */
#ifndef SERIAL_PORT_TYPE_UART
#define SERIAL_PORT_TYPE_UART (1U)
#endif
/*! @brief Enable or disable USB CDC port (1 - enable, 0 - disable) */
#ifndef SERIAL_PORT_TYPE_USBCDC
#define SERIAL_PORT_TYPE_USBCDC (0U)
#endif
/*! @brief Enable or disable SWO port (1 - enable, 0 - disable) */
#ifndef SERIAL_PORT_TYPE_SWO
#define SERIAL_PORT_TYPE_SWO (0U)
#endif
/*! @brief Enable or disable USB CDC virtual port (1 - enable, 0 - disable) */
#ifndef SERIAL_PORT_TYPE_USBCDC_VIRTUAL
#define SERIAL_PORT_TYPE_USBCDC_VIRTUAL (0U)
#endif
/*! @brief Set serial manager write handle size */
#if (defined(SERIAL_MANAGER_NON_BLOCKING_MODE) && (SERIAL_MANAGER_NON_BLOCKING_MODE > 0U))
#define SERIAL_MANAGER_WRITE_HANDLE_SIZE (44U)
#define SERIAL_MANAGER_READ_HANDLE_SIZE (44U)
#else
#define SERIAL_MANAGER_WRITE_HANDLE_SIZE (4U)
#define SERIAL_MANAGER_READ_HANDLE_SIZE (4U)
#endif
#if (defined(SERIAL_PORT_TYPE_UART) && (SERIAL_PORT_TYPE_UART > 0U))
#include "serial_port_uart.h"
#endif
#if (defined(SERIAL_PORT_TYPE_USBCDC) && (SERIAL_PORT_TYPE_USBCDC > 0U))
#if !(defined(SERIAL_MANAGER_NON_BLOCKING_MODE) && (SERIAL_MANAGER_NON_BLOCKING_MODE > 0U))
#error The serial manager blocking mode cannot be supported for USB CDC.
#endif
#include "serial_port_usb.h"
#endif
#if (defined(SERIAL_PORT_TYPE_SWO) && (SERIAL_PORT_TYPE_SWO > 0U))
#include "serial_port_swo.h"
#endif
#if (defined(SERIAL_PORT_TYPE_USBCDC_VIRTUAL) && (SERIAL_PORT_TYPE_USBCDC_VIRTUAL > 0U))
#if !(defined(SERIAL_MANAGER_NON_BLOCKING_MODE) && (SERIAL_MANAGER_NON_BLOCKING_MODE > 0U))
#error The serial manager blocking mode cannot be supported for USB CDC.
#endif
#include "serial_port_usb_virtual.h"
#endif
#define SERIAL_MANAGER_HANDLE_SIZE_TEMP 0U
#if (defined(SERIAL_PORT_TYPE_UART) && (SERIAL_PORT_TYPE_UART > 0U))
#if (SERIAL_PORT_UART_HANDLE_SIZE > SERIAL_MANAGER_HANDLE_SIZE_TEMP)
#undef SERIAL_MANAGER_HANDLE_SIZE_TEMP
#define SERIAL_MANAGER_HANDLE_SIZE_TEMP SERIAL_PORT_UART_HANDLE_SIZE
#endif
#endif
#if (defined(SERIAL_PORT_TYPE_USBCDC) && (SERIAL_PORT_TYPE_USBCDC > 0U))
#if (SERIAL_PORT_USB_CDC_HANDLE_SIZE > SERIAL_MANAGER_HANDLE_SIZE_TEMP)
#undef SERIAL_MANAGER_HANDLE_SIZE_TEMP
#define SERIAL_MANAGER_HANDLE_SIZE_TEMP SERIAL_PORT_USB_CDC_HANDLE_SIZE
#endif
#endif
#if (defined(SERIAL_PORT_TYPE_SWO) && (SERIAL_PORT_TYPE_SWO > 0U))
#if (SERIAL_PORT_SWO_HANDLE_SIZE > SERIAL_MANAGER_HANDLE_SIZE_TEMP)
#undef SERIAL_MANAGER_HANDLE_SIZE_TEMP
#define SERIAL_MANAGER_HANDLE_SIZE_TEMP SERIAL_PORT_SWO_HANDLE_SIZE
#endif
#endif
#if (defined(SERIAL_PORT_TYPE_USBCDC_VIRTUAL) && (SERIAL_PORT_TYPE_USBCDC_VIRTUAL > 0U))
#if (SERIAL_PORT_USB_VIRTUAL_HANDLE_SIZE > SERIAL_MANAGER_HANDLE_SIZE_TEMP)
#undef SERIAL_MANAGER_HANDLE_SIZE_TEMP
#define SERIAL_MANAGER_HANDLE_SIZE_TEMP SERIAL_PORT_USB_VIRTUAL_HANDLE_SIZE
#endif
#endif
/*! @brief SERIAL_PORT_UART_HANDLE_SIZE/SERIAL_PORT_USB_CDC_HANDLE_SIZE + serial manager dedicated size */
#if ((defined(SERIAL_MANAGER_HANDLE_SIZE_TEMP) && (SERIAL_MANAGER_HANDLE_SIZE_TEMP > 0U)))
#else
#error SERIAL_PORT_TYPE_UART, SERIAL_PORT_TYPE_USBCDC, SERIAL_PORT_TYPE_SWO and SERIAL_PORT_TYPE_USBCDC_VIRTUAL should not be cleared at same time.
#endif
#if (defined(SERIAL_MANAGER_NON_BLOCKING_MODE) && (SERIAL_MANAGER_NON_BLOCKING_MODE > 0U))
#define SERIAL_MANAGER_HANDLE_SIZE (SERIAL_MANAGER_HANDLE_SIZE_TEMP + 120U)
#else
#define SERIAL_MANAGER_HANDLE_SIZE (SERIAL_MANAGER_HANDLE_SIZE_TEMP + 12U)
#endif
#define SERIAL_MANAGER_USE_COMMON_TASK (1U)
#define SERIAL_MANAGER_TASK_PRIORITY (2U)
#define SERIAL_MANAGER_TASK_STACK_SIZE (1000U)
typedef void *serial_handle_t;
typedef void *serial_write_handle_t;
typedef void *serial_read_handle_t;
/*! @brief serial port type*/
typedef enum _serial_port_type
{
kSerialPort_Uart = 1U, /*!< Serial port UART */
kSerialPort_UsbCdc, /*!< Serial port USB CDC */
kSerialPort_Swo, /*!< Serial port SWO */
kSerialPort_UsbCdcVirtual, /*!< Serial port USB CDC Virtual */
} serial_port_type_t;
/*! @brief serial manager config structure*/
typedef struct _serial_manager_config
{
uint8_t *ringBuffer; /*!< Ring buffer address, it is used to buffer data received by the hardware.
Besides, the memory space cannot be free during the lifetime of the serial
manager module. */
uint32_t ringBufferSize; /*!< The size of the ring buffer */
serial_port_type_t type; /*!< Serial port type */
void *portConfig; /*!< Serial port configuration */
} serial_manager_config_t;
/*! @brief serial manager error code*/
typedef enum _serial_manager_status
{
kStatus_SerialManager_Success = kStatus_Success, /*!< Success */
kStatus_SerialManager_Error = MAKE_STATUS(kStatusGroup_SERIALMANAGER, 1), /*!< Failed */
kStatus_SerialManager_Busy = MAKE_STATUS(kStatusGroup_SERIALMANAGER, 2), /*!< Busy */
kStatus_SerialManager_Notify = MAKE_STATUS(kStatusGroup_SERIALMANAGER, 3), /*!< Ring buffer is not empty */
kStatus_SerialManager_Canceled =
MAKE_STATUS(kStatusGroup_SERIALMANAGER, 4), /*!< the non-blocking request is canceled */
kStatus_SerialManager_HandleConflict = MAKE_STATUS(kStatusGroup_SERIALMANAGER, 5), /*!< The handle is opened */
kStatus_SerialManager_RingBufferOverflow =
MAKE_STATUS(kStatusGroup_SERIALMANAGER, 6), /*!< The ring buffer is overflowed */
} serial_manager_status_t;
/*! @brief Callback message structure */
typedef struct _serial_manager_callback_message
{
uint8_t *buffer; /*!< Transferred buffer */
uint32_t length; /*!< Transferred data length */
} serial_manager_callback_message_t;
/*! @brief callback function */
typedef void (*serial_manager_callback_t)(void *callbackParam,
serial_manager_callback_message_t *message,
serial_manager_status_t status);
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* _cplusplus */
/*!
* @brief Initializes a serial manager module with the serial manager handle and the user configuration structure.
*
* This function configures the Serial Manager module with user-defined settings. The user can configure the
* configuration
* structure. The parameter serialHandle is a pointer to point to a memory space of size #SERIAL_MANAGER_HANDLE_SIZE
* allocated by the caller.
* The Serial Manager module supports two types of serial port, UART (includes UART, USART, LPSCI, LPUART, etc) and USB
* CDC.
* Please refer to #serial_port_type_t for serial port setting. These two types can be set by using
* #serial_manager_config_t.
*
* Example below shows how to use this API to configure the Serial Manager.
* For UART,
* @code
* #define SERIAL_MANAGER_RING_BUFFER_SIZE (256U)
* static uint8_t s_serialHandleBuffer[SERIAL_MANAGER_HANDLE_SIZE];
* static serial_handle_t s_serialHandle = &s_serialHandleBuffer[0];
* static uint8_t s_ringBuffer[SERIAL_MANAGER_RING_BUFFER_SIZE];
*
* serial_manager_config_t config;
* serial_port_uart_config_t uartConfig;
* config.type = kSerialPort_Uart;
* config.ringBuffer = &s_ringBuffer[0];
* config.ringBufferSize = SERIAL_MANAGER_RING_BUFFER_SIZE;
* uartConfig.instance = 0;
* uartConfig.clockRate = 24000000;
* uartConfig.baudRate = 115200;
* uartConfig.parityMode = kSerialManager_UartParityDisabled;
* uartConfig.stopBitCount = kSerialManager_UartOneStopBit;
* uartConfig.enableRx = 1;
* uartConfig.enableTx = 1;
* config.portConfig = &uartConfig;
* SerialManager_Init(s_serialHandle, &config);
* @endcode
* For USB CDC,
* @code
* #define SERIAL_MANAGER_RING_BUFFER_SIZE (256U)
* static uint8_t s_serialHandleBuffer[SERIAL_MANAGER_HANDLE_SIZE];
* static serial_handle_t s_serialHandle = &s_serialHandleBuffer[0];
* static uint8_t s_ringBuffer[SERIAL_MANAGER_RING_BUFFER_SIZE];
*
* serial_manager_config_t config;
* serial_port_usb_cdc_config_t usbCdcConfig;
* config.type = kSerialPort_UsbCdc;
* config.ringBuffer = &s_ringBuffer[0];
* config.ringBufferSize = SERIAL_MANAGER_RING_BUFFER_SIZE;
* usbCdcConfig.controllerIndex = kSerialManager_UsbControllerKhci0;
* config.portConfig = &usbCdcConfig;
* SerialManager_Init(s_serialHandle, &config);
* @endcode
*
* @param serialHandle Pointer to point to a memory space of size #SERIAL_MANAGER_HANDLE_SIZE allocated by the caller.
* @param config Pointer to user-defined configuration structure.
* @retval kStatus_SerialManager_Error An error occurred.
* @retval kStatus_SerialManager_Success The Serial Manager module initialization succeed.
*/
serial_manager_status_t SerialManager_Init(serial_handle_t serialHandle, serial_manager_config_t *config);
/*!
* @brief De-initializes the serial manager module instance.
*
* This function de-initializes the serial manager module instance. If the opened writing or
* reading handle is not closed, the function will return kStatus_SerialManager_Busy.
*
* @param serialHandle The serial manager module handle pointer.
* @retval kStatus_SerialManager_Success The serial manager de-initialization succeed.
* @retval kStatus_SerialManager_Busy Opened reading or writing handle is not closed.
*/
serial_manager_status_t SerialManager_Deinit(serial_handle_t serialHandle);
/*!
* @brief Opens a writing handle for the serial manager module.
*
* This function Opens a writing handle for the serial manager module. If the serial manager needs to
* be used in different tasks, the task should open a dedicated write handle for itself by calling
* #SerialManager_OpenWriteHandle. Since there can only one buffer for transmission for the writing
* handle at the same time, multiple writing handles need to be opened when the multiple transmission
* is needed for a task.
*
* @param serialHandle The serial manager module handle pointer.
* @param writeHandle The serial manager module writing handle pointer.
* @retval kStatus_SerialManager_Error An error occurred.
* @retval kStatus_SerialManager_HandleConflict The writing handle was opened.
* @retval kStatus_SerialManager_Success The writing handle is opened.
*
* Example below shows how to use this API to write data.
* For task 1,
* @code
* static uint8_t s_serialWriteHandleBuffer1[SERIAL_MANAGER_WRITE_HANDLE_SIZE];
* static serial_write_handle_t s_serialWriteHandle1 = &s_serialWriteHandleBuffer1[0];
* static uint8_t s_nonBlockingWelcome1[] = "This is non-blocking writing log for task1!\r\n";
* SerialManager_OpenWriteHandle(serialHandle, s_serialWriteHandle1);
* SerialManager_InstallTxCallback(s_serialWriteHandle1, Task1_SerialManagerTxCallback, s_serialWriteHandle1);
* SerialManager_WriteNonBlocking(s_serialWriteHandle1, s_nonBlockingWelcome1, sizeof(s_nonBlockingWelcome1) - 1);
* @endcode
* For task 2,
* @code
* static uint8_t s_serialWriteHandleBuffer2[SERIAL_MANAGER_WRITE_HANDLE_SIZE];
* static serial_write_handle_t s_serialWriteHandle2 = &s_serialWriteHandleBuffer2[0];
* static uint8_t s_nonBlockingWelcome2[] = "This is non-blocking writing log for task2!\r\n";
* SerialManager_OpenWriteHandle(serialHandle, s_serialWriteHandle2);
* SerialManager_InstallTxCallback(s_serialWriteHandle2, Task2_SerialManagerTxCallback, s_serialWriteHandle2);
* SerialManager_WriteNonBlocking(s_serialWriteHandle2, s_nonBlockingWelcome2, sizeof(s_nonBlockingWelcome2) - 1);
* @endcode
*/
serial_manager_status_t SerialManager_OpenWriteHandle(serial_handle_t serialHandle, serial_write_handle_t writeHandle);
/*!
* @brief Closes a writing handle for the serial manager module.
*
* This function Closes a writing handle for the serial manager module.
*
* @param writeHandle The serial manager module writing handle pointer.
* @retval kStatus_SerialManager_Success The writing handle is closed.
*/
serial_manager_status_t SerialManager_CloseWriteHandle(serial_write_handle_t writeHandle);
/*!
* @brief Opens a reading handle for the serial manager module.
*
* This function Opens a reading handle for the serial manager module. The reading handle can not be
* opened multiple at the same time. The error code kStatus_SerialManager_Busy would be returned when
* the previous reading handle is not closed. And There can only be one buffer for receiving for the
* reading handle at the same time.
*
* @param serialHandle The serial manager module handle pointer.
* @param readHandle The serial manager module reading handle pointer.
* @retval kStatus_SerialManager_Error An error occurred.
* @retval kStatus_SerialManager_Success The reading handle is opened.
* @retval kStatus_SerialManager_Busy Previous reading handle is not closed.
*
* Example below shows how to use this API to read data.
* @code
* static uint8_t s_serialReadHandleBuffer[SERIAL_MANAGER_READ_HANDLE_SIZE];
* static serial_read_handle_t s_serialReadHandle = &s_serialReadHandleBuffer[0];
* SerialManager_OpenReadHandle(serialHandle, s_serialReadHandle);
* static uint8_t s_nonBlockingBuffer[64];
* SerialManager_InstallRxCallback(s_serialReadHandle, APP_SerialManagerRxCallback, s_serialReadHandle);
* SerialManager_ReadNonBlocking(s_serialReadHandle, s_nonBlockingBuffer, sizeof(s_nonBlockingBuffer));
* @endcode
*/
serial_manager_status_t SerialManager_OpenReadHandle(serial_handle_t serialHandle, serial_read_handle_t readHandle);
/*!
* @brief Closes a reading for the serial manager module.
*
* This function Closes a reading for the serial manager module.
*
* @param readHandle The serial manager module reading handle pointer.
* @retval kStatus_SerialManager_Success The reading handle is closed.
*/
serial_manager_status_t SerialManager_CloseReadHandle(serial_read_handle_t readHandle);
/*!
* @brief Transmits data with the blocking mode.
*
* This is a blocking function, which polls the sending queue, waits for the sending queue to be empty.
* This function sends data using an interrupt method. The interrupt of the hardware could not be disabled.
* And There can only one buffer for transmission for the writing handle at the same time.
*
* @note The function #SerialManager_WriteBlocking and the function #SerialManager_WriteNonBlocking
* cannot be used at the same time.
* And, the function #SerialManager_CancelWriting cannot be used to abort the transmission of this function.
*
* @param writeHandle The serial manager module handle pointer.
* @param buffer Start address of the data to write.
* @param length Length of the data to write.
* @retval kStatus_SerialManager_Success Successfully sent all data.
* @retval kStatus_SerialManager_Busy Previous transmission still not finished; data not all sent yet.
* @retval kStatus_SerialManager_Error An error occurred.
*/
serial_manager_status_t SerialManager_WriteBlocking(serial_write_handle_t writeHandle,
uint8_t *buffer,
uint32_t length);
/*!
* @brief Reads data with the blocking mode.
*
* This is a blocking function, which polls the receiving buffer, waits for the receiving buffer to be full.
* This function receives data using an interrupt method. The interrupt of the hardware could not be disabled.
* And There can only one buffer for receiving for the reading handle at the same time.
*
* @note The function #SerialManager_ReadBlocking and the function #SerialManager_ReadNonBlocking
* cannot be used at the same time.
* And, the function #SerialManager_CancelReading cannot be used to abort the transmission of this function.
*
* @param readHandle The serial manager module handle pointer.
* @param buffer Start address of the data to store the received data.
* @param length The length of the data to be received.
* @retval kStatus_SerialManager_Success Successfully received all data.
* @retval kStatus_SerialManager_Busy Previous transmission still not finished; data not all received yet.
* @retval kStatus_SerialManager_Error An error occurred.
*/
serial_manager_status_t SerialManager_ReadBlocking(serial_read_handle_t readHandle, uint8_t *buffer, uint32_t length);
#if (defined(SERIAL_MANAGER_NON_BLOCKING_MODE) && (SERIAL_MANAGER_NON_BLOCKING_MODE > 0U))
/*!
* @brief Transmits data with the non-blocking mode.
*
* This is a non-blocking function, which returns directly without waiting for all data to be sent.
* When all data is sent, the module notifies the upper layer through a TX callback function and passes
* the status parameter @ref kStatus_SerialManager_Success.
* This function sends data using an interrupt method. The interrupt of the hardware could not be disabled.
* And There can only one buffer for transmission for the writing handle at the same time.
*
* @note The function #SerialManager_WriteBlocking and the function #SerialManager_WriteNonBlocking
* cannot be used at the same time. And, the TX callback is mandatory before the function could be used.
*
* @param writeHandle The serial manager module handle pointer.
* @param buffer Start address of the data to write.
* @param length Length of the data to write.
* @retval kStatus_SerialManager_Success Successfully sent all data.
* @retval kStatus_SerialManager_Busy Previous transmission still not finished; data not all sent yet.
* @retval kStatus_SerialManager_Error An error occurred.
*/
serial_manager_status_t SerialManager_WriteNonBlocking(serial_write_handle_t writeHandle,
uint8_t *buffer,
uint32_t length);
/*!
* @brief Reads data with the non-blocking mode.
*
* This is a non-blocking function, which returns directly without waiting for all data to be received.
* When all data is received, the module driver notifies the upper layer
* through a RX callback function and passes the status parameter @ref kStatus_SerialManager_Success.
* This function receives data using an interrupt method. The interrupt of the hardware could not be disabled.
* And There can only one buffer for receiving for the reading handle at the same time.
*
* @note The function #SerialManager_ReadBlocking and the function #SerialManager_ReadNonBlocking
* cannot be used at the same time. And, the RX callback is mandatory before the function could be used.
*
* @param readHandle The serial manager module handle pointer.
* @param buffer Start address of the data to store the received data.
* @param length The length of the data to be received.
* @retval kStatus_SerialManager_Success Successfully received all data.
* @retval kStatus_SerialManager_Busy Previous transmission still not finished; data not all received yet.
* @retval kStatus_SerialManager_Error An error occurred.
*/
serial_manager_status_t SerialManager_ReadNonBlocking(serial_read_handle_t readHandle,
uint8_t *buffer,
uint32_t length);
/*!
* @brief Tries to read data.
*
* The function tries to read data from internal ring buffer. If the ring buffer is not empty, the data will be
* copied from ring buffer to up layer buffer. The copied length is the minimum of the ring buffer and up layer length.
* After the data is copied, the actual data length is passed by the parameter length.
* And There can only one buffer for receiving for the reading handle at the same time.
*
* @param readHandle The serial manager module handle pointer.
* @param buffer Start address of the data to store the received data.
* @param length The length of the data to be received.
* @param receivedLength Length received from the ring buffer directly.
* @retval kStatus_SerialManager_Success Successfully received all data.
* @retval kStatus_SerialManager_Busy Previous transmission still not finished; data not all received yet.
* @retval kStatus_SerialManager_Error An error occurred.
*/
serial_manager_status_t SerialManager_TryRead(serial_read_handle_t readHandle,
uint8_t *buffer,
uint32_t length,
uint32_t *receivedLength);
/*!
* @brief Cancels unfinished send transmission.
*
* The function cancels unfinished send transmission. When the transfer is canceled, the module notifies the upper layer
* through a TX callback function and passes the status parameter @ref kStatus_SerialManager_Canceled.
*
* @note The function #SerialManager_CancelWriting cannot be used to abort the transmission of
* the function #SerialManager_WriteBlocking.
*
* @param writeHandle The serial manager module handle pointer.
* @retval kStatus_SerialManager_Success Get successfully abort the sending.
* @retval kStatus_SerialManager_Error An error occurred.
*/
serial_manager_status_t SerialManager_CancelWriting(serial_write_handle_t writeHandle);
/*!
* @brief Cancels unfinished receive transmission.
*
* The function cancels unfinished receive transmission. When the transfer is canceled, the module notifies the upper
* layer
* through a RX callback function and passes the status parameter @ref kStatus_SerialManager_Canceled.
*
* @note The function #SerialManager_CancelReading cannot be used to abort the transmission of
* the function #SerialManager_ReadBlocking.
*
* @param readHandle The serial manager module handle pointer.
* @retval kStatus_SerialManager_Success Get successfully abort the receiving.
* @retval kStatus_SerialManager_Error An error occurred.
*/
serial_manager_status_t SerialManager_CancelReading(serial_read_handle_t readHandle);
/*!
* @brief Installs a TX callback and callback parameter.
*
* This function is used to install the TX callback and callback parameter for the serial manager module.
* When any status of TX transmission changed, the driver will notify the upper layer by the installed callback
* function. And the status is also passed as status parameter when the callback is called.
*
* @param writeHandle The serial manager module handle pointer.
* @param callback The callback function.
* @param callbackParam The parameter of the callback function.
* @retval kStatus_SerialManager_Success Successfully install the callback.
*/
serial_manager_status_t SerialManager_InstallTxCallback(serial_write_handle_t writeHandle,
serial_manager_callback_t callback,
void *callbackParam);
/*!
* @brief Installs a RX callback and callback parameter.
*
* This function is used to install the RX callback and callback parameter for the serial manager module.
* When any status of RX transmission changed, the driver will notify the upper layer by the installed callback
* function. And the status is also passed as status parameter when the callback is called.
*
* @param readHandle The serial manager module handle pointer.
* @param callback The callback function.
* @param callbackParam The parameter of the callback function.
* @retval kStatus_SerialManager_Success Successfully install the callback.
*/
serial_manager_status_t SerialManager_InstallRxCallback(serial_read_handle_t readHandle,
serial_manager_callback_t callback,
void *callbackParam);
#endif
/*!
* @brief Prepares to enter low power consumption.
*
* This function is used to prepare to enter low power consumption.
*
* @param serialHandle The serial manager module handle pointer.
* @retval kStatus_SerialManager_Success Successful operation.
*/
serial_manager_status_t SerialManager_EnterLowpower(serial_handle_t serialHandle);
/*!
* @brief Restores from low power consumption.
*
* This function is used to restore from low power consumption.
*
* @param serialHandle The serial manager module handle pointer.
* @retval kStatus_SerialManager_Success Successful operation.
*/
serial_manager_status_t SerialManager_ExitLowpower(serial_handle_t serialHandle);
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* __SERIAL_MANAGER_H__ */

View File

@ -0,0 +1,55 @@
/*
* Copyright 2018 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SERIAL_PORT_UART_H__
#define __SERIAL_PORT_UART_H__
/*!
* @addtogroup serial_port_uart
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief serial port uart handle size*/
#if (defined(SERIAL_MANAGER_NON_BLOCKING_MODE) && (SERIAL_MANAGER_NON_BLOCKING_MODE > 0U))
#define SERIAL_PORT_UART_HANDLE_SIZE (166U)
#else
#define SERIAL_PORT_UART_HANDLE_SIZE (4U)
#endif
/*! @brief serial port uart parity mode*/
typedef enum _serial_port_uart_parity_mode
{
kSerialManager_UartParityDisabled = 0x0U, /*!< Parity disabled */
kSerialManager_UartParityEven = 0x1U, /*!< Parity even enabled */
kSerialManager_UartParityOdd = 0x2U, /*!< Parity odd enabled */
} serial_port_uart_parity_mode_t;
/*! @brief serial port uart stop bit count*/
typedef enum _serial_port_uart_stop_bit_count
{
kSerialManager_UartOneStopBit = 0U, /*!< One stop bit */
kSerialManager_UartTwoStopBit = 1U, /*!< Two stop bits */
} serial_port_uart_stop_bit_count_t;
/*! @brief serial port uart config struct*/
typedef struct _serial_port_uart_config
{
uint32_t clockRate; /*!< clock rate */
uint32_t baudRate; /*!< baud rate */
serial_port_uart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */
serial_port_uart_stop_bit_count_t stopBitCount; /*!< Number of stop bits, 1 stop bit (default) or 2 stop bits */
uint8_t instance; /*!< Instance (0 - UART0, 1 - UART1, ...), detail information
please refer to the SOC corresponding RM. */
uint8_t enableRx; /*!< Enable RX */
uint8_t enableTx; /*!< Enable TX */
} serial_port_uart_config_t;
/*! @} */
#endif /* __SERIAL_PORT_UART_H__ */

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016 - 2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SERIAL_PORT_USB_H__
#define __SERIAL_PORT_USB_H__
#if defined(FSL_RTOS_FREE_RTOS)
#include "FreeRTOS.h"
#endif
/*!
* @addtogroup serial_port_usb
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief serial port usb handle size*/
#define SERIAL_PORT_USB_CDC_HANDLE_SIZE (72)
/*! @brief USB interrupt priority*/
#if defined(__GIC_PRIO_BITS)
#define USB_DEVICE_INTERRUPT_PRIORITY (25U)
#else
#if defined(configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY)
#define USB_DEVICE_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY)
#else
/* The default value 3 is used to support different ARM Core, such as CM0P, CM4, CM7, and CM33, etc.
* The minimum number of priority bits implemented in the NVIC is 2 on these SOCs. The value of mininum
* priority is 3 (2^2 - 1). So, the default value is 3.
*/
#define USB_DEVICE_INTERRUPT_PRIORITY (3U)
#endif
#endif
/*! @brief USB controller ID */
typedef enum _serial_port_usb_cdc_controller_index
{
kSerialManager_UsbControllerKhci0 = 0U, /*!< KHCI 0U */
kSerialManager_UsbControllerKhci1 = 1U, /*!< KHCI 1U, Currently, there are no platforms which have two KHCI IPs,
this is reserved to be used in the future. */
kSerialManager_UsbControllerEhci0 = 2U, /*!< EHCI 0U */
kSerialManager_UsbControllerEhci1 = 3U, /*!< EHCI 1U, Currently, there are no platforms which have two EHCI IPs,
this is reserved to be used in the future. */
kSerialManager_UsbControllerLpcIp3511Fs0 = 4U, /*!< LPC USB IP3511 FS controller 0 */
kSerialManager_UsbControllerLpcIp3511Fs1 = 5U, /*!< LPC USB IP3511 FS controller 1, there are no platforms which
have two IP3511 IPs, this is reserved to be used in the future. */
kSerialManager_UsbControllerLpcIp3511Hs0 = 6U, /*!< LPC USB IP3511 HS controller 0 */
kSerialManager_UsbControllerLpcIp3511Hs1 = 7U, /*!< LPC USB IP3511 HS controller 1, there are no platforms which
have two IP3511 IPs, this is reserved to be used in the future. */
kSerialManager_UsbControllerOhci0 = 8U, /*!< OHCI 0U */
kSerialManager_UsbControllerOhci1 = 9U, /*!< OHCI 1U, Currently, there are no platforms which have two OHCI IPs,
this is reserved to be used in the future. */
kSerialManager_UsbControllerIp3516Hs0 = 10U, /*!< IP3516HS 0U */
kSerialManager_UsbControllerIp3516Hs1 = 11U, /*!< IP3516HS 1U, Currently, there are no platforms which have two
IP3516HS IPs, this is reserved to be used in the future. */
} serial_port_usb_cdc_controller_index_t;
/*! @brief serial port usb config struct*/
typedef struct _serial_port_usb_cdc_config
{
serial_port_usb_cdc_controller_index_t controllerIndex; /*!< controller index */
} serial_port_usb_cdc_config_t;
/*! @} */
#endif /* __SERIAL_PORT_USB_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 := hardware_rtc.c connect_rtc.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,452 @@
/*
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
* that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file connect_rtc.c
* @brief ok1052-c rtc function and structure
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
/*************************************************
File name: connect_rtc.c
Description: support ok1052-c rtc configure and spi bus register function
History:
1. Date: 2022-03-01
Author: AIIT XUOS Lab
Modification:
1. change command for XUOS
*************************************************/
#include "board.h"
#include "bus_rtc.h"
#include "pin_mux.h"
#include "dev_rtc.h"
#include "connect_rtc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define rtc_print KPrintf
#define MAX_TIME_STR_SIZE 50
///////////RX8010///////////
#define RX8010_SEC 0x10
#define RX8010_MIN 0x11
#define RX8010_HOUR 0x12
#define RX8010_WDAY 0x13
#define RX8010_MDAY 0x14
#define RX8010_MONTH 0x15
#define RX8010_YEAR 0x16
#define RX8010_YEAR 0x16
#define RX8010_RESV17 0x17
#define RX8010_ALMIN 0x18
#define RX8010_ALHOUR 0x19
#define RX8010_ALWDAY 0x1A
#define RX8010_TCOUNT0 0x1B
#define RX8010_TCOUNT1 0x1C
#define RX8010_EXT 0x1D
#define RX8010_FLAG 0x1E
#define RX8010_CTRL 0x1F
/* 0x20 to 0x2F are user registers */
#define RX8010_RESV30 0x30
#define RX8010_RESV31 0x31
#define RX8010_IRQ 0x32
#define RX8010_EXT_WADA 0x04 //BIT(3)
#define RX8010_FLAG_VLF 0x02 //BIT(1)
#define RX8010_FLAG_AF 0x04 //BIT(3)
#define RX8010_FLAG_TF 0x08 //BIT(4)
#define RX8010_FLAG_UF 0x10 //BIT(5)
#define RX8010_CTRL_AIE 0x04 //BIT(3)
#define RX8010_CTRL_UIE 0x10 //BIT(5)
#define RX8010_CTRL_STOP 0x20 //BIT(6)
#define RX8010_CTRL_TEST 0x40 //BIT(7)
#define RX8010_ALARM_AE 0x40 //BIT(7)
#define RX8010_TEST_TIME 10000
#define BCD_DATA_LEN 20
// change BIN format to BCD format
#define TO_BCD(_n) (((_n / 10) << 4) | (_n % 10))
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
// change BCD format date to BIN format
uint8_t bcd2bin(uint8_t data)
{
int i = 0;
uint8_t ret = 0;
uint8_t mask[4] = {0x01, 0x02, 0x04, 0x08};
//LOW
for(i = 0; i < 4; i++)
{
if(mask[i] & data)
{
ret += mask[i];
}
}
//HIGH
for(i = 0; i < 4; i++)
{
if(mask[i] & (data >> 4))
{
ret += (mask[i] * 10);
}
}
return ret;
}
// 8010 initialization
int RtcInit(void)
{
uint8_t flag = 0;
uint8_t data = 0;
uint8_t ctrl[2];
int need_clear = 0, err = 0;
err = RtcI2cRead(I2C_RTC_BASE, RX8010_FLAG, &flag, 1);
flag &= ~(RX8010_FLAG_VLF);
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_FLAG, &flag, 1);
/* Initialize reserved registers as specified in datasheet */
data = 0xD8;
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_RESV17, &data, 1);
data = 0x00;
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_RESV30, &data, 1);
data = 0x08;
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_RESV31, &data, 1);
data = 0x00;
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_IRQ, &data, 1);
err = RtcI2cRead(I2C_RTC_BASE, RX8010_FLAG, ctrl, 2);
if(ctrl[0] & RX8010_FLAG_VLF)
{
rtc_print("\r\n Frequency stop was detected\r\n");
}
if(ctrl[0] & RX8010_FLAG_AF)
{
rtc_print("\r\n Alarm was detected\r\n");
need_clear = 1;
}
if(ctrl[0] & RX8010_FLAG_TF)
{
need_clear = 1;
}
if(ctrl[0] & RX8010_FLAG_UF)
{
need_clear = 1;
}
if(need_clear)
{
ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF);
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_FLAG, ctrl,1);
if(!err)
{
return err;
}
}
return err;
}
// check format and get BCD format date like 2018-06-21 16:29:30
int RtcGetBcdDate(uint8_t* date, uint8_t* bcd_date)
{
int i;
int temp_date[6];
if(sscanf(date, "20%2d-%2d-%2d %2d:%2d:%2d",
&temp_date[5],
&temp_date[4],
&temp_date[3],
&temp_date[2],
&temp_date[1],
&temp_date[0]) == EOF)
{
rtc_print("i2c %s failed\n", __func__);
return -1;
}
for(i = 0; i < 6; i++)
{
bcd_date[i] = TO_BCD(temp_date[i]);
}
return 0;
}
// setup time
int RtcSetTime(uint8_t* asc_date)
{
uint8_t bcd_date[6];
int ret, err;
if(RtcGetBcdDate(asc_date, bcd_date))
{
rtc_print("\r\n Date format error! \r\n");
return -1;
}
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_SEC, bcd_date, 3);
err |= RtcI2cWrite(I2C_RTC_BASE, RX8010_MDAY, &bcd_date[3], 3);
return err;
}
// get rx8010 time
int RtcGetTime(struct tm *ct)
{
uint8_t rtc_data[7];
uint8_t time_str[7];
uint8_t flag_reg;
int err;
err = RtcI2cRead(I2C_RTC_BASE, RX8010_FLAG, &flag_reg, 1);
if(flag_reg & RX8010_FLAG_VLF)
{
rtc_print("\r\n Frequency stop was detected\r\n");
return 1;
}
err = RtcI2cRead(I2C_RTC_BASE, RX8010_SEC, rtc_data, 7);
time_str[0] = bcd2bin(rtc_data[RX8010_SEC - RX8010_SEC] & 0x7f);
time_str[1] = bcd2bin(rtc_data[RX8010_MIN - RX8010_SEC] & 0x7f);
time_str[2] = bcd2bin(rtc_data[RX8010_HOUR - RX8010_SEC] & 0x3f);
time_str[4] = bcd2bin(rtc_data[RX8010_MDAY - RX8010_SEC] & 0x3f);
time_str[5] = bcd2bin(rtc_data[RX8010_MONTH - RX8010_SEC] & 0x1f);
time_str[6] = bcd2bin(rtc_data[RX8010_YEAR - RX8010_SEC]);
time_str[3] = rtc_data[RX8010_WDAY - RX8010_SEC] & 0x7f;
rtc_print("RX8010 Time: 20%d%d-%d%d-%d%d %d%d:%d%d:%d%d\r\n",
time_str[6]/10, time_str[6]%10, time_str[5]/10, time_str[5]%10, time_str[4]/10, time_str[4]%10,
time_str[2]/10, time_str[2]%10, time_str[1]/10, time_str[1]%10, time_str[0]/10, time_str[0]%10);
ct->tm_year = time_str[6];
ct->tm_mon = time_str[5];
ct->tm_mday = time_str[4];
ct->tm_wday = time_str[3];
ct->tm_hour = time_str[2];
ct->tm_min = time_str[1];
ct->tm_sec = time_str[0];
return 0;
}
static int GetWeekDay(int year, int month, int day)
{
if(month==1||month==2)
{
year -=1;
month +=12;
}
return (day+1+2*month+3*(month+1)/5+year+(year/4)-year/100+year/400)%7+1;
}
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;
RtcGetTime(&ct);
*time = mktime(&ct);
}
break;
case OPER_RTC_SET_TIME:
{
char time_str[MAX_TIME_STR_SIZE] = {0};
struct tm *ct = localtime(time);
strftime(time_str, MAX_TIME_STR_SIZE, "%y-%m-%d %H:%M:%S", ct);
RtcSetTime(time_str);
}
break;
}
return EOK;
}
int RtcConfiguration(void)
{
BOARD_InitI2C1Pins();
RtcI2cInit();
RtcInit();
return 0;
}
/*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("hw_rtc_init RtcBusInit error %d\n", ret);
return ERROR;
}
/*Init the rtc driver*/
ret = RtcDriverInit(rtc_driver, RTC_DRV_NAME);
if(EOK != ret)
{
KPrintf("hw_rtc_init 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("hw_rtc_init 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("hw_rtc_init RtcDeviceInit device %s error %d\n", RTC_DEVICE_NAME, ret);
return ERROR;
}
ret = RtcDeviceAttachToBus(RTC_DEVICE_NAME, RTC_BUS_NAME);
if(EOK != ret)
{
KPrintf("hw_rtc_init RtcDeviceAttachToBus device %s error %d\n", RTC_DEVICE_NAME, ret);
return ERROR;
}
return ret;
}
int Imrt1052HwRtcInit(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("hw_rtc_init error ret %u\n", ret);
return ERROR;
}
ret = BoardRtcDevBend();
if(EOK != ret)
{
KPrintf("hw_rtc_init error ret %u\n", ret);
return ERROR;
}
RtcConfiguration();
return ret;
}
void RtcTestRx8010(int argc, char* argv[])
{
if(argc == 2)
{
if(RtcSetTime(argv[1]) == 0)
{
RtcGetTime(NULL);
}
}
else
{
RtcGetTime(NULL);
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)| SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)| SHELL_CMD_PARAM_NUM(3),
rtc, RtcTestRx8010, i2c rtc "date time");

View File

@ -0,0 +1,71 @@
/*
* The Clear BSD License
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
* that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file hardware_rtc.c
* @brief I2C RTC drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022.1.18
*/
/*************************************************
File name: hardware_rtc.c
Description: support ok1052-c rtc driver I2C function
History:
1. Date: 2022-01-18
Author: AIIT XUOS Lab
Modification:
1. support ok1052-c rtc
*************************************************/
#include "connect_rtc.h"
#include "connect_i2c.h"
void RtcI2cInit()
{
I2cHardwareInit();
}
status_t RtcI2cWrite(LPI2C_Type *base, uint32_t sub_addr, uint8_t *buf, uint16_t size)
{
return I2cHardwareWrite(base, I2C_RTC_ADDR, sub_addr, buf, size);
}
uint32_t RtcI2cRead(LPI2C_Type *base,uint32_t sub_addr,uint8_t* buf, uint16_t size)
{
return I2cHardwareRead(base, I2C_RTC_ADDR, sub_addr, buf, size);
}

View File

@ -0,0 +1,45 @@
config BSP_USING_SPI1
bool "Enable SPI1"
default y
if BSP_USING_SPI1
config SPI_1_BUS_NAME
string "spi1 bus name"
default "spi1"
config SPI_1_DRV_NAME
string "spi bus 1 driver name"
default "spi1_drv"
config SPI_1_DEV_NAME_0
string "spi bus 1 device name"
default "spi1_dev"
endif
config BSP_USING_SPI2
bool "Enable SPI2"
default y
if BSP_USING_SPI2
config SPI_2_BUS_NAME
string "spi2 bus name"
default "spi2"
config SPI_2_DRV_NAME
string "spi bus 2 driver name"
default "spi2_drv"
config SPI_2_DEV_NAME_0
string "spi bus 2 device name"
default "spi2_dev"
endif
config BSP_USING_SPI3
bool "Enable SPI3"
default y
if BSP_USING_SPI3
config SPI_3_BUS_NAME
string "spi3 bus name"
default "spi3"
config SPI_3_DRV_NAME
string "spi bus 3 driver name"
default "spi3_drv"
config SPI_3_DEV_NAME_0
string "spi bus 3 device name"
default "spi3_dev"
endif

View File

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

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2022 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-27 SummerGift add spi flash port file
*/
/**
* @file connect_flash_spi.c
* @brief support ok1052-c-board spi flash function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
/*************************************************
File name: connect_flash_spi.c
Description: support ok1052-c-board spi flash bus register function
Others: take RT-Thread v4.0.2/bsp/stm32/stm32f407-atk-explorer/board/ports/spi-flash-init.c
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2022-03-01
Author: AIIT XUOS Lab
Modification:
1. for ok1052-c compilation
*************************************************/
#include "flash_spi.h"
int FlashW25qxxSpiDeviceInit(void)
{
#ifdef BSP_USING_SPI1
#endif
return EOK;
}

View File

@ -0,0 +1,959 @@
/*
* Copyright (c) 2020 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-5 SummerGift first version
* 2018-12-11 greedyhao Porting for stm32f7xx
* 2019-01-03 zylx modify DMA initialization and spixfer function
* 2020-01-15 whj4674672 Porting for stm32h7xx
* 2020-06-18 thread-liu Porting for stm32mp1xx
* 2020-10-14 Dozingfiretruck Porting for stm32wbxx
*/
/**
* @file connect_spi.c
* @brief support ok1052-c spi function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
/*************************************************
File name: connect_spi.c
Description: support ok1052-c spi configure and spi bus register function
Others: take RT-Thread v4.0.2/bsp/stm32/libraries/HAL_Drivers/drv_spi.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2022-03-01
Author: AIIT XUOS Lab
Modification:
1. support ok1052-c spi configure, write and read
2. support ok1052-c spi bus device and driver register
3. add ok1052-c spi test letter command
*************************************************/
#include "board.h"
#include "connect_spi.h"
#include "fsl_lpspi.h"
#include "pin_mux.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define SPI_PCS_FOR_INIT (kLPSPI_Pcs0)
/* Select USB1 PLL PFD0 (720 MHz) as lpspi clock source */
#define SPI_CLOCK_SOURCE_SELECT (1U)
/* Clock divider for master lpspi clock source */
#define SPI_CLOCK_SOURCE_DIVIDER (7U)
#define SPI_CLOCK_FREQ (CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (SPI_CLOCK_SOURCE_DIVIDER + 1U))
#define TRANSFER_SIZE (512U) /*! Transfer dataSize .*/
#define TRANSFER_BAUDRATE (500000U) /*! Transfer baudrate - 500k */
#define spi_print KPrintf
#define spi_trace() KPrintf("lw: [%s][%d] passed!\n", __func__, __LINE__)
typedef struct __spi_transfer_t
{
uint32_t size;
volatile uint32_t cnt;
uint8_t water;
uint8_t fifo;
volatile bool completed;
uint8_t buf[TRANSFER_SIZE];
}spi_transfer_t;
#if defined(BSP_USING_SPI1)
struct Stm32Spi spi1;
spi_transfer_t spi1_rx_data;
spi_transfer_t spi1_tx_data;
#endif
#if defined(BSP_USING_SPI2)
struct Stm32Spi spi2;
spi_transfer_t spi2_rx_data;
spi_transfer_t spi2_tx_data;
#endif
#if defined(BSP_USING_SPI3)
struct Stm32Spi spi3;
spi_transfer_t spi3_rx_data;
spi_transfer_t spi3_tx_data;
#endif
/*******************************************************************************
* Code
******************************************************************************/
void LPSPI1_IRQHandler(int vector, void *param)
{
LPSPI_Type *spi_base = LPSPI1;
int rx_size = spi1_rx_data.size < TRANSFER_SIZE ? spi1_rx_data.size : TRANSFER_SIZE;
int tx_size = spi1_tx_data.size < TRANSFER_SIZE ? spi1_tx_data.size : TRANSFER_SIZE;
if (spi1_rx_data.cnt < rx_size)
{
/* First, disable the interrupts to avoid potentially triggering another interrupt
* while reading out the RX FIFO as more data may be coming into the RX FIFO. We'll
* re-enable the interrupts on the LPSPI state after reading out the FIFO.
*/
LPSPI_DisableInterrupts(spi_base, kLPSPI_RxInterruptEnable);
while (LPSPI_GetRxFifoCount(spi_base))
{
/*Read out the data*/
spi1_rx_data.buf[spi1_rx_data.cnt] = LPSPI_ReadData(spi_base);
spi1_rx_data.cnt++;
if (spi1_rx_data.cnt == rx_size)
{
break;
}
}
/* Re-enable the interrupts only if rxCount indicates there is more data to receive,
* else we may get a spurious interrupt.
* */
if (spi1_rx_data.cnt < rx_size)
{
/* Set the TDF and RDF interrupt enables simultaneously to avoid race conditions */
LPSPI_EnableInterrupts(spi_base, kLPSPI_RxInterruptEnable);
}
}
/*Update rxWatermark. There isn't RX interrupt for the last datas if the RX count is not greater than rxWatermark.*/
if ((rx_size - spi1_rx_data.cnt) <= spi1_rx_data.water)
{
spi_base->FCR =
(spi_base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
LPSPI_FCR_RXWATER(((rx_size - spi1_rx_data.cnt) > 1) ? ((rx_size - spi1_rx_data.cnt) - 1U) : (0U));
}
if (spi1_tx_data.cnt < tx_size)
{
while ((LPSPI_GetTxFifoCount(spi_base) < spi1_tx_data.fifo) &&
(spi1_tx_data.cnt - spi1_rx_data.cnt < spi1_tx_data.fifo))
{
/*Write the word to TX register*/
LPSPI_WriteData(spi_base, spi1_tx_data.buf[spi1_tx_data.cnt]);
spi1_tx_data.cnt++;
if (spi1_tx_data.cnt == tx_size)
{
spi1_tx_data.completed = true;
/* Complete the transfer and disable the interrupts */
LPSPI_DisableInterrupts(spi_base, kLPSPI_AllInterruptEnable);
break;
}
}
}
/* Check if we're done with this transfer.*/
if ((spi1_tx_data.cnt == tx_size) && (spi1_rx_data.cnt == tx_size))
{
spi1_tx_data.completed = true;
/* Complete the transfer and disable the interrupts */
LPSPI_DisableInterrupts(spi_base, kLPSPI_AllInterruptEnable);
}
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
DECLARE_HW_IRQ(LPSPI1_IRQn, LPSPI1_IRQHandler, NONE);
void LPSPI2_IRQHandler(int vector, void *param)
{
LPSPI_Type *spi_base = LPSPI2;
int rx_size = spi2_rx_data.size < TRANSFER_SIZE ? spi2_rx_data.size : TRANSFER_SIZE;
int tx_size = spi2_tx_data.size < TRANSFER_SIZE ? spi2_tx_data.size : TRANSFER_SIZE;
if (spi2_rx_data.cnt < rx_size)
{
/* First, disable the interrupts to avoid potentially triggering another interrupt
* while reading out the RX FIFO as more data may be coming into the RX FIFO. We'll
* re-enable the interrupts on the LPSPI state after reading out the FIFO.
*/
LPSPI_DisableInterrupts(spi_base, kLPSPI_RxInterruptEnable);
while (LPSPI_GetRxFifoCount(spi_base))
{
/*Read out the data*/
spi2_rx_data.buf[spi2_rx_data.cnt] = LPSPI_ReadData(spi_base);
spi2_rx_data.cnt++;
if (spi2_rx_data.cnt == rx_size)
{
break;
}
}
/* Re-enable the interrupts only if rxCount indicates there is more data to receive,
* else we may get a spurious interrupt.
* */
if (spi2_rx_data.cnt < rx_size)
{
/* Set the TDF and RDF interrupt enables simultaneously to avoid race conditions */
LPSPI_EnableInterrupts(spi_base, kLPSPI_RxInterruptEnable);
}
}
/*Update rxWatermark. There isn't RX interrupt for the last datas if the RX count is not greater than rxWatermark.*/
if ((rx_size - spi2_rx_data.cnt) <= spi2_rx_data.water)
{
spi_base->FCR =
(spi_base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
LPSPI_FCR_RXWATER(((rx_size - spi2_rx_data.cnt) > 1) ? ((rx_size - spi2_rx_data.cnt) - 1U) : (0U));
}
if (spi2_tx_data.cnt < tx_size)
{
while ((LPSPI_GetTxFifoCount(spi_base) < spi2_tx_data.fifo) &&
(spi2_tx_data.cnt - spi2_rx_data.cnt < spi2_tx_data.fifo))
{
/*Write the word to TX register*/
LPSPI_WriteData(spi_base, spi2_tx_data.buf[spi2_tx_data.cnt]);
spi2_tx_data.cnt++;
if (spi2_tx_data.cnt == tx_size)
{
spi2_tx_data.completed = true;
/* Complete the transfer and disable the interrupts */
LPSPI_DisableInterrupts(spi_base, kLPSPI_AllInterruptEnable);
break;
}
}
}
/* Check if we're done with this transfer.*/
if ((spi2_tx_data.cnt == tx_size) && (spi2_rx_data.cnt == tx_size))
{
spi2_tx_data.completed = true;
/* Complete the transfer and disable the interrupts */
LPSPI_DisableInterrupts(spi_base, kLPSPI_AllInterruptEnable);
}
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
DECLARE_HW_IRQ(LPSPI2_IRQn, LPSPI2_IRQHandler, NONE);
void LPSPI3_IRQHandler(int vector, void *param)
{
LPSPI_Type *spi_base = LPSPI3;
int rx_size = spi3_rx_data.size < TRANSFER_SIZE ? spi3_rx_data.size : TRANSFER_SIZE;
int tx_size = spi3_tx_data.size < TRANSFER_SIZE ? spi3_tx_data.size : TRANSFER_SIZE;
if (spi3_rx_data.cnt < rx_size)
{
/* First, disable the interrupts to avoid potentially triggering another interrupt
* while reading out the RX FIFO as more data may be coming into the RX FIFO. We'll
* re-enable the interrupts on the LPSPI state after reading out the FIFO.
*/
LPSPI_DisableInterrupts(spi_base, kLPSPI_RxInterruptEnable);
while (LPSPI_GetRxFifoCount(spi_base))
{
/*Read out the data*/
spi3_rx_data.buf[spi3_rx_data.cnt] = LPSPI_ReadData(spi_base);
spi3_rx_data.cnt++;
if (spi3_rx_data.cnt == rx_size)
{
break;
}
}
/* Re-enable the interrupts only if rxCount indicates there is more data to receive,
* else we may get a spurious interrupt.
* */
if (spi3_rx_data.cnt < rx_size)
{
/* Set the TDF and RDF interrupt enables simultaneously to avoid race conditions */
LPSPI_EnableInterrupts(spi_base, kLPSPI_RxInterruptEnable);
}
}
/*Update rxWatermark. There isn't RX interrupt for the last datas if the RX count is not greater than rxWatermark.*/
if ((rx_size - spi3_rx_data.cnt) <= spi3_rx_data.water)
{
spi_base->FCR =
(spi_base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
LPSPI_FCR_RXWATER(((rx_size - spi3_rx_data.cnt) > 1) ? ((rx_size - spi3_rx_data.cnt) - 1U) : (0U));
}
if (spi3_tx_data.cnt < tx_size)
{
while ((LPSPI_GetTxFifoCount(spi_base) < spi3_tx_data.fifo) &&
(spi3_tx_data.cnt - spi3_rx_data.cnt < spi3_tx_data.fifo))
{
/*Write the word to TX register*/
LPSPI_WriteData(spi_base, spi3_tx_data.buf[spi3_tx_data.cnt]);
spi3_tx_data.cnt++;
if (spi3_tx_data.cnt == tx_size)
{
spi3_tx_data.completed = true;
/* Complete the transfer and disable the interrupts */
LPSPI_DisableInterrupts(spi_base, kLPSPI_AllInterruptEnable);
break;
}
}
}
/* Check if we're done with this transfer.*/
if ((spi3_tx_data.cnt == tx_size) && (spi3_rx_data.cnt == tx_size))
{
spi3_tx_data.completed = true;
/* Complete the transfer and disable the interrupts */
LPSPI_DisableInterrupts(spi_base, kLPSPI_AllInterruptEnable);
}
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
DECLARE_HW_IRQ(LPSPI3_IRQn, LPSPI3_IRQHandler, NONE);
void SpiMasterInit(LPSPI_Type *base)
{
lpspi_master_config_t cfg;
/*Master config*/
cfg.baudRate = TRANSFER_BAUDRATE;
cfg.bitsPerFrame = 8;
cfg.cpol = kLPSPI_ClockPolarityActiveHigh;
cfg.cpha = kLPSPI_ClockPhaseFirstEdge;
cfg.direction = kLPSPI_MsbFirst;
cfg.pcsToSckDelayInNanoSec = 1000000000 / cfg.baudRate;
cfg.lastSckToPcsDelayInNanoSec = 1000000000 / cfg.baudRate;
cfg.betweenTransferDelayInNanoSec = 1000000000 / cfg.baudRate;
cfg.whichPcs = SPI_PCS_FOR_INIT;
cfg.pcsActiveHighOrLow = kLPSPI_PcsActiveLow;
cfg.pinCfg = kLPSPI_SdiInSdoOut;
cfg.dataOutConfig = kLpspiDataOutRetained;
LPSPI_MasterInit(base, &cfg, SPI_CLOCK_FREQ);
}
void SpiSlaveInit(LPSPI_Type *base)
{
lpspi_slave_config_t cfg;
/*Slave config*/
cfg.bitsPerFrame = 8;
cfg.cpol = kLPSPI_ClockPolarityActiveHigh;
cfg.cpha = kLPSPI_ClockPhaseFirstEdge;
cfg.direction = kLPSPI_MsbFirst;
cfg.whichPcs = SPI_PCS_FOR_INIT;
cfg.pcsActiveHighOrLow = kLPSPI_PcsActiveLow;
cfg.pinCfg = kLPSPI_SdiInSdoOut;
cfg.dataOutConfig = kLpspiDataOutRetained;
LPSPI_SlaveInit(base, &cfg);
}
int SpiHwParamInit(struct Stm32HwSpi *spi_param)
{
LPSPI_Type *spi_base = spi_param->base;
uint32_t whichPcs = kLPSPI_Pcs0;
uint8_t fifo_size, tx_water, rx_water;
/*The TX and RX FIFO sizes are always the same*/
fifo_size = LPSPI_GetRxFifoSize(spi_base);
/*Set the RX and TX watermarks to reduce the ISR times.*/
if (fifo_size > 1)
{
tx_water = 1;
rx_water = fifo_size - 2;
}
else
{
tx_water = 0;
rx_water = 0;
}
LPSPI_SetFifoWatermarks(spi_base, tx_water, rx_water);
LPSPI_Enable(spi_base, false);
spi_base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
LPSPI_Enable(spi_base, true);
/*Flush FIFO , clear status , disable all the inerrupts.*/
LPSPI_FlushFifo(spi_base, true, true);
LPSPI_ClearStatusFlags(spi_base, kLPSPI_AllStatusFlag);
LPSPI_DisableInterrupts(spi_base, kLPSPI_AllInterruptEnable);
spi_base->TCR =
(spi_base->TCR &
~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
LPSPI_TCR_CONT(0) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(0) | LPSPI_TCR_TXMSK(0) | LPSPI_TCR_PCS(whichPcs);
/* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
* and you should also enable the INTMUX interupt in your application.
*/
EnableIRQ(spi_param->irq);
LPSPI_EnableInterrupts(spi_base, kLPSPI_RxInterruptEnable);
}
int SpiReadData(struct Stm32HwSpi *spi_param, uint8_t *buf, int len)
{
int fifo_size;
int timeout = 50; // wait for read SPI data
LPSPI_Type *spi_base = spi_param->base;
BOARD_InitSPIPins();
/*Set clock source for LPSPI*/
CLOCK_SetMux(kCLOCK_LpspiMux, SPI_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_LpspiDiv, SPI_CLOCK_SOURCE_DIVIDER);
uint32_t errorCount;
uint32_t i;
uint32_t whichPcs;
uint8_t txWatermark;
BOARD_InitSPIPins();
/*Set clock source for LPSPI*/
CLOCK_SetMux(kCLOCK_LpspiMux, SPI_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_LpspiDiv, SPI_CLOCK_SOURCE_DIVIDER);
/*Set up the transfer data*/
for (i = 0; i < TRANSFER_SIZE; i++)
{
spi1_rx_data.buf[i] = 0;
}
SpiSlaveInit(spi_base);
/******************Set up slave first ******************/
spi1_rx_data.completed = false;
spi1_rx_data.cnt = 0;
spi1_rx_data.size = len;
whichPcs = SPI_PCS_FOR_INIT;
/*The TX and RX FIFO sizes are always the same*/
spi1_rx_data.fifo = LPSPI_GetRxFifoSize(spi_base);
/*Set the RX and TX watermarks to reduce the ISR times.*/
if (spi1_rx_data.fifo > 1)
{
txWatermark = 1;
spi1_rx_data.water = spi1_rx_data.fifo - 2;
}
else
{
txWatermark = 0;
spi1_rx_data.water = 0;
}
LPSPI_SetFifoWatermarks(spi_base, txWatermark, spi1_rx_data.water);
LPSPI_Enable(spi_base, false);
spi_base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
LPSPI_Enable(spi_base, true);
/*Flush FIFO , clear status , disable all the interrupts.*/
LPSPI_FlushFifo(spi_base, true, true);
LPSPI_ClearStatusFlags(spi_base, kLPSPI_AllStatusFlag);
LPSPI_DisableInterrupts(spi_base, kLPSPI_AllInterruptEnable);
spi_base->TCR =
(spi_base->TCR &
~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
LPSPI_TCR_CONT(0) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(0) | LPSPI_TCR_TXMSK(0) | LPSPI_TCR_PCS(whichPcs);
/* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
* and you should also enable the INTMUX interrupt in your application.
*/
EnableIRQ(spi_param->irq);
LPSPI_EnableInterrupts(spi_base, kLPSPI_RxInterruptEnable);
/******************Wait for slave transfer completed.******************/
while((spi1_rx_data.cnt < (len - 1)) && (timeout--))
{
MdelayKTask(100);
}
if(buf && (len <= TRANSFER_SIZE))
{
memcpy(buf, spi1_rx_data.buf, len);
}
LPSPI_Deinit(spi_base);
}
void SpiWriteData(struct Stm32HwSpi *spi_param, const uint8_t *buf, uint16_t len)
{
uint32_t errorCount;
uint32_t i;
uint32_t whichPcs;
uint8_t txWatermark;
LPSPI_Type *spi_base = spi_param->base;
int timeout = 1000; // wait for write SPI data
BOARD_InitSPIPins();
/*Set clock source for LPSPI*/
CLOCK_SetMux(kCLOCK_LpspiMux, SPI_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_LpspiDiv, SPI_CLOCK_SOURCE_DIVIDER);
/*Set up the transfer data*/
memcpy(spi1_tx_data.buf, buf, len);
SpiMasterInit(spi_base);
spi1_rx_data.size = len;
spi1_tx_data.size = len;
spi1_tx_data.completed = false;
spi1_tx_data.cnt = 0;
spi1_rx_data.cnt = 0;
whichPcs = SPI_PCS_FOR_INIT;
/*The TX and RX FIFO sizes are always the same*/
spi1_tx_data.fifo = LPSPI_GetRxFifoSize(spi_base);
/*Set the RX and TX watermarks to reduce the ISR times.*/
if (spi1_tx_data.fifo > 1)
{
txWatermark = 1;
spi1_rx_data.water = spi1_tx_data.fifo - 2;
}
else
{
txWatermark = 0;
spi1_rx_data.water = 0;
}
LPSPI_SetFifoWatermarks(spi_base, txWatermark, spi1_rx_data.water);
LPSPI_Enable(spi_base, false);
spi_base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
LPSPI_Enable(spi_base, true);
/*Flush FIFO , clear status , disable all the inerrupts.*/
LPSPI_FlushFifo(spi_base, true, true);
LPSPI_ClearStatusFlags(spi_base, kLPSPI_AllStatusFlag);
LPSPI_DisableInterrupts(spi_base, kLPSPI_AllInterruptEnable);
spi_base->TCR =
(spi_base->TCR &
~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
LPSPI_TCR_CONT(0) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(0) | LPSPI_TCR_TXMSK(0) | LPSPI_TCR_PCS(whichPcs);
/* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
* and you should also enable the INTMUX interupt in your application.
*/
EnableIRQ(spi_param->irq);
LPSPI_EnableInterrupts(spi_base, kLPSPI_AllInterruptEnable);
while((spi1_tx_data.cnt < (spi1_tx_data.size - 1)) && (timeout--))
{
MdelayKTask(10);
}
spi_print("SPI: master rx %d tx %d size %d completed s %d m %d!\r\n", spi1_rx_data.cnt,
spi1_tx_data.cnt, spi1_tx_data.size, spi1_rx_data.completed, spi1_tx_data.completed);
LPSPI_Deinit(spi_base);
}
static uint32 Stm32SpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg)
{
int state;
x_size_t message_length, already_send_length;
uint16 send_length;
const uint8 *write_buf;
NULL_PARAM_CHECK(spi_dev);
NULL_PARAM_CHECK(spi_datacfg);
struct Stm32Spi *StmSpi = CONTAINER_OF(spi_dev->haldev.owner_bus, struct Stm32Spi, spi_bus);
struct Stm32HwSpi *StmCfg = (struct Stm32HwSpi *) spi_dev->haldev.private_data;
while(NONE != spi_datacfg) {
message_length = spi_datacfg->length;
write_buf = spi_datacfg->tx_buff;
while (message_length) {
if (message_length > 65535){
send_length = 65535;
message_length = message_length - 65535;
} else {
send_length = message_length;
message_length = 0;
}
/* calculate the start address */
already_send_length = spi_datacfg->length - send_length - message_length;
write_buf = (uint8 *)spi_datacfg->tx_buff + already_send_length;
if (spi_datacfg->tx_buff) {
SpiWriteData(StmCfg, spi_datacfg->tx_buff, send_length);
}
if (state != 0) {
KPrintf("spi write error : %d\n", state);
spi_datacfg->length = 0;
}
}
spi_datacfg = spi_datacfg->next;
}
return EOK;
}
static uint32 Stm32SpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg)
{
int state;
x_size_t message_length, already_send_length;
uint16 read_length, spi_read_length = 0;
uint8 *read_buf;
NULL_PARAM_CHECK(spi_dev);
NULL_PARAM_CHECK(spi_datacfg);
struct Stm32Spi *StmSpi = CONTAINER_OF(spi_dev->haldev.owner_bus, struct Stm32Spi, spi_bus);
struct Stm32HwSpi *StmCfg = (struct Stm32HwSpi *) spi_dev->haldev.private_data;
while (NONE != spi_datacfg) {
message_length = spi_datacfg->length;
read_buf = spi_datacfg->rx_buff;
while (message_length) {
if (message_length > 65535) {
read_length = 65535;
message_length = message_length - 65535;
} else {
read_length = message_length;
message_length = 0;
}
/* calculate the start address */
already_send_length = spi_datacfg->length - read_length - message_length;
read_buf = (uint8 *)spi_datacfg->rx_buff + already_send_length;
if (spi_datacfg->rx_buff) {
memset(read_buf, 0xff, read_length);
SpiReadData(StmCfg, read_buf, read_length);
}
if (state != 0) {
KPrintf("spi read error : %d\n", state);
spi_datacfg->length = 0;
}
}
spi_read_length += spi_datacfg->length;
spi_datacfg = spi_datacfg->next;
}
return spi_read_length;
}
static const struct SpiDevDone spi_dev_done =
{
.dev_open = NONE,
.dev_close = NONE,
.dev_write = Stm32SpiWriteData,
.dev_read = Stm32SpiReadData,
};
static x_err_t Stm32SpiInit(struct Stm32Spi *spi_drv, struct SpiMasterParam *cfg)
{
NULL_PARAM_CHECK(spi_drv);
NULL_PARAM_CHECK(cfg);
}
static uint32 SpiDrvInit(struct SpiDriver *spi_drv)
{
NULL_PARAM_CHECK(spi_drv);
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data);
struct Stm32Spi *StmSpi = CONTAINER_OF(spi_drv->driver.owner_bus, struct Stm32Spi, spi_bus);
return Stm32SpiInit(StmSpi, dev_param->spi_master_param);
}
static uint32 SpiDrvConfigure(struct SpiDriver *spi_drv, struct SpiMasterParam *spi_param)
{
NULL_PARAM_CHECK(spi_drv);
NULL_PARAM_CHECK(spi_param);
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data);
dev_param->spi_master_param = spi_param;
dev_param->spi_master_param->spi_work_mode = dev_param->spi_master_param->spi_work_mode & SPI_MODE_MASK;
return EOK;
}
/*Configure the spi device param, make sure struct (configure_info->private_data) = (SpiMasterParam)*/
static uint32 Stm32SpiDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
struct SpiDriver *spi_drv = (struct SpiDriver *)drv;
struct SpiMasterParam *spi_param;
switch (configure_info->configure_cmd)
{
case OPE_INT:
ret = SpiDrvInit(spi_drv);
break;
case OPE_CFG:
spi_param = (struct SpiMasterParam *)configure_info->private_data;
ret = SpiDrvConfigure(spi_drv, spi_param);
break;
default:
break;
}
return ret;
}
static int BoardSpiBusInit(struct Stm32Spi *stm32spi_bus, struct SpiDriver *spi_driver, char* drv_name)
{
x_err_t ret = EOK;
/*Init the spi bus */
ret = SpiBusInit(&stm32spi_bus->spi_bus, stm32spi_bus->bus_name);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiBusInit error %d\n", ret);
return ERROR;
}
/*Init the spi driver*/
ret = SpiDriverInit(spi_driver, 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(drv_name, stm32spi_bus->bus_name);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
static int Stm32HwSpiBusInit(void)
{
x_err_t ret = EOK;
struct Stm32Spi *StmSpiBus;
#ifdef BSP_USING_SPI1
StmSpiBus = &spi1;
StmSpiBus->instance = LPSPI1;
StmSpiBus->bus_name = SPI_1_BUS_NAME;
StmSpiBus->spi_bus.private_data = &spi1;
static struct SpiDriver spi_driver_1;
memset(&spi_driver_1, 0, sizeof(struct SpiDriver));
spi_driver_1.configure = &(Stm32SpiDrvConfigure);
ret = BoardSpiBusInit(StmSpiBus, &spi_driver_1, SPI_1_DRV_NAME);
if (EOK != ret) {
KPrintf("Board_Spi_Init spi_bus_init %s error ret %u\n", StmSpiBus->bus_name, ret);
return ERROR;
}
static struct SpiHardwareDevice spi1_dev;
static struct Stm32HwSpi spi1_cfg;
spi1_cfg.base = StmSpiBus->instance;
spi1_cfg.irq = LPSPI1_IRQn;
spi1_dev.spi_dev_done = &spi_dev_done;
ret = SpiDeviceRegister(&spi1_dev, (void *)&spi1_cfg, SPI_1_DEV_NAME_0);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
ret = SpiDeviceAttachToBus(SPI_1_DEV_NAME_0, SPI_1_BUS_NAME);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
#endif
#ifdef BSP_USING_SPI2
StmSpiBus = &spi2;
StmSpiBus->instance = LPSPI2;
StmSpiBus->bus_name = SPI_2_BUS_NAME;
StmSpiBus->spi_bus.private_data = &spi2;
static struct SpiDriver spi_driver_2;
memset(&spi_driver_2, 0, sizeof(struct SpiDriver));
spi_driver_2.configure = &(Stm32SpiDrvConfigure);
ret = BoardSpiBusInit(StmSpiBus, &spi_driver_2, SPI_2_DRV_NAME);
if (EOK != ret) {
KPrintf("Board_Spi_Init spi_bus_init %s error ret %u\n", StmSpiBus->bus_name, ret);
return ERROR;
}
static struct SpiHardwareDevice spi2_dev;
static struct Stm32HwSpi spi2_cfg;
spi2_cfg.base = StmSpiBus->instance;
spi2_cfg.irq = LPSPI2_IRQn;
spi2_dev.spi_dev_done = &spi_dev_done;
ret = SpiDeviceRegister(&spi2_dev, (void *)&spi2_cfg, SPI_2_DEV_NAME_0);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
ret = SpiDeviceAttachToBus(SPI_2_DEV_NAME_0, SPI_2_BUS_NAME);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
#endif
#ifdef BSP_USING_SPI3
StmSpiBus = &spi3;
StmSpiBus->instance = LPSPI3;
StmSpiBus->bus_name = SPI_3_BUS_NAME;
StmSpiBus->spi_bus.private_data = &spi3;
static struct SpiDriver spi_driver_3;
memset(&spi_driver_3, 0, sizeof(struct SpiDriver));
spi_driver_3.configure = &(Stm32SpiDrvConfigure);
ret = BoardSpiBusInit(StmSpiBus, &spi_driver_3, SPI_3_DRV_NAME);
if (EOK != ret) {
KPrintf("Board_Spi_Init spi_bus_init %s error ret %u\n", StmSpiBus->bus_name, ret);
return ERROR;
}
static struct SpiHardwareDevice spi3_dev;
static struct Stm32HwSpi spi3_cfg;
spi3_cfg.base = StmSpiBus->instance;
spi3_cfg.irq = LPSPI3_IRQn;
spi3_dev.spi_dev_done = &spi_dev_done;
ret = SpiDeviceRegister(&spi3_dev, (void *)&spi3_cfg, SPI_3_DEV_NAME_0);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
ret = SpiDeviceAttachToBus(SPI_3_DEV_NAME_0, SPI_3_BUS_NAME);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
#endif
return EOK;
}
x_err_t HwSpiDeviceAttach(const char *bus_name, const char *device_name)
{
NULL_PARAM_CHECK(bus_name);
NULL_PARAM_CHECK(device_name);
x_err_t result;
struct SpiHardwareDevice *spi_device;
static SpiDeviceParam spi_dev_param;
memset(&spi_dev_param, 0, sizeof(SpiDeviceParam));
/* attach the device to spi bus*/
spi_device = (struct SpiHardwareDevice *)x_malloc(sizeof(struct SpiHardwareDevice));
CHECK(spi_device);
memset(spi_device, 0, sizeof(struct SpiHardwareDevice));
spi_device->spi_dev_done = &spi_dev_done;
result = SpiDeviceRegister(spi_device, (void *)&spi_dev_param, device_name);
if (result != EOK) {
SYS_ERR("%s device %p register faild, %d\n", device_name, spi_device, result);
}
result = SpiDeviceAttachToBus(device_name, bus_name);
if (result != EOK) {
SYS_ERR("%s attach to %s faild, %d\n", device_name, bus_name, result);
}
CHECK(result == EOK);
return result;
}
int Imrt1052HwSpiInit(void)
{
return Stm32HwSpiBusInit();
}
void SpiReadTest(void *arg)
{
uint32_t i;
uint8_t test_buf[32] = {0};
struct Stm32HwSpi spi_param;
spi_param.base = LPSPI1;
spi_param.irq = LPSPI1_IRQn;
SpiReadData(&spi_param, test_buf, 32);
for(i = 0; i < sizeof(test_buf) ;i ++)
{
spi_print("%d - %x\n", i, test_buf[i]);
}
}
SHELL_EXPORT_CMD (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
spiread, SpiReadTest, SPI Read);
void SpiWriteTest(void *arg)
{
uint32_t i;
uint8_t test_buf[100] = {0};
struct Stm32HwSpi spi_param;
spi_param.base = LPSPI1;
spi_param.irq = LPSPI1_IRQn;
for(i = 0; i < sizeof(test_buf) ;i ++)
{
test_buf[i] = i;
}
SpiWriteData(&spi_param, test_buf, 100);
}
SHELL_EXPORT_CMD (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
spiwrite, SpiWriteTest, SPI Write );

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,18 +6,6 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/*
* Copyright (c) 2021 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 fsl_lpuart.c * @file fsl_lpuart.c
* @brief fsl uart drivers * @brief fsl uart drivers

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 AIIT XUOS Lab * Copyright (c) 2022 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2. * XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the 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: * You may obtain a copy of Mulan PSL v2 at:
@ -12,14 +12,14 @@
/** /**
* @file connect_gpio.h * @file connect_gpio.h
* @brief define stm32f407-st-discovery-board gpio function and struct * @brief define ok1052-c gpio function and struct
* @version 1.0 * @version 1.0
* @author AIIT XUOS Lab * @author AIIT XUOS Lab
* @date 2021-04-25 * @date 2022-03-01
*/ */
#ifndef CONNECT_GPIO_H #ifndef __CONNECT_GPIO_H_
#define CONNECT_GPIO_H #define __CONNECT_GPIO_H_
#include <device.h> #include <device.h>

View File

@ -26,6 +26,8 @@
#include <xs_waitqueue.h> #include <xs_waitqueue.h>
#include <sys/time.h> #include <sys/time.h>
typedef unsigned long NfdsType;
#if !defined(POLLIN) && !defined(POLLOUT) #if !defined(POLLIN) && !defined(POLLOUT)
#define POLLIN 0x001 #define POLLIN 0x001
@ -36,8 +38,6 @@
#define POLLMASK_DEFAULT (POLLIN | POLLOUT ) #define POLLMASK_DEFAULT (POLLIN | POLLOUT )
typedef unsigned long NfdsType;
struct pollfd struct pollfd
{ {
int fd; int fd;
@ -54,6 +54,7 @@ typedef struct Pollreq
} pollreqType; } pollreqType;
void PollAdd(WaitQueueType *wq, pollreqType *req); void PollAdd(WaitQueueType *wq, pollreqType *req);
#ifndef poll
int poll(struct pollfd *fds, NfdsType nfds, int timeout); int poll(struct pollfd *fds, NfdsType nfds, int timeout);
#endif
#endif #endif

View File

@ -205,6 +205,7 @@ KERNELPATHS :=-I$(BSP_ROOT) \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \ -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \ -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch \ -I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch \
-I$(KERNEL_ROOT)/resources/include \
-I$(BSP_ROOT)/include # -I$(BSP_ROOT)/include #
endif endif
@ -291,6 +292,8 @@ endif
ifeq ($(CONFIG_SUPPORT_CONTROL_FRAMEWORK), y) ifeq ($(CONFIG_SUPPORT_CONTROL_FRAMEWORK), y)
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control #
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc/interoperability/opcua # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc/interoperability/opcua #
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc/shared #
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/lib/cJSON
endif endif
ifeq ($(CONFIG_CRYPTO), y) ifeq ($(CONFIG_CRYPTO), y)

View File

@ -120,3 +120,4 @@ int AdcDriverAttachToBus(const char *drv_name, const char *bus_name)
return ret; return ret;
} }

View File

@ -117,3 +117,4 @@ int AdcDeviceAttachToBus(const char *dev_name, const char *bus_name)
return EOK; return EOK;
} }

View File

@ -67,3 +67,4 @@ int AdcDriverRegister(struct Driver *driver)
return ret; return ret;
} }

View File

@ -12,8 +12,7 @@
/** /**
* @file bus.c * @file bus.c
* @brief 1support bus driver framework2provide bus API * @brief Support bus driver framework provide bus API version 1.0
* @version 1.0
* @author AIIT XUOS Lab * @author AIIT XUOS Lab
* @date 2021-04-24 * @date 2021-04-24
*/ */
@ -71,7 +70,7 @@ static int BusMatchDrvDev(struct Driver *driver, struct HardwareDev *device)
* @param dev - dev pointer * @param dev - dev pointer
* @param drv_name - drv name * @param drv_name - drv name
* @param configure_info - BusConfigureInfo pointer * @param configure_info - BusConfigureInfo pointer
* @return successfulEOKfailedERROR * @return successful:EOK,failed:ERROR
*/ */
int DeviceObtainBus(struct Bus *bus, struct HardwareDev *dev, const char *drv_name, struct BusConfigureInfo *configure_info) int DeviceObtainBus(struct Bus *bus, struct HardwareDev *dev, const char *drv_name, struct BusConfigureInfo *configure_info)
{ {
@ -104,7 +103,7 @@ int DeviceObtainBus(struct Bus *bus, struct HardwareDev *dev, const char *drv_na
/** /**
* @Description: support to register bus pointer with linklist * @Description: support to register bus pointer with linklist
* @param bus - bus pointer * @param bus - bus pointer
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
int BusRegister(struct Bus *bus) int BusRegister(struct Bus *bus)
{ {
@ -125,7 +124,7 @@ int BusRegister(struct Bus *bus)
/** /**
* @Description: support to release bus pointer in linklist * @Description: support to release bus pointer in linklist
* @param bus - bus pointer * @param bus - bus pointer
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
int BusRelease(struct Bus *bus) int BusRelease(struct Bus *bus)
{ {
@ -147,7 +146,7 @@ int BusRelease(struct Bus *bus)
/** /**
* @Description: support to unregister bus pointer and delete its linklist node * @Description: support to unregister bus pointer and delete its linklist node
* @param bus - bus pointer * @param bus - bus pointer
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
int BusUnregister(struct Bus *bus) int BusUnregister(struct Bus *bus)
{ {
@ -164,7 +163,7 @@ int BusUnregister(struct Bus *bus)
* @Description: support to register driver pointer to bus pointer * @Description: support to register driver pointer to bus pointer
* @param bus - bus pointer * @param bus - bus pointer
* @param driver - driver pointer * @param driver - driver pointer
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
int DriverRegisterToBus(struct Bus *bus, struct Driver *driver) int DriverRegisterToBus(struct Bus *bus, struct Driver *driver)
{ {
@ -183,7 +182,7 @@ int DriverRegisterToBus(struct Bus *bus, struct Driver *driver)
* @Description: support to register dev pointer to bus pointer * @Description: support to register dev pointer to bus pointer
* @param bus - bus pointer * @param bus - bus pointer
* @param device - device pointer * @param device - device pointer
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
int DeviceRegisterToBus(struct Bus *bus, struct HardwareDev *device) int DeviceRegisterToBus(struct Bus *bus, struct HardwareDev *device)
{ {
@ -202,7 +201,7 @@ int DeviceRegisterToBus(struct Bus *bus, struct HardwareDev *device)
* @Description: support to delete driver pointer from bus pointer * @Description: support to delete driver pointer from bus pointer
* @param bus - bus pointer * @param bus - bus pointer
* @param driver - driver pointer * @param driver - driver pointer
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
int DriverDeleteFromBus(struct Bus *bus, struct Driver *driver) int DriverDeleteFromBus(struct Bus *bus, struct Driver *driver)
{ {
@ -222,7 +221,7 @@ int DriverDeleteFromBus(struct Bus *bus, struct Driver *driver)
* @Description: support to delete dev pointer from bus pointer * @Description: support to delete dev pointer from bus pointer
* @param bus - bus pointer * @param bus - bus pointer
* @param device - device pointer * @param device - device pointer
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
int DeviceDeleteFromBus(struct Bus *bus, struct HardwareDev *device) int DeviceDeleteFromBus(struct Bus *bus, struct HardwareDev *device)
{ {
@ -241,7 +240,7 @@ int DeviceDeleteFromBus(struct Bus *bus, struct HardwareDev *device)
/** /**
* @Description: support to find bus pointer by bus name * @Description: support to find bus pointer by bus name
* @param bus_name - bus name * @param bus_name - bus name
* @return successfulbus pointerfailedNONE * @return successful:bus pointer,failed:NONE
*/ */
BusType BusFind(const char *bus_name) BusType BusFind(const char *bus_name)
{ {
@ -266,7 +265,7 @@ BusType BusFind(const char *bus_name)
* @Description: support to find driver pointer of certain bus by driver name * @Description: support to find driver pointer of certain bus by driver name
* @param bus - bus pointer * @param bus - bus pointer
* @param driver_name - driver name * @param driver_name - driver name
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
DriverType BusFindDriver(struct Bus *bus, const char *driver_name) DriverType BusFindDriver(struct Bus *bus, const char *driver_name)
{ {
@ -292,7 +291,7 @@ DriverType BusFindDriver(struct Bus *bus, const char *driver_name)
* @Description: support to find device pointer of certain bus by device name * @Description: support to find device pointer of certain bus by device name
* @param bus - bus pointer * @param bus - bus pointer
* @param device_name - device name * @param device_name - device name
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
HardwareDevType BusFindDevice(struct Bus *bus, const char *device_name) HardwareDevType BusFindDevice(struct Bus *bus, const char *device_name)
{ {
@ -319,7 +318,7 @@ HardwareDevType BusFindDevice(struct Bus *bus, const char *device_name)
* @Description: support to set dev receive function callback * @Description: support to set dev receive function callback
* @param dev - dev pointer * @param dev - dev pointer
* @param dev_recv_callback - callback function * @param dev_recv_callback - callback function
* @return successfulEOKfailedERROR * @return successful:EOK,failed:ERROR
*/ */
uint32 BusDevRecvCallback(struct HardwareDev *dev, int (*dev_recv_callback) (void *dev, x_size_t length)) uint32 BusDevRecvCallback(struct HardwareDev *dev, int (*dev_recv_callback) (void *dev, x_size_t length))
{ {
@ -333,7 +332,7 @@ uint32 BusDevRecvCallback(struct HardwareDev *dev, int (*dev_recv_callback) (voi
/** /**
* @Description: support to open dev * @Description: support to open dev
* @param dev - dev pointer * @param dev - dev pointer
* @return successfulEOKfailedERROR * @return successful:EOK,failed:ERROR
*/ */
uint32 BusDevOpen(struct HardwareDev *dev) uint32 BusDevOpen(struct HardwareDev *dev)
{ {
@ -355,7 +354,7 @@ uint32 BusDevOpen(struct HardwareDev *dev)
/** /**
* @Description: support to close dev * @Description: support to close dev
* @param dev - dev pointer * @param dev - dev pointer
* @return successfulEOKfailedERROR * @return successful:EOK,failed:ERROR
*/ */
uint32 BusDevClose(struct HardwareDev *dev) uint32 BusDevClose(struct HardwareDev *dev)
{ {
@ -378,7 +377,7 @@ uint32 BusDevClose(struct HardwareDev *dev)
* @Description: support to write data to dev * @Description: support to write data to dev
* @param dev - dev pointer * @param dev - dev pointer
* @param write_param - BusBlockWriteParam * @param write_param - BusBlockWriteParam
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
uint32 BusDevWriteData(struct HardwareDev *dev, struct BusBlockWriteParam *write_param) uint32 BusDevWriteData(struct HardwareDev *dev, struct BusBlockWriteParam *write_param)
{ {
@ -395,7 +394,7 @@ uint32 BusDevWriteData(struct HardwareDev *dev, struct BusBlockWriteParam *write
* @Description: support to read data from dev * @Description: support to read data from dev
* @param dev - dev pointer * @param dev - dev pointer
* @param read_param - BusBlockReadParam * @param read_param - BusBlockReadParam
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
uint32 BusDevReadData(struct HardwareDev *dev, struct BusBlockReadParam *read_param) uint32 BusDevReadData(struct HardwareDev *dev, struct BusBlockReadParam *read_param)
{ {
@ -412,7 +411,7 @@ uint32 BusDevReadData(struct HardwareDev *dev, struct BusBlockReadParam *read_pa
* @Description: support to configure drv, include OPE_CFG and OPE_INT * @Description: support to configure drv, include OPE_CFG and OPE_INT
* @param drv - drv pointer * @param drv - drv pointer
* @param configure_info - BusConfigureInfo * @param configure_info - BusConfigureInfo
* @return successfulEOKfailedNONE * @return successful:EOK,failed:NONE
*/ */
uint32 BusDrvConfigure(struct Driver *drv, struct BusConfigureInfo *configure_info) uint32 BusDrvConfigure(struct Driver *drv, struct BusConfigureInfo *configure_info)
{ {

View File

@ -29,17 +29,6 @@
* Author: Simon Goldschmidt * Author: Simon Goldschmidt
* *
*/ */
/*
* 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 sys_arch.c * @file sys_arch.c
@ -463,9 +452,9 @@ void lwip_input_thread(void *param)
void lwip_config_input(struct netif *net) void lwip_config_input(struct netif *net)
{ {
pthread_t th_id = 0; sys_thread_t th_id = 0;
th_id = sys_thread_new("eth_input", lwip_input_thread, net, 4096, 15); th_id = sys_thread_new("eth_input", lwip_input_thread, net, LWIP_TASK_STACK_SIZE, 15);
if (th_id >= 0) { if (th_id >= 0) {
lw_print("%s %d successfully!\n", __func__, th_id); lw_print("%s %d successfully!\n", __func__, th_id);
@ -489,6 +478,8 @@ void lwip_config_net(char *ip, char *mask, char *gw)
#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */ #endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
}; };
ETH_BSP_Config();
if(chk_lwip_bit(LWIP_INIT_FLAG)) if(chk_lwip_bit(LWIP_INIT_FLAG))
{ {
lw_print("lw: [%s] already ...\n", __func__); lw_print("lw: [%s] already ...\n", __func__);
@ -551,6 +542,8 @@ void lwip_config_tcp(char *ip, char *mask, char *gw)
#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */ #endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
}; };
ETH_BSP_Config();
if(chk_lwip_bit(LWIP_INIT_FLAG)) if(chk_lwip_bit(LWIP_INIT_FLAG))
{ {
lw_print("lw: [%s] already ...\n", __func__); lw_print("lw: [%s] already ...\n", __func__);

View File

@ -29,17 +29,6 @@
* Author: Simon Goldschmidt * Author: Simon Goldschmidt
* *
*/ */
/*
* 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 sys_arch.h * @file sys_arch.h

View File

@ -1763,7 +1763,7 @@
* sys_thread_new() when the thread is created. * sys_thread_new() when the thread is created.
*/ */
#if !defined TCPIP_THREAD_PRIO || defined __DOXYGEN__ #if !defined TCPIP_THREAD_PRIO || defined __DOXYGEN__
#define TCPIP_THREAD_PRIO 25 #define TCPIP_THREAD_PRIO 15
#endif #endif
/** /**

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