forked from xuos/xiuos
Merge branch 'prepare_for_master' of https://gitlink.org.cn/xuos/xiuos into develop
This commit is contained in:
commit
60dbe78045
|
@ -192,6 +192,23 @@ menu "test app"
|
|||
bool "Config test lcd device"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_ETHERNET
|
||||
bool "Config test ethernet only for edu-riscv64"
|
||||
default n
|
||||
if USER_TEST_ETHERNET
|
||||
if ADD_XIZI_FETURES
|
||||
choice
|
||||
prompt "set ethernet role as client or server"
|
||||
default ETHERNET_AS_SERVER
|
||||
|
||||
config ETHERNET_AS_SERVER
|
||||
bool "test as server"
|
||||
|
||||
config ETHERNET_AS_CLIENT
|
||||
bool "test as client"
|
||||
endchoice
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
endmenu
|
||||
|
|
|
@ -83,7 +83,11 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
|||
|
||||
ifeq ($(CONFIG_USER_TEST_CAMERA),y)
|
||||
SRC_FILES += test_camera.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_ETHERNET),y)
|
||||
SRC_FILES += test_ethernet.c
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
endif
|
||||
|
|
|
@ -2,15 +2,6 @@
|
|||
#include <string.h>
|
||||
#include <transform.h>
|
||||
|
||||
#define NULL_PARAMETER 0
|
||||
|
||||
#define DVP_INIT 0x00U
|
||||
#define REG_SCCB_READ 0x12U
|
||||
#define REG_SCCB_WRITE 0x13U
|
||||
#define OUTPUT_CONFIG 0x20U
|
||||
#define LCD_STRING_TYPE 0
|
||||
#define LCD_DOT_TYPE 1
|
||||
#define LCD_SIZE 320
|
||||
|
||||
static uint16_t image_buff[384000];
|
||||
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <transform.h>
|
||||
|
||||
#include <socket.h>
|
||||
|
||||
#define BUFF_SIZE 128
|
||||
#define RECV_SIZE 16
|
||||
#define TCP_PORT 12345
|
||||
|
||||
const static uint32_t sn = 0;
|
||||
|
||||
#ifdef ETHERNET_AS_SERVER
|
||||
static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size,
|
||||
uint16_t port, enum TCP_OPTION opt) {
|
||||
int32_t ret = 0;
|
||||
uint16_t size = 0, sentsize = 0;
|
||||
switch (getSn_SR(sn)) {
|
||||
case SOCK_ESTABLISHED:
|
||||
if (getSn_IR(sn) & Sn_IR_CON) {
|
||||
printf("%d:Connected\r\n", sn);
|
||||
setSn_IR(sn, Sn_IR_CON);
|
||||
}
|
||||
if (opt == SEND_DATA) {
|
||||
uint32_t sent_size = 0;
|
||||
memset(buf,0,buf_size);
|
||||
strcpy(buf,"The message has been recved");
|
||||
ret = wiz_sock_send(sn, buf, buf_size);
|
||||
if (ret < 0) {
|
||||
wiz_sock_close(sn);
|
||||
return ret;
|
||||
}
|
||||
} else if (opt == RECV_DATA) {
|
||||
uint32_t size = 0;
|
||||
if ((size = getSn_RX_RSR(sn)) > 0) {
|
||||
if (size > buf_size) size = buf_size;
|
||||
memset(buf,0,buf_size);
|
||||
ret = wiz_sock_recv(sn, buf, size);
|
||||
printf("Recv message: %s\n",buf);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SOCK_CLOSE_WAIT:
|
||||
printf("%d:CloseWait\r\n", sn);
|
||||
if ((ret = wiz_sock_disconnect(sn)) != SOCK_OK) return ret;
|
||||
printf("%d:Closed\r\n", sn);
|
||||
break;
|
||||
case SOCK_INIT:
|
||||
printf("%d:Listen, port [%d]\r\n", sn, port);
|
||||
if ((ret = wiz_sock_listen(sn)) != SOCK_OK) return ret;
|
||||
break;
|
||||
case SOCK_CLOSED:
|
||||
printf("%d:LBTStart\r\n", sn);
|
||||
if ((ret = wiz_socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
|
||||
printf("%d:Opened\r\n", sn);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TestSocketAsServer(int argc, char *argv[])
|
||||
{
|
||||
x_err_t ret;
|
||||
uint8_t buf[BUFF_SIZE] = {0};
|
||||
|
||||
while (1) {
|
||||
ret = wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, RECV_DATA);
|
||||
if (ret > 0) {
|
||||
wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, SEND_DATA);
|
||||
};
|
||||
}
|
||||
|
||||
return ;
|
||||
|
||||
}
|
||||
|
||||
PRIV_SHELL_CMD_FUNCTION(TestSocketAsServer, a w5500 server test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
#elif defined ETHERNET_AS_CLIENT
|
||||
|
||||
static uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size,
|
||||
uint8_t dst_ip[4], uint16_t dst_port,
|
||||
enum TCP_OPTION opt) {
|
||||
// assert(buf_size <= g_wiznet_buf_size);
|
||||
int32_t ret;
|
||||
switch (getSn_SR(sn)) {
|
||||
case SOCK_CLOSE_WAIT:
|
||||
wiz_sock_disconnect(sn);
|
||||
break;
|
||||
case SOCK_CLOSED:
|
||||
wiz_socket(sn, Sn_MR_TCP, 5000, 0x00);
|
||||
break;
|
||||
case SOCK_INIT:
|
||||
KPrintf("[SOCKET CLIENT] sock init.\n");
|
||||
wiz_sock_connect(sn, dst_ip, dst_port);
|
||||
break;
|
||||
case SOCK_ESTABLISHED:
|
||||
if (getSn_IR(sn) & Sn_IR_CON) {
|
||||
printf("[SOCKET CLIENT] %d:Connected\r\n", sn);
|
||||
setSn_IR(sn, Sn_IR_CON);
|
||||
}
|
||||
if (opt == SEND_DATA) {
|
||||
uint32_t sent_size = 0;
|
||||
ret = wiz_sock_send(sn, buf, buf_size);
|
||||
if (ret < 0) {
|
||||
wiz_sock_close(sn);
|
||||
return ret;
|
||||
}
|
||||
} else if (opt == RECV_DATA) {
|
||||
uint32_t size = 0;
|
||||
if ((size = getSn_RX_RSR(sn)) > 0) {
|
||||
if (size > buf_size) size = buf_size;
|
||||
ret = wiz_sock_recv(sn, buf, size);
|
||||
if (ret <= 0) return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TestSocketAsClient(int argc, char *argv[])
|
||||
{
|
||||
x_err_t ret;
|
||||
uint8_t buf[BUFF_SIZE] = {0};
|
||||
uint32_t tmp_ip[4];
|
||||
uint32_t port;
|
||||
const uint8_t client_sock = 2;
|
||||
|
||||
if(argc<3){
|
||||
printf("Please enter command like TestSocketAsClient ip:port msg\n");
|
||||
}
|
||||
|
||||
sscanf(argv[1],"%d.%d.%d.%d:%d",tmp_ip,tmp_ip+1,tmp_ip+2,tmp_ip+3,&port);
|
||||
printf("Client to %d.%d.%d.%d:%d\n",tmp_ip[0],tmp_ip[1],tmp_ip[2],tmp_ip[3],port);
|
||||
uint8_t destination_ip[4]={0};
|
||||
for(int i=0;i<4;i++){
|
||||
destination_ip[i]=tmp_ip[i];
|
||||
}
|
||||
|
||||
while(1){
|
||||
ret = wiz_client_op(client_sock, argv[2], strlen(argv[2]), destination_ip, port,SEND_DATA);
|
||||
printf("sizeof:%d\n",strlen(argv[2]));
|
||||
PrivTaskDelay(1000);
|
||||
if (ret > 0) {
|
||||
ret=wiz_client_op(client_sock, buf, BUFF_SIZE, destination_ip, port, RECV_DATA);
|
||||
printf("read ret is %d\n",ret);
|
||||
if(ret>0){
|
||||
printf("client recv msg successfully!\n");
|
||||
printf("%s\n",buf);
|
||||
}
|
||||
};
|
||||
PrivTaskDelay(1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return ;
|
||||
|
||||
}
|
||||
|
||||
PRIV_SHELL_CMD_FUNCTION(TestSocketAsClient, a w5500 client-ip-port-msg test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -67,7 +67,6 @@ void TestLora(int argc, char *argv[])
|
|||
|
||||
printf("pin configure success\n");
|
||||
struct SerialDataCfg uart_cfg;
|
||||
memset(&uart_cfg, 0, sizeof(struct SerialDataCfg));
|
||||
|
||||
// loraE220 support only 9600bps with 8N1 during initializing
|
||||
uart_cfg.serial_baud_rate = BAUD_RATE_9600;
|
||||
|
@ -96,7 +95,8 @@ void TestLora(int argc, char *argv[])
|
|||
printf("lora configure into sleep(configure) mode\n");
|
||||
|
||||
// send configure data, and receive the same length of data
|
||||
char sendbuff[] = {0xC0, 0x00, 0x05, 0x19, 0x49, 0xE6, 0x00, 0x17}; // config as address 1949 CH17 36.8kps
|
||||
// configure loraE220 as address 1949 CH17 36.8kps
|
||||
char sendbuff[] = {0xC0, 0x00, 0x05, 0x19, 0x49, 0xE6, 0x00, 0x17};
|
||||
|
||||
PrivTaskDelay(2000);
|
||||
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* 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 4g_app.c
|
||||
* @brief support get data from and send data to 4g server
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.12.12
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <transform.h>
|
||||
#include <adapter.h>
|
||||
|
||||
static uint8_t adapter_4g_status = 0;
|
||||
static pthread_t recv_4g_heart_task;
|
||||
struct Adapter *adapter_4g;
|
||||
|
||||
static const uint8_t server_addr[] = "xxx.xxx.xxx.xxx";
|
||||
static const uint8_t server_port[] = "xxx";
|
||||
|
||||
#define ADAPTER_4G_HEART "HEART"
|
||||
|
||||
int Adapter4GConnectFunction(struct Adapter *adapter, uint8_t reconnect)
|
||||
{
|
||||
int ret = 0;
|
||||
int baud_rate = BAUD_RATE_115200;
|
||||
|
||||
if (1 != reconnect) {
|
||||
ret = AdapterDeviceOpen(adapter);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = AdapterDeviceControl(adapter, OPE_INT, &baud_rate);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = AdapterDeviceConnect(adapter, CLIENT, server_addr, server_port, IPV4);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret < 0) {
|
||||
AdapterDeviceClose(adapter);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Adapter4gSend(uint8_t *send_data, size_t length)
|
||||
{
|
||||
if (adapter_4g_status) {
|
||||
AdapterDeviceSend(adapter_4g, send_data, length);
|
||||
}
|
||||
}
|
||||
|
||||
static void *Receive4gHeartTask(void* parameter)
|
||||
{
|
||||
char recv_msg[16] = {0};
|
||||
ssize_t recv_length = 0;
|
||||
uint8_t net_status_cnt = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
SetTaskStatus(0x01);
|
||||
|
||||
if (net_status_cnt > 5) {
|
||||
adapter_4g_status = 0;
|
||||
|
||||
while (Adapter4GConnectFunction(adapter_4g, 1) < 0) {
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
|
||||
net_status_cnt = 0;
|
||||
}
|
||||
|
||||
adapter_4g_status = 1;
|
||||
|
||||
recv_length = AdapterDeviceRecv(adapter_4g, recv_msg, 6);
|
||||
if (recv_length > 0) {
|
||||
//if (0 == strcmp(recv_msg, ADAPTER_4G_HEART)) {
|
||||
net_status_cnt = 0;
|
||||
//}
|
||||
} else {
|
||||
printf("4G recv heart error re-recv cnt %d\n", net_status_cnt);
|
||||
net_status_cnt++;
|
||||
}
|
||||
memset(recv_msg, 0, sizeof(recv_msg));
|
||||
}
|
||||
}
|
||||
|
||||
int Adapter4GActive(void)
|
||||
{
|
||||
int ret = 0;
|
||||
adapter_4g = AdapterDeviceFindByName(ADAPTER_4G_NAME);
|
||||
|
||||
#ifdef ADAPTER_EC200T
|
||||
adapter_4g->socket.socket_id = 0;
|
||||
|
||||
ret = Adapter4GConnectFunction(adapter_4g, 0);
|
||||
if (ret < 0) {
|
||||
printf("Adapter4GConnect failed %d\n", ret);
|
||||
}
|
||||
|
||||
adapter_4g_status = 1;
|
||||
|
||||
pthread_attr_t attr;
|
||||
attr.schedparam.sched_priority = 22;
|
||||
attr.stacksize = 2048;
|
||||
|
||||
PrivTaskCreate(&recv_4g_heart_task, &attr, &Receive4gHeartTask, NULL);
|
||||
PrivTaskStartup(&recv_4g_heart_task);
|
||||
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
SRC_FILES := 4g_app.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -1,6 +1,3 @@
|
|||
|
||||
ifeq ($(CONFIG_SOCKET_DEMO),y)
|
||||
|
||||
include $(KERNEL_ROOT)/.config
|
||||
|
||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
||||
|
@ -10,6 +7,10 @@ endif
|
|||
|
||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
||||
|
||||
ifeq ($(CONFIG_CONNECTION_ADAPTER_4G),y)
|
||||
SRC_DIR += 4g_app
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RESOURCES_LWIP),y)
|
||||
SRC_DIR += socket_demo
|
||||
endif
|
||||
|
@ -17,4 +18,3 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
|||
include $(KERNEL_ROOT)/compiler.mk
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <transform.h>
|
||||
|
||||
#ifdef ADD_XIZI_FETURES
|
||||
#include "sys_arch.h"
|
||||
#include <sys_arch.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include "lwip/sys.h"
|
||||
#endif
|
||||
|
@ -33,9 +33,17 @@
|
|||
#include "stdio.h"
|
||||
#endif
|
||||
|
||||
#define TCP_DEMO_BUF_SIZE 65535
|
||||
#define TCP_DEMO_BUF_SIZE 65535
|
||||
#define TCP_DEMO_SEND_TIMES 20
|
||||
#define LWIP_TCP_DEMO_TASK_STACK_SIZE 4096
|
||||
#define LWIP_TCP_DEMO_TASK_PRIO 20
|
||||
|
||||
char tcp_socket_ip[] = {192, 168, 250, 252};
|
||||
static pthread_t tcp_client_task;
|
||||
static pthread_t tcp_server_task;
|
||||
|
||||
static char tcp_demo_ipaddr[] = {192, 168, 131, 77};
|
||||
static char tcp_demo_netmask[] = {255, 255, 254, 0};
|
||||
static char tcp_demo_gwaddr[] = {192, 168, 131, 1};
|
||||
|
||||
#ifdef ADD_NUTTX_FETURES
|
||||
#define lw_print printf
|
||||
|
@ -46,8 +54,8 @@ char tcp_socket_ip[] = {192, 168, 250, 252};
|
|||
#define LWIP_TARGET_PORT 4840
|
||||
#endif
|
||||
|
||||
uint16_t tcp_socket_port = LWIP_TARGET_PORT;
|
||||
char tcp_ip_str[128] = {0};
|
||||
static uint16_t tcp_socket_port = 8888;
|
||||
static char tcp_ip_str[128] = {0};
|
||||
|
||||
/******************************************************************************/
|
||||
void TcpSocketConfigParam(char *ip_str)
|
||||
|
@ -55,35 +63,23 @@ void TcpSocketConfigParam(char *ip_str)
|
|||
int ip1, ip2, ip3, ip4, port = 0;
|
||||
|
||||
if(ip_str == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port))
|
||||
{
|
||||
if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) {
|
||||
printf("config ip %s port %d\n", ip_str, port);
|
||||
strcpy(tcp_ip_str, ip_str);
|
||||
tcp_socket_ip[0] = ip1;
|
||||
tcp_socket_ip[1] = ip2;
|
||||
tcp_socket_ip[2] = ip3;
|
||||
tcp_socket_ip[3] = ip4;
|
||||
if(port)
|
||||
tcp_socket_port = port;
|
||||
return;
|
||||
}
|
||||
|
||||
if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4))
|
||||
{
|
||||
if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) {
|
||||
printf("config ip %s\n", ip_str);
|
||||
tcp_socket_ip[0] = ip1;
|
||||
tcp_socket_ip[1] = ip2;
|
||||
tcp_socket_ip[2] = ip3;
|
||||
tcp_socket_ip[3] = ip4;
|
||||
strcpy(tcp_ip_str, ip_str);
|
||||
}
|
||||
}
|
||||
|
||||
static void TcpSocketRecvTask(void *arg)
|
||||
static void *TcpSocketRecvTask(void *arg)
|
||||
{
|
||||
int fd = -1, clientfd;
|
||||
int recv_len;
|
||||
|
@ -91,18 +87,15 @@ static void TcpSocketRecvTask(void *arg)
|
|||
struct sockaddr_in tcp_addr;
|
||||
socklen_t addr_len;
|
||||
|
||||
while(1)
|
||||
{
|
||||
while(1) {
|
||||
recv_buf = (char *)malloc(TCP_DEMO_BUF_SIZE);
|
||||
if (recv_buf == NULL)
|
||||
{
|
||||
if (recv_buf == NULL) {
|
||||
lw_error("No memory\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
if (fd < 0) {
|
||||
lw_error("Socket error\n");
|
||||
free(recv_buf);
|
||||
continue;
|
||||
|
@ -113,8 +106,7 @@ static void TcpSocketRecvTask(void *arg)
|
|||
tcp_addr.sin_port = htons(tcp_socket_port);
|
||||
memset(&(tcp_addr.sin_zero), 0, sizeof(tcp_addr.sin_zero));
|
||||
|
||||
if (bind(fd, (struct sockaddr *)&tcp_addr, sizeof(struct sockaddr)) == -1)
|
||||
{
|
||||
if (bind(fd, (struct sockaddr *)&tcp_addr, sizeof(struct sockaddr)) == -1) {
|
||||
lw_error("Unable to bind\n");
|
||||
close(fd);
|
||||
free(recv_buf);
|
||||
|
@ -125,8 +117,7 @@ static void TcpSocketRecvTask(void *arg)
|
|||
lw_notice("\nLocal Port:%d\n", tcp_socket_port);
|
||||
|
||||
// setup socket fd as listening mode
|
||||
if (listen(fd, 5) != 0 )
|
||||
{
|
||||
if (listen(fd, 5) != 0 ) {
|
||||
lw_error("Unable to listen\n");
|
||||
close(fd);
|
||||
free(recv_buf);
|
||||
|
@ -137,13 +128,11 @@ static void TcpSocketRecvTask(void *arg)
|
|||
clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len);
|
||||
lw_notice("client %s connected\n", inet_ntoa(tcp_addr.sin_addr));
|
||||
|
||||
while(1)
|
||||
{
|
||||
while(1) {
|
||||
memset(recv_buf, 0, TCP_DEMO_BUF_SIZE);
|
||||
recv_len = recvfrom(clientfd, recv_buf, TCP_DEMO_BUF_SIZE, 0,
|
||||
(struct sockaddr *)&tcp_addr, &addr_len);
|
||||
if(recv_len > 0)
|
||||
{
|
||||
if(recv_len > 0) {
|
||||
lw_notice("Receive from : %s\n", inet_ntoa(tcp_addr.sin_addr));
|
||||
lw_notice("Receive data : %d - %s\n\n", recv_len, recv_buf);
|
||||
}
|
||||
|
@ -157,26 +146,33 @@ static void TcpSocketRecvTask(void *arg)
|
|||
|
||||
void TcpSocketRecvTest(int argc, char *argv[])
|
||||
{
|
||||
if(argc >= 2)
|
||||
{
|
||||
if(argc >= 2) {
|
||||
lw_print("lw: [%s] target ip %s\n", __func__, argv[1]);
|
||||
TcpSocketConfigParam(argv[1]);
|
||||
}
|
||||
|
||||
#ifdef ADD_XIZI_FETURES
|
||||
lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, tcp_socket_ip);
|
||||
sys_thread_new("TcpSocketRecvTask", TcpSocketRecvTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
|
||||
lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr);
|
||||
|
||||
pthread_attr_t attr;
|
||||
attr.schedparam.sched_priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||
#endif
|
||||
|
||||
#ifdef ADD_NUTTX_FETURES
|
||||
TcpSocketRecvTask(NULL);
|
||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||
attr.priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||
#endif
|
||||
|
||||
PrivTaskCreate(&tcp_server_task, &attr, &TcpSocketRecvTask, NULL);
|
||||
PrivTaskStartup(&tcp_server_task);
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(TcpSocketRecvTest, a tcp receive sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
static void TcpSocketSendTask(void *arg)
|
||||
static void *TcpSocketSendTask(void *arg)
|
||||
{
|
||||
int cnt = LWIP_DEMO_TIMES;
|
||||
int cnt = TCP_DEMO_SEND_TIMES;
|
||||
int fd = -1;
|
||||
int ret;
|
||||
char send_msg[128];
|
||||
|
@ -186,10 +182,9 @@ static void TcpSocketSendTask(void *arg)
|
|||
|
||||
memset(send_msg, 0, sizeof(send_msg));
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
if (fd < 0) {
|
||||
lw_print("Socket error\n");
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sockaddr_in tcp_sock;
|
||||
|
@ -200,17 +195,15 @@ static void TcpSocketSendTask(void *arg)
|
|||
memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero));
|
||||
|
||||
ret = connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr));
|
||||
if (ret)
|
||||
{
|
||||
lw_print("Unable to connect %s = %d\n", tcp_ip_str, ret);
|
||||
if (ret < 0) {
|
||||
lw_print("Unable to connect %s:%d = %d\n", tcp_ip_str, tcp_socket_port, ret);
|
||||
close(fd);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lw_print("TCP connect %s:%d success, start to send.\n", tcp_ip_str, tcp_socket_port);
|
||||
|
||||
while (cnt --)
|
||||
{
|
||||
while (cnt --) {
|
||||
lw_print("Lwip client is running.\n");
|
||||
snprintf(send_msg, sizeof(send_msg), "TCP test package times %d\r\n", cnt);
|
||||
send(fd, send_msg, strlen(send_msg), 0);
|
||||
|
@ -219,24 +212,31 @@ static void TcpSocketSendTask(void *arg)
|
|||
}
|
||||
|
||||
close(fd);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void TcpSocketSendTest(int argc, char *argv[])
|
||||
{
|
||||
if(argc >= 2)
|
||||
{
|
||||
if(argc >= 2) {
|
||||
lw_print("lw: [%s] target ip %s\n", __func__, argv[1]);
|
||||
TcpSocketConfigParam(argv[1]);
|
||||
}
|
||||
|
||||
#ifdef ADD_XIZI_FETURES
|
||||
lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, tcp_socket_ip);
|
||||
sys_thread_new("Tcp Socket Send", TcpSocketSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
|
||||
lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr);
|
||||
|
||||
pthread_attr_t attr;
|
||||
attr.schedparam.sched_priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||
#endif
|
||||
#ifdef ADD_NUTTX_FETURES
|
||||
TcpSocketSendTask(NULL);
|
||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||
attr.priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||
#endif
|
||||
|
||||
PrivTaskCreate(&tcp_client_task, &attr, &TcpSocketSendTask, NULL);
|
||||
PrivTaskStartup(&tcp_client_task);
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(TcpSocketSendTest, a tcp send sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <transform.h>
|
||||
|
||||
#ifdef ADD_XIZI_FETURES
|
||||
#include "sys_arch.h"
|
||||
#include <sys_arch.h>
|
||||
#include "lwip/sockets.h"
|
||||
#endif
|
||||
|
||||
|
@ -38,11 +38,20 @@
|
|||
#define lw_print printf
|
||||
#endif
|
||||
|
||||
#define UDP_BUF_SIZE 65536
|
||||
#define UDP_DEMO_BUF_SIZE 65535
|
||||
#define UDP_DEMO_SEND_TIMES 20
|
||||
#define LWIP_UDP_DEMO_TASK_STACK_SIZE 4096
|
||||
#define LWIP_UDP_DEMO_TASK_PRIO 20
|
||||
|
||||
char udp_socket_ip[] = {192, 168, 250, 252};
|
||||
char udp_ip_str[128] = {0};
|
||||
uint16_t udp_socket_port = LWIP_LOCAL_PORT;
|
||||
static pthread_t udp_client_task;
|
||||
static pthread_t udp_server_task;
|
||||
|
||||
static char udp_demo_ipaddr[] = {192, 168, 131, 77};
|
||||
static char udp_demo_netmask[] = {255, 255, 254, 0};
|
||||
static char udp_demo_gwaddr[] = {192, 168, 131, 1};
|
||||
|
||||
static char udp_ip_str[128] = {0};
|
||||
static uint16_t udp_socket_port = 8888;
|
||||
|
||||
/*****************************************************************************/
|
||||
void UdpSocketConfigParam(char *ip_str)
|
||||
|
@ -50,53 +59,38 @@ void UdpSocketConfigParam(char *ip_str)
|
|||
int ip1, ip2, ip3, ip4, port = 0;
|
||||
|
||||
if(ip_str == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port))
|
||||
{
|
||||
if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) {
|
||||
printf("config ip %s port %d\n", ip_str, port);
|
||||
strcpy(udp_ip_str, ip_str);
|
||||
udp_socket_ip[0] = ip1;
|
||||
udp_socket_ip[1] = ip2;
|
||||
udp_socket_ip[2] = ip3;
|
||||
udp_socket_ip[3] = ip4;
|
||||
if(port)
|
||||
udp_socket_port = port;
|
||||
return;
|
||||
}
|
||||
|
||||
if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4))
|
||||
{
|
||||
if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) {
|
||||
printf("config ip %s\n", ip_str);
|
||||
udp_socket_ip[0] = ip1;
|
||||
udp_socket_ip[1] = ip2;
|
||||
udp_socket_ip[2] = ip3;
|
||||
udp_socket_ip[3] = ip4;
|
||||
strcpy(udp_ip_str, ip_str);
|
||||
}
|
||||
}
|
||||
|
||||
static void UdpSocketRecvTask(void *arg)
|
||||
static void *UdpSocketRecvTask(void *arg)
|
||||
{
|
||||
int fd = -1;
|
||||
char *recv_buf;
|
||||
struct sockaddr_in udp_addr, server_addr;
|
||||
int recv_len;
|
||||
|
||||
while(1)
|
||||
{
|
||||
recv_buf = (char *)malloc(UDP_BUF_SIZE);
|
||||
if(recv_buf == NULL)
|
||||
{
|
||||
while(1) {
|
||||
recv_buf = (char *)PrivMalloc(UDP_DEMO_BUF_SIZE);
|
||||
if(recv_buf == NULL) {
|
||||
lw_error("No memory\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(fd < 0)
|
||||
{
|
||||
if(fd < 0) {
|
||||
lw_error("Socket error\n");
|
||||
free(recv_buf);
|
||||
continue;
|
||||
|
@ -107,8 +101,7 @@ static void UdpSocketRecvTask(void *arg)
|
|||
udp_addr.sin_port = htons(udp_socket_port);
|
||||
memset(&(udp_addr.sin_zero), 0, sizeof(udp_addr.sin_zero));
|
||||
|
||||
if(bind(fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1)
|
||||
{
|
||||
if(bind(fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1) {
|
||||
lw_error("Unable to bind\n");
|
||||
close(fd);
|
||||
free(recv_buf);
|
||||
|
@ -118,12 +111,10 @@ static void UdpSocketRecvTask(void *arg)
|
|||
lw_notice("UDP bind success, start to receive.\n");
|
||||
lw_notice("\n\nLocal Port:%d\n\n", udp_socket_port);
|
||||
|
||||
while(1)
|
||||
{
|
||||
memset(recv_buf, 0, UDP_BUF_SIZE);
|
||||
recv_len = recv(fd, recv_buf, UDP_BUF_SIZE, 0);
|
||||
if(recv_len > 0)
|
||||
{
|
||||
while(1) {
|
||||
memset(recv_buf, 0, UDP_DEMO_BUF_SIZE);
|
||||
recv_len = recv(fd, recv_buf, UDP_DEMO_BUF_SIZE, 0);
|
||||
if(recv_len > 0) {
|
||||
lw_notice("Receive from : %s\n", inet_ntoa(server_addr.sin_addr));
|
||||
lw_notice("Receive data : %s\n\n", recv_buf);
|
||||
}
|
||||
|
@ -137,36 +128,41 @@ static void UdpSocketRecvTask(void *arg)
|
|||
|
||||
void UdpSocketRecvTest(int argc, char *argv[])
|
||||
{
|
||||
if(argc >= 2)
|
||||
{
|
||||
if(argc >= 2) {
|
||||
lw_notice("lw: [%s] target ip %s\n", __func__, argv[1]);
|
||||
UdpSocketConfigParam(argv[1]);
|
||||
}
|
||||
|
||||
#ifdef ADD_XIZI_FETURES
|
||||
lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, udp_socket_ip);
|
||||
sys_thread_new("UdpSocketRecvTask", UdpSocketRecvTask, NULL,
|
||||
LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
|
||||
lwip_config_tcp(0, udp_demo_ipaddr, udp_demo_netmask, udp_demo_gwaddr);
|
||||
|
||||
pthread_attr_t attr;
|
||||
attr.schedparam.sched_priority = LWIP_UDP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE;
|
||||
#endif
|
||||
#ifdef ADD_NUTTX_FETURES
|
||||
UdpSocketRecvTask(NULL);
|
||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||
attr.priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||
#endif
|
||||
|
||||
PrivTaskCreate(&udp_server_task, &attr, &UdpSocketRecvTask, NULL);
|
||||
PrivTaskStartup(&udp_server_task);
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(UdpSocketRecvTest, a udp receive sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
static void UdpSocketSendTask(void *arg)
|
||||
static void *UdpSocketSendTask(void *arg)
|
||||
{
|
||||
int cnt = LWIP_DEMO_TIMES;
|
||||
int cnt = UDP_DEMO_SEND_TIMES;
|
||||
char send_str[128];
|
||||
int fd = -1;
|
||||
|
||||
memset(send_str, 0, sizeof(send_str));
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(fd < 0)
|
||||
{
|
||||
if(fd < 0) {
|
||||
lw_error("Socket error\n");
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sockaddr_in udp_sock;
|
||||
|
@ -175,19 +171,17 @@ static void UdpSocketSendTask(void *arg)
|
|||
udp_sock.sin_addr.s_addr = inet_addr(udp_ip_str);
|
||||
memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero));
|
||||
|
||||
if(connect(fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr)))
|
||||
{
|
||||
lw_error("Unable to connect\n");
|
||||
if(connect(fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr)) < 0) {
|
||||
lw_error("Unable to connect %s:%d\n", udp_ip_str, udp_socket_port);
|
||||
close(fd);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lw_print("UDP connect %s:%d success, start to send.\n",
|
||||
udp_ip_str,
|
||||
udp_socket_port);
|
||||
|
||||
while(cnt --)
|
||||
{
|
||||
while(cnt --) {
|
||||
snprintf(send_str, sizeof(send_str), "UDP test package times %d\r\n", cnt);
|
||||
send(fd, send_str, strlen(send_str), 0);
|
||||
lw_notice("Send UDP msg: %s ", send_str);
|
||||
|
@ -195,25 +189,31 @@ static void UdpSocketSendTask(void *arg)
|
|||
}
|
||||
|
||||
close(fd);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void UdpSocketSendTest(int argc, char *argv[])
|
||||
{
|
||||
if(argc >= 2)
|
||||
{
|
||||
if(argc >= 2) {
|
||||
lw_notice("lw: [%s] target ip %s\n", __func__, argv[1]);
|
||||
UdpSocketConfigParam(argv[1]);
|
||||
}
|
||||
|
||||
#ifdef ADD_XIZI_FETURES
|
||||
lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, udp_socket_ip);
|
||||
sys_thread_new("UdpSocketSendTask", UdpSocketSendTask, NULL, LWIP_TASK_STACK_SIZE,
|
||||
LWIP_DEMO_TASK_PRIO);
|
||||
lwip_config_tcp(0, udp_demo_ipaddr, udp_demo_netmask, udp_demo_gwaddr);
|
||||
|
||||
pthread_attr_t attr;
|
||||
attr.schedparam.sched_priority = LWIP_UDP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE;
|
||||
#endif
|
||||
#ifdef ADD_NUTTX_FETURES
|
||||
UdpSocketSendTask(NULL);
|
||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||
attr.priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||
#endif
|
||||
|
||||
PrivTaskCreate(&udp_client_task, &attr, &UdpSocketSendTask, NULL);
|
||||
PrivTaskStartup(&udp_client_task);
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(UdpSocketSendTest, a udp send sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
|
|
@ -18,6 +18,47 @@
|
|||
* @date 2022.9.27
|
||||
*/
|
||||
|
||||
|
||||
#include <control.h>
|
||||
|
||||
extern int Adapter4GActive(void);
|
||||
|
||||
void ControlFx3uTest(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
int read_data_length = 0;
|
||||
uint8_t read_data[128] = {0};
|
||||
|
||||
#ifdef CONNECTION_ADAPTER_4G
|
||||
Adapter4GActive();
|
||||
#endif
|
||||
|
||||
ControlProtocolType modbus_tcp_protocol = ControlProtocolFind();
|
||||
if (NULL == modbus_tcp_protocol) {
|
||||
printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) {
|
||||
ControlProtocolOpen(modbus_tcp_protocol);
|
||||
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length);
|
||||
if (read_data_length) {
|
||||
for (j = 0; j < read_data_length; j ++) {
|
||||
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
|
||||
//ControlProtocolClose(modbus_tcp_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlFx3uTest, Mitsubishi fx3u Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ int CircularAreaAppIsEmpty(CircularAreaAppType circular_area)
|
|||
CA_PARAM_CHECK(circular_area);
|
||||
|
||||
if((circular_area->readidx == circular_area->writeidx) && (!circular_area->b_status)) {
|
||||
printf("the circular area is empty\n");
|
||||
//printf("the circular area is empty\n");
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -164,7 +164,7 @@ int CircularAreaAppRead(CircularAreaAppType circular_area, uint8_t *output_buffe
|
|||
return -1;
|
||||
}
|
||||
|
||||
uint32_t read_length = (data_length > CircularAreaAppGetDataLength(circular_area)) ? CircularAreaAppGetDataLength(circular_area) : data_length;
|
||||
int read_length = (data_length > CircularAreaAppGetDataLength(circular_area)) ? CircularAreaAppGetDataLength(circular_area) : data_length;
|
||||
// if (data_length > CircularAreaAppGetDataLength(circular_area)) {
|
||||
// return -1;
|
||||
// }
|
||||
|
|
|
@ -29,7 +29,14 @@ void WindDirectionQsFx(void)
|
|||
struct SensorQuantity *wind_direction = SensorQuantityFind(SENSOR_QUANTITY_QS_FX_WINDDIRECTION, SENSOR_QUANTITY_WINDDIRECTION);
|
||||
SensorQuantityOpen(wind_direction);
|
||||
PrivTaskDelay(2000);
|
||||
uint16_t result = SensorQuantityReadValue(wind_direction);
|
||||
printf("wind direction : %d degree\n", result);
|
||||
int result = 0;
|
||||
for(int i=0;i<2000;i++)
|
||||
{
|
||||
result = 0;
|
||||
PrivTaskDelay(1000);
|
||||
result = SensorQuantityReadValue(wind_direction);
|
||||
if(result > 0)
|
||||
printf("wind direction : %d degree\n", result);
|
||||
}
|
||||
SensorQuantityClose(wind_direction);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,14 @@ void WindSpeedQsFs(void)
|
|||
struct SensorQuantity *wind_speed = SensorQuantityFind(SENSOR_QUANTITY_QS_FS_WINDSPEED, SENSOR_QUANTITY_WINDSPEED);
|
||||
SensorQuantityOpen(wind_speed);
|
||||
PrivTaskDelay(2000);
|
||||
uint16_t result = SensorQuantityReadValue(wind_speed);
|
||||
printf("wind speed : %d.%d m/s\n", result/10, result%10);
|
||||
int result = 0;
|
||||
for(int i=0;i<2000;i++)
|
||||
{
|
||||
result = 0;
|
||||
PrivTaskDelay(1000);
|
||||
result = SensorQuantityReadValue(wind_speed);
|
||||
if(result > 0)
|
||||
printf("wind speed : %d.%d m/s\n", result/10, result%10);
|
||||
}
|
||||
SensorQuantityClose(wind_speed);
|
||||
}
|
||||
|
|
|
@ -263,7 +263,7 @@ static int E220SetRegisterParam(struct Adapter *adapter, uint16 address, uint8 c
|
|||
uint8 baud_rate_bit = E220BaudRateSwitch(baud_rate);
|
||||
|
||||
E220LoraModeConfig(CONFIGURE_MODE_MODE);
|
||||
PrivTaskDelay(30);
|
||||
PrivTaskDelay(2000);
|
||||
|
||||
buffer[0] = 0xC0; //write register order
|
||||
buffer[1] = 0x00; //register start-address
|
||||
|
@ -286,6 +286,7 @@ static int E220SetRegisterParam(struct Adapter *adapter, uint16 address, uint8 c
|
|||
printf("E220SetRegisterParam send failed %d!\n", ret);
|
||||
}
|
||||
|
||||
PrivTaskDelay(2000);
|
||||
|
||||
PrivRead(adapter->fd, buffer, 11);
|
||||
E220LoraModeConfig(DATA_TRANSFER_MODE);
|
||||
|
|
|
@ -2,12 +2,33 @@ menuconfig SUPPORT_CONTROL_FRAMEWORK
|
|||
bool "support control framework"
|
||||
default n
|
||||
select TRANSFORM_LAYER_ATTRIUBUTE
|
||||
select BSP_USING_LWIP
|
||||
select BSP_USING_SDIO
|
||||
select MOUNT_SDCARD_FS
|
||||
select LIB_USING_CJSON
|
||||
|
||||
if SUPPORT_CONTROL_FRAMEWORK
|
||||
config CONTROL_USING_SERIAL_485
|
||||
bool
|
||||
default n
|
||||
|
||||
config CONTROL_USING_SOCKET
|
||||
bool
|
||||
default n
|
||||
if CONTROL_USING_SOCKET
|
||||
choice
|
||||
prompt "select socket lib"
|
||||
default CONTROL_SOCKET_LWIP
|
||||
|
||||
config CONTROL_SOCKET_LWIP
|
||||
bool "support socket, using LwIP"
|
||||
select BSP_USING_LWIP
|
||||
|
||||
config CONTROL_SOCKET_W5500
|
||||
bool "support socket, using W5500"
|
||||
select BSP_USING_W5500
|
||||
endchoice
|
||||
endif
|
||||
|
||||
config CONTROL_RECIPE_FILE
|
||||
string "control framework recipe file name"
|
||||
default "test_recipe.json"
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
config CONTROL_PROTOCOL_MODBUS_TCP
|
||||
bool "Using modbus_tcp control protocol"
|
||||
default n
|
||||
select CONTROL_USING_SOCKET
|
||||
if CONTROL_PROTOCOL_MODBUS_TCP
|
||||
source "$APP_DIR/Framework/control/ipc_protocol/modbus_tcp/Kconfig"
|
||||
endif
|
||||
|
||||
config CONTROL_PROTOCOL_MODBUS_UART
|
||||
bool "Using modbus_uart control protocol"
|
||||
default n
|
||||
|
||||
select CONTROL_USING_SERIAL_485
|
||||
if CONTROL_PROTOCOL_MODBUS_UART
|
||||
source "$APP_DIR/Framework/control/ipc_protocol/modbus_uart/Kconfig"
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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 modbus_tcp.h
|
||||
* @brief support modbus_tcp function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.09.27
|
||||
*/
|
||||
|
||||
#ifndef MODBUS_TCP_H
|
||||
#define MODBUS_TCP_H
|
||||
|
||||
#include <control_def.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MODBUS_TCP_UNIT_ID 0x01
|
||||
#define MODBUS_TCP_READ_CMD_LENGTH 0x0C
|
||||
#define MODBUS_TCP_WRITE_SINGLE_CMD_LENGTH 0x0C
|
||||
|
||||
#define MODBUS_TCP_WRITE_MULTI_HEAD 0x07
|
||||
|
||||
typedef enum
|
||||
{
|
||||
READ_COIL_STATUS = 0x01, //read coil cmd
|
||||
READ_INPUT_STATUS = 0x02, //read input colr cmd
|
||||
READ_HOLDING_REGISTER = 0x03, //read register info cmd
|
||||
READ_INPUT_REGISTER = 0x04, //read input register cmd
|
||||
WRITE_SINGLE_COIL = 0x05, //write coil cmd
|
||||
WRITE_SINGLE_REGISTER = 0x06, //write single register cmd
|
||||
WRITE_MULTIPLE_COIL = 0x0F, //write multi coil cmd
|
||||
WRITE_MULTIPLE_REGISTER = 0x10 //write multi register cmd
|
||||
}ModbusTcpFunctionCode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BasicPlcDataInfo base_data_info;
|
||||
ModbusTcpFunctionCode function_code;
|
||||
}ModbusTcpDataInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ModbusTcpDataInfo data_info;
|
||||
|
||||
UniformValueType value_type;
|
||||
char value_name[20];
|
||||
|
||||
uint16_t start_address;
|
||||
uint16_t quantity;
|
||||
}ModbusTcpReadItem;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 modbus_uart.h
|
||||
* @brief support modbus_uart function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.12.29
|
||||
*/
|
||||
|
||||
#ifndef MODBUS_UART_H
|
||||
#define MODBUS_UART_H
|
||||
|
||||
#include <control_def.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MODBUS_UART_READ_CMD_LENGTH 0x08
|
||||
#define MODBUS_UART_WRITE_CMD_LENGTH 0x08
|
||||
|
||||
typedef enum
|
||||
{
|
||||
READ_COIL_STATUS = 0x01, //read coil cmd
|
||||
READ_INPUT_STATUS = 0x02, //read input colr cmd
|
||||
READ_HOLDING_REGISTER = 0x03, //read register info cmd
|
||||
READ_INPUT_REGISTER = 0x04, //read input register cmd
|
||||
WRITE_SINGLE_COIL = 0x05, //write coil cmd
|
||||
WRITE_SINGLE_REGISTER = 0x06, //write single register cmd
|
||||
WRITE_MULTIPLE_COIL = 0x0F, //write multi coil cmd
|
||||
WRITE_MULTIPLE_REGISTER = 0x10 //write multi register cmd
|
||||
}ModbusUartFunctionCode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BasicPlcDataInfo base_data_info;
|
||||
ModbusUartFunctionCode function_code;
|
||||
}ModbusUartDataInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ModbusUartDataInfo data_info;
|
||||
|
||||
UniformValueType value_type;
|
||||
char value_name[20];
|
||||
|
||||
uint8_t station;
|
||||
uint16_t start_address;
|
||||
uint16_t quantity;
|
||||
}ModbusUartReadItem;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -15,6 +15,465 @@
|
|||
* @brief support modbus_tcp function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.09.27
|
||||
* @date 2022.12.09
|
||||
*/
|
||||
|
||||
#include <modbus_tcp.h>
|
||||
|
||||
/*using cirtular area to receive write-data*/
|
||||
#define CA_DATA_LENGTH 512
|
||||
struct CircularAreaApp *g_write_data;
|
||||
|
||||
static BasicSocketPlc plc_socket = {0};
|
||||
static uint8_t recv_buff[1024] = {0};
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Data Transform from Receive Buffer To Control-Data
|
||||
* @param p_read_item - read item pointer
|
||||
* @param recv_buff - receive buff
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static void ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint8_t *recv_buff)
|
||||
{
|
||||
uint8_t head_length = 9;
|
||||
uint8_t *data_buffer;
|
||||
ModbusTcpDataInfo *p_modbus_tcp_data_info = &(p_read_item->data_info);
|
||||
uint16_t quantity = p_read_item->quantity;
|
||||
|
||||
ModbusTcpFunctionCode function_code = p_modbus_tcp_data_info->function_code;
|
||||
uint8_t *p_data = p_modbus_tcp_data_info->base_data_info.p_data;
|
||||
|
||||
uint8_t bytes_count = recv_buff[8];
|
||||
|
||||
if ((WRITE_SINGLE_COIL == function_code) || (WRITE_SINGLE_REGISTER == function_code) ||
|
||||
(WRITE_MULTIPLE_COIL == function_code) || (WRITE_MULTIPLE_REGISTER == function_code)) {
|
||||
head_length = 10;
|
||||
if (p_modbus_tcp_data_info->base_data_info.command_ready) {
|
||||
p_modbus_tcp_data_info->base_data_info.command_ready = 0;
|
||||
}
|
||||
}
|
||||
|
||||
data_buffer = recv_buff + head_length;//remove head data
|
||||
|
||||
if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) {
|
||||
printf("Receive data is ");
|
||||
for (int i = 0;i < bytes_count;i ++) {
|
||||
for (int j = 0;j < 8;j ++) {
|
||||
if ((i * 8 + j) < p_read_item->quantity) {
|
||||
*(uint8_t *)(p_data + i * 8 + j) = ((data_buffer[i] >> j) & 0x01) ? 1 : 0;
|
||||
printf("0x%x", *(uint8_t *)(p_data + i * 8 + j));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (READ_HOLDING_REGISTER == function_code || READ_INPUT_REGISTER == function_code) {
|
||||
printf("Receive data is ");
|
||||
for (uint16_t i = 0; i < quantity; i ++) {
|
||||
((int16_t *)p_data)[i] = ((int16_t *)data_buffer)[quantity - i - 1];
|
||||
printf("0x%x 0x%x ", p_data[2 * i], p_data[2 * i + 1]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
/**
|
||||
* @description: Modbus Tcp Get Data From Socket
|
||||
* @param socket - socket
|
||||
* @param p_read_item - read item pointer
|
||||
* @return success : 0 error : -1 -2
|
||||
*/
|
||||
static int ModbusTcpGetData(int32_t socket, ModbusTcpReadItem *p_read_item)
|
||||
{
|
||||
uint8_t try_count = 0;
|
||||
int32_t write_error = 0;
|
||||
|
||||
ModbusTcpDataInfo *p_modbus_tcp_data_info = &(p_read_item->data_info);
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_modbus_tcp_data_info->base_data_info);
|
||||
|
||||
if (!p_base_data_info->command_ready) {
|
||||
//command not ready, just return
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(recv_buff, 0, sizeof(recv_buff));
|
||||
|
||||
while (try_count < 10) {
|
||||
ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
try_count++;
|
||||
|
||||
write_error = socket_write(socket, p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
if (write_error < 0) {
|
||||
printf("Write socket error, errno is %d!\n", errno);
|
||||
} else {
|
||||
PrivTaskDelay(20);
|
||||
|
||||
int32_t recv_length = socket_read(socket, recv_buff, sizeof(recv_buff));
|
||||
if (recv_length < 0) {
|
||||
printf("Read socket error, errno is %d! read again\n", errno);
|
||||
memset(recv_buff, 0, sizeof(recv_buff));
|
||||
recv_length = socket_read(socket, recv_buff, sizeof(recv_buff));
|
||||
if (recv_length > 0) {
|
||||
ControlPrintfList("RECV", recv_buff, recv_length);
|
||||
ModbusTcpTransformRecvBuffToData(p_read_item, recv_buff);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ControlPrintfList("RECV", recv_buff, recv_length);
|
||||
ModbusTcpTransformRecvBuffToData(p_read_item, recv_buff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||
printf("Send command failed, errno is %d!\n", errno);
|
||||
continue;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Data Info Init
|
||||
* @param p_read_item - read item pointer
|
||||
* @param index - read item index
|
||||
* @param p_data - control-data pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int ModbusTcpInitialDataInfo(ModbusTcpReadItem *p_read_item, uint16_t index, uint8_t *p_data)
|
||||
{
|
||||
uint16_t command_index = 0;
|
||||
uint8_t function_code = p_read_item->data_info.function_code;
|
||||
uint16_t start_address = p_read_item->start_address;
|
||||
uint16_t quantity = p_read_item->quantity;
|
||||
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info);
|
||||
|
||||
switch (function_code)
|
||||
{
|
||||
case READ_COIL_STATUS:
|
||||
case READ_INPUT_STATUS:
|
||||
case READ_HOLDING_REGISTER:
|
||||
case READ_INPUT_REGISTER:
|
||||
p_base_data_info->command_length = MODBUS_TCP_READ_CMD_LENGTH;
|
||||
p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length);
|
||||
p_base_data_info->p_data = p_data;
|
||||
p_base_data_info->command_ready = 1;
|
||||
break;
|
||||
case WRITE_SINGLE_COIL:
|
||||
case WRITE_SINGLE_REGISTER:
|
||||
if (p_data == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
p_base_data_info->command_length = MODBUS_TCP_WRITE_SINGLE_CMD_LENGTH;
|
||||
p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length);
|
||||
p_base_data_info->p_data = p_data;
|
||||
p_base_data_info->data_size = 2;
|
||||
p_base_data_info->command_ready = 0;
|
||||
}
|
||||
break;
|
||||
case WRITE_MULTIPLE_COIL:
|
||||
if (p_data == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
//"quantity" define how many coil need to be written,"n_byte" define the bytes of write-data(counted by bit)
|
||||
uint16_t n_byte = (quantity - 1) / 8 + 1;
|
||||
p_base_data_info->command_length = n_byte + MODBUS_TCP_WRITE_MULTI_HEAD + 6;
|
||||
p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length);
|
||||
|
||||
//13th command define the bytes of write-data
|
||||
p_base_data_info->p_command[12] = ((quantity - 1) / 8 + 1);
|
||||
p_base_data_info->p_data = p_data;
|
||||
p_base_data_info->data_size = n_byte;
|
||||
p_base_data_info->command_ready = 0;
|
||||
}
|
||||
break;
|
||||
case WRITE_MULTIPLE_REGISTER:
|
||||
if (p_data == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
//"quantity" define how many register need to be written
|
||||
p_base_data_info->command_length = quantity * 2 + MODBUS_TCP_WRITE_MULTI_HEAD + 6;
|
||||
p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length);
|
||||
|
||||
//13th command define the bytes of write-data
|
||||
p_base_data_info->p_command[12] = 2 * quantity;
|
||||
p_base_data_info->p_data = p_data;
|
||||
p_base_data_info->data_size = quantity * 2;
|
||||
p_base_data_info->command_ready = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -2;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(p_base_data_info->p_command, 0, p_base_data_info->command_length);
|
||||
|
||||
p_base_data_info->p_command[0] = index >> 8;
|
||||
p_base_data_info->p_command[1] = index;
|
||||
p_base_data_info->p_command[2] = 0x00;
|
||||
p_base_data_info->p_command[3] = 0x00;
|
||||
p_base_data_info->p_command[4] = 0x00;
|
||||
|
||||
if (function_code < WRITE_MULTIPLE_COIL) {
|
||||
p_base_data_info->p_command[5] = 0x06;
|
||||
} else {
|
||||
p_base_data_info->p_command[5] = 0x09;
|
||||
}
|
||||
|
||||
p_base_data_info->p_command[6] = MODBUS_TCP_UNIT_ID;
|
||||
p_base_data_info->p_command[7] = function_code;
|
||||
p_base_data_info->p_command[8] = start_address >> 8;
|
||||
p_base_data_info->p_command[9] = start_address;
|
||||
|
||||
if ((function_code != WRITE_SINGLE_COIL) && (function_code != WRITE_SINGLE_REGISTER)) {
|
||||
p_base_data_info->p_command[10] = quantity >> 8;
|
||||
p_base_data_info->p_command[11] = quantity;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Format write data from "g_write_data"
|
||||
* @param p_read_item - read item pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int ModbusTcpForamatWriteData(ModbusTcpReadItem *p_read_item)
|
||||
{
|
||||
int i = 0;
|
||||
uint16_t command_index = 0;
|
||||
int write_data_length = 0;
|
||||
uint8_t write_data_buffer[32] = {0};
|
||||
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info);
|
||||
uint8_t *p_command = p_base_data_info->p_command;
|
||||
uint8_t function_code = p_read_item->data_info.function_code;
|
||||
|
||||
if (function_code < WRITE_SINGLE_COIL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
write_data_length = CircularAreaAppRead(g_write_data, write_data_buffer, p_base_data_info->data_size);
|
||||
if (p_base_data_info->data_size != write_data_length) {
|
||||
//printf("%s get write data %d [should be %d]failed!\n", __func__, write_data_length, p_base_data_info->data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (function_code)
|
||||
{
|
||||
case WRITE_SINGLE_COIL:
|
||||
case WRITE_SINGLE_REGISTER:
|
||||
command_index = 10;
|
||||
break;
|
||||
case WRITE_MULTIPLE_COIL:
|
||||
case WRITE_MULTIPLE_REGISTER:
|
||||
command_index = 13;
|
||||
break;
|
||||
default:
|
||||
return -2;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < write_data_length; i ++) {
|
||||
p_base_data_info->p_command[command_index + i] = write_data_buffer[i];
|
||||
}
|
||||
|
||||
p_base_data_info->command_ready = 1;
|
||||
|
||||
return write_data_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Receive Plc Data Task
|
||||
* @param parameter - parameter pointer
|
||||
* @return
|
||||
*/
|
||||
void *ReceivePlcDataTask(void *parameter)
|
||||
{
|
||||
int i = 0;
|
||||
uint8_t try_count = 0;
|
||||
uint16_t data_length = 0;
|
||||
uint8_t *modbus_tcp_data;
|
||||
uint16_t read_item_size = sizeof(ModbusTcpReadItem);
|
||||
|
||||
struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter;
|
||||
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||
ModbusTcpReadItem *modbus_tcp_read_item = (ModbusTcpReadItem *)control_protocol->recipe->read_item;
|
||||
modbus_tcp_data = control_protocol->recipe->protocol_data.data;
|
||||
data_length = control_protocol->recipe->protocol_data.data_length;
|
||||
|
||||
memset(&plc_socket, 0, sizeof(BasicSocketPlc));
|
||||
memcpy(plc_socket.ip, control_protocol->recipe->socket_config.plc_ip, 4);
|
||||
plc_socket.port = control_protocol->recipe->socket_config.port;
|
||||
plc_socket.socket = -1;
|
||||
plc_socket.secondary_connect_flag = 0;
|
||||
|
||||
while (1) {
|
||||
for (i = 0; i < control_protocol->recipe->read_item_count; i ++) {
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
/*only connect socket when close socket or init*/
|
||||
while (ControlConnectSocket(&plc_socket) < 0) {
|
||||
PrivTaskDelay(1000);
|
||||
}
|
||||
|
||||
ModbusTcpForamatWriteData((ModbusTcpReadItem *)modbus_tcp_read_item + i);
|
||||
|
||||
ModbusTcpGetData(plc_socket.socket, (ModbusTcpReadItem *)modbus_tcp_read_item + i);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*read all variable item data, put them into circular_area*/
|
||||
if (i == control_protocol->recipe->read_item_count) {
|
||||
printf("%s get %d item %d length modbus_tcp_data %p\n", __func__, i, data_length, modbus_tcp_data);
|
||||
CircularAreaAppWrite(circular_area, modbus_tcp_data, data_length, 0);
|
||||
}
|
||||
|
||||
/*read data every single 'read_period' ms*/
|
||||
PrivTaskDelay(control_protocol->recipe->read_period);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Protocol Open
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success : 0 error
|
||||
*/
|
||||
int ModbusTcpOpen(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
ControlProtocolOpenDef(control_protocol);
|
||||
|
||||
g_write_data = CircularAreaAppInit(CA_DATA_LENGTH);
|
||||
if (NULL == g_write_data) {
|
||||
printf("%s CircularAreaInit error\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Protocol Close
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success : 0 error
|
||||
*/
|
||||
int ModbusTcpClose(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
CircularAreaAppRelease(g_write_data);
|
||||
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
ControlDisconnectSocket(&plc_socket);
|
||||
#endif
|
||||
|
||||
ControlProtocolCloseDef();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Protocol Read Data
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param buf - read data buffer
|
||||
* @param len - read data length
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int ModbusTcpRead(struct ControlProtocol *control_protocol, void *buf, size_t len)
|
||||
{
|
||||
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||
return CircularAreaAppRead(circular_area, buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Protocol Write Data
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param buf - write data buffer
|
||||
* @param len - write data length
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int ModbusTcpWrite(struct ControlProtocol *control_protocol, const void *buf, size_t len)
|
||||
{
|
||||
CircularAreaAppWrite(g_write_data, (uint8_t *)buf, len, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Protocol Ioctl
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param cmd - ioctl cmd
|
||||
* @param args - ioctl args
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int ModbusTcpIoctl(struct ControlProtocol *control_protocol, int cmd, void *args)
|
||||
{
|
||||
//to do
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ControlDone modbustcp_protocol_done =
|
||||
{
|
||||
._open = ModbusTcpOpen,
|
||||
._close = ModbusTcpClose,
|
||||
._read = ModbusTcpRead,
|
||||
._write = ModbusTcpWrite,
|
||||
._ioctl = ModbusTcpIoctl,
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: Modbus TCP Protocol Cmd Generate
|
||||
* @param p_recipe - recipe pointer
|
||||
* @param protocol_format_info - protocol format info pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
int ModbusTcpProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info)
|
||||
{
|
||||
int ret = 0;
|
||||
static uint8_t last_item_size = 0;
|
||||
uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size;
|
||||
|
||||
ModbusTcpReadItem *modbustcp_read_item = (ModbusTcpReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index;
|
||||
|
||||
modbustcp_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint;
|
||||
strncpy(modbustcp_read_item->value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20);
|
||||
modbustcp_read_item->data_info.function_code = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "function_code")->valueint;
|
||||
modbustcp_read_item->start_address = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "start_address")->valueint;
|
||||
modbustcp_read_item->quantity = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "quantity")->valueint;
|
||||
|
||||
ret = ModbusTcpInitialDataInfo(modbustcp_read_item,
|
||||
protocol_format_info->read_item_index,
|
||||
p_read_item_data);
|
||||
|
||||
ControlPrintfList("CMD", modbustcp_read_item->data_info.base_data_info.p_command, modbustcp_read_item->data_info.base_data_info.command_length);
|
||||
protocol_format_info->last_item_size = GetValueTypeMemorySize(modbustcp_read_item->value_type);
|
||||
|
||||
last_item_size += protocol_format_info->last_item_size;
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus TCP Protocol Init
|
||||
* @param p_recipe - recipe pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
int ModbusTcpProtocolInit(struct ControlRecipe *p_recipe)
|
||||
{
|
||||
p_recipe->read_item = PrivMalloc(sizeof(ModbusTcpReadItem) * p_recipe->read_item_count);
|
||||
if (NULL == p_recipe->read_item) {
|
||||
PrivFree(p_recipe->read_item);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(p_recipe->read_item, 0, sizeof(ModbusTcpReadItem));
|
||||
|
||||
p_recipe->ControlProtocolFormatCmd = ModbusTcpProtocolFormatCmd;
|
||||
|
||||
p_recipe->done = &modbustcp_protocol_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* 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 modbus_tcp.h
|
||||
* @brief support modbus_tcp function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.09.27
|
||||
*/
|
||||
|
||||
#ifndef MODBUS_TCP_H
|
||||
#define MODBUS_TCP_H
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,142 @@
|
|||
{
|
||||
"device_id": 4,
|
||||
"device_name": "GJ2",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.9",
|
||||
"local_ip": "192.168.250.233",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.254.0",
|
||||
"port": 502
|
||||
},
|
||||
"protocol_type": 2,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "M0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8192,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M1",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address":8193,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M102",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8294,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M200",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8392,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M201",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address":8393,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M202",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8394,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M203",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8395,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M204",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8396,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M205",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8397,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M206",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8398,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D20",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 20,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D21",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 21,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D22",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 22,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D23",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 23,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D202",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 202,
|
||||
"quantity": 2
|
||||
},
|
||||
{
|
||||
"value_name": "D204",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 204,
|
||||
"quantity": 2
|
||||
},
|
||||
{
|
||||
"value_name": "D206",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 206,
|
||||
"quantity": 2
|
||||
},
|
||||
{
|
||||
"value_name": "D208",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 208,
|
||||
"quantity": 2
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,2 +1,37 @@
|
|||
if ADD_XIZI_FETURES
|
||||
config CONTROL_FRAMEWORK_UART_485_DIR
|
||||
int "control framework 485 direction pin number"
|
||||
default "2"
|
||||
|
||||
config CONTROL_FRAMEWORK_PIN_DEV
|
||||
string "control framework device pin dev path"
|
||||
default "/dev/pin_dev"
|
||||
|
||||
config CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
bool "Using extra uart to control framework"
|
||||
default n
|
||||
|
||||
config CONTROL_FRAMEWORK_UART_DEV
|
||||
string "control framework device uart dev path"
|
||||
default "/dev/uart3_dev3"
|
||||
depends on !CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
|
||||
if CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
config CONTROL_FRAMEWORK_UART_DEV
|
||||
string "control framework device extra uart dev path"
|
||||
default "/dev/extuart_dev0"
|
||||
|
||||
config CONTROL_FRAMEWORK_DEV_EXT_PORT
|
||||
int "if control framework device using extuart, choose port"
|
||||
default "0"
|
||||
endif
|
||||
endif
|
||||
|
||||
if ADD_NUTTX_FETURES
|
||||
|
||||
endif
|
||||
|
||||
if ADD_RTTHREAD_FETURES
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SRC_FILES :=
|
||||
SRC_FILES := modbus_uart.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
|
|
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* 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 modbus_uart.c
|
||||
* @brief support modbus_uart function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.12.29
|
||||
*/
|
||||
|
||||
#include <modbus_uart.h>
|
||||
|
||||
/*using cirtular area to receive write-data*/
|
||||
#define CA_DATA_LENGTH 512
|
||||
struct CircularAreaApp *g_write_data;
|
||||
|
||||
static BasicSocketPlc plc_socket = {0};
|
||||
static uint8_t recv_buff[1024] = {0};
|
||||
|
||||
/**
|
||||
* @description: CRC16 check
|
||||
* @param data data buffer
|
||||
* @param length data length
|
||||
* @return check code
|
||||
*/
|
||||
static uint16_t ModbusUartCrc16(uint8_t *data, uint32_t length)
|
||||
{
|
||||
int j;
|
||||
uint16_t reg_crc = 0xFFFF;
|
||||
|
||||
while (length--) {
|
||||
reg_crc ^= *data++;
|
||||
for (j = 0;j < 8;j ++) {
|
||||
if(reg_crc & 0x01)
|
||||
reg_crc = reg_crc >> 1 ^ 0xA001;
|
||||
else
|
||||
reg_crc = reg_crc >> 1;
|
||||
}
|
||||
}
|
||||
printf(" crc = [0x%x]\n", reg_crc);
|
||||
return reg_crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Data Transform from Receive Buffer To Control-Data
|
||||
* @param p_read_item - read item pointer
|
||||
* @param recv_buff - receive buff
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int ModbusUartTransformRecvBuffToData(ModbusUartReadItem *p_read_item, uint8_t *recv_buff)
|
||||
{
|
||||
uint8_t head_length = 3;
|
||||
uint8_t *data_buffer;
|
||||
ModbusUartDataInfo *p_modbus_uart_data_info = &(p_read_item->data_info);
|
||||
uint16_t quantity = p_read_item->quantity;
|
||||
|
||||
ModbusUartFunctionCode function_code = p_modbus_uart_data_info->function_code;
|
||||
uint8_t *p_data = p_modbus_uart_data_info->base_data_info.p_data;
|
||||
|
||||
uint8_t bytes_count = recv_buff[2];
|
||||
|
||||
if ((WRITE_SINGLE_COIL == function_code) || (WRITE_SINGLE_REGISTER == function_code)) {
|
||||
head_length = 4;
|
||||
if (p_modbus_uart_data_info->base_data_info.command_ready) {
|
||||
p_modbus_uart_data_info->base_data_info.command_ready = 0;
|
||||
}
|
||||
}
|
||||
|
||||
data_buffer = recv_buff + head_length;//remove head data
|
||||
|
||||
if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) {
|
||||
printf("Receive data is ");
|
||||
for (int i = 0;i < bytes_count;i ++) {
|
||||
for (int j = 0;j < 8;j ++) {
|
||||
if ((i * 8 + j) < p_read_item->quantity) {
|
||||
*(uint8_t *)(p_data + i * 8 + j) = ((data_buffer[i] >> j) & 0x01) ? 1 : 0;
|
||||
printf("0x%x", *(uint8_t *)(p_data + i * 8 + j));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (READ_HOLDING_REGISTER == function_code || READ_INPUT_REGISTER == function_code) {
|
||||
printf("Receive data is ");
|
||||
for (uint16_t i = 0; i < quantity; i ++) {
|
||||
((int16_t *)p_data)[i] = ((int16_t *)data_buffer)[quantity - i - 1];
|
||||
printf("0x%x 0x%x ", p_data[2 * i], p_data[2 * i + 1]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Get Data From Serial
|
||||
* @param p_read_item - read item pointer
|
||||
* @return success : 0 error : -1 -2
|
||||
*/
|
||||
static int ModbusUartGetDataBySerial(ModbusUartReadItem *p_read_item)
|
||||
{
|
||||
uint32_t cmd_length, read_length = 0;
|
||||
memset(recv_buff, 0, sizeof(recv_buff));
|
||||
|
||||
ModbusUartDataInfo *p_modbus_uart_data_info = &(p_read_item->data_info);
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_modbus_uart_data_info->base_data_info);
|
||||
ModbusUartFunctionCode function_code = p_modbus_uart_data_info->function_code;
|
||||
|
||||
ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
SerialWrite(p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
|
||||
if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) {
|
||||
cmd_length = 6;
|
||||
} else if (READ_HOLDING_REGISTER == function_code || READ_INPUT_REGISTER == function_code) {
|
||||
cmd_length = 7;
|
||||
} else if (WRITE_SINGLE_COIL == function_code || WRITE_SINGLE_REGISTER == function_code) {
|
||||
cmd_length = 8;
|
||||
} else {
|
||||
//MULTIPLE_COIL and MULTIPLE_REGISTER to do
|
||||
cmd_length = 0;
|
||||
}
|
||||
|
||||
read_length = SerialRead(recv_buff, cmd_length);
|
||||
if (read_length) {
|
||||
ControlPrintfList("RECV", recv_buff, read_length);
|
||||
return ModbusUartTransformRecvBuffToData(p_read_item, recv_buff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Data Info Init
|
||||
* @param p_read_item - read item pointer
|
||||
* @param station - uart station number
|
||||
* @param p_data - control-data pointer
|
||||
* @return success : 0 error : -1 -2
|
||||
*/
|
||||
static int ModbusUartInitialDataInfo(ModbusUartReadItem *p_read_item, uint8_t station, uint8_t *p_data)
|
||||
{
|
||||
uint16_t command_crc = 0;
|
||||
uint8_t function_code = p_read_item->data_info.function_code;
|
||||
uint16_t start_address = p_read_item->start_address;
|
||||
uint16_t quantity = p_read_item->quantity;
|
||||
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info);
|
||||
|
||||
switch (function_code)
|
||||
{
|
||||
case READ_COIL_STATUS:
|
||||
case READ_INPUT_STATUS:
|
||||
case READ_HOLDING_REGISTER:
|
||||
case READ_INPUT_REGISTER:
|
||||
p_base_data_info->command_length = MODBUS_UART_READ_CMD_LENGTH;
|
||||
p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length);
|
||||
p_base_data_info->p_data = p_data;
|
||||
p_base_data_info->command_ready = 1;
|
||||
break;
|
||||
case WRITE_SINGLE_COIL:
|
||||
case WRITE_SINGLE_REGISTER:
|
||||
if (p_data == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
p_base_data_info->command_length = MODBUS_UART_WRITE_CMD_LENGTH;
|
||||
p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length);
|
||||
p_base_data_info->p_data = p_data;
|
||||
p_base_data_info->data_size = 2;
|
||||
p_base_data_info->command_ready = 0;
|
||||
}
|
||||
break;
|
||||
case WRITE_MULTIPLE_COIL:
|
||||
case WRITE_MULTIPLE_REGISTER:
|
||||
//to do
|
||||
printf("%s unsupported function code %d\n", __func__, function_code);
|
||||
return -1;
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
|
||||
memset(p_base_data_info->p_command, 0, p_base_data_info->command_length);
|
||||
|
||||
p_base_data_info->p_command[0] = station;
|
||||
p_base_data_info->p_command[1] = function_code;
|
||||
p_base_data_info->p_command[2] = start_address >> 8;
|
||||
p_base_data_info->p_command[3] = start_address;
|
||||
if ((function_code != WRITE_SINGLE_COIL) && (function_code != WRITE_SINGLE_REGISTER)) {
|
||||
p_base_data_info->p_command[4] = quantity >> 8;
|
||||
p_base_data_info->p_command[5] = quantity;
|
||||
command_crc = ModbusUartCrc16(p_base_data_info->p_command, 6);
|
||||
p_base_data_info->p_command[6] = command_crc & 0xFF;
|
||||
p_base_data_info->p_command[7] = (command_crc >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Format write data from "g_write_data"
|
||||
* @param p_read_item - read item pointer
|
||||
* @return success : 0 error : -1 -2
|
||||
*/
|
||||
static int ModbusUartForamatWriteData(ModbusUartReadItem *p_read_item)
|
||||
{
|
||||
int i = 0;
|
||||
uint16_t command_index = 0;
|
||||
int write_data_length = 0;
|
||||
uint8_t write_data_buffer[32] = {0};
|
||||
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info);
|
||||
uint8_t *p_command = p_base_data_info->p_command;
|
||||
uint8_t function_code = p_read_item->data_info.function_code;
|
||||
|
||||
if (function_code < WRITE_SINGLE_COIL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
write_data_length = CircularAreaAppRead(g_write_data, write_data_buffer, p_base_data_info->data_size);
|
||||
if (p_base_data_info->data_size != write_data_length) {
|
||||
//printf("%s get write data %d [should be %d]failed!\n", __func__, write_data_length, p_base_data_info->data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (function_code)
|
||||
{
|
||||
case WRITE_SINGLE_COIL:
|
||||
case WRITE_SINGLE_REGISTER:
|
||||
command_index = 4;
|
||||
break;
|
||||
case WRITE_MULTIPLE_COIL:
|
||||
case WRITE_MULTIPLE_REGISTER:
|
||||
printf("%s unsupported function code %d\n", __func__, function_code);
|
||||
return -1;
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
|
||||
for (i = 0; i < write_data_length; i ++) {
|
||||
p_base_data_info->p_command[command_index + i] = write_data_buffer[i];
|
||||
}
|
||||
|
||||
p_base_data_info->command_ready = 1;
|
||||
|
||||
return write_data_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Receive Plc Data Task
|
||||
* @param parameter - parameter pointer
|
||||
* @return
|
||||
*/
|
||||
void *ReceivePlcDataTask(void *parameter)
|
||||
{
|
||||
int i = 0;
|
||||
uint8_t try_count = 0;
|
||||
uint16_t data_length = 0;
|
||||
uint8_t *modbus_uart_data;
|
||||
uint16_t read_item_size = sizeof(ModbusUartReadItem);
|
||||
|
||||
struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter;
|
||||
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||
ModbusUartReadItem *modbus_uart_read_item = (ModbusUartReadItem *)control_protocol->recipe->read_item;
|
||||
modbus_uart_data = control_protocol->recipe->protocol_data.data;
|
||||
data_length = control_protocol->recipe->protocol_data.data_length;
|
||||
|
||||
while (1) {
|
||||
for (i = 0; i < control_protocol->recipe->read_item_count; i ++) {
|
||||
|
||||
ModbusUartForamatWriteData((ModbusUartReadItem *)modbus_uart_read_item + i);
|
||||
|
||||
ModbusUartGetDataBySerial((ModbusUartReadItem *)modbus_uart_read_item + i);
|
||||
}
|
||||
|
||||
/*read all variable item data, put them into circular_area*/
|
||||
if (i == control_protocol->recipe->read_item_count) {
|
||||
printf("%s get %d item %d length modbus_uart_data %p\n", __func__, i, data_length, modbus_uart_data);
|
||||
CircularAreaAppWrite(circular_area, modbus_uart_data, data_length, 0);
|
||||
}
|
||||
|
||||
/*read data every single 'read_period' ms*/
|
||||
PrivTaskDelay(control_protocol->recipe->read_period);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Protocol Open
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success : 0 error
|
||||
*/
|
||||
int ModbusUartOpen(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
ControlProtocolOpenDef(control_protocol);
|
||||
|
||||
g_write_data = CircularAreaAppInit(CA_DATA_LENGTH);
|
||||
if (NULL == g_write_data) {
|
||||
printf("%s CircularAreaInit error\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Protocol Close
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success : 0 error
|
||||
*/
|
||||
int ModbusUartClose(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
CircularAreaAppRelease(g_write_data);
|
||||
|
||||
ControlProtocolCloseDef();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Protocol Read Data
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param buf - read data buffer
|
||||
* @param len - read data length
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int ModbusUartRead(struct ControlProtocol *control_protocol, void *buf, size_t len)
|
||||
{
|
||||
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||
return CircularAreaAppRead(circular_area, buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Protocol Write Data
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param buf - write data buffer
|
||||
* @param len - write data length
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int ModbusUartWrite(struct ControlProtocol *control_protocol, const void *buf, size_t len)
|
||||
{
|
||||
CircularAreaAppWrite(g_write_data, (uint8_t *)buf, len, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Protocol Ioctl
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param cmd - ioctl cmd
|
||||
* @param args - ioctl args
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int ModbusUartIoctl(struct ControlProtocol *control_protocol, int cmd, void *args)
|
||||
{
|
||||
//to do
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ControlDone modbusuart_protocol_done =
|
||||
{
|
||||
._open = ModbusUartOpen,
|
||||
._close = ModbusUartClose,
|
||||
._read = ModbusUartRead,
|
||||
._write = ModbusUartWrite,
|
||||
._ioctl = ModbusUartIoctl,
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: Modbus TCP Protocol Cmd Generate
|
||||
* @param p_recipe - recipe pointer
|
||||
* @param protocol_format_info - protocol format info pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
int ModbusUartProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info)
|
||||
{
|
||||
int ret = 0;
|
||||
static uint8_t last_item_size = 0;
|
||||
uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size;
|
||||
|
||||
ModbusUartReadItem *modbusuart_read_item = (ModbusUartReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index;
|
||||
|
||||
modbusuart_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint;
|
||||
strncpy(modbusuart_read_item->value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20);
|
||||
modbusuart_read_item->data_info.function_code = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "function_code")->valueint;
|
||||
modbusuart_read_item->start_address = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "start_address")->valueint;
|
||||
modbusuart_read_item->quantity = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "quantity")->valueint;
|
||||
|
||||
ret = ModbusUartInitialDataInfo(modbusuart_read_item,
|
||||
p_recipe->serial_config.station,
|
||||
p_read_item_data);
|
||||
|
||||
ControlPrintfList("CMD", modbusuart_read_item->data_info.base_data_info.p_command, modbusuart_read_item->data_info.base_data_info.command_length);
|
||||
protocol_format_info->last_item_size = GetValueTypeMemorySize(modbusuart_read_item->value_type);
|
||||
|
||||
last_item_size += protocol_format_info->last_item_size;
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus TCP Protocol Init
|
||||
* @param p_recipe - recipe pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
int ModbusUartProtocolInit(struct ControlRecipe *p_recipe)
|
||||
{
|
||||
p_recipe->read_item = PrivMalloc(sizeof(ModbusUartReadItem) * p_recipe->read_item_count);
|
||||
if (NULL == p_recipe->read_item) {
|
||||
PrivFree(p_recipe->read_item);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(p_recipe->read_item, 0, sizeof(ModbusUartReadItem));
|
||||
|
||||
p_recipe->ControlProtocolFormatCmd = ModbusUartProtocolFormatCmd;
|
||||
|
||||
p_recipe->done = &modbusuart_protocol_done;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "GJ2",
|
||||
"communication_type": 1,
|
||||
"serial_config": {
|
||||
"station": 1,
|
||||
"baud_rate": 9600,
|
||||
"data_bits": 8,
|
||||
"stop_bits": 1,
|
||||
"check_mode": 0
|
||||
},
|
||||
"protocol_type": 3,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "M0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8192,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D208",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 208,
|
||||
"quantity": 1
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,15 +1,28 @@
|
|||
config CONTROL_PROTOCOL_FINS
|
||||
bool "Using fins control protocol"
|
||||
default n
|
||||
select CONTROL_USING_SOCKET
|
||||
if CONTROL_PROTOCOL_FINS
|
||||
source "$APP_DIR/Framework/control/plc_protocol/fins/Kconfig"
|
||||
endif
|
||||
|
||||
config CONTROL_PROTOCOL_MELSEC
|
||||
bool "Using melsec control protocol"
|
||||
default n
|
||||
if CONTROL_PROTOCOL_MELSEC
|
||||
source "$APP_DIR/Framework/control/plc_protocol/melsec/Kconfig"
|
||||
endif
|
||||
|
||||
config CONTROL_PROTOCOL_OPCUA
|
||||
bool "Using opcua control protocol"
|
||||
default n
|
||||
if CONTROL_PROTOCOL_OPCUA
|
||||
source "$APP_DIR/Framework/control/plc_protocol/opcua/Kconfig"
|
||||
endif
|
||||
|
||||
config CONTROL_PROTOCOL_S7
|
||||
bool "Using s7 control protocol"
|
||||
default n
|
||||
if CONTROL_PROTOCOL_S7
|
||||
source "$APP_DIR/Framework/control/plc_protocol/s7/Kconfig"
|
||||
endif
|
||||
|
|
|
@ -154,6 +154,7 @@ static int FinsTransformRecvBuffToData(FinsReadItem *p_read_item, uint8_t *recv_
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
/**
|
||||
* @description: Fins Protocol Handshake
|
||||
* @param socket - socket
|
||||
|
@ -242,6 +243,7 @@ static int FinsGetData(int32_t socket, FinsReadItem *p_read_item)
|
|||
}
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @description: Fins Data Info Init
|
||||
|
@ -303,6 +305,7 @@ void *ReceivePlcDataTask(void *parameter)
|
|||
|
||||
while (1) {
|
||||
for (i = 0; i < control_protocol->recipe->read_item_count; i ++) {
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
/*only connect socket when close socket or init*/
|
||||
while (ControlConnectSocket(&plc_socket) < 0) {
|
||||
PrivTaskDelay(1000);
|
||||
|
@ -320,6 +323,7 @@ void *ReceivePlcDataTask(void *parameter)
|
|||
plc_socket.secondary_connect_flag = 1;
|
||||
|
||||
FinsGetData(plc_socket.socket, (FinsReadItem *)fins_read_item + i);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*read all variable item data, put them into circular_area*/
|
||||
|
@ -328,7 +332,7 @@ void *ReceivePlcDataTask(void *parameter)
|
|||
CircularAreaAppWrite(circular_area, fins_data, data_length, 0);
|
||||
}
|
||||
|
||||
/*read data every single 200ms*/
|
||||
/*read data every single 'read_period' ms*/
|
||||
PrivTaskDelay(control_protocol->recipe->read_period);
|
||||
}
|
||||
}
|
||||
|
@ -352,7 +356,9 @@ int FinsOpen(struct ControlProtocol *control_protocol)
|
|||
*/
|
||||
int FinsClose(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
ControlDisconnectSocket(&plc_socket);
|
||||
#endif
|
||||
|
||||
ControlProtocolCloseDef();
|
||||
|
||||
|
@ -390,6 +396,8 @@ static struct ControlDone fins_protocol_done =
|
|||
int FinsProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info)
|
||||
{
|
||||
int ret = 0;
|
||||
static uint8_t last_item_size = 0;
|
||||
uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size;
|
||||
|
||||
FinsReadItem *fins_read_item = (FinsReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index;
|
||||
|
||||
|
@ -405,11 +413,13 @@ int FinsProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *pr
|
|||
ret = FinsInitialDataInfo(fins_read_item,
|
||||
p_recipe->socket_config.plc_ip[3],
|
||||
p_recipe->socket_config.local_ip[3],
|
||||
protocol_format_info->p_read_item_data + protocol_format_info->last_item_size);
|
||||
p_read_item_data);
|
||||
|
||||
ControlPrintfList("CMD", fins_read_item->data_info.base_data_info.p_command, fins_read_item->data_info.base_data_info.command_length);
|
||||
protocol_format_info->last_item_size = GetValueTypeMemorySize(fins_read_item->value_type);
|
||||
|
||||
last_item_size += protocol_format_info->last_item_size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -426,6 +436,8 @@ int FinsProtocolInit(struct ControlRecipe *p_recipe)
|
|||
return -1;
|
||||
}
|
||||
|
||||
memset(p_recipe->read_item, 0, sizeof(FinsReadItem));
|
||||
|
||||
p_recipe->ControlProtocolFormatCmd = FinsProtocolFormatCmd;
|
||||
|
||||
p_recipe->done = &fins_protocol_done;
|
||||
|
|
|
@ -15,5 +15,98 @@
|
|||
* @brief plc protocol melsec
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-10-08
|
||||
*/
|
||||
* @date 2022-11-29
|
||||
*/
|
||||
|
||||
#ifndef MELSEC_H
|
||||
#define MELSEC_H
|
||||
|
||||
#include <control_def.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SUB_HEADER 0x5000
|
||||
#define NETWORK_NUMBER 0x00
|
||||
#define PC_NUMBER 0xFF
|
||||
#define QEQUEST_DESTINSTION_MODULE_IO_NUMBER 0x03FF
|
||||
#define QEQUEST_DESTINSTION_MODULE_STATION_NUMBER 0x00
|
||||
#define STATION_NUMBER 0x00
|
||||
#define FRAME_NUMBER 0x4639
|
||||
#define SELF_STATION_NUMBER 0x00
|
||||
|
||||
#define MELSEC_NAK 0x15
|
||||
#define MELSEC_STX 0x02
|
||||
#define MELSEC_ETX 0x03
|
||||
#define MELSEC_ENQ 0x05
|
||||
|
||||
#define MELSEC_1E_FRAME_RB 0x00
|
||||
#define MELSEC_1E_FRAME_RW 0x01
|
||||
#define MELSEC_1E_FRAME_WB 0x02
|
||||
#define MELSEC_1E_FRAME_WW 0x03
|
||||
|
||||
#define MELSEC_1C_FRAME_RB 0x4252
|
||||
#define MELSEC_1C_FRAME_RW 0x5752
|
||||
#define MELSEC_1C_FRAME_WB 0x4257
|
||||
#define MELSEC_1C_FRAME_WW 0x5757
|
||||
|
||||
//same as MELSEC_3E_Q_L_FRAME
|
||||
#define MELSEC_3C_FRAME_RB 0x04010001
|
||||
#define MELSEC_3C_FRAME_RW 0x04010000
|
||||
#define MELSEC_3C_FRAME_WB 0x14010001
|
||||
#define MELSEC_3C_FRAME_WW 0x14010000
|
||||
|
||||
//same as MELSEC_3C_FRAME
|
||||
#define MELSEC_3E_Q_L_FRAME_RB 0x04010001
|
||||
#define MELSEC_3E_Q_L_FRAME_RW 0x04010000
|
||||
#define MELSEC_3E_Q_L_FRAME_WB 0x14010001
|
||||
#define MELSEC_3E_Q_L_FRAME_WW 0x14010000
|
||||
|
||||
#define MELSEC_3E_IQ_R_FRAME_RB 0x04010003
|
||||
#define MELSEC_3E_IQ_R_FRAME_RW 0x04010002
|
||||
#define MELSEC_3E_IQ_R_FRAME_WB 0x14010003
|
||||
#define MELSEC_3E_IQ_R_FRAME_WW 0x14010002
|
||||
|
||||
typedef enum {
|
||||
READ_IN_BITS,
|
||||
READ_IN_WORD,
|
||||
WRITE_IN_BITS,
|
||||
WRITE_IN_WORD,
|
||||
TEST_IN_BIT,
|
||||
TEST_IN_WORD
|
||||
}MelsecCommandType;
|
||||
|
||||
typedef enum {
|
||||
MELSEC_1E_FRAME,
|
||||
MELSEC_3E_Q_L_FRAME,
|
||||
MELSEC_3E_IQ_R_FRAME,
|
||||
MELSEC_1C_FRAME,
|
||||
MELSEC_3C_FRAME
|
||||
}MelsecFrameType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BasicPlcDataInfo base_data_info;
|
||||
MelsecCommandType command_type;
|
||||
MelsecFrameType frame_type;
|
||||
}MelsecDataInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MelsecDataInfo data_info;
|
||||
|
||||
UniformValueType value_type;
|
||||
uint8_t value_name[20];
|
||||
|
||||
uint16_t monitoring_timer;
|
||||
uint16_t device_code;
|
||||
uint8_t head_device_number_string[6];
|
||||
uint16_t device_points_count;
|
||||
}MelsecReadItem;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,2 +1,64 @@
|
|||
choice
|
||||
prompt "select melsec protocol"
|
||||
default CONTROL_PROTOCOL_MELSEC_1E
|
||||
|
||||
config CONTROL_PROTOCOL_MELSEC_1E
|
||||
bool "support melsec_1e protocol, using SOCKET"
|
||||
select CONTROL_USING_SOCKET
|
||||
|
||||
config CONTROL_PROTOCOL_MELSEC_3E_Q_L
|
||||
bool "support melsec_3e_q_l protocol, using SOCKET"
|
||||
select CONTROL_USING_SOCKET
|
||||
|
||||
config CONTROL_PROTOCOL_MELSEC_3E_IQ_R
|
||||
bool "support melsec_3e_iq_r protocol, using SOCKET"
|
||||
select CONTROL_USING_SOCKET
|
||||
|
||||
config CONTROL_PROTOCOL_MELSEC_1C
|
||||
bool "support melsec_1c protocol, using SERIAL"
|
||||
select CONTROL_USING_SERIAL_485
|
||||
|
||||
config CONTROL_PROTOCOL_MELSEC_3C
|
||||
bool "support melsec_3c protocol, using SERIAL"
|
||||
select CONTROL_USING_SERIAL_485
|
||||
endchoice
|
||||
|
||||
if CONTROL_USING_SERIAL_485
|
||||
if ADD_XIZI_FETURES
|
||||
config CONTROL_FRAMEWORK_UART_485_DIR
|
||||
int "control framework 485 direction pin number"
|
||||
default "2"
|
||||
|
||||
config CONTROL_FRAMEWORK_PIN_DEV
|
||||
string "control framework device pin dev path"
|
||||
default "/dev/pin_dev"
|
||||
|
||||
config CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
bool "Using extra uart to control framework"
|
||||
default n
|
||||
|
||||
config CONTROL_FRAMEWORK_UART_DEV
|
||||
string "control framework device uart dev path"
|
||||
default "/dev/uart3_dev3"
|
||||
depends on !CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
|
||||
if CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
config CONTROL_FRAMEWORK_UART_DEV
|
||||
string "control framework device extra uart dev path"
|
||||
default "/dev/extuart_dev0"
|
||||
|
||||
config CONTROL_FRAMEWORK_DEV_EXT_PORT
|
||||
int "if control framework device using extuart, choose port"
|
||||
default "0"
|
||||
endif
|
||||
endif
|
||||
|
||||
if ADD_NUTTX_FETURES
|
||||
|
||||
endif
|
||||
|
||||
if ADD_RTTHREAD_FETURES
|
||||
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SRC_FILES :=
|
||||
SRC_FILES := melsec.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
|
|
|
@ -0,0 +1,805 @@
|
|||
/*
|
||||
* 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 melsec.c
|
||||
* @brief plc protocol melsec, support 1E、3E_Q_L、3E_IQ_R、1C、3C
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-11-29
|
||||
*/
|
||||
|
||||
#include <melsec.h>
|
||||
|
||||
static BasicSocketPlc plc_socket = {0};
|
||||
static uint8_t recv_buff[1024] = {0};
|
||||
|
||||
/**
|
||||
* @description: Melsec Get Check Sum
|
||||
* @param p_command - p_command pointer
|
||||
* @param command_length - command length
|
||||
* @return checksum
|
||||
*/
|
||||
static uint8_t GetCheckSum(uint8_t *p_command, uint16_t command_length)
|
||||
{
|
||||
uint8_t checksum = 0;
|
||||
for (uint16_t i = 0; i < command_length; i++) {
|
||||
checksum += p_command[i];
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Transform from Hex to Ascii
|
||||
* @param hex - hex
|
||||
* @return ascii
|
||||
*/
|
||||
static uint8_t TransformHexToAscii(uint8_t hex)
|
||||
{
|
||||
hex %= 0x10;
|
||||
return hex < 0xA ? hex + '0' : hex - 10 + 'A';
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Transform from Ascii to Hex
|
||||
* @param ascii - ascii
|
||||
* @return hex
|
||||
*/
|
||||
static uint8_t TransformAsciiToHex(uint8_t ascii)
|
||||
{
|
||||
if (ascii > 'F' || ascii < '0' || (ascii > '9' && ascii < 'A'))
|
||||
return 0;
|
||||
else
|
||||
return ascii < 'A' ? ascii - '0' : ascii - 'A' + 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Get Device Code
|
||||
* @param frame_type - melsec frame type
|
||||
* @param device_string - device string
|
||||
* @return device code
|
||||
*/
|
||||
static int MelsecGetDeviceCode(MelsecFrameType frame_type, char device_string[2])
|
||||
{
|
||||
switch (frame_type) {
|
||||
case MELSEC_1C_FRAME:
|
||||
if (strcmp(device_string, "M") == 0)
|
||||
return 0x4D;
|
||||
if (strcmp(device_string, "D") == 0)
|
||||
return 0x44;
|
||||
if (strcmp(device_string, "B") == 0)
|
||||
return 0x22;
|
||||
if (strcmp(device_string, "W") == 0)
|
||||
return 0x57;
|
||||
if (strcmp(device_string, "X") == 0)
|
||||
return 0x58;
|
||||
if (strcmp(device_string, "Y") == 0)
|
||||
return 0x59;
|
||||
case MELSEC_1E_FRAME:
|
||||
if (strcmp(device_string, "M") == 0)
|
||||
return 0x4D20;
|
||||
if (strcmp(device_string, "D") == 0)
|
||||
return 0x4420;
|
||||
if (strcmp(device_string, "B") == 0)
|
||||
return 0x2220;
|
||||
if (strcmp(device_string, "W") == 0)
|
||||
return 0x5720;
|
||||
if (strcmp(device_string, "X") == 0)
|
||||
return 0x5820;
|
||||
if (strcmp(device_string, "Y") == 0)
|
||||
return 0x5920;
|
||||
case MELSEC_3C_FRAME:
|
||||
if (strcmp(device_string, "M") == 0)
|
||||
return 0x4D2A;
|
||||
if (strcmp(device_string, "D") == 0)
|
||||
return 0x442A;
|
||||
if (strcmp(device_string, "B") == 0)
|
||||
return 0x222A;
|
||||
if (strcmp(device_string, "W") == 0)
|
||||
return 0x572A;
|
||||
case MELSEC_3E_IQ_R_FRAME:
|
||||
if (strcmp(device_string, "M") == 0)
|
||||
return 0x0090;
|
||||
if (strcmp(device_string, "D") == 0)
|
||||
return 0x00A8;
|
||||
if (strcmp(device_string, "B") == 0)
|
||||
return 0x00A0;
|
||||
if (strcmp(device_string, "W") == 0)
|
||||
return 0x00B4;
|
||||
if (strcmp(device_string, "X") == 0)
|
||||
return 0x009C;
|
||||
if (strcmp(device_string, "Y") == 0)
|
||||
return 0x009D;
|
||||
case MELSEC_3E_Q_L_FRAME:
|
||||
if (strcmp(device_string, "M") == 0)
|
||||
return 0x90;
|
||||
if (strcmp(device_string, "D") == 0)
|
||||
return 0xA8;
|
||||
if (strcmp(device_string, "B") == 0)
|
||||
return 0xA0;
|
||||
if (strcmp(device_string, "W") == 0)
|
||||
return 0xB4;
|
||||
if (strcmp(device_string, "X") == 0)
|
||||
return 0x9C;
|
||||
if (strcmp(device_string, "Y") == 0)
|
||||
return 0x9D;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Get Command Base Length
|
||||
* @param frame_type - melsec frame type
|
||||
* @return command length
|
||||
*/
|
||||
static int MelsecGetCommandBaseLength(MelsecFrameType frame_type)
|
||||
{
|
||||
switch (frame_type) {
|
||||
case MELSEC_1C_FRAME:
|
||||
return 17;
|
||||
case MELSEC_1E_FRAME:
|
||||
return 12;
|
||||
case MELSEC_3C_FRAME:
|
||||
return 33;
|
||||
case MELSEC_3E_IQ_R_FRAME:
|
||||
case MELSEC_3E_Q_L_FRAME:
|
||||
return 21;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Get Command Code
|
||||
* @param frame_type - melsec frame type
|
||||
* @param command_type - melsec command type
|
||||
* @return command code
|
||||
*/
|
||||
static uint32_t MelsecGetCommandCode(MelsecFrameType frame_type, MelsecCommandType command_type)
|
||||
{
|
||||
switch (frame_type) {
|
||||
case MELSEC_1C_FRAME:
|
||||
switch (command_type) {
|
||||
case READ_IN_BITS:
|
||||
return MELSEC_1C_FRAME_RB;
|
||||
case READ_IN_WORD:
|
||||
return MELSEC_1C_FRAME_RW;
|
||||
case WRITE_IN_BITS:
|
||||
return MELSEC_1C_FRAME_WB;
|
||||
case WRITE_IN_WORD:
|
||||
return MELSEC_1C_FRAME_WW;
|
||||
}
|
||||
case MELSEC_1E_FRAME:
|
||||
return command_type;
|
||||
case MELSEC_3C_FRAME:
|
||||
case MELSEC_3E_Q_L_FRAME:
|
||||
switch (command_type) {
|
||||
case READ_IN_BITS:
|
||||
return MELSEC_3E_Q_L_FRAME_RB;
|
||||
case READ_IN_WORD:
|
||||
return MELSEC_3E_Q_L_FRAME_RW;
|
||||
case WRITE_IN_BITS:
|
||||
return MELSEC_3E_Q_L_FRAME_WB;
|
||||
case WRITE_IN_WORD:
|
||||
return MELSEC_3E_Q_L_FRAME_WW;
|
||||
}
|
||||
case MELSEC_3E_IQ_R_FRAME:
|
||||
switch (command_type) {
|
||||
case READ_IN_BITS:
|
||||
return MELSEC_3E_IQ_R_FRAME_RB;
|
||||
case READ_IN_WORD:
|
||||
return MELSEC_3E_IQ_R_FRAME_RW;
|
||||
case WRITE_IN_BITS:
|
||||
return MELSEC_3E_IQ_R_FRAME_WB;
|
||||
case WRITE_IN_WORD:
|
||||
return MELSEC_3E_IQ_R_FRAME_WW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec_1E Cmd Genetare
|
||||
* @param p_command - command pointer
|
||||
* @param command_code - command code
|
||||
* @param p_read_item - p_read_item pointer
|
||||
* @return success : index error : 0
|
||||
*/
|
||||
static uint16_t Melsec1eGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item)
|
||||
{
|
||||
uint16_t index = 0;
|
||||
|
||||
p_command[index++] = command_code;
|
||||
p_command[index++] = PC_NUMBER;
|
||||
p_command[index++] = p_read_item->monitoring_timer / 250;
|
||||
p_command[index++] = (p_read_item->monitoring_timer / 250) >> 8;
|
||||
|
||||
uint16_t head_device_number = 0;
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (0 != p_read_item->head_device_number_string[i])
|
||||
head_device_number = TransformAsciiToHex(p_read_item->head_device_number_string[i]) + head_device_number * (((0x5820 == p_read_item->device_code) || (0x5920 == p_read_item->device_code)) ? 8 : 10);
|
||||
else
|
||||
break;
|
||||
}
|
||||
p_command[index++] = head_device_number;
|
||||
p_command[index++] = head_device_number >> (8 * 1);
|
||||
p_command[index++] = head_device_number >> (8 * 2);
|
||||
p_command[index++] = head_device_number >> (8 * 3);
|
||||
p_command[index++] = p_read_item->device_code;
|
||||
p_command[index++] = p_read_item->device_code >> 8;
|
||||
p_command[index++] = p_read_item->device_points_count;
|
||||
p_command[index++] = 0x00;
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec_3E_Q_L Cmd Genetare
|
||||
* @param p_command - command pointer
|
||||
* @param command_code - command code
|
||||
* @param p_read_item - p_read_item pointer
|
||||
* @return success : index error : 0
|
||||
*/
|
||||
static uint16_t Melsec3eqlGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item)
|
||||
{
|
||||
p_read_item->monitoring_timer /= 250;
|
||||
uint16_t index = 0;
|
||||
|
||||
p_command[index++] = SUB_HEADER >> 8;
|
||||
p_command[index++] = (uint8_t)SUB_HEADER;
|
||||
p_command[index++] = NETWORK_NUMBER;
|
||||
p_command[index++] = PC_NUMBER;
|
||||
p_command[index++] = (uint8_t)QEQUEST_DESTINSTION_MODULE_IO_NUMBER;
|
||||
p_command[index++] = (uint8_t)(QEQUEST_DESTINSTION_MODULE_IO_NUMBER >> 8);
|
||||
p_command[index++] = QEQUEST_DESTINSTION_MODULE_STATION_NUMBER;
|
||||
p_command[index++] = 0x0C;
|
||||
p_command[index++] = 0x00;
|
||||
p_command[index++] = p_read_item->monitoring_timer;
|
||||
p_command[index++] = p_read_item->monitoring_timer >> 8;
|
||||
p_command[index++] = command_code >> (8 * 2);
|
||||
p_command[index++] = command_code >> (8 * 3);
|
||||
p_command[index++] = command_code;
|
||||
p_command[index++] = command_code >> (8 * 1);
|
||||
|
||||
uint16_t head_device_number = 0;
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (0 != p_read_item->head_device_number_string[i])
|
||||
head_device_number = TransformAsciiToHex(p_read_item->head_device_number_string[i]) + head_device_number * (((0x9c == (uint8_t)p_read_item->device_code) || (0x9d == (uint8_t)p_read_item->device_code)) ? 16 : 10);
|
||||
else
|
||||
break;
|
||||
}
|
||||
p_command[index++] = head_device_number;
|
||||
p_command[index++] = head_device_number >> (8 * 1);
|
||||
p_command[index++] = head_device_number >> (8 * 2);
|
||||
p_command[index++] = p_read_item->device_code;
|
||||
p_command[index++] = p_read_item->device_points_count;
|
||||
p_command[index++] = p_read_item->device_points_count >> 8;
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec_3E_IQ_R Cmd Genetare
|
||||
* @param p_command - command pointer
|
||||
* @param command_code - command code
|
||||
* @param p_read_item - p_read_item pointer
|
||||
* @return success : index error : 0
|
||||
*/
|
||||
static uint16_t Melsec3eiqrGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item)
|
||||
{
|
||||
uint16_t index = Melsec3eqlGenerateCommand(p_command, command_code, p_read_item) - 6;
|
||||
|
||||
uint16_t head_device_number = 0;
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (0 != p_read_item->head_device_number_string[i])
|
||||
head_device_number = TransformAsciiToHex(p_read_item->head_device_number_string[i]) + head_device_number * (((0x9c == (uint8_t)p_read_item->device_code) || (0x9d == (uint8_t)p_read_item->device_code)) ? 16 : 10);
|
||||
else
|
||||
break;
|
||||
}
|
||||
p_command[index++] = head_device_number;
|
||||
p_command[index++] = head_device_number >> (8 * 1);
|
||||
p_command[index++] = head_device_number >> (8 * 2);
|
||||
p_command[index++] = head_device_number >> (8 * 3);
|
||||
p_command[index++] = p_read_item->device_code;
|
||||
p_command[index++] = p_read_item->device_code >> 8;
|
||||
p_command[index++] = p_read_item->device_points_count;
|
||||
p_command[index++] = p_read_item->device_points_count >> 8;
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec_1C Cmd Genetare
|
||||
* @param p_command - command pointer
|
||||
* @param command_code - command code
|
||||
* @param p_read_item - p_read_item pointer
|
||||
* @return success : index error : 0
|
||||
*/
|
||||
static uint16_t Melsec1cGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item)
|
||||
{
|
||||
p_read_item->monitoring_timer /= 10;
|
||||
uint16_t index = 0;
|
||||
uint8_t checksum = 0;
|
||||
|
||||
p_command[index++] = MELSEC_ENQ;
|
||||
p_command[index++] = TransformHexToAscii(STATION_NUMBER >> 4);
|
||||
p_command[index++] = TransformHexToAscii(STATION_NUMBER);
|
||||
p_command[index++] = TransformHexToAscii(PC_NUMBER >> 4);
|
||||
p_command[index++] = TransformHexToAscii(PC_NUMBER);
|
||||
p_command[index++] = command_code >> 8;
|
||||
p_command[index++] = command_code;
|
||||
p_command[index++] = TransformHexToAscii(p_read_item->monitoring_timer);
|
||||
p_command[index++] = p_read_item->device_code;
|
||||
uint8_t head_device_number_string_length = 0;
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (0 == p_read_item->head_device_number_string[i])
|
||||
break;
|
||||
else
|
||||
head_device_number_string_length++;
|
||||
}
|
||||
p_command[index++] = (head_device_number_string_length - 4 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 4];
|
||||
p_command[index++] = (head_device_number_string_length - 3 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 3];
|
||||
p_command[index++] = (head_device_number_string_length - 2 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 2];
|
||||
p_command[index++] = (head_device_number_string_length - 1 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 1];
|
||||
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> 4);
|
||||
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count);
|
||||
checksum = GetCheckSum(p_command + 1, index - 1);
|
||||
p_command[index++] = TransformHexToAscii(checksum >> 4);
|
||||
p_command[index++] = TransformHexToAscii(checksum);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec_3C Cmd Genetare
|
||||
* @param p_command - command pointer
|
||||
* @param command_code - command code
|
||||
* @param p_read_item - p_read_item pointer
|
||||
* @return success : index error : 0
|
||||
*/
|
||||
static uint16_t Melsec3cGenerateCommand(uint8_t* p_command, uint32_t command_code, MelsecReadItem *p_read_item)
|
||||
{
|
||||
uint16_t index = 0;
|
||||
uint8_t checksum = 0;
|
||||
|
||||
p_command[index++] = MELSEC_ENQ;
|
||||
p_command[index++] = FRAME_NUMBER >> 8;
|
||||
p_command[index++] = (uint8_t)FRAME_NUMBER;
|
||||
p_command[index++] = TransformHexToAscii(STATION_NUMBER >> 4);
|
||||
p_command[index++] = TransformHexToAscii(STATION_NUMBER);
|
||||
p_command[index++] = TransformHexToAscii(NETWORK_NUMBER >> 4);
|
||||
p_command[index++] = TransformHexToAscii(NETWORK_NUMBER);
|
||||
p_command[index++] = TransformHexToAscii(PC_NUMBER >> 4);
|
||||
p_command[index++] = TransformHexToAscii(PC_NUMBER);
|
||||
p_command[index++] = TransformHexToAscii(SELF_STATION_NUMBER >> 4);
|
||||
p_command[index++] = TransformHexToAscii(SELF_STATION_NUMBER);
|
||||
p_command[index++] = TransformHexToAscii(command_code >> (7 * 4));
|
||||
p_command[index++] = TransformHexToAscii(command_code >> (6 * 4));
|
||||
p_command[index++] = TransformHexToAscii(command_code >> (5 * 4));
|
||||
p_command[index++] = TransformHexToAscii(command_code >> (4 * 4));
|
||||
p_command[index++] = TransformHexToAscii(command_code >> (3 * 4));
|
||||
p_command[index++] = TransformHexToAscii(command_code >> (2 * 4));
|
||||
p_command[index++] = TransformHexToAscii(command_code >> (1 * 4));
|
||||
p_command[index++] = TransformHexToAscii(command_code);
|
||||
p_command[index++] = p_read_item->device_code >> 8;
|
||||
p_command[index++] = p_read_item->device_code;
|
||||
uint8_t head_device_number_string_length = 0;
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (0 == p_read_item->head_device_number_string[i])
|
||||
break;
|
||||
else
|
||||
head_device_number_string_length++;
|
||||
}
|
||||
p_command[index++] = (head_device_number_string_length - 6 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 6];
|
||||
p_command[index++] = (head_device_number_string_length - 5 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 5];
|
||||
p_command[index++] = (head_device_number_string_length - 4 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 4];
|
||||
p_command[index++] = (head_device_number_string_length - 3 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 3];
|
||||
p_command[index++] = (head_device_number_string_length - 2 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 2];
|
||||
p_command[index++] = (head_device_number_string_length - 1 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 1];
|
||||
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> (3 * 8));
|
||||
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> (2 * 8));
|
||||
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> (1 * 8));
|
||||
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count);
|
||||
checksum = GetCheckSum(p_command + 1, index - 1);
|
||||
p_command[index++] = TransformHexToAscii(checksum >> 4);
|
||||
p_command[index++] = TransformHexToAscii(checksum);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Cmd Genetare
|
||||
* @param p_command - command pointer
|
||||
* @param command_code - command code
|
||||
* @param p_read_item - p_read_item pointer
|
||||
* @return success : index error : 0
|
||||
*/
|
||||
static uint16_t MelsecGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item)
|
||||
{
|
||||
uint16_t (*GenerateMelsecCommandFunction)(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item);
|
||||
|
||||
switch (p_read_item->data_info.frame_type) {
|
||||
case MELSEC_1E_FRAME:
|
||||
GenerateMelsecCommandFunction = Melsec1eGenerateCommand;
|
||||
break;
|
||||
case MELSEC_3E_IQ_R_FRAME:
|
||||
GenerateMelsecCommandFunction = Melsec3eiqrGenerateCommand;
|
||||
break;
|
||||
case MELSEC_3E_Q_L_FRAME:
|
||||
GenerateMelsecCommandFunction = Melsec3eqlGenerateCommand;
|
||||
break;
|
||||
case MELSEC_1C_FRAME:
|
||||
GenerateMelsecCommandFunction = Melsec1cGenerateCommand;
|
||||
break;
|
||||
case MELSEC_3C_FRAME:
|
||||
GenerateMelsecCommandFunction = Melsec3cGenerateCommand;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return GenerateMelsecCommandFunction(p_command, command_code, p_read_item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Data Info Init
|
||||
* @param p_read_item - read item pointer
|
||||
* @param p_data - control-data pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
int MelsecInitialDataInfo(MelsecReadItem *p_read_item, uint8_t *p_data)
|
||||
{
|
||||
uint8_t check_sum = 0;
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info);
|
||||
|
||||
int command_base_length = MelsecGetCommandBaseLength(p_read_item->data_info.frame_type);
|
||||
if (command_base_length < 0) {
|
||||
printf("%s Not supported device code!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (p_read_item->data_info.command_type) {
|
||||
case READ_IN_BITS:
|
||||
p_base_data_info->command_length = command_base_length;
|
||||
p_base_data_info->p_command = PrivMalloc(command_base_length);
|
||||
p_base_data_info->data_size = p_read_item->device_points_count;
|
||||
p_base_data_info->p_data = p_data;
|
||||
break;
|
||||
case READ_IN_WORD:
|
||||
p_base_data_info->command_length = command_base_length;
|
||||
p_base_data_info->p_command = PrivMalloc(command_base_length);
|
||||
p_base_data_info->data_size = p_read_item->device_points_count * 2;
|
||||
p_base_data_info->p_data = p_data;
|
||||
break;
|
||||
case WRITE_IN_BITS:
|
||||
p_base_data_info->command_length = command_base_length + p_read_item->device_points_count;
|
||||
p_base_data_info->p_command = PrivMalloc(command_base_length + p_read_item->device_points_count);
|
||||
command_base_length -= (p_read_item->data_info.frame_type >= MELSEC_1C_FRAME) ? 2 : 0;
|
||||
memcpy(p_base_data_info->p_command + command_base_length, p_data, p_read_item->device_points_count);
|
||||
break;
|
||||
case WRITE_IN_WORD:
|
||||
p_base_data_info->command_length = command_base_length + p_read_item->device_points_count * 2;
|
||||
p_base_data_info->p_command = PrivMalloc(command_base_length + p_read_item->device_points_count * 2);
|
||||
command_base_length -= (p_read_item->data_info.frame_type >= MELSEC_1C_FRAME) ? 2 : 0;
|
||||
memcpy(p_base_data_info->p_command + command_base_length, p_data, p_read_item->device_points_count * 2);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t command_code = MelsecGetCommandCode(p_read_item->data_info.frame_type, p_read_item->data_info.command_type);
|
||||
MelsecGenerateCommand(p_base_data_info->p_command, command_code, p_read_item);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Data Transform from Receive Buffer To Control-Data
|
||||
* @param p_read_item - read item pointer
|
||||
* @param recv_buff - receive buff
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int MelsecTransformRecvBuffToData(MelsecReadItem *p_read_item, uint8_t *recv_buff)
|
||||
{
|
||||
MelsecDataInfo *p_melsec_data_info = &(p_read_item->data_info);
|
||||
MelsecFrameType frame_type = p_melsec_data_info->frame_type;
|
||||
MelsecCommandType command_type = p_melsec_data_info->command_type;
|
||||
uint8_t *p_data = p_melsec_data_info->base_data_info.p_data;
|
||||
|
||||
uint16_t device_points_count = p_read_item->device_points_count;
|
||||
uint8_t is_ascii = ((MELSEC_1E_FRAME == frame_type) || (MELSEC_3E_Q_L_FRAME == frame_type) || (MELSEC_3E_IQ_R_FRAME == frame_type)) ? 0 : 1;
|
||||
uint16_t abnormal_code = 0;
|
||||
|
||||
switch (frame_type) {
|
||||
case MELSEC_3E_IQ_R_FRAME:
|
||||
case MELSEC_3E_Q_L_FRAME:
|
||||
if (recv_buff[9] != 0 || recv_buff[10] != 0)
|
||||
abnormal_code = recv_buff[10] * 256 + recv_buff[9];
|
||||
else
|
||||
recv_buff += 11;
|
||||
break;
|
||||
case MELSEC_1E_FRAME:
|
||||
if (recv_buff[1] != 0)
|
||||
abnormal_code = recv_buff[2];
|
||||
else
|
||||
recv_buff += 2;
|
||||
break;
|
||||
case MELSEC_1C_FRAME:
|
||||
if (MELSEC_NAK == recv_buff[0])
|
||||
abnormal_code = recv_buff[5] * 256 + recv_buff[6];
|
||||
else
|
||||
recv_buff += 5;
|
||||
break;
|
||||
case MELSEC_3C_FRAME:
|
||||
if (MELSEC_NAK == recv_buff[0])
|
||||
abnormal_code = ((uint16_t)TransformAsciiToHex(recv_buff[11])) << 12 + ((uint16_t)TransformAsciiToHex(recv_buff[12])) << 8 +
|
||||
((uint16_t)TransformAsciiToHex(recv_buff[13])) << 4 + ((uint16_t)TransformAsciiToHex(recv_buff[14]));
|
||||
else
|
||||
recv_buff += 11;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (abnormal_code != 0) {
|
||||
printf("Data abnormal, abnormal code is %0x!", abnormal_code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ControlPrintfList("DATA", recv_buff, (uint16_t)(device_points_count * (READ_IN_BITS == command_type ? 0.5 : 2) * (frame_type >= MELSEC_1C_FRAME ? 2 : 1) + 0.6));
|
||||
printf("Receive data is ");
|
||||
for (uint16_t i = 0; i < device_points_count; i++) {
|
||||
if (READ_IN_BITS == command_type) {
|
||||
if (!is_ascii) {
|
||||
p_data[i] = (recv_buff[i / 2] & (i % 2 == 0 ? 0x10 : 0x01)) || 0;
|
||||
} else {
|
||||
p_data[i] = TransformAsciiToHex(recv_buff[i]);
|
||||
}
|
||||
printf("0x%x", p_data[i]);
|
||||
} else if (READ_IN_WORD == command_type) {
|
||||
if (!is_ascii) {
|
||||
uint16_t recv_buff_index = 2 * (device_points_count - 1 - i);
|
||||
p_data[2 * i] = recv_buff[recv_buff_index + 1];
|
||||
p_data[2 * i + 1] = recv_buff[recv_buff_index];
|
||||
} else {
|
||||
uint16_t recv_buff_index = 4 * (device_points_count - 1 - i);
|
||||
p_data[2 * i] = TransformAsciiToHex(recv_buff[recv_buff_index]) * 16 + TransformAsciiToHex(recv_buff[recv_buff_index + 1]);
|
||||
p_data[2 * i + 1] = TransformAsciiToHex(recv_buff[recv_buff_index + 2]) * 16 + TransformAsciiToHex(recv_buff[recv_buff_index + 3]);
|
||||
}
|
||||
printf("0x%x 0x%x", p_data[2 * i], p_data[2 * i + 1]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
/**
|
||||
* @description: Melsec Get Data From Socket
|
||||
* @param socket - socket
|
||||
* @param p_read_item - read item pointer
|
||||
* @return success : 0 error : -1 -2
|
||||
*/
|
||||
static int MelsecGetDataBySocket(int32_t socket, MelsecReadItem *p_read_item)
|
||||
{
|
||||
uint8_t try_count = 0;
|
||||
int32_t write_error = 0;
|
||||
|
||||
MelsecDataInfo *p_melsec_data_info = &(p_read_item->data_info);
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_melsec_data_info->base_data_info);
|
||||
|
||||
memset(recv_buff, 0, sizeof(recv_buff));
|
||||
|
||||
while (try_count < 10) {
|
||||
ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
try_count++;
|
||||
|
||||
write_error = socket_write(socket, p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
if (write_error < 0) {
|
||||
printf("Write socket error, errno is %d!", errno);
|
||||
} else {
|
||||
PrivTaskDelay(20);
|
||||
|
||||
int32_t recv_length = socket_read(socket, recv_buff, sizeof(recv_buff));
|
||||
if (recv_length < 0) {
|
||||
printf("Read socket error, errno is %d!", errno);
|
||||
} else {
|
||||
ControlPrintfList("RECV", recv_buff, recv_length);
|
||||
return MelsecTransformRecvBuffToData(p_read_item, recv_buff);
|
||||
}
|
||||
}
|
||||
|
||||
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||
printf("Send plc command failed, errno is %d!", errno);
|
||||
continue;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @description: Melsec Get Data From Serial
|
||||
* @param p_read_item - read item pointer
|
||||
* @return success : 0 error : -1 -2
|
||||
*/
|
||||
static int MelsecGetDataBySerial(MelsecReadItem *p_read_item)
|
||||
{
|
||||
uint32_t read_length = 0;
|
||||
memset(recv_buff, 0, sizeof(recv_buff));
|
||||
|
||||
MelsecDataInfo *p_melsec_data_info = &(p_read_item->data_info);
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_melsec_data_info->base_data_info);
|
||||
|
||||
ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
SerialWrite(p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
|
||||
read_length = SerialRead(recv_buff, sizeof(recv_buff));
|
||||
if (read_length) {
|
||||
ControlPrintfList("RECV", recv_buff, read_length);
|
||||
return MelsecTransformRecvBuffToData(p_read_item, recv_buff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Receive Plc Data Task
|
||||
* @param parameter - parameter pointer
|
||||
* @return
|
||||
*/
|
||||
void *ReceivePlcDataTask(void *parameter)
|
||||
{
|
||||
int i = 0;
|
||||
uint8_t try_count = 0;
|
||||
uint16_t data_length = 0;
|
||||
uint8_t *melsec_data;
|
||||
uint16_t read_item_size = sizeof(MelsecReadItem);
|
||||
|
||||
struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter;
|
||||
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||
MelsecReadItem *melsec_read_item = (MelsecReadItem *)control_protocol->recipe->read_item;
|
||||
melsec_data = control_protocol->recipe->protocol_data.data;
|
||||
data_length = control_protocol->recipe->protocol_data.data_length;
|
||||
|
||||
memset(&plc_socket, 0, sizeof(BasicSocketPlc));
|
||||
memcpy(plc_socket.ip, control_protocol->recipe->socket_config.plc_ip, 4);
|
||||
plc_socket.port = control_protocol->recipe->socket_config.port;
|
||||
plc_socket.socket = -1;
|
||||
|
||||
while (1) {
|
||||
for (i = 0; i < control_protocol->recipe->read_item_count; i ++) {
|
||||
|
||||
if ((PROTOCOL_MELSEC_1C == control_protocol->protocol_type) || (PROTOCOL_MELSEC_3C == control_protocol->protocol_type)) {
|
||||
MelsecGetDataBySerial((MelsecReadItem *)melsec_read_item + i);
|
||||
} else {
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
/*only connect socket when close socket or init*/
|
||||
while (ControlConnectSocket(&plc_socket) < 0) {
|
||||
PrivTaskDelay(1000);
|
||||
}
|
||||
|
||||
MelsecGetDataBySocket(plc_socket.socket, (MelsecReadItem *)melsec_read_item + i);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*read all variable item data, put them into circular_area*/
|
||||
if (i == control_protocol->recipe->read_item_count) {
|
||||
printf("%s get %d item %d length\n", __func__, i, data_length);
|
||||
CircularAreaAppWrite(circular_area, melsec_data, data_length, 0);
|
||||
}
|
||||
|
||||
/*read data every single 'read_period' ms*/
|
||||
PrivTaskDelay(control_protocol->recipe->read_period);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Protocol Open
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success : 0 error
|
||||
*/
|
||||
int MelsecOpen(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
ControlProtocolOpenDef(control_protocol);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Protocol Close
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success : 0 error
|
||||
*/
|
||||
int MelsecClose(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
if ((PROTOCOL_MELSEC_1C != control_protocol->protocol_type) && (PROTOCOL_MELSEC_3C != control_protocol->protocol_type)) {
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
ControlDisconnectSocket(&plc_socket);
|
||||
#endif
|
||||
}
|
||||
|
||||
ControlProtocolCloseDef();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Protocol Read Data
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param buf - read data buffer
|
||||
* @param len - read data length
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int MelsecRead(struct ControlProtocol *control_protocol, void *buf, size_t len)
|
||||
{
|
||||
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||
return CircularAreaAppRead(circular_area, buf, len);
|
||||
}
|
||||
|
||||
static struct ControlDone melsec_protocol_done =
|
||||
{
|
||||
._open = MelsecOpen,
|
||||
._close = MelsecClose,
|
||||
._read = MelsecRead,
|
||||
._write = NULL,
|
||||
._ioctl = NULL,
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: Melsec Protocol Cmd Generate
|
||||
* @param p_recipe - recipe pointer
|
||||
* @param protocol_format_info - protocol format info pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
int MelsecProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info)
|
||||
{
|
||||
int ret = 0;
|
||||
static uint8_t last_item_size = 0;
|
||||
uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size;
|
||||
|
||||
MelsecReadItem *melsec_read_item = (MelsecReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index;
|
||||
|
||||
melsec_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint;
|
||||
strncpy(melsec_read_item->value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20);
|
||||
melsec_read_item->data_info.command_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "command_type")->valueint;
|
||||
melsec_read_item->data_info.frame_type = p_recipe->protocol_type - PROTOCOL_MELSEC_1E;
|
||||
melsec_read_item->monitoring_timer = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "monitoring_timer")->valueint;
|
||||
melsec_read_item->device_code = MelsecGetDeviceCode(melsec_read_item->data_info.frame_type, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_code")->valuestring);
|
||||
strncpy(melsec_read_item->head_device_number_string, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "head_device_number_string")->valuestring, 6);
|
||||
melsec_read_item->device_points_count = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_points_count")->valueint;
|
||||
|
||||
ret = MelsecInitialDataInfo(melsec_read_item, p_read_item_data);
|
||||
|
||||
ControlPrintfList("CMD", melsec_read_item->data_info.base_data_info.p_command, melsec_read_item->data_info.base_data_info.command_length);
|
||||
protocol_format_info->last_item_size = GetValueTypeMemorySize(melsec_read_item->value_type);
|
||||
|
||||
last_item_size += protocol_format_info->last_item_size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Melsec Protocol Init
|
||||
* @param p_recipe - recipe pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
int MelsecProtocolInit(struct ControlRecipe *p_recipe)
|
||||
{
|
||||
p_recipe->read_item = PrivMalloc(sizeof(MelsecReadItem) * p_recipe->read_item_count);
|
||||
if (NULL == p_recipe->read_item) {
|
||||
PrivFree(p_recipe->read_item);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(p_recipe->read_item, 0, sizeof(MelsecReadItem));
|
||||
|
||||
p_recipe->ControlProtocolFormatCmd = MelsecProtocolFormatCmd;
|
||||
|
||||
p_recipe->done = &melsec_protocol_done;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"device_id": 769,
|
||||
"device_name": "S01",
|
||||
"communication_type": 1,
|
||||
"serial_config": {
|
||||
"station": 1,
|
||||
"baud_rate": 19200,
|
||||
"data_bits": 7,
|
||||
"stop_bits": 1,
|
||||
"check_mode": 3
|
||||
},
|
||||
"protocol_type": 9,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "启动",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "停止",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"device_id": 771,
|
||||
"device_name": "S03",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.20",
|
||||
"local_ip": "192.168.250.233",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.254.0",
|
||||
"port": 2000
|
||||
},
|
||||
"protocol_type": 6,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "启动",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "停止",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"device_id": 770,
|
||||
"device_name": "S02",
|
||||
"communication_type": 1,
|
||||
"serial_config": {
|
||||
"station": 1,
|
||||
"baud_rate": 19200,
|
||||
"data_bits": 7,
|
||||
"stop_bits": 1,
|
||||
"check_mode": 3
|
||||
},
|
||||
"protocol_type": 10,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "启动",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "停止",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"device_id": 773,
|
||||
"device_name": "S05",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.20",
|
||||
"local_ip": "192.168.250.233",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.254.0",
|
||||
"port": 2000
|
||||
},
|
||||
"protocol_type": 8,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "启动",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "停止",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"device_id": 772,
|
||||
"device_name": "S04",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.20",
|
||||
"local_ip": "192.168.250.233",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.254.0",
|
||||
"port": 2000
|
||||
},
|
||||
"protocol_type": 7,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "启动",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "0",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
},
|
||||
{
|
||||
"value_name": "停止",
|
||||
"value_type": 1,
|
||||
"device_code": "M",
|
||||
"head_device_number_string": "1",
|
||||
"device_points_count": 1,
|
||||
"command_type": 0,
|
||||
"monitoring_timer": 100
|
||||
}
|
||||
]
|
||||
}
|
|
@ -33,6 +33,18 @@ extern void *ReceivePlcDataTask(void *parameter);
|
|||
extern int FinsProtocolInit(struct ControlRecipe *p_recipe);
|
||||
#endif
|
||||
|
||||
#ifdef CONTROL_PROTOCOL_MELSEC
|
||||
extern int MelsecProtocolInit(struct ControlRecipe *p_recipe);
|
||||
#endif
|
||||
|
||||
#ifdef CONTROL_PROTOCOL_MODBUS_TCP
|
||||
extern int ModbusTcpProtocolInit(struct ControlRecipe *p_recipe);
|
||||
#endif
|
||||
|
||||
#ifdef CONTROL_PROTOCOL_MODBUS_UART
|
||||
extern int ModbusUartProtocolInit(struct ControlRecipe *p_recipe);
|
||||
#endif
|
||||
|
||||
/*
|
||||
CONTROL FRAMEWORK READ DATA FORMAT:
|
||||
| HEAD |device_id|read data length|read item count| data |
|
||||
|
@ -55,6 +67,19 @@ static struct ControlProtocolInitParam protocol_init[] =
|
|||
#ifdef CONTROL_PROTOCOL_FINS
|
||||
{ PROTOCOL_FINS, FinsProtocolInit },
|
||||
#endif
|
||||
#ifdef CONTROL_PROTOCOL_MELSEC
|
||||
{ PROTOCOL_MELSEC_1E, MelsecProtocolInit },
|
||||
{ PROTOCOL_MELSEC_3E_Q_L, MelsecProtocolInit },
|
||||
{ PROTOCOL_MELSEC_3E_IQ_R, MelsecProtocolInit },
|
||||
{ PROTOCOL_MELSEC_1C, MelsecProtocolInit },
|
||||
{ PROTOCOL_MELSEC_3C, MelsecProtocolInit },
|
||||
#endif
|
||||
#ifdef CONTROL_PROTOCOL_MODBUS_TCP
|
||||
{ PROTOCOL_MODBUS_TCP, ModbusTcpProtocolInit },
|
||||
#endif
|
||||
#ifdef CONTROL_PROTOCOL_MODBUS_UART
|
||||
{ PROTOCOL_MODBUS_UART, ModbusUartProtocolInit },
|
||||
#endif
|
||||
|
||||
{ PROTOCOL_END, NULL },
|
||||
};
|
||||
|
@ -125,12 +150,13 @@ static uint16_t GetRecipeTotalDataLength(cJSON* read_item_list_json)
|
|||
static void ControlBasicSerialConfig(struct ControlRecipe *p_recipe, cJSON *p_recipe_file_json)
|
||||
{
|
||||
cJSON *p_serial_config_json = cJSON_GetObjectItem(p_recipe_file_json, "serial_config");
|
||||
p_recipe->serial_config.station = cJSON_GetObjectItem(p_serial_config_json, "station")->valueint;
|
||||
p_recipe->serial_config.baud_rate = cJSON_GetObjectItem(p_serial_config_json, "baud_rate")->valueint;
|
||||
p_recipe->serial_config.data_bits = cJSON_GetObjectItem(p_serial_config_json, "data_bits")->valueint;
|
||||
p_recipe->serial_config.stop_bits = cJSON_GetObjectItem(p_serial_config_json, "stop_bits")->valueint;
|
||||
p_recipe->serial_config.check_mode = cJSON_GetObjectItem(p_serial_config_json, "check_mode")->valueint;
|
||||
printf("Serial_config: baud_rate: %d, data_bits: %d, stop_bits: %d, check_mode is %d\n",
|
||||
p_recipe->serial_config.baud_rate, p_recipe->serial_config.data_bits, p_recipe->serial_config.stop_bits, p_recipe->serial_config.check_mode);
|
||||
printf("Serial_config:station: %d baud_rate: %d, data_bits: %d, stop_bits: %d, check_mode is %d\n",
|
||||
p_recipe->serial_config.station, p_recipe->serial_config.baud_rate, p_recipe->serial_config.data_bits, p_recipe->serial_config.stop_bits, p_recipe->serial_config.check_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,13 +210,14 @@ static void ControlBasicSocketConfig(struct ControlRecipe *p_recipe, cJSON *p_re
|
|||
*/
|
||||
void ControlPrintfList(char name[5], uint8_t *number_list, uint16_t length)
|
||||
{
|
||||
printf("\n******************%5s****************\n", name);
|
||||
printf("\n******************%s****************\n", name);
|
||||
for (int32_t i = 0;i < length;i ++) {
|
||||
printf("0x%x ", number_list[i]);
|
||||
}
|
||||
printf("\n**************************************\n");
|
||||
}
|
||||
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
/**
|
||||
* @description: Control Framework Connect Socket
|
||||
* @param p_plc - basic socket plc pointer
|
||||
|
@ -267,6 +294,7 @@ int ControlDisconnectSocket(BasicSocketPlc *p_plc)
|
|||
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @description: Control Framework Protocol Open for Sub_Protocol, Init Circular Area and Receive Data Task
|
||||
|
|
|
@ -69,6 +69,7 @@ typedef struct
|
|||
{
|
||||
uint16_t command_length;
|
||||
uint16_t data_size;
|
||||
uint8_t command_ready;
|
||||
uint8_t *p_command;
|
||||
uint8_t *p_data;
|
||||
}BasicPlcDataInfo;
|
||||
|
@ -89,6 +90,7 @@ struct ProtocolData
|
|||
|
||||
struct SerialConfig
|
||||
{
|
||||
uint8_t station;
|
||||
uint32_t baud_rate;
|
||||
uint8_t data_bits;
|
||||
uint8_t stop_bits;
|
||||
|
|
|
@ -20,6 +20,96 @@
|
|||
|
||||
#include <control_io.h>
|
||||
|
||||
#ifdef CONTROL_USING_SERIAL_485
|
||||
static int pin_fd = 0;
|
||||
static int uart_fd = 0;
|
||||
|
||||
/**
|
||||
* @description: Set Uart 485 Input
|
||||
* @return
|
||||
*/
|
||||
static void Set485Input(void)
|
||||
{
|
||||
struct PinStat pin_stat;
|
||||
pin_stat.pin = CONTROL_FRAMEWORK_UART_485_DIR;
|
||||
pin_stat.val = GPIO_LOW;
|
||||
PrivWrite(pin_fd, &pin_stat, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Set Uart 485 Output
|
||||
* @return
|
||||
*/
|
||||
static void Set485Output(void)
|
||||
{
|
||||
struct PinStat pin_stat;
|
||||
pin_stat.pin = CONTROL_FRAMEWORK_UART_485_DIR;
|
||||
pin_stat.val = GPIO_HIGH;
|
||||
PrivWrite(pin_fd, &pin_stat, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Control Framework Uart 485 Init
|
||||
* @param baud_rate - baud rate
|
||||
* @param data_bits - data bits
|
||||
* @param stop_bits - stop bits
|
||||
* @param check_mode - check mode, even、odd、none
|
||||
* @return
|
||||
*/
|
||||
void Uart485Init(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_t check_mode)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
pin_fd = PrivOpen(CONTROL_FRAMEWORK_PIN_DEV, O_RDWR);
|
||||
if (pin_fd < 0) {
|
||||
printf("open %s error\n", CONTROL_FRAMEWORK_PIN_DEV);
|
||||
return;
|
||||
}
|
||||
|
||||
struct PinParam pin_param;
|
||||
pin_param.cmd = GPIO_CONFIG_MODE;
|
||||
pin_param.mode = GPIO_CFG_OUTPUT;
|
||||
pin_param.pin = CONTROL_FRAMEWORK_UART_485_DIR;
|
||||
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
ioctl_cfg.ioctl_driver_type = PIN_TYPE;
|
||||
ioctl_cfg.args = &pin_param;
|
||||
PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg);
|
||||
|
||||
uart_fd = open(CONTROL_FRAMEWORK_UART_DEV, O_RDWR);
|
||||
if (uart_fd < 0) {
|
||||
printf("open fd error %d\n", uart_fd);
|
||||
return;
|
||||
}
|
||||
printf("Uart485Init open fd %d baud_rate %d data_bits %d stop_bits %d check_mode %d\n",
|
||||
uart_fd, baud_rate, data_bits, stop_bits, check_mode);
|
||||
|
||||
struct SerialDataCfg cfg;
|
||||
cfg.serial_baud_rate = baud_rate;
|
||||
cfg.serial_data_bits = data_bits;
|
||||
cfg.serial_stop_bits = stop_bits;
|
||||
cfg.serial_buffer_size = 128;
|
||||
cfg.serial_parity_mode = check_mode;
|
||||
cfg.serial_bit_order = 0;
|
||||
cfg.serial_invert_mode = 0;
|
||||
#ifdef CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
cfg.ext_uart_no = 0;
|
||||
cfg.port_configure = PORT_CFG_INIT;
|
||||
#endif
|
||||
cfg.serial_timeout = 10000;
|
||||
|
||||
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
|
||||
ioctl_cfg.args = &cfg;
|
||||
ret = PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg);
|
||||
if (0 != ret) {
|
||||
printf("ioctl fd error %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s done!\n", __func__);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @description: Control Framework Socket Init
|
||||
* @param ip - local ip pointer
|
||||
|
@ -33,9 +123,14 @@ void SocketInit(char *ip, char *mask, char *gw)
|
|||
ip[0], ip[1], ip[2], ip[3],
|
||||
mask[0], mask[1], mask[2], mask[3],
|
||||
gw[0], gw[1], gw[2], gw[3]);
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
#ifdef BSP_USING_LWIP
|
||||
lwip_config_tcp(0, ip, mask, gw);
|
||||
#endif
|
||||
#ifdef BSP_USING_W5500
|
||||
//to do
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,5 +143,50 @@ void SocketInit(char *ip, char *mask, char *gw)
|
|||
*/
|
||||
void SerialInit(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_t check_mode)
|
||||
{
|
||||
// Uart485Init(baud_rate, data_bits, stop_bits, check_mode);
|
||||
#ifdef CONTROL_USING_SERIAL_485
|
||||
Uart485Init(baud_rate, data_bits, stop_bits, check_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Control Framework Serial Write
|
||||
* @param write_data - write data
|
||||
* @param length - length
|
||||
* @return
|
||||
*/
|
||||
void SerialWrite(uint8_t *write_data, int length)
|
||||
{
|
||||
#ifdef CONTROL_USING_SERIAL_485
|
||||
Set485Output();
|
||||
PrivTaskDelay(20);
|
||||
|
||||
PrivWrite(uart_fd, write_data, length);
|
||||
|
||||
PrivTaskDelay(15);
|
||||
Set485Input();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Control Framework Serial Read
|
||||
* @param read_data - read data
|
||||
* @param length - length
|
||||
* @return read data size
|
||||
*/
|
||||
int SerialRead(uint8_t *read_data, int length)
|
||||
{
|
||||
#ifdef CONTROL_USING_SERIAL_485
|
||||
int data_size = 0;
|
||||
int data_recv_size = 0;
|
||||
|
||||
while (data_size < length) {
|
||||
data_recv_size = PrivRead(uart_fd, read_data + data_recv_size, length);
|
||||
data_size += data_recv_size;
|
||||
}
|
||||
|
||||
//need to wait 30ms , make sure write cmd again and receive data successfully
|
||||
PrivTaskDelay(30);
|
||||
|
||||
return data_size;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -24,26 +24,42 @@
|
|||
#include <transform.h>
|
||||
#include <list.h>
|
||||
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
#ifdef BSP_USING_LWIP
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/sockets.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef CONTROL_USING_SOCKET
|
||||
#ifdef BSP_USING_LWIP
|
||||
#define socket_write lwip_write
|
||||
#define socket_read lwip_read
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_W5500
|
||||
//to do
|
||||
#define socket_write
|
||||
#define socket_read
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Control Framework Socket Init*/
|
||||
void SocketInit(char *ip, char *mask, char *gw);
|
||||
|
||||
/*Control Framework Serial Init*/
|
||||
void SerialInit(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_t check_mode);
|
||||
|
||||
/*Control Framework Serial Write*/
|
||||
void SerialWrite(uint8_t *write_data, int length);
|
||||
|
||||
/*Control Framework Serial Read*/
|
||||
int SerialRead(uint8_t *read_data, int length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SRC_DIR := tensorflow-lite
|
||||
SRC_DIR := kpu tensorflow-lite
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
SRC_DIR := k210_yolov2_detect_procedure yolov2 yolov2_json
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -3,5 +3,16 @@ menuconfig USING_K210_YOLOV2_DETECT
|
|||
depends on USING_KPU_PROCESSING
|
||||
default n
|
||||
|
||||
config KPU_DEV_DRIVER
|
||||
string "Set kpu dev path"
|
||||
default "/dev/kpu_dev"
|
||||
|
||||
config CAMERA_DEV_DRIVER
|
||||
string "Set camera dev path for kpu"
|
||||
default "/dev/ov2640"
|
||||
|
||||
config KPU_LCD_DEV_DRIVER
|
||||
string "Set lcd dev path for kpu"
|
||||
default "/dev/lcd_dev"
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
SRC_FILES := k210_yolov2_detect.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# YOLO Framework for K210 KPU
|
||||
|
||||
## Usage
|
||||
|
||||
* Include all src and header there in menuconfig, and copy codes like below in *main.c* in folder *Application*.
|
||||
* In board *edu-riscv64*, if all operations are right, the LCD should light and show the image from camera and YOLO inference.
|
||||
|
||||
```C
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
// #include <user_api.h>
|
||||
#include <transform.h>
|
||||
|
||||
|
||||
extern int FrameworkInit();
|
||||
extern void ApplicationOtaTaskInit(void);
|
||||
extern void k210_detect(char *json_file_path);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("Hello, world! \n");
|
||||
FrameworkInit();
|
||||
#ifdef APPLICATION_OTA
|
||||
ApplicationOtaTaskInit();
|
||||
#endif
|
||||
k210_detect("instrusion.json");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
* KPU drivers and frameworks are still not completed, because it is undefined how to reisgter KPU's bus and device name in rt-fusion system. The framework is still directly using the SDK with *ifdef* From Canaan Inc. But after the driver completed, it will be easy to adapt framework for the APIs.
|
||||
* Camera and LCD drivers between RT and XIZI are not completely compatible. So there are some marcos like *ifdef* to make the framework compatible for both systems.
|
||||
* After completed, all codes from kernel in knowing framework should be posix interfaces,like *PrivOpen*、*PrivIoctrl*、*PrivRead*.
|
|
@ -1,25 +1,29 @@
|
|||
#include "k210_yolov2_detect.h"
|
||||
|
||||
#include "cJSON.h"
|
||||
#include "dvp.h"
|
||||
#ifdef USING_YOLOV2_JSONPARSER
|
||||
#include <json_parser.h>
|
||||
#endif
|
||||
#include "region_layer.h"
|
||||
#define STACK_SIZE (128 * 1024)
|
||||
|
||||
static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX;
|
||||
|
||||
#define THREAD_PRIORITY_D (11)
|
||||
|
||||
static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX - 1;
|
||||
static _ioctl_shoot_para shoot_para_t = {0};
|
||||
|
||||
static pthread_t tid = 0;
|
||||
static void *thread_detect_entry(void *parameter);
|
||||
static int g_fd = 0;
|
||||
static int camera_fd = 0;
|
||||
static int kmodel_fd = 0;
|
||||
static int kpu_fd = 0;
|
||||
static int if_exit = 0;
|
||||
static unsigned char *showbuffer = NULL;
|
||||
static unsigned char *kpurgbbuffer = NULL;
|
||||
static int image_width = IMAGE_WIDTH;
|
||||
static int image_height = IMAGE_HEIGHT;
|
||||
|
||||
static _ioctl_shoot_para shoot_para_t = {0};
|
||||
unsigned char *model_data = NULL; // kpu data load memory
|
||||
unsigned char *model_data = NULL; // kpu data load memory
|
||||
unsigned char *model_data_align = NULL;
|
||||
|
||||
kpu_model_context_t detect_task;
|
||||
|
@ -29,6 +33,7 @@ volatile uint32_t g_ai_done_flag;
|
|||
|
||||
static void ai_done(void *ctx) { g_ai_done_flag = 1; }
|
||||
|
||||
|
||||
void k210_detect(char *json_file_path)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -36,45 +41,72 @@ void k210_detect(char *json_file_path)
|
|||
int size = 0;
|
||||
char kmodel_path[127] = {};
|
||||
|
||||
// open and parse from json file
|
||||
yolov2_params_t detect_params = param_parse(json_file_path);
|
||||
if (!detect_params.is_valid) {
|
||||
if (!detect_params.is_valid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_fd = open("/dev/ov2640", O_RDONLY);
|
||||
if (g_fd < 0) {
|
||||
printf("open ov2640 fail !!");
|
||||
#ifdef ADD_XIZI_FETURES
|
||||
kpu_fd = PrivOpen(KPU_DEV_DRIVER, O_RDONLY);
|
||||
if (camera_fd < 0)
|
||||
{
|
||||
printf("open %s fail !!", KPU_DEV_DRIVER);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("select camera device name:%s\n", CAMERA_DEV_DRIVER);
|
||||
camera_fd = PrivOpen(CAMERA_DEV_DRIVER, O_RDONLY);
|
||||
if (camera_fd < 0)
|
||||
{
|
||||
printf("open %s fail !!", CAMERA_DEV_DRIVER);
|
||||
return;
|
||||
}
|
||||
|
||||
// configure the resolution of camera
|
||||
_ioctl_set_reso set_dvp_reso = {detect_params.sensor_output_size[1], detect_params.sensor_output_size[0]};
|
||||
ioctl(g_fd, IOCTRL_CAMERA_OUT_SIZE_RESO, &set_dvp_reso);
|
||||
showbuffer =
|
||||
(unsigned char *)rt_malloc_align(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2, 64);
|
||||
if (NULL == showbuffer) {
|
||||
close(g_fd);
|
||||
printf("showbuffer apply memory fail !!");
|
||||
return;
|
||||
}
|
||||
kpurgbbuffer = (unsigned char *)rt_malloc_align(detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3, 64);
|
||||
if (NULL == kpurgbbuffer) {
|
||||
close(g_fd);
|
||||
rt_free_align(showbuffer);
|
||||
printf("kpurgbbuffer apply memory fail !!");
|
||||
return;
|
||||
}
|
||||
struct PrivIoctlCfg camera_cfg;
|
||||
camera_cfg.args = &set_dvp_reso;
|
||||
camera_cfg.ioctl_driver_type = CAMERA_TYPE;
|
||||
PrivIoctl(camera_fd, IOCTRL_CAMERA_OUT_SIZE_RESO, &camera_cfg);
|
||||
image_height = set_dvp_reso.height;
|
||||
image_width = set_dvp_reso.width;
|
||||
|
||||
// alloc the memory for camera and kpu running
|
||||
model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255);
|
||||
if (NULL == model_data) {
|
||||
rt_free_align(showbuffer);
|
||||
rt_free_align(kpurgbbuffer);
|
||||
close(g_fd);
|
||||
if (NULL == model_data)
|
||||
{
|
||||
free(showbuffer);
|
||||
free(kpurgbbuffer);
|
||||
PrivClose(camera_fd);
|
||||
printf("model_data apply memory fail !!");
|
||||
return;
|
||||
}
|
||||
showbuffer = (unsigned char *)malloc(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2);
|
||||
if (NULL == showbuffer)
|
||||
{
|
||||
PrivClose(camera_fd);
|
||||
printf("showbuffer apply memory fail !!");
|
||||
return;
|
||||
}
|
||||
kpurgbbuffer = (unsigned char *)malloc(detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3);
|
||||
if (NULL == kpurgbbuffer)
|
||||
{
|
||||
PrivClose(camera_fd);
|
||||
free(showbuffer);
|
||||
printf("kpurgbbuffer apply memory fail !!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
memset(model_data, 0, detect_params.kmodel_size + 255);
|
||||
memset(showbuffer, 0, detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2);
|
||||
memset(kpurgbbuffer, 0, detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3);
|
||||
shoot_para_t.pdata = (unsigned int *)(showbuffer);
|
||||
shoot_para_t.pdata = (uintptr_t)(showbuffer);
|
||||
shoot_para_t.length = (size_t)(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2);
|
||||
|
||||
/*
|
||||
load memory
|
||||
*/
|
||||
|
@ -83,83 +115,123 @@ void k210_detect(char *json_file_path)
|
|||
int idx_suffix_start = strlen(json_file_path) - 4;
|
||||
const char kmodel_suffix[7] = "kmodel";
|
||||
int kmodel_suffix_len = 6;
|
||||
while (kmodel_suffix_len--) {
|
||||
while (kmodel_suffix_len--)
|
||||
{
|
||||
kmodel_path[idx_suffix_start + 5 - kmodel_suffix_len] = kmodel_suffix[5 - kmodel_suffix_len];
|
||||
}
|
||||
printf("kmodel path: %s\n", kmodel_path);
|
||||
kmodel_fd = open(kmodel_path, O_RDONLY);
|
||||
if (kmodel_fd < 0) {
|
||||
unsigned char *model_data_align = (unsigned char *)(((uintptr_t)model_data + 255) & (~255));
|
||||
printf("model address:%x->%x\n", model_data_align, model_data_align + detect_params.kmodel_size);
|
||||
|
||||
kmodel_fd = PrivOpen(kmodel_path, O_RDONLY);
|
||||
|
||||
if (kmodel_fd < 0)
|
||||
{
|
||||
printf("open kmodel fail");
|
||||
close(g_fd);
|
||||
PrivClose(camera_fd);
|
||||
free(showbuffer);
|
||||
free(kpurgbbuffer);
|
||||
free(model_data);
|
||||
return;
|
||||
} else {
|
||||
size = read(kmodel_fd, model_data, detect_params.kmodel_size);
|
||||
if (size != detect_params.kmodel_size) {
|
||||
}
|
||||
else
|
||||
{
|
||||
size = PrivRead(kmodel_fd, model_data_align, detect_params.kmodel_size);
|
||||
if (size != detect_params.kmodel_size)
|
||||
{
|
||||
printf("read kmodel error size %d\n", size);
|
||||
close(g_fd);
|
||||
close(kmodel_fd);
|
||||
PrivClose(camera_fd);
|
||||
PrivClose(kmodel_fd);
|
||||
free(showbuffer);
|
||||
free(kpurgbbuffer);
|
||||
free(model_data);
|
||||
return;
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PrivClose(kmodel_fd);
|
||||
printf("read kmodel success \n");
|
||||
}
|
||||
}
|
||||
unsigned char *model_data_align = (unsigned char *)(((unsigned int)model_data + 255) & (~255));
|
||||
// dvp_set_ai_addr((uint32_t)kpurgbbuffer,
|
||||
// (uint32_t)(kpurgbbuffer + detect_params.net_input_size[0] * detect_params.net_input_size[1]),
|
||||
// (uint32_t)(kpurgbbuffer + detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2));
|
||||
|
||||
#ifdef ADD_RTTHREAD_FETURES
|
||||
dvp_set_ai_addr(
|
||||
(uint32_t)(kpurgbbuffer +
|
||||
detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0])),
|
||||
(uint32_t)(kpurgbbuffer +
|
||||
detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) +
|
||||
detect_params.net_input_size[0] * detect_params.net_input_size[1]),
|
||||
(uint32_t)(kpurgbbuffer +
|
||||
detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) +
|
||||
detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2));
|
||||
if (kpu_load_kmodel(&detect_task, model_data_align) != 0) {
|
||||
(uintptr_t)(kpurgbbuffer +
|
||||
detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0])),
|
||||
(uintptr_t)(kpurgbbuffer +
|
||||
detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) +
|
||||
detect_params.net_input_size[0] * detect_params.net_input_size[1]),
|
||||
(uintptr_t)(kpurgbbuffer +
|
||||
detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) +
|
||||
detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2));
|
||||
#else
|
||||
// Set AI buff address of Camera
|
||||
RgbAddress ai_address_preset;
|
||||
ai_address_preset.r_addr = (uintptr_t)kpurgbbuffer + detect_params.net_input_size[1];
|
||||
ai_address_preset.g_addr = ai_address_preset.r_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1];
|
||||
ai_address_preset.b_addr = ai_address_preset.g_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1];
|
||||
camera_cfg.args = &ai_address_preset;
|
||||
PrivIoctl(camera_fd, SET_AI_ADDR, &camera_cfg);
|
||||
#endif
|
||||
|
||||
// Load kmodel into kpu task
|
||||
#ifdef ADD_RTTHREAD_FETURES
|
||||
if (kpu_load_kmodel(&detect_task, model_data_align) != 0)
|
||||
{
|
||||
printf("\nmodel init error\n");
|
||||
close(g_fd);
|
||||
close(kmodel_fd);
|
||||
PrivClose(camera_fd);
|
||||
PrivClose(kmodel_fd);
|
||||
free(showbuffer);
|
||||
free(kpurgbbuffer);
|
||||
free(model_data);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
struct PrivIoctlCfg kpu_cfg;
|
||||
kpu_cfg.args = model_data_align;
|
||||
kpu_cfg.ioctl_driver_type = KPU_TYPE;
|
||||
if (PrivIoctl(kpu_fd,LOAD_KMODEL,&kpu_cfg) != 0)
|
||||
{
|
||||
printf("\nmodel init error\n");
|
||||
PrivClose(camera_fd);
|
||||
PrivClose(kmodel_fd);
|
||||
free(showbuffer);
|
||||
free(kpurgbbuffer);
|
||||
free(model_data);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
detect_rl.anchor_number = ANCHOR_NUM;
|
||||
detect_rl.anchor = detect_params.anchor;
|
||||
detect_rl.nms_value = detect_params.nms_thresh;
|
||||
detect_rl.classes = detect_params.class_num;
|
||||
result =
|
||||
region_layer_init(&detect_rl, detect_params.net_output_shape[0], detect_params.net_output_shape[1],
|
||||
detect_params.net_output_shape[2], detect_params.net_input_size[1], detect_params.net_input_size[0]);
|
||||
result = region_layer_init(&detect_rl, detect_params.net_output_shape[0], detect_params.net_output_shape[1],
|
||||
detect_params.net_output_shape[2], detect_params.net_input_size[1], detect_params.net_input_size[0]);
|
||||
printf("region_layer_init result %d \n\r", result);
|
||||
for (int idx = 0; idx < detect_params.class_num; idx++) {
|
||||
for (int idx = 0; idx < detect_params.class_num; idx++)
|
||||
{
|
||||
detect_rl.threshold[idx] = detect_params.obj_thresh[idx];
|
||||
}
|
||||
|
||||
size_t stack_size = STACK_SIZE;
|
||||
pthread_attr_t attr; /* 线程属性 */
|
||||
struct sched_param prio; /* 线程优先级 */
|
||||
prio.sched_priority = 8; /* 优先级设置为 8 */
|
||||
prio.sched_priority = THREAD_PRIORITY_D; /* 优先级设置为 11 */
|
||||
pthread_attr_init(&attr); /* 先使用默认值初始化属性 */
|
||||
pthread_attr_setschedparam(&attr, &prio); /* 修改属性对应的优先级 */
|
||||
pthread_attr_setstacksize(&attr, stack_size);
|
||||
|
||||
/* 创建线程 1, 属性为 attr,入口函数是 thread_entry,入口函数参数是 1 */
|
||||
result = pthread_create(&tid, &attr, thread_detect_entry, &detect_params);
|
||||
if (0 == result) {
|
||||
if (0 == result)
|
||||
{
|
||||
printf("thread_detect_entry successfully!\n");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("thread_detect_entry failed! error code is %d\n", result);
|
||||
close(g_fd);
|
||||
PrivClose(camera_fd);
|
||||
}
|
||||
}
|
||||
// #ifdef __RT_THREAD_H__
|
||||
|
@ -168,39 +240,93 @@ void k210_detect(char *json_file_path)
|
|||
|
||||
static void *thread_detect_entry(void *parameter)
|
||||
{
|
||||
#ifdef BSP_USING_LCD
|
||||
int lcd_fd = PrivOpen(KPU_LCD_DEV_DRIVER, O_RDWR);
|
||||
if (lcd_fd < 0)
|
||||
{
|
||||
printf("open lcd fd error:%d\n", lcd_fd);
|
||||
}
|
||||
LcdWriteParam graph_param;
|
||||
graph_param.type = LCD_DOT_TYPE;
|
||||
for (int i = 0; i < LCD_SIZE; i++)
|
||||
{
|
||||
graph_param.pixel_info.pixel_color = (uint16_t *)showbuffer;
|
||||
graph_param.pixel_info.x_startpos = 0;
|
||||
graph_param.pixel_info.y_startpos = i;
|
||||
graph_param.pixel_info.x_endpos = LCD_SIZE - 1;
|
||||
graph_param.pixel_info.y_endpos = graph_param.pixel_info.y_startpos;
|
||||
PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER);
|
||||
}
|
||||
#endif
|
||||
|
||||
yolov2_params_t detect_params = *(yolov2_params_t *)parameter;
|
||||
extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t * ptr);
|
||||
struct PrivIoctlCfg camera_cfg;
|
||||
camera_cfg.ioctl_driver_type = CAMERA_TYPE;
|
||||
|
||||
printf("thread_detect_entry start!\n");
|
||||
int ret = 0;
|
||||
// sysctl_enable_irq();
|
||||
while (1) {
|
||||
// memset(showbuffer,0,320*240*2);
|
||||
while (1)
|
||||
{
|
||||
g_ai_done_flag = 0;
|
||||
ret = ioctl(g_fd, IOCTRL_CAMERA_START_SHOT, &shoot_para_t);
|
||||
if (RT_ERROR == ret) {
|
||||
|
||||
// get a graph map from camera
|
||||
camera_cfg.args = &shoot_para_t;
|
||||
ret = PrivIoctl(camera_fd, IOCTRL_CAMERA_START_SHOT, &camera_cfg);
|
||||
if (EOF == ret)
|
||||
{
|
||||
printf("ov2640 can't wait event flag");
|
||||
rt_free(showbuffer);
|
||||
close(g_fd);
|
||||
free(showbuffer);
|
||||
PrivClose(camera_fd);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
if (dmalock_sync_take(&dma_ch, 2000)) {
|
||||
|
||||
int shoot_flag = 0;
|
||||
camera_cfg.args = (int *)&shoot_flag;
|
||||
PrivIoctl(camera_fd, FLAG_CHECK, &camera_cfg);
|
||||
while (shoot_flag == 2)
|
||||
PrivIoctl(camera_fd, FLAG_CHECK, &camera_cfg);
|
||||
|
||||
#ifdef ADD_RTTHREAD_FETURES
|
||||
if (dmalock_sync_take(&dma_ch, 2000))
|
||||
{
|
||||
printf("Fail to take DMA channel");
|
||||
}
|
||||
kpu_run_kmodel(&detect_task, kpurgbbuffer, DMAC_CHANNEL5, ai_done, NULL);
|
||||
while (!g_ai_done_flag)
|
||||
;
|
||||
dmalock_release(dma_ch);
|
||||
#elif defined ADD_XIZI_FETURES
|
||||
struct PrivIoctlCfg kpu_cfg;
|
||||
kpu_cfg.args = kpurgbbuffer;
|
||||
kpu_cfg.ioctl_driver_type = KPU_TYPE;
|
||||
PrivIoctl(kpu_fd,RUN_KMODEL,&kpu_cfg);
|
||||
|
||||
int wait_flag=0;
|
||||
kpu_cfg.args = &wait_flag;
|
||||
while (0==wait_flag){
|
||||
PrivIoctl(kpu_fd,WAIT_FLAG,&kpu_cfg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ADD_RTTHREAD_FETURES
|
||||
float *output;
|
||||
size_t output_size;
|
||||
kpu_get_output(&detect_task, 0, (uint8_t **)&output, &output_size);
|
||||
detect_rl.input = output;
|
||||
#else
|
||||
KpuOutputBuffer output_buffer;
|
||||
kpu_cfg.args = &output_buffer;
|
||||
PrivIoctl(kpu_fd,GET_OUTPUT,&kpu_cfg);
|
||||
detect_rl.input = (float*)(output_buffer.buffer);
|
||||
#endif
|
||||
region_layer_run(&detect_rl, &detect_info);
|
||||
printf("detect_info.obj_number:%d\n", detect_info.obj_number);
|
||||
/* display result */
|
||||
|
||||
for (int cnt = 0; cnt < detect_info.obj_number; cnt++) {
|
||||
detect_info.obj[cnt].y1 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0])/2;
|
||||
detect_info.obj[cnt].y2 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0])/2;
|
||||
for (int cnt = 0; cnt < detect_info.obj_number; cnt++)
|
||||
{
|
||||
detect_info.obj[cnt].y1 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0]) / 2;
|
||||
detect_info.obj[cnt].y2 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0]) / 2;
|
||||
draw_edge((uint32_t *)showbuffer, &detect_info, cnt, 0xF800, (uint16_t)detect_params.sensor_output_size[1],
|
||||
(uint16_t)detect_params.sensor_output_size[0]);
|
||||
printf("%d: (%d, %d, %d, %d) cls: %s conf: %f\t", cnt, detect_info.obj[cnt].x1, detect_info.obj[cnt].y1,
|
||||
|
@ -208,13 +334,29 @@ static void *thread_detect_entry(void *parameter)
|
|||
detect_info.obj[cnt].prob);
|
||||
}
|
||||
#ifdef BSP_USING_LCD
|
||||
|
||||
#ifdef ADD_RTTHREAD_FETURES
|
||||
extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t * ptr);
|
||||
lcd_draw_picture(0, 0, (uint16_t)detect_params.sensor_output_size[1] - 1,
|
||||
(uint16_t)detect_params.sensor_output_size[0] - 1, (uint32_t *)showbuffer);
|
||||
// lcd_show_image(0, 0, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0],
|
||||
// (unsigned int *)showbuffer);
|
||||
#else
|
||||
// refresh the LCD using photo of camera
|
||||
for (int i = 0; i < image_height; i++)
|
||||
{
|
||||
graph_param.pixel_info.pixel_color = (uint16_t *)showbuffer + (image_height-i-1) * image_width;
|
||||
graph_param.pixel_info.x_startpos = (LCD_SIZE - image_width) / 2;
|
||||
graph_param.pixel_info.y_startpos = i + (LCD_SIZE - image_height) / 2;
|
||||
graph_param.pixel_info.x_endpos = LCD_SIZE - 1 - (LCD_SIZE - image_width) / 2;
|
||||
graph_param.pixel_info.y_endpos = graph_param.pixel_info.y_startpos;
|
||||
PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER);
|
||||
}
|
||||
#endif
|
||||
usleep(500);
|
||||
if (1 == if_exit) {
|
||||
|
||||
#endif
|
||||
if (1 == if_exit)
|
||||
{
|
||||
if_exit = 0;
|
||||
printf("thread_detect_entry exit");
|
||||
pthread_exit(NULL);
|
||||
|
@ -224,10 +366,11 @@ static void *thread_detect_entry(void *parameter)
|
|||
|
||||
void detect_delete()
|
||||
{
|
||||
if (showbuffer != NULL) {
|
||||
if (showbuffer != NULL)
|
||||
{
|
||||
int ret = 0;
|
||||
close(g_fd);
|
||||
close(kmodel_fd);
|
||||
PrivClose(camera_fd);
|
||||
PrivClose(kmodel_fd);
|
||||
free(showbuffer);
|
||||
free(kpurgbbuffer);
|
||||
free(model_data);
|
||||
|
@ -235,46 +378,3 @@ void detect_delete()
|
|||
if_exit = 1;
|
||||
}
|
||||
}
|
||||
// #ifdef __RT_THREAD_H__
|
||||
// MSH_CMD_EXPORT(detect_delete, detect task delete);
|
||||
// #endif
|
||||
|
||||
// void kmodel_load(unsigned char *model_data)
|
||||
// {
|
||||
// int kmodel_fd = 0;
|
||||
// int size = 0;
|
||||
// char kmodel_path[127] = {};
|
||||
// // kmodel path generate from json file path, *.json -> *.kmodel
|
||||
// memcpy(kmodel_path, json_file_path, strlen(json_file_path));
|
||||
// int idx_suffix_start = strlen(json_file_path) - 4;
|
||||
// const char kmodel_suffix[5] = "kmodel";
|
||||
// int kmodel_suffix_len = 5;
|
||||
// while (kmodel_suffix_len--) {
|
||||
// kmodel_path[idx_suffix_start + 4 - kmodel_suffix_len] = kmodel_suffix[4 - kmodel_suffix_len];
|
||||
// }
|
||||
// printf("Kmodel path: %s\n", kmodel_path);
|
||||
// kmodel_fd = open(kmodel_path, O_RDONLY);
|
||||
|
||||
// model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255);
|
||||
// if (NULL == model_data) {
|
||||
// printf("model_data apply memory fail !!");
|
||||
// return;
|
||||
// }
|
||||
// memset(model_data, 0, detect_params.kmodel_size + 255);
|
||||
|
||||
// if (kmodel_fd >= 0) {
|
||||
// size = read(kmodel_fd, model_data, detect_params.kmodel_size);
|
||||
// if (size != detect_params.kmodel_size) {
|
||||
// printf("read kmodel error size %d\n", size);
|
||||
|
||||
// } else {
|
||||
// printf("read kmodel success");
|
||||
// }
|
||||
// } else {
|
||||
// free(model_data);
|
||||
// printf("open kmodel fail");
|
||||
// }
|
||||
// }
|
||||
// #ifdef __RT_THREAD_H__
|
||||
// MSH_CMD_EXPORT(kmodel_load, kmodel load memory);
|
||||
// #endif
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#ifndef _K210_DETECT_H_
|
||||
#define _K210_DETECT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <transform.h>
|
||||
#include "sleep.h"
|
||||
|
||||
void k210_detect(char *json_file_path);
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
SRC_FILES := region_layer.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
@ -224,7 +224,7 @@ static void get_region_boxes(region_layer_t *rl, float *predictions, float **pro
|
|||
correct_region_boxes(rl, boxes);
|
||||
}
|
||||
|
||||
static int nms_comparator(void *pa, void *pb)
|
||||
static int nms_comparator(const void *pa,const void *pb)
|
||||
{
|
||||
sortable_box_t a = *(sortable_box_t *)pa;
|
||||
sortable_box_t b = *(sortable_box_t *)pb;
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
SRC_FILES := json_parser.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
#include "json_parser.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
// #include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <transform.h>
|
||||
|
||||
#include "cJSON.h"
|
||||
|
||||
|
@ -31,9 +34,9 @@ yolov2_params_t param_parse(char *json_file_path)
|
|||
} else {
|
||||
printf("Reading config from: %s\n", json_file_path);
|
||||
}
|
||||
|
||||
read(fin, buffer, sizeof(buffer));
|
||||
close(fin);
|
||||
|
||||
// read json string
|
||||
json_obj = cJSON_Parse(buffer);
|
||||
// free(buffer);
|
||||
|
|
|
@ -22,6 +22,14 @@ config SENSOR_QS_FX
|
|||
default "/dev/uart2_dev2"
|
||||
depends on !SENSOR_QS_FX_DRIVER_EXTUART
|
||||
|
||||
config SENSOR_DEVICE_QS_FX_PIN_DEV
|
||||
string "qs-fx pin device name"
|
||||
default "/dev/pin_dev"
|
||||
|
||||
config SENSOR_DEVICE_QS_FX_PIN_NUMBER
|
||||
int "qs-fx pin device number"
|
||||
default 24
|
||||
|
||||
if SENSOR_QS_FX_DRIVER_EXTUART
|
||||
config SENSOR_DEVICE_QS_FX_DEV
|
||||
string "qs-fx device extra uart path"
|
||||
|
|
|
@ -53,6 +53,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev)
|
|||
cfg.serial_parity_mode = PARITY_NONE;
|
||||
cfg.serial_bit_order = 0;
|
||||
cfg.serial_invert_mode = 0;
|
||||
cfg.serial_timeout = 1000;
|
||||
cfg.is_ext_uart = 0;
|
||||
#ifdef SENSOR_QS_FX_DRIVER_EXTUART
|
||||
cfg.is_ext_uart = 1;
|
||||
|
@ -66,7 +67,34 @@ static int SensorDeviceOpen(struct SensorDevice *sdev)
|
|||
result = PrivIoctl(sdev->fd, OPE_INT, &ioctl_cfg);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static int PinOpen(void){
|
||||
int pin_fd = PrivOpen(SENSOR_DEVICE_QS_FX_PIN_DEV, O_RDWR);
|
||||
if (pin_fd < 0) {
|
||||
printf("open %s error\n", SENSOR_DEVICE_QS_FX_PIN_DEV);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//config led pin in board
|
||||
struct PinParam pin_parameter;
|
||||
memset(&pin_parameter, 0, sizeof(struct PinParam));
|
||||
pin_parameter.cmd = GPIO_CONFIG_MODE;
|
||||
pin_parameter.pin = SENSOR_DEVICE_QS_FX_PIN_NUMBER;
|
||||
pin_parameter.mode = GPIO_CFG_OUTPUT;
|
||||
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
ioctl_cfg.ioctl_driver_type = PIN_TYPE;
|
||||
ioctl_cfg.args = (void *)&pin_parameter;
|
||||
|
||||
if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) {
|
||||
printf("ioctl pin fd error %d\n", pin_fd);
|
||||
PrivClose(pin_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pin_fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Read sensor device
|
||||
|
@ -76,12 +104,25 @@ static int SensorDeviceOpen(struct SensorDevice *sdev)
|
|||
*/
|
||||
static int SensorDeviceRead(struct SensorDevice *sdev, size_t len)
|
||||
{
|
||||
int pin_fd=PinOpen();
|
||||
struct PinStat pin_dir;
|
||||
pin_dir.pin = SENSOR_DEVICE_QS_FX_PIN_NUMBER;
|
||||
|
||||
pin_dir.val = GPIO_HIGH;
|
||||
if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-up pin to configure as tx mode
|
||||
return -1;
|
||||
PrivTaskDelay(20);
|
||||
if (PrivWrite(sdev->fd, instructions, sizeof(instructions)) < 0)
|
||||
return -1;
|
||||
|
||||
PrivTaskDelay(20);
|
||||
pin_dir.val = GPIO_LOW;
|
||||
if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-down pin to configure as rx mode
|
||||
return -1;
|
||||
|
||||
if (PrivRead(sdev->fd, sdev->buffer, len) < 0)
|
||||
return -1;
|
||||
|
||||
PrivClose(pin_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -124,7 +165,10 @@ static int32_t ReadWindDirection(struct SensorQuantity *quant)
|
|||
short result;
|
||||
if (quant->sdev->done->read != NULL) {
|
||||
if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) {
|
||||
quant->sdev->done->read(quant->sdev, 6);
|
||||
quant->sdev->done->read(quant->sdev, 7);
|
||||
if(Crc16(quant->sdev->buffer,7)!=0x00){
|
||||
return -1;
|
||||
}
|
||||
result = (quant->sdev->buffer[3] << 8) | quant->sdev->buffer[4];
|
||||
|
||||
return (int32_t)result;
|
||||
|
|
|
@ -19,9 +19,17 @@ config SENSOR_QS_FS
|
|||
|
||||
config SENSOR_DEVICE_QS_FS_DEV
|
||||
string "qs-fx device name"
|
||||
default "/dev/uart2_dev2"
|
||||
default "/dev/uart1_dev1"
|
||||
depends on !SENSOR_QS_FS_DRIVER_EXTUART
|
||||
|
||||
config SENSOR_DEVICE_QS_FS_PIN_DEV
|
||||
string "qs-fx pin device name"
|
||||
default "/dev/pin_dev"
|
||||
|
||||
config SENSOR_DEVICE_QS_FS_PIN_NUMBER
|
||||
int "qs-fs pin device number"
|
||||
default 24
|
||||
|
||||
if SENSOR_QS_FS_DRIVER_EXTUART
|
||||
config SENSOR_DEVICE_QS_FS_DEV
|
||||
string "qs-fx device extra uart path"
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <sensor.h>
|
||||
|
||||
static struct SensorDevice qs_fs;
|
||||
static const unsigned char instructions[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A};
|
||||
static const unsigned char instructions[] = {0x02,0x03,0x00,0x00,0x00,0x01,0x84,0x39};
|
||||
|
||||
static struct SensorProductInfo info =
|
||||
{
|
||||
|
@ -68,6 +68,34 @@ static int SensorDeviceOpen(struct SensorDevice *sdev)
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int PinOpen(void){
|
||||
int pin_fd = PrivOpen(SENSOR_DEVICE_QS_FS_PIN_DEV, O_RDWR);
|
||||
if (pin_fd < 0) {
|
||||
printf("open %s error\n", SENSOR_DEVICE_QS_FS_PIN_DEV);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//config led pin in board
|
||||
struct PinParam pin_parameter;
|
||||
memset(&pin_parameter, 0, sizeof(struct PinParam));
|
||||
pin_parameter.cmd = GPIO_CONFIG_MODE;
|
||||
pin_parameter.pin = SENSOR_DEVICE_QS_FS_PIN_NUMBER;
|
||||
pin_parameter.mode = GPIO_CFG_OUTPUT;
|
||||
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
ioctl_cfg.ioctl_driver_type = PIN_TYPE;
|
||||
ioctl_cfg.args = (void *)&pin_parameter;
|
||||
|
||||
if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) {
|
||||
printf("ioctl pin fd error %d\n", pin_fd);
|
||||
PrivClose(pin_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pin_fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Read sensor device
|
||||
* @param sdev - sensor device pointer
|
||||
|
@ -76,12 +104,27 @@ static int SensorDeviceOpen(struct SensorDevice *sdev)
|
|||
*/
|
||||
static int SensorDeviceRead(struct SensorDevice *sdev, size_t len)
|
||||
{
|
||||
int pin_fd=PinOpen();
|
||||
struct PinStat pin_dir;
|
||||
pin_dir.pin = SENSOR_DEVICE_QS_FS_PIN_NUMBER;
|
||||
|
||||
pin_dir.val = GPIO_HIGH;
|
||||
if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-up pin to configure as tx mode
|
||||
return -1;
|
||||
PrivTaskDelay(20);
|
||||
if (PrivWrite(sdev->fd, instructions, sizeof(instructions)) < 0)
|
||||
return -1;
|
||||
PrivTaskDelay(20);
|
||||
|
||||
|
||||
pin_dir.val = GPIO_LOW;
|
||||
if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-down pin to configure as rx mode
|
||||
return -1;
|
||||
|
||||
if (PrivRead(sdev->fd, sdev->buffer, len) < 0)
|
||||
return -1;
|
||||
|
||||
PrivClose(pin_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -124,7 +167,10 @@ static int32_t ReadWindSpeed(struct SensorQuantity *quant)
|
|||
short result;
|
||||
if (quant->sdev->done->read != NULL) {
|
||||
if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) {
|
||||
quant->sdev->done->read(quant->sdev, 6);
|
||||
quant->sdev->done->read(quant->sdev, 7);
|
||||
if(Crc16(quant->sdev->buffer,7)!=0x00){
|
||||
return -1;
|
||||
}
|
||||
result = (quant->sdev->buffer[3] << 8) | quant->sdev->buffer[4];
|
||||
|
||||
return (int32_t)result;
|
||||
|
|
|
@ -104,7 +104,7 @@ int PrivTaskDelay(int32_t ms)
|
|||
#ifndef SEPARATE_COMPILE
|
||||
uint32_t PrivGetTickTime()
|
||||
{
|
||||
return CalculteTimeMsFromTick(CurrentTicksGain());
|
||||
return CalculateTimeMsFromTick(CurrentTicksGain());
|
||||
}
|
||||
#endif
|
||||
/*********************fs**************************/
|
||||
|
@ -154,7 +154,6 @@ int PrivIoctl(int fd, int cmd, void *args)
|
|||
{
|
||||
int ret;
|
||||
struct PrivIoctlCfg *ioctl_cfg = (struct PrivIoctlCfg *)args;
|
||||
|
||||
switch (ioctl_cfg->ioctl_driver_type)
|
||||
{
|
||||
case SERIAL_TYPE:
|
||||
|
@ -163,17 +162,16 @@ int PrivIoctl(int fd, int cmd, void *args)
|
|||
case PIN_TYPE:
|
||||
ret = PrivPinIoctl(fd, cmd, ioctl_cfg->args);
|
||||
break;
|
||||
case I2C_TYPE:
|
||||
ret = ioctl(fd, cmd, ioctl_cfg->args);
|
||||
break;
|
||||
case LCD_TYPE:
|
||||
ret = PrivLcdIoctl(fd, cmd, ioctl_cfg->args);
|
||||
break;
|
||||
case I2C_TYPE:
|
||||
case RTC_TYPE:
|
||||
case ADC_TYPE:
|
||||
case DAC_TYPE:
|
||||
case WDT_TYPE:
|
||||
case CAMERA_TYPE:
|
||||
case KPU_TYPE:
|
||||
ret = ioctl(fd, cmd, ioctl_cfg->args);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -151,6 +151,7 @@ enum IoctlDriverType
|
|||
WDT_TYPE,
|
||||
RTC_TYPE,
|
||||
CAMERA_TYPE,
|
||||
KPU_TYPE,
|
||||
DEFAULT_TYPE,
|
||||
};
|
||||
|
||||
|
@ -227,6 +228,36 @@ struct RtcDrvConfigureParam
|
|||
time_t *time;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uintptr_t pdata;
|
||||
uint32_t length;
|
||||
}_ioctl_shoot_para;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t width; // width The width of image
|
||||
uint32_t height; // height The height of image
|
||||
}_ioctl_set_reso;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uintptr_t r_addr;
|
||||
uintptr_t g_addr;
|
||||
uintptr_t b_addr;
|
||||
}RgbAddress;
|
||||
|
||||
enum TCP_OPTION {
|
||||
SEND_DATA = 0,
|
||||
RECV_DATA,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *buffer;
|
||||
size_t length;
|
||||
}KpuOutputBuffer;
|
||||
|
||||
#define PRIV_SYSTICK_GET (CurrentTicksGain())
|
||||
#define PRIV_LCD_DEV "/dev/lcd_dev"
|
||||
#define MY_DISP_HOR_RES BSP_LCD_Y_MAX
|
||||
|
@ -236,6 +267,35 @@ struct RtcDrvConfigureParam
|
|||
#define MY_INDEV_X BSP_LCD_Y_MAX
|
||||
#define MY_INDEV_Y BSP_LCD_X_MAX
|
||||
|
||||
#define LCD_STRING_TYPE 0
|
||||
#define LCD_DOT_TYPE 1
|
||||
#define LCD_SIZE 320
|
||||
#define IMAGE_HEIGHT 240
|
||||
#define IMAGE_WIDTH 320
|
||||
#define NULL_PARAMETER 0
|
||||
|
||||
#define REG_SCCB_READ 0xA2U
|
||||
#define REG_SCCB_WRITE 0xA3U
|
||||
#define SCCB_REG_LENGTH 0x08U
|
||||
|
||||
#define SET_DISPLAY_ADDR (0xD1)
|
||||
#define SET_AI_ADDR (0xD2)
|
||||
#define FLAG_CHECK (0xD4)
|
||||
|
||||
#define LOAD_KMODEL 0xA0
|
||||
#define RUN_KMODEL 0xA1
|
||||
#define GET_OUTPUT 0xA2
|
||||
#define WAIT_FLAG 0xA3
|
||||
|
||||
#define IOCTRL_CAMERA_START_SHOT (22) // start shoot
|
||||
#define IOCTRL_CAMERA_OUT_SIZE_RESO (23)
|
||||
#define IOCTRL_CAMERA_SET_WINDOWS_SIZE (21) // user set specific windows outsize
|
||||
#define IOCTRL_CAMERA_SET_LIGHT (24) //set light mode
|
||||
#define IOCTRL_CAMERA_SET_COLOR (25) //set color saturation
|
||||
#define IOCTRL_CAMERA_SET_BRIGHTNESS (26) //set color brightness
|
||||
#define IOCTRL_CAMERA_SET_CONTRAST (27) //set contrast
|
||||
#define IOCTRL_CAMERA_SET_EFFECT (28) //set effect
|
||||
#define IOCTRL_CAMERA_SET_EXPOSURE (29) //set auto exposure
|
||||
/*********************shell***********************/
|
||||
//for int func(int argc, char *agrv[])
|
||||
#define PRIV_SHELL_CMD_MAIN_ATTR (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN))
|
||||
|
|
|
@ -73,6 +73,12 @@ typedef int pid_t;
|
|||
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));
|
||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine)(void *), void *arg);
|
||||
int pthread_attr_init(pthread_attr_t *attr);
|
||||
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size);
|
||||
int pthread_attr_setschedparam(pthread_attr_t *attr,struct sched_param const *param);
|
||||
int pthread_attr_setstack(pthread_attr_t *attr,
|
||||
void *stack_base,
|
||||
size_t stack_size);
|
||||
void pthread_exit(void *value_ptr);
|
||||
int pthread_detach(pthread_t thread);
|
||||
int pthread_join(pthread_t thread, void **retval);
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
#include <stdio.h>
|
||||
#include "include/pthread.h"
|
||||
|
||||
#define DEFAULT_STACK_SIZE 2048
|
||||
#define DEFAULT_PRIORITY (KTASK_PRIORITY_MAX/2 + KTASK_PRIORITY_MAX/4)
|
||||
|
||||
|
||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine)(void *), void *arg)
|
||||
{
|
||||
|
@ -55,6 +59,28 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
|||
|
||||
}
|
||||
|
||||
int pthread_attr_init(pthread_attr_t *attr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setschedparam(pthread_attr_t *attr,
|
||||
struct sched_param const *param)
|
||||
{
|
||||
NULL_PARAM_CHECK(attr != NULL);
|
||||
NULL_PARAM_CHECK(param != NULL);
|
||||
|
||||
attr->schedparam.sched_priority = param->sched_priority;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size)
|
||||
{
|
||||
attr->stacksize = stack_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pthread_exit(void *value_ptr){
|
||||
//todo add exit value
|
||||
UserTaskQuit();
|
||||
|
|
|
@ -71,6 +71,5 @@ int hc32_bringup(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
printf("start %s\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -86,8 +86,8 @@ extern "C"
|
|||
|
||||
#define NR_IRQS (144 + 15)
|
||||
|
||||
#define NVIC_SYSH_PRIORITY_MIN 0xf0
|
||||
#define NVIC_SYSH_PRIORITY_DEFAULT 0x80
|
||||
#define NVIC_SYSH_PRIORITY_MIN 0U// 0xf0
|
||||
#define NVIC_SYSH_PRIORITY_DEFAULT 0U //0x80
|
||||
#define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_PRIORITY_DEFAULT
|
||||
|
||||
#define ARMV7M_PERIPHERAL_INTERRUPTS NR_IRQS
|
||||
|
|
|
@ -181,10 +181,27 @@ config HC32_SPI1
|
|||
config HC32_SPI2
|
||||
bool "SPI2"
|
||||
default n
|
||||
depends on HC32_HAVE_SPI2
|
||||
select SPI
|
||||
select HC32_SPI
|
||||
|
||||
config HC32_I2C1
|
||||
bool "I2C1"
|
||||
default n
|
||||
select I2C
|
||||
select HC32_I2C
|
||||
|
||||
config HC32_I2C2
|
||||
bool "I2C2"
|
||||
default n
|
||||
select I2C
|
||||
select HC32_I2C
|
||||
|
||||
config HC32_I2C3
|
||||
bool "I2C3"
|
||||
default n
|
||||
select I2C
|
||||
select HC32_I2C
|
||||
|
||||
|
||||
config HC32_SPI
|
||||
bool
|
||||
|
|
|
@ -86,9 +86,11 @@ CHIP_CSRCS += hc32_console.c
|
|||
|
||||
CHIP_CSRCS += hc32f4a0_clk.c hc32f4a0_efm.c hc32f4a0_gpio.c
|
||||
CHIP_CSRCS += hc32f4a0_interrupts.c hc32f4a0_usart.c hc32f4a0_utility.c
|
||||
CHIP_CSRCS += hc32f4a0_sram.c hc32f4a0_pwc.c
|
||||
CHIP_CSRCS += hc32f4a0_sram.c hc32f4a0_pwc.c hc32f4a0_i2c.c
|
||||
|
||||
CHIP_CSRCS += hc32f4a0_spi.c
|
||||
|
||||
CHIP_CSRCS += hc32_spiflash.c hc32_spi.c
|
||||
|
||||
CHIP_CSRCS += hc32_i2c.c
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include "hc32_uart.h"
|
||||
#include "hc32_spi.h"
|
||||
|
||||
#define CMP_STR(_tar, _str) (strncmp(_tar, _str, strlen(_str)) == 0)
|
||||
extern int hc32_i2c_test(void);
|
||||
|
||||
void hc32_test_console(void)
|
||||
{
|
||||
char *dev_str = "/dev/console";
|
||||
|
@ -31,16 +34,44 @@ void hc32_test_console(void)
|
|||
close(fd);
|
||||
}
|
||||
|
||||
void hc32_bmp180_test(void)
|
||||
{
|
||||
char *bmp_dev = "/dev/bmp180";
|
||||
char write_arr[] = {0xF4, 0x2E};
|
||||
int fd = 0, ret;
|
||||
|
||||
fd = open(bmp_dev, 0x6);
|
||||
ret = write(fd, write_arr, 2);
|
||||
hc32_print("%s: write attr ret %x\n", __func__, ret);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void hc32_console_handle(char *buf)
|
||||
{
|
||||
if(strncmp(buf, "console", 7) == 0)
|
||||
if(CMP_STR(buf, "console"))
|
||||
{
|
||||
hc32_test_console();
|
||||
}
|
||||
else if(strncmp(buf, "spi", 7) == 0)
|
||||
else if(CMP_STR(buf, "spi"))
|
||||
{
|
||||
hc32_print("start flash test ...\n");
|
||||
hc32_print("start flash test %d ...\n", g_system_timer);
|
||||
hc32_spiflash_test();
|
||||
}
|
||||
else if(CMP_STR(buf, "i2c"))
|
||||
{
|
||||
hc32_print("start i2c test %d ...\n", g_system_timer);
|
||||
hc32_i2c_test();
|
||||
}
|
||||
else if(CMP_STR(buf, "bmp"))
|
||||
{
|
||||
hc32_print("start bmp180 test ...\n");
|
||||
hc32_bmp180_test();
|
||||
}
|
||||
else if(CMP_STR(buf, "pr"))
|
||||
{
|
||||
printf("z\n");
|
||||
hc32_print("start pr test %d ...\n", g_system_timer);
|
||||
printf("b\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
/****************************************************************************
|
||||
* Pre-Processor Declarations
|
||||
****************************************************************************/
|
||||
typedef uint32_t gpio_pinset_t;
|
||||
|
||||
#define GPIO_OUTPUT_SET (1 << 25) /* Bit 8: If output, initial value of output */
|
||||
#define GPIO_OUTPUT_CLEAR (0)
|
||||
|
||||
|
|
844
Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_i2c.c
Executable file
844
Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_i2c.c
Executable file
|
@ -0,0 +1,844 @@
|
|||
/**
|
||||
*******************************************************************************
|
||||
* @file i2c/i2c_master_polling/source/main.c
|
||||
* @brief Main program of I2C master polling for the Device Driver Library.
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2020-06-12 Hexiao First version
|
||||
2020-08-31 Hexiao Modify I2C init flow
|
||||
2020-09-04 Hexiao Modify compile warning
|
||||
2021-01-21 Hexiao Replace PWC_FCG1_IIC1 with PWC_FCG1_I2C1
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by HDSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
#include "hc32_ddl.h"
|
||||
#include "hc32_gpio.h"
|
||||
#include "hc32_uart.h"
|
||||
|
||||
/**
|
||||
* @addtogroup HC32F4A0_DDL_Examples
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup I2C_Master_Polling
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
/* Define slave device address for example */
|
||||
#define DEVICE_ADDRESS (0x77U) //bmp180
|
||||
/* Define port and pin for SDA and SCL */
|
||||
#define I2C_SCL_PORT (GPIO_PORT_D)
|
||||
#define I2C_SCL_PIN (GPIO_PIN_03)
|
||||
#define I2C_SDA_PORT (GPIO_PORT_F)
|
||||
#define I2C_SDA_PIN (GPIO_PIN_10)
|
||||
|
||||
#define I2C_RET_OK (0U)
|
||||
#define I2C_RET_ERROR (1U)
|
||||
|
||||
#define GENERATE_START (0x00U)
|
||||
#define GENERATE_RESTART (0x01U)
|
||||
|
||||
#define ADDRESS_W (0x00U)
|
||||
#define ADDRESS_R (0x01U)
|
||||
|
||||
/* Define Write and read data length for the example */
|
||||
#define TEST_DATA_LEN (1U)
|
||||
/* Define i2c baudrate */
|
||||
#define I2C_BAUDRATE (400000UL)
|
||||
|
||||
//#define LED_GREEN_PORT (GPIO_PORT_I)
|
||||
//#define LED_GREEN_PIN (GPIO_PIN_03)
|
||||
|
||||
#define I2C_MASTER 1
|
||||
#define I2C_SLAVE 2
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
|
||||
/* I2C Device hardware configuration */
|
||||
|
||||
struct hc32_i2c_config_s
|
||||
{
|
||||
M4_I2C_TypeDef *base; /* I2C base address */
|
||||
gpio_pinset_t scl_pin; /* GPIO configuration for SCL as SCL */
|
||||
gpio_pinset_t sda_pin; /* GPIO configuration for SDA as SDA */
|
||||
uint8_t mode; /* Master or Slave mode */
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
uint32_t irq; /* Event IRQ */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* I2C Device Private Data */
|
||||
|
||||
struct hc32_i2c_priv_s
|
||||
{
|
||||
/* Standard I2C operations */
|
||||
|
||||
const struct i2c_ops_s *ops;
|
||||
|
||||
/* Port configuration */
|
||||
|
||||
const struct hc32_i2c_config_s *config;
|
||||
|
||||
int refs; /* Reference count */
|
||||
sem_t sem_excl; /* Mutual exclusion semaphore */
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
sem_t sem_isr; /* Interrupt wait semaphore */
|
||||
#endif
|
||||
volatile uint8_t intstate; /* Interrupt handshake (see enum hc32_intstate_e) */
|
||||
|
||||
uint8_t msgc; /* Message count */
|
||||
struct i2c_msg_s *msgv; /* Message list */
|
||||
uint8_t *ptr; /* Current message buffer */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
int dcnt; /* Current message length */
|
||||
uint16_t flags; /* Current message flags */
|
||||
|
||||
uint32_t status; /* End of transfer SR2|SR1 status */
|
||||
};
|
||||
|
||||
static int hc32_i2c_init(FAR struct hc32_i2c_priv_s *priv);
|
||||
static int hc32_i2c_deinit(FAR struct hc32_i2c_priv_s *priv);
|
||||
static int hc32_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
static int hc32_i2c_reset(FAR struct i2c_master_s *dev);
|
||||
#endif
|
||||
|
||||
/* I2C interface */
|
||||
|
||||
static const struct i2c_ops_s hc32_i2c_ops =
|
||||
{
|
||||
.transfer = hc32_i2c_transfer
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
, .reset = hc32_i2c_reset
|
||||
#endif
|
||||
};
|
||||
|
||||
/* I2C device structures */
|
||||
|
||||
#ifdef CONFIG_HC32_I2C1
|
||||
static const struct hc32_i2c_config_s hc32_i2c1_config =
|
||||
{
|
||||
.base = M4_I2C1,
|
||||
.scl_pin = GPIO_PINSET(I2C_SCL_PORT, I2C_SCL_PIN),
|
||||
.sda_pin = GPIO_PINSET(I2C_SDA_PORT, I2C_SDA_PIN),
|
||||
#ifndef CONFIG_I2C_SLAVE
|
||||
.mode = I2C_MASTER,
|
||||
#else
|
||||
.mode = I2C_SLAVE,
|
||||
#endif
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.irq = EVT_I2C1_RXI,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct hc32_i2c_priv_s hc32_i2c1_priv =
|
||||
{
|
||||
.ops = &hc32_i2c_ops,
|
||||
.config = &hc32_i2c1_config,
|
||||
.refs = 0,
|
||||
.intstate = INTSTATE_IDLE,
|
||||
.msgc = 0,
|
||||
.msgv = NULL,
|
||||
.ptr = NULL,
|
||||
.dcnt = 0,
|
||||
.flags = 0,
|
||||
.status = 0
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HC32_I2C2
|
||||
static const struct hc32_i2c_config_s hc32_i2c2_config =
|
||||
{
|
||||
.base = M4_I2C2,
|
||||
.scl_pin = GPIO_PINSET(I2C_SCL_PORT, I2C_SCL_PIN),
|
||||
.sda_pin = GPIO_PINSET(I2C_SDA_PORT, I2C_SDA_PIN),
|
||||
#ifndef CONFIG_I2C_SLAVE
|
||||
.mode = I2C_MASTER,
|
||||
#else
|
||||
.mode = I2C_SLAVE,
|
||||
#endif
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.irq = EVT_I2C2_RXI,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct hc32_i2c_priv_s hc32_i2c2_priv =
|
||||
{
|
||||
.ops = &hc32_i2c_ops,
|
||||
.config = &hc32_i2c2_config,
|
||||
.refs = 0,
|
||||
.intstate = INTSTATE_IDLE,
|
||||
.msgc = 0,
|
||||
.msgv = NULL,
|
||||
.ptr = NULL,
|
||||
.dcnt = 0,
|
||||
.flags = 0,
|
||||
.status = 0
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HC32_I2C3
|
||||
static const struct hc32_i2c_config_s hc32_i2c3_config =
|
||||
{
|
||||
.base = M4_I2C3,
|
||||
.scl_pin = GPIO_PINSET(I2C_SCL_PORT, I2C_SCL_PIN),
|
||||
.sda_pin = GPIO_PINSET(I2C_SDA_PORT, I2C_SDA_PIN),
|
||||
#ifndef CONFIG_I2C_SLAVE
|
||||
.mode = I2C_MASTER,
|
||||
#else
|
||||
.mode = I2C_SLAVE,
|
||||
#endif
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.irq = EVT_I2C3_RXI,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct hc32_i2c_priv_s hc32_i2c3_priv =
|
||||
{
|
||||
.ops = &hc32_i2c_ops,
|
||||
.config = &hc32_i2c3_config,
|
||||
.refs = 0,
|
||||
.intstate = INTSTATE_IDLE,
|
||||
.msgc = 0,
|
||||
.msgv = NULL,
|
||||
.ptr = NULL,
|
||||
.dcnt = 0,
|
||||
.flags = 0,
|
||||
.status = 0
|
||||
};
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
#define I2C_TIMEOUT (0x24000U)
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief MCU Peripheral registers write unprotected.
|
||||
* @param None
|
||||
* @retval None
|
||||
* @note Comment/uncomment each API depending on APP requires.
|
||||
*/
|
||||
static void Peripheral_WE(void)
|
||||
{
|
||||
/* Unlock GPIO register: PSPCR, PCCR, PINAER, PCRxy, PFSRxy */
|
||||
GPIO_Unlock();
|
||||
/* Unlock PWC register: FCG0 */
|
||||
PWC_FCG0_Unlock();
|
||||
/* Unlock PWC, CLK, PVD registers, @ref PWC_REG_Write_Unlock_Code for details */
|
||||
PWC_Unlock(PWC_UNLOCK_CODE_0 | PWC_UNLOCK_CODE_1 | PWC_UNLOCK_CODE_2);
|
||||
/* Unlock SRAM register: WTCR */
|
||||
SRAM_WTCR_Unlock();
|
||||
/* Unlock SRAM register: CKCR */
|
||||
SRAM_CKCR_Unlock();
|
||||
/* Unlock all EFM registers */
|
||||
EFM_Unlock();
|
||||
/* Unlock EFM register: FWMC */
|
||||
//EFM_FWMC_Unlock();
|
||||
/* Unlock EFM OTP write protect registers */
|
||||
//EFM_OTP_WP_Unlock();
|
||||
/* Unlock all MPU registers */
|
||||
// MPU_Unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief MCU Peripheral registers write protected.
|
||||
* @param None
|
||||
* @retval None
|
||||
* @note Comment/uncomment each API depending on APP requires.
|
||||
*/
|
||||
static __attribute__((unused)) void Peripheral_WP(void)
|
||||
{
|
||||
/* Lock GPIO register: PSPCR, PCCR, PINAER, PCRxy, PFSRxy */
|
||||
GPIO_Lock();
|
||||
/* Lock PWC register: FCG0 */
|
||||
PWC_FCG0_Lock();
|
||||
/* Lock PWC, CLK, PVD registers, @ref PWC_REG_Write_Unlock_Code for details */
|
||||
PWC_Lock(PWC_UNLOCK_CODE_0 | PWC_UNLOCK_CODE_1 | PWC_UNLOCK_CODE_2);
|
||||
/* Lock SRAM register: WTCR */
|
||||
SRAM_WTCR_Lock();
|
||||
/* Lock SRAM register: CKCR */
|
||||
SRAM_CKCR_Lock();
|
||||
/* Lock EFM OTP write protect registers */
|
||||
//EFM_OTP_WP_Lock();
|
||||
/* Lock EFM register: FWMC */
|
||||
//EFM_FWMC_Lock();
|
||||
/* Lock all EFM registers */
|
||||
EFM_Lock();
|
||||
/* Lock all MPU registers */
|
||||
// MPU_Lock();
|
||||
}
|
||||
|
||||
//static void Master_LedInit(void)
|
||||
//{
|
||||
// stc_gpio_init_t stcGpioInit;
|
||||
//
|
||||
// /* RGB LED initialize */
|
||||
// (void)GPIO_StructInit(&stcGpioInit);
|
||||
// (void)GPIO_Init(LED_GREEN_PORT, LED_GREEN_PIN, &stcGpioInit);
|
||||
//
|
||||
// /* "Turn off" LED before set to output */
|
||||
// GPIO_ResetPins(LED_GREEN_PORT, LED_GREEN_PIN);
|
||||
//
|
||||
// /* Output enable */
|
||||
// GPIO_OE(LED_GREEN_PORT, LED_GREEN_PIN, Enable);
|
||||
//}
|
||||
|
||||
//static void Master_LedOn(void)
|
||||
//{
|
||||
// GPIO_SetPins(LED_GREEN_PORT, LED_GREEN_PIN);
|
||||
//}
|
||||
|
||||
/**
|
||||
* @brief Send start or restart condition
|
||||
* @param [in] u8Start Indicate the start mode, start or restart
|
||||
* @retval Process result
|
||||
* - I2C_RET_ERROR Send start or restart failed
|
||||
* - I2C_RET_OK Send start or restart success
|
||||
*/
|
||||
static en_result_t Master_StartOrRestart(uint8_t u8Start)
|
||||
{
|
||||
en_result_t enRet;
|
||||
|
||||
/* generate start or restart signal */
|
||||
if(GENERATE_START == u8Start)
|
||||
{
|
||||
enRet = I2C_Start(M4_I2C1,I2C_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear start status flag */
|
||||
enRet = I2C_Restart(M4_I2C1,I2C_TIMEOUT);
|
||||
}
|
||||
|
||||
return enRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send slave address
|
||||
* @param [in] u8Adr The slave address
|
||||
* @param [in] u8Dir The transfer direction @ref I2C_Transfer_Direction
|
||||
* @retval Process result
|
||||
* - I2C_RET_ERROR Send failed
|
||||
* - I2C_RET_OK Send success
|
||||
*/
|
||||
static en_result_t Master_SendAdr(uint8_t u8Adr, uint8_t u8Dir)
|
||||
{
|
||||
return I2C_TransAddr(M4_I2C1,u8Adr,u8Dir,I2C_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send data to slave
|
||||
* @param [in] pTxData Pointer to the data buffer
|
||||
* @param [in] u32Size Data size
|
||||
* @retval Process result
|
||||
* - I2C_RET_ERROR Send failed
|
||||
* - I2C_RET_OK Send success
|
||||
*/
|
||||
static en_result_t Master_WriteData(uint8_t const pTxData[], uint32_t u32Size)
|
||||
{
|
||||
return I2C_TransData(M4_I2C1, pTxData, u32Size,I2C_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write address and receive data from slave
|
||||
* @param [in] pRxData Pointer to the data buffer
|
||||
* @param [in] u32Size Data size
|
||||
* @retval Process result
|
||||
* - I2C_RET_ERROR Process failed
|
||||
* - I2C_RET_OK Process success
|
||||
*/
|
||||
static en_result_t Master_ReceiveAndStop(uint8_t pRxData[], uint32_t u32Size)
|
||||
{
|
||||
return I2C_MasterReceiveAndStop(M4_I2C1,pRxData, u32Size,I2C_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief General stop condition to slave
|
||||
* @param None
|
||||
* @retval Process result
|
||||
* - I2C_RET_ERROR Process failed
|
||||
* - I2C_RET_OK Process success
|
||||
*/
|
||||
static en_result_t Master_Stop(void)
|
||||
{
|
||||
return I2C_Stop(M4_I2C1,I2C_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the I2C peripheral for master
|
||||
* @param None
|
||||
* @retval Process result
|
||||
* - I2C_RET_ERROR Process failed
|
||||
* - I2C_RET_OK Process success
|
||||
*/
|
||||
static en_result_t Master_Initialize(void)
|
||||
{
|
||||
stc_i2c_init_t stcI2cInit;
|
||||
float32_t fErr;
|
||||
|
||||
I2C_DeInit(M4_I2C1);
|
||||
|
||||
(void)I2C_StructInit(&stcI2cInit);
|
||||
stcI2cInit.u32Baudrate = I2C_BAUDRATE;
|
||||
stcI2cInit.u32SclTime = 5U;
|
||||
stcI2cInit.u32ClkDiv = I2C_CLK_DIV4;
|
||||
en_result_t enRet = I2C_Init(M4_I2C1, &stcI2cInit, &fErr);
|
||||
I2C_BusWaitCmd(M4_I2C1, Enable);
|
||||
|
||||
if(enRet == Ok)
|
||||
{
|
||||
I2C_Cmd(M4_I2C1, Enable);
|
||||
}
|
||||
|
||||
return enRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Judge the result. LED0 toggle when result is error status.
|
||||
* @param [in] enRet Result to be judged
|
||||
* @retval None
|
||||
*/
|
||||
static void JudgeResult(en_result_t enRet)
|
||||
{
|
||||
if(Ok != enRet)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
DDL_DelayMS(500U);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int hc32_i2c_init(FAR struct hc32_i2c_priv_s *priv)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int hc32_i2c_deinit(FAR struct hc32_i2c_priv_s *priv)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
static inline void hc32_i2c_sem_init(FAR struct hc32_i2c_priv_s *priv)
|
||||
{
|
||||
nxsem_init(&priv->sem_excl, 0, 1);
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
/* This semaphore is used for signaling and, hence, should not have
|
||||
* priority inheritance enabled.
|
||||
*/
|
||||
|
||||
nxsem_init(&priv->sem_isr, 0, 0);
|
||||
nxsem_set_protocol(&priv->sem_isr, SEM_PRIO_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline void hc32_i2c_sem_destroy(FAR struct hc32_i2c_priv_s *priv)
|
||||
{
|
||||
nxsem_destroy(&priv->sem_excl);
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
nxsem_destroy(&priv->sem_isr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hc32_i2c_sem_post
|
||||
*
|
||||
* Description:
|
||||
* Release the mutual exclusion semaphore
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void hc32_i2c_sem_post(struct hc32_i2c_priv_s *priv)
|
||||
{
|
||||
nxsem_post(&priv->sem_excl);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int hc32_i2c_transfer1(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count)
|
||||
{
|
||||
FAR struct hc32_i2c_priv_s *priv = (struct hc32_i2c_priv_s *)dev;
|
||||
uint32_t status = 0;
|
||||
#ifdef I2C1_FSMC_CONFLICT
|
||||
uint32_t ahbenr;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(count);
|
||||
|
||||
/* Ensure that address or flags don't change meanwhile */
|
||||
|
||||
ret = nxsem_wait(&priv->sem_excl);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
//
|
||||
//
|
||||
|
||||
/* Ensure that any ISR happening after we finish can't overwrite any user
|
||||
* data
|
||||
*/
|
||||
|
||||
priv->dcnt = 0;
|
||||
priv->ptr = NULL;
|
||||
|
||||
hc32_i2c_sem_post(priv);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int hc32_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count)
|
||||
{
|
||||
en_result_t ret;
|
||||
FAR struct hc32_i2c_priv_s *priv = (struct hc32_i2c_priv_s *)dev;
|
||||
|
||||
/* Initialize I2C peripheral and enable function*/
|
||||
ret = Master_Initialize();
|
||||
JudgeResult(ret);
|
||||
|
||||
/* I2C master data write*/
|
||||
ret = Master_StartOrRestart(GENERATE_START);
|
||||
JudgeResult(ret);
|
||||
ret = Master_SendAdr(msgs->addr, I2C_DIR_TX);
|
||||
JudgeResult(ret);
|
||||
ret = Master_WriteData(msgs->buffer, msgs->length);
|
||||
JudgeResult(ret);
|
||||
ret = Master_Stop();
|
||||
JudgeResult(ret);
|
||||
|
||||
/* 5mS delay for device*/
|
||||
DDL_DelayMS(5U);
|
||||
|
||||
/* I2C master data read*/
|
||||
ret = Master_StartOrRestart(GENERATE_START);
|
||||
if(1UL == msgs->length)
|
||||
{
|
||||
I2C_AckConfig(priv->config->base, I2C_NACK);
|
||||
}
|
||||
JudgeResult(ret);
|
||||
ret = Master_SendAdr(msgs->addr, I2C_DIR_RX);
|
||||
JudgeResult(ret);
|
||||
ret = Master_ReceiveAndStop(msgs->buffer, msgs->length);
|
||||
JudgeResult(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hc32_i2c_config(void)
|
||||
{
|
||||
/* Initialize I2C port*/
|
||||
stc_gpio_init_t stcGpioInit;
|
||||
|
||||
Peripheral_WE();
|
||||
|
||||
(void)GPIO_StructInit(&stcGpioInit);
|
||||
(void)GPIO_Init(I2C_SCL_PORT, I2C_SCL_PIN, &stcGpioInit);
|
||||
(void)GPIO_Init(I2C_SDA_PORT, I2C_SDA_PIN, &stcGpioInit);
|
||||
GPIO_SetFunc(I2C_SCL_PORT, I2C_SCL_PIN, GPIO_FUNC_49_I2C1_SCL, PIN_SUBFUNC_DISABLE);
|
||||
GPIO_SetFunc(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_FUNC_48_I2C1_SDA, PIN_SUBFUNC_DISABLE);
|
||||
|
||||
/* Enable peripheral clock */
|
||||
PWC_Fcg1PeriphClockCmd(PWC_FCG1_I2C1, Enable);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief BSP clock initialize.
|
||||
* Set board system clock to PLLH@240MHz
|
||||
* Flash: 5 wait
|
||||
* SRAM_HS: 1 wait
|
||||
* SRAM1_2_3_4_B: 2 wait
|
||||
* PCLK0: 240MHz
|
||||
* PCLK1: 120MHz
|
||||
* PCLK2: 60MHz
|
||||
* PCLK3: 60MHz
|
||||
* PCLK4: 120MHz
|
||||
* EXCLK: 120MHz
|
||||
* HCLK: 240MHz
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void BSP_CLK_Init(void)
|
||||
{
|
||||
stc_clk_xtal_init_t stcXtalInit;
|
||||
stc_clk_pllh_init_t stcPLLHInit;
|
||||
|
||||
/* PCLK0, HCLK Max 240MHz */
|
||||
/* PCLK1, PCLK4 Max 120MHz */
|
||||
/* PCLK2, PCLK3 Max 60MHz */
|
||||
/* EX BUS Max 120MHz */
|
||||
CLK_ClkDiv(CLK_CATE_ALL, \
|
||||
(CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 | \
|
||||
CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 | \
|
||||
CLK_HCLK_DIV1));
|
||||
|
||||
CLK_XtalStructInit(&stcXtalInit);
|
||||
/* Config Xtal and enable Xtal */
|
||||
stcXtalInit.u8XtalMode = CLK_XTALMODE_OSC;
|
||||
stcXtalInit.u8XtalDrv = CLK_XTALDRV_LOW;
|
||||
stcXtalInit.u8XtalState = CLK_XTAL_ON;
|
||||
stcXtalInit.u8XtalStb = CLK_XTALSTB_2MS;
|
||||
CLK_XtalInit(&stcXtalInit);
|
||||
|
||||
(void)CLK_PLLHStructInit(&stcPLLHInit);
|
||||
/* VCO = (8/1)*120 = 960MHz*/
|
||||
stcPLLHInit.u8PLLState = CLK_PLLH_ON;
|
||||
stcPLLHInit.PLLCFGR = 0UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLN = 120UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLP = 4UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLQ = 4UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLR = 4UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLLSRC_XTAL;
|
||||
(void)CLK_PLLHInit(&stcPLLHInit);
|
||||
|
||||
/* Highspeed SRAM set to 1 Read/Write wait cycle */
|
||||
SRAM_SetWaitCycle(SRAM_SRAMH, SRAM_WAIT_CYCLE_1, SRAM_WAIT_CYCLE_1);
|
||||
|
||||
/* SRAM1_2_3_4_backup set to 2 Read/Write wait cycle */
|
||||
SRAM_SetWaitCycle((SRAM_SRAM123 | SRAM_SRAM4 | SRAM_SRAMB), SRAM_WAIT_CYCLE_2, SRAM_WAIT_CYCLE_2);
|
||||
|
||||
/* 0-wait @ 40MHz */
|
||||
EFM_SetWaitCycle(EFM_WAIT_CYCLE_5);
|
||||
|
||||
/* 4 cycles for 200 ~ 250MHz */
|
||||
GPIO_SetReadWaitCycle(GPIO_READ_WAIT_4);
|
||||
|
||||
CLK_SetSysClkSrc(CLK_SYSCLKSOURCE_PLLH);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Main function of i2c_master_polling project
|
||||
* @param None
|
||||
* @retval int32_t return value, if needed
|
||||
*/
|
||||
int hc32_i2c_test(void)
|
||||
{
|
||||
en_result_t enRet;
|
||||
uint8_t u8TxBuf[TEST_DATA_LEN] = {0xD0};
|
||||
uint8_t u8RxBuf[TEST_DATA_LEN] = {0U};
|
||||
|
||||
hc32_i2c_config();
|
||||
|
||||
hc32_print("%s: %d start ...\n", __func__, __LINE__);
|
||||
|
||||
/* Initialize I2C peripheral and enable function*/
|
||||
enRet = Master_Initialize();
|
||||
JudgeResult(enRet);
|
||||
|
||||
hc32_print("%s: %d ret %d\n", __func__, __LINE__, enRet);
|
||||
|
||||
/* I2C master data write*/
|
||||
enRet = Master_StartOrRestart(GENERATE_START);
|
||||
JudgeResult(enRet);
|
||||
enRet = Master_SendAdr(DEVICE_ADDRESS, I2C_DIR_TX);
|
||||
JudgeResult(enRet);
|
||||
enRet = Master_WriteData(u8TxBuf, TEST_DATA_LEN);
|
||||
JudgeResult(enRet);
|
||||
enRet = Master_Stop();
|
||||
JudgeResult(enRet);
|
||||
|
||||
/* 5mS delay for device*/
|
||||
DDL_DelayMS(5U);
|
||||
|
||||
/* I2C master data read*/
|
||||
enRet = Master_StartOrRestart(GENERATE_START);
|
||||
if(1UL == TEST_DATA_LEN)
|
||||
{
|
||||
I2C_AckConfig(M4_I2C1, I2C_NACK);
|
||||
}
|
||||
|
||||
JudgeResult(enRet);
|
||||
enRet = Master_SendAdr(DEVICE_ADDRESS,I2C_DIR_RX);
|
||||
JudgeResult(enRet);
|
||||
enRet = Master_ReceiveAndStop(u8RxBuf, TEST_DATA_LEN);
|
||||
JudgeResult(enRet);
|
||||
|
||||
hc32_print("%s: i2c device id = %x\n", __func__, u8RxBuf[0]);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hc32_i2cbus_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize one I2C bus
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct i2c_master_s *hc32_i2cbus_initialize(int port)
|
||||
{
|
||||
struct hc32_i2c_priv_s * priv = NULL;
|
||||
irqstate_t flags;
|
||||
|
||||
/* Get I2C private structure */
|
||||
|
||||
switch (port)
|
||||
{
|
||||
#ifdef CONFIG_HC32_I2C1
|
||||
case 0:
|
||||
priv = (struct hc32_i2c_priv_s *)&hc32_i2c1_priv;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_HC32_I2C2
|
||||
case 1:
|
||||
priv = (struct hc32_i2c_priv_s *)&hc32_i2c2_priv;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_HC32_I2C3
|
||||
case 2:
|
||||
priv = (struct hc32_i2c_priv_s *)&hc32_i2c3_priv;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize private data for the first time, increment reference count,
|
||||
* power-up hardware and configure GPIOs.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
if ((volatile int)priv->refs++ == 0)
|
||||
{
|
||||
hc32_i2c_sem_init(priv);
|
||||
hc32_i2c_init(priv);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
return (struct i2c_master_s *)priv;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hc32_i2cbus_uninitialize
|
||||
*
|
||||
* Description:
|
||||
* Uninitialize an I2C bus
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int hc32_i2cbus_uninitialize(FAR struct i2c_master_s *dev)
|
||||
{
|
||||
FAR struct hc32_i2c_priv_s *priv = (struct hc32_i2c_priv_s *)dev;
|
||||
irqstate_t flags;
|
||||
|
||||
DEBUGASSERT(dev);
|
||||
|
||||
/* Decrement reference count and check for underflow */
|
||||
|
||||
if (priv->refs == 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
if (--priv->refs > 0)
|
||||
{
|
||||
leave_critical_section(flags);
|
||||
return OK;
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Disable power and other HW resource (GPIO's) */
|
||||
|
||||
hc32_i2c_deinit(priv);
|
||||
|
||||
/* Release unused resources */
|
||||
|
||||
hc32_i2c_sem_destroy(priv);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
static void hc32_i2c_register(int bus)
|
||||
{
|
||||
FAR struct i2c_master_s *i2c;
|
||||
int ret;
|
||||
|
||||
i2c = hc32_i2cbus_initialize(bus);
|
||||
if (i2c == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to get I2C%d interface\n", bus);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = i2c_register(i2c, bus);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to register I2C%d driver: %d\n", bus, ret);
|
||||
hc32_i2cbus_uninitialize(i2c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
|
@ -153,11 +153,6 @@ static void up_idlepm(void)
|
|||
void up_idle(void)
|
||||
{
|
||||
|
||||
#if defined (CONFIG_HC32F4A0_BOARD)
|
||||
extern void hc32_uart_handle(void);
|
||||
hc32_uart_handle();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS)
|
||||
/* If the system is idle and there are no timer interrupts, then process
|
||||
* "fake" timer interrupts. Hopefully, something will wake up.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -64,49 +64,7 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define USART_CR1_USED_INTS (USART_CR1_RIE | USART_CR1_TXEIE | USART_CR1_PCE | USART_CR1_TCIE)
|
||||
|
||||
|
||||
/* Some sanity checks *******************************************************/
|
||||
|
||||
/* DMA configuration */
|
||||
|
||||
/* If DMA is enabled on any USART, then very that other pre-requisites
|
||||
* have also been selected.
|
||||
*/
|
||||
|
||||
/* Power management definitions */
|
||||
|
||||
#if defined(CONFIG_PM) && !defined(CONFIG_HC32_PM_SERIAL_ACTIVITY)
|
||||
# define CONFIG_HC32_PM_SERIAL_ACTIVITY 10
|
||||
#endif
|
||||
#if defined(CONFIG_PM)
|
||||
# define PM_IDLE_DOMAIN 0 /* Revisit */
|
||||
#endif
|
||||
|
||||
/* Since RX DMA or TX DMA or both may be enabled for a given U[S]ART.
|
||||
* We need runtime detection in up_dma_setup and up_dma_shutdown
|
||||
* We use the default struct default init value of 0 which maps to
|
||||
* HC32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN0) which is not a U[S]ART.
|
||||
*/
|
||||
|
||||
#define INVALID_SERIAL_DMA_CHANNEL 0
|
||||
|
||||
/* Keep track if a Break was set
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* 1) This value is set in the priv->ie but never written to the control
|
||||
* register. It must not collide with USART_CR1_USED_INTS or USART_CR3_EIE
|
||||
* 2) USART_CR3_EIE is also carried in the up_dev_s ie member.
|
||||
*
|
||||
* See up_restoreusartint where the masking is done.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_HC32_SERIALBRK_BSDCOMPAT
|
||||
# define USART_CR1_IE_BREAK_INPROGRESS_SHFTS 15
|
||||
# define USART_CR1_IE_BREAK_INPROGRESS (1 << USART_CR1_IE_BREAK_INPROGRESS_SHFTS)
|
||||
#endif
|
||||
#define USART_CR1_USED_INTS (USART_CR1_RIE | USART_CR1_RTOIE | USART_CR1_TXEIE | USART_CR1_PCE | USART_CR1_TCIE)
|
||||
|
||||
#ifdef USE_SERIALDRIVER
|
||||
#ifdef HAVE_SERIALDRIVER
|
||||
|
@ -705,6 +663,10 @@ static struct up_dev_s * const g_uart_devs[HC32_NUSART] =
|
|||
|
||||
static inline uint32_t up_serialin(struct up_dev_s *priv, int offset);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
void hc32_rx_irq_cb(void)
|
||||
{
|
||||
up_interrupt(g_uart_rx_dev->rx_irq, NULL, g_uart_rx_dev);
|
||||
|
@ -725,54 +687,34 @@ void hc32_err_irq_cb(void)
|
|||
up_interrupt(g_uart_rx_dev->err_irq, NULL, g_uart_rx_dev);
|
||||
}
|
||||
|
||||
void hc32_handle_recv_buf(void)
|
||||
{
|
||||
struct up_dev_s *priv = g_uart_rx_dev;
|
||||
struct uart_buffer_s *recv = &priv->dev.recv;
|
||||
char recv_buf[255] = {0};
|
||||
int i, j = 0;
|
||||
static int cnt = 0;
|
||||
static int last_tail = 0;
|
||||
|
||||
if((recv->head != recv->tail) && (cnt ++ > 30))
|
||||
{
|
||||
last_tail = recv->tail;
|
||||
for(i = recv->tail; i < recv->head; i ++)
|
||||
{
|
||||
recv_buf[j++] = recv->buffer[last_tail++];
|
||||
}
|
||||
hc32_console_handle(recv_buf);
|
||||
hc32_print("nsh>%s\n", recv_buf);
|
||||
recv->tail = recv->head;
|
||||
cnt = 0;
|
||||
last_tail = 0;
|
||||
}
|
||||
static int hc32_err_irq_handler(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
up_irq_save();
|
||||
IRQ011_Handler();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hc32_handle_xmit_buf(void)
|
||||
static int hc32_rx_irq_handler(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
struct up_dev_s *priv = g_uart_rx_dev;
|
||||
int i, j = 0;
|
||||
char xmit_buf[255] = {0};
|
||||
|
||||
if(priv->dev.xmit.tail != priv->dev.xmit.head)
|
||||
{
|
||||
for(i = priv->dev.xmit.tail; i < priv->dev.xmit.head; i ++)
|
||||
{
|
||||
xmit_buf[j++] = priv->dev.xmit.buffer[i++];
|
||||
}
|
||||
hc32_print("nsh>%s", xmit_buf);
|
||||
}
|
||||
up_irq_save();
|
||||
IRQ012_Handler();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hc32_uart_handle(void)
|
||||
static int hc32_tx_irq_handler(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
hc32_handle_recv_buf();
|
||||
up_irq_save();
|
||||
IRQ013_Handler();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
static int hc32_tci_irq_handler(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
up_irq_save();
|
||||
IRQ014_Handler();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hc32_print(const char *fmt, ...)
|
||||
{
|
||||
|
@ -802,7 +744,7 @@ int hc32_print(const char *fmt, ...)
|
|||
* @param [in] u32Priority Interrupt priority
|
||||
* @retval None
|
||||
*/
|
||||
static void hc32_enable_irq(const stc_irq_signin_config_t *pstcConfig,
|
||||
static void hc32_serial_enableirq(const stc_irq_signin_config_t *pstcConfig,
|
||||
uint32_t u32Priority)
|
||||
{
|
||||
if (NULL != pstcConfig)
|
||||
|
@ -919,45 +861,6 @@ static void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
|
|||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
static int hc32_enable_serialirq(struct uart_dev_s *dev)
|
||||
{
|
||||
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
||||
stc_irq_signin_config_t cfg;
|
||||
|
||||
{
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.enIRQn = priv->rx_irq - HC32_IRQ_FIRST;
|
||||
cfg.enIntSrc = priv->rxint_src;
|
||||
cfg.pfnCallback = &hc32_rx_irq_cb;
|
||||
hc32_enable_irq(&cfg, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
}
|
||||
|
||||
{
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.enIRQn = priv->tx_irq - HC32_IRQ_FIRST;
|
||||
cfg.enIntSrc = priv->txint_src;
|
||||
cfg.pfnCallback = &hc32_tx_irq_cb;
|
||||
hc32_enable_irq(&cfg, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
}
|
||||
|
||||
{
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.enIRQn = priv->txc_irq - HC32_IRQ_FIRST;
|
||||
cfg.enIntSrc = priv->txcint_src;
|
||||
cfg.pfnCallback = &hc32_txc_irq_cb;
|
||||
hc32_enable_irq(&cfg, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
}
|
||||
|
||||
{
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.enIRQn = priv->err_irq - HC32_IRQ_FIRST;
|
||||
cfg.enIntSrc = priv->errint_src;
|
||||
cfg.pfnCallback = &hc32_err_irq_cb;
|
||||
hc32_enable_irq(&cfg, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_setup
|
||||
|
@ -971,6 +874,102 @@ static int up_setup(struct uart_dev_s *dev)
|
|||
{
|
||||
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
||||
|
||||
#ifndef CONFIG_SUPPRESS_UART_CONFIG
|
||||
uint32_t regval;
|
||||
|
||||
/* Note: The logic here depends on the fact that that the USART module
|
||||
* was enabled in stm32_lowsetup().
|
||||
*/
|
||||
|
||||
/* Enable USART APB1/2 clock */
|
||||
|
||||
// up_set_apb_clock(dev, true);
|
||||
|
||||
/* Configure pins for USART use */
|
||||
|
||||
hc32_configgpio(priv->tx_gpio);
|
||||
hc32_configgpio(priv->rx_gpio);
|
||||
|
||||
#ifdef CONFIG_SERIAL_OFLOWCONTROL
|
||||
if (priv->cts_gpio != 0)
|
||||
{
|
||||
hc32_configgpio(priv->cts_gpio);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||
if (priv->rts_gpio != 0)
|
||||
{
|
||||
uint32_t config = priv->rts_gpio;
|
||||
|
||||
#ifdef CONFIG_STM32_FLOWCONTROL_BROKEN
|
||||
/* Instead of letting hw manage this pin, we will bitbang */
|
||||
|
||||
config = (config & ~GPIO_MODE_MASK) | GPIO_OUTPUT;
|
||||
#endif
|
||||
hc32_configgpio(config);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RS485
|
||||
if (priv->rs485_dir_gpio != 0)
|
||||
{
|
||||
hc32_configgpio(priv->rs485_dir_gpio);
|
||||
hc32_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Configure CR2
|
||||
* Clear STOP, CLKEN, CPOL, CPHA, LBCL, and interrupt enable bits
|
||||
*/
|
||||
|
||||
regval = up_serialin(priv, offsetof(M4_USART_TypeDef, _CR2));
|
||||
regval &= ~(USART_CR2_STOP | USART_CR2_CLKC | USART_CR2_WKUPIE |
|
||||
USART_CR2_BEIE | USART_CR2_LBDIE | USART_CR2_LBDIE);
|
||||
|
||||
/* Configure STOP bits */
|
||||
|
||||
if (priv->stopbits2)
|
||||
{
|
||||
regval |= USART_CR2_STOP;
|
||||
}
|
||||
|
||||
up_serialout(priv, offsetof(M4_USART_TypeDef, _CR2), regval);
|
||||
|
||||
/* Configure CR1
|
||||
* Clear TE, REm and all interrupt enable bits
|
||||
*/
|
||||
|
||||
regval = up_serialin(priv, offsetof(M4_USART_TypeDef, _CR1));
|
||||
regval &= ~(USART_CR1_TE | USART_CR1_RE | USART_CR1_RTOE);
|
||||
|
||||
up_serialout(priv, offsetof(M4_USART_TypeDef, _CR1), regval);
|
||||
|
||||
/* Configure CR3
|
||||
* Clear CTSE, RTSE, and all interrupt enable bits
|
||||
*/
|
||||
|
||||
regval = up_serialin(priv, offsetof(M4_USART_TypeDef, _CR3));
|
||||
regval &= ~(USART_CR3_CTSE | USART_CR3_RTSE );
|
||||
|
||||
up_serialout(priv, offsetof(M4_USART_TypeDef, _CR3), regval);
|
||||
|
||||
/* Configure the USART line format and speed. */
|
||||
|
||||
// up_set_format(dev);
|
||||
|
||||
/* Enable Rx, Tx, and the USART */
|
||||
|
||||
regval = up_serialin(priv, offsetof(M4_USART_TypeDef, _CR1));
|
||||
|
||||
regval |= (USART_CR1_RTOE | USART_CR1_RTOIE | USART_CR1_TE |
|
||||
USART_CR1_RE | USART_CR1_RIE | USART_CR1_TXEIE | USART_CR1_TCIE);
|
||||
|
||||
up_serialout(priv, offsetof(M4_USART_TypeDef, _CR1), regval);
|
||||
|
||||
#endif /* CONFIG_SUPPRESS_UART_CONFIG */
|
||||
|
||||
|
||||
/* Set up the cached interrupt enables value */
|
||||
|
||||
priv->ie = 0;
|
||||
|
@ -1062,13 +1061,39 @@ static void up_shutdown(struct uart_dev_s *dev)
|
|||
static int up_attach(struct uart_dev_s *dev)
|
||||
{
|
||||
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
||||
int ret = 0;
|
||||
stc_irq_signin_config_t cfg;
|
||||
|
||||
hc32_print("%s: attach irq rx %d %d tx %d %d\n", __func__, priv->rx_irq, priv->rxint_src,
|
||||
priv->tx_irq, priv->txint_src);
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.enIRQn = priv->rx_irq - HC32_IRQ_FIRST;
|
||||
cfg.enIntSrc = priv->rxint_src;
|
||||
cfg.pfnCallback = &hc32_rx_irq_cb;
|
||||
hc32_serial_enableirq(&cfg, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
|
||||
ret = hc32_enable_serialirq(dev);
|
||||
return ret;
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.enIRQn = priv->tx_irq - HC32_IRQ_FIRST;
|
||||
cfg.enIntSrc = priv->txint_src;
|
||||
cfg.pfnCallback = &hc32_tx_irq_cb;
|
||||
hc32_serial_enableirq(&cfg, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.enIRQn = priv->txc_irq - HC32_IRQ_FIRST;
|
||||
cfg.enIntSrc = priv->txcint_src;
|
||||
cfg.pfnCallback = &hc32_txc_irq_cb;
|
||||
hc32_serial_enableirq(&cfg, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.enIRQn = priv->err_irq - HC32_IRQ_FIRST;
|
||||
cfg.enIntSrc = priv->errint_src;
|
||||
cfg.pfnCallback = &hc32_err_irq_cb;
|
||||
hc32_serial_enableirq(&cfg, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
|
||||
irq_attach(HC32_IRQ_SVCALL, arm_svcall, NULL);
|
||||
irq_attach(HC32_IRQ_HARDFAULT, arm_hardfault, NULL);
|
||||
irq_attach(USART_UNIT_ERR_INT_IRQn, hc32_err_irq_handler, NULL);
|
||||
irq_attach(USART_UNIT_RX_INT_IRQn, hc32_rx_irq_handler, NULL);
|
||||
irq_attach(USART_UNIT_TX_INT_IRQn, hc32_tx_irq_handler, NULL);
|
||||
irq_attach(USART_UNIT_TCI_INT_IRQn, hc32_tci_irq_handler, NULL);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -1084,10 +1109,14 @@ static int up_attach(struct uart_dev_s *dev)
|
|||
static void up_detach(struct uart_dev_s *dev)
|
||||
{
|
||||
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
||||
up_disable_irq(priv->irq);
|
||||
irq_detach(priv->irq);
|
||||
|
||||
hc32_print("check %s line %d irq %d\n", __func__, __LINE__, priv->irq);
|
||||
up_disable_irq(priv->rx_irq);
|
||||
irq_detach(priv->rx_irq);
|
||||
up_disable_irq(priv->tx_irq);
|
||||
irq_detach(priv->tx_irq);
|
||||
up_disable_irq(priv->txc_irq);
|
||||
irq_detach(priv->txc_irq);
|
||||
up_disable_irq(priv->err_irq);
|
||||
irq_detach(priv->err_irq);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -1535,24 +1564,14 @@ static void up_rxint(struct uart_dev_s *dev, bool enable)
|
|||
* (or an Rx timeout occurs).
|
||||
*/
|
||||
|
||||
ie |= USART_CR1_RIE;
|
||||
ie |= USART_CR1_RIE | USART_CR1_RTOIE | USART_CR1_RTOE | USART_CR1_TE | USART_CR1_RE;
|
||||
|
||||
up_enable_irq(priv->irq);
|
||||
|
||||
/* Enable TX && RX && RX interrupt function */
|
||||
USART_FuncCmd((M4_USART_TypeDef *)priv->usartbase,
|
||||
(USART_RX | USART_INT_RX | USART_TX | \
|
||||
USART_RTO | USART_INT_RTO), Enable);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ie &= ~(USART_CR1_RIE);
|
||||
ie &= ~(USART_CR1_RIE | USART_CR1_RTOIE | USART_CR1_RTOE);
|
||||
up_disable_irq(priv->irq);
|
||||
|
||||
USART_FuncCmd((M4_USART_TypeDef *)priv->usartbase,
|
||||
(USART_RX | USART_INT_RX | USART_TX | \
|
||||
USART_RTO | USART_INT_RTO), Disable);
|
||||
}
|
||||
|
||||
/* Then set the new interrupt state */
|
||||
|
@ -1560,8 +1579,6 @@ static void up_rxint(struct uart_dev_s *dev, bool enable)
|
|||
up_restoreusartint(priv, ie);
|
||||
leave_critical_section(flags);
|
||||
|
||||
hc32_print("%s: opened %d irq %d %s ie %x\n", __func__, dev->open_count, priv->irq,
|
||||
enable ? "enable" : "disable", ie);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -1740,11 +1757,11 @@ static void up_txint(struct uart_dev_s *dev, bool enable)
|
|||
|
||||
static bool up_txready(struct uart_dev_s *dev)
|
||||
{
|
||||
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
||||
M4_USART_TypeDef *base = (M4_USART_TypeDef *)priv->usartbase;
|
||||
|
||||
return((Set == USART_GetStatus(base, USART_FLAG_TXE))
|
||||
|| (Set == USART_GetStatus(base, USART_FLAG_TC)));
|
||||
// struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
||||
// M4_USART_TypeDef *base = (M4_USART_TypeDef *)priv->usartbase;
|
||||
// return((Set == USART_GetStatus(base, USART_FLAG_TXE))
|
||||
// || (Set == USART_GetStatus(base, USART_FLAG_TC)));
|
||||
return Set;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SERIALDRIVER */
|
||||
|
@ -1834,30 +1851,19 @@ void arm_serialinit(void)
|
|||
char devname[16];
|
||||
unsigned i;
|
||||
unsigned minor = 0;
|
||||
int ret;
|
||||
|
||||
/* Register to receive power management callbacks */
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
ret = pm_register(&g_serialcb);
|
||||
DEBUGASSERT(ret == OK);
|
||||
UNUSED(ret);
|
||||
#endif
|
||||
|
||||
/* Register the console */
|
||||
|
||||
#if CONSOLE_UART > 0
|
||||
ret = uart_register("/dev/console", &g_uart_devs[CONSOLE_UART - 1]->dev);
|
||||
uart_register("/dev/console", &g_uart_devs[CONSOLE_UART - 1]->dev);
|
||||
|
||||
#ifndef CONFIG_HC32_SERIAL_DISABLE_REORDERING
|
||||
/* If not disabled, register the console UART to ttyS0 and exclude
|
||||
* it from initializing it further down
|
||||
*/
|
||||
|
||||
ret = uart_register("/dev/ttyS0", &g_uart_devs[CONSOLE_UART - 1]->dev);
|
||||
uart_register("/dev/ttyS0", &g_uart_devs[CONSOLE_UART - 1]->dev);
|
||||
minor = 1;
|
||||
|
||||
hc32_print("register /dev/ttyS0 %d = %d\n", CONSOLE_UART - 1, ret);
|
||||
#endif
|
||||
|
||||
#endif /* CONSOLE_UART > 0 */
|
||||
|
|
|
@ -95,6 +95,11 @@ static int hc32_timerisr(int irq, uint32_t *regs, void *arg)
|
|||
}
|
||||
#endif
|
||||
|
||||
void SysTick_IrqHandler(void)
|
||||
{
|
||||
nxsched_process_timer();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
|
@ -77,7 +77,6 @@ extern void exception_common(void);
|
|||
* Note that the [ ... ] designated initializer is a GCC extension.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
unsigned _vectors[] locate_data(".vectors") =
|
||||
{
|
||||
/* Initial stack */
|
||||
|
@ -92,175 +91,3 @@ unsigned _vectors[] locate_data(".vectors") =
|
|||
|
||||
[2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = (unsigned)&exception_common
|
||||
};
|
||||
#else
|
||||
unsigned _vectors[] locate_data(".vectors") =
|
||||
{
|
||||
/* Initial stack */
|
||||
|
||||
IDLE_STACK,
|
||||
|
||||
/* Reset exception handler */
|
||||
|
||||
(unsigned)&__start,
|
||||
(unsigned)&NMI_Handler,
|
||||
(unsigned)&HardFault_Handler,
|
||||
(unsigned)&MemManage_Handler,
|
||||
(unsigned)&BusFault_Handler,
|
||||
(unsigned)&UsageFault_Handler,
|
||||
(unsigned)&exception_common,
|
||||
(unsigned)&exception_common,
|
||||
(unsigned)&exception_common,
|
||||
(unsigned)&exception_common,
|
||||
(unsigned)&SVC_Handler, /* SVC */
|
||||
(unsigned)&DebugMon_Handler, /* DebugMon */
|
||||
(unsigned)&exception_common,
|
||||
(unsigned)&PendSV_Handler,
|
||||
(unsigned)&SysTick_Handler, /* SysTick */
|
||||
(unsigned)&IRQ000_Handler,
|
||||
(unsigned)&IRQ001_Handler,
|
||||
(unsigned)&IRQ002_Handler,
|
||||
(unsigned)&IRQ003_Handler,
|
||||
(unsigned)&IRQ004_Handler,
|
||||
(unsigned)&IRQ005_Handler,
|
||||
(unsigned)&IRQ006_Handler,
|
||||
(unsigned)&IRQ007_Handler,
|
||||
(unsigned)&IRQ008_Handler,
|
||||
(unsigned)&IRQ009_Handler,
|
||||
(unsigned)&IRQ010_Handler,
|
||||
(unsigned)&IRQ011_Handler,
|
||||
(unsigned)&IRQ012_Handler,
|
||||
(unsigned)&IRQ013_Handler,
|
||||
(unsigned)&IRQ014_Handler,
|
||||
(unsigned)&IRQ015_Handler,
|
||||
(unsigned)&IRQ016_Handler,
|
||||
(unsigned)&IRQ017_Handler,
|
||||
(unsigned)&IRQ018_Handler,
|
||||
(unsigned)&IRQ019_Handler,
|
||||
(unsigned)&IRQ020_Handler,
|
||||
(unsigned)&IRQ021_Handler,
|
||||
(unsigned)&IRQ022_Handler,
|
||||
(unsigned)&IRQ023_Handler,
|
||||
(unsigned)&IRQ024_Handler,
|
||||
(unsigned)&IRQ025_Handler,
|
||||
(unsigned)&IRQ026_Handler,
|
||||
(unsigned)&IRQ027_Handler,
|
||||
(unsigned)&IRQ028_Handler,
|
||||
(unsigned)&IRQ029_Handler,
|
||||
(unsigned)&IRQ030_Handler,
|
||||
(unsigned)&IRQ031_Handler,
|
||||
(unsigned)&IRQ032_Handler,
|
||||
(unsigned)&IRQ033_Handler,
|
||||
(unsigned)&IRQ034_Handler,
|
||||
(unsigned)&IRQ035_Handler,
|
||||
(unsigned)&IRQ036_Handler,
|
||||
(unsigned)&IRQ037_Handler,
|
||||
(unsigned)&IRQ038_Handler,
|
||||
(unsigned)&IRQ039_Handler,
|
||||
(unsigned)&IRQ040_Handler,
|
||||
(unsigned)&IRQ041_Handler,
|
||||
(unsigned)&IRQ042_Handler,
|
||||
(unsigned)&IRQ043_Handler,
|
||||
(unsigned)&IRQ044_Handler,
|
||||
(unsigned)&IRQ045_Handler,
|
||||
(unsigned)&IRQ046_Handler,
|
||||
(unsigned)&IRQ047_Handler,
|
||||
(unsigned)&IRQ048_Handler,
|
||||
(unsigned)&IRQ049_Handler,
|
||||
(unsigned)&IRQ050_Handler,
|
||||
(unsigned)&IRQ051_Handler,
|
||||
(unsigned)&IRQ052_Handler,
|
||||
(unsigned)&IRQ053_Handler,
|
||||
(unsigned)&IRQ054_Handler,
|
||||
(unsigned)&IRQ055_Handler,
|
||||
(unsigned)&IRQ056_Handler,
|
||||
(unsigned)&IRQ057_Handler,
|
||||
(unsigned)&IRQ058_Handler,
|
||||
(unsigned)&IRQ059_Handler,
|
||||
(unsigned)&IRQ060_Handler,
|
||||
(unsigned)&IRQ061_Handler,
|
||||
(unsigned)&IRQ062_Handler,
|
||||
(unsigned)&IRQ063_Handler,
|
||||
(unsigned)&IRQ064_Handler,
|
||||
(unsigned)&IRQ065_Handler,
|
||||
(unsigned)&IRQ066_Handler,
|
||||
(unsigned)&IRQ067_Handler,
|
||||
(unsigned)&IRQ068_Handler,
|
||||
(unsigned)&IRQ069_Handler,
|
||||
(unsigned)&IRQ070_Handler,
|
||||
(unsigned)&IRQ071_Handler,
|
||||
(unsigned)&IRQ072_Handler,
|
||||
(unsigned)&IRQ073_Handler,
|
||||
(unsigned)&IRQ074_Handler,
|
||||
(unsigned)&IRQ075_Handler,
|
||||
(unsigned)&IRQ076_Handler,
|
||||
(unsigned)&IRQ077_Handler,
|
||||
(unsigned)&IRQ078_Handler,
|
||||
(unsigned)&IRQ079_Handler,
|
||||
(unsigned)&IRQ080_Handler,
|
||||
(unsigned)&IRQ081_Handler,
|
||||
(unsigned)&IRQ082_Handler,
|
||||
(unsigned)&IRQ083_Handler,
|
||||
(unsigned)&IRQ084_Handler,
|
||||
(unsigned)&IRQ085_Handler,
|
||||
(unsigned)&IRQ086_Handler,
|
||||
(unsigned)&IRQ087_Handler,
|
||||
(unsigned)&IRQ088_Handler,
|
||||
(unsigned)&IRQ089_Handler,
|
||||
(unsigned)&IRQ090_Handler,
|
||||
(unsigned)&IRQ091_Handler,
|
||||
(unsigned)&IRQ092_Handler,
|
||||
(unsigned)&IRQ093_Handler,
|
||||
(unsigned)&IRQ094_Handler,
|
||||
(unsigned)&IRQ095_Handler,
|
||||
(unsigned)&IRQ096_Handler,
|
||||
(unsigned)&IRQ097_Handler,
|
||||
(unsigned)&IRQ098_Handler,
|
||||
(unsigned)&IRQ099_Handler,
|
||||
(unsigned)&IRQ100_Handler,
|
||||
(unsigned)&IRQ101_Handler,
|
||||
(unsigned)&IRQ102_Handler,
|
||||
(unsigned)&IRQ103_Handler,
|
||||
(unsigned)&IRQ104_Handler,
|
||||
(unsigned)&IRQ105_Handler,
|
||||
(unsigned)&IRQ106_Handler,
|
||||
(unsigned)&IRQ107_Handler,
|
||||
(unsigned)&IRQ108_Handler,
|
||||
(unsigned)&IRQ109_Handler,
|
||||
(unsigned)&IRQ110_Handler,
|
||||
(unsigned)&IRQ111_Handler,
|
||||
(unsigned)&IRQ112_Handler,
|
||||
(unsigned)&IRQ113_Handler,
|
||||
(unsigned)&IRQ114_Handler,
|
||||
(unsigned)&IRQ115_Handler,
|
||||
(unsigned)&IRQ116_Handler,
|
||||
(unsigned)&IRQ117_Handler,
|
||||
(unsigned)&IRQ118_Handler,
|
||||
(unsigned)&IRQ119_Handler,
|
||||
(unsigned)&IRQ120_Handler,
|
||||
(unsigned)&IRQ121_Handler,
|
||||
(unsigned)&IRQ122_Handler,
|
||||
(unsigned)&IRQ123_Handler,
|
||||
(unsigned)&IRQ124_Handler,
|
||||
(unsigned)&IRQ125_Handler,
|
||||
(unsigned)&IRQ126_Handler,
|
||||
(unsigned)&IRQ127_Handler,
|
||||
(unsigned)&IRQ128_Handler,
|
||||
(unsigned)&IRQ129_Handler,
|
||||
(unsigned)&IRQ130_Handler,
|
||||
(unsigned)&IRQ131_Handler,
|
||||
(unsigned)&IRQ132_Handler,
|
||||
(unsigned)&IRQ133_Handler,
|
||||
(unsigned)&IRQ134_Handler,
|
||||
(unsigned)&IRQ135_Handler,
|
||||
(unsigned)&IRQ136_Handler,
|
||||
(unsigned)&IRQ137_Handler,
|
||||
(unsigned)&IRQ138_Handler,
|
||||
(unsigned)&IRQ139_Handler,
|
||||
(unsigned)&IRQ140_Handler,
|
||||
(unsigned)&IRQ141_Handler,
|
||||
(unsigned)&IRQ142_Handler,
|
||||
(unsigned)&IRQ143_Handler
|
||||
|
||||
// [2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = (unsigned)&exception_common
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,8 @@ extern "C"
|
|||
******************************************************************************/
|
||||
#include "hc32_common.h"
|
||||
#include "ddl_config.h"
|
||||
#include <arch/irq.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/**
|
||||
* @addtogroup HC32F4A0_DDL_Driver
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# XiZi_AIoT Project Configuration
|
||||
#
|
||||
CONFIG_BOARD_IMX6Q_SABRELITE_EVB=y
|
||||
CONFIG_ARCH_ARM=y
|
||||
|
||||
#
|
||||
# imx6q sabrelite feature
|
||||
#
|
||||
|
||||
#
|
||||
# Lib
|
||||
#
|
||||
CONFIG_LIB=y
|
||||
CONFIG_LIB_POSIX=y
|
||||
CONFIG_LIB_NEWLIB=y
|
||||
# CONFIG_LIB_MUSLLIB is not set
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
source "$KERNEL_DIR/services/Kconfig"
|
||||
source "$KERNEL_DIR/softkernel/Kconfig"
|
||||
source "$KERNEL_DIR/support/Kconfig"
|
||||
source "$KERNEL_DIR/testing/Kconfig"
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
MAKEFLAGS += --no-print-directory
|
||||
|
||||
.PHONY:all clean distclean show_info menuconfig
|
||||
.PHONY:COMPILE_APP COMPILE_KERNEL
|
||||
|
||||
riscv_support :=
|
||||
arm_support += imx6q-sabrelite
|
||||
emulator_support +=
|
||||
support := $(riscv_support) $(arm_support) $(emulator_support)
|
||||
SRC_DIR :=
|
||||
|
||||
export BOARD ?=imx6q-sabrelite
|
||||
# This is the environment variable for kconfig-mconf
|
||||
export KCONFIG_CONFIG ?= .config
|
||||
|
||||
ifeq ($(filter $(BOARD),$(support)),)
|
||||
$(warning "You should choose board like this: make BOARD=imx6q-sabrelite")
|
||||
$(warning "This is what we support:")
|
||||
$(warning "RISCV EVB: $(riscv_support)")
|
||||
$(warning "ARM EVB: $(arm_support)")
|
||||
$(warning "EMULATORS: $(emulator_support)")
|
||||
# $(warning "$(support)")
|
||||
$(error "break" )
|
||||
endif
|
||||
|
||||
export TARGET
|
||||
export COMPILE_TYPE
|
||||
export KERNEL_ROOT ?=$(strip $(shell pwd))
|
||||
|
||||
MAKEFILES =$(KERNEL_ROOT)/.config
|
||||
-include $(KERNEL_ROOT)/.config
|
||||
|
||||
export BSP_ROOT ?= $(KERNEL_ROOT)/services/boards/$(BOARD)
|
||||
export UBIQUITOUS_ROOT ?= ..
|
||||
include services/boards/$(BOARD)/config.mk
|
||||
export BSP_BUILD_DIR := boards/$(BOARD)
|
||||
export HOSTTOOLS_DIR ?= $(KERNEL_ROOT)/services/tools/hosttools
|
||||
export CONFIG2H_EXE ?= $(HOSTTOOLS_DIR)/xsconfig.sh
|
||||
|
||||
export CPPPATHS
|
||||
export SRC_APP_DIR := ../../APP_Framework
|
||||
export SRC_KERNEL_DIR := hardkernel services softkernel support testing
|
||||
# export SRC_DIR:= $(SRC_APP_DIR) $(SRC_KERNEL_DIR)
|
||||
export SRC_DIR:= $(SRC_KERNEL_DIR)
|
||||
export LIBCC
|
||||
export MUSL_DIR := $(KERNEL_ROOT)/services/lib/musllib
|
||||
|
||||
PART:=
|
||||
|
||||
all:
|
||||
ifeq ($(CONFIG_COMPILER_APP)_$(CONFIG_COMPILER_KERNEL),y_)
|
||||
PART += COMPILE_APP
|
||||
|
||||
else ifeq ($(CONFIG_COMPILER_APP)_$(CONFIG_COMPILER_KERNEL),_y)
|
||||
PART += COMPILE_KERNEL
|
||||
|
||||
else ifeq ($(CONFIG_COMPILER_APP)_$(CONFIG_COMPILER_KERNEL),y_y)
|
||||
PART := COMPILE_APP COMPILE_KERNEL
|
||||
|
||||
else
|
||||
|
||||
ifeq ($(CONFIG_LIB_MUSLLIB), y)
|
||||
PART += COMPILE_MUSL
|
||||
endif
|
||||
|
||||
PART += COMPILE_ALL
|
||||
endif
|
||||
|
||||
|
||||
all: $(PART)
|
||||
|
||||
|
||||
COMPILE_ALL:
|
||||
@for dir in $(SRC_DIR);do \
|
||||
$(MAKE) -C $$dir; \
|
||||
done
|
||||
@cp link.mk build/Makefile
|
||||
@$(MAKE) -C build TARGET=XiZi-$(BOARD).elf LINK_FLAGS=LFLAGS
|
||||
@rm build/Makefile build/make.obj
|
||||
|
||||
COMPILE_MUSL:
|
||||
@for dir in $(MUSL_DIR);do \
|
||||
$(MAKE) -C $$dir COMPILE_TYPE=$@ CONFIG_RESOURCES_LWIP=n; \
|
||||
done
|
||||
@cp link_libc.mk build/Makefile
|
||||
@$(MAKE) -C build TARGET=libmusl.a LINK_FLAGS=LFLAGS
|
||||
@cp build/libmusl.a $(KERNEL_ROOT)/lib/musllib/libmusl.a
|
||||
@rm build/Makefile build/make.obj
|
||||
|
||||
COMPILE_KERNEL:
|
||||
@for dir in $(SRC_KERNEL_DIR);do \
|
||||
$(MAKE) -C $$dir; \
|
||||
done
|
||||
@cp link.mk build/Makefile
|
||||
@$(MAKE) -C build COMPILE_TYPE="_kernel" TARGET=XiZi-$(BOARD)_kernel.elf LINK_FLAGS=LFLAGS
|
||||
@rm build/Makefile build/make.obj
|
||||
|
||||
COMPILE_APP:
|
||||
@echo $(SRC_APP_DIR)
|
||||
@for dir in $(SRC_APP_DIR);do \
|
||||
$(MAKE) -C $$dir USE_APP_INCLUDEPATH=y; \
|
||||
done
|
||||
@cp link.mk build/Makefile
|
||||
@$(MAKE) -C build COMPILE_TYPE="_app" TARGET=XiZi-$(BOARD)_app.elf LINK_FLAGS=APPLFLAGS
|
||||
@rm build/Makefile build/make.obj
|
||||
|
||||
show_info:
|
||||
@echo "CONFIG_COMPILER_APP is :" $(CONFIG_COMPILER_APP)
|
||||
@echo "CONFIG_COMPILER_KERNEL is :" $(CONFIG_COMPILER_KERNEL)
|
||||
@echo "KERNELPATHS is :" $(KERNELPATHS)
|
||||
@echo "TARGET is :" $(TARGET)
|
||||
@echo "VPATH is :" $(VPATH)
|
||||
@echo "BSP_ROOT is :" $(BSP_ROOT)
|
||||
@echo "KERNEL_ROOT is :" $(KERNEL_ROOT)
|
||||
@echo "CPPPATHS is :" $(CPPPATHS)
|
||||
@echo "SRC_DIR is :" $(SRC_DIR)
|
||||
@echo "BUILD_DIR is :" $(BUILD_DIR)
|
||||
@echo "BSP_BUILD_DIR is :" $(BSP_BUILD_DIR)
|
||||
@echo "OBJS is :" $(OBJS)
|
||||
@for f in $(CPPPATHS); do \
|
||||
echo $$f; \
|
||||
done
|
||||
|
||||
menuconfig:
|
||||
@if [ -f "$(BSP_ROOT)/.config" ]; then \
|
||||
cp $(BSP_ROOT)/.config $(KERNEL_ROOT)/.config; \
|
||||
else if [ -f "$(BSP_ROOT)/.defconfig" ]; then \
|
||||
cp $(BSP_ROOT)/.defconfig $(KERNEL_ROOT)/.config ;\
|
||||
fi ;fi
|
||||
@kconfig-mconf $(BSP_ROOT)/Kconfig
|
||||
@$(CONFIG2H_EXE) .config
|
||||
@cp $(KERNEL_ROOT)/.config $(BSP_ROOT)/.config
|
||||
|
||||
clean:
|
||||
@echo Clean target and build_dir
|
||||
@rm -rf build
|
||||
@rm -rf temp.txt
|
||||
|
||||
distclean:
|
||||
@echo Clean all configuration
|
||||
@make clean
|
||||
@rm -f .config*
|
||||
@rm -f $(KERNEL_ROOT)/lib/musllib/libmusl.a
|
||||
@rm -f $(KERNEL_ROOT)/board/*/.config
|
|
@ -0,0 +1,127 @@
|
|||
ifeq ($(COMPILE_TYPE), COMPILE_MUSL)
|
||||
SRC_DIR_TEMP := $(MUSL_DIR)
|
||||
else ifeq ($(COMPILE_TYPE), COMPILE_LWIP)
|
||||
SRC_DIR_TEMP := $(LWIP_DIR)
|
||||
else
|
||||
SRC_DIR_TEMP := $(SRC_DIR)
|
||||
endif
|
||||
|
||||
SRC_DIR :=
|
||||
MUSL_DIR :=
|
||||
LWIP_DIR :=
|
||||
|
||||
ifeq ($(USE_APP_INCLUDEPATH), y)
|
||||
include $(KERNEL_ROOT)/path_app.mk
|
||||
else
|
||||
include $(KERNEL_ROOT)/path_kernel.mk
|
||||
endif
|
||||
export CPPPATHS := $(KERNELPATHS)
|
||||
|
||||
CUR_DIR :=$(shell pwd)
|
||||
|
||||
CFLAGS += $(CPPPATHS)
|
||||
AFLAGS += $(CPPPATHS)
|
||||
CXXFLAGS += $(CPPPATHS)
|
||||
|
||||
CFLAGS += $(DEFINES)
|
||||
AFLAGS += $(DEFINES)
|
||||
CXXFLAGS += $(DEFINES)
|
||||
BUILD_DIR := $(KERNEL_ROOT)/build
|
||||
APP_DIR := Ubiquitous/XiZi
|
||||
|
||||
|
||||
.PHONY:COMPILER
|
||||
COMPILER:
|
||||
@if [ "${SRC_DIR_TEMP}" != "" ]; then \
|
||||
for dir in $(SRC_DIR_TEMP);do \
|
||||
$(MAKE) -C $$dir; \
|
||||
done; \
|
||||
fi
|
||||
@/bin/echo -n $(OBJS) " " >> $(KERNEL_ROOT)/build/make.obj
|
||||
|
||||
|
||||
################################################
|
||||
define add_c_file
|
||||
$(eval COBJ := $(1:%.c=%.o)) \
|
||||
$(eval COBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(COBJ))) \
|
||||
$(eval LOCALC := $(addprefix $(BUILD_DIR)/,$(COBJ))) \
|
||||
$(eval OBJS += $(LOCALC)) \
|
||||
$(if $(strip $(LOCALC)),$(eval $(LOCALC): $(1)
|
||||
@if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi
|
||||
@echo cc $$<
|
||||
@/bin/echo -n $(dir $(LOCALC)) >>$(KERNEL_ROOT)/build/make.dep
|
||||
@($(CROSS_COMPILE)gcc -MM $$(CFLAGS) -c $$<) >>$(KERNEL_ROOT)/build/make.dep
|
||||
@$(CROSS_COMPILE)gcc $$(CFLAGS) -c $$< -o $$@))
|
||||
endef
|
||||
|
||||
define add_cpp_file
|
||||
$(eval COBJ := $(1:%.cpp=%.o)) \
|
||||
$(eval COBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(COBJ))) \
|
||||
$(eval LOCALCPP := $(addprefix $(BUILD_DIR)/,$(COBJ))) \
|
||||
$(eval OBJS += $(LOCALCPP)) \
|
||||
$(if $(strip $(LOCALCPP)),$(eval $(LOCALCPP): $(1)
|
||||
@if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi
|
||||
@echo cc $$<
|
||||
@/bin/echo -n $(dir $(LOCALCPP)) >>$(KERNEL_ROOT)/build/make.dep
|
||||
@$(CROSS_COMPILE)g++ -MM $$(CXXFLAGS) -c $$< >>$(KERNEL_ROOT)/build/make.dep
|
||||
@$(CROSS_COMPILE)g++ $$(CXXFLAGS) -c $$< -o $$@))
|
||||
endef
|
||||
|
||||
define add_cc_file
|
||||
$(eval COBJ := $(1:%.cc=%.o)) \
|
||||
$(eval COBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(COBJ))) \
|
||||
$(eval LOCALCPP := $(addprefix $(BUILD_DIR)/,$(COBJ))) \
|
||||
$(eval OBJS += $(LOCALCPP)) \
|
||||
$(if $(strip $(LOCALCPP)),$(eval $(LOCALCPP): $(1)
|
||||
@if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi
|
||||
@echo cc $$<
|
||||
@/bin/echo -n $(dir $(LOCALCPP)) >>$(KERNEL_ROOT)/build/make.dep
|
||||
@$(CROSS_COMPILE)g++ -MM $$(CXXFLAGS) -c $$< >>$(KERNEL_ROOT)/build/make.dep
|
||||
@$(CROSS_COMPILE)g++ $$(CXXFLAGS) -c $$< -o $$@))
|
||||
endef
|
||||
|
||||
define add_S_file
|
||||
$(eval SOBJ := $(1:%.S=%.o)) \
|
||||
$(eval SOBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(SOBJ))) \
|
||||
$(eval LOCALS := $(addprefix $(BUILD_DIR)/,$(SOBJ))) \
|
||||
$(eval OBJS += $(LOCALS)) \
|
||||
$(if $(strip $(LOCALS)),$(eval $(LOCALS): $(1)
|
||||
@if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi
|
||||
@echo cc $$<
|
||||
@/bin/echo -n $(dir $(LOCALC)) >>$(KERNEL_ROOT)/build/make.dep
|
||||
@$(CROSS_COMPILE)gcc -MM $$(CFLAGS) -c $$< >>$(KERNEL_ROOT)/build/make.dep
|
||||
@$(CROSS_COMPILE)gcc $$(AFLAGS) -c $$< -o $$@))
|
||||
endef
|
||||
|
||||
define add_a_file
|
||||
$(eval SOBJ := $(1:%.a=%.a)) \
|
||||
$(eval SOBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(SOBJ))) \
|
||||
$(eval LOCALA := $(addprefix $(BUILD_DIR)/,$(SOBJ))) \
|
||||
$(eval OBJS += $(LOCALA)) \
|
||||
$(if $(strip $(LOCALA)),$(eval $(LOCALA): $(1)
|
||||
@if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi
|
||||
@echo cp $$<
|
||||
@cp $$< $$@))
|
||||
endef
|
||||
|
||||
|
||||
SRCS := $(strip $(filter %.c,$(SRC_FILES)))
|
||||
$(if $(SRCS),$(foreach f,$(SRCS),$(call add_c_file,$(addprefix $(CUR_DIR)/,$(f)))))
|
||||
|
||||
SRCS := $(strip $(filter %.cpp,$(SRC_FILES)))
|
||||
$(if $(SRCS),$(foreach f,$(SRCS),$(call add_cpp_file,$(addprefix $(CUR_DIR)/,$(f)))))
|
||||
|
||||
SRCS := $(strip $(filter %.cc,$(SRC_FILES)))
|
||||
$(if $(SRCS),$(foreach f,$(SRCS),$(call add_cc_file,$(addprefix $(CUR_DIR)/,$(f)))))
|
||||
|
||||
SRCS := $(strip $(filter %.S,$(SRC_FILES)))
|
||||
$(if $(SRCS),$(foreach f,$(SRCS),$(call add_S_file,$(addprefix $(CUR_DIR)/,$(f)))))
|
||||
|
||||
SRCS := $(strip $(filter %.a,$(SRC_FILES)))
|
||||
$(if $(SRCS),$(foreach f,$(SRCS),$(call add_a_file,$(addprefix $(CUR_DIR)/,$(f)))))
|
||||
|
||||
COMPILER:$(OBJS)
|
||||
|
||||
|
||||
|
||||
-include $(KERNEL_ROOT)/build/make.dep
|
|
@ -0,0 +1,3 @@
|
|||
SRC_DIR := arch abstraction
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,3 @@
|
|||
SRC_FILES := cache.c isr.c mmu.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* 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: isr.c
|
||||
* @brief: the general management of system isr
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2020/3/15
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "isr.h"
|
||||
|
||||
struct InterruptServiceRoutines isrManager = {0} ;
|
||||
|
||||
#ifdef ARCH_SMP
|
||||
extern int GetCpuId(void);
|
||||
#endif
|
||||
/**
|
||||
* This functionwill get the isr nest level.
|
||||
*
|
||||
* @return isr nest level
|
||||
*/
|
||||
static uint16_t GetIsrCounter()
|
||||
{
|
||||
uint16_t ret = 0;
|
||||
|
||||
#ifdef ARCH_SMP
|
||||
ret = isrManager.isr_count[GetCpuId()];
|
||||
#else
|
||||
ret = isrManager.isr_count;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void IncIsrCounter()
|
||||
{
|
||||
#ifdef ARCH_SMP
|
||||
isrManager.isr_count[GetCpuId()] ++ ;
|
||||
#else
|
||||
isrManager.isr_count ++;
|
||||
#endif
|
||||
return ;
|
||||
}
|
||||
|
||||
static void DecIsrCounter()
|
||||
{
|
||||
|
||||
#ifdef ARCH_SMP
|
||||
isrManager.isr_count[GetCpuId()] -- ;
|
||||
#else
|
||||
isrManager.isr_count --;
|
||||
#endif
|
||||
return ;
|
||||
}
|
||||
|
||||
bool IsInIsr()
|
||||
{
|
||||
#ifdef ARCH_SMP
|
||||
return ( isrManager.isr_count[GetCpuId()] != 0 ? TRUE : FALSE ) ;
|
||||
#else
|
||||
return ( isrManager.isr_count != 0 ? TRUE : FALSE ) ;
|
||||
#endif
|
||||
|
||||
}
|
||||
/**
|
||||
* This function will register a new irq.
|
||||
*
|
||||
* @param irq_num the number of the irq
|
||||
* @param handler the callback of the interrupt
|
||||
* @param arg param of thge callback
|
||||
*
|
||||
* @return 0 on success; -1 on failure
|
||||
*/
|
||||
static int32_t RegisterHwIrq(uint32_t irq_num, IsrHandlerType handler, void *arg)
|
||||
{
|
||||
if (irq_num >= ARCH_MAX_IRQ_NUM )
|
||||
return -1;
|
||||
|
||||
struct IrqDesc *desc = &isrManager.irq_table[irq_num];
|
||||
|
||||
desc->handler = handler;
|
||||
desc->param = arg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* This function will free a irq.
|
||||
*
|
||||
* @param irq_num the number of the irq
|
||||
*
|
||||
* @return 0 on success; -1 on failure
|
||||
*/
|
||||
static int32_t FreeHwIrq(uint32_t irq_num)
|
||||
{
|
||||
if (irq_num >= ARCH_MAX_IRQ_NUM )
|
||||
return -1;
|
||||
|
||||
memset(&isrManager.irq_table[irq_num], 0, sizeof(struct IrqDesc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will enable a irq.
|
||||
*
|
||||
* @param irq_num the number of the irq
|
||||
*
|
||||
* @return 0 on success; -1 on failure
|
||||
*/
|
||||
static int32_t EnableHwIrq(uint32_t irq_num)
|
||||
{
|
||||
if (irq_num >= ARCH_MAX_IRQ_NUM )
|
||||
return -1;
|
||||
|
||||
return ArchEnableHwIrq(irq_num);
|
||||
}
|
||||
/**
|
||||
* This function will disable a irq.
|
||||
*
|
||||
* @param irq_num the number of the irq
|
||||
*
|
||||
* @return 0 on success; -1 on failure
|
||||
*/
|
||||
|
||||
static int32_t DisableHwIrq(uint32_t irq_num)
|
||||
{
|
||||
if (irq_num >= ARCH_MAX_IRQ_NUM )
|
||||
return -1;
|
||||
|
||||
return ArchDisableHwIrq(irq_num);
|
||||
}
|
||||
|
||||
/* called from arch-specific ISR wrapper */
|
||||
static void IsrCommon(uint32_t irq_num)
|
||||
{
|
||||
struct IrqDesc *desc = &isrManager.irq_table[irq_num];
|
||||
|
||||
if (desc->handler == NULL) {
|
||||
// SYS_KDEBUG_LOG(KDBG_IRQ, ("Spurious interrupt: IRQ No. %d\n", irq_num));
|
||||
while (1) {}
|
||||
}
|
||||
desc->handler(irq_num, desc->param);
|
||||
|
||||
}
|
||||
|
||||
static void SetIsrSwitchTrigerFlag()
|
||||
{
|
||||
|
||||
#ifdef ARCH_SMP
|
||||
isrManager.isr_switch_trigger_flag[GetCpuId()] = 1;
|
||||
#else
|
||||
isrManager.isr_switch_trigger_flag = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ClearIsrSwitchTrigerFlag()
|
||||
{
|
||||
|
||||
#ifdef ARCH_SMP
|
||||
isrManager.isr_switch_trigger_flag[GetCpuId()] = 0;
|
||||
#else
|
||||
isrManager.isr_switch_trigger_flag = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t GetIsrSwitchTrigerFlag()
|
||||
{
|
||||
|
||||
#ifdef ARCH_SMP
|
||||
return isrManager.isr_switch_trigger_flag[GetCpuId()];
|
||||
#else
|
||||
return isrManager.isr_switch_trigger_flag ;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct IsrDone isrDone = {
|
||||
IsInIsr,
|
||||
RegisterHwIrq ,
|
||||
FreeHwIrq,
|
||||
EnableHwIrq,
|
||||
DisableHwIrq,
|
||||
IsrCommon,
|
||||
GetIsrCounter,
|
||||
IncIsrCounter,
|
||||
DecIsrCounter,
|
||||
GetIsrSwitchTrigerFlag,
|
||||
SetIsrSwitchTrigerFlag,
|
||||
ClearIsrSwitchTrigerFlag
|
||||
};
|
||||
|
||||
void SysInitIsrManager()
|
||||
{
|
||||
extern int __isrtbl_idx_start;
|
||||
extern int __isrtbl_start;
|
||||
extern int __isrtbl_end;
|
||||
memset(&isrManager,0,sizeof(struct InterruptServiceRoutines));
|
||||
isrManager.done = &isrDone;
|
||||
|
||||
uint32_t *index = (uint32_t *)&__isrtbl_idx_start;
|
||||
struct IrqDesc *desc = (struct IrqDesc *)&__isrtbl_start;
|
||||
|
||||
while (desc != (struct IrqDesc *)&__isrtbl_end)
|
||||
isrManager.irq_table[*index++] = *desc++;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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: isr.h
|
||||
* @brief: function declaration and structure defintion of isr
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2020/3/10
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ISR_H__
|
||||
#define __ISR_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <arch_interrupt.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define DECLARE_HW_IRQ(_irq_num, _handler, _arg) \
|
||||
const uint32_t __irq_desc_idx_##_handler SECTION(".isrtbl.idx") = _irq_num + ARCH_IRQ_NUM_OFFSET ; \
|
||||
const struct IrqDesc __irq_desc_##_handler SECTION(".isrtbl") = { \
|
||||
.handler = _handler, \
|
||||
.param = _arg, \
|
||||
}
|
||||
|
||||
typedef void (*IsrHandlerType)(int vector, void *param);
|
||||
|
||||
struct IrqDesc
|
||||
{
|
||||
IsrHandlerType handler;
|
||||
void *param;
|
||||
|
||||
#ifdef CONFIG_INTERRUPT_INFO
|
||||
char name[NAME_NUM_MAX];
|
||||
uint32_t counter;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct IsrDone
|
||||
{
|
||||
bool (*isInIsr)();
|
||||
int32_t (*registerIrq)(uint32_t irq_num, IsrHandlerType handler, void *arg);
|
||||
int32_t (*freeIrq)(uint32_t irq_num);
|
||||
int32_t (*enableIrq)(uint32_t irq_num);
|
||||
int32_t (*disableIrq)(uint32_t irq_num);
|
||||
void (*handleIrq)(uint32_t irq_num);
|
||||
uint16_t (*getCounter)() ;
|
||||
void (*incCounter)();
|
||||
void (*decCounter)();
|
||||
uint8_t (*getSwitchTrigerFlag)();
|
||||
void (*setSwitchTrigerFlag)();
|
||||
void (*clearSwitchTrigerFlag)();
|
||||
};
|
||||
|
||||
struct InterruptServiceRoutines {
|
||||
|
||||
#ifdef ARCH_SMP
|
||||
volatile uint16_t isr_count[CPU_NUMBERS];
|
||||
volatile uint8_t isr_switch_trigger_flag[CPU_NUMBERS];
|
||||
#else
|
||||
volatile uint16_t isr_count ;
|
||||
volatile uint8_t isr_switch_trigger_flag;
|
||||
#endif
|
||||
struct IrqDesc irq_table[ARCH_MAX_IRQ_NUM];
|
||||
struct IsrDone *done;
|
||||
};
|
||||
|
||||
extern struct InterruptServiceRoutines isrManager ;
|
||||
|
||||
uint32_t DisableLocalInterrupt();
|
||||
void EnableLocalInterrupt(unsigned long level);
|
||||
|
||||
#define DISABLE_INTERRUPT DisableLocalInterrupt
|
||||
#define ENABLE_INTERRUPT EnableLocalInterrupt
|
||||
|
||||
void SysInitIsrManager();
|
||||
void InitHwinterrupt(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
config ARCH_CPU_64BIT
|
||||
bool
|
||||
|
||||
config ARCH_RISCV
|
||||
bool
|
||||
|
||||
config ARCH_ARM
|
||||
bool
|
||||
|
||||
config ARCH_RISCV64
|
||||
select ARCH_RISCV
|
||||
select ARCH_CPU_64BIT
|
||||
bool
|
|
@ -0,0 +1,3 @@
|
|||
SRC_DIR := $(ARCH)
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,4 @@
|
|||
# The following three platforms support compatiable instructions.
|
||||
SRC_DIR := $(ARCH_ARMV)
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,8 @@
|
|||
# The following three platforms support compatiable instructions.
|
||||
|
||||
ifeq ($(CONFIG_BOARD_IMX6Q_SABRELITE_EVB),y)
|
||||
SRC_DIR := cortex-a9
|
||||
endif
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,87 @@
|
|||
|
||||
.equ Mode_USR, 0x10
|
||||
.equ Mode_FIQ, 0x11
|
||||
.equ Mode_IRQ, 0x12
|
||||
.equ Mode_SVC, 0x13
|
||||
.equ Mode_ABT, 0x17
|
||||
.equ Mode_UND, 0x1B
|
||||
.equ Mode_SYS, 0x1F
|
||||
|
||||
.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
|
||||
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
|
||||
|
||||
.equ STACK_SIZE, 0x00000100
|
||||
|
||||
.globl _start
|
||||
|
||||
_start:
|
||||
/* set the cpu to SVC32 mode and disable interrupt */
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #0x1f
|
||||
orr r0, r0, #0x13
|
||||
msr cpsr_c, r0
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, #(1 << 12) /* i cache */
|
||||
bic r0, #(1 << 2) /* d cache */
|
||||
bic r0, #(1 << 0) /* mmu */
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
ldr r0, =stack_top
|
||||
|
||||
@ Set the startup stack for svc
|
||||
mov sp, r0
|
||||
|
||||
@ Enter Undefined Instruction Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_UND|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #STACK_SIZE
|
||||
|
||||
@ Enter Abort Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_ABT|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #STACK_SIZE
|
||||
|
||||
@ Enter FIQ Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #STACK_SIZE
|
||||
|
||||
@ Enter IRQ Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #STACK_SIZE
|
||||
|
||||
/* come back to SVC mode */
|
||||
msr cpsr_c, #Mode_SVC|I_Bit|F_Bit
|
||||
|
||||
/* clear .bss */
|
||||
mov r0, #0 /* get a zero */
|
||||
ldr r1,=BSS_START /* bss start */
|
||||
ldr r2,=BSS_END /* bss end */
|
||||
|
||||
bss_loop:
|
||||
cmp r1,r2 /* check if data to clear */
|
||||
strlo r0,[r1],#4 /* clear 4 bytes */
|
||||
blo bss_loop /* loop until done */
|
||||
|
||||
/* call C++ constructors of global objects */
|
||||
ldr r0, =__ctors_start__
|
||||
ldr r1, =__ctors_end__
|
||||
bss_end:
|
||||
|
||||
ctor_loop:
|
||||
cmp r0, r1
|
||||
beq ctor_end
|
||||
ldr r2, [r0], #4
|
||||
stmfd sp!, {r0-r1}
|
||||
mov lr, pc
|
||||
bx r2
|
||||
ldmfd sp!, {r0-r1}
|
||||
b ctor_loop
|
||||
ctor_end:
|
||||
|
||||
bl start_kernel
|
||||
|
||||
_loop_here:
|
||||
b _loop_here
|
|
@ -0,0 +1,66 @@
|
|||
.section .vectors, "ax"
|
||||
.code 32
|
||||
|
||||
.globl ExceptionVectors
|
||||
ExceptionVectors:
|
||||
ldr pc, _ResetException
|
||||
ldr pc, _UndefInstrException
|
||||
ldr pc, _SwiException
|
||||
ldr pc, _PrefetchAbortException
|
||||
ldr pc, _DataAbortAbortException
|
||||
ldr pc, _ResvException
|
||||
ldr pc, _IrqException
|
||||
ldr pc, _FiqException
|
||||
|
||||
.globl Reset_Handler
|
||||
.globl UndefInstrExceptionHandle
|
||||
.globl SwiExceptionHandle
|
||||
.globl PrefetchAbortExceptionHandle
|
||||
.globl DataAbortExceptionHandle
|
||||
.globl ResvExceptionHandle
|
||||
.globl ExceptionIsrEntry
|
||||
.globl FiqExceptionHandle
|
||||
|
||||
_ResetException:
|
||||
.word Reset_Handler
|
||||
_UndefInstrException:
|
||||
.word UndefInstrExceptionHandle
|
||||
_SwiException:
|
||||
.word SwiExceptionHandle
|
||||
_PrefetchAbortException:
|
||||
.word PrefetchAbortExceptionHandle
|
||||
_DataAbortAbortException:
|
||||
.word DataAbortExceptionHandle
|
||||
_ResvException:
|
||||
.word ResvExceptionHandle
|
||||
_IrqException:
|
||||
.word ExceptionIsrEntry
|
||||
_FiqException:
|
||||
.word FiqExceptionHandle
|
||||
|
||||
.globl _start
|
||||
Reset_Handler:
|
||||
b _start
|
||||
|
||||
UndefInstrExceptionHandle:
|
||||
b UndefInstrIsrEntry
|
||||
|
||||
SwiExceptionHandle:
|
||||
b SvcIsrEntry
|
||||
|
||||
PrefetchAbortExceptionHandle:
|
||||
b PrefetchAbortIsrEntry
|
||||
|
||||
DataAbortExceptionHandle:
|
||||
b UndefInstrIsrEntry
|
||||
|
||||
ResvExceptionHandle:
|
||||
b DataAbortIsrEntry
|
||||
|
||||
ExceptionIsrEntry:
|
||||
stmfd sp!, {r0-r12,lr}
|
||||
|
||||
bl IsrEntry
|
||||
|
||||
FiqExceptionHandle:
|
||||
b FiqIsrEntry
|
|
@ -0,0 +1,3 @@
|
|||
SRC_FILES := boot.S cache.S exception.S cortexA9.S gic.c interrupt.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ARCH_INTERRUPT_H__
|
||||
#define ARCH_INTERRUPT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <board.h>
|
||||
#include "gic.h"
|
||||
|
||||
#define ARCH_MAX_IRQ_NUM PLATFORM_MAX_IRQ_NR
|
||||
|
||||
int32_t ArchEnableHwIrq(uint32_t irq_num);
|
||||
int32_t ArchDisableHwIrq(uint32_t irq_num);
|
||||
|
||||
//! @brief
|
||||
typedef enum {
|
||||
CPU_0,
|
||||
CPU_1,
|
||||
CPU_2,
|
||||
CPU_3,
|
||||
} cpuid_e;
|
||||
|
||||
struct ExceptionStackRegister
|
||||
{
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r4;
|
||||
uint32_t r5;
|
||||
uint32_t r6;
|
||||
uint32_t r7;
|
||||
uint32_t r8;
|
||||
uint32_t r9;
|
||||
uint32_t r10;
|
||||
uint32_t r11;
|
||||
uint32_t r12;
|
||||
uint32_t r13_sp;
|
||||
uint32_t r14_lr;
|
||||
uint32_t r15_pc;
|
||||
uint32_t cpsr;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,92 @@
|
|||
#include <asm_defines.h>
|
||||
|
||||
.global ExceptionVectors
|
||||
|
||||
.section ".startup","ax"
|
||||
.globl _reset
|
||||
|
||||
_reset:
|
||||
|
||||
/* set the cpu to SVC32 mode and disable interrupt */
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #0x1f
|
||||
orr r0, r0, #0x13
|
||||
msr cpsr_c, r0
|
||||
|
||||
/* disable i/d cache mmu*/
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, #(1 << 12) /* i cache */
|
||||
bic r0, #(1 << 2) /* d cache */
|
||||
bic r0, #(1 << 0) /* mmu */
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
ldr r0, =stack_top
|
||||
|
||||
@ Set the startup stack for svc
|
||||
mov sp, r0
|
||||
|
||||
@ Enter Undefined Instruction Mode and set its Stack Pointer
|
||||
msr cpsr_c, #MODE_UND|I_BIT|F_BIT
|
||||
mov sp, r0
|
||||
sub r0, r0, #EXCEPTION_STACK_SIZE
|
||||
|
||||
@ Enter Abort Mode and set its Stack Pointer
|
||||
msr cpsr_c, #MODE_ABT|I_BIT|F_BIT
|
||||
mov sp, r0
|
||||
sub r0, r0, #EXCEPTION_STACK_SIZE
|
||||
|
||||
@ Enter FIQ Mode and set its Stack Pointer
|
||||
msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT
|
||||
mov sp, r0
|
||||
sub r0, r0, #EXCEPTION_STACK_SIZE
|
||||
|
||||
@ Enter IRQ Mode and set its Stack Pointer
|
||||
msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT
|
||||
mov sp, r0
|
||||
sub r0, r0, #EXCEPTION_STACK_SIZE
|
||||
|
||||
/* come back to SVC mode */
|
||||
msr cpsr_c, #MODE_SVC|I_BIT|F_BIT
|
||||
|
||||
/*
|
||||
* copy the vector table into the RAM vectors
|
||||
* this assumes that the RAM vectors size is divisible by 3 words (12 bytes)
|
||||
*/
|
||||
ldr r1,=__ram_vectors_start
|
||||
ldr r2,=__ram_vectors_end
|
||||
ldr r3,=ExceptionVectors
|
||||
1: cmp r1,r2
|
||||
ldmlt r3!,{r4,r5,r6}
|
||||
stmlt r1!,{r4,r5,r6}
|
||||
blt 1b
|
||||
|
||||
/* clear .bss */
|
||||
mov r0, #0 /* get a zero */
|
||||
ldr r1,=__bss_start /* bss start */
|
||||
ldr r2,=__bss_end /* bss end */
|
||||
|
||||
bss_loop:
|
||||
cmp r1,r2 /* check if data to clear */
|
||||
strlo r0,[r1],#4 /* clear 4 bytes */
|
||||
blo bss_loop /* loop until done */
|
||||
|
||||
/* call C++ constructors of global objects */
|
||||
ldr r0, =__ctors_start__
|
||||
ldr r1, =__ctors_end__
|
||||
bss_end:
|
||||
|
||||
ctor_loop:
|
||||
cmp r0, r1
|
||||
beq ctor_end
|
||||
ldr r2, [r0], #4
|
||||
stmfd sp!, {r0-r1}
|
||||
mov lr, pc
|
||||
bx r2
|
||||
ldmfd sp!, {r0-r1}
|
||||
b ctor_loop
|
||||
ctor_end:
|
||||
|
||||
bl start_kernel
|
||||
|
||||
_loop_here:
|
||||
b _loop_here
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @file cortexA9.s
|
||||
* @brief This file contains cortexA9 functions
|
||||
*
|
||||
*/
|
||||
|
||||
.code 32
|
||||
.section ".text","ax"
|
||||
|
||||
/*
|
||||
* bool arm_set_interrupt_state(bool enable)
|
||||
*/
|
||||
.global arm_set_interrupt_state
|
||||
.func arm_set_interrupt_state
|
||||
arm_set_interrupt_state:
|
||||
mrs r2,CPSR @ read CPSR (Current Program Status Register)
|
||||
teq r0,#0
|
||||
bicne r1,r2,#0xc0 @ disable IRQ and FIQ
|
||||
orreq r1,r2,#0xc0 @ enable IRQ and FIQ
|
||||
msr CPSR_c,r1
|
||||
tst r2,#0x80
|
||||
movne r0,#0
|
||||
moveq r0,#1
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
.global cpu_get_current
|
||||
@ int cpu_get_current(void)@
|
||||
@ get current CPU ID
|
||||
.func cpu_get_current
|
||||
cpu_get_current:
|
||||
mrc p15, 0, r0, c0, c0, 5
|
||||
and r0, r0, #3
|
||||
BX lr
|
||||
.endfunc @cpu_get_current()@
|
||||
|
||||
.global enable_neon_fpu
|
||||
.func enable_neon_fpu
|
||||
enable_neon_fpu:
|
||||
/* set NSACR, both Secure and Non-secure access are allowed to NEON */
|
||||
MRC p15, 0, r0, c1, c1, 2
|
||||
ORR r0, r0, #(0x3<<10) @ enable fpu/neon
|
||||
MCR p15, 0, r0, c1, c1, 2
|
||||
/* Set the CPACR for access to CP10 and CP11*/
|
||||
LDR r0, =0xF00000
|
||||
MCR p15, 0, r0, c1, c0, 2
|
||||
/* Set the FPEXC EN bit to enable the FPU */
|
||||
MOV r3, #0x40000000
|
||||
@VMSR FPEXC, r3
|
||||
MCR p10, 7, r3, c8, c0, 0
|
||||
.endfunc
|
||||
|
||||
.global disable_strict_align_check
|
||||
.func disable_strict_align_check
|
||||
disable_strict_align_check:
|
||||
/*Ray's note: disable strict alignment fault checking.
|
||||
without disabling this, data abort will happen when accessing
|
||||
the BPB structure of file system since it is packed.*/
|
||||
|
||||
push {r0, lr}
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, r0, #(0x1<<1) @clear A bit of SCTLR
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
pop {r0, pc}
|
||||
.endfunc
|
||||
|
||||
.global disable_L1_cache
|
||||
.func disable_L1_cache
|
||||
disable_L1_cache:
|
||||
push {r0-r6, lr}
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, r0, #(0x1<<12)
|
||||
bic r0, r0, #(0x1<<11)
|
||||
bic r0, r0, #(0x1<<2)
|
||||
bic r0, r0, #(0x1<<0)
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
pop {r0-r6, pc}
|
||||
|
||||
.endfunc
|
||||
|
||||
.global get_arm_private_peripheral_base
|
||||
@ uint32_t get_arm_private_peripheral_base(void)@
|
||||
.func get_arm_private_peripheral_base
|
||||
get_arm_private_peripheral_base:
|
||||
|
||||
@ Get base address of private perpherial space
|
||||
mrc p15, 4, r0, c15, c0, 0 @ Read periph base address
|
||||
bx lr
|
||||
|
||||
.endfunc @get_arm_private_peripheral_base()@
|
||||
|
||||
@ ------------------------------------------------------------
|
||||
@ TLB
|
||||
@ ------------------------------------------------------------
|
||||
|
||||
.global arm_unified_tlb_invalidate
|
||||
@ void arm_unified_tlb_invalidate(void)@
|
||||
.func arm_unified_tlb_invalidate
|
||||
arm_unified_tlb_invalidate:
|
||||
mov r0, #1
|
||||
mcr p15, 0, r0, c8, c7, 0 @ TLBIALL - Invalidate entire unified TLB
|
||||
dsb
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
.global arm_unified_tlb_invalidate_is
|
||||
@ void arm_unified_tlb_invalidate_is(void)@
|
||||
.func arm_unified_tlb_invalidate_is
|
||||
arm_unified_tlb_invalidate_is:
|
||||
mov r0, #1
|
||||
mcr p15, 0, r0, c8, c3, 0 @ TLBIALLIS - Invalidate entire unified TLB Inner Shareable
|
||||
dsb
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
@ ------------------------------------------------------------
|
||||
@ Branch Prediction
|
||||
@ ------------------------------------------------------------
|
||||
|
||||
.global arm_branch_prediction_enable
|
||||
@ void arm_branch_prediction_enable(void)
|
||||
.func arm_branch_prediction_enable
|
||||
arm_branch_prediction_enable:
|
||||
mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR
|
||||
orr r0, r0, #(1 << 11) @ Set the Z bit (bit 11)
|
||||
mcr p15, 0,r0, c1, c0, 0 @ Write SCTLR
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
.global arm_branch_prediction_disable
|
||||
@ void arm_branch_prediction_disable(void)
|
||||
.func arm_branch_prediction_disable
|
||||
arm_branch_prediction_disable:
|
||||
mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR
|
||||
bic r0, r0, #(1 << 11) @ Clear the Z bit (bit 11)
|
||||
mcr p15, 0,r0, c1, c0, 0 @ Write SCTLR
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
.global arm_branch_target_cache_invalidate
|
||||
@ void arm_branch_target_cache_invalidate(void)
|
||||
.func arm_branch_target_cache_invalidate
|
||||
arm_branch_target_cache_invalidate:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 6 @ BPIALL - Invalidate entire branch predictor array
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
.global arm_branch_target_cache_invalidate_is
|
||||
@ void arm_branch_target_cache_invalidate_is(void)
|
||||
.func arm_branch_target_cache_invalidate_is
|
||||
arm_branch_target_cache_invalidate_is:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c1, 6 @ BPIALLIS - Invalidate entire branch predictor array Inner Shareable
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
@ ------------------------------------------------------------
|
||||
@ SCU
|
||||
@ ------------------------------------------------------------
|
||||
|
||||
@ SCU offset from base of private peripheral space --> 0x000
|
||||
|
||||
.global scu_enable
|
||||
@ void scu_enable(void)
|
||||
@ Enables the SCU
|
||||
.func scu_enable
|
||||
scu_enable:
|
||||
|
||||
mrc p15, 4, r0, c15, c0, 0 @ Read periph base address
|
||||
|
||||
ldr r1, [r0, #0x0] @ Read the SCU Control Register
|
||||
orr r1, r1, #0x1 @ Set bit 0 (The Enable bit)
|
||||
str r1, [r0, #0x0] @ Write back modifed value
|
||||
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
@ ------------------------------------------------------------
|
||||
|
||||
.global scu_join_smp
|
||||
@ void scu_join_smp(void)
|
||||
@ Set this CPU as participating in SMP
|
||||
.func scu_join_smp
|
||||
scu_join_smp:
|
||||
|
||||
@ SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 1 @ Read ACTLR
|
||||
orr r0, r0, #0x040 @ Set bit 6
|
||||
mcr p15, 0, r0, c1, c0, 1 @ Write ACTLR
|
||||
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
@ ------------------------------------------------------------
|
||||
|
||||
.global scu_leave_smp
|
||||
@ void scu_leave_smp(void)
|
||||
@ Set this CPU as NOT participating in SMP
|
||||
.func scu_leave_smp
|
||||
scu_leave_smp:
|
||||
|
||||
@ SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 1 @ Read ACTLR
|
||||
bic r0, r0, #0x040 @ Clear bit 6
|
||||
mcr p15, 0, r0, c1, c0, 1 @ Write ACTLR
|
||||
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
@ ------------------------------------------------------------
|
||||
|
||||
.global scu_get_cpus_in_smp
|
||||
@ unsigned int scu_get_cpus_in_smp(void)
|
||||
@ The return value is 1 bit per core:
|
||||
@ bit 0 - CPU 0
|
||||
@ bit 1 - CPU 1
|
||||
@ etc...
|
||||
.func scu_get_cpus_in_smp
|
||||
scu_get_cpus_in_smp:
|
||||
|
||||
mrc p15, 4, r0, c15, c0, 0 @ Read periph base address
|
||||
|
||||
ldr r0, [r0, #0x004] @ Read SCU Configuration register
|
||||
mov r0, r0, lsr #4 @ Bits 7:4 gives the cores in SMP mode, shift then mask
|
||||
and r0, r0, #0x0F
|
||||
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
@ ------------------------------------------------------------
|
||||
|
||||
.global scu_enable_maintenance_broadcast
|
||||
@ void scu_enable_maintenance_broadcast(void)
|
||||
@ Enable the broadcasting of cache & TLB maintenance operations
|
||||
@ When enabled AND in SMP, broadcast all "inner sharable"
|
||||
@ cache and TLM maintenance operations to other SMP cores
|
||||
.func scu_enable_maintenance_broadcast
|
||||
scu_enable_maintenance_broadcast:
|
||||
mrc p15, 0, r0, c1, c0, 1 @ Read Aux Ctrl register
|
||||
orr r0, r0, #0x01 @ Set the FW bit (bit 0)
|
||||
mcr p15, 0, r0, c1, c0, 1 @ Write Aux Ctrl register
|
||||
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
@ ------------------------------------------------------------
|
||||
|
||||
.global scu_disable_maintenance_broadcast
|
||||
@ void scu_disable_maintenance_broadcast(void)
|
||||
@ Disable the broadcasting of cache & TLB maintenance operations
|
||||
.func scu_disable_maintenance_broadcast
|
||||
scu_disable_maintenance_broadcast:
|
||||
mrc p15, 0, r0, c1, c0, 1 @ Read Aux Ctrl register
|
||||
bic r0, r0, #0x01 @ Clear the FW bit (bit 0)
|
||||
mcr p15, 0, r0, c1, c0, 1 @ Write Aux Ctrl register
|
||||
|
||||
bx lr
|
||||
.endfunc
|
||||
|
||||
@ ------------------------------------------------------------
|
||||
|
||||
.global scu_secure_invalidate
|
||||
@ void scu_secure_invalidate(unsigned int cpu, unsigned int ways)
|
||||
@ cpu: 0x0=CPU 0 0x1=CPU 1 etc...
|
||||
@ This function invalidates the SCU copy of the tag rams
|
||||
@ for the specified core. typically only done at start-up.
|
||||
@ Possible flow:
|
||||
@ - Invalidate L1 caches
|
||||
@ - Invalidate SCU copy of TAG RAMs
|
||||
@ - Join SMP
|
||||
.func scu_secure_invalidate
|
||||
scu_secure_invalidate:
|
||||
and r0, r0, #0x03 @ Mask off unused bits of CPU ID
|
||||
mov r0, r0, lsl #2 @ Convert into bit offset (four bits per core)
|
||||
|
||||
and r1, r1, #0x0F @ Mask off unused bits of ways
|
||||
mov r1, r1, lsl r0 @ Shift ways into the correct CPU field
|
||||
|
||||
mrc p15, 4, r2, c15, c0, 0 @ Read periph base address
|
||||
|
||||
str r1, [r2, #0x0C] @ Write to SCU Invalidate All in Secure State
|
||||
|
||||
bx lr
|
||||
|
||||
.endfunc
|
||||
|
||||
@ ------------------------------------------------------------
|
||||
@ End of cortexA9.s
|
||||
@ ------------------------------------------------------------
|
||||
.end
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(__CORTEX_A9_H__)
|
||||
#define __CORTEX_A9_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//! @addtogroup cortexa9
|
||||
//! @{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @name Instruction macros
|
||||
//@{
|
||||
#define _ARM_NOP() asm volatile ("nop\n\t")
|
||||
#define _ARM_WFI() asm volatile ("wfi\n\t")
|
||||
#define _ARM_WFE() asm volatile ("wfe\n\t")
|
||||
#define _ARM_SEV() asm volatile ("sev\n\t")
|
||||
#define _ARM_DSB() asm volatile ("dsb\n\t")
|
||||
#define _ARM_ISB() asm volatile ("isb\n\t")
|
||||
|
||||
#define _ARM_MRC(coproc, opcode1, Rt, CRn, CRm, opcode2) \
|
||||
asm volatile ("mrc p" #coproc ", " #opcode1 ", %[output], c" #CRn ", c" #CRm ", " #opcode2 "\n" : [output] "=r" (Rt))
|
||||
|
||||
#define _ARM_MCR(coproc, opcode1, Rt, CRn, CRm, opcode2) \
|
||||
asm volatile ("mcr p" #coproc ", " #opcode1 ", %[input], c" #CRn ", c" #CRm ", " #opcode2 "\n" :: [input] "r" (Rt))
|
||||
//@}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//! @name Misc
|
||||
//@{
|
||||
//! @brief Enable or disable the IRQ and FIQ state.
|
||||
bool arm_set_interrupt_state(bool enable);
|
||||
|
||||
//! @brief Get current CPU ID.
|
||||
int cpu_get_current(void);
|
||||
|
||||
//! @brief Enable the NEON MPE.
|
||||
void enable_neon_fpu(void);
|
||||
|
||||
//! @brief Disable aborts on unaligned accesses.
|
||||
void disable_strict_align_check(void);
|
||||
|
||||
//! @brief Get base address of private perpherial space.
|
||||
//!
|
||||
//! @return The address of the ARM CPU's private peripherals.
|
||||
uint32_t get_arm_private_peripheral_base(void);
|
||||
//@}
|
||||
|
||||
|
||||
//! @name Data cache operations
|
||||
//@{
|
||||
|
||||
//! @brief Check if dcache is enabled or disabled.
|
||||
int arm_dcache_state_query();
|
||||
|
||||
//! @brief Enables data cache at any available cache level.
|
||||
//!
|
||||
//! Works only if MMU is enabled!
|
||||
void arm_dcache_enable();
|
||||
|
||||
//! @brief Disables the data cache at any available cache level.
|
||||
void arm_dcache_disable();
|
||||
|
||||
//! @brief Invalidates the entire data cache.
|
||||
void arm_dcache_invalidate();
|
||||
|
||||
//! @brief Invalidate a line of data cache.
|
||||
void arm_dcache_invalidate_line(const void * addr);
|
||||
|
||||
//! @brief Invalidate a number of lines of data cache.
|
||||
//!
|
||||
//! Number of lines depends on length parameter and size of line.
|
||||
//! Size of line for A9 L1 cache is 32B.
|
||||
void arm_dcache_invalidate_mlines(const void * addr, size_t length);
|
||||
|
||||
//! @brief Flush (clean) all lines of cache (all sets in all ways).
|
||||
void arm_dcache_flush();
|
||||
|
||||
//! @brief Flush (clean) one line of cache.
|
||||
void arm_dcache_flush_line(const void * addr);
|
||||
|
||||
// @brief Flush (clean) multiple lines of cache.
|
||||
//!
|
||||
//! Number of lines depends on length parameter and size of line.
|
||||
void arm_dcache_flush_mlines(const void * addr, size_t length);
|
||||
//@}
|
||||
|
||||
//! @name Instrution cache operations
|
||||
//@{
|
||||
|
||||
//! @brief Check if icache is enabled or disabled.
|
||||
int arm_icache_state_query();
|
||||
|
||||
//! @brief Enables instruction cache at any available cache level.
|
||||
//!
|
||||
//! Works without enabled MMU too!
|
||||
void arm_icache_enable();
|
||||
|
||||
//! @brief Disables the instruction cache at any available cache level.
|
||||
void arm_icache_disable();
|
||||
|
||||
//! @brief Invalidates the entire instruction cache.
|
||||
void arm_icache_invalidate();
|
||||
|
||||
//! @brief Invalidates the entire instruction cache inner shareable.
|
||||
void arm_icache_invalidate_is();
|
||||
|
||||
//! @brief Invalidate a line of the instruction cache.
|
||||
void arm_icache_invalidate_line(const void * addr);
|
||||
|
||||
//! @brief Invalidate a number of lines of instruction cache.
|
||||
//!
|
||||
//! Number of lines depends on length parameter and size of line.
|
||||
void arm_icache_invalidate_mlines(const void * addr, size_t length);
|
||||
//@}
|
||||
|
||||
//! @name TLB operations
|
||||
//@{
|
||||
//! @brief Invalidate entire unified TLB.
|
||||
void arm_unified_tlb_invalidate(void);
|
||||
|
||||
//! @brief Invalidate entire unified TLB Inner Shareable.
|
||||
void arm_unified_tlb_invalidate_is(void);
|
||||
//@}
|
||||
|
||||
//! @name Branch predictor operations
|
||||
//@{
|
||||
//! @brief Enable branch prediction.
|
||||
void arm_branch_prediction_enable(void);
|
||||
|
||||
//! @brief Disable branch prediction.
|
||||
void arm_branch_prediction_disable(void);
|
||||
|
||||
//! @brief Invalidate entire branch predictor array.
|
||||
void arm_branch_target_cache_invalidate(void);
|
||||
|
||||
//! @brief Invalidate entire branch predictor array Inner Shareable
|
||||
void arm_branch_target_cache_invalidate_is(void);
|
||||
//@}
|
||||
|
||||
//! @name SCU
|
||||
//@{
|
||||
//! @brief Enables the SCU.
|
||||
void scu_enable(void);
|
||||
|
||||
//! @brief Set this CPU as participating in SMP.
|
||||
void scu_join_smp(void);
|
||||
|
||||
//! @brief Set this CPU as not participating in SMP.
|
||||
void scu_leave_smp(void);
|
||||
|
||||
//! @brief Determine which CPUs are participating in SMP.
|
||||
//!
|
||||
//! The return value is 1 bit per core:
|
||||
//! - bit 0 - CPU 0
|
||||
//! - bit 1 - CPU 1
|
||||
//! - etc...
|
||||
unsigned int scu_get_cpus_in_smp(void);
|
||||
|
||||
//! @brief Enable the broadcasting of cache & TLB maintenance operations.
|
||||
//!
|
||||
//! When enabled AND in SMP, broadcast all "inner sharable"
|
||||
//! cache and TLM maintenance operations to other SMP cores
|
||||
void scu_enable_maintenance_broadcast(void);
|
||||
|
||||
//! @brief Disable the broadcasting of cache & TLB maintenance operations.
|
||||
void scu_disable_maintenance_broadcast(void);
|
||||
|
||||
//! @brief Invalidates the SCU copy of the tag rams for the specified core.
|
||||
//!
|
||||
//! Typically only done at start-up.
|
||||
//! Possible flow:
|
||||
//! - Invalidate L1 caches
|
||||
//! - Invalidate SCU copy of TAG RAMs
|
||||
//! - Join SMP
|
||||
//!
|
||||
//! @param cpu 0x0=CPU 0, 0x1=CPU 1, etc...
|
||||
//! @param ways The ways to invalidate. Pass 0xf to invalidate all ways.
|
||||
void scu_secure_invalidate(unsigned int cpu, unsigned int ways);
|
||||
//@}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // __CORTEX_A9_H__
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,145 @@
|
|||
#include <asm_defines.h>
|
||||
|
||||
.section .text.vectors, "ax"
|
||||
.code 32
|
||||
|
||||
.globl ExceptionVectors
|
||||
ExceptionVectors:
|
||||
ldr pc, _ResetException
|
||||
ldr pc, _UndefInstrException
|
||||
ldr pc, _SwiException
|
||||
ldr pc, _PrefetchAbortException
|
||||
ldr pc, _DataAbortAbortException
|
||||
ldr pc, _ResvException
|
||||
ldr pc, _IrqException
|
||||
ldr pc, _FiqException
|
||||
|
||||
.globl _reset
|
||||
.globl UndefInstrExceptionHandle
|
||||
.globl SwiExceptionHandle
|
||||
.globl PrefetchAbortExceptionHandle
|
||||
.globl DataAbortExceptionHandle
|
||||
.globl ResvExceptionHandle
|
||||
.globl ExceptionIsrEntry
|
||||
.globl FiqExceptionHandle
|
||||
|
||||
_ResetException:
|
||||
.word _reset
|
||||
_UndefInstrException:
|
||||
.word UndefInstrExceptionHandle
|
||||
_SwiException:
|
||||
.word SwiExceptionHandle
|
||||
_PrefetchAbortException:
|
||||
.word PrefetchAbortExceptionHandle
|
||||
_DataAbortAbortException:
|
||||
.word DataAbortExceptionHandle
|
||||
_ResvException:
|
||||
.word ResvExceptionHandle
|
||||
_IrqException:
|
||||
.word ExceptionIsrEntry
|
||||
_FiqException:
|
||||
.word FiqExceptionHandle
|
||||
|
||||
.word 0 // extra word in RAM vectors
|
||||
|
||||
|
||||
.macro push_svc_reg
|
||||
sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */
|
||||
stmia sp, {r0 - r12} @/* Calling r0-r12 */
|
||||
mov r0, sp
|
||||
mrs r6, spsr @/* Save CPSR */
|
||||
str lr, [r0, #15*4] @/* Push PC */
|
||||
str r6, [r0, #16*4] @/* Push CPSR */
|
||||
cps #MODE_SVC
|
||||
str sp, [r0, #13*4] @/* Save calling SP */
|
||||
str lr, [r0, #14*4] @/* Save calling PC */
|
||||
.endm
|
||||
|
||||
.align 5
|
||||
.globl UndefInstrExceptionHandle
|
||||
UndefInstrExceptionHandle:
|
||||
1:
|
||||
b 1b
|
||||
|
||||
.align 5
|
||||
.globl SwiExceptionHandle
|
||||
SwiExceptionHandle:
|
||||
push_svc_reg
|
||||
bl DoSvcCallProcess
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl PrefetchAbortExceptionHandle
|
||||
PrefetchAbortExceptionHandle:
|
||||
1:
|
||||
b 1b
|
||||
|
||||
.align 5
|
||||
.globl DataAbortExceptionHandle
|
||||
DataAbortExceptionHandle:
|
||||
1:
|
||||
b 1b
|
||||
|
||||
.align 5
|
||||
.globl ResvExceptionHandle
|
||||
ResvExceptionHandle:
|
||||
1:
|
||||
b 1b
|
||||
|
||||
.section .text.isr, "ax"
|
||||
.align 5
|
||||
.globl ExceptionIsrEntry
|
||||
ExceptionIsrEntry:
|
||||
|
||||
stmfd sp!, {r0-r12,lr}
|
||||
|
||||
bl DoIrqProcess
|
||||
|
||||
@ ldr r0, =rt_thread_switch_interrupt_flag
|
||||
@ ldr r1, [r0]
|
||||
@ cmp r1, #1
|
||||
@ beq rt_hw_context_switch_interrupt_do
|
||||
|
||||
ldmfd sp!, {r0-r12,lr}
|
||||
subs pc, lr, #4
|
||||
|
||||
@ rt_hw_context_switch_interrupt_do:
|
||||
@ mov r1, #0 @ clear flag
|
||||
@ str r1, [r0]
|
||||
|
||||
@ mov r1, sp @ r1 point to {r0-r3} in stack
|
||||
@ add sp, sp, #4*4
|
||||
@ ldmfd sp!, {r4-r12,lr}@ reload saved registers
|
||||
@ mrs r0, spsr @ get cpsr of interrupt thread
|
||||
@ sub r2, lr, #4 @ save old task's pc to r2
|
||||
|
||||
@ @ Switch to SVC mode with no interrupt. If the usr mode guest is
|
||||
@ @ interrupted, this will just switch to the stack of kernel space.
|
||||
@ @ save the registers in kernel space won't trigger data abort.
|
||||
@ msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
|
||||
|
||||
@ stmfd sp!, {r2} @ push old task's pc
|
||||
@ stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4
|
||||
@ ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread
|
||||
@ stmfd sp!, {r1-r4} @ push old task's r0-r3
|
||||
@ stmfd sp!, {r0} @ push old task's cpsr
|
||||
|
||||
@ ldr r4, =rt_interrupt_from_thread
|
||||
@ ldr r5, [r4]
|
||||
@ str sp, [r5] @ store sp in preempted tasks's TCB
|
||||
|
||||
@ ldr r6, =rt_interrupt_to_thread
|
||||
@ ldr r6, [r6]
|
||||
@ ldr sp, [r6] @ get new task's stack pointer
|
||||
|
||||
@ ldmfd sp!, {r4} @ pop new task's cpsr to spsr
|
||||
@ msr spsr_cxsf, r4
|
||||
|
||||
@ ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
|
||||
|
||||
|
||||
.align 5
|
||||
.globl FiqExceptionHandle
|
||||
FiqExceptionHandle:
|
||||
1:
|
||||
b 1b
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include "gic.h"
|
||||
#include "gic_registers.h"
|
||||
#include "cortex_a9.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Prototypes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline gicd_t * gic_get_gicd(void);
|
||||
static inline gicc_t * gic_get_gicc(void);
|
||||
static inline uint32_t irq_get_register_offset(uint32_t irqID);
|
||||
static inline uint32_t irq_get_bit_offset(uint32_t irqID);
|
||||
static inline uint32_t irq_get_bit_mask(uint32_t irqID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline gicd_t * gic_get_gicd(void)
|
||||
{
|
||||
uint32_t base = get_arm_private_peripheral_base() + kGICDBaseOffset;
|
||||
return (gicd_t *)base;
|
||||
}
|
||||
|
||||
static inline gicc_t * gic_get_gicc(void)
|
||||
{
|
||||
uint32_t base = get_arm_private_peripheral_base() + kGICCBaseOffset;
|
||||
return (gicc_t *)base;
|
||||
}
|
||||
|
||||
static inline uint32_t irq_get_register_offset(uint32_t irqID)
|
||||
{
|
||||
return irqID / 32;
|
||||
}
|
||||
|
||||
static inline uint32_t irq_get_bit_offset(uint32_t irqID)
|
||||
{
|
||||
return irqID & 0x1f;
|
||||
}
|
||||
|
||||
static inline uint32_t irq_get_bit_mask(uint32_t irqID)
|
||||
{
|
||||
return 1 << irq_get_bit_offset(irqID);
|
||||
}
|
||||
|
||||
void gic_enable(bool enableIt)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
if (enableIt)
|
||||
{
|
||||
// Enable both secure and non-secure.
|
||||
gicd->CTLR |= kBM_GICD_CTLR_EnableGrp0 | kBM_GICD_CTLR_EnableGrp1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear the enable bits.
|
||||
gicd->CTLR &= ~(kBM_GICD_CTLR_EnableGrp0 | kBM_GICD_CTLR_EnableGrp1);
|
||||
}
|
||||
}
|
||||
|
||||
void gic_set_irq_security(uint32_t irqID, bool isSecure)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
uint32_t reg = irq_get_register_offset(irqID);
|
||||
uint32_t mask = irq_get_bit_mask(irqID);
|
||||
|
||||
uint32_t value = gicd->IGROUPRn[reg];
|
||||
if (!isSecure)
|
||||
{
|
||||
value &= ~mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
value |= mask;
|
||||
}
|
||||
gicd->IGROUPRn[reg] = value;
|
||||
}
|
||||
|
||||
void gic_enable_irq(uint32_t irqID, bool isEnabled)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
uint32_t reg = irq_get_register_offset(irqID);
|
||||
uint32_t mask = irq_get_bit_mask(irqID);
|
||||
|
||||
// Select set-enable or clear-enable register based on enable flag.
|
||||
if (isEnabled)
|
||||
{
|
||||
gicd->ISENABLERn[reg] = mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
gicd->ICENABLERn[reg] = mask;
|
||||
}
|
||||
}
|
||||
|
||||
void gic_set_irq_priority(uint32_t ID, uint32_t priority)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
// Update the priority register. The priority registers are byte accessible, and the register
|
||||
// struct has the priority registers as a byte array, so we can just index directly by the
|
||||
// interrupt ID.
|
||||
gicd->IPRIORITYRn[ID] = priority & 0xff;
|
||||
}
|
||||
|
||||
void gic_set_cpu_target(uint32_t irqID, unsigned cpuNumber, bool enableIt)
|
||||
{
|
||||
// Make sure the CPU number is valid.
|
||||
assert(cpuNumber <= 7);
|
||||
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
uint8_t cpuMask = 1 << cpuNumber;
|
||||
|
||||
// Like the priority registers, the target registers are byte accessible, and the register
|
||||
// struct has the them as a byte array, so we can just index directly by the
|
||||
// interrupt ID.
|
||||
if (enableIt)
|
||||
{
|
||||
gicd->ITARGETSRn[irqID] |= (cpuMask & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
gicd->ITARGETSRn[irqID] &= ~(cpuMask & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void gic_send_sgi(uint32_t irqID, uint32_t target_list, uint32_t filter_list)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
gicd->SGIR = (filter_list << kBP_GICD_SGIR_TargetListFilter)
|
||||
| (target_list << kBP_GICD_SGIR_CPUTargetList)
|
||||
| (irqID & 0xf);
|
||||
}
|
||||
|
||||
void gic_cpu_enable(bool enableIt)
|
||||
{
|
||||
gicc_t * gicc = gic_get_gicc();
|
||||
|
||||
if (enableIt)
|
||||
{
|
||||
gicc->CTLR |= kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS;
|
||||
}
|
||||
else
|
||||
{
|
||||
gicc->CTLR &= ~(kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS);
|
||||
}
|
||||
}
|
||||
|
||||
void gic_set_cpu_priority_mask(uint32_t priority)
|
||||
{
|
||||
gicc_t * gicc = gic_get_gicc();
|
||||
gicc->PMR = priority & 0xff;
|
||||
}
|
||||
|
||||
uint32_t gic_read_irq_ack(void)
|
||||
{
|
||||
gicc_t * gicc = gic_get_gicc();
|
||||
return gicc->IAR;
|
||||
}
|
||||
|
||||
void gic_write_end_of_irq(uint32_t irqID)
|
||||
{
|
||||
gicc_t * gicc = gic_get_gicc();
|
||||
gicc->EOIR = irqID;
|
||||
}
|
||||
|
||||
void gic_init(void)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
// First disable the distributor.
|
||||
gic_enable(false);
|
||||
|
||||
// Clear all pending interrupts.
|
||||
int i;
|
||||
for (i = 0; i < 32; ++i)
|
||||
{
|
||||
gicd->ICPENDRn[i] = 0xffffffff;
|
||||
}
|
||||
|
||||
// Set all interrupts to secure.
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
gicd->IGROUPRn[i] = 0;
|
||||
}
|
||||
|
||||
// Init the GIC CPU interface.
|
||||
gic_init_cpu();
|
||||
|
||||
// Now enable the distributor.
|
||||
gic_enable(true);
|
||||
}
|
||||
|
||||
void gic_init_cpu(void)
|
||||
{
|
||||
// Init the GIC CPU interface.
|
||||
gic_set_cpu_priority_mask(0xff);
|
||||
|
||||
// Disable preemption.
|
||||
gicc_t * gicc = gic_get_gicc();
|
||||
gicc->BPR = 7;
|
||||
|
||||
// Enable signaling the CPU.
|
||||
gic_cpu_enable(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __GIC_H__
|
||||
#define __GIC_H__
|
||||
|
||||
#include "sdk_types.h"
|
||||
|
||||
//! @addtogroup gic
|
||||
//! @{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief Options for sending a software generated interrupt.
|
||||
//!
|
||||
//! These options are used for the @a filter_list parameter of the gic_send_sgi()
|
||||
//! function. They control how to select which CPUs that the interrupt is
|
||||
//! sent to.
|
||||
enum _gicd_sgi_filter
|
||||
{
|
||||
//! Forward the interrupt to the CPU interfaces specified in the @a target_list parameter.
|
||||
kGicSgiFilter_UseTargetList = 0,
|
||||
|
||||
//! Forward the interrupt to all CPU interfaces except that of the processor that requested
|
||||
//! the interrupt.
|
||||
kGicSgiFilter_AllOtherCPUs = 1,
|
||||
|
||||
//! Forward the interrupt only to the CPU interface of the processor that requested the
|
||||
//! interrupt.
|
||||
kGicSgiFilter_OnlyThisCPU = 2
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//! @name Initialization
|
||||
//@{
|
||||
//! @brief Init interrupt handling.
|
||||
//!
|
||||
//! This function is intended to be called only by the primary CPU init code, so it will
|
||||
//! only be called once during system bootup.
|
||||
//!
|
||||
//! Also inits the current CPU. You don't need to call gic_init_cpu() separately.
|
||||
//!
|
||||
//! @post The interrupt distributor and the current CPU interface are enabled. All interrupts
|
||||
//! that were pending are cleared, and all interrupts are made secure (group 0).
|
||||
void gic_init(void);
|
||||
|
||||
//! @brief Init the current CPU's GIC interface.
|
||||
//!
|
||||
//! @post Enables the CPU interface and sets the priority mask to 255. Interrupt preemption
|
||||
//! is disabled by setting the Binary Point to a value of 7.
|
||||
void gic_init_cpu(void);
|
||||
//@}
|
||||
|
||||
//! @name GIC Interrupt Distributor Functions
|
||||
//@{
|
||||
//! @brief Enable or disable the GIC Distributor.
|
||||
//!
|
||||
//! Enables or disables the GIC distributor passing both secure (group 0) and non-secure
|
||||
//! (group 1) interrupts to the CPU interfaces.
|
||||
//!
|
||||
//! @param enableIt Pass true to enable or false to disable.
|
||||
void gic_enable(bool enableIt);
|
||||
|
||||
//! @brief Set the security mode for an interrupt.
|
||||
//!
|
||||
//! @param irqID The interrupt number.
|
||||
//! @param isSecure Whether the interrupt is taken to secure mode.
|
||||
void gic_set_irq_security(uint32_t irqID, bool isSecure);
|
||||
|
||||
//! @brief Enable or disable an interrupt.
|
||||
//!
|
||||
//! @param irqID The number of the interrupt to control.
|
||||
//! @param isEnabled Pass true to enable or false to disable.
|
||||
void gic_enable_irq(uint32_t irqID, bool isEnabled);
|
||||
|
||||
//! @brief Set whether a CPU will receive a particular interrupt.
|
||||
//!
|
||||
//! @param irqID The interrupt number.
|
||||
//! @param cpuNumber The CPU number. The first CPU core is 0.
|
||||
//! @param enableIt Whether to send the interrupt to the specified CPU. Pass true to enable
|
||||
//! or false to disable.
|
||||
void gic_set_cpu_target(uint32_t irqID, unsigned cpuNumber, bool enableIt);
|
||||
|
||||
//! @brief Set an interrupt's priority.
|
||||
//!
|
||||
//! @param irq_id The interrupt number.
|
||||
//! @param priority The priority for the interrupt. In the range of 0 through 0xff, with
|
||||
//! 0 being the highest priority.
|
||||
void gic_set_irq_priority(uint32_t irq_id, uint32_t priority);
|
||||
|
||||
//! @brief Send a software generated interrupt to a specific CPU.
|
||||
//!
|
||||
//! @param irq_id The interrupt number to send.
|
||||
//! @param target_list Each bit indicates a CPU to which the interrupt will be forwarded.
|
||||
//! Bit 0 is CPU 0, bit 1 is CPU 1, and so on. If the value is 0, then the interrupt
|
||||
//! will not be forwarded to any CPUs. This parameter is only used if @a filter_list
|
||||
//! is set to #kGicSgiFilter_UseTargetList.
|
||||
//! @param filter_list One of the enums of the #_gicd_sgi_filter enumeration. The selected
|
||||
//! option determines which CPUs the interrupt will be sent to. If the value
|
||||
//! is #kGicSgiFilter_UseTargetList, then the @a target_list parameter is used.
|
||||
void gic_send_sgi(uint32_t irq_id, uint32_t target_list, uint32_t filter_list);
|
||||
//@}
|
||||
|
||||
//! @name GIC CPU Interface Functions
|
||||
//@{
|
||||
//! @brief Enable or disable the interface to the GIC for the current CPU.
|
||||
//!
|
||||
//! @param enableIt Pass true to enable or false to disable.
|
||||
void gic_cpu_enable(bool enableIt);
|
||||
|
||||
//! @brief Set the mask of which interrupt priorities the CPU will receive.
|
||||
//!
|
||||
//! @param priority The lowest priority that will be passed to the current CPU. Pass 0xff to
|
||||
//! allow all priority interrupts to signal the CPU.
|
||||
void gic_set_cpu_priority_mask(uint32_t priority);
|
||||
|
||||
//! @brief Acknowledge starting of interrupt handling and get the interrupt number.
|
||||
//!
|
||||
//! Normally, this function is called at the beginning of the IRQ handler. It tells the GIC
|
||||
//! that you are starting to handle an interupt, and returns the number of the interrupt you
|
||||
//! need to handle. After the interrupt is handled, you should call gic_write_end_of_irq()
|
||||
//! to signal that the interrupt is completely handled.
|
||||
//!
|
||||
//! In some cases, a spurious interrupt might happen. One possibility is if another CPU handles
|
||||
//! the interrupt. When a spurious interrupt occurs, the end of the interrupt should be indicated
|
||||
//! but nothing else.
|
||||
//!
|
||||
//! @return The number for the highest priority interrupt available for the calling CPU. If
|
||||
//! the return value is 1022 or 1023, a spurious interrupt has occurred.
|
||||
uint32_t gic_read_irq_ack(void);
|
||||
|
||||
//! @brief Signal the end of handling an interrupt.
|
||||
//!
|
||||
//! @param irq_id The number of the interrupt for which handling has finished.
|
||||
void gic_write_end_of_irq(uint32_t irq_id);
|
||||
//@}
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // __GIC_H__
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "sdk_types.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief Offsets to the GIC registers.
|
||||
enum _gic_base_offsets
|
||||
{
|
||||
kGICDBaseOffset = 0x1000, //!< GIC distributor offset.
|
||||
kGICCBaseOffset = 0x100 //!< GIC CPU interface offset.
|
||||
};
|
||||
|
||||
//! @brief GIC distributor registers.
|
||||
//!
|
||||
//! Uses the GICv2 register names, but does not include GICv2 registers.
|
||||
//!
|
||||
//! The IPRIORITYRn and ITARGETSRn registers are byte accessible, so their types are uint8_t
|
||||
//! instead of uint32_t to reflect this. These members are indexed directly with the interrupt
|
||||
//! number.
|
||||
struct _gicd_registers
|
||||
{
|
||||
uint32_t CTLR; //!< Distributor Control Register.
|
||||
uint32_t TYPER; //!< Interrupt Controller Type Register.
|
||||
uint32_t IIDR; //!< Distributor Implementer Identification Register.
|
||||
uint32_t _reserved0[29];
|
||||
uint32_t IGROUPRn[8]; //!< Interrupt Group Registers.
|
||||
uint32_t _reserved1[24];
|
||||
uint32_t ISENABLERn[32]; //!< Interrupt Set-Enable Registers.
|
||||
uint32_t ICENABLERn[32]; //!< Interrupt Clear-Enable Registers.
|
||||
uint32_t ISPENDRn[32]; //!< Interrupt Set-Pending Registers.
|
||||
uint32_t ICPENDRn[32]; //!< Interrupt Clear-Pending Registers.
|
||||
uint32_t ICDABRn[32]; //!< Active Bit Registers.
|
||||
uint32_t _reserved2[32];
|
||||
uint8_t IPRIORITYRn[255 * sizeof(uint32_t)]; //!< Interrupt Priority Registers. (Byte accessible)
|
||||
uint32_t _reserved3;
|
||||
uint8_t ITARGETSRn[255 * sizeof(uint32_t)]; //!< Interrupt Processor Targets Registers. (Byte accessible)
|
||||
uint32_t _reserved4;
|
||||
uint32_t ICFGRn[64]; //!< Interrupt Configuration Registers.
|
||||
uint32_t _reserved5[128];
|
||||
uint32_t SGIR; //!< Software Generated Interrupt Register
|
||||
};
|
||||
|
||||
//! @brief Bitfields constants for the GICD_CTLR register.
|
||||
enum _gicd_ctlr_fields
|
||||
{
|
||||
kBM_GICD_CTLR_EnableGrp1 = (1 << 1),
|
||||
kBM_GICD_CTLR_EnableGrp0 = (1 << 0)
|
||||
};
|
||||
|
||||
//! @brief Bitfields constants for the GICD_SGIR register.
|
||||
enum _gicd_sgir_fields
|
||||
{
|
||||
kBP_GICD_SGIR_TargetListFilter = 24,
|
||||
kBM_GICD_SGIR_TargetListFilter = (0x3 << kBP_GICD_SGIR_TargetListFilter),
|
||||
|
||||
kBP_GICD_SGIR_CPUTargetList = 16,
|
||||
kBM_GICD_SGIR_CPUTargetList = (0xff << kBP_GICD_SGIR_CPUTargetList),
|
||||
|
||||
kBP_GICD_SGIR_NSATT = 15,
|
||||
kBM_GICD_SGIR_NSATT = (1 << kBP_GICD_SGIR_NSATT),
|
||||
|
||||
kBP_GICD_SGIR_SGIINTID = 0,
|
||||
kBM_GICD_SGIR_SGIINTID = 0xf
|
||||
};
|
||||
|
||||
//! @brief GIC CPU interface registers.
|
||||
//!
|
||||
//! Uses the GICv2 register names. Does not include GICv2 registers.
|
||||
struct _gicc_registers
|
||||
{
|
||||
uint32_t CTLR; //!< CPU Interface Control Register.
|
||||
uint32_t PMR; //!< Interrupt Priority Mask Register.
|
||||
uint32_t BPR; //!< Binary Point Register.
|
||||
uint32_t IAR; //!< Interrupt Acknowledge Register.
|
||||
uint32_t EOIR; //!< End of Interrupt Register.
|
||||
uint32_t RPR; //!< Running Priority Register.
|
||||
uint32_t HPPIR; //!< Highest Priority Pending Interrupt Register.
|
||||
uint32_t ABPR; //!< Aliased Binary Point Register. (only visible with a secure access)
|
||||
uint32_t _reserved[56];
|
||||
uint32_t IIDR; //!< CPU Interface Identification Register.
|
||||
};
|
||||
|
||||
//! @brief Bitfields constants for the GICC_CTLR register.
|
||||
enum _gicc_ctlr_fields
|
||||
{
|
||||
kBP_GICC_CTLR_EnableS = 0,
|
||||
kBM_GICC_CTLR_EnableS = (1 << 0),
|
||||
|
||||
kBP_GICC_CTLR_EnableNS = 1,
|
||||
kBM_GICC_CTLR_EnableNS = (1 << 1),
|
||||
|
||||
kBP_GICC_CTLR_AckCtl = 2,
|
||||
kBM_GICC_CTLR_AckCtl = (1 << 2),
|
||||
|
||||
kBP_GICC_CTLR_FIQEn = 3,
|
||||
kBM_GICC_CTLR_FIQEn = (1 << 3),
|
||||
|
||||
kBP_GICC_CTLR_SBPR = 4,
|
||||
kBM_GICC_CTLR_SBPR = (1 << 4)
|
||||
};
|
||||
|
||||
//! @brier Type for the GIC distributor registers.
|
||||
typedef volatile struct _gicd_registers gicd_t;
|
||||
|
||||
//! @brier Type for the GIC CPU interface registers.
|
||||
typedef volatile struct _gicc_registers gicc_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,111 @@
|
|||
// extern void _svcall(uintptr_t* contex);
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <isr.h>
|
||||
|
||||
uint32_t DisableLocalInterrupt(void)
|
||||
{
|
||||
uint32_t intSave;
|
||||
__asm__ __volatile__(
|
||||
"mrs %0, cpsr \n"
|
||||
"cpsid if "
|
||||
: "=r"(intSave)
|
||||
:
|
||||
: "memory");
|
||||
return intSave;
|
||||
}
|
||||
|
||||
void EnableLocalInterrupt(unsigned long level)
|
||||
{
|
||||
uint32_t intSave;
|
||||
__asm__ __volatile__(
|
||||
"mrs %0, cpsr \n"
|
||||
"cpsie if "
|
||||
: "=r"(intSave)
|
||||
:
|
||||
: "memory");
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t ArchEnableHwIrq(uint32_t irq_num)
|
||||
{
|
||||
// gic_set_irq_priority(irq_num, priority);
|
||||
gic_set_irq_security(irq_num, false); // set IRQ as non-secure
|
||||
// gic_set_cpu_target(irq_num, CPU_0, true);
|
||||
gic_enable_irq(irq_num, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ArchDisableHwIrq(uint32_t irq_num)
|
||||
{
|
||||
gic_enable_irq(irq_num, false);
|
||||
// gic_set_cpu_target(irq_num, CPU_0, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void KTaskOsAssignAfterIrq(void *context);
|
||||
|
||||
void IsrEntry(uint32_t irq_num)
|
||||
{
|
||||
isrManager.done->incCounter();
|
||||
isrManager.done->handleIrq(irq_num);
|
||||
// KTaskOsAssignAfterIrq(NULL);
|
||||
isrManager.done->decCounter();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* this function will show registers of CPU
|
||||
*
|
||||
* @param regs the registers point
|
||||
*/
|
||||
void PrintStackFrame(struct ExceptionStackRegister *regs)
|
||||
{
|
||||
// KPrintf("Execption:\n");
|
||||
// KPrintf("r0: 0x%08x\n", regs->r0);
|
||||
// KPrintf("r1: 0x%08x\n", regs->r1);
|
||||
// KPrintf("r2: 0x%08x\n", regs->r2);
|
||||
// KPrintf("r3: 0x%08x\n", regs->r3);
|
||||
// KPrintf("r4: 0x%08x\n", regs->r4);
|
||||
// KPrintf("r5: 0x%08x\n", regs->r5);
|
||||
// KPrintf("r6: 0x%08x\n", regs->r6);
|
||||
// KPrintf("r7: 0x%08x\n", regs->r7);
|
||||
// KPrintf("r8: 0x%08x\n", regs->r8);
|
||||
// KPrintf("r9: 0x%08x\n", regs->r9);
|
||||
// KPrintf("r10: 0x%08x\n", regs->r10);
|
||||
// KPrintf("r11: 0x%08x\n", regs->r11);
|
||||
// KPrintf("r12: 0x%08x\n", regs->r12);
|
||||
// KPrintf("r13_sp: 0x%08x\n", regs->r13_sp);
|
||||
// KPrintf("r14_lr: 0x%08x\n", regs->r14_lr);
|
||||
// KPrintf("r15_pc: 0x%08x\n", regs->r15_pc);
|
||||
// KPrintf("cpsr: 0x%08x\n", regs->cpsr);
|
||||
}
|
||||
|
||||
|
||||
void DoSvcCallProcess(struct ExceptionStackRegister *regs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DoIrqProcess(void)
|
||||
{
|
||||
uint32_t iar = gic_read_irq_ack();
|
||||
uint32_t irq_num = iar & 0x3ff;
|
||||
|
||||
if(irq_num >= ARCH_MAX_IRQ_NUM)
|
||||
{
|
||||
gic_write_end_of_irq(irq_num);
|
||||
return;
|
||||
}
|
||||
|
||||
IsrEntry(irq_num);
|
||||
|
||||
gic_write_end_of_irq(irq_num);
|
||||
}
|
||||
// uintptr_t *Svcall(unsigned int ipsr, uintptr_t* contex )
|
||||
// {
|
||||
// #ifdef TASK_ISOLATION
|
||||
// _svcall(contex);
|
||||
// #endif
|
||||
// return contex;
|
||||
// }
|
|
@ -0,0 +1,10 @@
|
|||
OBJS := $(shell cat make.obj)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
@echo ------------------------------------------------
|
||||
@echo link $(TARGET)
|
||||
@$(CROSS_COMPILE)g++ -o $@ $($(LINK_FLAGS)) $(OBJS) $(LINK_MUSLLIB) $(LIBCC)
|
||||
@echo ------------------------------------------------
|
||||
@$(CROSS_COMPILE)objcopy -O binary $@ XiZi-$(BOARD)$(COMPILE_TYPE).bin
|
||||
@$(CROSS_COMPILE)objcopy -O ihex $@ XiZi-$(BOARD)$(COMPILE_TYPE).hex
|
||||
@$(CROSS_COMPILE)size $@
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
export KERNELPATHS:= -I$(BSP_ROOT)
|
||||
|
||||
ifeq ($(CONFIG_LIB_MUSLLIB), y)
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/services/lib/musllib/src/include \
|
||||
-I$(KERNEL_ROOT)/services/lib/musllib/include \
|
||||
-I$(KERNEL_ROOT)/services/lib/musllib/src/internal #
|
||||
# chose arch for musl
|
||||
ifeq ($(ARCH), arm)
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/services/lib/musllib/arch/arm
|
||||
endif
|
||||
ifeq ($(ARCH), risc-v)
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/services/lib/musllib/arch/riscv64
|
||||
endif
|
||||
|
||||
endif # end of musl include path
|
||||
|
||||
ifeq ($(CONFIG_LIB_NEWLIB),y)
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/services/lib/newlib/include #
|
||||
endif
|
||||
|
||||
ifeq ($(BSP_ROOT),$(KERNEL_ROOT)/services/boards/imx6q-sabrelite)
|
||||
KERNELPATHS += \
|
||||
-I$(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9 \
|
||||
-I$(KERNEL_ROOT)/hardkernel/abstraction \
|
||||
-I$(KERNEL_ROOT)/include \
|
||||
-I$(BSP_ROOT)/include
|
||||
|
||||
ifeq ($(CONFIG_RESOURCES_LWIP),y)
|
||||
KERNELPATHS += \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/compat \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/netif \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/apps \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch
|
||||
endif
|
||||
endif
|
||||
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Applications/general_functions/list #
|
||||
|
||||
ifeq ($(ARCH), arm)
|
||||
KERNELPATHS +=-I$(KERNEL_ROOT)/arch/arm/shared \
|
||||
-I$(KERNEL_ROOT)/lib/comlibc/common #
|
||||
endif
|
||||
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/kernel/include #
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue