diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index 4fc3bfbfa..6e1581cea 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -8,5 +8,26 @@ menu "test app" bool "Config test spi flash" default n + menuconfig USER_TEST_ADC + bool "Config test adc" + default n + if USER_TEST_ADC + if ADD_XIUOS_FETURES + config ADC_DEV_DRIVER + string "Set ADC dev path" + default "/dev/adc1_dev" + endif + endif + + menuconfig USER_TEST_DAC + bool "Config test dac" + default n + if USER_TEST_DAC + if ADD_XIUOS_FETURES + config DAC_DEV_DRIVER + string "Set DAC dev path" + default "/dev/dac_dev" + endif + endif endif endmenu diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 96322c1c5..8a74e5531 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -4,4 +4,12 @@ ifeq ($(CONFIG_USER_TEST_SPI_FLASH),y) SRC_FILES += test_spi_flash.c endif +ifeq ($(CONFIG_USER_TEST_ADC),y) + SRC_FILES += test_adc.c +endif + +ifeq ($(CONFIG_USER_TEST_DAC),y) + SRC_FILES += test_dac.c +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Applications/app_test/test_adc.c b/APP_Framework/Applications/app_test/test_adc.c new file mode 100644 index 000000000..fbbf3ed09 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_adc.c @@ -0,0 +1,60 @@ +/* +* 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: test_adc.c +* @brief: a application of adc function +* @version: 1.1 +* @author: AIIT XUOS Lab +* @date: 2022/1/7 +*/ + +#include +#include +#include + +void test_adc() +{ + int adc_fd; + uint8 adc_channel = 0x0; + uint16 adc_sample, adc_value_decimal = 0; + float adc_value; + + adc_fd = PrivOpen(ADC_DEV_DRIVER, O_RDWR); + if (adc_fd < 0) { + KPrintf("open adc fd error %d\n", adc_fd); + return; + } + + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = ADC_TYPE; + ioctl_cfg.args = &adc_channel; + if (0 != PrivIoctl(adc_fd, OPE_CFG, &ioctl_cfg)) { + KPrintf("ioctl adc fd error %d\n", adc_fd); + PrivClose(adc_fd); + return; + } + + PrivRead(adc_fd, &adc_sample, 2); + + adc_value = (float)adc_sample * (3.3 / 4096); + + adc_value_decimal = (adc_value - (uint16)adc_value) * 1000; + + printf("adc sample %u value integer %u decimal %u\n", adc_sample, (uint16)adc_value, adc_value_decimal); + + PrivClose(adc_fd); + + return; +} +// SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), +// test_adc, test_adc, read 3.3 voltage data from adc); diff --git a/APP_Framework/Applications/app_test/test_dac.c b/APP_Framework/Applications/app_test/test_dac.c new file mode 100644 index 000000000..60c2f8bfb --- /dev/null +++ b/APP_Framework/Applications/app_test/test_dac.c @@ -0,0 +1,60 @@ +/* +* 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: test_dac.c +* @brief: a application of dac function +* @version: 2.0 +* @author: AIIT XUOS Lab +* @date: 2022/1/11 +*/ + +#include +#include +#include + +void test_dac() +{ + int dac_fd; + uint16 dac_set_value = 800; + uint16 dac_sample, dac_value_decimal = 0; + float dac_value; + + dac_fd = PrivOpen(DAC_DEV_DRIVER, O_RDWR); + if (dac_fd < 0) { + KPrintf("open dac fd error %d\n", dac_fd); + return; + } + + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = DAC_TYPE; + ioctl_cfg.args = &dac_set_value; + if (0 != PrivIoctl(dac_fd, OPE_CFG, &ioctl_cfg)) { + KPrintf("ioctl dac fd error %d\n", dac_fd); + PrivClose(dac_fd); + return; + } + + PrivRead(dac_fd, &dac_sample, 2); + + dac_value = (float)dac_sample * (3.3 / 4096);//Vref+ need to be 3.3V + + dac_value_decimal = (dac_value - (uint16)dac_value) * 1000; + + printf("dac sample %u value integer %u decimal %u\n", dac_sample, (uint16)dac_value, dac_value_decimal); + + PrivClose(dac_fd); + + return; +} +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), + test_dac, test_dac, set digital data to dac); diff --git a/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c b/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c index 08452c8ee..b018be453 100755 --- a/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c +++ b/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c @@ -38,7 +38,7 @@ char tcp_socket_ip[] = {192, 168, 250, 252}; -#define TCP_BUF_SIZE 1024 +#define TCP_DEMO_BUF_SIZE 65535 /******************************************************************************* * Code @@ -46,17 +46,15 @@ char tcp_socket_ip[] = {192, 168, 250, 252}; static void tcp_recv_demo(void *arg) { - lw_print("tcp_recv_demo start.\n"); - - int fd = -1; - char *recv_buf; - struct sockaddr_in tcp_addr, server_addr; + int fd = -1, clientfd; int recv_len; + char *recv_buf; + struct sockaddr_in tcp_addr; socklen_t addr_len; while(1) { - recv_buf = (char *)malloc(TCP_BUF_SIZE); + recv_buf = (char *)malloc(TCP_DEMO_BUF_SIZE); if (recv_buf == NULL) { lw_print("No memory\n"); @@ -72,7 +70,7 @@ static void tcp_recv_demo(void *arg) tcp_addr.sin_family = AF_INET; tcp_addr.sin_addr.s_addr = INADDR_ANY; - tcp_addr.sin_port = htons(LOCAL_PORT_SERVER); + tcp_addr.sin_port = htons(LWIP_LOCAL_PORT); memset(&(tcp_addr.sin_zero), 0, sizeof(tcp_addr.sin_zero)); if (bind(fd, (struct sockaddr *)&tcp_addr, sizeof(struct sockaddr)) == -1) @@ -81,16 +79,30 @@ static void tcp_recv_demo(void *arg) goto __exit; } - lw_print("tcp bind sucess, start to receive.\n"); - lw_print("\n\nLocal Port:%d\n\n", LOCAL_PORT_SERVER); + lw_print("tcp bind success, start to receive.\n"); + lw_print("\n\nLocal Port:%d\n\n", LWIP_LOCAL_PORT); + + // setup socket fd as listening mode + if (listen(fd, 5) != 0 ) + { + lw_print("Unable to listen\n"); + goto __exit; + } + + // accept client connection + clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len); + lw_print("client %s connected\n", inet_ntoa(tcp_addr.sin_addr)); while(1) { - memset(recv_buf, 0, TCP_BUF_SIZE); - recv_len = recvfrom(fd, recv_buf, TCP_BUF_SIZE, 0, (struct sockaddr *)&server_addr, &addr_len); - lw_pr_info("Receive from : %s\n", inet_ntoa(server_addr.sin_addr)); - lw_pr_info("Receive data : %s\n\n", recv_buf); - sendto(fd, recv_buf, recv_len, 0, (struct sockaddr*)&server_addr, addr_len); + 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) + { + lw_pr_info("Receive from : %s\n", inet_ntoa(tcp_addr.sin_addr)); + lw_pr_info("Receive data : %d - %s\n\n", recv_len, recv_buf); + } + sendto(clientfd, recv_buf, recv_len, 0, (struct sockaddr*)&tcp_addr, addr_len); } __exit: @@ -116,7 +128,7 @@ void tcp_socket_recv_run(int argc, char *argv[]) ETH_BSP_Config(); lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); - sys_thread_new("tcp_recv_demo", tcp_recv_demo, NULL, 4096, 15); + sys_thread_new("tcp_recv_demo", tcp_recv_demo, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), @@ -124,11 +136,12 @@ SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | static void tcp_send_demo(void *arg) { - int cnt = TEST_LWIP_TIMES; - lw_print("tcp_send_demo start.\n"); + int cnt = LWIP_DEMO_TIMES; int fd = -1; char send_msg[128]; + lw_print("%s start\n", __func__); + memset(send_msg, 0, sizeof(send_msg)); fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) @@ -139,8 +152,8 @@ static void tcp_send_demo(void *arg) struct sockaddr_in tcp_sock; tcp_sock.sin_family = AF_INET; - tcp_sock.sin_port = htons(TARGET_PORT_CLIENT); - tcp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(tcp_socket_ip[0],tcp_socket_ip[1],tcp_socket_ip[2],tcp_socket_ip[3])); + tcp_sock.sin_port = htons(LWIP_TARGET_PORT); + tcp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(tcp_socket_ip[0], tcp_socket_ip[1], tcp_socket_ip[2], tcp_socket_ip[3])); memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero)); if (connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr))) @@ -150,14 +163,14 @@ static void tcp_send_demo(void *arg) } lw_print("tcp connect success, start to send.\n"); - lw_print("\n\nTarget Port:%d\n\n", tcp_sock.sin_port); + lw_pr_info("\n\nTarget Port:%d\n\n", tcp_sock.sin_port); while (cnt --) { lw_print("Lwip client is running.\n"); snprintf(send_msg, sizeof(send_msg), "TCP test package times %d\r\n", cnt); sendto(fd, send_msg, strlen(send_msg), 0, (struct sockaddr*)&tcp_sock, sizeof(struct sockaddr)); - lw_print("Send tcp msg: %s ", send_msg); + lw_pr_info("Send tcp msg: %s ", send_msg); MdelayKTask(1000); } @@ -178,8 +191,8 @@ void tcp_socket_send_run(int argc, char *argv[]) } ETH_BSP_Config(); - lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); - sys_thread_new("tcp socket", tcp_send_demo, NULL, 4096, 25); + lwip_config_tcp(lwip_ipaddr, lwip_netmask, tcp_socket_ip); + sys_thread_new("tcp socket", tcp_send_demo, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), diff --git a/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c b/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c index 3f71783a3..b04311f5f 100755 --- a/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c +++ b/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c @@ -78,7 +78,7 @@ static void udp_recv_demo(void *arg) udp_addr.sin_family = AF_INET; udp_addr.sin_addr.s_addr = INADDR_ANY; - udp_addr.sin_port = htons(LOCAL_PORT_SERVER); + udp_addr.sin_port = htons(LWIP_LOCAL_PORT); memset(&(udp_addr.sin_zero), 0, sizeof(udp_addr.sin_zero)); if (bind(socket_fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1) @@ -88,7 +88,7 @@ static void udp_recv_demo(void *arg) } lw_print("UDP bind sucess, start to receive.\n"); - lw_print("\n\nLocal Port:%d\n\n", LOCAL_PORT_SERVER); + lw_print("\n\nLocal Port:%d\n\n", LWIP_LOCAL_PORT); while(1) { @@ -135,7 +135,7 @@ SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | static void udp_send_demo(void *arg) { - int cnt = TEST_LWIP_TIMES; + int cnt = LWIP_DEMO_TIMES; char send_str[128]; lw_print("udp_send_demo start.\n"); @@ -152,7 +152,7 @@ static void udp_send_demo(void *arg) struct sockaddr_in udp_sock; udp_sock.sin_family = AF_INET; - udp_sock.sin_port = htons(TARGET_PORT_CLIENT); + udp_sock.sin_port = htons(LWIP_TARGET_PORT); udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_target[0],udp_target[1],udp_target[2],udp_target[3])); memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero)); diff --git a/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c b/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c index 76634b9d4..9e948c81f 100755 --- a/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c +++ b/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c @@ -28,10 +28,9 @@ /******************************************************************************* * Definitions ******************************************************************************/ -//#define ua_print KPrintf -#define ua_trace() KPrintf("ua: [%s] %d pass!\n", __func__, __LINE__) #define TCP_LOCAL_PORT 4840 +#define UA_URL_SIZE 100 /******************************************************************************* * Prototypes @@ -41,24 +40,19 @@ * Variables ******************************************************************************/ -const char *test_uri = "opc.tcp://192.168.250.5:4840"; -const char *test_cb_str = "tcp client connected\r\n"; - -char test_ua_gw[] = {192, 168, 250, 5}; - -static pthread_t eth_input_id = 0; -static pthread_t ua_demo_id; +char test_ua_ip[] = {192, 168, 250, 5}; /******************************************************************************* * Code ******************************************************************************/ -void *test_ua_get_server_info(void *param); - static void test_ua_connect(void *arg) { struct netif net; UA_StatusCode retval; + char ua_uri[UA_URL_SIZE]; + + memset(ua_uri, 0, sizeof(ua_uri)); UA_Client *client = UA_Client_new(); @@ -71,7 +65,10 @@ static void test_ua_connect(void *arg) UA_ClientConfig *config = UA_Client_getConfig(client); UA_ClientConfig_setDefault(config); - retval = UA_Client_connect(client, test_uri); + snprintf(ua_uri, UA_URL_SIZE, "opc.tcp://%d.%d.%d.%d:4840", + test_ua_ip[0], test_ua_ip[1], test_ua_ip[2], test_ua_ip[3]); + + retval = UA_Client_connect(client, ua_uri); if (retval != UA_STATUSCODE_GOOD) { ua_print("ua: [%s] ret %x\n", __func__, retval); @@ -85,7 +82,7 @@ static void test_ua_connect(void *arg) void test_ua_connect_thr(void *arg) { ETH_BSP_Config(); - lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_gw); + lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); test_ua_connect(NULL); } @@ -100,16 +97,16 @@ void test_sh_ua_connect(void) SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), UaConnect, test_sh_ua_connect, Test Opc UA connection); -void *test_ua_get_server_info(void *param) +void test_ua_browser_objects(void *param) { UA_Client *client = UA_Client_new(); - ua_print("ua: [%s] start ...\n", __func__); + ua_pr_info("ua: [%s] start ...\n", __func__); if (client == NULL) { ua_print("ua: [%s] tcp client null\n", __func__); - return NULL; + return; } UA_ClientConfig *config = UA_Client_getConfig(client); @@ -119,12 +116,69 @@ void *test_ua_get_server_info(void *param) if(retval != UA_STATUSCODE_GOOD) { ua_print("ua: [%s] connect failed %#x\n", __func__, retval); UA_Client_delete(client); - return NULL; + return; } ua_print("ua: [%s] connect ok!\n", __func__); + ua_pr_info("--- start read time ---\n", __func__); ua_read_time(client); + + ua_pr_info("--- get server info ---\n", __func__); + ua_browser_objects(client); + + /* Clean up */ + UA_Client_disconnect(client); + UA_Client_delete(client); /* Disconnects the client internally */ +} + +void *test_sh_ua_brower_objects(int argc, char *argv[]) +{ + if(argc == 2) + { + if(isdigit(argv[1][0])) + { + if(sscanf(argv[1], "%d.%d.%d.%d", &test_ua_ip[0], &test_ua_ip[1], &test_ua_ip[2], &test_ua_ip[3]) == EOF) + { + lw_pr_info("input wrong ip\n"); + return NULL; + } + } + } + + ETH_BSP_Config(); + lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); + sys_thread_new("ua object", test_ua_browser_objects, NULL, 4096, 15); + return NULL; +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), + UaObj, test_sh_ua_brower_objects, UaObj [IP]); + +void test_ua_get_info(void *param) +{ + UA_Client *client = UA_Client_new(); + + ua_pr_info("ua: [%s] start ...\n", __func__); + + if (client == NULL) + { + ua_print("ua: [%s] tcp client null\n", __func__); + return; + } + + UA_ClientConfig *config = UA_Client_getConfig(client); + UA_ClientConfig_setDefault(config); + + UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER); + if(retval != UA_STATUSCODE_GOOD) { + ua_print("ua: [%s] connect failed %#x\n", __func__, retval); + UA_Client_delete(client); + return; + } + + ua_print("ua: [%s] connect ok!\n", __func__); + ua_pr_info("--- get server info ---\n", __func__); ua_get_server_info(client); /* Clean up */ @@ -132,29 +186,26 @@ void *test_ua_get_server_info(void *param) UA_Client_delete(client); /* Disconnects the client internally */ } -void *test_ua_get_server_info_thr(void *arg) +void *test_sh_ua_get_info(int argc, char *argv[]) { - ETH_BSP_Config(); - lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_gw); - test_ua_get_server_info(NULL); -} - -void *test_sh_ua_get_server_info(void *param) -{ - int result = 0; - pthread_attr_t attr; - - attr.schedparam.sched_priority = 15; - attr.stacksize = 4096; - - result = pthread_create(&ua_demo_id, &attr, test_ua_get_server_info_thr, NULL); - if (0 == result) { - lw_print("test_ua_get_server_info %d successfully!\n", __func__, ua_demo_id); - } else { - lw_print("test_ua_get_server_info failed! error code is %d\n", __func__, result); + if(argc == 2) + { + if(isdigit(argv[1][0])) + { + if(sscanf(argv[1], "%d.%d.%d.%d", &test_ua_ip[0], &test_ua_ip[1], &test_ua_ip[2], &test_ua_ip[3]) == EOF) + { + lw_pr_info("input wrong ip\n"); + return NULL; + } + } } + + ETH_BSP_Config(); + lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); + sys_thread_new("ua object", test_ua_browser_objects, NULL, 4096, 15); + return NULL; } -SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), - UaGetInfo, test_sh_ua_get_server_info, Get information from OpcUA server); +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), + UaInfo, test_sh_ua_get_info, UaInfo [IP]); diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/open62541.c b/APP_Framework/Framework/control/plc/interoperability/opcua/open62541.c index 961f243a1..d94e28a6b 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/open62541.c +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/open62541.c @@ -46,9 +46,7 @@ #endif #include "open62541.h" - -#define ua_print KPrintf -#define ua_trace() KPrintf("ua: [%s] line %d checked!\n", __func__, __LINE__) +#include "ua_api.h" #if LWIP_DNS @@ -7147,6 +7145,8 @@ encodeWithExchangeBuffer(const void *ptr, const UA_DataType *type, Ctx *ctx) { ctx->pos = oldpos; /* Set to the last known good position and exchange */ ret = exchangeBuffer(ctx); UA_CHECK_STATUS(ret, return ret); + + ua_print("ua: [%s] exchange kind %d ret %d\n", __func__, type->typeKind, ret); ret = encodeBinaryJumpTable[type->typeKind](ptr, type, ctx); } return ret; @@ -7493,6 +7493,11 @@ Array_encodeBinary(const void *src, size_t length, const UA_DataType *type, Ctx ret = Array_encodeBinaryComplex((uintptr_t)src, length, type, ctx); } UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); + + //tst by wly + ua_debug("ua: [%s] src %p len %d %d type %p <%d> <%d> %p ret %d\n", __func__, + src, length, signed_length, *type, type->typeKind, type->overlayable, ctx, ret); + return ret; } @@ -8335,6 +8340,26 @@ encodeBinaryStruct(const void *src, const UA_DataType *type, Ctx *ctx) { const UA_DataType *mt = m->memberType; ptr += m->padding; + if(mt->typeKind > UA_DATATYPEKINDS) + { + ua_debug("ua: [%s] %d type %d %p ptr %p failed\n", __func__, i, mt->typeKind, m->memberType, ptr); + return ret; + } + + ua_debug("ua: [%s] > %d < %d mt %p %d %d dep %d msg %p %p:<%x> <%d> isArry %d ret %d\n", __func__, + i, + type->membersSize, + mt, + mt->typeKind, + mt->memSize, + ctx->depth, + ptr, + src, + ((UA_TcpMessageHeader *)src)->messageTypeAndChunkType, + ((UA_TcpMessageHeader *)src)->messageSize, + m->isArray, + ret); + /* Array. Buffer-exchange is done inside Array_encodeBinary if required. */ if(m->isArray) { const size_t length = *((const size_t*)ptr); @@ -8348,6 +8373,21 @@ encodeBinaryStruct(const void *src, const UA_DataType *type, Ctx *ctx) { /* Scalar */ ret = encodeWithExchangeBuffer((const void*)ptr, mt, ctx); UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); + + ua_debug("ua: [%s] >> %d < %d mt %p %d %d dep %d msg %p %p:<%x> <%d> isArry %d ret %d\n", __func__, + i, + type->membersSize, + mt, + mt->typeKind, + mt->memSize, + ctx->depth, + ptr, + src, + ((UA_TcpMessageHeader *)src)->messageTypeAndChunkType, + ((UA_TcpMessageHeader *)src)->messageSize, + m->isArray, + ret); + ptr += mt->memSize; } @@ -8584,20 +8624,70 @@ decodeBinaryStructure(void *dst, const UA_DataType *type, Ctx *ctx) { const UA_DataType *mt = m->memberType; ptr += m->padding; + if(mt->typeKind >= UA_DATATYPEKINDS) + { + ua_debug("ua: [%s] fail %d < %d mt %p %d %d dep %d msg %p %p:<%x> <%d>\n", __func__, + i, + membersSize, + mt, + mt->typeKind, + mt->memSize, + ctx->depth, + ptr, + dst, + ((UA_TcpMessageHeader *)dst)->messageTypeAndChunkType, + ((UA_TcpMessageHeader *)dst)->messageSize); + + return ret; + } + + ua_debug("ua: [%s] > %d < %d mt %p %d %d dep %d msg %p %p:<%x> <%d> isArry %d ret %d\n", __func__, + i, + membersSize, + mt, + mt->typeKind, + mt->memSize, + ctx->depth, + ptr, + dst, + ((UA_TcpMessageHeader *)dst)->messageTypeAndChunkType, + ((UA_TcpMessageHeader *)dst)->messageSize, + m->isArray, + ret); + /* Array */ if(m->isArray) { size_t *length = (size_t*)ptr; ptr += sizeof(size_t); ret = Array_decodeBinary((void *UA_RESTRICT *UA_RESTRICT)ptr, length, mt , ctx); ptr += sizeof(void*); + ua_debug("ua: [%s] %d ret %d ptr %p len %d\n", __func__, i, ret, ptr, length); continue; } /* Scalar */ ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx); ptr += mt->memSize; + + ua_debug("ua: [%s] >> %d < %d dep %d msg %p %p:<%x> <%d> ret %d\n", __func__, + i, + membersSize, + ctx->depth, + ptr, + dst, + ((UA_TcpMessageHeader *)dst)->messageTypeAndChunkType, + ((UA_TcpMessageHeader *)dst)->messageSize, + ret); } + ua_debug("ua: [%s] >>> dep %d msg %p %p:<%x> <%d> ret %d\n", __func__, + ctx->depth, + ptr, + dst, + ((UA_TcpMessageHeader *)dst)->messageTypeAndChunkType, + ((UA_TcpMessageHeader *)dst)->messageSize, + ret); + ctx->depth--; return ret; } @@ -8739,8 +8829,18 @@ UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset, /* Decode */ memset(dst, 0, type->memSize); /* Initialize the value */ + + ua_debug("ua: [%s] t %d mem %d len %d off %d pos %d end %d dst %p type %x size %x\n", __func__, + type->typeKind, type->memSize, src->length, *offset, *ctx.pos, *ctx.end, + dst, ((UA_TcpMessageHeader *)dst)->messageTypeAndChunkType, + ((UA_TcpMessageHeader *)dst)->messageSize); + status ret = decodeBinaryJumpTable[type->typeKind](dst, type, &ctx); + ua_debug("ua: [%s] -> t %d dst %p type %x size %x ret %d\n", __func__, + type->typeKind, dst, ((UA_TcpMessageHeader *)dst)->messageTypeAndChunkType, + ((UA_TcpMessageHeader *)dst)->messageSize, ret); + if(UA_LIKELY(ret == UA_STATUSCODE_GOOD)) { /* Set the new offset */ *offset = (size_t)(ctx.pos - src->data) / sizeof(u8); @@ -8748,7 +8848,16 @@ UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset, /* Clean up */ UA_clear(dst, type); memset(dst, 0, type->memSize); + + ua_debug("ua: [%s] => t %d dst %p type %x size %x\n", __func__, + type->typeKind, dst, ((UA_TcpMessageHeader *)dst)->messageTypeAndChunkType, + ((UA_TcpMessageHeader *)dst)->messageSize); } + + ua_debug("ua: [%s] #> off %d %p %p t %d dst %p type %x size %x\n", __func__, *offset, + ctx.pos, src->data, + type->typeKind, dst, ((UA_TcpMessageHeader *)dst)->messageTypeAndChunkType, + ((UA_TcpMessageHeader *)dst)->messageSize); return ret; } @@ -18516,6 +18625,12 @@ processChunks(UA_SecureChannel *channel, void *application, channel->decryptedChunksCount > channel->config.localMaxChunkCount) || (channel->config.localMaxMessageSize != 0 && channel->decryptedChunksLength > channel->config.localMaxMessageSize)) { + ua_print("ua: [%s] count %d max %d len %d mess %d\n", + channel->decryptedChunksCount, + channel->config.localMaxChunkCount, + channel->decryptedChunksLength, + channel->config.localMaxMessageSize + ); return UA_STATUSCODE_BADTCPMESSAGETOOLARGE; } @@ -18552,6 +18667,10 @@ extractCompleteChunk(UA_SecureChannel *channel, const UA_ByteString *buffer, UA_StatusCode res = UA_decodeBinaryInternal(buffer, &initial_offset, &hdr, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], NULL); + + ua_debug("ua: [%s] res %d buf %p offset %d hdr %d size %d\n", __func__, res, buffer, *offset, + hdr.messageTypeAndChunkType, hdr.messageSize); + UA_assert(res == UA_STATUSCODE_GOOD); (void)res; /* pacify compilers if assert is ignored */ UA_MessageType msgType = (UA_MessageType) @@ -18563,7 +18682,10 @@ extractCompleteChunk(UA_SecureChannel *channel, const UA_ByteString *buffer, if(hdr.messageSize < UA_SECURECHANNEL_MESSAGE_MIN_LENGTH) return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID; if(hdr.messageSize > channel->config.recvBufferSize) + { + ua_debug("lw: [%s] msg size %d rec %d\n", __func__, hdr.messageSize, channel->config.recvBufferSize); return UA_STATUSCODE_BADTCPMESSAGETOOLARGE; + } /* Incomplete chunk */ if(hdr.messageSize > remaining) { @@ -44134,6 +44256,8 @@ UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) { client->sessionState < UA_SESSIONSTATE_ACTIVATED) { retval = connectIterate(client, timeout); notifyClientState(client); + lw_print("lw: [%s] ret %d timeout %d state %d ch %d\n", __func__, retval, timeout, + client->sessionState, client->channel.state); return retval; } @@ -45075,21 +45199,21 @@ connectIterate(UA_Client *client, UA_UInt32 timeout) { return UA_STATUSCODE_BADCONNECTIONCLOSED; } + ua_debug("ua: [%s] conn %d state %d handle %p\n", __func__, client->connectStatus, + client->connection.state, client->connection.handle); + /* The connection is closed. Reset the SecureChannel and open a new TCP * connection */ if(client->connection.state == UA_CONNECTIONSTATE_CLOSED) return initConnect(client); - ua_print("ua: [%s] state %d %d handle %p\n", __func__, client->connectStatus, - client->connection.state, client->connection.handle); - /* Poll the connection status */ if(client->connection.state == UA_CONNECTIONSTATE_OPENING) { client->connectStatus = client->config.pollConnectionFunc(&client->connection, timeout, &client->config.logger); - ua_print("ua: [%s] exit conn %x %d time %d handle %p\n", __func__, + ua_debug("ua: [%s] exit conn %x %d time %d handle %p\n", __func__, client->connectStatus, client->connection.state, timeout, client->connection.handle); @@ -45175,6 +45299,7 @@ connectIterate(UA_Client *client, UA_UInt32 timeout) { break; } + lw_print("lw: [%s] sess %d conn %d\n", __func__, client->sessionState, client->connectStatus); return client->connectStatus; } @@ -45286,6 +45411,8 @@ connectSync(UA_Client *client) { UA_DateTime now = UA_DateTime_nowMonotonic(); UA_DateTime maxDate = now + ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC); + ua_print("ua; [%s] time %d\n", __func__, (UA_DateTime)client->config.timeout); + UA_StatusCode retval = initConnect(client); if(retval != UA_STATUSCODE_GOOD) return retval; @@ -68096,6 +68223,9 @@ void UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category, const char *msg, va_list args) { + char str[120]; + memset(str, 0, sizeof(str)); + /* Assume that context is casted to UA_LogLevel */ /* TODO we may later change this to a struct with bitfields to filter on category */ if ( context != NULL && (UA_LogLevel)(uintptr_t)context > level ) @@ -68115,8 +68245,8 @@ UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category, KPrintf("%s/%s" ANSI_COLOR_RESET "\t", logLevelNames[level], logCategoryNames[category]); - - KPrintf(msg, args); + vsnprintf(str, sizeof(str) - 1, msg, args); + KPrintf(msg, str); KPrintf("\n"); // printf("\n"); @@ -70191,7 +70321,7 @@ UA_Client * UA_Client_new() { UA_StatusCode UA_ClientConfig_setDefault(UA_ClientConfig *config) { - config->timeout = 5000; + config->timeout = 20000; config->secureChannelLifeTime = 10 * 60 * 1000; /* 10 minutes */ if(!config->logger.log) { @@ -70656,13 +70786,15 @@ UA_Log_Syslog_withLevel(UA_LogLevel minlevel) { #define configTICK_RATE_HZ TICK_PER_SECOND #define xTaskGetTickCount CurrentTicksGain -#define EHOSTUNREACH 113 /* No route to host */ -#define EINPROGRESS 115 /* Operation now in progress */ #define EADDRINUSE 98 /* Address already in use */ -#define EALREADY 114 /* Operation already in progress */ +#define ECONNABORTED 103 /* Software caused connection abort */ + #define EISCONN 106 /* Transport endpoint is already connected */ #define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ECONNABORTED 103 /* Software caused connection abort */ + +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ #ifdef UA_ARCHITECTURE_FREERTOSLWIP_POSIX_CLOCK diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h index 19790b2a6..30345d4c5 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h @@ -15,10 +15,16 @@ #include "open62541.h" #define OPC_SERVER "opc.tcp://192.168.250.5:4840" -#define ua_print printf + +#define ua_print //printf +#define ua_trace() //printf("ua: [%s] line %d checked!\n", __func__, __LINE__) +#define ua_pr_info KPrintf +#define ua_debug int ua_server_connect(void); int ua_get_server_info(UA_Client *client); +void ua_browser_objects(UA_Client *client); +void ua_browser_nodes(UA_Client *client); void ua_read_time(UA_Client *client); int16 ua_test(void); diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_client.c b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_client.c index a6795b618..eb8e439ea 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_client.c +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_client.c @@ -12,9 +12,7 @@ #include "open62541.h" #include - -#define OPC_SERVER "opc.tcp://192.168.250.5:4840" -#define ua_print printf +#include "ua_api.h" #ifdef UA_ENABLE_SUBSCRIPTIONS static void handler_TheAnswerChanged(UA_Client *client, UA_UInt32 subId, void *subContext, @@ -32,7 +30,7 @@ static UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId } UA_NodeId *parent = (UA_NodeId *)handle; - ua_print("%d, %d --- %d ---> NodeId %d, %d\n", + ua_pr_info("%d, %d --- %d ---> NodeId %d, %d\n", parent->namespaceIndex, parent->identifier.numeric, referenceTypeId.identifier.numeric, childId.namespaceIndex, childId.identifier.numeric); @@ -61,32 +59,42 @@ int ua_get_points(UA_Client *client) endpointArray[i].endpointUrl.data); } UA_Array_delete(endpointArray,endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); - return EXIT_SUCCESS; + return EXIT_SUCCESS; } void ua_browser_objects(UA_Client *client) { /* Browse some objects */ - ua_print("Browsing nodes in objects folder:\n"); + ua_pr_info("Browsing nodes in objects folder:\n"); + UA_BrowseRequest bReq; UA_BrowseRequest_init(&bReq); + bReq.requestedMaxReferencesPerNode = 0; bReq.nodesToBrowse = UA_BrowseDescription_new(); bReq.nodesToBrowseSize = 1; bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); /* browse objects folder */ bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; /* return everything */ + UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq); - ua_print("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME"); - for(size_t i = 0; i < bResp.resultsSize; ++i) { - for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) { + + ua_pr_info("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME"); + + for(size_t i = 0; i < bResp.resultsSize; ++i) + { + for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) + { UA_ReferenceDescription *ref = &(bResp.results[i].references[j]); - if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC) { - ua_print("%-9d %-16d %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex, + if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC) + { + ua_pr_info("%-9d %-16d %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex, ref->nodeId.nodeId.identifier.numeric, (int)ref->browseName.name.length, ref->browseName.name.data, (int)ref->displayName.text.length, ref->displayName.text.data); - } else if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_STRING) { - ua_print("%-9d %-16.*s %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex, + } + else if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_STRING) + { + ua_pr_info("%-9d %-16.*s %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex, (int)ref->nodeId.nodeId.identifier.string.length, ref->nodeId.nodeId.identifier.string.data, (int)ref->browseName.name.length, ref->browseName.name.data, @@ -95,6 +103,7 @@ void ua_browser_objects(UA_Client *client) /* TODO: distinguish further types */ } } + ua_pr_info("\n"); UA_BrowseRequest_clear(&bReq); UA_BrowseResponse_clear(&bResp); } @@ -133,7 +142,7 @@ UA_UInt32 ua_start_sub(UA_Client *client) /* The first publish request should return the initial value of the variable */ UA_Client_run_iterate(client, 1000); - return subId; + return subId; } void ua_read_attr(UA_Client *client) @@ -165,7 +174,8 @@ void ua_read_attr(UA_Client *client) wReq.nodesToWrite[0].value.value.data = &value; UA_WriteResponse wResp = UA_Client_Service_write(client, wReq); if(wResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD) - ua_print("the new value is: %i\n", value); + ua_print("the new value is: %i\n", value); + UA_WriteRequest_clear(&wReq); UA_WriteResponse_clear(&wResp); @@ -189,11 +199,14 @@ void ua_call_remote(UA_Client *client) UA_Variant *output; UA_StatusCode retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output); - if(retval == UA_STATUSCODE_GOOD) { + if(retval == UA_STATUSCODE_GOOD) + { ua_print("Method call was successful, and %lu returned values available.\n", (unsigned long)outputSize); UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]); - } else { + } + else + { ua_print("Method call was unsuccessful, and %x returned values available.\n", retval); } UA_Variant_clear(&input); @@ -271,33 +284,16 @@ void ua_add_nodes(UA_Client *client) int ua_get_server_info(UA_Client *client) { - UA_StatusCode retval; - - /* Listing endpoints */ - retval = ua_get_points(client); - if(retval != UA_STATUSCODE_GOOD) { - UA_Client_delete(client); - return EXIT_FAILURE; - } - - /* Connect to a server */ - /* anonymous connect would be: retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); */ - retval = UA_Client_connect(client, OPC_SERVER); - if(retval != UA_STATUSCODE_GOOD) { - UA_Client_delete(client); - return EXIT_FAILURE; - } - - ua_browser_objects(client); + ua_browser_objects(client); /* Same thing, this time using the node iterator... */ - ua_browser_nodes(client); + ua_browser_nodes(client); #ifdef UA_ENABLE_SUBSCRIPTIONS - UA_Int32 subId = ua_start_sub(client); + UA_Int32 subId = ua_start_sub(client); #endif - ua_read_attr(client); + ua_read_attr(client); #ifdef UA_ENABLE_SUBSCRIPTIONS /* Take another look at the.answer */ @@ -308,11 +304,11 @@ int ua_get_server_info(UA_Client *client) #endif #ifdef UA_ENABLE_METHODCALLS - ua_call_remote(client); + ua_call_remote(client); #endif #ifdef UA_ENABLE_NODEMANAGEMENT - ua_add_nodes(client); + ua_add_nodes(client); #endif return EXIT_SUCCESS; diff --git a/APP_Framework/Framework/transform_layer/xiuos/transform.c b/APP_Framework/Framework/transform_layer/xiuos/transform.c index 36d7c3181..4ae2d21b3 100644 --- a/APP_Framework/Framework/transform_layer/xiuos/transform.c +++ b/APP_Framework/Framework/transform_layer/xiuos/transform.c @@ -164,6 +164,10 @@ int PrivIoctl(int fd, int cmd, void *args) case LCD_TYPE: ret = PrivLcdIoctl(fd, cmd, ioctl_cfg->args); break; + case ADC_TYPE: + case DAC_TYPE: + ret = ioctl(fd, cmd, ioctl_cfg->args); + break; default: break; } diff --git a/APP_Framework/Framework/transform_layer/xiuos/transform.h b/APP_Framework/Framework/transform_layer/xiuos/transform.h index a43c13770..209d96ffa 100644 --- a/APP_Framework/Framework/transform_layer/xiuos/transform.h +++ b/APP_Framework/Framework/transform_layer/xiuos/transform.h @@ -139,6 +139,8 @@ enum IoctlDriverType I2C_TYPE, PIN_TYPE, LCD_TYPE, + ADC_TYPE, + DAC_TYPE, DEFAULT_TYPE, }; diff --git a/APP_Framework/Kconfig b/APP_Framework/Kconfig index e63a1a14d..8e96e6f76 100644 --- a/APP_Framework/Kconfig +++ b/APP_Framework/Kconfig @@ -5,8 +5,8 @@ menu "APP_Framework" option env="SRC_APP_DIR" default "." -source "$APP_DIR/Applications/Kconfig" source "$APP_DIR/Framework/Kconfig" +source "$APP_DIR/Applications/Kconfig" source "$APP_DIR/lib/Kconfig" diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/board.c b/Ubiquitous/XiUOS/board/aiit-arm32-board/board.c index 5bad81d7c..d7b03ef99 100644 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/board.c +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/board.c @@ -48,6 +48,8 @@ extern int Stm32HwTouchBusInit(void); extern int Stm32HwCanBusInit(void); extern int HwSdioInit(); extern int HwSramInit(void); +extern int Stm32HwAdcInit(void); +extern int Stm32HwDacInit(void); static void ClockConfiguration() { @@ -146,6 +148,12 @@ struct InitSequenceDesc _board_init[] = #endif #ifdef BSP_USING_EXTMEM { "hw extern sram", HwSramInit }, +#endif +#ifdef BSP_USING_ADC + {"hw adc init", Stm32HwAdcInit}, +#endif +#ifdef BSP_USING_DAC + {"hw dac init", Stm32HwDacInit}, #endif { " NONE ",NONE }, }; diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Kconfig b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Kconfig index b48232b0d..cf0b85e9f 100755 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Kconfig +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Kconfig @@ -94,8 +94,21 @@ if BSP_USING_UART source "$BSP_DIR/third_party_driver/uart/Kconfig" endif +menuconfig BSP_USING_ADC +bool "Using ADC device" +default n +select RESOURCES_ADC +if BSP_USING_ADC +source "$BSP_DIR/third_party_driver/adc/Kconfig" +endif - +menuconfig BSP_USING_DAC +bool "Using DAC device" +default n +select RESOURCES_DAC +if BSP_USING_DAC +source "$BSP_DIR/third_party_driver/dac/Kconfig" +endif menuconfig BSP_USING_CAN bool "Using CAN device" diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Makefile b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Makefile index 6eed5c45e..dd2c65616 100644 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Makefile +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/Makefile @@ -4,7 +4,6 @@ ifeq ($(CONFIG_BSP_USING_CH438),y) SRC_DIR += ch438 endif - ifeq ($(CONFIG_BSP_USING_EXTMEM),y) SRC_DIR += extmem endif @@ -57,4 +56,12 @@ ifeq ($(CONFIG_BSP_USING_CAN),y) SRC_DIR += can endif +ifeq ($(CONFIG_BSP_USING_ADC),y) + SRC_DIR += adc +endif + +ifeq ($(CONFIG_BSP_USING_DAC),y) + SRC_DIR += dac +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/Kconfig b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/Kconfig new file mode 100644 index 000000000..ac7cd3078 --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/Kconfig @@ -0,0 +1,76 @@ + + +menuconfig BSP_USING_ADC1 + bool "Enable ADC1" + default n + if BSP_USING_ADC1 + config ADC1_BUS_NAME + string "adc 1 bus name" + default "adc1" + + config ADC1_DRIVER_NAME + string "adc 1 driver name" + default "adc1_drv" + + config ADC1_DEVICE_NAME + string "adc 1 bus device name" + default "adc1_dev" + + config ADC1_GPIO_NUM + int "adc 1 gpio pin num" + default "0" + + config ADC1_GPIO_DEF + string "adc 1 gpio define type" + default "A" + endif + +menuconfig BSP_USING_ADC2 + bool "Enable ADC2" + default n + if BSP_USING_ADC2 + config ADC2_BUS_NAME + string "adc 2 bus name" + default "adc2" + + config ADC2_DRIVER_NAME + string "adc 2 driver name" + default "adc2_drv" + + config ADC2_DEVICE_NAME + string "adc 2 bus device name" + default "adc2_dev" + + config ADC2_GPIO_NUM + int "adc 2 gpio pin num" + default "6" + + config ADC2_GPIO_DEF + string "adc 2 gpio define type" + default "A" + endif + +menuconfig BSP_USING_ADC3 + bool "Enable ADC3" + default n + if BSP_USING_ADC3 + config ADC3_BUS_NAME + string "adc 3 bus name" + default "adc3" + + config ADC3_DRIVER_NAME + string "adc 3 driver name" + default "adc3_drv" + + config ADC3_DEVICE_NAME + string "adc 3 bus device name" + default "adc3_dev" + + config ADC3_GPIO_NUM + int "adc 3 gpio pin num" + default "0" + + config ADC3_GPIO_DEF + string "adc 3 gpio define type" + default "A" + endif diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/Makefile b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/Makefile new file mode 100644 index 000000000..c2dc54fa9 --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := connect_adc.c hardware_adc.c + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/connect_adc.c b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/connect_adc.c new file mode 100644 index 000000000..26f7e6494 --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/connect_adc.c @@ -0,0 +1,433 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_adc.c +* @brief support to register ADC pointer and function +* @version 1.1 +* @author AIIT XUOS Lab +* @date 2021-12-28 +*/ + +#include + +#define _ADC_CONS(string1, string2) string1##string2 +#define ADC_CONS(string1, string2) _ADC_CONS(string1, string2) + +#ifdef BSP_USING_ADC1 +#define ADC1_GPIO ADC_CONS(GPIO_Pin_, ADC1_GPIO_NUM) +#endif + +#ifdef BSP_USING_ADC2 +#define ADC2_GPIO ADC_CONS(GPIO_Pin_, ADC2_GPIO_NUM) +#endif + +#ifdef BSP_USING_ADC3 +#define ADC3_GPIO ADC_CONS(GPIO_Pin_, ADC3_GPIO_NUM) +#endif + +static int Stm32AdcUdelay(uint32 us) +{ + uint32 ticks; + uint32 told, tnow, tcnt = 0; + uint32 reload = SysTick->LOAD; + + ticks = us * reload / (1000000 / TICK_PER_SECOND); + told = SysTick->VAL; + while (1) { + tnow = SysTick->VAL; + if (tnow != told) { + if (tnow < told) { + tcnt += told - tnow; + } else { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) { + return 0; + break; + } + } + } +} + +static GPIO_TypeDef* AdcGetGpioType(char *adc_gpio_def) +{ + if (0 == strncmp(adc_gpio_def, "A", 2)) { + return GPIOA; + } else if (0 == strncmp(adc_gpio_def, "B", 2)) { + return GPIOB; + } else if (0 == strncmp(adc_gpio_def, "C", 2)) { + return GPIOC; + } else if (0 == strncmp(adc_gpio_def, "F", 2)) { + return GPIOF; + } else { + printf("AdcGetGpioType do not support %s GPIO\n", adc_gpio_def); + return GPIOA; + } +} + +static uint32 AdcGetGpioRcc(char *adc_gpio_def) +{ + if (0 == strncmp(adc_gpio_def, "A", 2)) { + return RCC_AHB1Periph_GPIOA; + } else if (0 == strncmp(adc_gpio_def, "B", 2)) { + return RCC_AHB1Periph_GPIOB; + } else if (0 == strncmp(adc_gpio_def, "C", 2)) { + return RCC_AHB1Periph_GPIOC; + } else if (0 == strncmp(adc_gpio_def, "F", 2)) { + return RCC_AHB1Periph_GPIOF; + } else { + printf("AdcGetGpioRcc do not support %s GPIO\n", adc_gpio_def); + return RCC_AHB1Periph_GPIOA; + } +} + +static void AdcInit(struct AdcHardwareDevice *adc_dev) +{ + GPIO_InitTypeDef GPIO_InitStructure; + ADC_CommonInitTypeDef ADC_CommonInitStructure; + ADC_InitTypeDef ADC_InitStructure; + uint32_t RCC_AHB1Periph; + GPIO_TypeDef* GPIOx; + +#ifdef BSP_USING_ADC1 + if (0 == strncmp(adc_dev->haldev.dev_name, ADC1_DEVICE_NAME, NAME_NUM_MAX)) { + + GPIOx = AdcGetGpioType(ADC1_GPIO_DEF); + RCC_AHB1Periph = AdcGetGpioRcc(ADC1_GPIO_DEF); + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph, ENABLE);//enable GPIOA clock + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//enable ADC1 clock + + GPIO_InitStructure.GPIO_Pin = ADC1_GPIO; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//analog input + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOx, &GPIO_InitStructure); + + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE); + + ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; + ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; + ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; + ADC_CommonInit(&ADC_CommonInitStructure); + + ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12 bit mode + ADC_InitStructure.ADC_ScanConvMode = DISABLE; + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; + ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStructure.ADC_NbrOfConversion = 1; + ADC_Init(ADC1, &ADC_InitStructure); + + ADC_Cmd(ADC1, ENABLE); + } +#endif + +#ifdef BSP_USING_ADC2 + if (0 == strncmp(adc_dev->haldev.dev_name, ADC2_DEVICE_NAME, NAME_NUM_MAX)) { + + GPIOx = AdcGetGpioType(ADC2_GPIO_DEF); + RCC_AHB1Periph = AdcGetGpioRcc(ADC2_GPIO_DEF); + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph, ENABLE);//enable GPIOA clock + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);//enable ADC2 clock + + GPIO_InitStructure.GPIO_Pin = ADC2_GPIO; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//analog input + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOx, &GPIO_InitStructure); + + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2, DISABLE); + + ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; + ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; + ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; + ADC_CommonInit(&ADC_CommonInitStructure); + + ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12 bit mode + ADC_InitStructure.ADC_ScanConvMode = DISABLE; + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; + ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStructure.ADC_NbrOfConversion = 1; + ADC_Init(ADC2, &ADC_InitStructure); + + ADC_Cmd(ADC2, ENABLE); + } +#endif + +#ifdef BSP_USING_ADC3 + if (0 == strncmp(adc_dev->haldev.dev_name, ADC3_DEVICE_NAME, NAME_NUM_MAX)) { + + GPIOx = AdcGetGpioType(ADC3_GPIO_DEF); + RCC_AHB1Periph = AdcGetGpioRcc(ADC3_GPIO_DEF); + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph, ENABLE);//enable GPIOA clock + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);//enable ADC3 clock + + GPIO_InitStructure.GPIO_Pin = ADC3_GPIO; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//analog input + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOx, &GPIO_InitStructure); + + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3, DISABLE); + + ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; + ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; + ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; + ADC_CommonInit(&ADC_CommonInitStructure); + + ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12 bit mode + ADC_InitStructure.ADC_ScanConvMode = DISABLE; + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; + ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStructure.ADC_NbrOfConversion = 1; + ADC_Init(ADC3, &ADC_InitStructure); + + ADC_Cmd(ADC3, ENABLE); + } +#endif +} + +static uint16 GetAdcValue(ADC_TypeDef *ADCx, uint8 channel) +{ + //set ADCx channel, rank, sampletime + ADC_RegularChannelConfig(ADCx, channel, 1, ADC_SampleTime_480Cycles); + + ADC_SoftwareStartConv(ADCx); + + while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC)); + + return ADC_GetConversionValue(ADCx); +} + +static uint16 GetAdcAverageValue(ADC_TypeDef *ADCx, uint8 channel, uint8 times) +{ + uint32 temp_val = 0; + int i; + + for(i = 0;i < times;i ++) { + temp_val += GetAdcValue(ADCx, channel) & 0x0FFF; + KPrintf("GetAdcAverageValue val %u\n", GetAdcValue(ADCx, channel)); + Stm32AdcUdelay(5000); + } + return temp_val / times; +} + +static uint32 Stm32AdcOpen(void *dev) +{ + struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev; + + AdcInit(adc_dev); + + return EOK; +} + +static uint32 Stm32AdcClose(void *dev) +{ + struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev; + + ADC_DeInit(); + + return EOK; +} + +static uint32 Stm32AdcRead(void *dev, struct BusBlockReadParam *read_param) +{ + struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev; + struct Stm32HwAdc *adc_cfg = (struct Stm32HwAdc *)adc_dev->haldev.private_data; + + uint16 adc_average_value = 0; + uint8 times = 20; + + adc_average_value = GetAdcAverageValue(adc_cfg->ADCx, adc_cfg->adc_channel, times); + + *(uint16 *)read_param->buffer = adc_average_value; + read_param->read_length = 2; + + return read_param->read_length; +} + +static uint32 Stm32AdcDrvConfigure(void *drv, struct BusConfigureInfo *configure_info) +{ + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(configure_info); + + x_err_t ret = EOK; + uint8 adc_channel; + + struct AdcDriver *adc_drv = (struct AdcDriver *)drv; + struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)adc_drv->driver.owner_bus->owner_haldev; + struct Stm32HwAdc *adc_cfg = (struct Stm32HwAdc *)adc_dev->haldev.private_data; + + switch (configure_info->configure_cmd) + { + case OPE_CFG: + adc_cfg->adc_channel = *(uint8 *)configure_info->private_data; + if (adc_cfg->adc_channel > 18) { + KPrintf("Stm32AdcDrvConfigure set adc channel(0-18) %u error!", adc_cfg->adc_channel); + adc_cfg->adc_channel = 0; + ret = ERROR; + } + break; + default: + break; + } + + return ret; +} + +static const struct AdcDevDone dev_done = +{ + Stm32AdcOpen, + Stm32AdcClose, + NONE, + Stm32AdcRead, +}; + +int Stm32HwAdcInit(void) +{ + x_err_t ret = EOK; + +#ifdef BSP_USING_ADC1 + static struct AdcBus adc1_bus; + static struct AdcDriver adc1_drv; + static struct AdcHardwareDevice adc1_dev; + static struct Stm32HwAdc adc1_cfg; + + adc1_drv.configure = Stm32AdcDrvConfigure; + + ret = AdcBusInit(&adc1_bus, ADC1_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC1 bus init error %d\n", ret); + return ERROR; + } + + ret = AdcDriverInit(&adc1_drv, ADC1_DRIVER_NAME); + if (ret != EOK) { + KPrintf("ADC1 driver init error %d\n", ret); + return ERROR; + } + ret = AdcDriverAttachToBus(ADC1_DRIVER_NAME, ADC1_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC1 driver attach error %d\n", ret); + return ERROR; + } + + adc1_dev.adc_dev_done = &dev_done; + adc1_cfg.ADCx = ADC1; + adc1_cfg.adc_channel = 0; + + ret = AdcDeviceRegister(&adc1_dev, (void *)&adc1_cfg, ADC1_DEVICE_NAME); + if (ret != EOK) { + KPrintf("ADC1 device register error %d\n", ret); + return ERROR; + } + ret = AdcDeviceAttachToBus(ADC1_DEVICE_NAME, ADC1_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC1 device register error %d\n", ret); + return ERROR; + } +#endif + +#ifdef BSP_USING_ADC2 + static struct AdcBus adc2_bus; + static struct AdcDriver adc2_drv; + static struct AdcHardwareDevice adc2_dev; + static struct Stm32HwAdc adc2_cfg; + + adc2_drv.configure = Stm32AdcDrvConfigure; + + ret = AdcBusInit(&adc2_bus, ADC2_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC2 bus init error %d\n", ret); + return ERROR; + } + + ret = AdcDriverInit(&adc2_drv, ADC2_DRIVER_NAME); + if (ret != EOK) { + KPrintf("ADC2 driver init error %d\n", ret); + return ERROR; + } + ret = AdcDriverAttachToBus(ADC2_DRIVER_NAME, ADC2_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC2 driver attach error %d\n", ret); + return ERROR; + } + + adc2_dev.adc_dev_done = &dev_done; + adc2_cfg.ADCx = ADC2; + adc2_cfg.adc_channel = 0; + + ret = AdcDeviceRegister(&adc2_dev, (void *)&adc2_cfg, ADC2_DEVICE_NAME); + if (ret != EOK) { + KPrintf("ADC2 device register error %d\n", ret); + return ERROR; + } + ret = AdcDeviceAttachToBus(ADC2_DEVICE_NAME, ADC2_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC2 device register error %d\n", ret); + return ERROR; + } +#endif + +#ifdef BSP_USING_ADC3 + static struct AdcBus adc3_bus; + static struct AdcDriver adc3_drv; + static struct AdcHardwareDevice adc3_dev; + static struct Stm32HwAdc adc3_cfg; + + adc3_drv.configure = Stm32AdcDrvConfigure; + + ret = AdcBusInit(&adc3_bus, ADC3_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC3 bus init error %d\n", ret); + return ERROR; + } + + ret = AdcDriverInit(&adc3_drv, ADC3_DRIVER_NAME); + if (ret != EOK) { + KPrintf("ADC3 driver init error %d\n", ret); + return ERROR; + } + ret = AdcDriverAttachToBus(ADC3_DRIVER_NAME, ADC3_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC3 driver attach error %d\n", ret); + return ERROR; + } + + adc3_dev.adc_dev_done = &dev_done; + adc3_cfg.ADCx = ADC3; + adc3_cfg.adc_channel = 0; + + ret = AdcDeviceRegister(&adc3_dev, (void *)&adc3_cfg, ADC3_DEVICE_NAME); + if (ret != EOK) { + KPrintf("ADC3 device register error %d\n", ret); + return ERROR; + } + ret = AdcDeviceAttachToBus(ADC3_DEVICE_NAME, ADC3_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC3 device register error %d\n", ret); + return ERROR; + } +#endif + + return ret; +} diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/hardware_adc.c b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/hardware_adc.c new file mode 100644 index 000000000..a7bc99366 --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/adc/hardware_adc.c @@ -0,0 +1,1765 @@ +/** + ****************************************************************************** + * @file stm32f4xx_adc.c + * @author MCD Application Team + * @version V1.4.0 + * @date 04-August-2014 + * @brief This file provides firmware functions to manage the following + * functionalities of the Analog to Digital Convertor (ADC) peripheral: + * + Initialization and Configuration (in addition to ADC multi mode + * selection) + * + Analog Watchdog configuration + * + Temperature Sensor & Vrefint (Voltage Reference internal) & VBAT + * management + * + Regular Channels Configuration + * + Regular Channels DMA Configuration + * + Injected channels Configuration + * + Interrupts and flags management + * + @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + (#) Enable the ADC interface clock using + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADCx, ENABLE); + + (#) ADC pins configuration + (++) Enable the clock for the ADC GPIOs using the following function: + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE); + (++) Configure these ADC pins in analog mode using GPIO_Init(); + + (#) Configure the ADC Prescaler, conversion resolution and data + alignment using the ADC_Init() function. + (#) Activate the ADC peripheral using ADC_Cmd() function. + + *** Regular channels group configuration *** + ============================================ + [..] + (+) To configure the ADC regular channels group features, use + ADC_Init() and ADC_RegularChannelConfig() functions. + (+) To activate the continuous mode, use the ADC_continuousModeCmd() + function. + (+) To configurate and activate the Discontinuous mode, use the + ADC_DiscModeChannelCountConfig() and ADC_DiscModeCmd() functions. + (+) To read the ADC converted values, use the ADC_GetConversionValue() + function. + + *** Multi mode ADCs Regular channels configuration *** + ====================================================== + [..] + (+) Refer to "Regular channels group configuration" description to + configure the ADC1, ADC2 and ADC3 regular channels. + (+) Select the Multi mode ADC regular channels features (dual or + triple mode) using ADC_CommonInit() function and configure + the DMA mode using ADC_MultiModeDMARequestAfterLastTransferCmd() + functions. + (+) Read the ADCs converted values using the + ADC_GetMultiModeConversionValue() function. + + *** DMA for Regular channels group features configuration *** + ============================================================= + [..] + (+) To enable the DMA mode for regular channels group, use the + ADC_DMACmd() function. + (+) To enable the generation of DMA requests continuously at the end + of the last DMA transfer, use the ADC_DMARequestAfterLastTransferCmd() + function. + + *** Injected channels group configuration *** + ============================================= + [..] + (+) To configure the ADC Injected channels group features, use + ADC_InjectedChannelConfig() and ADC_InjectedSequencerLengthConfig() + functions. + (+) To activate the continuous mode, use the ADC_continuousModeCmd() + function. + (+) To activate the Injected Discontinuous mode, use the + ADC_InjectedDiscModeCmd() function. + (+) To activate the AutoInjected mode, use the ADC_AutoInjectedConvCmd() + function. + (+) To read the ADC converted values, use the ADC_GetInjectedConversionValue() + function. + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/** +* @file: hardware_adc.c +* @brief: support hardware adc function +* @version: 1.1 +* @author: AIIT XUOS Lab +* @date: 2021/12/28 +*/ + +/************************************************* +File name: hardware_adc.c +Description: support hardware adc function +Others: +History: +1. Date: 2021-12-28 +Author: AIIT XUOS Lab +Modification: +1. rename stm32f4xx_adc.c for XiUOS +*************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup ADC + * @brief ADC driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* ADC DISCNUM mask */ +#define CR1_DISCNUM_RESET ((uint32_t)0xFFFF1FFF) + +/* ADC AWDCH mask */ +#define CR1_AWDCH_RESET ((uint32_t)0xFFFFFFE0) + +/* ADC Analog watchdog enable mode mask */ +#define CR1_AWDMode_RESET ((uint32_t)0xFF3FFDFF) + +/* CR1 register Mask */ +#define CR1_CLEAR_MASK ((uint32_t)0xFCFFFEFF) + +/* ADC EXTEN mask */ +#define CR2_EXTEN_RESET ((uint32_t)0xCFFFFFFF) + +/* ADC JEXTEN mask */ +#define CR2_JEXTEN_RESET ((uint32_t)0xFFCFFFFF) + +/* ADC JEXTSEL mask */ +#define CR2_JEXTSEL_RESET ((uint32_t)0xFFF0FFFF) + +/* CR2 register Mask */ +#define CR2_CLEAR_MASK ((uint32_t)0xC0FFF7FD) + +/* ADC SQx mask */ +#define SQR3_SQ_SET ((uint32_t)0x0000001F) +#define SQR2_SQ_SET ((uint32_t)0x0000001F) +#define SQR1_SQ_SET ((uint32_t)0x0000001F) + +/* ADC L Mask */ +#define SQR1_L_RESET ((uint32_t)0xFF0FFFFF) + +/* ADC JSQx mask */ +#define JSQR_JSQ_SET ((uint32_t)0x0000001F) + +/* ADC JL mask */ +#define JSQR_JL_SET ((uint32_t)0x00300000) +#define JSQR_JL_RESET ((uint32_t)0xFFCFFFFF) + +/* ADC SMPx mask */ +#define SMPR1_SMP_SET ((uint32_t)0x00000007) +#define SMPR2_SMP_SET ((uint32_t)0x00000007) + +/* ADC JDRx registers offset */ +#define JDR_OFFSET ((uint8_t)0x28) + +/* ADC CDR register base address */ +#define CDR_ADDRESS ((uint32_t)0x40012308) + +/* ADC CCR register Mask */ +#define CR_CLEAR_MASK ((uint32_t)0xFFFC30E0) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup ADC_Private_Functions + * @{ + */ + +/** @defgroup ADC_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize and configure the ADC Prescaler + (+) ADC Conversion Resolution (12bit..6bit) + (+) Scan Conversion Mode (multichannel or one channel) for regular group + (+) ADC Continuous Conversion Mode (Continuous or Single conversion) for + regular group + (+) External trigger Edge and source of regular group, + (+) Converted data alignment (left or right) + (+) The number of ADC conversions that will be done using the sequencer for + regular channel group + (+) Multi ADC mode selection + (+) Direct memory access mode selection for multi ADC mode + (+) Delay between 2 sampling phases (used in dual or triple interleaved modes) + (+) Enable or disable the ADC peripheral +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes all ADCs peripherals registers to their default reset + * values. + * @param None + * @retval None + */ +void ADC_DeInit(void) +{ + /* Enable all ADCs reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC, ENABLE); + + /* Release all ADCs from reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC, DISABLE); +} + +/** + * @brief Initializes the ADCx peripheral according to the specified parameters + * in the ADC_InitStruct. + * @note This function is used to configure the global features of the ADC ( + * Resolution and Data Alignment), however, the rest of the configuration + * parameters are specific to the regular channels group (scan mode + * activation, continuous mode activation, External trigger source and + * edge, number of conversion in the regular channels group sequencer). + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_InitStruct: pointer to an ADC_InitTypeDef structure that contains + * the configuration information for the specified ADC peripheral. + * @retval None + */ +void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct) +{ + uint32_t tmpreg1 = 0; + uint8_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_RESOLUTION(ADC_InitStruct->ADC_Resolution)); + assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ScanConvMode)); + assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ContinuousConvMode)); + assert_param(IS_ADC_EXT_TRIG_EDGE(ADC_InitStruct->ADC_ExternalTrigConvEdge)); + assert_param(IS_ADC_EXT_TRIG(ADC_InitStruct->ADC_ExternalTrigConv)); + assert_param(IS_ADC_DATA_ALIGN(ADC_InitStruct->ADC_DataAlign)); + assert_param(IS_ADC_REGULAR_LENGTH(ADC_InitStruct->ADC_NbrOfConversion)); + + /*---------------------------- ADCx CR1 Configuration -----------------*/ + /* Get the ADCx CR1 value */ + tmpreg1 = ADCx->CR1; + + /* Clear RES and SCAN bits */ + tmpreg1 &= CR1_CLEAR_MASK; + + /* Configure ADCx: scan conversion mode and resolution */ + /* Set SCAN bit according to ADC_ScanConvMode value */ + /* Set RES bit according to ADC_Resolution value */ + tmpreg1 |= (uint32_t)(((uint32_t)ADC_InitStruct->ADC_ScanConvMode << 8) | \ + ADC_InitStruct->ADC_Resolution); + /* Write to ADCx CR1 */ + ADCx->CR1 = tmpreg1; + /*---------------------------- ADCx CR2 Configuration -----------------*/ + /* Get the ADCx CR2 value */ + tmpreg1 = ADCx->CR2; + + /* Clear CONT, ALIGN, EXTEN and EXTSEL bits */ + tmpreg1 &= CR2_CLEAR_MASK; + + /* Configure ADCx: external trigger event and edge, data alignment and + continuous conversion mode */ + /* Set ALIGN bit according to ADC_DataAlign value */ + /* Set EXTEN bits according to ADC_ExternalTrigConvEdge value */ + /* Set EXTSEL bits according to ADC_ExternalTrigConv value */ + /* Set CONT bit according to ADC_ContinuousConvMode value */ + tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_DataAlign | \ + ADC_InitStruct->ADC_ExternalTrigConv | + ADC_InitStruct->ADC_ExternalTrigConvEdge | \ + ((uint32_t)ADC_InitStruct->ADC_ContinuousConvMode << 1)); + + /* Write to ADCx CR2 */ + ADCx->CR2 = tmpreg1; + /*---------------------------- ADCx SQR1 Configuration -----------------*/ + /* Get the ADCx SQR1 value */ + tmpreg1 = ADCx->SQR1; + + /* Clear L bits */ + tmpreg1 &= SQR1_L_RESET; + + /* Configure ADCx: regular channel sequence length */ + /* Set L bits according to ADC_NbrOfConversion value */ + tmpreg2 |= (uint8_t)(ADC_InitStruct->ADC_NbrOfConversion - (uint8_t)1); + tmpreg1 |= ((uint32_t)tmpreg2 << 20); + + /* Write to ADCx SQR1 */ + ADCx->SQR1 = tmpreg1; +} + +/** + * @brief Fills each ADC_InitStruct member with its default value. + * @note This function is used to initialize the global features of the ADC ( + * Resolution and Data Alignment), however, the rest of the configuration + * parameters are specific to the regular channels group (scan mode + * activation, continuous mode activation, External trigger source and + * edge, number of conversion in the regular channels group sequencer). + * @param ADC_InitStruct: pointer to an ADC_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct) +{ + /* Initialize the ADC_Mode member */ + ADC_InitStruct->ADC_Resolution = ADC_Resolution_12b; + + /* initialize the ADC_ScanConvMode member */ + ADC_InitStruct->ADC_ScanConvMode = DISABLE; + + /* Initialize the ADC_ContinuousConvMode member */ + ADC_InitStruct->ADC_ContinuousConvMode = DISABLE; + + /* Initialize the ADC_ExternalTrigConvEdge member */ + ADC_InitStruct->ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + + /* Initialize the ADC_ExternalTrigConv member */ + ADC_InitStruct->ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; + + /* Initialize the ADC_DataAlign member */ + ADC_InitStruct->ADC_DataAlign = ADC_DataAlign_Right; + + /* Initialize the ADC_NbrOfConversion member */ + ADC_InitStruct->ADC_NbrOfConversion = 1; +} + +/** + * @brief Initializes the ADCs peripherals according to the specified parameters + * in the ADC_CommonInitStruct. + * @param ADC_CommonInitStruct: pointer to an ADC_CommonInitTypeDef structure + * that contains the configuration information for All ADCs peripherals. + * @retval None + */ +void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct) +{ + uint32_t tmpreg1 = 0; + /* Check the parameters */ + assert_param(IS_ADC_MODE(ADC_CommonInitStruct->ADC_Mode)); + assert_param(IS_ADC_PRESCALER(ADC_CommonInitStruct->ADC_Prescaler)); + assert_param(IS_ADC_DMA_ACCESS_MODE(ADC_CommonInitStruct->ADC_DMAAccessMode)); + assert_param(IS_ADC_SAMPLING_DELAY(ADC_CommonInitStruct->ADC_TwoSamplingDelay)); + /*---------------------------- ADC CCR Configuration -----------------*/ + /* Get the ADC CCR value */ + tmpreg1 = ADC->CCR; + + /* Clear MULTI, DELAY, DMA and ADCPRE bits */ + tmpreg1 &= CR_CLEAR_MASK; + + /* Configure ADCx: Multi mode, Delay between two sampling time, ADC prescaler, + and DMA access mode for multimode */ + /* Set MULTI bits according to ADC_Mode value */ + /* Set ADCPRE bits according to ADC_Prescaler value */ + /* Set DMA bits according to ADC_DMAAccessMode value */ + /* Set DELAY bits according to ADC_TwoSamplingDelay value */ + tmpreg1 |= (uint32_t)(ADC_CommonInitStruct->ADC_Mode | + ADC_CommonInitStruct->ADC_Prescaler | + ADC_CommonInitStruct->ADC_DMAAccessMode | + ADC_CommonInitStruct->ADC_TwoSamplingDelay); + + /* Write to ADC CCR */ + ADC->CCR = tmpreg1; +} + +/** + * @brief Fills each ADC_CommonInitStruct member with its default value. + * @param ADC_CommonInitStruct: pointer to an ADC_CommonInitTypeDef structure + * which will be initialized. + * @retval None + */ +void ADC_CommonStructInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct) +{ + /* Initialize the ADC_Mode member */ + ADC_CommonInitStruct->ADC_Mode = ADC_Mode_Independent; + + /* initialize the ADC_Prescaler member */ + ADC_CommonInitStruct->ADC_Prescaler = ADC_Prescaler_Div2; + + /* Initialize the ADC_DMAAccessMode member */ + ADC_CommonInitStruct->ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + + /* Initialize the ADC_TwoSamplingDelay member */ + ADC_CommonInitStruct->ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; +} + +/** + * @brief Enables or disables the specified ADC peripheral. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the ADCx peripheral. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Set the ADON bit to wake up the ADC from power down mode */ + ADCx->CR2 |= (uint32_t)ADC_CR2_ADON; + } + else + { + /* Disable the selected ADC peripheral */ + ADCx->CR2 &= (uint32_t)(~ADC_CR2_ADON); + } +} +/** + * @} + */ + +/** @defgroup ADC_Group2 Analog Watchdog configuration functions + * @brief Analog Watchdog configuration functions + * +@verbatim + =============================================================================== + ##### Analog Watchdog configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to configure the Analog Watchdog + (AWD) feature in the ADC. + + [..] A typical configuration Analog Watchdog is done following these steps : + (#) the ADC guarded channel(s) is (are) selected using the + ADC_AnalogWatchdogSingleChannelConfig() function. + (#) The Analog watchdog lower and higher threshold are configured using the + ADC_AnalogWatchdogThresholdsConfig() function. + (#) The Analog watchdog is enabled and configured to enable the check, on one + or more channels, using the ADC_AnalogWatchdogCmd() function. +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the analog watchdog on single/all regular or + * injected channels + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_AnalogWatchdog: the ADC analog watchdog configuration. + * This parameter can be one of the following values: + * @arg ADC_AnalogWatchdog_SingleRegEnable: Analog watchdog on a single regular channel + * @arg ADC_AnalogWatchdog_SingleInjecEnable: Analog watchdog on a single injected channel + * @arg ADC_AnalogWatchdog_SingleRegOrInjecEnable: Analog watchdog on a single regular or injected channel + * @arg ADC_AnalogWatchdog_AllRegEnable: Analog watchdog on all regular channel + * @arg ADC_AnalogWatchdog_AllInjecEnable: Analog watchdog on all injected channel + * @arg ADC_AnalogWatchdog_AllRegAllInjecEnable: Analog watchdog on all regular and injected channels + * @arg ADC_AnalogWatchdog_None: No channel guarded by the analog watchdog + * @retval None + */ +void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_ANALOG_WATCHDOG(ADC_AnalogWatchdog)); + + /* Get the old register value */ + tmpreg = ADCx->CR1; + + /* Clear AWDEN, JAWDEN and AWDSGL bits */ + tmpreg &= CR1_AWDMode_RESET; + + /* Set the analog watchdog enable mode */ + tmpreg |= ADC_AnalogWatchdog; + + /* Store the new register value */ + ADCx->CR1 = tmpreg; +} + +/** + * @brief Configures the high and low thresholds of the analog watchdog. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param HighThreshold: the ADC analog watchdog High threshold value. + * This parameter must be a 12-bit value. + * @param LowThreshold: the ADC analog watchdog Low threshold value. + * This parameter must be a 12-bit value. + * @retval None + */ +void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, + uint16_t LowThreshold) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_THRESHOLD(HighThreshold)); + assert_param(IS_ADC_THRESHOLD(LowThreshold)); + + /* Set the ADCx high threshold */ + ADCx->HTR = HighThreshold; + + /* Set the ADCx low threshold */ + ADCx->LTR = LowThreshold; +} + +/** + * @brief Configures the analog watchdog guarded single channel + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_Channel: the ADC channel to configure for the analog watchdog. + * This parameter can be one of the following values: + * @arg ADC_Channel_0: ADC Channel0 selected + * @arg ADC_Channel_1: ADC Channel1 selected + * @arg ADC_Channel_2: ADC Channel2 selected + * @arg ADC_Channel_3: ADC Channel3 selected + * @arg ADC_Channel_4: ADC Channel4 selected + * @arg ADC_Channel_5: ADC Channel5 selected + * @arg ADC_Channel_6: ADC Channel6 selected + * @arg ADC_Channel_7: ADC Channel7 selected + * @arg ADC_Channel_8: ADC Channel8 selected + * @arg ADC_Channel_9: ADC Channel9 selected + * @arg ADC_Channel_10: ADC Channel10 selected + * @arg ADC_Channel_11: ADC Channel11 selected + * @arg ADC_Channel_12: ADC Channel12 selected + * @arg ADC_Channel_13: ADC Channel13 selected + * @arg ADC_Channel_14: ADC Channel14 selected + * @arg ADC_Channel_15: ADC Channel15 selected + * @arg ADC_Channel_16: ADC Channel16 selected + * @arg ADC_Channel_17: ADC Channel17 selected + * @arg ADC_Channel_18: ADC Channel18 selected + * @retval None + */ +void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CHANNEL(ADC_Channel)); + + /* Get the old register value */ + tmpreg = ADCx->CR1; + + /* Clear the Analog watchdog channel select bits */ + tmpreg &= CR1_AWDCH_RESET; + + /* Set the Analog watchdog channel */ + tmpreg |= ADC_Channel; + + /* Store the new register value */ + ADCx->CR1 = tmpreg; +} +/** + * @} + */ + +/** @defgroup ADC_Group3 Temperature Sensor, Vrefint (Voltage Reference internal) + * and VBAT (Voltage BATtery) management functions + * @brief Temperature Sensor, Vrefint and VBAT management functions + * +@verbatim + =============================================================================== + ##### Temperature Sensor, Vrefint and VBAT management functions ##### + =============================================================================== + [..] This section provides functions allowing to enable/ disable the internal + connections between the ADC and the Temperature Sensor, the Vrefint and + the Vbat sources. + + [..] A typical configuration to get the Temperature sensor and Vrefint channels + voltages is done following these steps : + (#) Enable the internal connection of Temperature sensor and Vrefint sources + with the ADC channels using ADC_TempSensorVrefintCmd() function. + (#) Select the ADC_Channel_TempSensor and/or ADC_Channel_Vrefint using + ADC_RegularChannelConfig() or ADC_InjectedChannelConfig() functions + (#) Get the voltage values, using ADC_GetConversionValue() or + ADC_GetInjectedConversionValue(). + + [..] A typical configuration to get the VBAT channel voltage is done following + these steps : + (#) Enable the internal connection of VBAT source with the ADC channel using + ADC_VBATCmd() function. + (#) Select the ADC_Channel_Vbat using ADC_RegularChannelConfig() or + ADC_InjectedChannelConfig() functions + (#) Get the voltage value, using ADC_GetConversionValue() or + ADC_GetInjectedConversionValue(). + +@endverbatim + * @{ + */ + + +/** + * @brief Enables or disables the temperature sensor and Vrefint channels. + * @param NewState: new state of the temperature sensor and Vrefint channels. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_TempSensorVrefintCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the temperature sensor and Vrefint channel*/ + ADC->CCR |= (uint32_t)ADC_CCR_TSVREFE; + } + else + { + /* Disable the temperature sensor and Vrefint channel*/ + ADC->CCR &= (uint32_t)(~ADC_CCR_TSVREFE); + } +} + +/** + * @brief Enables or disables the VBAT (Voltage Battery) channel. + * + * @note the Battery voltage measured is equal to VBAT/2 on STM32F40xx and + * STM32F41xx devices and equal to VBAT/4 on STM32F42xx and STM32F43xx devices + * + * @param NewState: new state of the VBAT channel. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_VBATCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the VBAT channel*/ + ADC->CCR |= (uint32_t)ADC_CCR_VBATE; + } + else + { + /* Disable the VBAT channel*/ + ADC->CCR &= (uint32_t)(~ADC_CCR_VBATE); + } +} + +/** + * @} + */ + +/** @defgroup ADC_Group4 Regular Channels Configuration functions + * @brief Regular Channels Configuration functions + * +@verbatim + =============================================================================== + ##### Regular Channels Configuration functions ##### + =============================================================================== + + [..] This section provides functions allowing to manage the ADC's regular channels, + it is composed of 2 sub sections : + + (#) Configuration and management functions for regular channels: This subsection + provides functions allowing to configure the ADC regular channels : + (++) Configure the rank in the regular group sequencer for each channel + (++) Configure the sampling time for each channel + (++) select the conversion Trigger for regular channels + (++) select the desired EOC event behavior configuration + (++) Activate the continuous Mode (*) + (++) Activate the Discontinuous Mode + -@@- Please Note that the following features for regular channels + are configurated using the ADC_Init() function : + (+@@) scan mode activation + (+@@) continuous mode activation (**) + (+@@) External trigger source + (+@@) External trigger edge + (+@@) number of conversion in the regular channels group sequencer. + + -@@- (*) and (**) are performing the same configuration + + (#) Get the conversion data: This subsection provides an important function in + the ADC peripheral since it returns the converted data of the current + regular channel. When the Conversion value is read, the EOC Flag is + automatically cleared. + + -@- For multi ADC mode, the last ADC1, ADC2 and ADC3 regular conversions + results data (in the selected multi mode) can be returned in the same + time using ADC_GetMultiModeConversionValue() function. + +@endverbatim + * @{ + */ +/** + * @brief Configures for the selected ADC regular channel its corresponding + * rank in the sequencer and its sample time. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_Channel: the ADC channel to configure. + * This parameter can be one of the following values: + * @arg ADC_Channel_0: ADC Channel0 selected + * @arg ADC_Channel_1: ADC Channel1 selected + * @arg ADC_Channel_2: ADC Channel2 selected + * @arg ADC_Channel_3: ADC Channel3 selected + * @arg ADC_Channel_4: ADC Channel4 selected + * @arg ADC_Channel_5: ADC Channel5 selected + * @arg ADC_Channel_6: ADC Channel6 selected + * @arg ADC_Channel_7: ADC Channel7 selected + * @arg ADC_Channel_8: ADC Channel8 selected + * @arg ADC_Channel_9: ADC Channel9 selected + * @arg ADC_Channel_10: ADC Channel10 selected + * @arg ADC_Channel_11: ADC Channel11 selected + * @arg ADC_Channel_12: ADC Channel12 selected + * @arg ADC_Channel_13: ADC Channel13 selected + * @arg ADC_Channel_14: ADC Channel14 selected + * @arg ADC_Channel_15: ADC Channel15 selected + * @arg ADC_Channel_16: ADC Channel16 selected + * @arg ADC_Channel_17: ADC Channel17 selected + * @arg ADC_Channel_18: ADC Channel18 selected + * @param Rank: The rank in the regular group sequencer. + * This parameter must be between 1 to 16. + * @param ADC_SampleTime: The sample time value to be set for the selected channel. + * This parameter can be one of the following values: + * @arg ADC_SampleTime_3Cycles: Sample time equal to 3 cycles + * @arg ADC_SampleTime_15Cycles: Sample time equal to 15 cycles + * @arg ADC_SampleTime_28Cycles: Sample time equal to 28 cycles + * @arg ADC_SampleTime_56Cycles: Sample time equal to 56 cycles + * @arg ADC_SampleTime_84Cycles: Sample time equal to 84 cycles + * @arg ADC_SampleTime_112Cycles: Sample time equal to 112 cycles + * @arg ADC_SampleTime_144Cycles: Sample time equal to 144 cycles + * @arg ADC_SampleTime_480Cycles: Sample time equal to 480 cycles + * @retval None + */ +void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CHANNEL(ADC_Channel)); + assert_param(IS_ADC_REGULAR_RANK(Rank)); + assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime)); + + /* if ADC_Channel_10 ... ADC_Channel_18 is selected */ + if (ADC_Channel > ADC_Channel_9) + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR1; + + /* Calculate the mask to clear */ + tmpreg2 = SMPR1_SMP_SET << (3 * (ADC_Channel - 10)); + + /* Clear the old sample time */ + tmpreg1 &= ~tmpreg2; + + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10)); + + /* Set the new sample time */ + tmpreg1 |= tmpreg2; + + /* Store the new register value */ + ADCx->SMPR1 = tmpreg1; + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR2; + + /* Calculate the mask to clear */ + tmpreg2 = SMPR2_SMP_SET << (3 * ADC_Channel); + + /* Clear the old sample time */ + tmpreg1 &= ~tmpreg2; + + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + + /* Set the new sample time */ + tmpreg1 |= tmpreg2; + + /* Store the new register value */ + ADCx->SMPR2 = tmpreg1; + } + /* For Rank 1 to 6 */ + if (Rank < 7) + { + /* Get the old register value */ + tmpreg1 = ADCx->SQR3; + + /* Calculate the mask to clear */ + tmpreg2 = SQR3_SQ_SET << (5 * (Rank - 1)); + + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1)); + + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + + /* Store the new register value */ + ADCx->SQR3 = tmpreg1; + } + /* For Rank 7 to 12 */ + else if (Rank < 13) + { + /* Get the old register value */ + tmpreg1 = ADCx->SQR2; + + /* Calculate the mask to clear */ + tmpreg2 = SQR2_SQ_SET << (5 * (Rank - 7)); + + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7)); + + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + + /* Store the new register value */ + ADCx->SQR2 = tmpreg1; + } + /* For Rank 13 to 16 */ + else + { + /* Get the old register value */ + tmpreg1 = ADCx->SQR1; + + /* Calculate the mask to clear */ + tmpreg2 = SQR1_SQ_SET << (5 * (Rank - 13)); + + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13)); + + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + + /* Store the new register value */ + ADCx->SQR1 = tmpreg1; + } +} + +/** + * @brief Enables the selected ADC software start conversion of the regular channels. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval None + */ +void ADC_SoftwareStartConv(ADC_TypeDef* ADCx) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + + /* Enable the selected ADC conversion for regular group */ + ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; +} + +/** + * @brief Gets the selected ADC Software start regular conversion Status. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The new state of ADC software start conversion (SET or RESET). + */ +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + + /* Check the status of SWSTART bit */ + if ((ADCx->CR2 & ADC_CR2_SWSTART) != (uint32_t)RESET) + { + /* SWSTART bit is set */ + bitstatus = SET; + } + else + { + /* SWSTART bit is reset */ + bitstatus = RESET; + } + + /* Return the SWSTART bit status */ + return bitstatus; +} + + +/** + * @brief Enables or disables the EOC on each regular channel conversion + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC EOC flag rising + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected ADC EOC rising on each regular channel conversion */ + ADCx->CR2 |= (uint32_t)ADC_CR2_EOCS; + } + else + { + /* Disable the selected ADC EOC rising on each regular channel conversion */ + ADCx->CR2 &= (uint32_t)(~ADC_CR2_EOCS); + } +} + +/** + * @brief Enables or disables the ADC continuous conversion mode + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC continuous conversion mode + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected ADC continuous conversion mode */ + ADCx->CR2 |= (uint32_t)ADC_CR2_CONT; + } + else + { + /* Disable the selected ADC continuous conversion mode */ + ADCx->CR2 &= (uint32_t)(~ADC_CR2_CONT); + } +} + +/** + * @brief Configures the discontinuous mode for the selected ADC regular group + * channel. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param Number: specifies the discontinuous mode regular channel count value. + * This number must be between 1 and 8. + * @retval None + */ +void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_REGULAR_DISC_NUMBER(Number)); + + /* Get the old register value */ + tmpreg1 = ADCx->CR1; + + /* Clear the old discontinuous mode channel count */ + tmpreg1 &= CR1_DISCNUM_RESET; + + /* Set the discontinuous mode channel count */ + tmpreg2 = Number - 1; + tmpreg1 |= tmpreg2 << 13; + + /* Store the new register value */ + ADCx->CR1 = tmpreg1; +} + +/** + * @brief Enables or disables the discontinuous mode on regular group channel + * for the specified ADC + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC discontinuous mode on + * regular group channel. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected ADC regular discontinuous mode */ + ADCx->CR1 |= (uint32_t)ADC_CR1_DISCEN; + } + else + { + /* Disable the selected ADC regular discontinuous mode */ + ADCx->CR1 &= (uint32_t)(~ADC_CR1_DISCEN); + } +} + +/** + * @brief Returns the last ADCx conversion result data for regular channel. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The Data conversion value. + */ +uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + + /* Return the selected ADC conversion value */ + return (uint16_t) ADCx->DR; +} + +/** + * @brief Returns the last ADC1, ADC2 and ADC3 regular conversions results + * data in the selected multi mode. + * @param None + * @retval The Data conversion value. + * @note In dual mode, the value returned by this function is as following + * Data[15:0] : these bits contain the regular data of ADC1. + * Data[31:16]: these bits contain the regular data of ADC2. + * @note In triple mode, the value returned by this function is as following + * Data[15:0] : these bits contain alternatively the regular data of ADC1, ADC3 and ADC2. + * Data[31:16]: these bits contain alternatively the regular data of ADC2, ADC1 and ADC3. + */ +uint32_t ADC_GetMultiModeConversionValue(void) +{ + /* Return the multi mode conversion value */ + return (*(__IO uint32_t *) CDR_ADDRESS); +} +/** + * @} + */ + +/** @defgroup ADC_Group5 Regular Channels DMA Configuration functions + * @brief Regular Channels DMA Configuration functions + * +@verbatim + =============================================================================== + ##### Regular Channels DMA Configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to configure the DMA for ADC + regular channels. + Since converted regular channel values are stored into a unique data + register, it is useful to use DMA for conversion of more than one regular + channel. This avoids the loss of the data already stored in the ADC + Data register. + When the DMA mode is enabled (using the ADC_DMACmd() function), after each + conversion of a regular channel, a DMA request is generated. + [..] Depending on the "DMA disable selection for Independent ADC mode" + configuration (using the ADC_DMARequestAfterLastTransferCmd() function), + at the end of the last DMA transfer, two possibilities are allowed: + (+) No new DMA request is issued to the DMA controller (feature DISABLED) + (+) Requests can continue to be generated (feature ENABLED). + [..] Depending on the "DMA disable selection for multi ADC mode" configuration + (using the void ADC_MultiModeDMARequestAfterLastTransferCmd() function), + at the end of the last DMA transfer, two possibilities are allowed: + (+) No new DMA request is issued to the DMA controller (feature DISABLED) + (+) Requests can continue to be generated (feature ENABLED). + +@endverbatim + * @{ + */ + + /** + * @brief Enables or disables the specified ADC DMA request. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC DMA transfer. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC DMA request */ + ADCx->CR2 |= (uint32_t)ADC_CR2_DMA; + } + else + { + /* Disable the selected ADC DMA request */ + ADCx->CR2 &= (uint32_t)(~ADC_CR2_DMA); + } +} + +/** + * @brief Enables or disables the ADC DMA request after last transfer (Single-ADC mode) + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC DMA request after last transfer. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC DMA request after last transfer */ + ADCx->CR2 |= (uint32_t)ADC_CR2_DDS; + } + else + { + /* Disable the selected ADC DMA request after last transfer */ + ADCx->CR2 &= (uint32_t)(~ADC_CR2_DDS); + } +} + +/** + * @brief Enables or disables the ADC DMA request after last transfer in multi ADC mode + * @param NewState: new state of the selected ADC DMA request after last transfer. + * This parameter can be: ENABLE or DISABLE. + * @note if Enabled, DMA requests are issued as long as data are converted and + * DMA mode for multi ADC mode (selected using ADC_CommonInit() function + * by ADC_CommonInitStruct.ADC_DMAAccessMode structure member) is + * ADC_DMAAccessMode_1, ADC_DMAAccessMode_2 or ADC_DMAAccessMode_3. + * @retval None + */ +void ADC_MultiModeDMARequestAfterLastTransferCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC DMA request after last transfer */ + ADC->CCR |= (uint32_t)ADC_CCR_DDS; + } + else + { + /* Disable the selected ADC DMA request after last transfer */ + ADC->CCR &= (uint32_t)(~ADC_CCR_DDS); + } +} +/** + * @} + */ + +/** @defgroup ADC_Group6 Injected channels Configuration functions + * @brief Injected channels Configuration functions + * +@verbatim + =============================================================================== + ##### Injected channels Configuration functions ##### + =============================================================================== + + [..] This section provide functions allowing to configure the ADC Injected channels, + it is composed of 2 sub sections : + + (#) Configuration functions for Injected channels: This subsection provides + functions allowing to configure the ADC injected channels : + (++) Configure the rank in the injected group sequencer for each channel + (++) Configure the sampling time for each channel + (++) Activate the Auto injected Mode + (++) Activate the Discontinuous Mode + (++) scan mode activation + (++) External/software trigger source + (++) External trigger edge + (++) injected channels sequencer. + + (#) Get the Specified Injected channel conversion data: This subsection + provides an important function in the ADC peripheral since it returns the + converted data of the specific injected channel. + +@endverbatim + * @{ + */ +/** + * @brief Configures for the selected ADC injected channel its corresponding + * rank in the sequencer and its sample time. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_Channel: the ADC channel to configure. + * This parameter can be one of the following values: + * @arg ADC_Channel_0: ADC Channel0 selected + * @arg ADC_Channel_1: ADC Channel1 selected + * @arg ADC_Channel_2: ADC Channel2 selected + * @arg ADC_Channel_3: ADC Channel3 selected + * @arg ADC_Channel_4: ADC Channel4 selected + * @arg ADC_Channel_5: ADC Channel5 selected + * @arg ADC_Channel_6: ADC Channel6 selected + * @arg ADC_Channel_7: ADC Channel7 selected + * @arg ADC_Channel_8: ADC Channel8 selected + * @arg ADC_Channel_9: ADC Channel9 selected + * @arg ADC_Channel_10: ADC Channel10 selected + * @arg ADC_Channel_11: ADC Channel11 selected + * @arg ADC_Channel_12: ADC Channel12 selected + * @arg ADC_Channel_13: ADC Channel13 selected + * @arg ADC_Channel_14: ADC Channel14 selected + * @arg ADC_Channel_15: ADC Channel15 selected + * @arg ADC_Channel_16: ADC Channel16 selected + * @arg ADC_Channel_17: ADC Channel17 selected + * @arg ADC_Channel_18: ADC Channel18 selected + * @param Rank: The rank in the injected group sequencer. + * This parameter must be between 1 to 4. + * @param ADC_SampleTime: The sample time value to be set for the selected channel. + * This parameter can be one of the following values: + * @arg ADC_SampleTime_3Cycles: Sample time equal to 3 cycles + * @arg ADC_SampleTime_15Cycles: Sample time equal to 15 cycles + * @arg ADC_SampleTime_28Cycles: Sample time equal to 28 cycles + * @arg ADC_SampleTime_56Cycles: Sample time equal to 56 cycles + * @arg ADC_SampleTime_84Cycles: Sample time equal to 84 cycles + * @arg ADC_SampleTime_112Cycles: Sample time equal to 112 cycles + * @arg ADC_SampleTime_144Cycles: Sample time equal to 144 cycles + * @arg ADC_SampleTime_480Cycles: Sample time equal to 480 cycles + * @retval None + */ +void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CHANNEL(ADC_Channel)); + assert_param(IS_ADC_INJECTED_RANK(Rank)); + assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime)); + /* if ADC_Channel_10 ... ADC_Channel_18 is selected */ + if (ADC_Channel > ADC_Channel_9) + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR1; + /* Calculate the mask to clear */ + tmpreg2 = SMPR1_SMP_SET << (3*(ADC_Channel - 10)); + /* Clear the old sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3*(ADC_Channel - 10)); + /* Set the new sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SMPR1 = tmpreg1; + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR2; + /* Calculate the mask to clear */ + tmpreg2 = SMPR2_SMP_SET << (3 * ADC_Channel); + /* Clear the old sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + /* Set the new sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SMPR2 = tmpreg1; + } + /* Rank configuration */ + /* Get the old register value */ + tmpreg1 = ADCx->JSQR; + /* Get JL value: Number = JL+1 */ + tmpreg3 = (tmpreg1 & JSQR_JL_SET)>> 20; + /* Calculate the mask to clear: ((Rank-1)+(4-JL-1)) */ + tmpreg2 = JSQR_JSQ_SET << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + /* Clear the old JSQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set: ((Rank-1)+(4-JL-1)) */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + /* Set the JSQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->JSQR = tmpreg1; +} + +/** + * @brief Configures the sequencer length for injected channels + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param Length: The sequencer length. + * This parameter must be a number between 1 to 4. + * @retval None + */ +void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_INJECTED_LENGTH(Length)); + + /* Get the old register value */ + tmpreg1 = ADCx->JSQR; + + /* Clear the old injected sequence length JL bits */ + tmpreg1 &= JSQR_JL_RESET; + + /* Set the injected sequence length JL bits */ + tmpreg2 = Length - 1; + tmpreg1 |= tmpreg2 << 20; + + /* Store the new register value */ + ADCx->JSQR = tmpreg1; +} + +/** + * @brief Set the injected channels conversion value offset + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_InjectedChannel: the ADC injected channel to set its offset. + * This parameter can be one of the following values: + * @arg ADC_InjectedChannel_1: Injected Channel1 selected + * @arg ADC_InjectedChannel_2: Injected Channel2 selected + * @arg ADC_InjectedChannel_3: Injected Channel3 selected + * @arg ADC_InjectedChannel_4: Injected Channel4 selected + * @param Offset: the offset value for the selected ADC injected channel + * This parameter must be a 12bit value. + * @retval None + */ +void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset) +{ + __IO uint32_t tmp = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel)); + assert_param(IS_ADC_OFFSET(Offset)); + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel; + + /* Set the selected injected channel data offset */ + *(__IO uint32_t *) tmp = (uint32_t)Offset; +} + + /** + * @brief Configures the ADCx external trigger for injected channels conversion. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_ExternalTrigInjecConv: specifies the ADC trigger to start injected conversion. + * This parameter can be one of the following values: + * @arg ADC_ExternalTrigInjecConv_T1_CC4: Timer1 capture compare4 selected + * @arg ADC_ExternalTrigInjecConv_T1_TRGO: Timer1 TRGO event selected + * @arg ADC_ExternalTrigInjecConv_T2_CC1: Timer2 capture compare1 selected + * @arg ADC_ExternalTrigInjecConv_T2_TRGO: Timer2 TRGO event selected + * @arg ADC_ExternalTrigInjecConv_T3_CC2: Timer3 capture compare2 selected + * @arg ADC_ExternalTrigInjecConv_T3_CC4: Timer3 capture compare4 selected + * @arg ADC_ExternalTrigInjecConv_T4_CC1: Timer4 capture compare1 selected + * @arg ADC_ExternalTrigInjecConv_T4_CC2: Timer4 capture compare2 selected + * @arg ADC_ExternalTrigInjecConv_T4_CC3: Timer4 capture compare3 selected + * @arg ADC_ExternalTrigInjecConv_T4_TRGO: Timer4 TRGO event selected + * @arg ADC_ExternalTrigInjecConv_T5_CC4: Timer5 capture compare4 selected + * @arg ADC_ExternalTrigInjecConv_T5_TRGO: Timer5 TRGO event selected + * @arg ADC_ExternalTrigInjecConv_T8_CC2: Timer8 capture compare2 selected + * @arg ADC_ExternalTrigInjecConv_T8_CC3: Timer8 capture compare3 selected + * @arg ADC_ExternalTrigInjecConv_T8_CC4: Timer8 capture compare4 selected + * @arg ADC_ExternalTrigInjecConv_Ext_IT15: External interrupt line 15 event selected + * @retval None + */ +void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_EXT_INJEC_TRIG(ADC_ExternalTrigInjecConv)); + + /* Get the old register value */ + tmpreg = ADCx->CR2; + + /* Clear the old external event selection for injected group */ + tmpreg &= CR2_JEXTSEL_RESET; + + /* Set the external event selection for injected group */ + tmpreg |= ADC_ExternalTrigInjecConv; + + /* Store the new register value */ + ADCx->CR2 = tmpreg; +} + +/** + * @brief Configures the ADCx external trigger edge for injected channels conversion. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_ExternalTrigInjecConvEdge: specifies the ADC external trigger edge + * to start injected conversion. + * This parameter can be one of the following values: + * @arg ADC_ExternalTrigInjecConvEdge_None: external trigger disabled for + * injected conversion + * @arg ADC_ExternalTrigInjecConvEdge_Rising: detection on rising edge + * @arg ADC_ExternalTrigInjecConvEdge_Falling: detection on falling edge + * @arg ADC_ExternalTrigInjecConvEdge_RisingFalling: detection on both rising + * and falling edge + * @retval None + */ +void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_EXT_INJEC_TRIG_EDGE(ADC_ExternalTrigInjecConvEdge)); + /* Get the old register value */ + tmpreg = ADCx->CR2; + /* Clear the old external trigger edge for injected group */ + tmpreg &= CR2_JEXTEN_RESET; + /* Set the new external trigger edge for injected group */ + tmpreg |= ADC_ExternalTrigInjecConvEdge; + /* Store the new register value */ + ADCx->CR2 = tmpreg; +} + +/** + * @brief Enables the selected ADC software start conversion of the injected channels. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval None + */ +void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + /* Enable the selected ADC conversion for injected group */ + ADCx->CR2 |= (uint32_t)ADC_CR2_JSWSTART; +} + +/** + * @brief Gets the selected ADC Software start injected conversion Status. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The new state of ADC software start injected conversion (SET or RESET). + */ +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + + /* Check the status of JSWSTART bit */ + if ((ADCx->CR2 & ADC_CR2_JSWSTART) != (uint32_t)RESET) + { + /* JSWSTART bit is set */ + bitstatus = SET; + } + else + { + /* JSWSTART bit is reset */ + bitstatus = RESET; + } + /* Return the JSWSTART bit status */ + return bitstatus; +} + +/** + * @brief Enables or disables the selected ADC automatic injected group + * conversion after regular one. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC auto injected conversion + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC automatic injected group conversion */ + ADCx->CR1 |= (uint32_t)ADC_CR1_JAUTO; + } + else + { + /* Disable the selected ADC automatic injected group conversion */ + ADCx->CR1 &= (uint32_t)(~ADC_CR1_JAUTO); + } +} + +/** + * @brief Enables or disables the discontinuous mode for injected group + * channel for the specified ADC + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC discontinuous mode on injected + * group channel. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC injected discontinuous mode */ + ADCx->CR1 |= (uint32_t)ADC_CR1_JDISCEN; + } + else + { + /* Disable the selected ADC injected discontinuous mode */ + ADCx->CR1 &= (uint32_t)(~ADC_CR1_JDISCEN); + } +} + +/** + * @brief Returns the ADC injected channel conversion result + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_InjectedChannel: the converted ADC injected channel. + * This parameter can be one of the following values: + * @arg ADC_InjectedChannel_1: Injected Channel1 selected + * @arg ADC_InjectedChannel_2: Injected Channel2 selected + * @arg ADC_InjectedChannel_3: Injected Channel3 selected + * @arg ADC_InjectedChannel_4: Injected Channel4 selected + * @retval The Data conversion value. + */ +uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel)); + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel + JDR_OFFSET; + + /* Returns the selected injected channel conversion data value */ + return (uint16_t) (*(__IO uint32_t*) tmp); +} +/** + * @} + */ + +/** @defgroup ADC_Group7 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + + [..] This section provides functions allowing to configure the ADC Interrupts + and to get the status and clear flags and Interrupts pending bits. + + [..] Each ADC provides 4 Interrupts sources and 6 Flags which can be divided + into 3 groups: + + *** Flags and Interrupts for ADC regular channels *** + ===================================================== + [..] + (+) Flags : + (##) ADC_FLAG_OVR : Overrun detection when regular converted data are lost + + (##) ADC_FLAG_EOC : Regular channel end of conversion ==> to indicate + (depending on EOCS bit, managed by ADC_EOCOnEachRegularChannelCmd() ) + the end of: + (+++) a regular CHANNEL conversion + (+++) sequence of regular GROUP conversions . + + (##) ADC_FLAG_STRT: Regular channel start ==> to indicate when regular + CHANNEL conversion starts. + [..] + (+) Interrupts : + (##) ADC_IT_OVR : specifies the interrupt source for Overrun detection + event. + (##) ADC_IT_EOC : specifies the interrupt source for Regular channel end + of conversion event. + + + *** Flags and Interrupts for ADC Injected channels *** + ====================================================== + [..] + (+) Flags : + (##) ADC_FLAG_JEOC : Injected channel end of conversion ==> to indicate + at the end of injected GROUP conversion + + (##) ADC_FLAG_JSTRT: Injected channel start ==> to indicate hardware when + injected GROUP conversion starts. + [..] + (+) Interrupts : + (##) ADC_IT_JEOC : specifies the interrupt source for Injected channel + end of conversion event. + + *** General Flags and Interrupts for the ADC *** + ================================================ + [..] + (+)Flags : + (##) ADC_FLAG_AWD: Analog watchdog ==> to indicate if the converted voltage + crosses the programmed thresholds values. + [..] + (+) Interrupts : + (##) ADC_IT_AWD : specifies the interrupt source for Analog watchdog event. + + + [..] The user should identify which mode will be used in his application to + manage the ADC controller events: Polling mode or Interrupt mode. + + [..] In the Polling Mode it is advised to use the following functions: + (+) ADC_GetFlagStatus() : to check if flags events occur. + (+) ADC_ClearFlag() : to clear the flags events. + + [..] In the Interrupt Mode it is advised to use the following functions: + (+) ADC_ITConfig() : to enable or disable the interrupt source. + (+) ADC_GetITStatus() : to check if Interrupt occurs. + (+) ADC_ClearITPendingBit() : to clear the Interrupt pending Bit + (corresponding Flag). +@endverbatim + * @{ + */ +/** + * @brief Enables or disables the specified ADC interrupts. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_IT: specifies the ADC interrupt sources to be enabled or disabled. + * This parameter can be one of the following values: + * @arg ADC_IT_EOC: End of conversion interrupt mask + * @arg ADC_IT_AWD: Analog watchdog interrupt mask + * @arg ADC_IT_JEOC: End of injected conversion interrupt mask + * @arg ADC_IT_OVR: Overrun interrupt enable + * @param NewState: new state of the specified ADC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState) +{ + uint32_t itmask = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + assert_param(IS_ADC_IT(ADC_IT)); + + /* Get the ADC IT index */ + itmask = (uint8_t)ADC_IT; + itmask = (uint32_t)0x01 << itmask; + + if (NewState != DISABLE) + { + /* Enable the selected ADC interrupts */ + ADCx->CR1 |= itmask; + } + else + { + /* Disable the selected ADC interrupts */ + ADCx->CR1 &= (~(uint32_t)itmask); + } +} + +/** + * @brief Checks whether the specified ADC flag is set or not. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg ADC_FLAG_AWD: Analog watchdog flag + * @arg ADC_FLAG_EOC: End of conversion flag + * @arg ADC_FLAG_JEOC: End of injected group conversion flag + * @arg ADC_FLAG_JSTRT: Start of injected group conversion flag + * @arg ADC_FLAG_STRT: Start of regular group conversion flag + * @arg ADC_FLAG_OVR: Overrun flag + * @retval The new state of ADC_FLAG (SET or RESET). + */ +FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_GET_FLAG(ADC_FLAG)); + + /* Check the status of the specified ADC flag */ + if ((ADCx->SR & ADC_FLAG) != (uint8_t)RESET) + { + /* ADC_FLAG is set */ + bitstatus = SET; + } + else + { + /* ADC_FLAG is reset */ + bitstatus = RESET; + } + /* Return the ADC_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the ADCx's pending flags. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_FLAG: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg ADC_FLAG_AWD: Analog watchdog flag + * @arg ADC_FLAG_EOC: End of conversion flag + * @arg ADC_FLAG_JEOC: End of injected group conversion flag + * @arg ADC_FLAG_JSTRT: Start of injected group conversion flag + * @arg ADC_FLAG_STRT: Start of regular group conversion flag + * @arg ADC_FLAG_OVR: Overrun flag + * @retval None + */ +void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CLEAR_FLAG(ADC_FLAG)); + + /* Clear the selected ADC flags */ + ADCx->SR = ~(uint32_t)ADC_FLAG; +} + +/** + * @brief Checks whether the specified ADC interrupt has occurred or not. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_IT: specifies the ADC interrupt source to check. + * This parameter can be one of the following values: + * @arg ADC_IT_EOC: End of conversion interrupt mask + * @arg ADC_IT_AWD: Analog watchdog interrupt mask + * @arg ADC_IT_JEOC: End of injected conversion interrupt mask + * @arg ADC_IT_OVR: Overrun interrupt mask + * @retval The new state of ADC_IT (SET or RESET). + */ +ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT) +{ + ITStatus bitstatus = RESET; + uint32_t itmask = 0, enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_IT(ADC_IT)); + + /* Get the ADC IT index */ + itmask = ADC_IT >> 8; + + /* Get the ADC_IT enable bit status */ + enablestatus = (ADCx->CR1 & ((uint32_t)0x01 << (uint8_t)ADC_IT)) ; + + /* Check the status of the specified ADC interrupt */ + if (((ADCx->SR & itmask) != (uint32_t)RESET) && enablestatus) + { + /* ADC_IT is set */ + bitstatus = SET; + } + else + { + /* ADC_IT is reset */ + bitstatus = RESET; + } + /* Return the ADC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the ADCx's interrupt pending bits. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_IT: specifies the ADC interrupt pending bit to clear. + * This parameter can be one of the following values: + * @arg ADC_IT_EOC: End of conversion interrupt mask + * @arg ADC_IT_AWD: Analog watchdog interrupt mask + * @arg ADC_IT_JEOC: End of injected conversion interrupt mask + * @arg ADC_IT_OVR: Overrun interrupt mask + * @retval None + */ +void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT) +{ + uint8_t itmask = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_IT(ADC_IT)); + /* Get the ADC IT index */ + itmask = (uint8_t)(ADC_IT >> 8); + /* Clear the selected ADC interrupt pending bits */ + ADCx->SR = ~(uint32_t)itmask; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/Kconfig b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/Kconfig new file mode 100644 index 000000000..a289b6ca9 --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/Kconfig @@ -0,0 +1,17 @@ +if BSP_USING_DAC + config DAC_BUS_NAME + string "dac bus name" + default "dac" + + config DAC_DRIVER_NAME + string "dac driver name" + default "dac_drv" + + config DAC_DEVICE_NAME + string "dac bus device name" + default "dac_dev" + + config DAC_GPIO_NUM + int "dac gpio pin num(only support 4 or 5)" + default "4" +endif diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/Makefile b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/Makefile new file mode 100644 index 000000000..4bd1c0c55 --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := connect_dac.c hardware_dac.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/connect_dac.c b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/connect_dac.c new file mode 100644 index 000000000..6186b0a48 --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/connect_dac.c @@ -0,0 +1,168 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_dac.c +* @brief support to register DAC pointer and function +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-1-10 +*/ + +#include + +#define _DAC_CONS(string1, string2) string1##string2 +#define DAC_CONS(string1, string2) _DAC_CONS(string1, string2) + +#ifdef BSP_USING_DAC +#define DAC_GPIO DAC_CONS(GPIO_Pin_, DAC_GPIO_NUM) +#endif + +static void DacInit(struct DacHardwareDevice *dac_dev) +{ + GPIO_InitTypeDef GPIO_InitStructure; + DAC_InitTypeDef DAC_InitType; + +#ifdef BSP_USING_DAC + if (0 == strncmp(dac_dev->haldev.dev_name, DAC_DEVICE_NAME, NAME_NUM_MAX)) { + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//enable GPIOA clock + RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//enable DAC clock + + GPIO_InitStructure.GPIO_Pin = DAC_GPIO; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + DAC_InitType.DAC_Trigger = DAC_Trigger_None;//disable trigger function TEN1=0 + DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;//disable wave generation function + DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;//mask and amplitude configure + DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable;//disable DAC1 output buffer BOFF1=1 + DAC_Init(DAC_Channel_1, &DAC_InitType); + + DAC_Cmd(DAC_Channel_1, ENABLE);//enable DAC channel 1 + + DAC_SetChannel1Data(DAC_Align_12b_R, 0);//12 bits、R-Align data format, default 0 + } +#endif +} + +static uint32 Stm32DacOpen(void *dev) +{ + struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev; + + DacInit(dac_dev); + + return EOK; +} + +static uint32 Stm32DacClose(void *dev) +{ + struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev; + + DAC_DeInit(); + + return EOK; +} + +static uint32 Stm32DacRead(void *dev, struct BusBlockReadParam *read_param) +{ + struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev; + + uint16 dac_set_value = 0; + + dac_set_value = DAC_GetDataOutputValue(DAC_Channel_1); + + *(uint16 *)read_param->buffer = dac_set_value; + read_param->read_length = 2; + + return read_param->read_length; +} + +static uint32 Stm32DacDrvConfigure(void *drv, struct BusConfigureInfo *configure_info) +{ + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(configure_info); + + x_err_t ret = EOK; + + struct DacDriver *dac_drv = (struct DacDriver *)drv; + struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dac_drv->driver.owner_bus->owner_haldev; + struct Stm32HwDac *dac_cfg = (struct Stm32HwDac *)dac_dev->haldev.private_data; + + switch (configure_info->configure_cmd) + { + case OPE_CFG: + dac_cfg->digital_data = *(uint16 *)configure_info->private_data; + DAC_SetChannel1Data(DAC_Align_12b_R, dac_cfg->digital_data);//12 bits、R-Align data format, digital data + break; + default: + break; + } + + return ret; +} + +static const struct DacDevDone dev_done = +{ + Stm32DacOpen, + Stm32DacClose, + NONE, + Stm32DacRead, +}; + +int Stm32HwDacInit(void) +{ + x_err_t ret = EOK; + +#ifdef BSP_USING_DAC + static struct DacBus dac_bus; + static struct DacDriver dac_drv; + static struct DacHardwareDevice dac_dev; + static struct Stm32HwDac dac_cfg; + + dac_drv.configure = Stm32DacDrvConfigure; + + ret = DacBusInit(&dac_bus, DAC_BUS_NAME); + if (ret != EOK) { + KPrintf("DAC bus init error %d\n", ret); + return ERROR; + } + + ret = DacDriverInit(&dac_drv, DAC_DRIVER_NAME); + if (ret != EOK) { + KPrintf("DAC driver init error %d\n", ret); + return ERROR; + } + ret = DacDriverAttachToBus(DAC_DRIVER_NAME, DAC_BUS_NAME); + if (ret != EOK) { + KPrintf("DAC driver attach error %d\n", ret); + return ERROR; + } + + dac_dev.dac_dev_done = &dev_done; + dac_cfg.DACx = DAC; + dac_cfg.digital_data = 0; + + ret = DacDeviceRegister(&dac_dev, (void *)&dac_cfg, DAC_DEVICE_NAME); + if (ret != EOK) { + KPrintf("DAC device register error %d\n", ret); + return ERROR; + } + ret = DacDeviceAttachToBus(DAC_DEVICE_NAME, DAC_BUS_NAME); + if (ret != EOK) { + KPrintf("DAC device register error %d\n", ret); + return ERROR; + } +#endif + + return ret; +} diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/hardware_dac.c b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/hardware_dac.c new file mode 100644 index 000000000..a74137f38 --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/dac/hardware_dac.c @@ -0,0 +1,733 @@ +/** + ****************************************************************************** + * @file stm32f4xx_dac.c + * @author MCD Application Team + * @version V1.4.0 + * @date 04-August-2014 + * @brief This file provides firmware functions to manage the following + * functionalities of the Digital-to-Analog Converter (DAC) peripheral: + * + DAC channels configuration: trigger, output buffer, data format + * + DMA management + * + Interrupts and flags management + * + @verbatim + =============================================================================== + ##### DAC Peripheral features ##### + =============================================================================== + [..] + *** DAC Channels *** + ==================== + [..] + The device integrates two 12-bit Digital Analog Converters that can + be used independently or simultaneously (dual mode): + (#) DAC channel1 with DAC_OUT1 (PA4) as output + (#) DAC channel2 with DAC_OUT2 (PA5) as output + + *** DAC Triggers *** + ==================== + [..] + Digital to Analog conversion can be non-triggered using DAC_Trigger_None + and DAC_OUT1/DAC_OUT2 is available once writing to DHRx register + using DAC_SetChannel1Data() / DAC_SetChannel2Data() functions. + [..] + Digital to Analog conversion can be triggered by: + (#) External event: EXTI Line 9 (any GPIOx_Pin9) using DAC_Trigger_Ext_IT9. + The used pin (GPIOx_Pin9) must be configured in input mode. + + (#) Timers TRGO: TIM2, TIM4, TIM5, TIM6, TIM7 and TIM8 + (DAC_Trigger_T2_TRGO, DAC_Trigger_T4_TRGO...) + The timer TRGO event should be selected using TIM_SelectOutputTrigger() + + (#) Software using DAC_Trigger_Software + + *** DAC Buffer mode feature *** + =============================== + [..] + Each DAC channel integrates an output buffer that can be used to + reduce the output impedance, and to drive external loads directly + without having to add an external operational amplifier. + To enable, the output buffer use + DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; + [..] + (@) Refer to the device datasheet for more details about output + impedance value with and without output buffer. + + *** DAC wave generation feature *** + =================================== + [..] + Both DAC channels can be used to generate + (#) Noise wave using DAC_WaveGeneration_Noise + (#) Triangle wave using DAC_WaveGeneration_Triangle + + -@- Wave generation can be disabled using DAC_WaveGeneration_None + + *** DAC data format *** + ======================= + [..] + The DAC data format can be: + (#) 8-bit right alignment using DAC_Align_8b_R + (#) 12-bit left alignment using DAC_Align_12b_L + (#) 12-bit right alignment using DAC_Align_12b_R + + *** DAC data value to voltage correspondence *** + ================================================ + [..] + The analog output voltage on each DAC channel pin is determined + by the following equation: + DAC_OUTx = VREF+ * DOR / 4095 + with DOR is the Data Output Register + VEF+ is the input voltage reference (refer to the device datasheet) + e.g. To set DAC_OUT1 to 0.7V, use + DAC_SetChannel1Data(DAC_Align_12b_R, 868); + Assuming that VREF+ = 3.3V, DAC_OUT1 = (3.3 * 868) / 4095 = 0.7V + + *** DMA requests *** + ===================== + [..] + A DMA1 request can be generated when an external trigger (but not + a software trigger) occurs if DMA1 requests are enabled using + DAC_DMACmd() + [..] + DMA1 requests are mapped as following: + (#) DAC channel1 : mapped on DMA1 Stream5 channel7 which must be + already configured + (#) DAC channel2 : mapped on DMA1 Stream6 channel7 which must be + already configured + + + ##### How to use this driver ##### + =============================================================================== + [..] + (+) DAC APB clock must be enabled to get write access to DAC + registers using + RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE) + (+) Configure DAC_OUTx (DAC_OUT1: PA4, DAC_OUT2: PA5) in analog mode. + (+) Configure the DAC channel using DAC_Init() function + (+) Enable the DAC channel using DAC_Cmd() function + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/** +* @file: hardware_dac.c +* @brief: support hardware dac function +* @version: 2.0 +* @author: AIIT XUOS Lab +* @date: 2022/1/11 +*/ + +/************************************************* +File name: hardware_dac.c +Description: support hardware dac function +Others: +History: +1. Date: 2022-1-11 +Author: AIIT XUOS Lab +Modification: +1. rename stm32f4xx_dac.c for XiUOS +*************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup DAC + * @brief DAC driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* CR register Mask */ +#define CR_CLEAR_MASK ((uint32_t)0x00000FFE) + +/* DAC Dual Channels SWTRIG masks */ +#define DUAL_SWTRIG_SET ((uint32_t)0x00000003) +#define DUAL_SWTRIG_RESET ((uint32_t)0xFFFFFFFC) + +/* DHR registers offsets */ +#define DHR12R1_OFFSET ((uint32_t)0x00000008) +#define DHR12R2_OFFSET ((uint32_t)0x00000014) +#define DHR12RD_OFFSET ((uint32_t)0x00000020) + +/* DOR register offset */ +#define DOR_OFFSET ((uint32_t)0x0000002C) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup DAC_Private_Functions + * @{ + */ + +/** @defgroup DAC_Group1 DAC channels configuration + * @brief DAC channels configuration: trigger, output buffer, data format + * +@verbatim + =============================================================================== + ##### DAC channels configuration: trigger, output buffer, data format ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes the DAC peripheral registers to their default reset values. + * @param None + * @retval None + */ +void DAC_DeInit(void) +{ + /* Enable DAC reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, ENABLE); + /* Release DAC from reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, DISABLE); +} + +/** + * @brief Initializes the DAC peripheral according to the specified parameters + * in the DAC_InitStruct. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_InitStruct: pointer to a DAC_InitTypeDef structure that contains + * the configuration information for the specified DAC channel. + * @retval None + */ +void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + + /* Check the DAC parameters */ + assert_param(IS_DAC_TRIGGER(DAC_InitStruct->DAC_Trigger)); + assert_param(IS_DAC_GENERATE_WAVE(DAC_InitStruct->DAC_WaveGeneration)); + assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude)); + assert_param(IS_DAC_OUTPUT_BUFFER_STATE(DAC_InitStruct->DAC_OutputBuffer)); + +/*---------------------------- DAC CR Configuration --------------------------*/ + /* Get the DAC CR value */ + tmpreg1 = DAC->CR; + /* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */ + tmpreg1 &= ~(CR_CLEAR_MASK << DAC_Channel); + /* Configure for the selected DAC channel: buffer output, trigger, + wave generation, mask/amplitude for wave generation */ + /* Set TSELx and TENx bits according to DAC_Trigger value */ + /* Set WAVEx bits according to DAC_WaveGeneration value */ + /* Set MAMPx bits according to DAC_LFSRUnmask_TriangleAmplitude value */ + /* Set BOFFx bit according to DAC_OutputBuffer value */ + tmpreg2 = (DAC_InitStruct->DAC_Trigger | DAC_InitStruct->DAC_WaveGeneration | + DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude | \ + DAC_InitStruct->DAC_OutputBuffer); + /* Calculate CR register value depending on DAC_Channel */ + tmpreg1 |= tmpreg2 << DAC_Channel; + /* Write to DAC CR */ + DAC->CR = tmpreg1; +} + +/** + * @brief Fills each DAC_InitStruct member with its default value. + * @param DAC_InitStruct: pointer to a DAC_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct) +{ +/*--------------- Reset DAC init structure parameters values -----------------*/ + /* Initialize the DAC_Trigger member */ + DAC_InitStruct->DAC_Trigger = DAC_Trigger_None; + /* Initialize the DAC_WaveGeneration member */ + DAC_InitStruct->DAC_WaveGeneration = DAC_WaveGeneration_None; + /* Initialize the DAC_LFSRUnmask_TriangleAmplitude member */ + DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; + /* Initialize the DAC_OutputBuffer member */ + DAC_InitStruct->DAC_OutputBuffer = DAC_OutputBuffer_Enable; +} + +/** + * @brief Enables or disables the specified DAC channel. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param NewState: new state of the DAC channel. + * This parameter can be: ENABLE or DISABLE. + * @note When the DAC channel is enabled the trigger source can no more be modified. + * @retval None + */ +void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected DAC channel */ + DAC->CR |= (DAC_CR_EN1 << DAC_Channel); + } + else + { + /* Disable the selected DAC channel */ + DAC->CR &= (~(DAC_CR_EN1 << DAC_Channel)); + } +} + +/** + * @brief Enables or disables the selected DAC channel software trigger. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param NewState: new state of the selected DAC channel software trigger. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable software trigger for the selected DAC channel */ + DAC->SWTRIGR |= (uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4); + } + else + { + /* Disable software trigger for the selected DAC channel */ + DAC->SWTRIGR &= ~((uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4)); + } +} + +/** + * @brief Enables or disables simultaneously the two DAC channels software triggers. + * @param NewState: new state of the DAC channels software triggers. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_DualSoftwareTriggerCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable software trigger for both DAC channels */ + DAC->SWTRIGR |= DUAL_SWTRIG_SET; + } + else + { + /* Disable software trigger for both DAC channels */ + DAC->SWTRIGR &= DUAL_SWTRIG_RESET; + } +} + +/** + * @brief Enables or disables the selected DAC channel wave generation. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_Wave: specifies the wave type to enable or disable. + * This parameter can be one of the following values: + * @arg DAC_Wave_Noise: noise wave generation + * @arg DAC_Wave_Triangle: triangle wave generation + * @param NewState: new state of the selected DAC channel wave generation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_WAVE(DAC_Wave)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected wave generation for the selected DAC channel */ + DAC->CR |= DAC_Wave << DAC_Channel; + } + else + { + /* Disable the selected wave generation for the selected DAC channel */ + DAC->CR &= ~(DAC_Wave << DAC_Channel); + } +} + +/** + * @brief Set the specified data holding register value for DAC channel1. + * @param DAC_Align: Specifies the data alignment for DAC channel1. + * This parameter can be one of the following values: + * @arg DAC_Align_8b_R: 8bit right data alignment selected + * @arg DAC_Align_12b_L: 12bit left data alignment selected + * @arg DAC_Align_12b_R: 12bit right data alignment selected + * @param Data: Data to be loaded in the selected data holding register. + * @retval None + */ +void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data)); + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12R1_OFFSET + DAC_Align; + + /* Set the DAC channel1 selected data holding register */ + *(__IO uint32_t *) tmp = Data; +} + +/** + * @brief Set the specified data holding register value for DAC channel2. + * @param DAC_Align: Specifies the data alignment for DAC channel2. + * This parameter can be one of the following values: + * @arg DAC_Align_8b_R: 8bit right data alignment selected + * @arg DAC_Align_12b_L: 12bit left data alignment selected + * @arg DAC_Align_12b_R: 12bit right data alignment selected + * @param Data: Data to be loaded in the selected data holding register. + * @retval None + */ +void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data)); + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12R2_OFFSET + DAC_Align; + + /* Set the DAC channel2 selected data holding register */ + *(__IO uint32_t *)tmp = Data; +} + +/** + * @brief Set the specified data holding register value for dual channel DAC. + * @param DAC_Align: Specifies the data alignment for dual channel DAC. + * This parameter can be one of the following values: + * @arg DAC_Align_8b_R: 8bit right data alignment selected + * @arg DAC_Align_12b_L: 12bit left data alignment selected + * @arg DAC_Align_12b_R: 12bit right data alignment selected + * @param Data2: Data for DAC Channel2 to be loaded in the selected data holding register. + * @param Data1: Data for DAC Channel1 to be loaded in the selected data holding register. + * @note In dual mode, a unique register access is required to write in both + * DAC channels at the same time. + * @retval None + */ +void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1) +{ + uint32_t data = 0, tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data1)); + assert_param(IS_DAC_DATA(Data2)); + + /* Calculate and set dual DAC data holding register value */ + if (DAC_Align == DAC_Align_8b_R) + { + data = ((uint32_t)Data2 << 8) | Data1; + } + else + { + data = ((uint32_t)Data2 << 16) | Data1; + } + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12RD_OFFSET + DAC_Align; + + /* Set the dual DAC selected data holding register */ + *(__IO uint32_t *)tmp = data; +} + +/** + * @brief Returns the last data output value of the selected DAC channel. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @retval The selected DAC channel data output value. + */ +uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + + tmp = (uint32_t) DAC_BASE ; + tmp += DOR_OFFSET + ((uint32_t)DAC_Channel >> 2); + + /* Returns the DAC channel data output register value */ + return (uint16_t) (*(__IO uint32_t*) tmp); +} +/** + * @} + */ + +/** @defgroup DAC_Group2 DMA management functions + * @brief DMA management functions + * +@verbatim + =============================================================================== + ##### DMA management functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified DAC channel DMA request. + * @note When enabled DMA1 is generated when an external trigger (EXTI Line9, + * TIM2, TIM4, TIM5, TIM6, TIM7 or TIM8 but not a software trigger) occurs. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param NewState: new state of the selected DAC channel DMA request. + * This parameter can be: ENABLE or DISABLE. + * @note The DAC channel1 is mapped on DMA1 Stream 5 channel7 which must be + * already configured. + * @note The DAC channel2 is mapped on DMA1 Stream 6 channel7 which must be + * already configured. + * @retval None + */ +void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected DAC channel DMA request */ + DAC->CR |= (DAC_CR_DMAEN1 << DAC_Channel); + } + else + { + /* Disable the selected DAC channel DMA request */ + DAC->CR &= (~(DAC_CR_DMAEN1 << DAC_Channel)); + } +} +/** + * @} + */ + +/** @defgroup DAC_Group3 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified DAC interrupts. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_IT: specifies the DAC interrupt sources to be enabled or disabled. + * This parameter can be the following values: + * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * @param NewState: new state of the specified DAC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_ITConfig(uint32_t DAC_Channel, uint32_t DAC_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + assert_param(IS_DAC_IT(DAC_IT)); + + if (NewState != DISABLE) + { + /* Enable the selected DAC interrupts */ + DAC->CR |= (DAC_IT << DAC_Channel); + } + else + { + /* Disable the selected DAC interrupts */ + DAC->CR &= (~(uint32_t)(DAC_IT << DAC_Channel)); + } +} + +/** + * @brief Checks whether the specified DAC flag is set or not. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_FLAG: specifies the flag to check. + * This parameter can be only of the following value: + * @arg DAC_FLAG_DMAUDR: DMA underrun flag + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * @retval The new state of DAC_FLAG (SET or RESET). + */ +FlagStatus DAC_GetFlagStatus(uint32_t DAC_Channel, uint32_t DAC_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_FLAG(DAC_FLAG)); + + /* Check the status of the specified DAC flag */ + if ((DAC->SR & (DAC_FLAG << DAC_Channel)) != (uint8_t)RESET) + { + /* DAC_FLAG is set */ + bitstatus = SET; + } + else + { + /* DAC_FLAG is reset */ + bitstatus = RESET; + } + /* Return the DAC_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the DAC channel's pending flags. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_FLAG: specifies the flag to clear. + * This parameter can be of the following value: + * @arg DAC_FLAG_DMAUDR: DMA underrun flag + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * @retval None + */ +void DAC_ClearFlag(uint32_t DAC_Channel, uint32_t DAC_FLAG) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_FLAG(DAC_FLAG)); + + /* Clear the selected DAC flags */ + DAC->SR = (DAC_FLAG << DAC_Channel); +} + +/** + * @brief Checks whether the specified DAC interrupt has occurred or not. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_IT: specifies the DAC interrupt source to check. + * This parameter can be the following values: + * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * @retval The new state of DAC_IT (SET or RESET). + */ +ITStatus DAC_GetITStatus(uint32_t DAC_Channel, uint32_t DAC_IT) +{ + ITStatus bitstatus = RESET; + uint32_t enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_IT(DAC_IT)); + + /* Get the DAC_IT enable bit status */ + enablestatus = (DAC->CR & (DAC_IT << DAC_Channel)) ; + + /* Check the status of the specified DAC interrupt */ + if (((DAC->SR & (DAC_IT << DAC_Channel)) != (uint32_t)RESET) && enablestatus) + { + /* DAC_IT is set */ + bitstatus = SET; + } + else + { + /* DAC_IT is reset */ + bitstatus = RESET; + } + /* Return the DAC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the DAC channel's interrupt pending bits. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_IT: specifies the DAC interrupt pending bit to clear. + * This parameter can be the following values: + * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * @retval None + */ +void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_IT(DAC_IT)); + + /* Clear the selected DAC interrupt pending bits */ + DAC->SR = (DAC_IT << DAC_Channel); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/connect_adc.h b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/connect_adc.h new file mode 100644 index 000000000..fa15f48cb --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/connect_adc.h @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_adc.h +* @brief define aiit-arm32-board adc function and struct +* @version 1.1 +* @author AIIT XUOS Lab +* @date 2021-12-28 +*/ + +#ifndef CONNECT_ADC_H +#define CONNECT_ADC_H + +#include +#include +#include +#include + +struct Stm32HwAdc +{ + ADC_TypeDef *ADCx; + uint8 adc_channel; +}; + +int Stm32HwAdcInit(void); + +#endif diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/connect_dac.h b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/connect_dac.h new file mode 100644 index 000000000..e5fa169de --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/connect_dac.h @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_dac.h +* @brief define stm32f407-st-discovery adc function and struct +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-1-10 +*/ + +#ifndef CONNECT_DAC_H +#define CONNECT_DAC_H + +#include +#include +#include +#include + +struct Stm32HwDac +{ + DAC_TypeDef *DACx; + uint16 digital_data; +}; + +int Stm32HwDacInit(void); + +#endif diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_adc.h b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_adc.h new file mode 100644 index 000000000..a731859d9 --- /dev/null +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_adc.h @@ -0,0 +1,675 @@ +/** + ****************************************************************************** + * @file stm32f4xx_adc.h + * @author MCD Application Team + * @version V1.4.0 + * @date 04-August-2014 + * @brief This file contains all the functions prototypes for the ADC firmware + * library. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/** +* @file: hardware_adc.h +* @brief: define hardware adc function +* @version: 1.1 +* @author: AIIT XUOS Lab +* @date: 2021/12/28 +*/ + +/************************************************* +File name: hardware_adc.h +Description: define hardware adc function +Others: +History: +1. Date: 2021-12-28 +Author: AIIT XUOS Lab +Modification: +1. rename stm32f4xx_adc.h for XiUOS +*************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __HARDWARE_ADC_H__ +#define __HARDWARE_ADC_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @addtogroup ADC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief ADC Init structure definition + */ +typedef struct +{ + uint32_t ADC_Resolution; /*!< Configures the ADC resolution dual mode. + This parameter can be a value of @ref ADC_resolution */ + FunctionalState ADC_ScanConvMode; /*!< Specifies whether the conversion + is performed in Scan (multichannels) + or Single (one channel) mode. + This parameter can be set to ENABLE or DISABLE */ + FunctionalState ADC_ContinuousConvMode; /*!< Specifies whether the conversion + is performed in Continuous or Single mode. + This parameter can be set to ENABLE or DISABLE. */ + uint32_t ADC_ExternalTrigConvEdge; /*!< Select the external trigger edge and + enable the trigger of a regular group. + This parameter can be a value of + @ref ADC_external_trigger_edge_for_regular_channels_conversion */ + uint32_t ADC_ExternalTrigConv; /*!< Select the external event used to trigger + the start of conversion of a regular group. + This parameter can be a value of + @ref ADC_extrenal_trigger_sources_for_regular_channels_conversion */ + uint32_t ADC_DataAlign; /*!< Specifies whether the ADC data alignment + is left or right. This parameter can be + a value of @ref ADC_data_align */ + uint8_t ADC_NbrOfConversion; /*!< Specifies the number of ADC conversions + that will be done using the sequencer for + regular channel group. + This parameter must range from 1 to 16. */ +}ADC_InitTypeDef; + +/** + * @brief ADC Common Init structure definition + */ +typedef struct +{ + uint32_t ADC_Mode; /*!< Configures the ADC to operate in + independent or multi mode. + This parameter can be a value of @ref ADC_Common_mode */ + uint32_t ADC_Prescaler; /*!< Select the frequency of the clock + to the ADC. The clock is common for all the ADCs. + This parameter can be a value of @ref ADC_Prescaler */ + uint32_t ADC_DMAAccessMode; /*!< Configures the Direct memory access + mode for multi ADC mode. + This parameter can be a value of + @ref ADC_Direct_memory_access_mode_for_multi_mode */ + uint32_t ADC_TwoSamplingDelay; /*!< Configures the Delay between 2 sampling phases. + This parameter can be a value of + @ref ADC_delay_between_2_sampling_phases */ + +}ADC_CommonInitTypeDef; + + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup ADC_Exported_Constants + * @{ + */ +#define IS_ADC_ALL_PERIPH(PERIPH) (((PERIPH) == ADC1) || \ + ((PERIPH) == ADC2) || \ + ((PERIPH) == ADC3)) + +/** @defgroup ADC_Common_mode + * @{ + */ +#define ADC_Mode_Independent ((uint32_t)0x00000000) +#define ADC_DualMode_RegSimult_InjecSimult ((uint32_t)0x00000001) +#define ADC_DualMode_RegSimult_AlterTrig ((uint32_t)0x00000002) +#define ADC_DualMode_InjecSimult ((uint32_t)0x00000005) +#define ADC_DualMode_RegSimult ((uint32_t)0x00000006) +#define ADC_DualMode_Interl ((uint32_t)0x00000007) +#define ADC_DualMode_AlterTrig ((uint32_t)0x00000009) +#define ADC_TripleMode_RegSimult_InjecSimult ((uint32_t)0x00000011) +#define ADC_TripleMode_RegSimult_AlterTrig ((uint32_t)0x00000012) +#define ADC_TripleMode_InjecSimult ((uint32_t)0x00000015) +#define ADC_TripleMode_RegSimult ((uint32_t)0x00000016) +#define ADC_TripleMode_Interl ((uint32_t)0x00000017) +#define ADC_TripleMode_AlterTrig ((uint32_t)0x00000019) +#define IS_ADC_MODE(MODE) (((MODE) == ADC_Mode_Independent) || \ + ((MODE) == ADC_DualMode_RegSimult_InjecSimult) || \ + ((MODE) == ADC_DualMode_RegSimult_AlterTrig) || \ + ((MODE) == ADC_DualMode_InjecSimult) || \ + ((MODE) == ADC_DualMode_RegSimult) || \ + ((MODE) == ADC_DualMode_Interl) || \ + ((MODE) == ADC_DualMode_AlterTrig) || \ + ((MODE) == ADC_TripleMode_RegSimult_InjecSimult) || \ + ((MODE) == ADC_TripleMode_RegSimult_AlterTrig) || \ + ((MODE) == ADC_TripleMode_InjecSimult) || \ + ((MODE) == ADC_TripleMode_RegSimult) || \ + ((MODE) == ADC_TripleMode_Interl) || \ + ((MODE) == ADC_TripleMode_AlterTrig)) +/** + * @} + */ + + +/** @defgroup ADC_Prescaler + * @{ + */ +#define ADC_Prescaler_Div2 ((uint32_t)0x00000000) +#define ADC_Prescaler_Div4 ((uint32_t)0x00010000) +#define ADC_Prescaler_Div6 ((uint32_t)0x00020000) +#define ADC_Prescaler_Div8 ((uint32_t)0x00030000) +#define IS_ADC_PRESCALER(PRESCALER) (((PRESCALER) == ADC_Prescaler_Div2) || \ + ((PRESCALER) == ADC_Prescaler_Div4) || \ + ((PRESCALER) == ADC_Prescaler_Div6) || \ + ((PRESCALER) == ADC_Prescaler_Div8)) +/** + * @} + */ + + +/** @defgroup ADC_Direct_memory_access_mode_for_multi_mode + * @{ + */ +#define ADC_DMAAccessMode_Disabled ((uint32_t)0x00000000) /* DMA mode disabled */ +#define ADC_DMAAccessMode_1 ((uint32_t)0x00004000) /* DMA mode 1 enabled (2 / 3 half-words one by one - 1 then 2 then 3)*/ +#define ADC_DMAAccessMode_2 ((uint32_t)0x00008000) /* DMA mode 2 enabled (2 / 3 half-words by pairs - 2&1 then 1&3 then 3&2)*/ +#define ADC_DMAAccessMode_3 ((uint32_t)0x0000C000) /* DMA mode 3 enabled (2 / 3 bytes by pairs - 2&1 then 1&3 then 3&2) */ +#define IS_ADC_DMA_ACCESS_MODE(MODE) (((MODE) == ADC_DMAAccessMode_Disabled) || \ + ((MODE) == ADC_DMAAccessMode_1) || \ + ((MODE) == ADC_DMAAccessMode_2) || \ + ((MODE) == ADC_DMAAccessMode_3)) + +/** + * @} + */ + + +/** @defgroup ADC_delay_between_2_sampling_phases + * @{ + */ +#define ADC_TwoSamplingDelay_5Cycles ((uint32_t)0x00000000) +#define ADC_TwoSamplingDelay_6Cycles ((uint32_t)0x00000100) +#define ADC_TwoSamplingDelay_7Cycles ((uint32_t)0x00000200) +#define ADC_TwoSamplingDelay_8Cycles ((uint32_t)0x00000300) +#define ADC_TwoSamplingDelay_9Cycles ((uint32_t)0x00000400) +#define ADC_TwoSamplingDelay_10Cycles ((uint32_t)0x00000500) +#define ADC_TwoSamplingDelay_11Cycles ((uint32_t)0x00000600) +#define ADC_TwoSamplingDelay_12Cycles ((uint32_t)0x00000700) +#define ADC_TwoSamplingDelay_13Cycles ((uint32_t)0x00000800) +#define ADC_TwoSamplingDelay_14Cycles ((uint32_t)0x00000900) +#define ADC_TwoSamplingDelay_15Cycles ((uint32_t)0x00000A00) +#define ADC_TwoSamplingDelay_16Cycles ((uint32_t)0x00000B00) +#define ADC_TwoSamplingDelay_17Cycles ((uint32_t)0x00000C00) +#define ADC_TwoSamplingDelay_18Cycles ((uint32_t)0x00000D00) +#define ADC_TwoSamplingDelay_19Cycles ((uint32_t)0x00000E00) +#define ADC_TwoSamplingDelay_20Cycles ((uint32_t)0x00000F00) +#define IS_ADC_SAMPLING_DELAY(DELAY) (((DELAY) == ADC_TwoSamplingDelay_5Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_6Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_7Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_8Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_9Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_10Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_11Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_12Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_13Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_14Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_15Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_16Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_17Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_18Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_19Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_20Cycles)) + +/** + * @} + */ + + +/** @defgroup ADC_resolution + * @{ + */ +#define ADC_Resolution_12b ((uint32_t)0x00000000) +#define ADC_Resolution_10b ((uint32_t)0x01000000) +#define ADC_Resolution_8b ((uint32_t)0x02000000) +#define ADC_Resolution_6b ((uint32_t)0x03000000) +#define IS_ADC_RESOLUTION(RESOLUTION) (((RESOLUTION) == ADC_Resolution_12b) || \ + ((RESOLUTION) == ADC_Resolution_10b) || \ + ((RESOLUTION) == ADC_Resolution_8b) || \ + ((RESOLUTION) == ADC_Resolution_6b)) + +/** + * @} + */ + + +/** @defgroup ADC_external_trigger_edge_for_regular_channels_conversion + * @{ + */ +#define ADC_ExternalTrigConvEdge_None ((uint32_t)0x00000000) +#define ADC_ExternalTrigConvEdge_Rising ((uint32_t)0x10000000) +#define ADC_ExternalTrigConvEdge_Falling ((uint32_t)0x20000000) +#define ADC_ExternalTrigConvEdge_RisingFalling ((uint32_t)0x30000000) +#define IS_ADC_EXT_TRIG_EDGE(EDGE) (((EDGE) == ADC_ExternalTrigConvEdge_None) || \ + ((EDGE) == ADC_ExternalTrigConvEdge_Rising) || \ + ((EDGE) == ADC_ExternalTrigConvEdge_Falling) || \ + ((EDGE) == ADC_ExternalTrigConvEdge_RisingFalling)) +/** + * @} + */ + + +/** @defgroup ADC_extrenal_trigger_sources_for_regular_channels_conversion + * @{ + */ +#define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000) +#define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x01000000) +#define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x02000000) +#define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x03000000) +#define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x04000000) +#define ADC_ExternalTrigConv_T2_CC4 ((uint32_t)0x05000000) +#define ADC_ExternalTrigConv_T2_TRGO ((uint32_t)0x06000000) +#define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x07000000) +#define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x08000000) +#define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x09000000) +#define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x0A000000) +#define ADC_ExternalTrigConv_T5_CC2 ((uint32_t)0x0B000000) +#define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x0C000000) +#define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x0D000000) +#define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x0E000000) +#define ADC_ExternalTrigConv_Ext_IT11 ((uint32_t)0x0F000000) +#define IS_ADC_EXT_TRIG(REGTRIG) (((REGTRIG) == ADC_ExternalTrigConv_T1_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T1_CC2) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T1_CC3) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T2_CC2) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T2_CC3) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T2_CC4) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T2_TRGO) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T3_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T3_TRGO) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T4_CC4) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T5_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T5_CC2) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T5_CC3) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T8_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T8_TRGO) || \ + ((REGTRIG) == ADC_ExternalTrigConv_Ext_IT11)) +/** + * @} + */ + + +/** @defgroup ADC_data_align + * @{ + */ +#define ADC_DataAlign_Right ((uint32_t)0x00000000) +#define ADC_DataAlign_Left ((uint32_t)0x00000800) +#define IS_ADC_DATA_ALIGN(ALIGN) (((ALIGN) == ADC_DataAlign_Right) || \ + ((ALIGN) == ADC_DataAlign_Left)) +/** + * @} + */ + + +/** @defgroup ADC_channels + * @{ + */ +#define ADC_Channel_0 ((uint8_t)0x00) +#define ADC_Channel_1 ((uint8_t)0x01) +#define ADC_Channel_2 ((uint8_t)0x02) +#define ADC_Channel_3 ((uint8_t)0x03) +#define ADC_Channel_4 ((uint8_t)0x04) +#define ADC_Channel_5 ((uint8_t)0x05) +#define ADC_Channel_6 ((uint8_t)0x06) +#define ADC_Channel_7 ((uint8_t)0x07) +#define ADC_Channel_8 ((uint8_t)0x08) +#define ADC_Channel_9 ((uint8_t)0x09) +#define ADC_Channel_10 ((uint8_t)0x0A) +#define ADC_Channel_11 ((uint8_t)0x0B) +#define ADC_Channel_12 ((uint8_t)0x0C) +#define ADC_Channel_13 ((uint8_t)0x0D) +#define ADC_Channel_14 ((uint8_t)0x0E) +#define ADC_Channel_15 ((uint8_t)0x0F) +#define ADC_Channel_16 ((uint8_t)0x10) +#define ADC_Channel_17 ((uint8_t)0x11) +#define ADC_Channel_18 ((uint8_t)0x12) + +#if defined (STM32F40_41xxx) +#define ADC_Channel_TempSensor ((uint8_t)ADC_Channel_16) +#endif /* STM32F40_41xxx */ + +#if defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx) || defined (STM32F411xE) +#define ADC_Channel_TempSensor ((uint8_t)ADC_Channel_18) +#endif /* STM32F427_437xx || STM32F429_439xx || STM32F401xx || STM32F411xE */ + +#define ADC_Channel_Vrefint ((uint8_t)ADC_Channel_17) +#define ADC_Channel_Vbat ((uint8_t)ADC_Channel_18) + +#define IS_ADC_CHANNEL(CHANNEL) (((CHANNEL) == ADC_Channel_0) || \ + ((CHANNEL) == ADC_Channel_1) || \ + ((CHANNEL) == ADC_Channel_2) || \ + ((CHANNEL) == ADC_Channel_3) || \ + ((CHANNEL) == ADC_Channel_4) || \ + ((CHANNEL) == ADC_Channel_5) || \ + ((CHANNEL) == ADC_Channel_6) || \ + ((CHANNEL) == ADC_Channel_7) || \ + ((CHANNEL) == ADC_Channel_8) || \ + ((CHANNEL) == ADC_Channel_9) || \ + ((CHANNEL) == ADC_Channel_10) || \ + ((CHANNEL) == ADC_Channel_11) || \ + ((CHANNEL) == ADC_Channel_12) || \ + ((CHANNEL) == ADC_Channel_13) || \ + ((CHANNEL) == ADC_Channel_14) || \ + ((CHANNEL) == ADC_Channel_15) || \ + ((CHANNEL) == ADC_Channel_16) || \ + ((CHANNEL) == ADC_Channel_17) || \ + ((CHANNEL) == ADC_Channel_18)) +/** + * @} + */ + + +/** @defgroup ADC_sampling_times + * @{ + */ +#define ADC_SampleTime_3Cycles ((uint8_t)0x00) +#define ADC_SampleTime_15Cycles ((uint8_t)0x01) +#define ADC_SampleTime_28Cycles ((uint8_t)0x02) +#define ADC_SampleTime_56Cycles ((uint8_t)0x03) +#define ADC_SampleTime_84Cycles ((uint8_t)0x04) +#define ADC_SampleTime_112Cycles ((uint8_t)0x05) +#define ADC_SampleTime_144Cycles ((uint8_t)0x06) +#define ADC_SampleTime_480Cycles ((uint8_t)0x07) +#define IS_ADC_SAMPLE_TIME(TIME) (((TIME) == ADC_SampleTime_3Cycles) || \ + ((TIME) == ADC_SampleTime_15Cycles) || \ + ((TIME) == ADC_SampleTime_28Cycles) || \ + ((TIME) == ADC_SampleTime_56Cycles) || \ + ((TIME) == ADC_SampleTime_84Cycles) || \ + ((TIME) == ADC_SampleTime_112Cycles) || \ + ((TIME) == ADC_SampleTime_144Cycles) || \ + ((TIME) == ADC_SampleTime_480Cycles)) +/** + * @} + */ + + +/** @defgroup ADC_external_trigger_edge_for_injected_channels_conversion + * @{ + */ +#define ADC_ExternalTrigInjecConvEdge_None ((uint32_t)0x00000000) +#define ADC_ExternalTrigInjecConvEdge_Rising ((uint32_t)0x00100000) +#define ADC_ExternalTrigInjecConvEdge_Falling ((uint32_t)0x00200000) +#define ADC_ExternalTrigInjecConvEdge_RisingFalling ((uint32_t)0x00300000) +#define IS_ADC_EXT_INJEC_TRIG_EDGE(EDGE) (((EDGE) == ADC_ExternalTrigInjecConvEdge_None) || \ + ((EDGE) == ADC_ExternalTrigInjecConvEdge_Rising) || \ + ((EDGE) == ADC_ExternalTrigInjecConvEdge_Falling) || \ + ((EDGE) == ADC_ExternalTrigInjecConvEdge_RisingFalling)) + +/** + * @} + */ + + +/** @defgroup ADC_extrenal_trigger_sources_for_injected_channels_conversion + * @{ + */ +#define ADC_ExternalTrigInjecConv_T1_CC4 ((uint32_t)0x00000000) +#define ADC_ExternalTrigInjecConv_T1_TRGO ((uint32_t)0x00010000) +#define ADC_ExternalTrigInjecConv_T2_CC1 ((uint32_t)0x00020000) +#define ADC_ExternalTrigInjecConv_T2_TRGO ((uint32_t)0x00030000) +#define ADC_ExternalTrigInjecConv_T3_CC2 ((uint32_t)0x00040000) +#define ADC_ExternalTrigInjecConv_T3_CC4 ((uint32_t)0x00050000) +#define ADC_ExternalTrigInjecConv_T4_CC1 ((uint32_t)0x00060000) +#define ADC_ExternalTrigInjecConv_T4_CC2 ((uint32_t)0x00070000) +#define ADC_ExternalTrigInjecConv_T4_CC3 ((uint32_t)0x00080000) +#define ADC_ExternalTrigInjecConv_T4_TRGO ((uint32_t)0x00090000) +#define ADC_ExternalTrigInjecConv_T5_CC4 ((uint32_t)0x000A0000) +#define ADC_ExternalTrigInjecConv_T5_TRGO ((uint32_t)0x000B0000) +#define ADC_ExternalTrigInjecConv_T8_CC2 ((uint32_t)0x000C0000) +#define ADC_ExternalTrigInjecConv_T8_CC3 ((uint32_t)0x000D0000) +#define ADC_ExternalTrigInjecConv_T8_CC4 ((uint32_t)0x000E0000) +#define ADC_ExternalTrigInjecConv_Ext_IT15 ((uint32_t)0x000F0000) +#define IS_ADC_EXT_INJEC_TRIG(INJTRIG) (((INJTRIG) == ADC_ExternalTrigInjecConv_T1_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T1_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T2_CC1) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T2_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T3_CC2) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T3_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC1) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC2) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC3) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T5_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T5_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC2) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC3) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_Ext_IT15)) +/** + * @} + */ + + +/** @defgroup ADC_injected_channel_selection + * @{ + */ +#define ADC_InjectedChannel_1 ((uint8_t)0x14) +#define ADC_InjectedChannel_2 ((uint8_t)0x18) +#define ADC_InjectedChannel_3 ((uint8_t)0x1C) +#define ADC_InjectedChannel_4 ((uint8_t)0x20) +#define IS_ADC_INJECTED_CHANNEL(CHANNEL) (((CHANNEL) == ADC_InjectedChannel_1) || \ + ((CHANNEL) == ADC_InjectedChannel_2) || \ + ((CHANNEL) == ADC_InjectedChannel_3) || \ + ((CHANNEL) == ADC_InjectedChannel_4)) +/** + * @} + */ + + +/** @defgroup ADC_analog_watchdog_selection + * @{ + */ +#define ADC_AnalogWatchdog_SingleRegEnable ((uint32_t)0x00800200) +#define ADC_AnalogWatchdog_SingleInjecEnable ((uint32_t)0x00400200) +#define ADC_AnalogWatchdog_SingleRegOrInjecEnable ((uint32_t)0x00C00200) +#define ADC_AnalogWatchdog_AllRegEnable ((uint32_t)0x00800000) +#define ADC_AnalogWatchdog_AllInjecEnable ((uint32_t)0x00400000) +#define ADC_AnalogWatchdog_AllRegAllInjecEnable ((uint32_t)0x00C00000) +#define ADC_AnalogWatchdog_None ((uint32_t)0x00000000) +#define IS_ADC_ANALOG_WATCHDOG(WATCHDOG) (((WATCHDOG) == ADC_AnalogWatchdog_SingleRegEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_SingleInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_SingleRegOrInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_AllRegEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_AllInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_AllRegAllInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_None)) +/** + * @} + */ + + +/** @defgroup ADC_interrupts_definition + * @{ + */ +#define ADC_IT_EOC ((uint16_t)0x0205) +#define ADC_IT_AWD ((uint16_t)0x0106) +#define ADC_IT_JEOC ((uint16_t)0x0407) +#define ADC_IT_OVR ((uint16_t)0x201A) +#define IS_ADC_IT(IT) (((IT) == ADC_IT_EOC) || ((IT) == ADC_IT_AWD) || \ + ((IT) == ADC_IT_JEOC)|| ((IT) == ADC_IT_OVR)) +/** + * @} + */ + + +/** @defgroup ADC_flags_definition + * @{ + */ +#define ADC_FLAG_AWD ((uint8_t)0x01) +#define ADC_FLAG_EOC ((uint8_t)0x02) +#define ADC_FLAG_JEOC ((uint8_t)0x04) +#define ADC_FLAG_JSTRT ((uint8_t)0x08) +#define ADC_FLAG_STRT ((uint8_t)0x10) +#define ADC_FLAG_OVR ((uint8_t)0x20) + +#define IS_ADC_CLEAR_FLAG(FLAG) ((((FLAG) & (uint8_t)0xC0) == 0x00) && ((FLAG) != 0x00)) +#define IS_ADC_GET_FLAG(FLAG) (((FLAG) == ADC_FLAG_AWD) || \ + ((FLAG) == ADC_FLAG_EOC) || \ + ((FLAG) == ADC_FLAG_JEOC) || \ + ((FLAG)== ADC_FLAG_JSTRT) || \ + ((FLAG) == ADC_FLAG_STRT) || \ + ((FLAG)== ADC_FLAG_OVR)) +/** + * @} + */ + + +/** @defgroup ADC_thresholds + * @{ + */ +#define IS_ADC_THRESHOLD(THRESHOLD) ((THRESHOLD) <= 0xFFF) +/** + * @} + */ + + +/** @defgroup ADC_injected_offset + * @{ + */ +#define IS_ADC_OFFSET(OFFSET) ((OFFSET) <= 0xFFF) +/** + * @} + */ + + +/** @defgroup ADC_injected_length + * @{ + */ +#define IS_ADC_INJECTED_LENGTH(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x4)) +/** + * @} + */ + + +/** @defgroup ADC_injected_rank + * @{ + */ +#define IS_ADC_INJECTED_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x4)) +/** + * @} + */ + + +/** @defgroup ADC_regular_length + * @{ + */ +#define IS_ADC_REGULAR_LENGTH(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x10)) +/** + * @} + */ + + +/** @defgroup ADC_regular_rank + * @{ + */ +#define IS_ADC_REGULAR_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x10)) +/** + * @} + */ + + +/** @defgroup ADC_regular_discontinuous_mode_number + * @{ + */ +#define IS_ADC_REGULAR_DISC_NUMBER(NUMBER) (((NUMBER) >= 0x1) && ((NUMBER) <= 0x8)) +/** + * @} + */ + + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/* Function used to set the ADC configuration to the default reset state *****/ +void ADC_DeInit(void); + +/* Initialization and Configuration functions *********************************/ +void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); +void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct); +void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct); +void ADC_CommonStructInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct); +void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); + +/* Analog Watchdog configuration functions ************************************/ +void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog); +void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,uint16_t LowThreshold); +void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel); + +/* Temperature Sensor, Vrefint and VBAT management functions ******************/ +void ADC_TempSensorVrefintCmd(FunctionalState NewState); +void ADC_VBATCmd(FunctionalState NewState); + +/* Regular Channels Configuration functions ***********************************/ +void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_SoftwareStartConv(ADC_TypeDef* ADCx); +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx); +void ADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number); +void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx); +uint32_t ADC_GetMultiModeConversionValue(void); + +/* Regular Channels DMA Configuration functions *******************************/ +void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_MultiModeDMARequestAfterLastTransferCmd(FunctionalState NewState); + +/* Injected channels Configuration functions **********************************/ +void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length); +void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset); +void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv); +void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge); +void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx); +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx); +void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel); + +/* Interrupts and flags management functions **********************************/ +void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState); +FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); +void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); +ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT); +void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F4xx_ADC_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_conf.h b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_conf.h index b6e0204bb..9f05bf72d 100644 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_conf.h +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_conf.h @@ -80,7 +80,7 @@ Modification: /* Uncomment the line below to expanse the "assert_param" macro in the Standard Peripheral Library drivers code */ -#define USE_FULL_ASSERT 1 +//#define USE_FULL_ASSERT 1 /* Exported macro ------------------------------------------------------------*/ #ifdef USE_FULL_ASSERT diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_dac.h b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_dac.h index 8ac5d55c0..2918dc7c6 100644 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_dac.h +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/include/hardware_dac.h @@ -2,30 +2,36 @@ ****************************************************************************** * @file stm32f4xx_dac.h * @author MCD Application Team - * @version V1.0.0 - * @date 30-September-2011 + * @version V1.4.0 + * @date 04-August-2014 * @brief This file contains all the functions prototypes for the DAC firmware * library. ****************************************************************************** * @attention * - * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS - * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE - * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY - * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING - * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE - * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - *

© COPYRIGHT 2011 STMicroelectronics

****************************************************************************** */ /** * @file: hardware_dac.h * @brief: define hardware dac function -* @version: 1.0 +* @version: 2.0 * @author: AIIT XUOS Lab -* @date: 2021/4/25 +* @date: 2022/1/10 */ /************************************************* @@ -33,7 +39,7 @@ File name: hardware_dac.h Description: define hardware dac function Others: History: -1. Date: 2021-04-25 +1. Date: 2022-1-10 Author: AIIT XUOS Lab Modification: 1. rename stm32f4xx_dac.h for XiUOS @@ -48,7 +54,7 @@ Modification: #endif /* Includes ------------------------------------------------------------------*/ -#include +#include "stm32f4xx.h" /** @addtogroup STM32F4xx_StdPeriph_Driver * @{ @@ -314,4 +320,4 @@ void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT); * @} */ -/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/uart/Kconfig b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/uart/Kconfig index e95c28aad..c9a07f334 100644 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/uart/Kconfig +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/uart/Kconfig @@ -9,8 +9,11 @@ menuconfig BSP_USING_USART1 string "serial bus 1 driver name" default "usart1_drv" config SERIAL_1_DEVICE_NAME_0 - string "serial bus 1 device name" - default "usart1_dev1" + string "serial bus 1 device 0 name" + default "usart1_dev1" + config USART1_USING_DMA + bool "usart1 using DMA" + default n endif menuconfig BSP_USING_USART2 @@ -24,8 +27,11 @@ menuconfig BSP_USING_USART2 string "serial bus 2 driver name" default "usart2_drv" config SERIAL_2_DEVICE_NAME_0 - string "serial bus 2 device name" - default "usart2_dev2" + string "serial bus 2 device 0 name" + default "usart2_dev2" + config USART2_USING_DMA + bool "usart2 using DMA" + default n endif menuconfig BSP_USING_USART3 @@ -39,8 +45,11 @@ menuconfig BSP_USING_USART3 string "serial bus 3 driver name" default "usart3_drv" config SERIAL_3_DEVICE_NAME_0 - string "serial bus 3 device name" - default "usart3_dev3" + string "serial bus 3 device 0 name" + default "usart3_dev3" + config USART3_USING_DMA + bool "usart3 using DMA" + default n endif menuconfig BSP_USING_UART4 @@ -54,8 +63,11 @@ menuconfig BSP_USING_UART4 string "serial bus 4 driver name" default "uart4_drv" config SERIAL_4_DEVICE_NAME_0 - string "serial bus 4 device name" - default "uart4_dev4" + string "serial bus 4 device 0 name" + default "uart4_dev4" + config USART4_USING_DMA + bool "usart4 using DMA" + default n endif menuconfig BSP_USING_UART5 @@ -69,6 +81,9 @@ menuconfig BSP_USING_UART5 string "serial bus 5 driver name" default "uart5_drv" config SERIAL_5_DEVICE_NAME_0 - string "serial bus 5 device name" - default "uart5_dev5" + string "serial bus 5 device 0 name" + default "uart5_dev5" + config USART5_USING_DMA + bool "usart5 using DMA" + default n endif diff --git a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/uart/connect_usart.c b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/uart/connect_usart.c index 23bed8857..32f8cda32 100644 --- a/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/uart/connect_usart.c +++ b/Ubiquitous/XiUOS/board/aiit-arm32-board/third_party_driver/uart/connect_usart.c @@ -228,19 +228,19 @@ static void SerialCfgParamCheck(struct SerialCfgParam *serial_cfg_default, struc struct SerialDataCfg *data_cfg_default = &serial_cfg_default->data_cfg; struct SerialDataCfg *data_cfg_new = &serial_cfg_new->data_cfg; - if((data_cfg_default->serial_baud_rate != data_cfg_new->serial_baud_rate) && (data_cfg_new->serial_baud_rate)){ + if((data_cfg_default->serial_baud_rate != data_cfg_new->serial_baud_rate) && (data_cfg_new->serial_baud_rate)) { data_cfg_default->serial_baud_rate = data_cfg_new->serial_baud_rate; } - if((data_cfg_default->serial_bit_order != data_cfg_new->serial_bit_order) && (data_cfg_new->serial_bit_order)){ + if((data_cfg_default->serial_bit_order != data_cfg_new->serial_bit_order) && (data_cfg_new->serial_bit_order)) { data_cfg_default->serial_bit_order = data_cfg_new->serial_bit_order; } - if((data_cfg_default->serial_buffer_size != data_cfg_new->serial_buffer_size) && (data_cfg_new->serial_buffer_size)){ + if((data_cfg_default->serial_buffer_size != data_cfg_new->serial_buffer_size) && (data_cfg_new->serial_buffer_size)) { data_cfg_default->serial_buffer_size = data_cfg_new->serial_buffer_size; } - if((data_cfg_default->serial_data_bits != data_cfg_new->serial_data_bits) && (data_cfg_new->serial_data_bits)){ + if((data_cfg_default->serial_data_bits != data_cfg_new->serial_data_bits) && (data_cfg_new->serial_data_bits)) { data_cfg_default->serial_data_bits = data_cfg_new->serial_data_bits; } @@ -322,8 +322,7 @@ static uint32 Stm32SerialConfigure(struct SerialDriver *serial_drv, int serial_o USART_ITConfig(serial_hw_cfg->uart_device, USART_IT_RXNE, ENABLE); break; case OPER_CONFIG : - if (SIGN_OPER_DMA_RX == serial_dev_param->serial_set_mode) - { + if (SIGN_OPER_DMA_RX == serial_dev_param->serial_set_mode) { DMAConfiguration(serial_dev, serial_hw_cfg->uart_device); } } @@ -378,8 +377,16 @@ static void DmaRxDoneIsr(struct Stm32Usart *serial, struct SerialDriver *serial_ if (DMA_GetFlagStatus(dma->RxStream, dma->RxFlag) != RESET) { x_base level = CriticalAreaLock(); - x_size_t recv_len = dma->SettingRecvLen - dma->LastRecvIndex; - dma->LastRecvIndex = 0; + x_size_t recv_len; + + x_size_t recv_total_index = dma->SettingRecvLen - DMA_GetCurrDataCounter(dma->RxStream); + if (0 != recv_total_index) { + recv_len = recv_total_index - dma->LastRecvIndex; + } else { + recv_len = dma->SettingRecvLen - dma->LastRecvIndex; + } + dma->LastRecvIndex = recv_total_index; + CriticalAreaUnLock(level); if (recv_len) SerialSetIsr(serial_dev, SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); @@ -397,15 +404,14 @@ static void UartIsr(struct Stm32Usart *serial, struct SerialDriver *serial_drv, if (USART_GetITStatus(serial_hw_cfg->uart_device, USART_IT_RXNE) != RESET) { SerialSetIsr(serial_dev, SERIAL_EVENT_RX_IND); USART_ClearITPendingBit(serial_hw_cfg->uart_device, USART_IT_RXNE); - } - if (USART_GetITStatus(serial_hw_cfg->uart_device, USART_IT_IDLE) != RESET) { + } else if (USART_GetITStatus(serial_hw_cfg->uart_device, USART_IT_IDLE) != RESET) { DmaUartRxIdleIsr(serial_dev, dma, serial_hw_cfg->uart_device); - } - if (USART_GetITStatus(serial_hw_cfg->uart_device, USART_IT_TC) != RESET) { + } else if (USART_GetITStatus(serial_hw_cfg->uart_device, USART_IT_TC) != RESET) { USART_ClearITPendingBit(serial_hw_cfg->uart_device, USART_IT_TC); - } - if (USART_GetFlagStatus(serial_hw_cfg->uart_device, USART_FLAG_ORE) == SET) { - USART_ReceiveData(serial_hw_cfg->uart_device); + } else { + if (USART_GetFlagStatus(serial_hw_cfg->uart_device, USART_FLAG_ORE) == SET) { + USART_ReceiveData(serial_hw_cfg->uart_device); + } } } @@ -673,6 +679,9 @@ int Stm32HwUsartInit(void) serial_driver_1.private_data = (void *)&serial_cfg_1; serial_dev_param_1.serial_work_mode = SIGN_OPER_INT_RX; +#ifdef USART1_USING_DMA + serial_dev_param_1.serial_work_mode = SIGN_OPER_DMA_RX; +#endif serial_device_1.haldev.private_data = (void *)&serial_dev_param_1; NVIC_Configuration(serial_hw_cfg_1.irq); @@ -707,7 +716,6 @@ int Stm32HwUsartInit(void) serial_device_2.hwdev_done = &hwdev_done; serial_cfg_2.data_cfg = data_cfg_init; - serial_cfg_2.data_cfg.serial_baud_rate=BAUD_RATE_115200; serial_hw_cfg_2.uart_device = USART2; serial_hw_cfg_2.irq = USART2_IRQn; @@ -715,6 +723,9 @@ int Stm32HwUsartInit(void) serial_driver_2.private_data = (void *)&serial_cfg_2; serial_dev_param_2.serial_work_mode = SIGN_OPER_INT_RX; +#ifdef USART2_USING_DMA + serial_dev_param_2.serial_work_mode = SIGN_OPER_DMA_RX; +#endif serial_device_2.haldev.private_data = (void *)&serial_dev_param_2; NVIC_Configuration(serial_hw_cfg_2.irq); @@ -749,7 +760,6 @@ int Stm32HwUsartInit(void) serial_device_3.hwdev_done = &hwdev_done; serial_cfg_3.data_cfg = data_cfg_init; - serial_cfg_3.data_cfg.serial_baud_rate=BAUD_RATE_57600; serial_hw_cfg_3.uart_device = USART3; serial_hw_cfg_3.irq = USART3_IRQn; @@ -757,6 +767,9 @@ int Stm32HwUsartInit(void) serial_driver_3.private_data = (void *)&serial_cfg_3; serial_dev_param_3.serial_work_mode = SIGN_OPER_INT_RX; +#ifdef USART3_USING_DMA + serial_dev_param_3.serial_work_mode = SIGN_OPER_DMA_RX; +#endif serial_device_3.haldev.private_data = (void *)&serial_dev_param_3; NVIC_Configuration(serial_hw_cfg_3.irq); @@ -798,6 +811,9 @@ int Stm32HwUsartInit(void) serial_driver_4.private_data = (void *)&serial_cfg_4; serial_dev_param_4.serial_work_mode = SIGN_OPER_INT_RX; +#ifdef USART4_USING_DMA + serial_dev_param_4.serial_work_mode = SIGN_OPER_DMA_RX; +#endif serial_device_4.haldev.private_data = (void *)&serial_dev_param_4; NVIC_Configuration(serial_hw_cfg_4.irq); @@ -839,6 +855,9 @@ int Stm32HwUsartInit(void) serial_driver_5.private_data = (void *)&serial_cfg_5; serial_dev_param_5.serial_work_mode = SIGN_OPER_INT_RX; +#ifdef USART5_USING_DMA + serial_dev_param_5.serial_work_mode = SIGN_OPER_DMA_RX; +#endif serial_device_5.haldev.private_data = (void *)&serial_dev_param_5; NVIC_Configuration(serial_hw_cfg_5.irq); diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c index 39d9f45be..40a9e3251 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c @@ -216,7 +216,7 @@ void ethernetif_input(struct netif *netif) /* pass all packets to ethernet_input, which decides what packets it supports */ if ((ret = netif->input(p, netif)) != ERR_OK) { -// LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); lw_print("lw: [%s] ret %d p %p\n", __func__, ret, p); pbuf_free(p); p = NULL; diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_kinetis.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_kinetis.c index 68c63777c..dd91ce952 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_kinetis.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_kinetis.c @@ -1,735 +1,686 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -/* - * Copyright (c) 2013-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2019 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* - * Copyright (c) 2021 AIIT XUOS Lab - * XiUOS is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -/** - * @file enet_ethernetif_kinetis.c - * @brief ethernet drivers - * @version 1.0 - * @author AIIT XUOS Lab - * @date 2021.11.11 - */ - -#include "lwip/opt.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/ethip6.h" -#include "netif/etharp.h" -#include "netif/ppp/pppoe.h" -#include "lwip/igmp.h" -#include "lwip/mld6.h" - -//#define USE_RTOS 1 -//#define FSL_RTOS_FREE_RTOS -//#define FSL_RTOS_XIUOS - -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - -#ifdef FSL_RTOS_XIUOS -#include "xs_sem.h" - -#else -#include "FreeRTOS.h" -#include "event_groups.h" -#include "list.h" -#endif - -typedef uint32_t TickType_t; -#define portMAX_DELAY ( TickType_t ) 0xffffffffUL - -typedef TickType_t EventBits_t; - -typedef long BaseType_t; -typedef unsigned long UBaseType_t; - -#define portBASE_TYPE long - -#define pdFALSE ( ( BaseType_t ) 0 ) -#define pdTRUE ( ( BaseType_t ) 1 ) - -#define pdPASS ( pdTRUE ) -#define pdFAIL ( pdFALSE ) - -#ifndef FSL_RTOS_XIUOS -typedef struct EventGroupDef_t -{ - EventBits_t uxEventBits; - List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ - - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxEventGroupNumber; - #endif - - #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ - #endif -} EventGroup_t; - -struct EventGroupDef_t; -typedef struct EventGroupDef_t * EventGroupHandle_t; -#endif - -#endif - -#include "enet_ethernetif.h" -#include "enet_ethernetif_priv.h" - -#include "fsl_enet.h" -#include "fsl_phy.h" - -#include "sys_arch.h" - - - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/** - * Helper struct to hold private data used to operate your ethernet interface. - */ -struct ethernetif -{ - ENET_Type *base; -#if (defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)) || \ - (USE_RTOS && defined(FSL_RTOS_FREE_RTOS)) - enet_handle_t handle; -#endif -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - -#ifdef FSL_RTOS_XIUOS - int enetSemaphore; -#else - EventGroupHandle_t enetTransmitAccessEvent; -#endif - EventBits_t txFlag; -#endif - enet_rx_bd_struct_t *RxBuffDescrip; - enet_tx_bd_struct_t *TxBuffDescrip; - rx_buffer_t *RxDataBuff; - tx_buffer_t *TxDataBuff; -}; - - -/******************************************************************************* - * Code - ******************************************************************************/ -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) -#if FSL_FEATURE_ENET_QUEUE > 1 -static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, uint32_t ringId, enet_event_t event, void *param) -#else -static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) -#endif /* FSL_FEATURE_ENET_QUEUE */ -{ - struct netif *netif = (struct netif *)param; - struct ethernetif *ethernetif = netif->state; - BaseType_t xResult; - - - lw_print("lw: [%s] input event %#x \n", __func__, event); - - switch (event) - { - case kENET_RxEvent: - ethernetif_input(netif); - break; - case kENET_TxEvent: - { - portBASE_TYPE taskToWake = pdFALSE; - -#ifdef FSL_RTOS_XIUOS - -#else -#ifdef __CA7_REV - if (SystemGetIRQNestingLevel()) -#else - if (__get_IPSR()) -#endif - { - xResult = xEventGroupSetBitsFromISR(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, &taskToWake); - if ((pdPASS == xResult) && (pdTRUE == taskToWake)) - { - portYIELD_FROM_ISR(taskToWake); - } - } - else - { - xEventGroupSetBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag); - } -#endif - } - break; - default: - break; - } - - KSemaphoreAbandon(ethernetif->enetSemaphore); -} -#endif - -#if LWIP_IPV4 && LWIP_IGMP -err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, - enum netif_mac_filter_action action) -{ - struct ethernetif *ethernetif = netif->state; - uint8_t multicastMacAddr[6]; - err_t result; - - multicastMacAddr[0] = 0x01U; - multicastMacAddr[1] = 0x00U; - multicastMacAddr[2] = 0x5EU; - multicastMacAddr[3] = (group->addr >> 8) & 0x7FU; - multicastMacAddr[4] = (group->addr >> 16) & 0xFFU; - multicastMacAddr[5] = (group->addr >> 24) & 0xFFU; - - switch (action) - { - case IGMP_ADD_MAC_FILTER: - /* Adds the ENET device to a multicast group.*/ - ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr); - result = ERR_OK; - break; - case IGMP_DEL_MAC_FILTER: - /* - * Moves the ENET device from a multicast group. - * Since the ENET_LeaveMulticastGroup() could filter out also other - * group addresses having the same hash, the call is commented out. - */ - /* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */ - result = ERR_OK; - break; - default: - result = ERR_IF; - break; - } - - return result; -} -#endif - -#if LWIP_IPV6 && LWIP_IPV6_MLD -err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group, - enum netif_mac_filter_action action) -{ - struct ethernetif *ethernetif = netif->state; - uint8_t multicastMacAddr[6]; - err_t result; - - multicastMacAddr[0] = 0x33U; - multicastMacAddr[1] = 0x33U; - multicastMacAddr[2] = (group->addr[3]) & 0xFFU; - multicastMacAddr[3] = (group->addr[3] >> 8) & 0xFFU; - multicastMacAddr[4] = (group->addr[3] >> 16) & 0xFFU; - multicastMacAddr[5] = (group->addr[3] >> 24) & 0xFFU; - - switch (action) - { - case NETIF_ADD_MAC_FILTER: - /* Adds the ENET device to a multicast group.*/ - ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr); - result = ERR_OK; - break; - case NETIF_DEL_MAC_FILTER: - /* - * Moves the ENET device from a multicast group. - * Since the ENET_LeaveMulticastGroup() could filter out also other - * group addresses having the same hash, the call is commented out. - */ - /* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */ - result = ERR_OK; - break; - default: - result = ERR_IF; - break; - } - - return result; -} -#endif - -#define netifINTERFACE_TASK_STACK_SIZE ( 4096 ) - -/** - * This function is the ethernetif_input task, it is processed when a packet - * is ready to be read from the interface. It uses the function low_level_input() - * that should handle the actual reception of bytes from the network - * interface. Then the type of the received packet is determined and - * the appropriate input function is called. - * - * @param netif the lwip network interface structure for this ethernetif - */ -//void eth_input( void * pvParameters ) -//{ -// struct pbuf *p; -// -// for( ;; ) -// { -// if (KSemaphoreObtain( s_xSemaphore, WAITING_FOREVER)==EOK) -// { -// p = low_level_input( s_pxNetIf ); -// -// if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf)) -// { -// KPrintf("netif input return not OK ! \n"); -// pbuf_free(p); -// p=NULL; -// } -// } -// } -//} -// -//void low_level_init() -//{ -// /* create the task that handles the ETH_MAC */ -// uint32 thr_id = KTaskCreate((signed char*) "eth_input", -// eth_input, -// NULL, -// netifINTERFACE_TASK_STACK_SIZE, -// 15); -// if (thr_id >= 0) -// { -// StartupKTask(thr_id); -// } -// else -// { -// KPrintf("Eth create failed !"); -// } -//} - - -/** - * Initializes ENET driver. - */ -void ethernetif_enet_init(struct netif *netif, struct ethernetif *ethernetif, - const ethernetif_config_t *ethernetifConfig) -{ - enet_config_t config; - uint32_t sysClock; - enet_buffer_config_t buffCfg[ENET_RING_NUM]; - - /* prepare the buffer configuration. */ - buffCfg[0].rxBdNumber = ENET_RXBD_NUM; /* Receive buffer descriptor number. */ - buffCfg[0].txBdNumber = ENET_TXBD_NUM; /* Transmit buffer descriptor number. */ - buffCfg[0].rxBuffSizeAlign = sizeof(rx_buffer_t); /* Aligned receive data buffer size. */ - buffCfg[0].txBuffSizeAlign = sizeof(tx_buffer_t); /* Aligned transmit data buffer size. */ - buffCfg[0].rxBdStartAddrAlign = &(ethernetif->RxBuffDescrip[0]); /* Aligned receive buffer descriptor start address. */ - buffCfg[0].txBdStartAddrAlign = &(ethernetif->TxBuffDescrip[0]); /* Aligned transmit buffer descriptor start address. */ - buffCfg[0].rxBufferAlign = &(ethernetif->RxDataBuff[0][0]); /* Receive data buffer start address. */ - buffCfg[0].txBufferAlign = &(ethernetif->TxDataBuff[0][0]); /* Transmit data buffer start address. */ - - sysClock = CLOCK_GetFreq(ethernetifConfig->clockName); - - ENET_GetDefaultConfig(&config); - config.ringNum = ENET_RING_NUM; - - ethernetif_phy_init(ethernetif, ethernetifConfig, &config); - -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - uint32_t instance; - static ENET_Type *const enetBases[] = ENET_BASE_PTRS; - static const IRQn_Type enetTxIrqId[] = ENET_Transmit_IRQS; - /*! @brief Pointers to enet receive IRQ number for each instance. */ - static const IRQn_Type enetRxIrqId[] = ENET_Receive_IRQS; -#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE - /*! @brief Pointers to enet timestamp IRQ number for each instance. */ - static const IRQn_Type enetTsIrqId[] = ENET_1588_Timer_IRQS; -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ - - /* Create the Event for transmit busy release trigger. */ -#ifdef FSL_RTOS_XIUOS - if(ethernetif->enetSemaphore < 0) - { - ethernetif->enetSemaphore = KSemaphoreCreate(0); - } -#else - ethernetif->enetTransmitAccessEvent = xEventGroupCreate(); -#endif - ethernetif->txFlag = 0x1; - - config.interrupt |= kENET_RxFrameInterrupt | kENET_TxFrameInterrupt | kENET_TxBufferInterrupt; - - for (instance = 0; instance < ARRAY_SIZE(enetBases); instance++) - { - if (enetBases[instance] == ethernetif->base) - { -#ifdef __CA7_REV - GIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY); - GIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY); -#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE - GIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY); -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ -#else - NVIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY); - NVIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY); -#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE - NVIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY); -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ -#endif /* __CA7_REV */ - break; - } - } - - LWIP_ASSERT("Input Ethernet base error!", (instance != ARRAY_SIZE(enetBases))); -#endif /* USE_RTOS */ - - /* Initialize the ENET module.*/ - ENET_Init(ethernetif->base, ðernetif->handle, &config, &buffCfg[0], netif->hwaddr, sysClock); - -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - ENET_SetCallback(ðernetif->handle, ethernet_callback, netif); -#endif - - ENET_ActiveRead(ethernetif->base); -// low_level_init(); -} - -ENET_Type **ethernetif_enet_ptr(struct ethernetif *ethernetif) -{ - return &(ethernetif->base); -} - -/** - * Returns next buffer for TX. - * Can wait if no buffer available. - */ -static unsigned char *enet_get_tx_buffer(struct ethernetif *ethernetif) -{ - static unsigned char ucBuffer[ENET_FRAME_MAX_FRAMELEN]; - return ucBuffer; -} - -/** - * Sends frame via ENET. - */ -static err_t enet_send_frame(struct ethernetif *ethernetif, unsigned char *data, const uint32_t length) -{ -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - { - status_t result; - - lw_print("lw: [%s] len %d\n", __func__, length); - - do - { - result = ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length); - - if (result == kStatus_ENET_TxFrameBusy) - { -#ifdef FSL_RTOS_XIUOS -// KSemaphoreObtain(ethernetif->enetSemaphore, portMAX_DELAY); -#else - xEventGroupWaitBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, pdTRUE, (BaseType_t) false, - portMAX_DELAY); -#endif - } - - } while (result == kStatus_ENET_TxFrameBusy); - - return ERR_OK; - } -#else - { - uint32_t counter; - - for (counter = ENET_TIMEOUT; counter != 0U; counter--) - { - if (ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length) != kStatus_ENET_TxFrameBusy) - { - return ERR_OK; - } - } - - return ERR_TIMEOUT; - } -#endif -} - -struct pbuf *ethernetif_linkinput(struct netif *netif) -{ - struct ethernetif *ethernetif = netif->state; - struct pbuf *p = NULL; - struct pbuf *q; - uint32_t len; - status_t status; - - /* Obtain the size of the packet and put it into the "len" - variable. */ - status = ENET_GetRxFrameSize(ðernetif->handle, &len); - - if (kStatus_ENET_RxFrameEmpty != status) - { - /* Call ENET_ReadFrame when there is a received frame. */ - if (len != 0) - { -#if ETH_PAD_SIZE - len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ -#endif - - /* We allocate a pbuf chain of pbufs from the pool. */ - p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); - - if (p != NULL) - { -#if ETH_PAD_SIZE - pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ -#endif - if (p->next == 0) /* One-chain buffer.*/ - { - ENET_ReadFrame(ethernetif->base, ðernetif->handle, p->payload, p->len); - } - else /* Multi-chain buffer.*/ - { - uint8_t data_tmp[ENET_FRAME_MAX_FRAMELEN]; - uint32_t data_tmp_len = 0; - - ENET_ReadFrame(ethernetif->base, ðernetif->handle, data_tmp, p->tot_len); - - /* We iterate over the pbuf chain until we have read the entire - * packet into the pbuf. */ - for (q = p; (q != NULL) && ((data_tmp_len + q->len) <= sizeof(data_tmp)); q = q->next) - { - /* Read enough bytes to fill this pbuf in the chain. The - * available data in the pbuf is given by the q->len - * variable. */ - memcpy(q->payload, &data_tmp[data_tmp_len], q->len); - data_tmp_len += q->len; - } - } - - MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); - if (((u8_t *)p->payload)[0] & 1) - { - /* broadcast or multicast packet*/ - MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); - } - else - { - /* unicast packet*/ - MIB2_STATS_NETIF_INC(netif, ifinucastpkts); - } -#if ETH_PAD_SIZE - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ -#endif - - LINK_STATS_INC(link.recv); - } - else - { - /* drop packet*/ - ENET_ReadFrame(ethernetif->base, ðernetif->handle, NULL, 0U); - - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: Fail to allocate new memory space\n")); - - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(netif, ifindiscards); - } - } - else - { - /* Update the received buffer when error happened. */ - if (status == kStatus_ENET_RxFrameError) - { -#if 0 && defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0) /* Error statisctics */ - enet_data_error_stats_t eErrStatic; - /* Get the error information of the received g_frame. */ - ENET_GetRxErrBeforeReadFrame(ðernetif->handle, &eErrStatic); -#endif - - /* Update the receive buffer. */ - ENET_ReadFrame(ethernetif->base, ðernetif->handle, NULL, 0U); - - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: RxFrameError\n")); - - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(netif, ifindiscards); - } - } - } - - return p; -} - -err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) -{ - err_t result; - struct ethernetif *ethernetif = netif->state; - struct pbuf *q; - unsigned char *pucBuffer; - unsigned char *pucChar; - - LWIP_ASSERT("Output packet buffer empty", p); - - pucBuffer = enet_get_tx_buffer(ethernetif); - if (pucBuffer == NULL) - { - return ERR_BUF; - } - -/* Initiate transfer. */ - -#if ETH_PAD_SIZE - pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ -#endif - - if (p->len == p->tot_len) - { - /* No pbuf chain, don't have to copy -> faster. */ - pucBuffer = (unsigned char *)p->payload; - } - else - { - /* pbuf chain, copy into contiguous ucBuffer. */ - if (p->tot_len > ENET_FRAME_MAX_FRAMELEN) - { - return ERR_BUF; - } - else - { - pucChar = pucBuffer; - - for (q = p; q != NULL; q = q->next) - { - /* Send the data from the pbuf to the interface, one pbuf at a - time. The size of the data in each pbuf is kept in the ->len - variable. */ - /* send data from(q->payload, q->len); */ - memcpy(pucChar, q->payload, q->len); - pucChar += q->len; - } - } - } - - /* Send frame. */ - result = enet_send_frame(ethernetif, pucBuffer, p->tot_len); - - MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len); - if (((u8_t *)p->payload)[0] & 1) - { - /* broadcast or multicast packet*/ - MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); - } - else - { - /* unicast packet */ - MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); - } -/* increase ifoutdiscards or ifouterrors on error */ - -#if ETH_PAD_SIZE - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ -#endif - - LINK_STATS_INC(link.xmit); - - return result; -} - -/** - * Should be called at the beginning of the program to set up the - * first network interface. It calls the function ethernetif_init() to do the - * actual setup of the hardware. - * - * This function should be passed as a parameter to netif_add(). - * - * @param netif the lwip network interface structure for this ethernetif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - * any other err_t on error - */ -err_t ethernetif0_init(struct netif *netif) -{ - static struct ethernetif ethernetif_0; - AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - SDK_ALIGN(static rx_buffer_t rxDataBuff_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - SDK_ALIGN(static tx_buffer_t txDataBuff_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - - ethernetif_0.RxBuffDescrip = &(rxBuffDescrip_0[0]); - ethernetif_0.TxBuffDescrip = &(txBuffDescrip_0[0]); - ethernetif_0.RxDataBuff = &(rxDataBuff_0[0]); - ethernetif_0.TxDataBuff = &(txDataBuff_0[0]); - - return ethernetif_init(netif, ðernetif_0, 0U, (ethernetif_config_t *)netif->state); -} - -#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 1) -/** - * Should be called at the beginning of the program to set up the - * second network interface. It calls the function ethernetif_init() to do the - * actual setup of the hardware. - * - * This function should be passed as a parameter to netif_add(). - * - * @param netif the lwip network interface structure for this ethernetif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - * any other err_t on error - */ -err_t ethernetif1_init(struct netif *netif) -{ - static struct ethernetif ethernetif_1; - AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - SDK_ALIGN(static rx_buffer_t rxDataBuff_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - SDK_ALIGN(static tx_buffer_t txDataBuff_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - - ethernetif_1.RxBuffDescrip = &(rxBuffDescrip_1[0]); - ethernetif_1.TxBuffDescrip = &(txBuffDescrip_1[0]); - ethernetif_1.RxDataBuff = &(rxDataBuff_1[0]); - ethernetif_1.TxDataBuff = &(txDataBuff_1[0]); - - return ethernetif_init(netif, ðernetif_1, 1U, (ethernetif_config_t *)netif->state); -} -#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * Copyright (c) 2013-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Copyright (c) 2021 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +/** + * @file enet_ethernetif_kinetis.c + * @brief ethernet drivers + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2021.11.11 + */ + +#include "sys_arch.h" +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/ethip6.h" +#include "netif/etharp.h" +#include "netif/ppp/pppoe.h" +#include "lwip/igmp.h" +#include "lwip/mld6.h" + +#ifdef FSL_RTOS_XIUOS +#define USE_RTOS 1 +#define FSL_RTOS_FREE_RTOS +#endif + +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + +#ifdef FSL_RTOS_XIUOS +#include "xs_sem.h" + +#else +#include "FreeRTOS.h" +#include "event_groups.h" +#include "list.h" +#endif + +typedef uint32_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +typedef TickType_t EventBits_t; + +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#define portBASE_TYPE long + +#define pdFALSE ( ( BaseType_t ) 0 ) +#define pdTRUE ( ( BaseType_t ) 1 ) + +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) + +#ifndef FSL_RTOS_XIUOS +typedef struct EventGroupDef_t +{ + EventBits_t uxEventBits; + List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxEventGroupNumber; + #endif + + #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ + #endif +} EventGroup_t; + +struct EventGroupDef_t; +typedef struct EventGroupDef_t * EventGroupHandle_t; +#endif + +#endif + +#include "enet_ethernetif.h" +#include "enet_ethernetif_priv.h" + +#include "fsl_enet.h" +#include "fsl_phy.h" + +#include "sys_arch.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/** + * Helper struct to hold private data used to operate your ethernet interface. + */ +struct ethernetif +{ + ENET_Type *base; +#if (defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)) || \ + (USE_RTOS && defined(FSL_RTOS_FREE_RTOS)) + enet_handle_t handle; +#endif +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + +#ifdef FSL_RTOS_XIUOS + int enetSemaphore; +#else + EventGroupHandle_t enetTransmitAccessEvent; +#endif + EventBits_t txFlag; +#endif + enet_rx_bd_struct_t *RxBuffDescrip; + enet_tx_bd_struct_t *TxBuffDescrip; + rx_buffer_t *RxDataBuff; + tx_buffer_t *TxDataBuff; +}; + + +/******************************************************************************* + * Code + ******************************************************************************/ +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + +int32 lwip_obtain_semaphore(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + return (KSemaphoreObtain(ethernetif->enetSemaphore, WAITING_FOREVER) == EOK); +} + +#if FSL_FEATURE_ENET_QUEUE > 1 +static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, uint32_t ringId, enet_event_t event, void *param) +#else +static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) +#endif /* FSL_FEATURE_ENET_QUEUE */ +{ + struct netif *netif = (struct netif *)param; + struct ethernetif *ethernetif = netif->state; + BaseType_t xResult; + + switch (event) + { + case kENET_RxEvent: + ethernetif_input(netif); + break; + case kENET_TxEvent: +#ifndef FSL_RTOS_XIUOS + { + portBASE_TYPE taskToWake = pdFALSE; + +#ifdef __CA7_REV + if (SystemGetIRQNestingLevel()) +#else + if (__get_IPSR()) +#endif + { + xResult = xEventGroupSetBitsFromISR(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, &taskToWake); + if ((pdPASS == xResult) && (pdTRUE == taskToWake)) + { + portYIELD_FROM_ISR(taskToWake); + } + } + else + { + xEventGroupSetBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag); + } + } +#endif + break; + default: + break; + } + + KSemaphoreAbandon(ethernetif->enetSemaphore); +} +#endif + +#if LWIP_IPV4 && LWIP_IGMP +err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, + enum netif_mac_filter_action action) +{ + struct ethernetif *ethernetif = netif->state; + uint8_t multicastMacAddr[6]; + err_t result; + + multicastMacAddr[0] = 0x01U; + multicastMacAddr[1] = 0x00U; + multicastMacAddr[2] = 0x5EU; + multicastMacAddr[3] = (group->addr >> 8) & 0x7FU; + multicastMacAddr[4] = (group->addr >> 16) & 0xFFU; + multicastMacAddr[5] = (group->addr >> 24) & 0xFFU; + + switch (action) + { + case IGMP_ADD_MAC_FILTER: + /* Adds the ENET device to a multicast group.*/ + ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr); + result = ERR_OK; + break; + case IGMP_DEL_MAC_FILTER: + /* + * Moves the ENET device from a multicast group. + * Since the ENET_LeaveMulticastGroup() could filter out also other + * group addresses having the same hash, the call is commented out. + */ + /* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */ + result = ERR_OK; + break; + default: + result = ERR_IF; + break; + } + + return result; +} +#endif + +#if LWIP_IPV6 && LWIP_IPV6_MLD +err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group, + enum netif_mac_filter_action action) +{ + struct ethernetif *ethernetif = netif->state; + uint8_t multicastMacAddr[6]; + err_t result; + + multicastMacAddr[0] = 0x33U; + multicastMacAddr[1] = 0x33U; + multicastMacAddr[2] = (group->addr[3]) & 0xFFU; + multicastMacAddr[3] = (group->addr[3] >> 8) & 0xFFU; + multicastMacAddr[4] = (group->addr[3] >> 16) & 0xFFU; + multicastMacAddr[5] = (group->addr[3] >> 24) & 0xFFU; + + switch (action) + { + case NETIF_ADD_MAC_FILTER: + /* Adds the ENET device to a multicast group.*/ + ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr); + result = ERR_OK; + break; + case NETIF_DEL_MAC_FILTER: + /* + * Moves the ENET device from a multicast group. + * Since the ENET_LeaveMulticastGroup() could filter out also other + * group addresses having the same hash, the call is commented out. + */ + /* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */ + result = ERR_OK; + break; + default: + result = ERR_IF; + break; + } + + return result; +} +#endif + +/** + * Initializes ENET driver. + */ +void ethernetif_enet_init(struct netif *netif, struct ethernetif *ethernetif, + const ethernetif_config_t *ethernetifConfig) +{ + enet_config_t config; + uint32_t sysClock; + enet_buffer_config_t buffCfg[ENET_RING_NUM]; + + /* prepare the buffer configuration. */ + buffCfg[0].rxBdNumber = ENET_RXBD_NUM; /* Receive buffer descriptor number. */ + buffCfg[0].txBdNumber = ENET_TXBD_NUM; /* Transmit buffer descriptor number. */ + buffCfg[0].rxBuffSizeAlign = sizeof(rx_buffer_t); /* Aligned receive data buffer size. */ + buffCfg[0].txBuffSizeAlign = sizeof(tx_buffer_t); /* Aligned transmit data buffer size. */ + buffCfg[0].rxBdStartAddrAlign = &(ethernetif->RxBuffDescrip[0]); /* Aligned receive buffer descriptor start address. */ + buffCfg[0].txBdStartAddrAlign = &(ethernetif->TxBuffDescrip[0]); /* Aligned transmit buffer descriptor start address. */ + buffCfg[0].rxBufferAlign = &(ethernetif->RxDataBuff[0][0]); /* Receive data buffer start address. */ + buffCfg[0].txBufferAlign = &(ethernetif->TxDataBuff[0][0]); /* Transmit data buffer start address. */ + + sysClock = CLOCK_GetFreq(ethernetifConfig->clockName); + + ENET_GetDefaultConfig(&config); + config.ringNum = ENET_RING_NUM; + + ethernetif_phy_init(ethernetif, ethernetifConfig, &config); + +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + uint32_t instance; + static ENET_Type *const enetBases[] = ENET_BASE_PTRS; + static const IRQn_Type enetTxIrqId[] = ENET_Transmit_IRQS; + /*! @brief Pointers to enet receive IRQ number for each instance. */ + static const IRQn_Type enetRxIrqId[] = ENET_Receive_IRQS; +#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + /*! @brief Pointers to enet timestamp IRQ number for each instance. */ + static const IRQn_Type enetTsIrqId[] = ENET_1588_Timer_IRQS; +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ + + /* Create the Event for transmit busy release trigger. */ +#ifdef FSL_RTOS_XIUOS + if(ethernetif->enetSemaphore < 0) + { + ethernetif->enetSemaphore = KSemaphoreCreate(0); + } +#else + ethernetif->enetTransmitAccessEvent = xEventGroupCreate(); +#endif + ethernetif->txFlag = 0x1; + + config.interrupt |= kENET_RxFrameInterrupt | kENET_TxFrameInterrupt | kENET_TxBufferInterrupt; + + for (instance = 0; instance < ARRAY_SIZE(enetBases); instance++) + { + if (enetBases[instance] == ethernetif->base) + { +#ifdef __CA7_REV + GIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY); + GIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY); +#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + GIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY); +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ +#else + NVIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY); + NVIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY); +#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + NVIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY); +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ +#endif /* __CA7_REV */ + break; + } + } + + LWIP_ASSERT("Input Ethernet base error!", (instance != ARRAY_SIZE(enetBases))); +#endif /* USE_RTOS */ + + /* Initialize the ENET module.*/ + ENET_Init(ethernetif->base, ðernetif->handle, &config, &buffCfg[0], netif->hwaddr, sysClock); + +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + ENET_SetCallback(ðernetif->handle, ethernet_callback, netif); +#endif + + ENET_ActiveRead(ethernetif->base); +// low_level_init(); +} + +ENET_Type **ethernetif_enet_ptr(struct ethernetif *ethernetif) +{ + return &(ethernetif->base); +} + +/** + * Returns next buffer for TX. + * Can wait if no buffer available. + */ +static unsigned char *enet_get_tx_buffer(struct ethernetif *ethernetif) +{ + static unsigned char ucBuffer[ENET_FRAME_MAX_FRAMELEN]; + return ucBuffer; +} + +/** + * Sends frame via ENET. + */ +static err_t enet_send_frame(struct ethernetif *ethernetif, unsigned char *data, const uint32_t length) +{ +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + { + status_t result; + + lw_print("lw: [%s] len %d\n", __func__, length); + + do + { + result = ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length); + + if (result == kStatus_ENET_TxFrameBusy) + { +#ifdef FSL_RTOS_XIUOS + KSemaphoreObtain(ethernetif->enetSemaphore, portMAX_DELAY); +#else + xEventGroupWaitBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, pdTRUE, (BaseType_t) false, + portMAX_DELAY); +#endif + } + + } while (result == kStatus_ENET_TxFrameBusy); + + return ERR_OK; + } +#else + { + uint32_t counter; + + for (counter = ENET_TIMEOUT; counter != 0U; counter--) + { + if (ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length) != kStatus_ENET_TxFrameBusy) + { + return ERR_OK; + } + } + + return ERR_TIMEOUT; + } +#endif +} + +struct pbuf *ethernetif_linkinput(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + struct pbuf *p = NULL; + struct pbuf *q; + uint32_t len; + status_t status; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + status = ENET_GetRxFrameSize(ðernetif->handle, &len); + + if (kStatus_ENET_RxFrameEmpty != status) + { + /* Call ENET_ReadFrame when there is a received frame. */ + if (len != 0) + { +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + if (p != NULL) + { +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + if (p->next == 0) /* One-chain buffer.*/ + { + ENET_ReadFrame(ethernetif->base, ðernetif->handle, p->payload, p->len); + } + else /* Multi-chain buffer.*/ + { + uint8_t data_tmp[ENET_FRAME_MAX_FRAMELEN]; + uint32_t data_tmp_len = 0; + + ENET_ReadFrame(ethernetif->base, ðernetif->handle, data_tmp, p->tot_len); + + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for (q = p; (q != NULL) && ((data_tmp_len + q->len) <= sizeof(data_tmp)); q = q->next) + { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. */ + memcpy(q->payload, &data_tmp[data_tmp_len], q->len); + data_tmp_len += q->len; + } + } + + MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); + if (((u8_t *)p->payload)[0] & 1) + { + /* broadcast or multicast packet*/ + MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); + } + else + { + /* unicast packet*/ + MIB2_STATS_NETIF_INC(netif, ifinucastpkts); + } +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } + else + { + /* drop packet*/ + ENET_ReadFrame(ethernetif->base, ðernetif->handle, NULL, 0U); + + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: Fail to allocate new memory space\n")); + + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifindiscards); + } + } + else + { + /* Update the received buffer when error happened. */ + if (status == kStatus_ENET_RxFrameError) + { +#if 0 && defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0) /* Error statisctics */ + enet_data_error_stats_t eErrStatic; + /* Get the error information of the received g_frame. */ + ENET_GetRxErrBeforeReadFrame(ðernetif->handle, &eErrStatic); +#endif + /* Update the receive buffer. */ + ENET_ReadFrame(ethernetif->base, ðernetif->handle, NULL, 0U); + + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: RxFrameError\n")); + + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifindiscards); + } + } + } + + return p; +} + +err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) +{ + err_t result; + struct ethernetif *ethernetif = netif->state; + struct pbuf *q; + unsigned char *pucBuffer; + unsigned char *pucChar; + + LWIP_ASSERT("Output packet buffer empty", p); + + pucBuffer = enet_get_tx_buffer(ethernetif); + if (pucBuffer == NULL) + { + return ERR_BUF; + } + +/* Initiate transfer. */ + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + if (p->len == p->tot_len) + { + /* No pbuf chain, don't have to copy -> faster. */ + pucBuffer = (unsigned char *)p->payload; + } + else + { + /* pbuf chain, copy into contiguous ucBuffer. */ + if (p->tot_len > ENET_FRAME_MAX_FRAMELEN) + { + return ERR_BUF; + } + else + { + pucChar = pucBuffer; + + for (q = p; q != NULL; q = q->next) + { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + /* send data from(q->payload, q->len); */ + memcpy(pucChar, q->payload, q->len); + pucChar += q->len; + } + } + } + + /* Send frame. */ + result = enet_send_frame(ethernetif, pucBuffer, p->tot_len); + + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len); + if (((u8_t *)p->payload)[0] & 1) + { + /* broadcast or multicast packet*/ + MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); + } + else + { + /* unicast packet */ + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + } +/* increase ifoutdiscards or ifouterrors on error */ + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return result; +} + +/** + * Should be called at the beginning of the program to set up the + * first network interface. It calls the function ethernetif_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif0_init(struct netif *netif) +{ + static struct ethernetif ethernetif_0; + AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + SDK_ALIGN(static rx_buffer_t rxDataBuff_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + SDK_ALIGN(static tx_buffer_t txDataBuff_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + + ethernetif_0.RxBuffDescrip = &(rxBuffDescrip_0[0]); + ethernetif_0.TxBuffDescrip = &(txBuffDescrip_0[0]); + ethernetif_0.RxDataBuff = &(rxDataBuff_0[0]); + ethernetif_0.TxDataBuff = &(txDataBuff_0[0]); + + return ethernetif_init(netif, ðernetif_0, 0U, (ethernetif_config_t *)netif->state); +} + +#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 1) +/** + * Should be called at the beginning of the program to set up the + * second network interface. It calls the function ethernetif_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif1_init(struct netif *netif) +{ + static struct ethernetif ethernetif_1; + AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + SDK_ALIGN(static rx_buffer_t rxDataBuff_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + SDK_ALIGN(static tx_buffer_t txDataBuff_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + + ethernetif_1.RxBuffDescrip = &(rxBuffDescrip_1[0]); + ethernetif_1.TxBuffDescrip = &(txBuffDescrip_1[0]); + ethernetif_1.RxDataBuff = &(rxDataBuff_1[0]); + ethernetif_1.TxDataBuff = &(txDataBuff_1[0]); + + return ethernetif_init(netif, ðernetif_1, 1U, (ethernetif_config_t *)netif->state); +} +#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_lpc.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_lpc.c index 3afc0da46..d851dc709 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_lpc.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_lpc.c @@ -801,30 +801,30 @@ err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) } } - if (copy) + if (copy) { /* Pbuf needs to be copied. */ p_copy = pbuf_alloc(PBUF_RAW, (uint16_t) p->tot_len, PBUF_POOL); - if (p_copy == NULL) + if (p_copy == NULL) { - return ERR_MEM; - } + return ERR_MEM; + } - dst = (uint8_t *) p_copy->payload; - for (q = p; q != NULL; q = q->next) + dst = (uint8_t *) p_copy->payload; + for (q = p; q != NULL; q = q->next) { LWIP_ASSERT("Copied bytes would exceed p->tot_len", (q->len + dst - (uint8_t *) p_copy->payload) <= p->tot_len); memcpy(dst, (uint8_t *)q->payload, q->len); - dst += q->len; - } + dst += q->len; + } LWIP_ASSERT("Copied bytes != p->tot_len", (dst - (uint8_t *) p_copy->payload) == p->tot_len); - p_copy->len = p_copy->tot_len = p->tot_len; + p_copy->len = p_copy->tot_len = p->tot_len; - p = p_copy; - } + p = p_copy; + } else { /* diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/fsl_enet.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/fsl_enet.c index 4da401faf..a5f14720d 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/fsl_enet.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/fsl_enet.c @@ -1490,6 +1490,9 @@ static void ENET_UpdateReadBuffers(ENET_Type *base, enet_handle_t *handle, uint3 assert(handle); assert(ringId < FSL_FEATURE_ENET_QUEUE); + +// lw_print("lw: [%s] base %p handle %p ring %d\n", __func__, base, handle, ringId); + /* Clears status. */ handle->rxBdCurrent[ringId]->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; /* Sets the receive buffer descriptor with the empty flag. */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/enet_ethernetif.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/enet_ethernetif.h index b7009bc3d..cc7016b3b 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/enet_ethernetif.h +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/enet_ethernetif.h @@ -195,6 +195,8 @@ void ethernetif_input( struct netif *netif); void ETH_BSP_Config(void); +int32 lwip_obtain_semaphore(struct netif *netif); + #if defined(__cplusplus) } #endif /* __cplusplus */ diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/board.c b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/board.c index 51ac93994..7bbe653a1 100644 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/board.c +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/board.c @@ -48,6 +48,8 @@ extern int Stm32HwI2cInit(void); extern int Stm32HwUsartInit(); extern int Stm32HwRtcInit(); extern int HwSdioInit(); +extern int Stm32HwAdcInit(void); +extern int Stm32HwDacInit(void); static void ClockConfiguration() { @@ -132,7 +134,13 @@ struct InitSequenceDesc _board_init[] = { "hw rtc", Stm32HwRtcInit}, #endif #ifdef BSP_USING_SDIO - {"hw sdcard init",HwSdioInit}, + {"hw sdcard init", HwSdioInit}, +#endif +#ifdef BSP_USING_ADC + {"hw adc init", Stm32HwAdcInit}, +#endif +#ifdef BSP_USING_DAC + {"hw dac init", Stm32HwDacInit}, #endif { " NONE ",NONE }, }; diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Kconfig b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Kconfig index cfea7e201..4bbfcb82c 100755 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Kconfig +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Kconfig @@ -1,3 +1,11 @@ +menuconfig BSP_USING_ADC +bool "Using ADC device" +default n +select RESOURCES_ADC +if BSP_USING_ADC +source "$BSP_DIR/third_party_driver/adc/Kconfig" +endif + menuconfig BSP_USING_CAN bool "Using CAN device" default n @@ -6,6 +14,14 @@ if BSP_USING_CAN source "$BSP_DIR/third_party_driver/can/Kconfig" endif +menuconfig BSP_USING_DAC +bool "Using DAC device" +default n +select RESOURCES_DAC +if BSP_USING_DAC +source "$BSP_DIR/third_party_driver/dac/Kconfig" +endif + menuconfig BSP_USING_DMA bool "Using DMA device" default y diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Makefile b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Makefile index b01d7930b..13a71f67a 100644 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Makefile +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/Makefile @@ -1,10 +1,18 @@ SRC_DIR := common +ifeq ($(CONFIG_BSP_USING_ADC),y) + SRC_DIR += adc +endif + ifeq ($(CONFIG_BSP_USING_CAN),y) SRC_DIR += can endif +ifeq ($(CONFIG_BSP_USING_DAC),y) + SRC_DIR += dac +endif + ifeq ($(CONFIG_BSP_USING_GPIO),y) SRC_DIR += gpio endif diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/Kconfig b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/Kconfig new file mode 100644 index 000000000..ac7cd3078 --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/Kconfig @@ -0,0 +1,76 @@ + + +menuconfig BSP_USING_ADC1 + bool "Enable ADC1" + default n + if BSP_USING_ADC1 + config ADC1_BUS_NAME + string "adc 1 bus name" + default "adc1" + + config ADC1_DRIVER_NAME + string "adc 1 driver name" + default "adc1_drv" + + config ADC1_DEVICE_NAME + string "adc 1 bus device name" + default "adc1_dev" + + config ADC1_GPIO_NUM + int "adc 1 gpio pin num" + default "0" + + config ADC1_GPIO_DEF + string "adc 1 gpio define type" + default "A" + endif + +menuconfig BSP_USING_ADC2 + bool "Enable ADC2" + default n + if BSP_USING_ADC2 + config ADC2_BUS_NAME + string "adc 2 bus name" + default "adc2" + + config ADC2_DRIVER_NAME + string "adc 2 driver name" + default "adc2_drv" + + config ADC2_DEVICE_NAME + string "adc 2 bus device name" + default "adc2_dev" + + config ADC2_GPIO_NUM + int "adc 2 gpio pin num" + default "6" + + config ADC2_GPIO_DEF + string "adc 2 gpio define type" + default "A" + endif + +menuconfig BSP_USING_ADC3 + bool "Enable ADC3" + default n + if BSP_USING_ADC3 + config ADC3_BUS_NAME + string "adc 3 bus name" + default "adc3" + + config ADC3_DRIVER_NAME + string "adc 3 driver name" + default "adc3_drv" + + config ADC3_DEVICE_NAME + string "adc 3 bus device name" + default "adc3_dev" + + config ADC3_GPIO_NUM + int "adc 3 gpio pin num" + default "0" + + config ADC3_GPIO_DEF + string "adc 3 gpio define type" + default "A" + endif diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/Makefile b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/Makefile new file mode 100644 index 000000000..c2dc54fa9 --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := connect_adc.c hardware_adc.c + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/connect_adc.c b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/connect_adc.c new file mode 100644 index 000000000..26f7e6494 --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/connect_adc.c @@ -0,0 +1,433 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_adc.c +* @brief support to register ADC pointer and function +* @version 1.1 +* @author AIIT XUOS Lab +* @date 2021-12-28 +*/ + +#include + +#define _ADC_CONS(string1, string2) string1##string2 +#define ADC_CONS(string1, string2) _ADC_CONS(string1, string2) + +#ifdef BSP_USING_ADC1 +#define ADC1_GPIO ADC_CONS(GPIO_Pin_, ADC1_GPIO_NUM) +#endif + +#ifdef BSP_USING_ADC2 +#define ADC2_GPIO ADC_CONS(GPIO_Pin_, ADC2_GPIO_NUM) +#endif + +#ifdef BSP_USING_ADC3 +#define ADC3_GPIO ADC_CONS(GPIO_Pin_, ADC3_GPIO_NUM) +#endif + +static int Stm32AdcUdelay(uint32 us) +{ + uint32 ticks; + uint32 told, tnow, tcnt = 0; + uint32 reload = SysTick->LOAD; + + ticks = us * reload / (1000000 / TICK_PER_SECOND); + told = SysTick->VAL; + while (1) { + tnow = SysTick->VAL; + if (tnow != told) { + if (tnow < told) { + tcnt += told - tnow; + } else { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) { + return 0; + break; + } + } + } +} + +static GPIO_TypeDef* AdcGetGpioType(char *adc_gpio_def) +{ + if (0 == strncmp(adc_gpio_def, "A", 2)) { + return GPIOA; + } else if (0 == strncmp(adc_gpio_def, "B", 2)) { + return GPIOB; + } else if (0 == strncmp(adc_gpio_def, "C", 2)) { + return GPIOC; + } else if (0 == strncmp(adc_gpio_def, "F", 2)) { + return GPIOF; + } else { + printf("AdcGetGpioType do not support %s GPIO\n", adc_gpio_def); + return GPIOA; + } +} + +static uint32 AdcGetGpioRcc(char *adc_gpio_def) +{ + if (0 == strncmp(adc_gpio_def, "A", 2)) { + return RCC_AHB1Periph_GPIOA; + } else if (0 == strncmp(adc_gpio_def, "B", 2)) { + return RCC_AHB1Periph_GPIOB; + } else if (0 == strncmp(adc_gpio_def, "C", 2)) { + return RCC_AHB1Periph_GPIOC; + } else if (0 == strncmp(adc_gpio_def, "F", 2)) { + return RCC_AHB1Periph_GPIOF; + } else { + printf("AdcGetGpioRcc do not support %s GPIO\n", adc_gpio_def); + return RCC_AHB1Periph_GPIOA; + } +} + +static void AdcInit(struct AdcHardwareDevice *adc_dev) +{ + GPIO_InitTypeDef GPIO_InitStructure; + ADC_CommonInitTypeDef ADC_CommonInitStructure; + ADC_InitTypeDef ADC_InitStructure; + uint32_t RCC_AHB1Periph; + GPIO_TypeDef* GPIOx; + +#ifdef BSP_USING_ADC1 + if (0 == strncmp(adc_dev->haldev.dev_name, ADC1_DEVICE_NAME, NAME_NUM_MAX)) { + + GPIOx = AdcGetGpioType(ADC1_GPIO_DEF); + RCC_AHB1Periph = AdcGetGpioRcc(ADC1_GPIO_DEF); + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph, ENABLE);//enable GPIOA clock + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//enable ADC1 clock + + GPIO_InitStructure.GPIO_Pin = ADC1_GPIO; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//analog input + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOx, &GPIO_InitStructure); + + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE); + + ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; + ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; + ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; + ADC_CommonInit(&ADC_CommonInitStructure); + + ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12 bit mode + ADC_InitStructure.ADC_ScanConvMode = DISABLE; + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; + ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStructure.ADC_NbrOfConversion = 1; + ADC_Init(ADC1, &ADC_InitStructure); + + ADC_Cmd(ADC1, ENABLE); + } +#endif + +#ifdef BSP_USING_ADC2 + if (0 == strncmp(adc_dev->haldev.dev_name, ADC2_DEVICE_NAME, NAME_NUM_MAX)) { + + GPIOx = AdcGetGpioType(ADC2_GPIO_DEF); + RCC_AHB1Periph = AdcGetGpioRcc(ADC2_GPIO_DEF); + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph, ENABLE);//enable GPIOA clock + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);//enable ADC2 clock + + GPIO_InitStructure.GPIO_Pin = ADC2_GPIO; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//analog input + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOx, &GPIO_InitStructure); + + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2, DISABLE); + + ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; + ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; + ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; + ADC_CommonInit(&ADC_CommonInitStructure); + + ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12 bit mode + ADC_InitStructure.ADC_ScanConvMode = DISABLE; + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; + ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStructure.ADC_NbrOfConversion = 1; + ADC_Init(ADC2, &ADC_InitStructure); + + ADC_Cmd(ADC2, ENABLE); + } +#endif + +#ifdef BSP_USING_ADC3 + if (0 == strncmp(adc_dev->haldev.dev_name, ADC3_DEVICE_NAME, NAME_NUM_MAX)) { + + GPIOx = AdcGetGpioType(ADC3_GPIO_DEF); + RCC_AHB1Periph = AdcGetGpioRcc(ADC3_GPIO_DEF); + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph, ENABLE);//enable GPIOA clock + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);//enable ADC3 clock + + GPIO_InitStructure.GPIO_Pin = ADC3_GPIO; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//analog input + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOx, &GPIO_InitStructure); + + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3, DISABLE); + + ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; + ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; + ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; + ADC_CommonInit(&ADC_CommonInitStructure); + + ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12 bit mode + ADC_InitStructure.ADC_ScanConvMode = DISABLE; + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; + ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStructure.ADC_NbrOfConversion = 1; + ADC_Init(ADC3, &ADC_InitStructure); + + ADC_Cmd(ADC3, ENABLE); + } +#endif +} + +static uint16 GetAdcValue(ADC_TypeDef *ADCx, uint8 channel) +{ + //set ADCx channel, rank, sampletime + ADC_RegularChannelConfig(ADCx, channel, 1, ADC_SampleTime_480Cycles); + + ADC_SoftwareStartConv(ADCx); + + while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC)); + + return ADC_GetConversionValue(ADCx); +} + +static uint16 GetAdcAverageValue(ADC_TypeDef *ADCx, uint8 channel, uint8 times) +{ + uint32 temp_val = 0; + int i; + + for(i = 0;i < times;i ++) { + temp_val += GetAdcValue(ADCx, channel) & 0x0FFF; + KPrintf("GetAdcAverageValue val %u\n", GetAdcValue(ADCx, channel)); + Stm32AdcUdelay(5000); + } + return temp_val / times; +} + +static uint32 Stm32AdcOpen(void *dev) +{ + struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev; + + AdcInit(adc_dev); + + return EOK; +} + +static uint32 Stm32AdcClose(void *dev) +{ + struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev; + + ADC_DeInit(); + + return EOK; +} + +static uint32 Stm32AdcRead(void *dev, struct BusBlockReadParam *read_param) +{ + struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev; + struct Stm32HwAdc *adc_cfg = (struct Stm32HwAdc *)adc_dev->haldev.private_data; + + uint16 adc_average_value = 0; + uint8 times = 20; + + adc_average_value = GetAdcAverageValue(adc_cfg->ADCx, adc_cfg->adc_channel, times); + + *(uint16 *)read_param->buffer = adc_average_value; + read_param->read_length = 2; + + return read_param->read_length; +} + +static uint32 Stm32AdcDrvConfigure(void *drv, struct BusConfigureInfo *configure_info) +{ + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(configure_info); + + x_err_t ret = EOK; + uint8 adc_channel; + + struct AdcDriver *adc_drv = (struct AdcDriver *)drv; + struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)adc_drv->driver.owner_bus->owner_haldev; + struct Stm32HwAdc *adc_cfg = (struct Stm32HwAdc *)adc_dev->haldev.private_data; + + switch (configure_info->configure_cmd) + { + case OPE_CFG: + adc_cfg->adc_channel = *(uint8 *)configure_info->private_data; + if (adc_cfg->adc_channel > 18) { + KPrintf("Stm32AdcDrvConfigure set adc channel(0-18) %u error!", adc_cfg->adc_channel); + adc_cfg->adc_channel = 0; + ret = ERROR; + } + break; + default: + break; + } + + return ret; +} + +static const struct AdcDevDone dev_done = +{ + Stm32AdcOpen, + Stm32AdcClose, + NONE, + Stm32AdcRead, +}; + +int Stm32HwAdcInit(void) +{ + x_err_t ret = EOK; + +#ifdef BSP_USING_ADC1 + static struct AdcBus adc1_bus; + static struct AdcDriver adc1_drv; + static struct AdcHardwareDevice adc1_dev; + static struct Stm32HwAdc adc1_cfg; + + adc1_drv.configure = Stm32AdcDrvConfigure; + + ret = AdcBusInit(&adc1_bus, ADC1_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC1 bus init error %d\n", ret); + return ERROR; + } + + ret = AdcDriverInit(&adc1_drv, ADC1_DRIVER_NAME); + if (ret != EOK) { + KPrintf("ADC1 driver init error %d\n", ret); + return ERROR; + } + ret = AdcDriverAttachToBus(ADC1_DRIVER_NAME, ADC1_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC1 driver attach error %d\n", ret); + return ERROR; + } + + adc1_dev.adc_dev_done = &dev_done; + adc1_cfg.ADCx = ADC1; + adc1_cfg.adc_channel = 0; + + ret = AdcDeviceRegister(&adc1_dev, (void *)&adc1_cfg, ADC1_DEVICE_NAME); + if (ret != EOK) { + KPrintf("ADC1 device register error %d\n", ret); + return ERROR; + } + ret = AdcDeviceAttachToBus(ADC1_DEVICE_NAME, ADC1_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC1 device register error %d\n", ret); + return ERROR; + } +#endif + +#ifdef BSP_USING_ADC2 + static struct AdcBus adc2_bus; + static struct AdcDriver adc2_drv; + static struct AdcHardwareDevice adc2_dev; + static struct Stm32HwAdc adc2_cfg; + + adc2_drv.configure = Stm32AdcDrvConfigure; + + ret = AdcBusInit(&adc2_bus, ADC2_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC2 bus init error %d\n", ret); + return ERROR; + } + + ret = AdcDriverInit(&adc2_drv, ADC2_DRIVER_NAME); + if (ret != EOK) { + KPrintf("ADC2 driver init error %d\n", ret); + return ERROR; + } + ret = AdcDriverAttachToBus(ADC2_DRIVER_NAME, ADC2_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC2 driver attach error %d\n", ret); + return ERROR; + } + + adc2_dev.adc_dev_done = &dev_done; + adc2_cfg.ADCx = ADC2; + adc2_cfg.adc_channel = 0; + + ret = AdcDeviceRegister(&adc2_dev, (void *)&adc2_cfg, ADC2_DEVICE_NAME); + if (ret != EOK) { + KPrintf("ADC2 device register error %d\n", ret); + return ERROR; + } + ret = AdcDeviceAttachToBus(ADC2_DEVICE_NAME, ADC2_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC2 device register error %d\n", ret); + return ERROR; + } +#endif + +#ifdef BSP_USING_ADC3 + static struct AdcBus adc3_bus; + static struct AdcDriver adc3_drv; + static struct AdcHardwareDevice adc3_dev; + static struct Stm32HwAdc adc3_cfg; + + adc3_drv.configure = Stm32AdcDrvConfigure; + + ret = AdcBusInit(&adc3_bus, ADC3_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC3 bus init error %d\n", ret); + return ERROR; + } + + ret = AdcDriverInit(&adc3_drv, ADC3_DRIVER_NAME); + if (ret != EOK) { + KPrintf("ADC3 driver init error %d\n", ret); + return ERROR; + } + ret = AdcDriverAttachToBus(ADC3_DRIVER_NAME, ADC3_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC3 driver attach error %d\n", ret); + return ERROR; + } + + adc3_dev.adc_dev_done = &dev_done; + adc3_cfg.ADCx = ADC3; + adc3_cfg.adc_channel = 0; + + ret = AdcDeviceRegister(&adc3_dev, (void *)&adc3_cfg, ADC3_DEVICE_NAME); + if (ret != EOK) { + KPrintf("ADC3 device register error %d\n", ret); + return ERROR; + } + ret = AdcDeviceAttachToBus(ADC3_DEVICE_NAME, ADC3_BUS_NAME); + if (ret != EOK) { + KPrintf("ADC3 device register error %d\n", ret); + return ERROR; + } +#endif + + return ret; +} diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/hardware_adc.c b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/hardware_adc.c new file mode 100644 index 000000000..a7bc99366 --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/adc/hardware_adc.c @@ -0,0 +1,1765 @@ +/** + ****************************************************************************** + * @file stm32f4xx_adc.c + * @author MCD Application Team + * @version V1.4.0 + * @date 04-August-2014 + * @brief This file provides firmware functions to manage the following + * functionalities of the Analog to Digital Convertor (ADC) peripheral: + * + Initialization and Configuration (in addition to ADC multi mode + * selection) + * + Analog Watchdog configuration + * + Temperature Sensor & Vrefint (Voltage Reference internal) & VBAT + * management + * + Regular Channels Configuration + * + Regular Channels DMA Configuration + * + Injected channels Configuration + * + Interrupts and flags management + * + @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + (#) Enable the ADC interface clock using + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADCx, ENABLE); + + (#) ADC pins configuration + (++) Enable the clock for the ADC GPIOs using the following function: + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE); + (++) Configure these ADC pins in analog mode using GPIO_Init(); + + (#) Configure the ADC Prescaler, conversion resolution and data + alignment using the ADC_Init() function. + (#) Activate the ADC peripheral using ADC_Cmd() function. + + *** Regular channels group configuration *** + ============================================ + [..] + (+) To configure the ADC regular channels group features, use + ADC_Init() and ADC_RegularChannelConfig() functions. + (+) To activate the continuous mode, use the ADC_continuousModeCmd() + function. + (+) To configurate and activate the Discontinuous mode, use the + ADC_DiscModeChannelCountConfig() and ADC_DiscModeCmd() functions. + (+) To read the ADC converted values, use the ADC_GetConversionValue() + function. + + *** Multi mode ADCs Regular channels configuration *** + ====================================================== + [..] + (+) Refer to "Regular channels group configuration" description to + configure the ADC1, ADC2 and ADC3 regular channels. + (+) Select the Multi mode ADC regular channels features (dual or + triple mode) using ADC_CommonInit() function and configure + the DMA mode using ADC_MultiModeDMARequestAfterLastTransferCmd() + functions. + (+) Read the ADCs converted values using the + ADC_GetMultiModeConversionValue() function. + + *** DMA for Regular channels group features configuration *** + ============================================================= + [..] + (+) To enable the DMA mode for regular channels group, use the + ADC_DMACmd() function. + (+) To enable the generation of DMA requests continuously at the end + of the last DMA transfer, use the ADC_DMARequestAfterLastTransferCmd() + function. + + *** Injected channels group configuration *** + ============================================= + [..] + (+) To configure the ADC Injected channels group features, use + ADC_InjectedChannelConfig() and ADC_InjectedSequencerLengthConfig() + functions. + (+) To activate the continuous mode, use the ADC_continuousModeCmd() + function. + (+) To activate the Injected Discontinuous mode, use the + ADC_InjectedDiscModeCmd() function. + (+) To activate the AutoInjected mode, use the ADC_AutoInjectedConvCmd() + function. + (+) To read the ADC converted values, use the ADC_GetInjectedConversionValue() + function. + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/** +* @file: hardware_adc.c +* @brief: support hardware adc function +* @version: 1.1 +* @author: AIIT XUOS Lab +* @date: 2021/12/28 +*/ + +/************************************************* +File name: hardware_adc.c +Description: support hardware adc function +Others: +History: +1. Date: 2021-12-28 +Author: AIIT XUOS Lab +Modification: +1. rename stm32f4xx_adc.c for XiUOS +*************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup ADC + * @brief ADC driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* ADC DISCNUM mask */ +#define CR1_DISCNUM_RESET ((uint32_t)0xFFFF1FFF) + +/* ADC AWDCH mask */ +#define CR1_AWDCH_RESET ((uint32_t)0xFFFFFFE0) + +/* ADC Analog watchdog enable mode mask */ +#define CR1_AWDMode_RESET ((uint32_t)0xFF3FFDFF) + +/* CR1 register Mask */ +#define CR1_CLEAR_MASK ((uint32_t)0xFCFFFEFF) + +/* ADC EXTEN mask */ +#define CR2_EXTEN_RESET ((uint32_t)0xCFFFFFFF) + +/* ADC JEXTEN mask */ +#define CR2_JEXTEN_RESET ((uint32_t)0xFFCFFFFF) + +/* ADC JEXTSEL mask */ +#define CR2_JEXTSEL_RESET ((uint32_t)0xFFF0FFFF) + +/* CR2 register Mask */ +#define CR2_CLEAR_MASK ((uint32_t)0xC0FFF7FD) + +/* ADC SQx mask */ +#define SQR3_SQ_SET ((uint32_t)0x0000001F) +#define SQR2_SQ_SET ((uint32_t)0x0000001F) +#define SQR1_SQ_SET ((uint32_t)0x0000001F) + +/* ADC L Mask */ +#define SQR1_L_RESET ((uint32_t)0xFF0FFFFF) + +/* ADC JSQx mask */ +#define JSQR_JSQ_SET ((uint32_t)0x0000001F) + +/* ADC JL mask */ +#define JSQR_JL_SET ((uint32_t)0x00300000) +#define JSQR_JL_RESET ((uint32_t)0xFFCFFFFF) + +/* ADC SMPx mask */ +#define SMPR1_SMP_SET ((uint32_t)0x00000007) +#define SMPR2_SMP_SET ((uint32_t)0x00000007) + +/* ADC JDRx registers offset */ +#define JDR_OFFSET ((uint8_t)0x28) + +/* ADC CDR register base address */ +#define CDR_ADDRESS ((uint32_t)0x40012308) + +/* ADC CCR register Mask */ +#define CR_CLEAR_MASK ((uint32_t)0xFFFC30E0) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup ADC_Private_Functions + * @{ + */ + +/** @defgroup ADC_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize and configure the ADC Prescaler + (+) ADC Conversion Resolution (12bit..6bit) + (+) Scan Conversion Mode (multichannel or one channel) for regular group + (+) ADC Continuous Conversion Mode (Continuous or Single conversion) for + regular group + (+) External trigger Edge and source of regular group, + (+) Converted data alignment (left or right) + (+) The number of ADC conversions that will be done using the sequencer for + regular channel group + (+) Multi ADC mode selection + (+) Direct memory access mode selection for multi ADC mode + (+) Delay between 2 sampling phases (used in dual or triple interleaved modes) + (+) Enable or disable the ADC peripheral +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes all ADCs peripherals registers to their default reset + * values. + * @param None + * @retval None + */ +void ADC_DeInit(void) +{ + /* Enable all ADCs reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC, ENABLE); + + /* Release all ADCs from reset state */ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC, DISABLE); +} + +/** + * @brief Initializes the ADCx peripheral according to the specified parameters + * in the ADC_InitStruct. + * @note This function is used to configure the global features of the ADC ( + * Resolution and Data Alignment), however, the rest of the configuration + * parameters are specific to the regular channels group (scan mode + * activation, continuous mode activation, External trigger source and + * edge, number of conversion in the regular channels group sequencer). + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_InitStruct: pointer to an ADC_InitTypeDef structure that contains + * the configuration information for the specified ADC peripheral. + * @retval None + */ +void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct) +{ + uint32_t tmpreg1 = 0; + uint8_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_RESOLUTION(ADC_InitStruct->ADC_Resolution)); + assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ScanConvMode)); + assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ContinuousConvMode)); + assert_param(IS_ADC_EXT_TRIG_EDGE(ADC_InitStruct->ADC_ExternalTrigConvEdge)); + assert_param(IS_ADC_EXT_TRIG(ADC_InitStruct->ADC_ExternalTrigConv)); + assert_param(IS_ADC_DATA_ALIGN(ADC_InitStruct->ADC_DataAlign)); + assert_param(IS_ADC_REGULAR_LENGTH(ADC_InitStruct->ADC_NbrOfConversion)); + + /*---------------------------- ADCx CR1 Configuration -----------------*/ + /* Get the ADCx CR1 value */ + tmpreg1 = ADCx->CR1; + + /* Clear RES and SCAN bits */ + tmpreg1 &= CR1_CLEAR_MASK; + + /* Configure ADCx: scan conversion mode and resolution */ + /* Set SCAN bit according to ADC_ScanConvMode value */ + /* Set RES bit according to ADC_Resolution value */ + tmpreg1 |= (uint32_t)(((uint32_t)ADC_InitStruct->ADC_ScanConvMode << 8) | \ + ADC_InitStruct->ADC_Resolution); + /* Write to ADCx CR1 */ + ADCx->CR1 = tmpreg1; + /*---------------------------- ADCx CR2 Configuration -----------------*/ + /* Get the ADCx CR2 value */ + tmpreg1 = ADCx->CR2; + + /* Clear CONT, ALIGN, EXTEN and EXTSEL bits */ + tmpreg1 &= CR2_CLEAR_MASK; + + /* Configure ADCx: external trigger event and edge, data alignment and + continuous conversion mode */ + /* Set ALIGN bit according to ADC_DataAlign value */ + /* Set EXTEN bits according to ADC_ExternalTrigConvEdge value */ + /* Set EXTSEL bits according to ADC_ExternalTrigConv value */ + /* Set CONT bit according to ADC_ContinuousConvMode value */ + tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_DataAlign | \ + ADC_InitStruct->ADC_ExternalTrigConv | + ADC_InitStruct->ADC_ExternalTrigConvEdge | \ + ((uint32_t)ADC_InitStruct->ADC_ContinuousConvMode << 1)); + + /* Write to ADCx CR2 */ + ADCx->CR2 = tmpreg1; + /*---------------------------- ADCx SQR1 Configuration -----------------*/ + /* Get the ADCx SQR1 value */ + tmpreg1 = ADCx->SQR1; + + /* Clear L bits */ + tmpreg1 &= SQR1_L_RESET; + + /* Configure ADCx: regular channel sequence length */ + /* Set L bits according to ADC_NbrOfConversion value */ + tmpreg2 |= (uint8_t)(ADC_InitStruct->ADC_NbrOfConversion - (uint8_t)1); + tmpreg1 |= ((uint32_t)tmpreg2 << 20); + + /* Write to ADCx SQR1 */ + ADCx->SQR1 = tmpreg1; +} + +/** + * @brief Fills each ADC_InitStruct member with its default value. + * @note This function is used to initialize the global features of the ADC ( + * Resolution and Data Alignment), however, the rest of the configuration + * parameters are specific to the regular channels group (scan mode + * activation, continuous mode activation, External trigger source and + * edge, number of conversion in the regular channels group sequencer). + * @param ADC_InitStruct: pointer to an ADC_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct) +{ + /* Initialize the ADC_Mode member */ + ADC_InitStruct->ADC_Resolution = ADC_Resolution_12b; + + /* initialize the ADC_ScanConvMode member */ + ADC_InitStruct->ADC_ScanConvMode = DISABLE; + + /* Initialize the ADC_ContinuousConvMode member */ + ADC_InitStruct->ADC_ContinuousConvMode = DISABLE; + + /* Initialize the ADC_ExternalTrigConvEdge member */ + ADC_InitStruct->ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + + /* Initialize the ADC_ExternalTrigConv member */ + ADC_InitStruct->ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; + + /* Initialize the ADC_DataAlign member */ + ADC_InitStruct->ADC_DataAlign = ADC_DataAlign_Right; + + /* Initialize the ADC_NbrOfConversion member */ + ADC_InitStruct->ADC_NbrOfConversion = 1; +} + +/** + * @brief Initializes the ADCs peripherals according to the specified parameters + * in the ADC_CommonInitStruct. + * @param ADC_CommonInitStruct: pointer to an ADC_CommonInitTypeDef structure + * that contains the configuration information for All ADCs peripherals. + * @retval None + */ +void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct) +{ + uint32_t tmpreg1 = 0; + /* Check the parameters */ + assert_param(IS_ADC_MODE(ADC_CommonInitStruct->ADC_Mode)); + assert_param(IS_ADC_PRESCALER(ADC_CommonInitStruct->ADC_Prescaler)); + assert_param(IS_ADC_DMA_ACCESS_MODE(ADC_CommonInitStruct->ADC_DMAAccessMode)); + assert_param(IS_ADC_SAMPLING_DELAY(ADC_CommonInitStruct->ADC_TwoSamplingDelay)); + /*---------------------------- ADC CCR Configuration -----------------*/ + /* Get the ADC CCR value */ + tmpreg1 = ADC->CCR; + + /* Clear MULTI, DELAY, DMA and ADCPRE bits */ + tmpreg1 &= CR_CLEAR_MASK; + + /* Configure ADCx: Multi mode, Delay between two sampling time, ADC prescaler, + and DMA access mode for multimode */ + /* Set MULTI bits according to ADC_Mode value */ + /* Set ADCPRE bits according to ADC_Prescaler value */ + /* Set DMA bits according to ADC_DMAAccessMode value */ + /* Set DELAY bits according to ADC_TwoSamplingDelay value */ + tmpreg1 |= (uint32_t)(ADC_CommonInitStruct->ADC_Mode | + ADC_CommonInitStruct->ADC_Prescaler | + ADC_CommonInitStruct->ADC_DMAAccessMode | + ADC_CommonInitStruct->ADC_TwoSamplingDelay); + + /* Write to ADC CCR */ + ADC->CCR = tmpreg1; +} + +/** + * @brief Fills each ADC_CommonInitStruct member with its default value. + * @param ADC_CommonInitStruct: pointer to an ADC_CommonInitTypeDef structure + * which will be initialized. + * @retval None + */ +void ADC_CommonStructInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct) +{ + /* Initialize the ADC_Mode member */ + ADC_CommonInitStruct->ADC_Mode = ADC_Mode_Independent; + + /* initialize the ADC_Prescaler member */ + ADC_CommonInitStruct->ADC_Prescaler = ADC_Prescaler_Div2; + + /* Initialize the ADC_DMAAccessMode member */ + ADC_CommonInitStruct->ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + + /* Initialize the ADC_TwoSamplingDelay member */ + ADC_CommonInitStruct->ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; +} + +/** + * @brief Enables or disables the specified ADC peripheral. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the ADCx peripheral. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Set the ADON bit to wake up the ADC from power down mode */ + ADCx->CR2 |= (uint32_t)ADC_CR2_ADON; + } + else + { + /* Disable the selected ADC peripheral */ + ADCx->CR2 &= (uint32_t)(~ADC_CR2_ADON); + } +} +/** + * @} + */ + +/** @defgroup ADC_Group2 Analog Watchdog configuration functions + * @brief Analog Watchdog configuration functions + * +@verbatim + =============================================================================== + ##### Analog Watchdog configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to configure the Analog Watchdog + (AWD) feature in the ADC. + + [..] A typical configuration Analog Watchdog is done following these steps : + (#) the ADC guarded channel(s) is (are) selected using the + ADC_AnalogWatchdogSingleChannelConfig() function. + (#) The Analog watchdog lower and higher threshold are configured using the + ADC_AnalogWatchdogThresholdsConfig() function. + (#) The Analog watchdog is enabled and configured to enable the check, on one + or more channels, using the ADC_AnalogWatchdogCmd() function. +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the analog watchdog on single/all regular or + * injected channels + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_AnalogWatchdog: the ADC analog watchdog configuration. + * This parameter can be one of the following values: + * @arg ADC_AnalogWatchdog_SingleRegEnable: Analog watchdog on a single regular channel + * @arg ADC_AnalogWatchdog_SingleInjecEnable: Analog watchdog on a single injected channel + * @arg ADC_AnalogWatchdog_SingleRegOrInjecEnable: Analog watchdog on a single regular or injected channel + * @arg ADC_AnalogWatchdog_AllRegEnable: Analog watchdog on all regular channel + * @arg ADC_AnalogWatchdog_AllInjecEnable: Analog watchdog on all injected channel + * @arg ADC_AnalogWatchdog_AllRegAllInjecEnable: Analog watchdog on all regular and injected channels + * @arg ADC_AnalogWatchdog_None: No channel guarded by the analog watchdog + * @retval None + */ +void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_ANALOG_WATCHDOG(ADC_AnalogWatchdog)); + + /* Get the old register value */ + tmpreg = ADCx->CR1; + + /* Clear AWDEN, JAWDEN and AWDSGL bits */ + tmpreg &= CR1_AWDMode_RESET; + + /* Set the analog watchdog enable mode */ + tmpreg |= ADC_AnalogWatchdog; + + /* Store the new register value */ + ADCx->CR1 = tmpreg; +} + +/** + * @brief Configures the high and low thresholds of the analog watchdog. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param HighThreshold: the ADC analog watchdog High threshold value. + * This parameter must be a 12-bit value. + * @param LowThreshold: the ADC analog watchdog Low threshold value. + * This parameter must be a 12-bit value. + * @retval None + */ +void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, + uint16_t LowThreshold) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_THRESHOLD(HighThreshold)); + assert_param(IS_ADC_THRESHOLD(LowThreshold)); + + /* Set the ADCx high threshold */ + ADCx->HTR = HighThreshold; + + /* Set the ADCx low threshold */ + ADCx->LTR = LowThreshold; +} + +/** + * @brief Configures the analog watchdog guarded single channel + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_Channel: the ADC channel to configure for the analog watchdog. + * This parameter can be one of the following values: + * @arg ADC_Channel_0: ADC Channel0 selected + * @arg ADC_Channel_1: ADC Channel1 selected + * @arg ADC_Channel_2: ADC Channel2 selected + * @arg ADC_Channel_3: ADC Channel3 selected + * @arg ADC_Channel_4: ADC Channel4 selected + * @arg ADC_Channel_5: ADC Channel5 selected + * @arg ADC_Channel_6: ADC Channel6 selected + * @arg ADC_Channel_7: ADC Channel7 selected + * @arg ADC_Channel_8: ADC Channel8 selected + * @arg ADC_Channel_9: ADC Channel9 selected + * @arg ADC_Channel_10: ADC Channel10 selected + * @arg ADC_Channel_11: ADC Channel11 selected + * @arg ADC_Channel_12: ADC Channel12 selected + * @arg ADC_Channel_13: ADC Channel13 selected + * @arg ADC_Channel_14: ADC Channel14 selected + * @arg ADC_Channel_15: ADC Channel15 selected + * @arg ADC_Channel_16: ADC Channel16 selected + * @arg ADC_Channel_17: ADC Channel17 selected + * @arg ADC_Channel_18: ADC Channel18 selected + * @retval None + */ +void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CHANNEL(ADC_Channel)); + + /* Get the old register value */ + tmpreg = ADCx->CR1; + + /* Clear the Analog watchdog channel select bits */ + tmpreg &= CR1_AWDCH_RESET; + + /* Set the Analog watchdog channel */ + tmpreg |= ADC_Channel; + + /* Store the new register value */ + ADCx->CR1 = tmpreg; +} +/** + * @} + */ + +/** @defgroup ADC_Group3 Temperature Sensor, Vrefint (Voltage Reference internal) + * and VBAT (Voltage BATtery) management functions + * @brief Temperature Sensor, Vrefint and VBAT management functions + * +@verbatim + =============================================================================== + ##### Temperature Sensor, Vrefint and VBAT management functions ##### + =============================================================================== + [..] This section provides functions allowing to enable/ disable the internal + connections between the ADC and the Temperature Sensor, the Vrefint and + the Vbat sources. + + [..] A typical configuration to get the Temperature sensor and Vrefint channels + voltages is done following these steps : + (#) Enable the internal connection of Temperature sensor and Vrefint sources + with the ADC channels using ADC_TempSensorVrefintCmd() function. + (#) Select the ADC_Channel_TempSensor and/or ADC_Channel_Vrefint using + ADC_RegularChannelConfig() or ADC_InjectedChannelConfig() functions + (#) Get the voltage values, using ADC_GetConversionValue() or + ADC_GetInjectedConversionValue(). + + [..] A typical configuration to get the VBAT channel voltage is done following + these steps : + (#) Enable the internal connection of VBAT source with the ADC channel using + ADC_VBATCmd() function. + (#) Select the ADC_Channel_Vbat using ADC_RegularChannelConfig() or + ADC_InjectedChannelConfig() functions + (#) Get the voltage value, using ADC_GetConversionValue() or + ADC_GetInjectedConversionValue(). + +@endverbatim + * @{ + */ + + +/** + * @brief Enables or disables the temperature sensor and Vrefint channels. + * @param NewState: new state of the temperature sensor and Vrefint channels. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_TempSensorVrefintCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the temperature sensor and Vrefint channel*/ + ADC->CCR |= (uint32_t)ADC_CCR_TSVREFE; + } + else + { + /* Disable the temperature sensor and Vrefint channel*/ + ADC->CCR &= (uint32_t)(~ADC_CCR_TSVREFE); + } +} + +/** + * @brief Enables or disables the VBAT (Voltage Battery) channel. + * + * @note the Battery voltage measured is equal to VBAT/2 on STM32F40xx and + * STM32F41xx devices and equal to VBAT/4 on STM32F42xx and STM32F43xx devices + * + * @param NewState: new state of the VBAT channel. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_VBATCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the VBAT channel*/ + ADC->CCR |= (uint32_t)ADC_CCR_VBATE; + } + else + { + /* Disable the VBAT channel*/ + ADC->CCR &= (uint32_t)(~ADC_CCR_VBATE); + } +} + +/** + * @} + */ + +/** @defgroup ADC_Group4 Regular Channels Configuration functions + * @brief Regular Channels Configuration functions + * +@verbatim + =============================================================================== + ##### Regular Channels Configuration functions ##### + =============================================================================== + + [..] This section provides functions allowing to manage the ADC's regular channels, + it is composed of 2 sub sections : + + (#) Configuration and management functions for regular channels: This subsection + provides functions allowing to configure the ADC regular channels : + (++) Configure the rank in the regular group sequencer for each channel + (++) Configure the sampling time for each channel + (++) select the conversion Trigger for regular channels + (++) select the desired EOC event behavior configuration + (++) Activate the continuous Mode (*) + (++) Activate the Discontinuous Mode + -@@- Please Note that the following features for regular channels + are configurated using the ADC_Init() function : + (+@@) scan mode activation + (+@@) continuous mode activation (**) + (+@@) External trigger source + (+@@) External trigger edge + (+@@) number of conversion in the regular channels group sequencer. + + -@@- (*) and (**) are performing the same configuration + + (#) Get the conversion data: This subsection provides an important function in + the ADC peripheral since it returns the converted data of the current + regular channel. When the Conversion value is read, the EOC Flag is + automatically cleared. + + -@- For multi ADC mode, the last ADC1, ADC2 and ADC3 regular conversions + results data (in the selected multi mode) can be returned in the same + time using ADC_GetMultiModeConversionValue() function. + +@endverbatim + * @{ + */ +/** + * @brief Configures for the selected ADC regular channel its corresponding + * rank in the sequencer and its sample time. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_Channel: the ADC channel to configure. + * This parameter can be one of the following values: + * @arg ADC_Channel_0: ADC Channel0 selected + * @arg ADC_Channel_1: ADC Channel1 selected + * @arg ADC_Channel_2: ADC Channel2 selected + * @arg ADC_Channel_3: ADC Channel3 selected + * @arg ADC_Channel_4: ADC Channel4 selected + * @arg ADC_Channel_5: ADC Channel5 selected + * @arg ADC_Channel_6: ADC Channel6 selected + * @arg ADC_Channel_7: ADC Channel7 selected + * @arg ADC_Channel_8: ADC Channel8 selected + * @arg ADC_Channel_9: ADC Channel9 selected + * @arg ADC_Channel_10: ADC Channel10 selected + * @arg ADC_Channel_11: ADC Channel11 selected + * @arg ADC_Channel_12: ADC Channel12 selected + * @arg ADC_Channel_13: ADC Channel13 selected + * @arg ADC_Channel_14: ADC Channel14 selected + * @arg ADC_Channel_15: ADC Channel15 selected + * @arg ADC_Channel_16: ADC Channel16 selected + * @arg ADC_Channel_17: ADC Channel17 selected + * @arg ADC_Channel_18: ADC Channel18 selected + * @param Rank: The rank in the regular group sequencer. + * This parameter must be between 1 to 16. + * @param ADC_SampleTime: The sample time value to be set for the selected channel. + * This parameter can be one of the following values: + * @arg ADC_SampleTime_3Cycles: Sample time equal to 3 cycles + * @arg ADC_SampleTime_15Cycles: Sample time equal to 15 cycles + * @arg ADC_SampleTime_28Cycles: Sample time equal to 28 cycles + * @arg ADC_SampleTime_56Cycles: Sample time equal to 56 cycles + * @arg ADC_SampleTime_84Cycles: Sample time equal to 84 cycles + * @arg ADC_SampleTime_112Cycles: Sample time equal to 112 cycles + * @arg ADC_SampleTime_144Cycles: Sample time equal to 144 cycles + * @arg ADC_SampleTime_480Cycles: Sample time equal to 480 cycles + * @retval None + */ +void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CHANNEL(ADC_Channel)); + assert_param(IS_ADC_REGULAR_RANK(Rank)); + assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime)); + + /* if ADC_Channel_10 ... ADC_Channel_18 is selected */ + if (ADC_Channel > ADC_Channel_9) + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR1; + + /* Calculate the mask to clear */ + tmpreg2 = SMPR1_SMP_SET << (3 * (ADC_Channel - 10)); + + /* Clear the old sample time */ + tmpreg1 &= ~tmpreg2; + + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10)); + + /* Set the new sample time */ + tmpreg1 |= tmpreg2; + + /* Store the new register value */ + ADCx->SMPR1 = tmpreg1; + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR2; + + /* Calculate the mask to clear */ + tmpreg2 = SMPR2_SMP_SET << (3 * ADC_Channel); + + /* Clear the old sample time */ + tmpreg1 &= ~tmpreg2; + + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + + /* Set the new sample time */ + tmpreg1 |= tmpreg2; + + /* Store the new register value */ + ADCx->SMPR2 = tmpreg1; + } + /* For Rank 1 to 6 */ + if (Rank < 7) + { + /* Get the old register value */ + tmpreg1 = ADCx->SQR3; + + /* Calculate the mask to clear */ + tmpreg2 = SQR3_SQ_SET << (5 * (Rank - 1)); + + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1)); + + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + + /* Store the new register value */ + ADCx->SQR3 = tmpreg1; + } + /* For Rank 7 to 12 */ + else if (Rank < 13) + { + /* Get the old register value */ + tmpreg1 = ADCx->SQR2; + + /* Calculate the mask to clear */ + tmpreg2 = SQR2_SQ_SET << (5 * (Rank - 7)); + + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7)); + + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + + /* Store the new register value */ + ADCx->SQR2 = tmpreg1; + } + /* For Rank 13 to 16 */ + else + { + /* Get the old register value */ + tmpreg1 = ADCx->SQR1; + + /* Calculate the mask to clear */ + tmpreg2 = SQR1_SQ_SET << (5 * (Rank - 13)); + + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13)); + + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + + /* Store the new register value */ + ADCx->SQR1 = tmpreg1; + } +} + +/** + * @brief Enables the selected ADC software start conversion of the regular channels. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval None + */ +void ADC_SoftwareStartConv(ADC_TypeDef* ADCx) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + + /* Enable the selected ADC conversion for regular group */ + ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; +} + +/** + * @brief Gets the selected ADC Software start regular conversion Status. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The new state of ADC software start conversion (SET or RESET). + */ +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + + /* Check the status of SWSTART bit */ + if ((ADCx->CR2 & ADC_CR2_SWSTART) != (uint32_t)RESET) + { + /* SWSTART bit is set */ + bitstatus = SET; + } + else + { + /* SWSTART bit is reset */ + bitstatus = RESET; + } + + /* Return the SWSTART bit status */ + return bitstatus; +} + + +/** + * @brief Enables or disables the EOC on each regular channel conversion + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC EOC flag rising + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected ADC EOC rising on each regular channel conversion */ + ADCx->CR2 |= (uint32_t)ADC_CR2_EOCS; + } + else + { + /* Disable the selected ADC EOC rising on each regular channel conversion */ + ADCx->CR2 &= (uint32_t)(~ADC_CR2_EOCS); + } +} + +/** + * @brief Enables or disables the ADC continuous conversion mode + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC continuous conversion mode + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected ADC continuous conversion mode */ + ADCx->CR2 |= (uint32_t)ADC_CR2_CONT; + } + else + { + /* Disable the selected ADC continuous conversion mode */ + ADCx->CR2 &= (uint32_t)(~ADC_CR2_CONT); + } +} + +/** + * @brief Configures the discontinuous mode for the selected ADC regular group + * channel. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param Number: specifies the discontinuous mode regular channel count value. + * This number must be between 1 and 8. + * @retval None + */ +void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_REGULAR_DISC_NUMBER(Number)); + + /* Get the old register value */ + tmpreg1 = ADCx->CR1; + + /* Clear the old discontinuous mode channel count */ + tmpreg1 &= CR1_DISCNUM_RESET; + + /* Set the discontinuous mode channel count */ + tmpreg2 = Number - 1; + tmpreg1 |= tmpreg2 << 13; + + /* Store the new register value */ + ADCx->CR1 = tmpreg1; +} + +/** + * @brief Enables or disables the discontinuous mode on regular group channel + * for the specified ADC + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC discontinuous mode on + * regular group channel. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected ADC regular discontinuous mode */ + ADCx->CR1 |= (uint32_t)ADC_CR1_DISCEN; + } + else + { + /* Disable the selected ADC regular discontinuous mode */ + ADCx->CR1 &= (uint32_t)(~ADC_CR1_DISCEN); + } +} + +/** + * @brief Returns the last ADCx conversion result data for regular channel. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The Data conversion value. + */ +uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + + /* Return the selected ADC conversion value */ + return (uint16_t) ADCx->DR; +} + +/** + * @brief Returns the last ADC1, ADC2 and ADC3 regular conversions results + * data in the selected multi mode. + * @param None + * @retval The Data conversion value. + * @note In dual mode, the value returned by this function is as following + * Data[15:0] : these bits contain the regular data of ADC1. + * Data[31:16]: these bits contain the regular data of ADC2. + * @note In triple mode, the value returned by this function is as following + * Data[15:0] : these bits contain alternatively the regular data of ADC1, ADC3 and ADC2. + * Data[31:16]: these bits contain alternatively the regular data of ADC2, ADC1 and ADC3. + */ +uint32_t ADC_GetMultiModeConversionValue(void) +{ + /* Return the multi mode conversion value */ + return (*(__IO uint32_t *) CDR_ADDRESS); +} +/** + * @} + */ + +/** @defgroup ADC_Group5 Regular Channels DMA Configuration functions + * @brief Regular Channels DMA Configuration functions + * +@verbatim + =============================================================================== + ##### Regular Channels DMA Configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to configure the DMA for ADC + regular channels. + Since converted regular channel values are stored into a unique data + register, it is useful to use DMA for conversion of more than one regular + channel. This avoids the loss of the data already stored in the ADC + Data register. + When the DMA mode is enabled (using the ADC_DMACmd() function), after each + conversion of a regular channel, a DMA request is generated. + [..] Depending on the "DMA disable selection for Independent ADC mode" + configuration (using the ADC_DMARequestAfterLastTransferCmd() function), + at the end of the last DMA transfer, two possibilities are allowed: + (+) No new DMA request is issued to the DMA controller (feature DISABLED) + (+) Requests can continue to be generated (feature ENABLED). + [..] Depending on the "DMA disable selection for multi ADC mode" configuration + (using the void ADC_MultiModeDMARequestAfterLastTransferCmd() function), + at the end of the last DMA transfer, two possibilities are allowed: + (+) No new DMA request is issued to the DMA controller (feature DISABLED) + (+) Requests can continue to be generated (feature ENABLED). + +@endverbatim + * @{ + */ + + /** + * @brief Enables or disables the specified ADC DMA request. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC DMA transfer. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC DMA request */ + ADCx->CR2 |= (uint32_t)ADC_CR2_DMA; + } + else + { + /* Disable the selected ADC DMA request */ + ADCx->CR2 &= (uint32_t)(~ADC_CR2_DMA); + } +} + +/** + * @brief Enables or disables the ADC DMA request after last transfer (Single-ADC mode) + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC DMA request after last transfer. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC DMA request after last transfer */ + ADCx->CR2 |= (uint32_t)ADC_CR2_DDS; + } + else + { + /* Disable the selected ADC DMA request after last transfer */ + ADCx->CR2 &= (uint32_t)(~ADC_CR2_DDS); + } +} + +/** + * @brief Enables or disables the ADC DMA request after last transfer in multi ADC mode + * @param NewState: new state of the selected ADC DMA request after last transfer. + * This parameter can be: ENABLE or DISABLE. + * @note if Enabled, DMA requests are issued as long as data are converted and + * DMA mode for multi ADC mode (selected using ADC_CommonInit() function + * by ADC_CommonInitStruct.ADC_DMAAccessMode structure member) is + * ADC_DMAAccessMode_1, ADC_DMAAccessMode_2 or ADC_DMAAccessMode_3. + * @retval None + */ +void ADC_MultiModeDMARequestAfterLastTransferCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC DMA request after last transfer */ + ADC->CCR |= (uint32_t)ADC_CCR_DDS; + } + else + { + /* Disable the selected ADC DMA request after last transfer */ + ADC->CCR &= (uint32_t)(~ADC_CCR_DDS); + } +} +/** + * @} + */ + +/** @defgroup ADC_Group6 Injected channels Configuration functions + * @brief Injected channels Configuration functions + * +@verbatim + =============================================================================== + ##### Injected channels Configuration functions ##### + =============================================================================== + + [..] This section provide functions allowing to configure the ADC Injected channels, + it is composed of 2 sub sections : + + (#) Configuration functions for Injected channels: This subsection provides + functions allowing to configure the ADC injected channels : + (++) Configure the rank in the injected group sequencer for each channel + (++) Configure the sampling time for each channel + (++) Activate the Auto injected Mode + (++) Activate the Discontinuous Mode + (++) scan mode activation + (++) External/software trigger source + (++) External trigger edge + (++) injected channels sequencer. + + (#) Get the Specified Injected channel conversion data: This subsection + provides an important function in the ADC peripheral since it returns the + converted data of the specific injected channel. + +@endverbatim + * @{ + */ +/** + * @brief Configures for the selected ADC injected channel its corresponding + * rank in the sequencer and its sample time. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_Channel: the ADC channel to configure. + * This parameter can be one of the following values: + * @arg ADC_Channel_0: ADC Channel0 selected + * @arg ADC_Channel_1: ADC Channel1 selected + * @arg ADC_Channel_2: ADC Channel2 selected + * @arg ADC_Channel_3: ADC Channel3 selected + * @arg ADC_Channel_4: ADC Channel4 selected + * @arg ADC_Channel_5: ADC Channel5 selected + * @arg ADC_Channel_6: ADC Channel6 selected + * @arg ADC_Channel_7: ADC Channel7 selected + * @arg ADC_Channel_8: ADC Channel8 selected + * @arg ADC_Channel_9: ADC Channel9 selected + * @arg ADC_Channel_10: ADC Channel10 selected + * @arg ADC_Channel_11: ADC Channel11 selected + * @arg ADC_Channel_12: ADC Channel12 selected + * @arg ADC_Channel_13: ADC Channel13 selected + * @arg ADC_Channel_14: ADC Channel14 selected + * @arg ADC_Channel_15: ADC Channel15 selected + * @arg ADC_Channel_16: ADC Channel16 selected + * @arg ADC_Channel_17: ADC Channel17 selected + * @arg ADC_Channel_18: ADC Channel18 selected + * @param Rank: The rank in the injected group sequencer. + * This parameter must be between 1 to 4. + * @param ADC_SampleTime: The sample time value to be set for the selected channel. + * This parameter can be one of the following values: + * @arg ADC_SampleTime_3Cycles: Sample time equal to 3 cycles + * @arg ADC_SampleTime_15Cycles: Sample time equal to 15 cycles + * @arg ADC_SampleTime_28Cycles: Sample time equal to 28 cycles + * @arg ADC_SampleTime_56Cycles: Sample time equal to 56 cycles + * @arg ADC_SampleTime_84Cycles: Sample time equal to 84 cycles + * @arg ADC_SampleTime_112Cycles: Sample time equal to 112 cycles + * @arg ADC_SampleTime_144Cycles: Sample time equal to 144 cycles + * @arg ADC_SampleTime_480Cycles: Sample time equal to 480 cycles + * @retval None + */ +void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CHANNEL(ADC_Channel)); + assert_param(IS_ADC_INJECTED_RANK(Rank)); + assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime)); + /* if ADC_Channel_10 ... ADC_Channel_18 is selected */ + if (ADC_Channel > ADC_Channel_9) + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR1; + /* Calculate the mask to clear */ + tmpreg2 = SMPR1_SMP_SET << (3*(ADC_Channel - 10)); + /* Clear the old sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3*(ADC_Channel - 10)); + /* Set the new sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SMPR1 = tmpreg1; + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SMPR2; + /* Calculate the mask to clear */ + tmpreg2 = SMPR2_SMP_SET << (3 * ADC_Channel); + /* Clear the old sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + /* Set the new sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SMPR2 = tmpreg1; + } + /* Rank configuration */ + /* Get the old register value */ + tmpreg1 = ADCx->JSQR; + /* Get JL value: Number = JL+1 */ + tmpreg3 = (tmpreg1 & JSQR_JL_SET)>> 20; + /* Calculate the mask to clear: ((Rank-1)+(4-JL-1)) */ + tmpreg2 = JSQR_JSQ_SET << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + /* Clear the old JSQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set: ((Rank-1)+(4-JL-1)) */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + /* Set the JSQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->JSQR = tmpreg1; +} + +/** + * @brief Configures the sequencer length for injected channels + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param Length: The sequencer length. + * This parameter must be a number between 1 to 4. + * @retval None + */ +void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_INJECTED_LENGTH(Length)); + + /* Get the old register value */ + tmpreg1 = ADCx->JSQR; + + /* Clear the old injected sequence length JL bits */ + tmpreg1 &= JSQR_JL_RESET; + + /* Set the injected sequence length JL bits */ + tmpreg2 = Length - 1; + tmpreg1 |= tmpreg2 << 20; + + /* Store the new register value */ + ADCx->JSQR = tmpreg1; +} + +/** + * @brief Set the injected channels conversion value offset + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_InjectedChannel: the ADC injected channel to set its offset. + * This parameter can be one of the following values: + * @arg ADC_InjectedChannel_1: Injected Channel1 selected + * @arg ADC_InjectedChannel_2: Injected Channel2 selected + * @arg ADC_InjectedChannel_3: Injected Channel3 selected + * @arg ADC_InjectedChannel_4: Injected Channel4 selected + * @param Offset: the offset value for the selected ADC injected channel + * This parameter must be a 12bit value. + * @retval None + */ +void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset) +{ + __IO uint32_t tmp = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel)); + assert_param(IS_ADC_OFFSET(Offset)); + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel; + + /* Set the selected injected channel data offset */ + *(__IO uint32_t *) tmp = (uint32_t)Offset; +} + + /** + * @brief Configures the ADCx external trigger for injected channels conversion. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_ExternalTrigInjecConv: specifies the ADC trigger to start injected conversion. + * This parameter can be one of the following values: + * @arg ADC_ExternalTrigInjecConv_T1_CC4: Timer1 capture compare4 selected + * @arg ADC_ExternalTrigInjecConv_T1_TRGO: Timer1 TRGO event selected + * @arg ADC_ExternalTrigInjecConv_T2_CC1: Timer2 capture compare1 selected + * @arg ADC_ExternalTrigInjecConv_T2_TRGO: Timer2 TRGO event selected + * @arg ADC_ExternalTrigInjecConv_T3_CC2: Timer3 capture compare2 selected + * @arg ADC_ExternalTrigInjecConv_T3_CC4: Timer3 capture compare4 selected + * @arg ADC_ExternalTrigInjecConv_T4_CC1: Timer4 capture compare1 selected + * @arg ADC_ExternalTrigInjecConv_T4_CC2: Timer4 capture compare2 selected + * @arg ADC_ExternalTrigInjecConv_T4_CC3: Timer4 capture compare3 selected + * @arg ADC_ExternalTrigInjecConv_T4_TRGO: Timer4 TRGO event selected + * @arg ADC_ExternalTrigInjecConv_T5_CC4: Timer5 capture compare4 selected + * @arg ADC_ExternalTrigInjecConv_T5_TRGO: Timer5 TRGO event selected + * @arg ADC_ExternalTrigInjecConv_T8_CC2: Timer8 capture compare2 selected + * @arg ADC_ExternalTrigInjecConv_T8_CC3: Timer8 capture compare3 selected + * @arg ADC_ExternalTrigInjecConv_T8_CC4: Timer8 capture compare4 selected + * @arg ADC_ExternalTrigInjecConv_Ext_IT15: External interrupt line 15 event selected + * @retval None + */ +void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_EXT_INJEC_TRIG(ADC_ExternalTrigInjecConv)); + + /* Get the old register value */ + tmpreg = ADCx->CR2; + + /* Clear the old external event selection for injected group */ + tmpreg &= CR2_JEXTSEL_RESET; + + /* Set the external event selection for injected group */ + tmpreg |= ADC_ExternalTrigInjecConv; + + /* Store the new register value */ + ADCx->CR2 = tmpreg; +} + +/** + * @brief Configures the ADCx external trigger edge for injected channels conversion. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_ExternalTrigInjecConvEdge: specifies the ADC external trigger edge + * to start injected conversion. + * This parameter can be one of the following values: + * @arg ADC_ExternalTrigInjecConvEdge_None: external trigger disabled for + * injected conversion + * @arg ADC_ExternalTrigInjecConvEdge_Rising: detection on rising edge + * @arg ADC_ExternalTrigInjecConvEdge_Falling: detection on falling edge + * @arg ADC_ExternalTrigInjecConvEdge_RisingFalling: detection on both rising + * and falling edge + * @retval None + */ +void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_EXT_INJEC_TRIG_EDGE(ADC_ExternalTrigInjecConvEdge)); + /* Get the old register value */ + tmpreg = ADCx->CR2; + /* Clear the old external trigger edge for injected group */ + tmpreg &= CR2_JEXTEN_RESET; + /* Set the new external trigger edge for injected group */ + tmpreg |= ADC_ExternalTrigInjecConvEdge; + /* Store the new register value */ + ADCx->CR2 = tmpreg; +} + +/** + * @brief Enables the selected ADC software start conversion of the injected channels. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval None + */ +void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + /* Enable the selected ADC conversion for injected group */ + ADCx->CR2 |= (uint32_t)ADC_CR2_JSWSTART; +} + +/** + * @brief Gets the selected ADC Software start injected conversion Status. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @retval The new state of ADC software start injected conversion (SET or RESET). + */ +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + + /* Check the status of JSWSTART bit */ + if ((ADCx->CR2 & ADC_CR2_JSWSTART) != (uint32_t)RESET) + { + /* JSWSTART bit is set */ + bitstatus = SET; + } + else + { + /* JSWSTART bit is reset */ + bitstatus = RESET; + } + /* Return the JSWSTART bit status */ + return bitstatus; +} + +/** + * @brief Enables or disables the selected ADC automatic injected group + * conversion after regular one. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC auto injected conversion + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC automatic injected group conversion */ + ADCx->CR1 |= (uint32_t)ADC_CR1_JAUTO; + } + else + { + /* Disable the selected ADC automatic injected group conversion */ + ADCx->CR1 &= (uint32_t)(~ADC_CR1_JAUTO); + } +} + +/** + * @brief Enables or disables the discontinuous mode for injected group + * channel for the specified ADC + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param NewState: new state of the selected ADC discontinuous mode on injected + * group channel. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Enable the selected ADC injected discontinuous mode */ + ADCx->CR1 |= (uint32_t)ADC_CR1_JDISCEN; + } + else + { + /* Disable the selected ADC injected discontinuous mode */ + ADCx->CR1 &= (uint32_t)(~ADC_CR1_JDISCEN); + } +} + +/** + * @brief Returns the ADC injected channel conversion result + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_InjectedChannel: the converted ADC injected channel. + * This parameter can be one of the following values: + * @arg ADC_InjectedChannel_1: Injected Channel1 selected + * @arg ADC_InjectedChannel_2: Injected Channel2 selected + * @arg ADC_InjectedChannel_3: Injected Channel3 selected + * @arg ADC_InjectedChannel_4: Injected Channel4 selected + * @retval The Data conversion value. + */ +uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel)); + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel + JDR_OFFSET; + + /* Returns the selected injected channel conversion data value */ + return (uint16_t) (*(__IO uint32_t*) tmp); +} +/** + * @} + */ + +/** @defgroup ADC_Group7 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + + [..] This section provides functions allowing to configure the ADC Interrupts + and to get the status and clear flags and Interrupts pending bits. + + [..] Each ADC provides 4 Interrupts sources and 6 Flags which can be divided + into 3 groups: + + *** Flags and Interrupts for ADC regular channels *** + ===================================================== + [..] + (+) Flags : + (##) ADC_FLAG_OVR : Overrun detection when regular converted data are lost + + (##) ADC_FLAG_EOC : Regular channel end of conversion ==> to indicate + (depending on EOCS bit, managed by ADC_EOCOnEachRegularChannelCmd() ) + the end of: + (+++) a regular CHANNEL conversion + (+++) sequence of regular GROUP conversions . + + (##) ADC_FLAG_STRT: Regular channel start ==> to indicate when regular + CHANNEL conversion starts. + [..] + (+) Interrupts : + (##) ADC_IT_OVR : specifies the interrupt source for Overrun detection + event. + (##) ADC_IT_EOC : specifies the interrupt source for Regular channel end + of conversion event. + + + *** Flags and Interrupts for ADC Injected channels *** + ====================================================== + [..] + (+) Flags : + (##) ADC_FLAG_JEOC : Injected channel end of conversion ==> to indicate + at the end of injected GROUP conversion + + (##) ADC_FLAG_JSTRT: Injected channel start ==> to indicate hardware when + injected GROUP conversion starts. + [..] + (+) Interrupts : + (##) ADC_IT_JEOC : specifies the interrupt source for Injected channel + end of conversion event. + + *** General Flags and Interrupts for the ADC *** + ================================================ + [..] + (+)Flags : + (##) ADC_FLAG_AWD: Analog watchdog ==> to indicate if the converted voltage + crosses the programmed thresholds values. + [..] + (+) Interrupts : + (##) ADC_IT_AWD : specifies the interrupt source for Analog watchdog event. + + + [..] The user should identify which mode will be used in his application to + manage the ADC controller events: Polling mode or Interrupt mode. + + [..] In the Polling Mode it is advised to use the following functions: + (+) ADC_GetFlagStatus() : to check if flags events occur. + (+) ADC_ClearFlag() : to clear the flags events. + + [..] In the Interrupt Mode it is advised to use the following functions: + (+) ADC_ITConfig() : to enable or disable the interrupt source. + (+) ADC_GetITStatus() : to check if Interrupt occurs. + (+) ADC_ClearITPendingBit() : to clear the Interrupt pending Bit + (corresponding Flag). +@endverbatim + * @{ + */ +/** + * @brief Enables or disables the specified ADC interrupts. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_IT: specifies the ADC interrupt sources to be enabled or disabled. + * This parameter can be one of the following values: + * @arg ADC_IT_EOC: End of conversion interrupt mask + * @arg ADC_IT_AWD: Analog watchdog interrupt mask + * @arg ADC_IT_JEOC: End of injected conversion interrupt mask + * @arg ADC_IT_OVR: Overrun interrupt enable + * @param NewState: new state of the specified ADC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState) +{ + uint32_t itmask = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + assert_param(IS_ADC_IT(ADC_IT)); + + /* Get the ADC IT index */ + itmask = (uint8_t)ADC_IT; + itmask = (uint32_t)0x01 << itmask; + + if (NewState != DISABLE) + { + /* Enable the selected ADC interrupts */ + ADCx->CR1 |= itmask; + } + else + { + /* Disable the selected ADC interrupts */ + ADCx->CR1 &= (~(uint32_t)itmask); + } +} + +/** + * @brief Checks whether the specified ADC flag is set or not. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg ADC_FLAG_AWD: Analog watchdog flag + * @arg ADC_FLAG_EOC: End of conversion flag + * @arg ADC_FLAG_JEOC: End of injected group conversion flag + * @arg ADC_FLAG_JSTRT: Start of injected group conversion flag + * @arg ADC_FLAG_STRT: Start of regular group conversion flag + * @arg ADC_FLAG_OVR: Overrun flag + * @retval The new state of ADC_FLAG (SET or RESET). + */ +FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_GET_FLAG(ADC_FLAG)); + + /* Check the status of the specified ADC flag */ + if ((ADCx->SR & ADC_FLAG) != (uint8_t)RESET) + { + /* ADC_FLAG is set */ + bitstatus = SET; + } + else + { + /* ADC_FLAG is reset */ + bitstatus = RESET; + } + /* Return the ADC_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the ADCx's pending flags. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_FLAG: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg ADC_FLAG_AWD: Analog watchdog flag + * @arg ADC_FLAG_EOC: End of conversion flag + * @arg ADC_FLAG_JEOC: End of injected group conversion flag + * @arg ADC_FLAG_JSTRT: Start of injected group conversion flag + * @arg ADC_FLAG_STRT: Start of regular group conversion flag + * @arg ADC_FLAG_OVR: Overrun flag + * @retval None + */ +void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_CLEAR_FLAG(ADC_FLAG)); + + /* Clear the selected ADC flags */ + ADCx->SR = ~(uint32_t)ADC_FLAG; +} + +/** + * @brief Checks whether the specified ADC interrupt has occurred or not. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_IT: specifies the ADC interrupt source to check. + * This parameter can be one of the following values: + * @arg ADC_IT_EOC: End of conversion interrupt mask + * @arg ADC_IT_AWD: Analog watchdog interrupt mask + * @arg ADC_IT_JEOC: End of injected conversion interrupt mask + * @arg ADC_IT_OVR: Overrun interrupt mask + * @retval The new state of ADC_IT (SET or RESET). + */ +ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT) +{ + ITStatus bitstatus = RESET; + uint32_t itmask = 0, enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_IT(ADC_IT)); + + /* Get the ADC IT index */ + itmask = ADC_IT >> 8; + + /* Get the ADC_IT enable bit status */ + enablestatus = (ADCx->CR1 & ((uint32_t)0x01 << (uint8_t)ADC_IT)) ; + + /* Check the status of the specified ADC interrupt */ + if (((ADCx->SR & itmask) != (uint32_t)RESET) && enablestatus) + { + /* ADC_IT is set */ + bitstatus = SET; + } + else + { + /* ADC_IT is reset */ + bitstatus = RESET; + } + /* Return the ADC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the ADCx's interrupt pending bits. + * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. + * @param ADC_IT: specifies the ADC interrupt pending bit to clear. + * This parameter can be one of the following values: + * @arg ADC_IT_EOC: End of conversion interrupt mask + * @arg ADC_IT_AWD: Analog watchdog interrupt mask + * @arg ADC_IT_JEOC: End of injected conversion interrupt mask + * @arg ADC_IT_OVR: Overrun interrupt mask + * @retval None + */ +void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT) +{ + uint8_t itmask = 0; + /* Check the parameters */ + assert_param(IS_ADC_ALL_PERIPH(ADCx)); + assert_param(IS_ADC_IT(ADC_IT)); + /* Get the ADC IT index */ + itmask = (uint8_t)(ADC_IT >> 8); + /* Clear the selected ADC interrupt pending bits */ + ADCx->SR = ~(uint32_t)itmask; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/Kconfig b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/Kconfig new file mode 100644 index 000000000..a289b6ca9 --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/Kconfig @@ -0,0 +1,17 @@ +if BSP_USING_DAC + config DAC_BUS_NAME + string "dac bus name" + default "dac" + + config DAC_DRIVER_NAME + string "dac driver name" + default "dac_drv" + + config DAC_DEVICE_NAME + string "dac bus device name" + default "dac_dev" + + config DAC_GPIO_NUM + int "dac gpio pin num(only support 4 or 5)" + default "4" +endif diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/Makefile b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/Makefile new file mode 100644 index 000000000..4bd1c0c55 --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := connect_dac.c hardware_dac.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/connect_dac.c b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/connect_dac.c new file mode 100644 index 000000000..6186b0a48 --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/connect_dac.c @@ -0,0 +1,168 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_dac.c +* @brief support to register DAC pointer and function +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-1-10 +*/ + +#include + +#define _DAC_CONS(string1, string2) string1##string2 +#define DAC_CONS(string1, string2) _DAC_CONS(string1, string2) + +#ifdef BSP_USING_DAC +#define DAC_GPIO DAC_CONS(GPIO_Pin_, DAC_GPIO_NUM) +#endif + +static void DacInit(struct DacHardwareDevice *dac_dev) +{ + GPIO_InitTypeDef GPIO_InitStructure; + DAC_InitTypeDef DAC_InitType; + +#ifdef BSP_USING_DAC + if (0 == strncmp(dac_dev->haldev.dev_name, DAC_DEVICE_NAME, NAME_NUM_MAX)) { + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//enable GPIOA clock + RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//enable DAC clock + + GPIO_InitStructure.GPIO_Pin = DAC_GPIO; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + DAC_InitType.DAC_Trigger = DAC_Trigger_None;//disable trigger function TEN1=0 + DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;//disable wave generation function + DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;//mask and amplitude configure + DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable;//disable DAC1 output buffer BOFF1=1 + DAC_Init(DAC_Channel_1, &DAC_InitType); + + DAC_Cmd(DAC_Channel_1, ENABLE);//enable DAC channel 1 + + DAC_SetChannel1Data(DAC_Align_12b_R, 0);//12 bits、R-Align data format, default 0 + } +#endif +} + +static uint32 Stm32DacOpen(void *dev) +{ + struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev; + + DacInit(dac_dev); + + return EOK; +} + +static uint32 Stm32DacClose(void *dev) +{ + struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev; + + DAC_DeInit(); + + return EOK; +} + +static uint32 Stm32DacRead(void *dev, struct BusBlockReadParam *read_param) +{ + struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev; + + uint16 dac_set_value = 0; + + dac_set_value = DAC_GetDataOutputValue(DAC_Channel_1); + + *(uint16 *)read_param->buffer = dac_set_value; + read_param->read_length = 2; + + return read_param->read_length; +} + +static uint32 Stm32DacDrvConfigure(void *drv, struct BusConfigureInfo *configure_info) +{ + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(configure_info); + + x_err_t ret = EOK; + + struct DacDriver *dac_drv = (struct DacDriver *)drv; + struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dac_drv->driver.owner_bus->owner_haldev; + struct Stm32HwDac *dac_cfg = (struct Stm32HwDac *)dac_dev->haldev.private_data; + + switch (configure_info->configure_cmd) + { + case OPE_CFG: + dac_cfg->digital_data = *(uint16 *)configure_info->private_data; + DAC_SetChannel1Data(DAC_Align_12b_R, dac_cfg->digital_data);//12 bits、R-Align data format, digital data + break; + default: + break; + } + + return ret; +} + +static const struct DacDevDone dev_done = +{ + Stm32DacOpen, + Stm32DacClose, + NONE, + Stm32DacRead, +}; + +int Stm32HwDacInit(void) +{ + x_err_t ret = EOK; + +#ifdef BSP_USING_DAC + static struct DacBus dac_bus; + static struct DacDriver dac_drv; + static struct DacHardwareDevice dac_dev; + static struct Stm32HwDac dac_cfg; + + dac_drv.configure = Stm32DacDrvConfigure; + + ret = DacBusInit(&dac_bus, DAC_BUS_NAME); + if (ret != EOK) { + KPrintf("DAC bus init error %d\n", ret); + return ERROR; + } + + ret = DacDriverInit(&dac_drv, DAC_DRIVER_NAME); + if (ret != EOK) { + KPrintf("DAC driver init error %d\n", ret); + return ERROR; + } + ret = DacDriverAttachToBus(DAC_DRIVER_NAME, DAC_BUS_NAME); + if (ret != EOK) { + KPrintf("DAC driver attach error %d\n", ret); + return ERROR; + } + + dac_dev.dac_dev_done = &dev_done; + dac_cfg.DACx = DAC; + dac_cfg.digital_data = 0; + + ret = DacDeviceRegister(&dac_dev, (void *)&dac_cfg, DAC_DEVICE_NAME); + if (ret != EOK) { + KPrintf("DAC device register error %d\n", ret); + return ERROR; + } + ret = DacDeviceAttachToBus(DAC_DEVICE_NAME, DAC_BUS_NAME); + if (ret != EOK) { + KPrintf("DAC device register error %d\n", ret); + return ERROR; + } +#endif + + return ret; +} diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/hardware_dac.c b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/hardware_dac.c new file mode 100644 index 000000000..a74137f38 --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/dac/hardware_dac.c @@ -0,0 +1,733 @@ +/** + ****************************************************************************** + * @file stm32f4xx_dac.c + * @author MCD Application Team + * @version V1.4.0 + * @date 04-August-2014 + * @brief This file provides firmware functions to manage the following + * functionalities of the Digital-to-Analog Converter (DAC) peripheral: + * + DAC channels configuration: trigger, output buffer, data format + * + DMA management + * + Interrupts and flags management + * + @verbatim + =============================================================================== + ##### DAC Peripheral features ##### + =============================================================================== + [..] + *** DAC Channels *** + ==================== + [..] + The device integrates two 12-bit Digital Analog Converters that can + be used independently or simultaneously (dual mode): + (#) DAC channel1 with DAC_OUT1 (PA4) as output + (#) DAC channel2 with DAC_OUT2 (PA5) as output + + *** DAC Triggers *** + ==================== + [..] + Digital to Analog conversion can be non-triggered using DAC_Trigger_None + and DAC_OUT1/DAC_OUT2 is available once writing to DHRx register + using DAC_SetChannel1Data() / DAC_SetChannel2Data() functions. + [..] + Digital to Analog conversion can be triggered by: + (#) External event: EXTI Line 9 (any GPIOx_Pin9) using DAC_Trigger_Ext_IT9. + The used pin (GPIOx_Pin9) must be configured in input mode. + + (#) Timers TRGO: TIM2, TIM4, TIM5, TIM6, TIM7 and TIM8 + (DAC_Trigger_T2_TRGO, DAC_Trigger_T4_TRGO...) + The timer TRGO event should be selected using TIM_SelectOutputTrigger() + + (#) Software using DAC_Trigger_Software + + *** DAC Buffer mode feature *** + =============================== + [..] + Each DAC channel integrates an output buffer that can be used to + reduce the output impedance, and to drive external loads directly + without having to add an external operational amplifier. + To enable, the output buffer use + DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; + [..] + (@) Refer to the device datasheet for more details about output + impedance value with and without output buffer. + + *** DAC wave generation feature *** + =================================== + [..] + Both DAC channels can be used to generate + (#) Noise wave using DAC_WaveGeneration_Noise + (#) Triangle wave using DAC_WaveGeneration_Triangle + + -@- Wave generation can be disabled using DAC_WaveGeneration_None + + *** DAC data format *** + ======================= + [..] + The DAC data format can be: + (#) 8-bit right alignment using DAC_Align_8b_R + (#) 12-bit left alignment using DAC_Align_12b_L + (#) 12-bit right alignment using DAC_Align_12b_R + + *** DAC data value to voltage correspondence *** + ================================================ + [..] + The analog output voltage on each DAC channel pin is determined + by the following equation: + DAC_OUTx = VREF+ * DOR / 4095 + with DOR is the Data Output Register + VEF+ is the input voltage reference (refer to the device datasheet) + e.g. To set DAC_OUT1 to 0.7V, use + DAC_SetChannel1Data(DAC_Align_12b_R, 868); + Assuming that VREF+ = 3.3V, DAC_OUT1 = (3.3 * 868) / 4095 = 0.7V + + *** DMA requests *** + ===================== + [..] + A DMA1 request can be generated when an external trigger (but not + a software trigger) occurs if DMA1 requests are enabled using + DAC_DMACmd() + [..] + DMA1 requests are mapped as following: + (#) DAC channel1 : mapped on DMA1 Stream5 channel7 which must be + already configured + (#) DAC channel2 : mapped on DMA1 Stream6 channel7 which must be + already configured + + + ##### How to use this driver ##### + =============================================================================== + [..] + (+) DAC APB clock must be enabled to get write access to DAC + registers using + RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE) + (+) Configure DAC_OUTx (DAC_OUT1: PA4, DAC_OUT2: PA5) in analog mode. + (+) Configure the DAC channel using DAC_Init() function + (+) Enable the DAC channel using DAC_Cmd() function + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/** +* @file: hardware_dac.c +* @brief: support hardware dac function +* @version: 2.0 +* @author: AIIT XUOS Lab +* @date: 2022/1/11 +*/ + +/************************************************* +File name: hardware_dac.c +Description: support hardware dac function +Others: +History: +1. Date: 2022-1-11 +Author: AIIT XUOS Lab +Modification: +1. rename stm32f4xx_dac.c for XiUOS +*************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup DAC + * @brief DAC driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* CR register Mask */ +#define CR_CLEAR_MASK ((uint32_t)0x00000FFE) + +/* DAC Dual Channels SWTRIG masks */ +#define DUAL_SWTRIG_SET ((uint32_t)0x00000003) +#define DUAL_SWTRIG_RESET ((uint32_t)0xFFFFFFFC) + +/* DHR registers offsets */ +#define DHR12R1_OFFSET ((uint32_t)0x00000008) +#define DHR12R2_OFFSET ((uint32_t)0x00000014) +#define DHR12RD_OFFSET ((uint32_t)0x00000020) + +/* DOR register offset */ +#define DOR_OFFSET ((uint32_t)0x0000002C) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup DAC_Private_Functions + * @{ + */ + +/** @defgroup DAC_Group1 DAC channels configuration + * @brief DAC channels configuration: trigger, output buffer, data format + * +@verbatim + =============================================================================== + ##### DAC channels configuration: trigger, output buffer, data format ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes the DAC peripheral registers to their default reset values. + * @param None + * @retval None + */ +void DAC_DeInit(void) +{ + /* Enable DAC reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, ENABLE); + /* Release DAC from reset state */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, DISABLE); +} + +/** + * @brief Initializes the DAC peripheral according to the specified parameters + * in the DAC_InitStruct. + * @param DAC_Channel: the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_InitStruct: pointer to a DAC_InitTypeDef structure that contains + * the configuration information for the specified DAC channel. + * @retval None + */ +void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + + /* Check the DAC parameters */ + assert_param(IS_DAC_TRIGGER(DAC_InitStruct->DAC_Trigger)); + assert_param(IS_DAC_GENERATE_WAVE(DAC_InitStruct->DAC_WaveGeneration)); + assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude)); + assert_param(IS_DAC_OUTPUT_BUFFER_STATE(DAC_InitStruct->DAC_OutputBuffer)); + +/*---------------------------- DAC CR Configuration --------------------------*/ + /* Get the DAC CR value */ + tmpreg1 = DAC->CR; + /* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */ + tmpreg1 &= ~(CR_CLEAR_MASK << DAC_Channel); + /* Configure for the selected DAC channel: buffer output, trigger, + wave generation, mask/amplitude for wave generation */ + /* Set TSELx and TENx bits according to DAC_Trigger value */ + /* Set WAVEx bits according to DAC_WaveGeneration value */ + /* Set MAMPx bits according to DAC_LFSRUnmask_TriangleAmplitude value */ + /* Set BOFFx bit according to DAC_OutputBuffer value */ + tmpreg2 = (DAC_InitStruct->DAC_Trigger | DAC_InitStruct->DAC_WaveGeneration | + DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude | \ + DAC_InitStruct->DAC_OutputBuffer); + /* Calculate CR register value depending on DAC_Channel */ + tmpreg1 |= tmpreg2 << DAC_Channel; + /* Write to DAC CR */ + DAC->CR = tmpreg1; +} + +/** + * @brief Fills each DAC_InitStruct member with its default value. + * @param DAC_InitStruct: pointer to a DAC_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct) +{ +/*--------------- Reset DAC init structure parameters values -----------------*/ + /* Initialize the DAC_Trigger member */ + DAC_InitStruct->DAC_Trigger = DAC_Trigger_None; + /* Initialize the DAC_WaveGeneration member */ + DAC_InitStruct->DAC_WaveGeneration = DAC_WaveGeneration_None; + /* Initialize the DAC_LFSRUnmask_TriangleAmplitude member */ + DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; + /* Initialize the DAC_OutputBuffer member */ + DAC_InitStruct->DAC_OutputBuffer = DAC_OutputBuffer_Enable; +} + +/** + * @brief Enables or disables the specified DAC channel. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param NewState: new state of the DAC channel. + * This parameter can be: ENABLE or DISABLE. + * @note When the DAC channel is enabled the trigger source can no more be modified. + * @retval None + */ +void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected DAC channel */ + DAC->CR |= (DAC_CR_EN1 << DAC_Channel); + } + else + { + /* Disable the selected DAC channel */ + DAC->CR &= (~(DAC_CR_EN1 << DAC_Channel)); + } +} + +/** + * @brief Enables or disables the selected DAC channel software trigger. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param NewState: new state of the selected DAC channel software trigger. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable software trigger for the selected DAC channel */ + DAC->SWTRIGR |= (uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4); + } + else + { + /* Disable software trigger for the selected DAC channel */ + DAC->SWTRIGR &= ~((uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4)); + } +} + +/** + * @brief Enables or disables simultaneously the two DAC channels software triggers. + * @param NewState: new state of the DAC channels software triggers. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_DualSoftwareTriggerCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable software trigger for both DAC channels */ + DAC->SWTRIGR |= DUAL_SWTRIG_SET; + } + else + { + /* Disable software trigger for both DAC channels */ + DAC->SWTRIGR &= DUAL_SWTRIG_RESET; + } +} + +/** + * @brief Enables or disables the selected DAC channel wave generation. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_Wave: specifies the wave type to enable or disable. + * This parameter can be one of the following values: + * @arg DAC_Wave_Noise: noise wave generation + * @arg DAC_Wave_Triangle: triangle wave generation + * @param NewState: new state of the selected DAC channel wave generation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_WAVE(DAC_Wave)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected wave generation for the selected DAC channel */ + DAC->CR |= DAC_Wave << DAC_Channel; + } + else + { + /* Disable the selected wave generation for the selected DAC channel */ + DAC->CR &= ~(DAC_Wave << DAC_Channel); + } +} + +/** + * @brief Set the specified data holding register value for DAC channel1. + * @param DAC_Align: Specifies the data alignment for DAC channel1. + * This parameter can be one of the following values: + * @arg DAC_Align_8b_R: 8bit right data alignment selected + * @arg DAC_Align_12b_L: 12bit left data alignment selected + * @arg DAC_Align_12b_R: 12bit right data alignment selected + * @param Data: Data to be loaded in the selected data holding register. + * @retval None + */ +void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data)); + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12R1_OFFSET + DAC_Align; + + /* Set the DAC channel1 selected data holding register */ + *(__IO uint32_t *) tmp = Data; +} + +/** + * @brief Set the specified data holding register value for DAC channel2. + * @param DAC_Align: Specifies the data alignment for DAC channel2. + * This parameter can be one of the following values: + * @arg DAC_Align_8b_R: 8bit right data alignment selected + * @arg DAC_Align_12b_L: 12bit left data alignment selected + * @arg DAC_Align_12b_R: 12bit right data alignment selected + * @param Data: Data to be loaded in the selected data holding register. + * @retval None + */ +void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data)); + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12R2_OFFSET + DAC_Align; + + /* Set the DAC channel2 selected data holding register */ + *(__IO uint32_t *)tmp = Data; +} + +/** + * @brief Set the specified data holding register value for dual channel DAC. + * @param DAC_Align: Specifies the data alignment for dual channel DAC. + * This parameter can be one of the following values: + * @arg DAC_Align_8b_R: 8bit right data alignment selected + * @arg DAC_Align_12b_L: 12bit left data alignment selected + * @arg DAC_Align_12b_R: 12bit right data alignment selected + * @param Data2: Data for DAC Channel2 to be loaded in the selected data holding register. + * @param Data1: Data for DAC Channel1 to be loaded in the selected data holding register. + * @note In dual mode, a unique register access is required to write in both + * DAC channels at the same time. + * @retval None + */ +void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1) +{ + uint32_t data = 0, tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data1)); + assert_param(IS_DAC_DATA(Data2)); + + /* Calculate and set dual DAC data holding register value */ + if (DAC_Align == DAC_Align_8b_R) + { + data = ((uint32_t)Data2 << 8) | Data1; + } + else + { + data = ((uint32_t)Data2 << 16) | Data1; + } + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12RD_OFFSET + DAC_Align; + + /* Set the dual DAC selected data holding register */ + *(__IO uint32_t *)tmp = data; +} + +/** + * @brief Returns the last data output value of the selected DAC channel. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @retval The selected DAC channel data output value. + */ +uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + + tmp = (uint32_t) DAC_BASE ; + tmp += DOR_OFFSET + ((uint32_t)DAC_Channel >> 2); + + /* Returns the DAC channel data output register value */ + return (uint16_t) (*(__IO uint32_t*) tmp); +} +/** + * @} + */ + +/** @defgroup DAC_Group2 DMA management functions + * @brief DMA management functions + * +@verbatim + =============================================================================== + ##### DMA management functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified DAC channel DMA request. + * @note When enabled DMA1 is generated when an external trigger (EXTI Line9, + * TIM2, TIM4, TIM5, TIM6, TIM7 or TIM8 but not a software trigger) occurs. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param NewState: new state of the selected DAC channel DMA request. + * This parameter can be: ENABLE or DISABLE. + * @note The DAC channel1 is mapped on DMA1 Stream 5 channel7 which must be + * already configured. + * @note The DAC channel2 is mapped on DMA1 Stream 6 channel7 which must be + * already configured. + * @retval None + */ +void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected DAC channel DMA request */ + DAC->CR |= (DAC_CR_DMAEN1 << DAC_Channel); + } + else + { + /* Disable the selected DAC channel DMA request */ + DAC->CR &= (~(DAC_CR_DMAEN1 << DAC_Channel)); + } +} +/** + * @} + */ + +/** @defgroup DAC_Group3 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified DAC interrupts. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_IT: specifies the DAC interrupt sources to be enabled or disabled. + * This parameter can be the following values: + * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * @param NewState: new state of the specified DAC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DAC_ITConfig(uint32_t DAC_Channel, uint32_t DAC_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + assert_param(IS_DAC_IT(DAC_IT)); + + if (NewState != DISABLE) + { + /* Enable the selected DAC interrupts */ + DAC->CR |= (DAC_IT << DAC_Channel); + } + else + { + /* Disable the selected DAC interrupts */ + DAC->CR &= (~(uint32_t)(DAC_IT << DAC_Channel)); + } +} + +/** + * @brief Checks whether the specified DAC flag is set or not. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_FLAG: specifies the flag to check. + * This parameter can be only of the following value: + * @arg DAC_FLAG_DMAUDR: DMA underrun flag + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * @retval The new state of DAC_FLAG (SET or RESET). + */ +FlagStatus DAC_GetFlagStatus(uint32_t DAC_Channel, uint32_t DAC_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_FLAG(DAC_FLAG)); + + /* Check the status of the specified DAC flag */ + if ((DAC->SR & (DAC_FLAG << DAC_Channel)) != (uint8_t)RESET) + { + /* DAC_FLAG is set */ + bitstatus = SET; + } + else + { + /* DAC_FLAG is reset */ + bitstatus = RESET; + } + /* Return the DAC_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the DAC channel's pending flags. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_FLAG: specifies the flag to clear. + * This parameter can be of the following value: + * @arg DAC_FLAG_DMAUDR: DMA underrun flag + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * @retval None + */ +void DAC_ClearFlag(uint32_t DAC_Channel, uint32_t DAC_FLAG) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_FLAG(DAC_FLAG)); + + /* Clear the selected DAC flags */ + DAC->SR = (DAC_FLAG << DAC_Channel); +} + +/** + * @brief Checks whether the specified DAC interrupt has occurred or not. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_IT: specifies the DAC interrupt source to check. + * This parameter can be the following values: + * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * @retval The new state of DAC_IT (SET or RESET). + */ +ITStatus DAC_GetITStatus(uint32_t DAC_Channel, uint32_t DAC_IT) +{ + ITStatus bitstatus = RESET; + uint32_t enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_IT(DAC_IT)); + + /* Get the DAC_IT enable bit status */ + enablestatus = (DAC->CR & (DAC_IT << DAC_Channel)) ; + + /* Check the status of the specified DAC interrupt */ + if (((DAC->SR & (DAC_IT << DAC_Channel)) != (uint32_t)RESET) && enablestatus) + { + /* DAC_IT is set */ + bitstatus = SET; + } + else + { + /* DAC_IT is reset */ + bitstatus = RESET; + } + /* Return the DAC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the DAC channel's interrupt pending bits. + * @param DAC_Channel: The selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_Channel_1: DAC Channel1 selected + * @arg DAC_Channel_2: DAC Channel2 selected + * @param DAC_IT: specifies the DAC interrupt pending bit to clear. + * This parameter can be the following values: + * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask + * @note The DMA underrun occurs when a second external trigger arrives before the + * acknowledgement for the first external trigger is received (first request). + * @retval None + */ +void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_IT(DAC_IT)); + + /* Clear the selected DAC interrupt pending bits */ + DAC->SR = (DAC_IT << DAC_Channel); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/connect_adc.h b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/connect_adc.h new file mode 100644 index 000000000..ffd3de7bc --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/connect_adc.h @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_adc.h +* @brief define stm32f407-st-discovery adc function and struct +* @version 1.1 +* @author AIIT XUOS Lab +* @date 2021-12-28 +*/ + +#ifndef CONNECT_ADC_H +#define CONNECT_ADC_H + +#include +#include +#include +#include + +struct Stm32HwAdc +{ + ADC_TypeDef *ADCx; + uint8 adc_channel; +}; + +int Stm32HwAdcInit(void); + +#endif diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/connect_dac.h b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/connect_dac.h new file mode 100644 index 000000000..e5fa169de --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/connect_dac.h @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_dac.h +* @brief define stm32f407-st-discovery adc function and struct +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-1-10 +*/ + +#ifndef CONNECT_DAC_H +#define CONNECT_DAC_H + +#include +#include +#include +#include + +struct Stm32HwDac +{ + DAC_TypeDef *DACx; + uint16 digital_data; +}; + +int Stm32HwDacInit(void); + +#endif diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_adc.h b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_adc.h new file mode 100644 index 000000000..a731859d9 --- /dev/null +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_adc.h @@ -0,0 +1,675 @@ +/** + ****************************************************************************** + * @file stm32f4xx_adc.h + * @author MCD Application Team + * @version V1.4.0 + * @date 04-August-2014 + * @brief This file contains all the functions prototypes for the ADC firmware + * library. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/** +* @file: hardware_adc.h +* @brief: define hardware adc function +* @version: 1.1 +* @author: AIIT XUOS Lab +* @date: 2021/12/28 +*/ + +/************************************************* +File name: hardware_adc.h +Description: define hardware adc function +Others: +History: +1. Date: 2021-12-28 +Author: AIIT XUOS Lab +Modification: +1. rename stm32f4xx_adc.h for XiUOS +*************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __HARDWARE_ADC_H__ +#define __HARDWARE_ADC_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @addtogroup ADC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief ADC Init structure definition + */ +typedef struct +{ + uint32_t ADC_Resolution; /*!< Configures the ADC resolution dual mode. + This parameter can be a value of @ref ADC_resolution */ + FunctionalState ADC_ScanConvMode; /*!< Specifies whether the conversion + is performed in Scan (multichannels) + or Single (one channel) mode. + This parameter can be set to ENABLE or DISABLE */ + FunctionalState ADC_ContinuousConvMode; /*!< Specifies whether the conversion + is performed in Continuous or Single mode. + This parameter can be set to ENABLE or DISABLE. */ + uint32_t ADC_ExternalTrigConvEdge; /*!< Select the external trigger edge and + enable the trigger of a regular group. + This parameter can be a value of + @ref ADC_external_trigger_edge_for_regular_channels_conversion */ + uint32_t ADC_ExternalTrigConv; /*!< Select the external event used to trigger + the start of conversion of a regular group. + This parameter can be a value of + @ref ADC_extrenal_trigger_sources_for_regular_channels_conversion */ + uint32_t ADC_DataAlign; /*!< Specifies whether the ADC data alignment + is left or right. This parameter can be + a value of @ref ADC_data_align */ + uint8_t ADC_NbrOfConversion; /*!< Specifies the number of ADC conversions + that will be done using the sequencer for + regular channel group. + This parameter must range from 1 to 16. */ +}ADC_InitTypeDef; + +/** + * @brief ADC Common Init structure definition + */ +typedef struct +{ + uint32_t ADC_Mode; /*!< Configures the ADC to operate in + independent or multi mode. + This parameter can be a value of @ref ADC_Common_mode */ + uint32_t ADC_Prescaler; /*!< Select the frequency of the clock + to the ADC. The clock is common for all the ADCs. + This parameter can be a value of @ref ADC_Prescaler */ + uint32_t ADC_DMAAccessMode; /*!< Configures the Direct memory access + mode for multi ADC mode. + This parameter can be a value of + @ref ADC_Direct_memory_access_mode_for_multi_mode */ + uint32_t ADC_TwoSamplingDelay; /*!< Configures the Delay between 2 sampling phases. + This parameter can be a value of + @ref ADC_delay_between_2_sampling_phases */ + +}ADC_CommonInitTypeDef; + + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup ADC_Exported_Constants + * @{ + */ +#define IS_ADC_ALL_PERIPH(PERIPH) (((PERIPH) == ADC1) || \ + ((PERIPH) == ADC2) || \ + ((PERIPH) == ADC3)) + +/** @defgroup ADC_Common_mode + * @{ + */ +#define ADC_Mode_Independent ((uint32_t)0x00000000) +#define ADC_DualMode_RegSimult_InjecSimult ((uint32_t)0x00000001) +#define ADC_DualMode_RegSimult_AlterTrig ((uint32_t)0x00000002) +#define ADC_DualMode_InjecSimult ((uint32_t)0x00000005) +#define ADC_DualMode_RegSimult ((uint32_t)0x00000006) +#define ADC_DualMode_Interl ((uint32_t)0x00000007) +#define ADC_DualMode_AlterTrig ((uint32_t)0x00000009) +#define ADC_TripleMode_RegSimult_InjecSimult ((uint32_t)0x00000011) +#define ADC_TripleMode_RegSimult_AlterTrig ((uint32_t)0x00000012) +#define ADC_TripleMode_InjecSimult ((uint32_t)0x00000015) +#define ADC_TripleMode_RegSimult ((uint32_t)0x00000016) +#define ADC_TripleMode_Interl ((uint32_t)0x00000017) +#define ADC_TripleMode_AlterTrig ((uint32_t)0x00000019) +#define IS_ADC_MODE(MODE) (((MODE) == ADC_Mode_Independent) || \ + ((MODE) == ADC_DualMode_RegSimult_InjecSimult) || \ + ((MODE) == ADC_DualMode_RegSimult_AlterTrig) || \ + ((MODE) == ADC_DualMode_InjecSimult) || \ + ((MODE) == ADC_DualMode_RegSimult) || \ + ((MODE) == ADC_DualMode_Interl) || \ + ((MODE) == ADC_DualMode_AlterTrig) || \ + ((MODE) == ADC_TripleMode_RegSimult_InjecSimult) || \ + ((MODE) == ADC_TripleMode_RegSimult_AlterTrig) || \ + ((MODE) == ADC_TripleMode_InjecSimult) || \ + ((MODE) == ADC_TripleMode_RegSimult) || \ + ((MODE) == ADC_TripleMode_Interl) || \ + ((MODE) == ADC_TripleMode_AlterTrig)) +/** + * @} + */ + + +/** @defgroup ADC_Prescaler + * @{ + */ +#define ADC_Prescaler_Div2 ((uint32_t)0x00000000) +#define ADC_Prescaler_Div4 ((uint32_t)0x00010000) +#define ADC_Prescaler_Div6 ((uint32_t)0x00020000) +#define ADC_Prescaler_Div8 ((uint32_t)0x00030000) +#define IS_ADC_PRESCALER(PRESCALER) (((PRESCALER) == ADC_Prescaler_Div2) || \ + ((PRESCALER) == ADC_Prescaler_Div4) || \ + ((PRESCALER) == ADC_Prescaler_Div6) || \ + ((PRESCALER) == ADC_Prescaler_Div8)) +/** + * @} + */ + + +/** @defgroup ADC_Direct_memory_access_mode_for_multi_mode + * @{ + */ +#define ADC_DMAAccessMode_Disabled ((uint32_t)0x00000000) /* DMA mode disabled */ +#define ADC_DMAAccessMode_1 ((uint32_t)0x00004000) /* DMA mode 1 enabled (2 / 3 half-words one by one - 1 then 2 then 3)*/ +#define ADC_DMAAccessMode_2 ((uint32_t)0x00008000) /* DMA mode 2 enabled (2 / 3 half-words by pairs - 2&1 then 1&3 then 3&2)*/ +#define ADC_DMAAccessMode_3 ((uint32_t)0x0000C000) /* DMA mode 3 enabled (2 / 3 bytes by pairs - 2&1 then 1&3 then 3&2) */ +#define IS_ADC_DMA_ACCESS_MODE(MODE) (((MODE) == ADC_DMAAccessMode_Disabled) || \ + ((MODE) == ADC_DMAAccessMode_1) || \ + ((MODE) == ADC_DMAAccessMode_2) || \ + ((MODE) == ADC_DMAAccessMode_3)) + +/** + * @} + */ + + +/** @defgroup ADC_delay_between_2_sampling_phases + * @{ + */ +#define ADC_TwoSamplingDelay_5Cycles ((uint32_t)0x00000000) +#define ADC_TwoSamplingDelay_6Cycles ((uint32_t)0x00000100) +#define ADC_TwoSamplingDelay_7Cycles ((uint32_t)0x00000200) +#define ADC_TwoSamplingDelay_8Cycles ((uint32_t)0x00000300) +#define ADC_TwoSamplingDelay_9Cycles ((uint32_t)0x00000400) +#define ADC_TwoSamplingDelay_10Cycles ((uint32_t)0x00000500) +#define ADC_TwoSamplingDelay_11Cycles ((uint32_t)0x00000600) +#define ADC_TwoSamplingDelay_12Cycles ((uint32_t)0x00000700) +#define ADC_TwoSamplingDelay_13Cycles ((uint32_t)0x00000800) +#define ADC_TwoSamplingDelay_14Cycles ((uint32_t)0x00000900) +#define ADC_TwoSamplingDelay_15Cycles ((uint32_t)0x00000A00) +#define ADC_TwoSamplingDelay_16Cycles ((uint32_t)0x00000B00) +#define ADC_TwoSamplingDelay_17Cycles ((uint32_t)0x00000C00) +#define ADC_TwoSamplingDelay_18Cycles ((uint32_t)0x00000D00) +#define ADC_TwoSamplingDelay_19Cycles ((uint32_t)0x00000E00) +#define ADC_TwoSamplingDelay_20Cycles ((uint32_t)0x00000F00) +#define IS_ADC_SAMPLING_DELAY(DELAY) (((DELAY) == ADC_TwoSamplingDelay_5Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_6Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_7Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_8Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_9Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_10Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_11Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_12Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_13Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_14Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_15Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_16Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_17Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_18Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_19Cycles) || \ + ((DELAY) == ADC_TwoSamplingDelay_20Cycles)) + +/** + * @} + */ + + +/** @defgroup ADC_resolution + * @{ + */ +#define ADC_Resolution_12b ((uint32_t)0x00000000) +#define ADC_Resolution_10b ((uint32_t)0x01000000) +#define ADC_Resolution_8b ((uint32_t)0x02000000) +#define ADC_Resolution_6b ((uint32_t)0x03000000) +#define IS_ADC_RESOLUTION(RESOLUTION) (((RESOLUTION) == ADC_Resolution_12b) || \ + ((RESOLUTION) == ADC_Resolution_10b) || \ + ((RESOLUTION) == ADC_Resolution_8b) || \ + ((RESOLUTION) == ADC_Resolution_6b)) + +/** + * @} + */ + + +/** @defgroup ADC_external_trigger_edge_for_regular_channels_conversion + * @{ + */ +#define ADC_ExternalTrigConvEdge_None ((uint32_t)0x00000000) +#define ADC_ExternalTrigConvEdge_Rising ((uint32_t)0x10000000) +#define ADC_ExternalTrigConvEdge_Falling ((uint32_t)0x20000000) +#define ADC_ExternalTrigConvEdge_RisingFalling ((uint32_t)0x30000000) +#define IS_ADC_EXT_TRIG_EDGE(EDGE) (((EDGE) == ADC_ExternalTrigConvEdge_None) || \ + ((EDGE) == ADC_ExternalTrigConvEdge_Rising) || \ + ((EDGE) == ADC_ExternalTrigConvEdge_Falling) || \ + ((EDGE) == ADC_ExternalTrigConvEdge_RisingFalling)) +/** + * @} + */ + + +/** @defgroup ADC_extrenal_trigger_sources_for_regular_channels_conversion + * @{ + */ +#define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000) +#define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x01000000) +#define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x02000000) +#define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x03000000) +#define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x04000000) +#define ADC_ExternalTrigConv_T2_CC4 ((uint32_t)0x05000000) +#define ADC_ExternalTrigConv_T2_TRGO ((uint32_t)0x06000000) +#define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x07000000) +#define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x08000000) +#define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x09000000) +#define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x0A000000) +#define ADC_ExternalTrigConv_T5_CC2 ((uint32_t)0x0B000000) +#define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x0C000000) +#define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x0D000000) +#define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x0E000000) +#define ADC_ExternalTrigConv_Ext_IT11 ((uint32_t)0x0F000000) +#define IS_ADC_EXT_TRIG(REGTRIG) (((REGTRIG) == ADC_ExternalTrigConv_T1_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T1_CC2) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T1_CC3) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T2_CC2) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T2_CC3) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T2_CC4) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T2_TRGO) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T3_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T3_TRGO) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T4_CC4) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T5_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T5_CC2) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T5_CC3) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T8_CC1) || \ + ((REGTRIG) == ADC_ExternalTrigConv_T8_TRGO) || \ + ((REGTRIG) == ADC_ExternalTrigConv_Ext_IT11)) +/** + * @} + */ + + +/** @defgroup ADC_data_align + * @{ + */ +#define ADC_DataAlign_Right ((uint32_t)0x00000000) +#define ADC_DataAlign_Left ((uint32_t)0x00000800) +#define IS_ADC_DATA_ALIGN(ALIGN) (((ALIGN) == ADC_DataAlign_Right) || \ + ((ALIGN) == ADC_DataAlign_Left)) +/** + * @} + */ + + +/** @defgroup ADC_channels + * @{ + */ +#define ADC_Channel_0 ((uint8_t)0x00) +#define ADC_Channel_1 ((uint8_t)0x01) +#define ADC_Channel_2 ((uint8_t)0x02) +#define ADC_Channel_3 ((uint8_t)0x03) +#define ADC_Channel_4 ((uint8_t)0x04) +#define ADC_Channel_5 ((uint8_t)0x05) +#define ADC_Channel_6 ((uint8_t)0x06) +#define ADC_Channel_7 ((uint8_t)0x07) +#define ADC_Channel_8 ((uint8_t)0x08) +#define ADC_Channel_9 ((uint8_t)0x09) +#define ADC_Channel_10 ((uint8_t)0x0A) +#define ADC_Channel_11 ((uint8_t)0x0B) +#define ADC_Channel_12 ((uint8_t)0x0C) +#define ADC_Channel_13 ((uint8_t)0x0D) +#define ADC_Channel_14 ((uint8_t)0x0E) +#define ADC_Channel_15 ((uint8_t)0x0F) +#define ADC_Channel_16 ((uint8_t)0x10) +#define ADC_Channel_17 ((uint8_t)0x11) +#define ADC_Channel_18 ((uint8_t)0x12) + +#if defined (STM32F40_41xxx) +#define ADC_Channel_TempSensor ((uint8_t)ADC_Channel_16) +#endif /* STM32F40_41xxx */ + +#if defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx) || defined (STM32F411xE) +#define ADC_Channel_TempSensor ((uint8_t)ADC_Channel_18) +#endif /* STM32F427_437xx || STM32F429_439xx || STM32F401xx || STM32F411xE */ + +#define ADC_Channel_Vrefint ((uint8_t)ADC_Channel_17) +#define ADC_Channel_Vbat ((uint8_t)ADC_Channel_18) + +#define IS_ADC_CHANNEL(CHANNEL) (((CHANNEL) == ADC_Channel_0) || \ + ((CHANNEL) == ADC_Channel_1) || \ + ((CHANNEL) == ADC_Channel_2) || \ + ((CHANNEL) == ADC_Channel_3) || \ + ((CHANNEL) == ADC_Channel_4) || \ + ((CHANNEL) == ADC_Channel_5) || \ + ((CHANNEL) == ADC_Channel_6) || \ + ((CHANNEL) == ADC_Channel_7) || \ + ((CHANNEL) == ADC_Channel_8) || \ + ((CHANNEL) == ADC_Channel_9) || \ + ((CHANNEL) == ADC_Channel_10) || \ + ((CHANNEL) == ADC_Channel_11) || \ + ((CHANNEL) == ADC_Channel_12) || \ + ((CHANNEL) == ADC_Channel_13) || \ + ((CHANNEL) == ADC_Channel_14) || \ + ((CHANNEL) == ADC_Channel_15) || \ + ((CHANNEL) == ADC_Channel_16) || \ + ((CHANNEL) == ADC_Channel_17) || \ + ((CHANNEL) == ADC_Channel_18)) +/** + * @} + */ + + +/** @defgroup ADC_sampling_times + * @{ + */ +#define ADC_SampleTime_3Cycles ((uint8_t)0x00) +#define ADC_SampleTime_15Cycles ((uint8_t)0x01) +#define ADC_SampleTime_28Cycles ((uint8_t)0x02) +#define ADC_SampleTime_56Cycles ((uint8_t)0x03) +#define ADC_SampleTime_84Cycles ((uint8_t)0x04) +#define ADC_SampleTime_112Cycles ((uint8_t)0x05) +#define ADC_SampleTime_144Cycles ((uint8_t)0x06) +#define ADC_SampleTime_480Cycles ((uint8_t)0x07) +#define IS_ADC_SAMPLE_TIME(TIME) (((TIME) == ADC_SampleTime_3Cycles) || \ + ((TIME) == ADC_SampleTime_15Cycles) || \ + ((TIME) == ADC_SampleTime_28Cycles) || \ + ((TIME) == ADC_SampleTime_56Cycles) || \ + ((TIME) == ADC_SampleTime_84Cycles) || \ + ((TIME) == ADC_SampleTime_112Cycles) || \ + ((TIME) == ADC_SampleTime_144Cycles) || \ + ((TIME) == ADC_SampleTime_480Cycles)) +/** + * @} + */ + + +/** @defgroup ADC_external_trigger_edge_for_injected_channels_conversion + * @{ + */ +#define ADC_ExternalTrigInjecConvEdge_None ((uint32_t)0x00000000) +#define ADC_ExternalTrigInjecConvEdge_Rising ((uint32_t)0x00100000) +#define ADC_ExternalTrigInjecConvEdge_Falling ((uint32_t)0x00200000) +#define ADC_ExternalTrigInjecConvEdge_RisingFalling ((uint32_t)0x00300000) +#define IS_ADC_EXT_INJEC_TRIG_EDGE(EDGE) (((EDGE) == ADC_ExternalTrigInjecConvEdge_None) || \ + ((EDGE) == ADC_ExternalTrigInjecConvEdge_Rising) || \ + ((EDGE) == ADC_ExternalTrigInjecConvEdge_Falling) || \ + ((EDGE) == ADC_ExternalTrigInjecConvEdge_RisingFalling)) + +/** + * @} + */ + + +/** @defgroup ADC_extrenal_trigger_sources_for_injected_channels_conversion + * @{ + */ +#define ADC_ExternalTrigInjecConv_T1_CC4 ((uint32_t)0x00000000) +#define ADC_ExternalTrigInjecConv_T1_TRGO ((uint32_t)0x00010000) +#define ADC_ExternalTrigInjecConv_T2_CC1 ((uint32_t)0x00020000) +#define ADC_ExternalTrigInjecConv_T2_TRGO ((uint32_t)0x00030000) +#define ADC_ExternalTrigInjecConv_T3_CC2 ((uint32_t)0x00040000) +#define ADC_ExternalTrigInjecConv_T3_CC4 ((uint32_t)0x00050000) +#define ADC_ExternalTrigInjecConv_T4_CC1 ((uint32_t)0x00060000) +#define ADC_ExternalTrigInjecConv_T4_CC2 ((uint32_t)0x00070000) +#define ADC_ExternalTrigInjecConv_T4_CC3 ((uint32_t)0x00080000) +#define ADC_ExternalTrigInjecConv_T4_TRGO ((uint32_t)0x00090000) +#define ADC_ExternalTrigInjecConv_T5_CC4 ((uint32_t)0x000A0000) +#define ADC_ExternalTrigInjecConv_T5_TRGO ((uint32_t)0x000B0000) +#define ADC_ExternalTrigInjecConv_T8_CC2 ((uint32_t)0x000C0000) +#define ADC_ExternalTrigInjecConv_T8_CC3 ((uint32_t)0x000D0000) +#define ADC_ExternalTrigInjecConv_T8_CC4 ((uint32_t)0x000E0000) +#define ADC_ExternalTrigInjecConv_Ext_IT15 ((uint32_t)0x000F0000) +#define IS_ADC_EXT_INJEC_TRIG(INJTRIG) (((INJTRIG) == ADC_ExternalTrigInjecConv_T1_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T1_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T2_CC1) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T2_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T3_CC2) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T3_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC1) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC2) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC3) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T5_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T5_TRGO) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC2) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC3) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC4) || \ + ((INJTRIG) == ADC_ExternalTrigInjecConv_Ext_IT15)) +/** + * @} + */ + + +/** @defgroup ADC_injected_channel_selection + * @{ + */ +#define ADC_InjectedChannel_1 ((uint8_t)0x14) +#define ADC_InjectedChannel_2 ((uint8_t)0x18) +#define ADC_InjectedChannel_3 ((uint8_t)0x1C) +#define ADC_InjectedChannel_4 ((uint8_t)0x20) +#define IS_ADC_INJECTED_CHANNEL(CHANNEL) (((CHANNEL) == ADC_InjectedChannel_1) || \ + ((CHANNEL) == ADC_InjectedChannel_2) || \ + ((CHANNEL) == ADC_InjectedChannel_3) || \ + ((CHANNEL) == ADC_InjectedChannel_4)) +/** + * @} + */ + + +/** @defgroup ADC_analog_watchdog_selection + * @{ + */ +#define ADC_AnalogWatchdog_SingleRegEnable ((uint32_t)0x00800200) +#define ADC_AnalogWatchdog_SingleInjecEnable ((uint32_t)0x00400200) +#define ADC_AnalogWatchdog_SingleRegOrInjecEnable ((uint32_t)0x00C00200) +#define ADC_AnalogWatchdog_AllRegEnable ((uint32_t)0x00800000) +#define ADC_AnalogWatchdog_AllInjecEnable ((uint32_t)0x00400000) +#define ADC_AnalogWatchdog_AllRegAllInjecEnable ((uint32_t)0x00C00000) +#define ADC_AnalogWatchdog_None ((uint32_t)0x00000000) +#define IS_ADC_ANALOG_WATCHDOG(WATCHDOG) (((WATCHDOG) == ADC_AnalogWatchdog_SingleRegEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_SingleInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_SingleRegOrInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_AllRegEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_AllInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_AllRegAllInjecEnable) || \ + ((WATCHDOG) == ADC_AnalogWatchdog_None)) +/** + * @} + */ + + +/** @defgroup ADC_interrupts_definition + * @{ + */ +#define ADC_IT_EOC ((uint16_t)0x0205) +#define ADC_IT_AWD ((uint16_t)0x0106) +#define ADC_IT_JEOC ((uint16_t)0x0407) +#define ADC_IT_OVR ((uint16_t)0x201A) +#define IS_ADC_IT(IT) (((IT) == ADC_IT_EOC) || ((IT) == ADC_IT_AWD) || \ + ((IT) == ADC_IT_JEOC)|| ((IT) == ADC_IT_OVR)) +/** + * @} + */ + + +/** @defgroup ADC_flags_definition + * @{ + */ +#define ADC_FLAG_AWD ((uint8_t)0x01) +#define ADC_FLAG_EOC ((uint8_t)0x02) +#define ADC_FLAG_JEOC ((uint8_t)0x04) +#define ADC_FLAG_JSTRT ((uint8_t)0x08) +#define ADC_FLAG_STRT ((uint8_t)0x10) +#define ADC_FLAG_OVR ((uint8_t)0x20) + +#define IS_ADC_CLEAR_FLAG(FLAG) ((((FLAG) & (uint8_t)0xC0) == 0x00) && ((FLAG) != 0x00)) +#define IS_ADC_GET_FLAG(FLAG) (((FLAG) == ADC_FLAG_AWD) || \ + ((FLAG) == ADC_FLAG_EOC) || \ + ((FLAG) == ADC_FLAG_JEOC) || \ + ((FLAG)== ADC_FLAG_JSTRT) || \ + ((FLAG) == ADC_FLAG_STRT) || \ + ((FLAG)== ADC_FLAG_OVR)) +/** + * @} + */ + + +/** @defgroup ADC_thresholds + * @{ + */ +#define IS_ADC_THRESHOLD(THRESHOLD) ((THRESHOLD) <= 0xFFF) +/** + * @} + */ + + +/** @defgroup ADC_injected_offset + * @{ + */ +#define IS_ADC_OFFSET(OFFSET) ((OFFSET) <= 0xFFF) +/** + * @} + */ + + +/** @defgroup ADC_injected_length + * @{ + */ +#define IS_ADC_INJECTED_LENGTH(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x4)) +/** + * @} + */ + + +/** @defgroup ADC_injected_rank + * @{ + */ +#define IS_ADC_INJECTED_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x4)) +/** + * @} + */ + + +/** @defgroup ADC_regular_length + * @{ + */ +#define IS_ADC_REGULAR_LENGTH(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x10)) +/** + * @} + */ + + +/** @defgroup ADC_regular_rank + * @{ + */ +#define IS_ADC_REGULAR_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x10)) +/** + * @} + */ + + +/** @defgroup ADC_regular_discontinuous_mode_number + * @{ + */ +#define IS_ADC_REGULAR_DISC_NUMBER(NUMBER) (((NUMBER) >= 0x1) && ((NUMBER) <= 0x8)) +/** + * @} + */ + + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/* Function used to set the ADC configuration to the default reset state *****/ +void ADC_DeInit(void); + +/* Initialization and Configuration functions *********************************/ +void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); +void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct); +void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct); +void ADC_CommonStructInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct); +void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); + +/* Analog Watchdog configuration functions ************************************/ +void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog); +void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,uint16_t LowThreshold); +void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel); + +/* Temperature Sensor, Vrefint and VBAT management functions ******************/ +void ADC_TempSensorVrefintCmd(FunctionalState NewState); +void ADC_VBATCmd(FunctionalState NewState); + +/* Regular Channels Configuration functions ***********************************/ +void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_SoftwareStartConv(ADC_TypeDef* ADCx); +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx); +void ADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number); +void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx); +uint32_t ADC_GetMultiModeConversionValue(void); + +/* Regular Channels DMA Configuration functions *******************************/ +void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_MultiModeDMARequestAfterLastTransferCmd(FunctionalState NewState); + +/* Injected channels Configuration functions **********************************/ +void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length); +void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset); +void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv); +void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge); +void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx); +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx); +void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel); + +/* Interrupts and flags management functions **********************************/ +void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState); +FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); +void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); +ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT); +void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F4xx_ADC_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_conf.h b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_conf.h index b6e0204bb..70757dae2 100644 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_conf.h +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_conf.h @@ -80,7 +80,7 @@ Modification: /* Uncomment the line below to expanse the "assert_param" macro in the Standard Peripheral Library drivers code */ -#define USE_FULL_ASSERT 1 +// #define USE_FULL_ASSERT 1 /* Exported macro ------------------------------------------------------------*/ #ifdef USE_FULL_ASSERT diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_dac.h b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_dac.h index 8ac5d55c0..2918dc7c6 100644 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_dac.h +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/hardware_dac.h @@ -2,30 +2,36 @@ ****************************************************************************** * @file stm32f4xx_dac.h * @author MCD Application Team - * @version V1.0.0 - * @date 30-September-2011 + * @version V1.4.0 + * @date 04-August-2014 * @brief This file contains all the functions prototypes for the DAC firmware * library. ****************************************************************************** * @attention * - * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS - * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE - * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY - * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING - * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE - * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - *

© COPYRIGHT 2011 STMicroelectronics

****************************************************************************** */ /** * @file: hardware_dac.h * @brief: define hardware dac function -* @version: 1.0 +* @version: 2.0 * @author: AIIT XUOS Lab -* @date: 2021/4/25 +* @date: 2022/1/10 */ /************************************************* @@ -33,7 +39,7 @@ File name: hardware_dac.h Description: define hardware dac function Others: History: -1. Date: 2021-04-25 +1. Date: 2022-1-10 Author: AIIT XUOS Lab Modification: 1. rename stm32f4xx_dac.h for XiUOS @@ -48,7 +54,7 @@ Modification: #endif /* Includes ------------------------------------------------------------------*/ -#include +#include "stm32f4xx.h" /** @addtogroup STM32F4xx_StdPeriph_Driver * @{ @@ -314,4 +320,4 @@ void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT); * @} */ -/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/uart/Kconfig b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/uart/Kconfig index 79ce0890c..c9a07f334 100644 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/uart/Kconfig +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/uart/Kconfig @@ -9,8 +9,11 @@ menuconfig BSP_USING_USART1 string "serial bus 1 driver name" default "usart1_drv" config SERIAL_1_DEVICE_NAME_0 - string "serial bus 1 device 0 name" - default "usart1_dev1" + string "serial bus 1 device 0 name" + default "usart1_dev1" + config USART1_USING_DMA + bool "usart1 using DMA" + default n endif menuconfig BSP_USING_USART2 @@ -24,8 +27,11 @@ menuconfig BSP_USING_USART2 string "serial bus 2 driver name" default "usart2_drv" config SERIAL_2_DEVICE_NAME_0 - string "serial bus 2 device 0 name" - default "usart2_dev2" + string "serial bus 2 device 0 name" + default "usart2_dev2" + config USART2_USING_DMA + bool "usart2 using DMA" + default n endif menuconfig BSP_USING_USART3 @@ -39,8 +45,11 @@ menuconfig BSP_USING_USART3 string "serial bus 3 driver name" default "usart3_drv" config SERIAL_3_DEVICE_NAME_0 - string "serial bus 3 device 0 name" - default "usart3_dev3" + string "serial bus 3 device 0 name" + default "usart3_dev3" + config USART3_USING_DMA + bool "usart3 using DMA" + default n endif menuconfig BSP_USING_UART4 @@ -54,8 +63,11 @@ menuconfig BSP_USING_UART4 string "serial bus 4 driver name" default "uart4_drv" config SERIAL_4_DEVICE_NAME_0 - string "serial bus 4 device 0 name" - default "uart4_dev4" + string "serial bus 4 device 0 name" + default "uart4_dev4" + config USART4_USING_DMA + bool "usart4 using DMA" + default n endif menuconfig BSP_USING_UART5 @@ -69,6 +81,9 @@ menuconfig BSP_USING_UART5 string "serial bus 5 driver name" default "uart5_drv" config SERIAL_5_DEVICE_NAME_0 - string "serial bus 5 device 0 name" - default "uart5_dev5" + string "serial bus 5 device 0 name" + default "uart5_dev5" + config USART5_USING_DMA + bool "usart5 using DMA" + default n endif diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/uart/connect_usart.c b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/uart/connect_usart.c index 9ff17887b..b10ea6cba 100644 --- a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/uart/connect_usart.c +++ b/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/uart/connect_usart.c @@ -280,7 +280,7 @@ static uint32 Stm32SerialInit(struct SerialDriver *serial_drv, struct BusConfigu USART_InitStructure.USART_WordLength = USART_WordLength_9b; } - if (serial_cfg->data_cfg.serial_stop_bits == STOP_BITS_1){ + if (serial_cfg->data_cfg.serial_stop_bits == STOP_BITS_1) { USART_InitStructure.USART_StopBits = USART_StopBits_1; } else if (serial_cfg->data_cfg.serial_stop_bits == STOP_BITS_2) { USART_InitStructure.USART_StopBits = USART_StopBits_2; @@ -323,7 +323,7 @@ static uint32 Stm32SerialConfigure(struct SerialDriver *serial_drv, int serial_o USART_ITConfig(serial_hw_cfg->uart_device, USART_IT_RXNE, ENABLE); break; case OPER_CONFIG : - if (SIGN_OPER_DMA_RX == serial_dev_param->serial_set_mode){ + if (SIGN_OPER_DMA_RX == serial_dev_param->serial_set_mode) { DMAConfiguration(serial_dev, serial_hw_cfg->uart_device); } } @@ -378,8 +378,16 @@ static void DmaRxDoneIsr(struct Stm32Usart *serial, struct SerialDriver *serial_ if (DMA_GetFlagStatus(dma->RxStream, dma->RxFlag) != RESET) { x_base level = CriticalAreaLock(); - x_size_t recv_len = dma->SettingRecvLen - dma->LastRecvIndex; - dma->LastRecvIndex = 0; + x_size_t recv_len; + + x_size_t recv_total_index = dma->SettingRecvLen - DMA_GetCurrDataCounter(dma->RxStream); + if (0 != recv_total_index) { + recv_len = recv_total_index - dma->LastRecvIndex; + } else { + recv_len = dma->SettingRecvLen - dma->LastRecvIndex; + } + dma->LastRecvIndex = recv_total_index; + CriticalAreaUnLock(level); if (recv_len) SerialSetIsr(serial_dev, SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); @@ -397,15 +405,14 @@ static void UartIsr(struct Stm32Usart *serial, struct SerialDriver *serial_drv, if (USART_GetITStatus(serial_hw_cfg->uart_device, USART_IT_RXNE) != RESET) { SerialSetIsr(serial_dev, SERIAL_EVENT_RX_IND); USART_ClearITPendingBit(serial_hw_cfg->uart_device, USART_IT_RXNE); - } - if (USART_GetITStatus(serial_hw_cfg->uart_device, USART_IT_IDLE) != RESET) { + } else if (USART_GetITStatus(serial_hw_cfg->uart_device, USART_IT_IDLE) != RESET) { DmaUartRxIdleIsr(serial_dev, dma, serial_hw_cfg->uart_device); - } - if (USART_GetITStatus(serial_hw_cfg->uart_device, USART_IT_TC) != RESET) { + } else if (USART_GetITStatus(serial_hw_cfg->uart_device, USART_IT_TC) != RESET) { USART_ClearITPendingBit(serial_hw_cfg->uart_device, USART_IT_TC); - } - if (USART_GetFlagStatus(serial_hw_cfg->uart_device, USART_FLAG_ORE) == SET) { - USART_ReceiveData(serial_hw_cfg->uart_device); + } else { + if (USART_GetFlagStatus(serial_hw_cfg->uart_device, USART_FLAG_ORE) == SET) { + USART_ReceiveData(serial_hw_cfg->uart_device); + } } } @@ -673,6 +680,9 @@ int Stm32HwUsartInit(void) serial_driver_1.private_data = (void *)&serial_cfg_1; serial_dev_param_1.serial_work_mode = SIGN_OPER_INT_RX; +#ifdef USART1_USING_DMA + serial_dev_param_1.serial_work_mode = SIGN_OPER_DMA_RX; +#endif serial_device_1.haldev.private_data = (void *)&serial_dev_param_1; NVIC_Configuration(serial_hw_cfg_1.irq); @@ -714,6 +724,9 @@ int Stm32HwUsartInit(void) serial_driver_2.private_data = (void *)&serial_cfg_2; serial_dev_param_2.serial_work_mode = SIGN_OPER_INT_RX; +#ifdef USART2_USING_DMA + serial_dev_param_2.serial_work_mode = SIGN_OPER_DMA_RX; +#endif serial_device_2.haldev.private_data = (void *)&serial_dev_param_2; NVIC_Configuration(serial_hw_cfg_2.irq); @@ -755,6 +768,9 @@ int Stm32HwUsartInit(void) serial_driver_3.private_data = (void *)&serial_cfg_3; serial_dev_param_3.serial_work_mode = SIGN_OPER_INT_RX; +#ifdef USART3_USING_DMA + serial_dev_param_3.serial_work_mode = SIGN_OPER_DMA_RX; +#endif serial_device_3.haldev.private_data = (void *)&serial_dev_param_3; NVIC_Configuration(serial_hw_cfg_3.irq); @@ -796,6 +812,9 @@ int Stm32HwUsartInit(void) serial_driver_4.private_data = (void *)&serial_cfg_4; serial_dev_param_4.serial_work_mode = SIGN_OPER_INT_RX; +#ifdef USART4_USING_DMA + serial_dev_param_4.serial_work_mode = SIGN_OPER_DMA_RX; +#endif serial_device_4.haldev.private_data = (void *)&serial_dev_param_4; NVIC_Configuration(serial_hw_cfg_4.irq); @@ -837,6 +856,9 @@ int Stm32HwUsartInit(void) serial_driver_5.private_data = (void *)&serial_cfg_5; serial_dev_param_5.serial_work_mode = SIGN_OPER_INT_RX; +#ifdef USART5_USING_DMA + serial_dev_param_5.serial_work_mode = SIGN_OPER_DMA_RX; +#endif serial_device_5.haldev.private_data = (void *)&serial_dev_param_5; NVIC_Configuration(serial_hw_cfg_5.irq); diff --git a/Ubiquitous/XiUOS/kernel/kernel_test/test_serial.c b/Ubiquitous/XiUOS/kernel/kernel_test/test_serial.c index 8fbd0cf61..f810be149 100644 --- a/Ubiquitous/XiUOS/kernel/kernel_test/test_serial.c +++ b/Ubiquitous/XiUOS/kernel/kernel_test/test_serial.c @@ -66,11 +66,13 @@ static void TestSerialRecvTask(void *parameter) read_param.buffer = &recv_data; read_param.read_length = 0; + KPrintf("ready to read data\n"); BusDevReadData(bus_device, &read_param); for (i = 0; i < read_param.read_length; i ++) { KPrintf("TestSerialRecvTask i %d char 0x%x\n", i, recv_data); } + KPrintf("send data %c\n", recv_data); write_param.buffer = &recv_data; write_param.size = 1; BusDevWriteData(bus_device, &write_param); @@ -141,7 +143,8 @@ static int SerialBusCheck(const char *bus_name, const char *driver_name, const c bus->match(bus_driver, bus_device); /*step 3: open bus_device, configure struct SerialDevParam if necessary*/ - serial_dev_param->serial_set_mode = SIGN_OPER_INT_RX; + serial_dev_param->serial_set_mode = 0; + serial_dev_param->serial_work_mode = SIGN_OPER_DMA_RX;//SIGN_OPER_INT_RX; serial_dev_param->serial_stream_mode = SIGN_OPER_STREAM; BusDevOpen(bus_device); KPrintf("BusDevOpen done\n"); diff --git a/Ubiquitous/XiUOS/resources/Kconfig b/Ubiquitous/XiUOS/resources/Kconfig index cb3eccf29..e41b96df9 100644 --- a/Ubiquitous/XiUOS/resources/Kconfig +++ b/Ubiquitous/XiUOS/resources/Kconfig @@ -151,3 +151,15 @@ if BSP_USING_WDT bool "Using Watch Dog bus drivers" default n endif + +if BSP_USING_ADC + config RESOURCES_ADC + bool "Using ADC bus drivers" + default n +endif + +if BSP_USING_DAC + config RESOURCES_DAC + bool "Using DAC bus drivers" + default n +endif diff --git a/Ubiquitous/XiUOS/resources/Makefile b/Ubiquitous/XiUOS/resources/Makefile index fd98f6dee..d270dd528 100644 --- a/Ubiquitous/XiUOS/resources/Makefile +++ b/Ubiquitous/XiUOS/resources/Makefile @@ -57,4 +57,12 @@ ifeq ($(CONFIG_RESOURCES_WDT),y) SRC_DIR += watchdog endif +ifeq ($(CONFIG_RESOURCES_ADC),y) + SRC_DIR += adc +endif + +ifeq ($(CONFIG_RESOURCES_DAC),y) + SRC_DIR += dac +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/resources/adc/Makefile b/Ubiquitous/XiUOS/resources/adc/Makefile new file mode 100644 index 000000000..32f131753 --- /dev/null +++ b/Ubiquitous/XiUOS/resources/adc/Makefile @@ -0,0 +1,3 @@ +SRC_FILES += dev_adc.c drv_adc.c bus_adc.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/resources/adc/bus_adc.c b/Ubiquitous/XiUOS/resources/adc/bus_adc.c new file mode 100644 index 000000000..c3231899d --- /dev/null +++ b/Ubiquitous/XiUOS/resources/adc/bus_adc.c @@ -0,0 +1,122 @@ +/* +* 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 bus_adc.c +* @brief register adc bus function using bus driver framework +* @version 1.1 +* @author AIIT XUOS Lab +* @date 2021-12-28 +*/ + +#include +#include + +/*Register the ADC BUS*/ +int AdcBusInit(struct AdcBus *adc_bus, const char *bus_name) +{ + NULL_PARAM_CHECK(adc_bus); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + if (BUS_INSTALL != adc_bus->bus.bus_state) { + strncpy(adc_bus->bus.bus_name, bus_name, NAME_NUM_MAX); + + adc_bus->bus.bus_type = TYPE_ADC_BUS; + adc_bus->bus.bus_state = BUS_INSTALL; + adc_bus->bus.private_data = adc_bus->private_data; + + ret = BusRegister(&adc_bus->bus); + if (EOK != ret) { + KPrintf("AdcBusInit BusRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("AdcBusInit BusRegister bus has been register state%u\n", adc_bus->bus.bus_state); + } + + return ret; +} + +/*Register the ADC Driver*/ +int AdcDriverInit(struct AdcDriver *adc_driver, const char *driver_name) +{ + NULL_PARAM_CHECK(adc_driver); + NULL_PARAM_CHECK(driver_name); + + x_err_t ret = EOK; + + if (DRV_INSTALL != adc_driver->driver.driver_state) { + adc_driver->driver.driver_type = TYPE_ADC_DRV; + adc_driver->driver.driver_state = DRV_INSTALL; + + strncpy(adc_driver->driver.drv_name, driver_name, NAME_NUM_MAX); + + adc_driver->driver.configure = adc_driver->configure; + adc_driver->driver.private_data = adc_driver->private_data; + + ret = AdcDriverRegister(&adc_driver->driver); + if (EOK != ret) { + KPrintf("AdcDriverInit DriverRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("AdcDriverInit DriverRegister driver has been register state%u\n", adc_driver->driver.driver_state); + } + + return ret; +} + +/*Release the ADC device*/ +int AdcReleaseBus(struct AdcBus *adc_bus) +{ + NULL_PARAM_CHECK(adc_bus); + + return BusRelease(&adc_bus->bus); +} + +/*Register the ADC Driver to the ADC BUS*/ +int AdcDriverAttachToBus(const char *drv_name, const char *bus_name) +{ + NULL_PARAM_CHECK(drv_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct Driver *driver; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("AdcDriverAttachToBus find adc bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_ADC_BUS == bus->bus_type) { + driver = AdcDriverFind(drv_name, TYPE_ADC_DRV); + if (NONE == driver) { + KPrintf("AdcDriverAttachToBus find adc driver error!name %s\n", drv_name); + return ERROR; + } + + if (TYPE_ADC_DRV == driver->driver_type) { + ret = DriverRegisterToBus(bus, driver); + if (EOK != ret) { + KPrintf("AdcDriverAttachToBus DriverRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return ret; +} diff --git a/Ubiquitous/XiUOS/resources/adc/dev_adc.c b/Ubiquitous/XiUOS/resources/adc/dev_adc.c new file mode 100644 index 000000000..29fdfb49d --- /dev/null +++ b/Ubiquitous/XiUOS/resources/adc/dev_adc.c @@ -0,0 +1,119 @@ +/* +* 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 dev_adc.c +* @brief register adc dev function using bus driver framework +* @version 1.1 +* @author AIIT XUOS Lab +* @date 2021-12-28 +*/ + +#include +#include + +static DoubleLinklistType adcdev_linklist; + +/*Create the ADC device linklist*/ +static void AdcDeviceLinkInit() +{ + InitDoubleLinkList(&adcdev_linklist); +} + +/*Find the register ADC device*/ +HardwareDevType AdcDeviceFind(const char *dev_name, enum DevType dev_type) +{ + NULL_PARAM_CHECK(dev_name); + + struct HardwareDev *device = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &adcdev_linklist; + for (node = head->node_next; node != head; node = node->node_next) { + device = SYS_DOUBLE_LINKLIST_ENTRY(node, struct HardwareDev, dev_link); + if ((!strcmp(device->dev_name, dev_name)) && (dev_type == device->dev_type)) { + return device; + } + } + + KPrintf("AdcDeviceFind adcnot find the %s device.return NULL\n", dev_name); + return NONE; +} + +/*Register the ADC device*/ +int AdcDeviceRegister(struct AdcHardwareDevice *adc_device, void *adc_param, const char *device_name) +{ + NULL_PARAM_CHECK(adc_device); + NULL_PARAM_CHECK(device_name); + + x_err_t ret = EOK; + static x_bool dev_link_flag = RET_FALSE; + + if (!dev_link_flag) { + AdcDeviceLinkInit(); + dev_link_flag = RET_TRUE; + } + + if (DEV_INSTALL != adc_device->haldev.dev_state) { + strncpy(adc_device->haldev.dev_name, device_name, NAME_NUM_MAX); + adc_device->haldev.dev_type = TYPE_ADC_DEV; + adc_device->haldev.dev_state = DEV_INSTALL; + + adc_device->haldev.dev_done = (struct HalDevDone *)adc_device->adc_dev_done; + + adc_device->haldev.private_data = adc_param; + + DoubleLinkListInsertNodeAfter(&adcdev_linklist, &(adc_device->haldev.dev_link)); + } else { + KPrintf("AdcDeviceRegister device has been register state%u\n", adc_device->haldev.dev_state); + } + + return ret; +} + +/*Register the ADC Device to the ADC BUS*/ +int AdcDeviceAttachToBus(const char *dev_name, const char *bus_name) +{ + NULL_PARAM_CHECK(dev_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct HardwareDev *device; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("AdcDeviceAttachToBus find adc bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_ADC_BUS == bus->bus_type) { + device = AdcDeviceFind(dev_name, TYPE_ADC_DEV); + + if (NONE == device) { + KPrintf("AdcDeviceAttachToBus find adc device error!name %s\n", dev_name); + return ERROR; + } + + if (TYPE_ADC_DEV == device->dev_type) { + ret = DeviceRegisterToBus(bus, device); + + if (EOK != ret) { + KPrintf("AdcDeviceAttachToBus DeviceRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return EOK; +} diff --git a/Ubiquitous/XiUOS/resources/adc/drv_adc.c b/Ubiquitous/XiUOS/resources/adc/drv_adc.c new file mode 100644 index 000000000..e96ebb411 --- /dev/null +++ b/Ubiquitous/XiUOS/resources/adc/drv_adc.c @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file drv_adc.c +* @brief register adc drv function using bus driver framework +* @version 1.1 +* @author AIIT XUOS Lab +* @date 2021-12-28 +*/ + +#include +#include + +static DoubleLinklistType adcdrv_linklist; + +/*Create the driver linklist*/ +static void AdcDrvLinkInit() +{ + InitDoubleLinkList(&adcdrv_linklist); +} + +/*Find the regiter driver*/ +DriverType AdcDriverFind(const char *drv_name, enum DriverType_e drv_type) +{ + NULL_PARAM_CHECK(drv_name); + + struct Driver *driver = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &adcdrv_linklist; + + for (node = head->node_next; node != head; node = node->node_next) { + driver = SYS_DOUBLE_LINKLIST_ENTRY(node, struct Driver, driver_link); + if ((!strcmp(driver->drv_name, drv_name)) && (drv_type == driver->driver_type)) { + return driver; + } + } + + KPrintf("AdcDriverFind cannot find the %s driver.return NULL\n", drv_name); + return NONE; +} + +/*Register the Driver, manage with the double linklist*/ +int AdcDriverRegister(struct Driver *driver) +{ + NULL_PARAM_CHECK(driver); + + x_err_t ret = EOK; + static x_bool driver_link_flag = RET_FALSE; + + if (!driver_link_flag) { + AdcDrvLinkInit(); + driver_link_flag = RET_TRUE; + } + + DoubleLinkListInsertNodeAfter(&adcdrv_linklist, &(driver->driver_link)); + + return ret; +} diff --git a/Ubiquitous/XiUOS/resources/dac/Makefile b/Ubiquitous/XiUOS/resources/dac/Makefile new file mode 100644 index 000000000..7b5fac03e --- /dev/null +++ b/Ubiquitous/XiUOS/resources/dac/Makefile @@ -0,0 +1,3 @@ +SRC_FILES += dev_dac.c drv_dac.c bus_dac.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/resources/dac/bus_dac.c b/Ubiquitous/XiUOS/resources/dac/bus_dac.c new file mode 100644 index 000000000..ef29455a5 --- /dev/null +++ b/Ubiquitous/XiUOS/resources/dac/bus_dac.c @@ -0,0 +1,122 @@ +/* +* 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 bus_dac.c +* @brief register dac bus function using bus driver framework +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-1-11 +*/ + +#include +#include + +/*Register the DAC BUS*/ +int DacBusInit(struct DacBus *dac_bus, const char *bus_name) +{ + NULL_PARAM_CHECK(dac_bus); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + if (BUS_INSTALL != dac_bus->bus.bus_state) { + strncpy(dac_bus->bus.bus_name, bus_name, NAME_NUM_MAX); + + dac_bus->bus.bus_type = TYPE_DAC_BUS; + dac_bus->bus.bus_state = BUS_INSTALL; + dac_bus->bus.private_data = dac_bus->private_data; + + ret = BusRegister(&dac_bus->bus); + if (EOK != ret) { + KPrintf("DacBusInit BusRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("DacBusInit BusRegister bus has been register state%u\n", dac_bus->bus.bus_state); + } + + return ret; +} + +/*Register the DAC Driver*/ +int DacDriverInit(struct DacDriver *dac_driver, const char *driver_name) +{ + NULL_PARAM_CHECK(dac_driver); + NULL_PARAM_CHECK(driver_name); + + x_err_t ret = EOK; + + if (DRV_INSTALL != dac_driver->driver.driver_state) { + dac_driver->driver.driver_type = TYPE_DAC_DRV; + dac_driver->driver.driver_state = DRV_INSTALL; + + strncpy(dac_driver->driver.drv_name, driver_name, NAME_NUM_MAX); + + dac_driver->driver.configure = dac_driver->configure; + dac_driver->driver.private_data = dac_driver->private_data; + + ret = DacDriverRegister(&dac_driver->driver); + if (EOK != ret) { + KPrintf("DacDriverInit DriverRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("DacDriverInit DriverRegister driver has been register state%u\n", dac_driver->driver.driver_state); + } + + return ret; +} + +/*Release the DAC device*/ +int DacReleaseBus(struct DacBus *dac_bus) +{ + NULL_PARAM_CHECK(dac_bus); + + return BusRelease(&dac_bus->bus); +} + +/*Register the DAC Driver to the DAC BUS*/ +int DacDriverAttachToBus(const char *drv_name, const char *bus_name) +{ + NULL_PARAM_CHECK(drv_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct Driver *driver; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("DacDriverAttachToBus find dac bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_DAC_BUS == bus->bus_type) { + driver = DacDriverFind(drv_name, TYPE_DAC_DRV); + if (NONE == driver) { + KPrintf("DacDriverAttachToBus find dac driver error!name %s\n", drv_name); + return ERROR; + } + + if (TYPE_DAC_DRV == driver->driver_type) { + ret = DriverRegisterToBus(bus, driver); + if (EOK != ret) { + KPrintf("DacDriverAttachToBus DriverRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return ret; +} diff --git a/Ubiquitous/XiUOS/resources/dac/dev_dac.c b/Ubiquitous/XiUOS/resources/dac/dev_dac.c new file mode 100644 index 000000000..ad342ebaf --- /dev/null +++ b/Ubiquitous/XiUOS/resources/dac/dev_dac.c @@ -0,0 +1,119 @@ +/* +* 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 dev_dac.c +* @brief register dac dev function using bus driver framework +* @version 1.1 +* @author AIIT XUOS Lab +* @date 2021-12-28 +*/ + +#include +#include + +static DoubleLinklistType dacdev_linklist; + +/*Create the DAC device linklist*/ +static void DacDeviceLinkInit() +{ + InitDoubleLinkList(&dacdev_linklist); +} + +/*Find the register DAC device*/ +HardwareDevType DacDeviceFind(const char *dev_name, enum DevType dev_type) +{ + NULL_PARAM_CHECK(dev_name); + + struct HardwareDev *device = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &dacdev_linklist; + for (node = head->node_next; node != head; node = node->node_next) { + device = SYS_DOUBLE_LINKLIST_ENTRY(node, struct HardwareDev, dev_link); + if ((!strcmp(device->dev_name, dev_name)) && (dev_type == device->dev_type)) { + return device; + } + } + + KPrintf("DacDeviceFind dacnot find the %s device.return NULL\n", dev_name); + return NONE; +} + +/*Register the DAC device*/ +int DacDeviceRegister(struct DacHardwareDevice *dac_device, void *dac_param, const char *device_name) +{ + NULL_PARAM_CHECK(dac_device); + NULL_PARAM_CHECK(device_name); + + x_err_t ret = EOK; + static x_bool dev_link_flag = RET_FALSE; + + if (!dev_link_flag) { + DacDeviceLinkInit(); + dev_link_flag = RET_TRUE; + } + + if (DEV_INSTALL != dac_device->haldev.dev_state) { + strncpy(dac_device->haldev.dev_name, device_name, NAME_NUM_MAX); + dac_device->haldev.dev_type = TYPE_DAC_DEV; + dac_device->haldev.dev_state = DEV_INSTALL; + + dac_device->haldev.dev_done = (struct HalDevDone *)dac_device->dac_dev_done; + + dac_device->haldev.private_data = dac_param; + + DoubleLinkListInsertNodeAfter(&dacdev_linklist, &(dac_device->haldev.dev_link)); + } else { + KPrintf("DacDeviceRegister device has been register state%u\n", dac_device->haldev.dev_state); + } + + return ret; +} + +/*Register the DAC Device to the DAC BUS*/ +int DacDeviceAttachToBus(const char *dev_name, const char *bus_name) +{ + NULL_PARAM_CHECK(dev_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct HardwareDev *device; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("DacDeviceAttachToBus find dac bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_DAC_BUS == bus->bus_type) { + device = DacDeviceFind(dev_name, TYPE_DAC_DEV); + + if (NONE == device) { + KPrintf("DacDeviceAttachToBus find dac device error!name %s\n", dev_name); + return ERROR; + } + + if (TYPE_DAC_DEV == device->dev_type) { + ret = DeviceRegisterToBus(bus, device); + + if (EOK != ret) { + KPrintf("DacDeviceAttachToBus DeviceRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return EOK; +} diff --git a/Ubiquitous/XiUOS/resources/dac/drv_dac.c b/Ubiquitous/XiUOS/resources/dac/drv_dac.c new file mode 100644 index 000000000..19347cb6d --- /dev/null +++ b/Ubiquitous/XiUOS/resources/dac/drv_dac.c @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file drv_dac.c +* @brief register dac drv function using bus driver framework +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-1-11 +*/ + +#include +#include + +static DoubleLinklistType dacdrv_linklist; + +/*Create the driver linklist*/ +static void DacDrvLinkInit() +{ + InitDoubleLinkList(&dacdrv_linklist); +} + +/*Find the regiter driver*/ +DriverType DacDriverFind(const char *drv_name, enum DriverType_e drv_type) +{ + NULL_PARAM_CHECK(drv_name); + + struct Driver *driver = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &dacdrv_linklist; + + for (node = head->node_next; node != head; node = node->node_next) { + driver = SYS_DOUBLE_LINKLIST_ENTRY(node, struct Driver, driver_link); + if ((!strcmp(driver->drv_name, drv_name)) && (drv_type == driver->driver_type)) { + return driver; + } + } + + KPrintf("DacDriverFind cannot find the %s driver.return NULL\n", drv_name); + return NONE; +} + +/*Register the Driver, manage with the double linklist*/ +int DacDriverRegister(struct Driver *driver) +{ + NULL_PARAM_CHECK(driver); + + x_err_t ret = EOK; + static x_bool driver_link_flag = RET_FALSE; + + if (!driver_link_flag) { + DacDrvLinkInit(); + driver_link_flag = RET_TRUE; + } + + DoubleLinkListInsertNodeAfter(&dacdrv_linklist, &(driver->driver_link)); + + return ret; +} diff --git a/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c b/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c index 99845580f..388263fcb 100644 --- a/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c +++ b/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c @@ -81,20 +81,13 @@ #include "enet_ethernetif.h" #include -/* MAC address configuration. */ -#define configMAC_ADDR { 0x02, 0x12, 0x13, 0x10, 0x15, 0x11} - char lwip_ipaddr[] = {192, 168, 250, 253}; char lwip_netmask[] = {255, 255, 255, 0}; char lwip_gwaddr[] = {192, 168, 250, 252}; - -int errno; -int is_lwip_test = 0; //for lwip input thread +char lwip_flag = 0; x_ticks_t lwip_sys_now; -static int lwip_init_flag = 0; - struct sys_timeouts { struct sys_timeo *next; }; @@ -389,7 +382,7 @@ ip4_addr_t ipaddr; ip4_addr_t netmask; ip4_addr_t gw; -void TcpIpInit(void) +void lwip_tcp_init(void) { tcpip_init(NULL, NULL); @@ -400,14 +393,9 @@ void TcpIpInit(void) ip_addr_set_zero_ip4(&netmask); ip_addr_set_zero_ip4(&gw); #else - #ifdef SET_AS_SERVER - IP4_ADDR(&ipaddr,IP_ADDR0_SERVER,IP_ADDR1_SERVER,IP_ADDR2_SERVER,IP_ADDR3_SERVER); - #else - IP4_ADDR(&ipaddr,IP_ADDR0_ClIENT,IP_ADDR1_ClIENT,IP_ADDR2_ClIENT,IP_ADDR3_ClIENT); - #endif - - IP4_ADDR(&netmask,NETMASK_ADDR0,NETMASK_ADDR1,NETMASK_ADDR2,NETMASK_ADDR3); - IP4_ADDR(&gw,GW_ADDR0,GW_ADDR1,GW_ADDR2,GW_ADDR3); + IP4_ADDR(&ipaddr, lwip_ipaddr[0], lwip_ipaddr[1], lwip_ipaddr[2], lwip_ipaddr[3]); + IP4_ADDR(&netmask, lwip_netmask[0], lwip_netmask[1], lwip_netmask[2], lwip_netmask[3]); + IP4_ADDR(&gw, lwip_gwaddr[0], lwip_gwaddr[1], lwip_gwaddr[2], lwip_gwaddr[3]); #endif /* USE_DHCP */ /* USER CODE END 0 */ /* Initilialize the LwIP stack without RTOS */ @@ -420,13 +408,13 @@ void TcpIpInit(void) if (netif_is_link_up(&gnetif)) { /* When the netif is fully configured this function must be called */ - KPrintf("TcpIpInit : netif_set_up\n"); + KPrintf("%s : netif_set_up\n", __func__); netif_set_up(&gnetif); } else { /* When the netif link is down this function must be called */ - KPrintf("TcpIpInit : netif_set_down\n"); + KPrintf("%s : netif_set_down\n", __func__); netif_set_down(&gnetif); } @@ -462,10 +450,14 @@ void lwip_input_thread(void *param) while (1) { - /* Poll the driver, get any outstanding frames */ - ethernetif_input(net); - sys_check_timeouts(); /* Handle all system timeouts for all core protocols */ -// DelayKTask(1); +#ifdef FSL_RTOS_XIUOS + if (lwip_obtain_semaphore(net) == EOK) +#endif + { + /* Poll the driver, get any outstanding frames */ + ethernetif_input(net); + sys_check_timeouts(); /* Handle all system timeouts for all core protocols */ + } } } @@ -497,7 +489,7 @@ void lwip_config_net(char *ip, char *mask, char *gw) #endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */ }; - if(lwip_init_flag) + if(chk_lwip_bit(LWIP_INIT_FLAG)) { lw_print("lw: [%s] already ...\n", __func__); @@ -505,6 +497,7 @@ void lwip_config_net(char *ip, char *mask, char *gw) IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]); IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]); + // update ip addr netif_set_down(&gnetif); netif_set_gw(&gnetif, &net_gw); netif_set_netmask(&gnetif, &net_netmask); @@ -512,7 +505,7 @@ void lwip_config_net(char *ip, char *mask, char *gw) netif_set_up(&gnetif); return; } - lwip_init_flag = 1; + set_lwip_bit(LWIP_INIT_FLAG); lw_print("lw: [%s] start ...\n", __func__); @@ -527,7 +520,7 @@ void lwip_config_net(char *ip, char *mask, char *gw) netif_set_default(&gnetif); netif_set_up(&gnetif); - if(is_lwip_test) + if(chk_lwip_bit(LWIP_PRINT_FLAG)) { lw_pr_info("\r\n************************************************\r\n"); lw_pr_info(" Network Configuration\r\n"); @@ -558,12 +551,13 @@ void lwip_config_tcp(char *ip, char *mask, char *gw) #endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */ }; - if(lwip_init_flag) + if(chk_lwip_bit(LWIP_INIT_FLAG)) { lw_print("lw: [%s] already ...\n", __func__); return; } - lwip_init_flag = 1; + + set_lwip_bit(LWIP_INIT_FLAG); tcpip_init(NULL, NULL); diff --git a/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.h b/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.h index dab1c5445..ab5a66b2a 100644 --- a/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.h +++ b/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.h @@ -60,38 +60,18 @@ #include -/* USER CODE BEGIN 0 */ -// #define SET_AS_SERVER 1 /* define this terminal is udp server or not*/ +/* LWIP task parameter */ +#define LWIP_LOCAL_PORT 4840 +#define LWIP_TARGET_PORT LWIP_LOCAL_PORT -#define LOCAL_PORT_SERVER 4840 -#define TARGET_PORT_CLIENT LOCAL_PORT_SERVER +#define LWIP_DEMO_TIMES 3 +#define LWIP_TASK_STACK_SIZE 4096 +#define LWIP_DEMO_TASK_PRIO 20 -#define TEST_LWIP_TIMES 3 +/* MAC address configuration. */ +#define configMAC_ADDR {0x02, 0x12, 0x13, 0x10, 0x15, 0x11} -/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */ -#define IP_ADDR0_SERVER 192 -#define IP_ADDR1_SERVER 168 -#define IP_ADDR2_SERVER 250 -#define IP_ADDR3_SERVER 252 - -#define IP_ADDR0_ClIENT 192 -#define IP_ADDR1_ClIENT 168 -#define IP_ADDR2_ClIENT 250 -#define IP_ADDR3_ClIENT 253 - -/*NETMASK*/ -#define NETMASK_ADDR0 255 -#define NETMASK_ADDR1 255 -#define NETMASK_ADDR2 255 -#define NETMASK_ADDR3 0 - -/*Gateway Address*/ -#define GW_ADDR0 192 -#define GW_ADDR1 168 -#define GW_ADDR2 250 -#define GW_ADDR3 5 /* USER CODE END 0 */ - #define SYS_MBOX_NULL -1 #define SYS_SEM_NULL 0 #define SYS_MRTEX_NULL SYS_SEM_NULL @@ -100,18 +80,28 @@ typedef int32 sys_sem_t; typedef int32 sys_mutex_t; typedef int32 sys_mbox_t; typedef int32 sys_thread_t; - typedef x_base sys_prot_t; -#define MS_PER_SYSTICK_F407 1000/TICK_PER_SECOND +#define MS_PER_SYSTICK_F407 (1000 / TICK_PER_SECOND) + +//debug rtos with IRQ +//#define FSL_RTOS_XIUOS + +extern char lwip_flag; + +#define LWIP_INIT_FLAG (1 << 0) +#define LWIP_PRINT_FLAG (1 << 1) + +#define set_lwip_bit(__bit) lwip_flag |= (__bit) +#define clr_lwip_bit(__bit) lwip_flag &= ~(__bit) +#define chk_lwip_bit(__bit) ((lwip_flag & (__bit)) == (__bit)) extern char lwip_ipaddr[]; extern char lwip_netmask[]; extern char lwip_gwaddr[]; -extern int is_lwip_test; extern struct netif gnetif; -void TcpIpInit(void); +void lwip_tcp_init(void); void lwip_config_net(char *ip, char *mask, char *gw); void lwip_config_tcp(char *ip, char *mask, char *gw); diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_config_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_config_demo.c index 4268d2306..8a5c13be9 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_config_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_config_demo.c @@ -107,8 +107,10 @@ SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | setip, lwip_setip_thread, SetIp [IP] [Netmask] [Gateway]); -void lwip_getip_thread(int argc, char *argv[]) +void lwip_showip_thread(int argc, char *argv[]) { + char mac_addr[] = configMAC_ADDR; + lw_pr_info("\r\n************************************************\r\n"); lw_pr_info(" Network Configuration\r\n"); lw_pr_info("************************************************\r\n"); @@ -118,10 +120,12 @@ void lwip_getip_thread(int argc, char *argv[]) ((u8_t *)&lwip_netmask)[2], ((u8_t *)&lwip_netmask)[3]); lw_pr_info(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&lwip_gwaddr)[0], ((u8_t *)&lwip_gwaddr)[1], ((u8_t *)&lwip_gwaddr)[2], ((u8_t *)&lwip_gwaddr)[3]); + lw_pr_info(" MAC Address : %x:%x:%x:%x:%x:%x\r\n", mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); lw_pr_info("************************************************\r\n"); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), - showip, lwip_getip_thread, GetIp [IP] [Netmask] [Gateway]); + showip, lwip_showip_thread, GetIp [IP] [Netmask] [Gateway]); #endif diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_demo.h b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_demo.h index c2cf2ebbb..99e273aa1 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_demo.h +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_demo.h @@ -1,6 +1,7 @@ #ifndef __LWIP_DEMO_H__ #define __LWIP_DEMO_H__ -void *eth_input_thread(void *param); +#define LWIP_TEST_STACK_SIZE 4096 +#define LWIP_TEST_TASK_PRIO 20 #endif /* __LWIP_DEMO_H__ */ diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_dhcp_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_dhcp_demo.c index b4e47d00e..6cf60699e 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_dhcp_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_dhcp_demo.c @@ -133,7 +133,7 @@ void lwip_dhcp_test(void) ETH_BSP_Config(); lwip_config_net(ip_addr, ip_addr, ip_addr); - is_lwip_test = 1; + set_lwip_bit(LWIP_PRINT_FLAG); dhcp_start(&gnetif); @@ -167,7 +167,7 @@ void lwip_dhcp_test(void) } } - is_lwip_test = 0; + clr_lwip_bit(LWIP_PRINT_FLAG); } diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c index 65a159cdb..a0c6807bb 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c @@ -101,11 +101,13 @@ void lwip_ping_thread(int argc, char *argv[]) return; } } +#if (LWIP_DHCP) && (PING_USE_SOCKETS) else { get_url_ip(argv[1]); return; } +#endif } lw_print("lw: [%s] argc %d\n", __func__, argc); diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c index 647199d97..baebfbbcb 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c @@ -29,6 +29,8 @@ * Definitions ******************************************************************************/ +#define MSG_SIZE 128 + /******************************************************************************* * Prototypes ******************************************************************************/ @@ -37,10 +39,9 @@ * Variables ******************************************************************************/ -char tcp_target[] = {192, 168, 250, 252}; -#define MSG_SIZE 128 // this is for test in shell, in fact, shell restrict the length of input string, which is less then 128 char tcp_send_msg[MSG_SIZE] = {0}; +char tcp_target[] = {192, 168, 250, 252}; /******************************************************************************* * Code @@ -60,7 +61,7 @@ static void lwip_tcp_send_thread(void *arg) struct sockaddr_in tcp_sock; tcp_sock.sin_family = AF_INET; - tcp_sock.sin_port = htons(TARGET_PORT_CLIENT); + tcp_sock.sin_port = htons(LWIP_TARGET_PORT); tcp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(tcp_target[0], tcp_target[1], tcp_target[2], tcp_target[3])); memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero)); @@ -104,7 +105,7 @@ void lwip_tcp_send_run(int argc, char *argv[]) ETH_BSP_Config(); lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); - sys_thread_new("tcp send", lwip_tcp_send_thread, NULL, 4096, 25); + sys_thread_new("tcp send", lwip_tcp_send_thread, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_udp_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_udp_demo.c index 37c16b0e2..5dd19c5c3 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_udp_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_udp_demo.c @@ -53,7 +53,7 @@ char udp_send_msg[] = "\n\nThis one is UDP pkg. Congratulations on you.\n\n"; static void lwip_udp_send(void *arg) { - int cnt = TEST_LWIP_TIMES; + int cnt = LWIP_DEMO_TIMES; lw_print("udp_send_demo start.\n"); @@ -67,7 +67,7 @@ static void lwip_udp_send(void *arg) struct sockaddr_in udp_sock; udp_sock.sin_family = AF_INET; - udp_sock.sin_port = htons(TARGET_PORT_CLIENT); + udp_sock.sin_port = htons(LWIP_TARGET_PORT); udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_target[0],udp_target[1],udp_target[2],udp_target[3])); memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero)); @@ -170,7 +170,7 @@ void udpecho_raw_init(void) return; } - err = udp_bind(udpecho_raw_pcb, IP_ANY_TYPE, LOCAL_PORT_SERVER); + err = udp_bind(udpecho_raw_pcb, IP_ANY_TYPE, LWIP_LOCAL_PORT); if (err == ERR_OK) { udp_recv(udpecho_raw_pcb, udpecho_raw_recv, NULL); diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/ping.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/ping.c index 925f174ba..1a66bd272 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/ping.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/ping.c @@ -105,10 +105,6 @@ static u32_t ping_time; static struct raw_pcb *ping_pcb; #endif /* PING_USE_SOCKETS */ -#define PING_THREAD_STACKSIZE 4096 -#define PING_THREAD_PRIO 15 - - /** Prepare a echo ICMP request */ static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) @@ -248,7 +244,7 @@ ping_thread(void *arg) { int s; int ret; - int cnt = TEST_LWIP_TIMES; + int cnt = LWIP_DEMO_TIMES; #if LWIP_SO_SNDRCVTIMEO_NONSTANDARD int timeout = PING_RCV_TIMEO; @@ -268,7 +264,7 @@ ping_thread(void *arg) s = lwip_socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6); } #else - s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP); + s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP); #endif if (s < 0) { lw_print("lw: [%s] ping failed %d!\n", __func__, s); @@ -367,7 +363,7 @@ ping_send(struct raw_pcb *raw, const ip_addr_t *addr) static void ping_timeout(void *arg) { - static int cnt = TEST_LWIP_TIMES; + static int cnt = LWIP_DEMO_TIMES; struct raw_pcb *pcb = (struct raw_pcb*)arg; LWIP_ASSERT("ping_timeout: no pcb given!", pcb != NULL); @@ -380,7 +376,7 @@ ping_timeout(void *arg) } else { - cnt = TEST_LWIP_TIMES; + cnt = LWIP_DEMO_TIMES; } } @@ -412,7 +408,7 @@ ping_init(const ip_addr_t* ping_addr) ping_target = ping_addr; #if PING_USE_SOCKETS - th = sys_thread_new("ping_thread", ping_thread, NULL, PING_THREAD_STACKSIZE, PING_THREAD_PRIO); + th = sys_thread_new("ping_thread", ping_thread, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); lw_print("lw: [%s] new thread %d addr %#x\n", __func__, th, (*ping_addr).addr); #else /* PING_USE_SOCKETS */ ping_raw_init(); @@ -476,6 +472,7 @@ int lwip_ping_recv(int s, int *ttl) return len; } +#if (LWIP_DHCP) && (PING_USE_SOCKETS) int get_url_ip(char* url) { #if LWIP_VERSION_MAJOR >= 2U @@ -483,7 +480,7 @@ int get_url_ip(char* url) #else int timeout = PING_RCV_TIMEO * 1000UL / TICK_PER_SECOND; #endif - int cnt = TEST_LWIP_TIMES; + int cnt = LWIP_DEMO_TIMES; int s, ttl, recv_len; ip_addr_t target_addr; @@ -539,6 +536,6 @@ int get_url_ip(char* url) lwip_close(s); return 0; } - +#endif #endif /* LWIP_RAW */ diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/tcpecho_raw.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/tcpecho_raw.c index 887e8bcd8..026207891 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/tcpecho_raw.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/tcpecho_raw.c @@ -49,7 +49,10 @@ #if LWIP_TCP && LWIP_CALLBACK_API -#define MAX_TESTED_TCP_SEND_SIZE (56000) +#define MAX_TCP_RECV_SIZE (56000) +#define MAX_TCP_SHOW_SIZE 80 +#define TCP_ACK_MSG_SIZE 20 +#define TCP_EOF_CH '\n' static struct tcp_pcb *tcpecho_raw_pcb; @@ -109,70 +112,73 @@ tcpecho_raw_error(void *arg, err_t err) tcpecho_raw_free(es); } -#define SHELL_TCP_LENGTH 80 -char* recved_msg; -int recved_msg_length; +static void +tcpecho_raw_ack_size(struct tcp_pcb *tpcb, int ack_len) +{ + struct pbuf *ack_buf = NULL; + + // ack message + ack_buf = pbuf_alloc(PBUF_TRANSPORT, TCP_ACK_MSG_SIZE, PBUF_RAM); + snprintf(ack_buf->payload, TCP_ACK_MSG_SIZE, "%d\n\0", ack_len); + ack_buf->len = strlen(ack_buf->payload); + ack_buf->tot_len = strlen(ack_buf->payload); + ack_buf->next = NULL; + + tcp_write(tpcb, ack_buf->payload, ack_buf->len, 1); + pbuf_free(ack_buf); +} + // compute received message length until '\n' -static void record_msg(struct tcp_pcb *tpcb, struct tcpecho_raw_state* es){ - struct pbuf* ptr = es->p; - int plen = ptr->len; - if(es==NULL||ptr==NULL||plen==0){ - if(recved_msg){ - free(recved_msg); - recved_msg = NULL; - } - recved_msg_length = 0; +static void +tcpecho_raw_ack(struct tcp_pcb *tpcb, struct tcpecho_raw_state* es){ + struct pbuf *ptr = es->p; + char *recv_buf = ptr->payload; + int recv_len = ptr->len; + static char *g_buf = NULL; //global received buffer + static int g_buf_size = 0; + + lw_print("lw: [%s] recv %d tot %d next %p ref %d tye %d id %d %s\n", __func__, ptr->len, ptr->tot_len, + ptr->next, ptr->ref, ptr->type_internal, + ptr->if_idx, ptr->payload); + + if(g_buf == NULL) + { + g_buf = (char *)malloc(MAX_TCP_RECV_SIZE); + memset(g_buf, 0, MAX_TCP_RECV_SIZE); + memcpy(g_buf, recv_buf, recv_len); } - int new_size = plen+1; - char* temp = recved_msg; - if(temp!=NULL){ - new_size += strlen(temp); - } - recved_msg = malloc(new_size); - memset(recved_msg, 0, new_size); - if(temp!=NULL){ - memcpy(recved_msg,temp,strlen(temp)); - } - memcpy(recved_msg+new_size-plen-1, ptr->payload, plen); - free(temp); - recved_msg_length += plen; - if(recved_msg_length>=SHELL_TCP_LENGTH){ - if(recved_msg){ - free(recved_msg); - recved_msg = NULL; + else + { + if(g_buf_size + recv_len <= MAX_TCP_RECV_SIZE) + { + memcpy(g_buf + g_buf_size, recv_buf, recv_len); } } - if(((char*)ptr->payload)[plen-1]=='\n'){ - if(recved_msg_length>MAX_TESTED_TCP_SEND_SIZE){ - KPrintf("Recved_msg_length is larger than %d, which may lead to unexpected exceptions.\n",MAX_TESTED_TCP_SEND_SIZE); - } - if(recved_msg_lengthpayload,"%d\n\0",recved_msg_length); - reply_pbuf->len = strlen(reply_pbuf->payload); - reply_pbuf->tot_len = strlen(reply_pbuf->payload); - reply_pbuf->next = NULL; - - tcp_write(tpcb, reply_pbuf->payload, reply_pbuf->len, 1); - - pbuf_free(reply_pbuf); - free(recved_msg); - recved_msg = NULL; - recved_msg_length = 0; + + tcpecho_raw_ack_size(tpcb, g_buf_size); + + free(g_buf); + g_buf = NULL; + g_buf_size = 0; } + es->p = ptr->next; if(es->p != NULL) { /* new reference! */ pbuf_ref(es->p); } pbuf_free(ptr); - tcp_recved(tpcb, plen); -} + tcp_recved(tpcb, recv_len); +} static err_t tcpecho_raw_poll(void *arg, struct tcp_pcb *tpcb) @@ -184,7 +190,7 @@ tcpecho_raw_poll(void *arg, struct tcp_pcb *tpcb) if (es != NULL) { if (es->p != NULL) { /* there is a remaining pbuf (chain) */ - record_msg(tpcb, es); + tcpecho_raw_ack(tpcb, es); } else { /* no remaining pbuf (chain) */ if(es->state == ES_CLOSING) { @@ -233,7 +239,7 @@ tcpecho_raw_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) tcpecho_raw_close(tpcb, es); } else { /* we're not done yet */ - record_msg(tpcb, es); + tcpecho_raw_ack(tpcb, es); } ret_err = ERR_OK; } else if(err != ERR_OK) { @@ -248,13 +254,13 @@ tcpecho_raw_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) es->state = ES_RECEIVED; /* store reference to incoming pbuf (chain) */ es->p = p; - record_msg(tpcb, es); + tcpecho_raw_ack(tpcb, es); ret_err = ERR_OK; } else if (es->state == ES_RECEIVED) { /* read some more data */ if(es->p == NULL) { es->p = p; - record_msg(tpcb, es); + tcpecho_raw_ack(tpcb, es); } else { struct pbuf *ptr; @@ -277,8 +283,6 @@ tcpecho_raw_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { err_t ret_err; struct tcpecho_raw_state *es; - recved_msg = NULL; - recved_msg_length = 0; LWIP_UNUSED_ARG(arg); if ((err != ERR_OK) || (newpcb == NULL)) { diff --git a/Ubiquitous/XiUOS/resources/include/bus.h b/Ubiquitous/XiUOS/resources/include/bus.h index b36b03b11..5cd0fd314 100644 --- a/Ubiquitous/XiUOS/resources/include/bus.h +++ b/Ubiquitous/XiUOS/resources/include/bus.h @@ -52,6 +52,8 @@ enum BusType_e TYPE_PIN_BUS, TYPE_RTC_BUS, TYPE_SERIAL_BUS, + TYPE_ADC_BUS, + TYPE_DAC_BUS, TYPE_BUS_END, }; @@ -76,6 +78,8 @@ enum DevType TYPE_PIN_DEV, TYPE_RTC_DEV, TYPE_SERIAL_DEV, + TYPE_ADC_DEV, + TYPE_DAC_DEV, TYPE_DEV_END, }; @@ -100,6 +104,8 @@ enum DriverType_e TYPE_PIN_DRV, TYPE_RTC_DRV, TYPE_SERIAL_DRV, + TYPE_ADC_DRV, + TYPE_DAC_DRV, TYPE_DRV_END, }; diff --git a/Ubiquitous/XiUOS/resources/include/bus_adc.h b/Ubiquitous/XiUOS/resources/include/bus_adc.h new file mode 100644 index 000000000..42636b5fa --- /dev/null +++ b/Ubiquitous/XiUOS/resources/include/bus_adc.h @@ -0,0 +1,67 @@ +/* +* 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 bus_adc.h +* @brief define adc bus and drv function using bus driver framework +* @version 1.1 +* @author AIIT XUOS Lab +* @date 2021-12-28 +*/ + +#ifndef BUS_ADC_H +#define BUS_ADC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct AdcDriver +{ + struct Driver driver; + uint32 (*configure) (void *drv, struct BusConfigureInfo *configure_info); + + void *private_data; +}; + +struct AdcBus +{ + struct Bus bus; + + void *private_data; +}; + +/*Register the ADC bus*/ +int AdcBusInit(struct AdcBus *adc_bus, const char *bus_name); + +/*Register the ADC driver*/ +int AdcDriverInit(struct AdcDriver *adc_driver, const char *driver_name); + +/*Release the ADC device*/ +int AdcReleaseBus(struct AdcBus *adc_bus); + +/*Register the ADC driver to the ADC bus*/ +int AdcDriverAttachToBus(const char *drv_name, const char *bus_name); + +/*Register the driver, manage with the double linklist*/ +int AdcDriverRegister(struct Driver *driver); + +/*Find the register driver*/ +DriverType AdcDriverFind(const char *drv_name, enum DriverType_e drv_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiUOS/resources/include/bus_dac.h b/Ubiquitous/XiUOS/resources/include/bus_dac.h new file mode 100644 index 000000000..e87b9635f --- /dev/null +++ b/Ubiquitous/XiUOS/resources/include/bus_dac.h @@ -0,0 +1,67 @@ +/* +* 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 bus_dac.h +* @brief define dac bus and drv function using bus driver framework +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-1-11 +*/ + +#ifndef BUS_DAC_H +#define BUS_DAC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct DacDriver +{ + struct Driver driver; + uint32 (*configure) (void *drv, struct BusConfigureInfo *configure_info); + + void *private_data; +}; + +struct DacBus +{ + struct Bus bus; + + void *private_data; +}; + +/*Register the DAC bus*/ +int DacBusInit(struct DacBus *dac_bus, const char *bus_name); + +/*Register the DAC driver*/ +int DacDriverInit(struct DacDriver *dac_driver, const char *driver_name); + +/*Release the DAC device*/ +int DacReleaseBus(struct DacBus *dac_bus); + +/*Register the DAC driver to the DAC bus*/ +int DacDriverAttachToBus(const char *drv_name, const char *bus_name); + +/*Register the driver, manage with the double linklist*/ +int DacDriverRegister(struct Driver *driver); + +/*Find the register driver*/ +DriverType DacDriverFind(const char *drv_name, enum DriverType_e drv_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiUOS/resources/include/dev_adc.h b/Ubiquitous/XiUOS/resources/include/dev_adc.h new file mode 100644 index 000000000..23633d605 --- /dev/null +++ b/Ubiquitous/XiUOS/resources/include/dev_adc.h @@ -0,0 +1,61 @@ +/* +* 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 dev_adc.h +* @brief define adc dev function using bus driver framework +* @version 1.1 +* @author AIIT XUOS Lab +* @date 2021-12-28 +*/ + +#ifndef DEV_ADC_H +#define DEV_ADC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct AdcHardwareDevice; + +struct AdcDevDone +{ + uint32 (*open) (void *dev); + uint32 (*close) (void *dev); + uint32 (*write) (void *dev,struct BusBlockWriteParam *write_param); + uint32 (*read) (void *dev, struct BusBlockReadParam *read_param); +}; + +struct AdcHardwareDevice +{ + struct HardwareDev haldev; + const struct AdcDevDone *adc_dev_done; + + void *private_data; +}; + +/*Register the ADC device*/ +int AdcDeviceRegister(struct AdcHardwareDevice *adc_device, void *adc_param, const char *device_name); + +/*Register the ADC device to the ADC bus*/ +int AdcDeviceAttachToBus(const char *dev_name, const char *bus_name); + +/*Find the register ADC device*/ +HardwareDevType AdcDeviceFind(const char *dev_name, enum DevType dev_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiUOS/resources/include/dev_dac.h b/Ubiquitous/XiUOS/resources/include/dev_dac.h new file mode 100644 index 000000000..d51bbcc6f --- /dev/null +++ b/Ubiquitous/XiUOS/resources/include/dev_dac.h @@ -0,0 +1,61 @@ +/* +* 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 dev_dac.h +* @brief define dac dev function using bus driver framework +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-1-11 +*/ + +#ifndef DEV_DAC_H +#define DEV_DAC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct DacHardwareDevice; + +struct DacDevDone +{ + uint32 (*open) (void *dev); + uint32 (*close) (void *dev); + uint32 (*write) (void *dev,struct BusBlockWriteParam *write_param); + uint32 (*read) (void *dev, struct BusBlockReadParam *read_param); +}; + +struct DacHardwareDevice +{ + struct HardwareDev haldev; + const struct DacDevDone *dac_dev_done; + + void *private_data; +}; + +/*Register the DAC device*/ +int DacDeviceRegister(struct DacHardwareDevice *dac_device, void *dac_param, const char *device_name); + +/*Register the DAC device to the DAC bus*/ +int DacDeviceAttachToBus(const char *dev_name, const char *bus_name); + +/*Find the register DAC device*/ +HardwareDevType DacDeviceFind(const char *dev_name, enum DevType dev_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiUOS/resources/include/device.h b/Ubiquitous/XiUOS/resources/include/device.h index 85e44084e..db9799b2a 100644 --- a/Ubiquitous/XiUOS/resources/include/device.h +++ b/Ubiquitous/XiUOS/resources/include/device.h @@ -94,4 +94,14 @@ HardwareDevType ObtainConsole(void); #include #endif +#ifdef RESOURCES_ADC +#include +#include +#endif + +#ifdef RESOURCES_DAC +#include +#include +#endif + #endif diff --git a/Ubiquitous/XiUOS/resources/serial/dev_serial.c b/Ubiquitous/XiUOS/resources/serial/dev_serial.c index d97e336fe..1e694ed6b 100644 --- a/Ubiquitous/XiUOS/resources/serial/dev_serial.c +++ b/Ubiquitous/XiUOS/resources/serial/dev_serial.c @@ -303,6 +303,7 @@ static inline int SerialDevDMARead(struct SerialHardwareDevice *serial_dev, stru serial_dev->serial_fifo.serial_rx->serial_rx_buffer, read_dma_length + serial_dev->serial_fifo.serial_rx->serial_recv_num - serial_cfg->data_cfg.serial_buffer_size); } SerialDmaRxSetRecvLength(serial_dev, read_dma_length); + read_param->read_length = read_dma_length; CriticalAreaUnLock(lock); return EOK; } else { diff --git a/Ubiquitous/XiUOS/tool/shell/letter-shell/cmd.c b/Ubiquitous/XiUOS/tool/shell/letter-shell/cmd.c index a10e1ac0e..008236ded 100644 --- a/Ubiquitous/XiUOS/tool/shell/letter-shell/cmd.c +++ b/Ubiquitous/XiUOS/tool/shell/letter-shell/cmd.c @@ -382,6 +382,8 @@ static char *const bus_type_str[] = "PIN_BUS", "RTC_BUS", "SERIAL_BUS", + "ADC_BUS", + "DAC_BUS", "Unknown" }; diff --git a/Ubiquitous/XiUOS/tool/shell/letter-shell/shell.c b/Ubiquitous/XiUOS/tool/shell/letter-shell/shell.c index 564d8325e..277349d35 100644 --- a/Ubiquitous/XiUOS/tool/shell/letter-shell/shell.c +++ b/Ubiquitous/XiUOS/tool/shell/letter-shell/shell.c @@ -1642,14 +1642,12 @@ void shellTask(void *param) /* One input key from the the keyboard/uart may consist of mutliple characters (e.g., arrow keys). */ char data[KEY_LENGTH]; int i; - int data_len; + char data_len; while(RET_TRUE) { - if (shell->read && shell->read(data) == 0) { - // KPrintf("in 1741 the char is: '%c' and ascii code is %d.\n\n",data,data); - // KPrintf("the buffer is:'%s'\n\n",shell->parser.); - data_len = strlen(data); + if (shell->read) { + data_len = shell->read(data); for (i = 0; i < data_len; i++) { shellHandler(shell, data[i]); } diff --git a/Ubiquitous/XiUOS/tool/shell/letter-shell/shell_port.c b/Ubiquitous/XiUOS/tool/shell/letter-shell/shell_port.c index 5393fb9e0..607d53749 100644 --- a/Ubiquitous/XiUOS/tool/shell/letter-shell/shell_port.c +++ b/Ubiquitous/XiUOS/tool/shell/letter-shell/shell_port.c @@ -46,13 +46,17 @@ void userShellWrite(char data) */ signed char userShellRead(char *data) { + char read_length = 0; struct BusBlockReadParam read_param; + read_param.read_length = 0; read_param.size = 1; read_param.buffer = data; BusDevReadData(console, &read_param); - return 0; + read_length = (char)read_param.read_length; + + return read_length; } #ifdef SHELL_ENABLE_FILESYSTEM @@ -107,7 +111,7 @@ int userShellInit(void) /*Open the serial device in interrupt receiving and polling sending mode */ struct SerialDevParam *serial_dev_param = (struct SerialDevParam *)console->private_data; - serial_dev_param->serial_set_mode = SIGN_OPER_INT_RX; + serial_dev_param->serial_set_mode = 0; serial_dev_param->serial_stream_mode = SIGN_OPER_STREAM; BusDevOpen(console);