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 b018be453..3eccb8dc0 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 @@ -28,6 +28,8 @@ * Definitions ******************************************************************************/ +#define TCP_DEMO_BUF_SIZE 65535 + /******************************************************************************* * Prototypes ******************************************************************************/ @@ -38,8 +40,6 @@ char tcp_socket_ip[] = {192, 168, 250, 252}; -#define TCP_DEMO_BUF_SIZE 65535 - /******************************************************************************* * Code ******************************************************************************/ @@ -80,7 +80,7 @@ static void tcp_recv_demo(void *arg) } lw_print("tcp bind success, start to receive.\n"); - lw_print("\n\nLocal Port:%d\n\n", LWIP_LOCAL_PORT); + lw_pr_info("\n\nLocal Port:%d\n\n", LWIP_LOCAL_PORT); // setup socket fd as listening mode if (listen(fd, 5) != 0 ) @@ -91,7 +91,7 @@ static void tcp_recv_demo(void *arg) // 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)); + lw_pr_info("client %s connected\n", inet_ntoa(tcp_addr.sin_addr)); while(1) { @@ -163,7 +163,7 @@ static void tcp_send_demo(void *arg) } lw_print("tcp connect success, start to send.\n"); - lw_pr_info("\n\nTarget Port:%d\n\n", tcp_sock.sin_port); + lw_pr_info("\n\nTarget Port:%d\n\n", LWIP_TARGET_PORT); while (cnt --) { 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 420f8d699..36d49cf4f 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 @@ -39,6 +39,7 @@ /******************************************************************************* * Variables ******************************************************************************/ + extern char udp_target[]; static struct udp_pcb *udpecho_raw_pcb; char udp_socket_ip[] = {192, 168, 250, 252}; @@ -59,14 +60,14 @@ static void udp_recv_demo(void *arg) while(1) { recv_buf = (char *)malloc(UDP_BUF_SIZE); - if (recv_buf == NULL) + if(recv_buf == NULL) { lw_print("No memory\n"); goto __exit; } socket_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (socket_fd < 0) + if(socket_fd < 0) { lw_print("Socket error\n"); goto __exit; @@ -77,7 +78,7 @@ static void udp_recv_demo(void *arg) 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) + if(bind(socket_fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1) { lw_print("Unable to bind\n"); goto __exit; @@ -96,11 +97,15 @@ static void udp_recv_demo(void *arg) } __exit: - if (socket_fd >= 0) + if(socket_fd >= 0) + { closesocket(socket_fd); + } - if (recv_buf) + if(recv_buf) + { free(recv_buf); + } } } @@ -135,7 +140,7 @@ static void udp_send_demo(void *arg) memset(send_str, 0, sizeof(send_str)); socket_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (socket_fd < 0) + if(socket_fd < 0) { lw_print("Socket error\n"); goto __exit; @@ -144,10 +149,10 @@ static void udp_send_demo(void *arg) struct sockaddr_in udp_sock; udp_sock.sin_family = AF_INET; udp_sock.sin_port = htons(LWIP_TARGET_PORT); - udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_target[0],udp_target[1],udp_target[2],udp_target[3])); + udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_target[0], udp_target[1], udp_target[2], udp_target[3])); memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero)); - if (connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr))) + if(connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr))) { lw_print("Unable to connect\n"); goto __exit; @@ -165,7 +170,7 @@ static void udp_send_demo(void *arg) } __exit: - if (socket_fd >= 0) + if(socket_fd >= 0) { closesocket(socket_fd); } diff --git a/APP_Framework/Framework/control/plc/shared/Makefile b/APP_Framework/Framework/control/plc/shared/Makefile index 03bb1bbf7..1f0543f9a 100755 --- a/APP_Framework/Framework/control/plc/shared/Makefile +++ b/APP_Framework/Framework/control/plc/shared/Makefile @@ -1,4 +1,4 @@ -SRC_FILES := plc.c +SRC_FILES := plc.c plc_dev.c plc_bus.c plc_drv.c include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/control/plc/shared/bus.h b/APP_Framework/Framework/control/plc/shared/bus.h new file mode 100755 index 000000000..c50997495 --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/bus.h @@ -0,0 +1,266 @@ +/* +* 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.h +* @brief define bus driver framework function and common API +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-24 +*/ + +#ifndef BUS_H +#define BUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define OPE_INT 0x0000 +#define OPE_CFG 0x0001 + +#define OPER_WDT_SET_TIMEOUT 0x0002 +#define OPER_WDT_KEEPALIVE 0x0003 + +typedef struct Bus *BusType; +typedef struct HardwareDev *HardwareDevType; +typedef struct Driver *DriverType; + +/* need to add new bus type in ../tool/shell/letter-shell/cmd.c, ensure ShowBus cmd supported*/ +enum BusType_e +{ + TYPE_I2C_BUS = 0, + TYPE_SPI_BUS, + TYPE_HWTIMER_BUS, + TYPE_USB_BUS, + TYPE_CAN_BUS, + TYPE_WDT_BUS, + TYPE_SDIO_BUS, + TYPE_TOUCH_BUS, + TYPE_LCD_BUS, + TYPE_PIN_BUS, + TYPE_RTC_BUS, + TYPE_SERIAL_BUS, + TYPE_PLC_BUS, + TYPE_BUS_END, +}; + +enum BusState +{ + BUS_INIT = 0, + BUS_INSTALL, + BUS_UNINSTALL, +}; + +enum DevType +{ + TYPE_I2C_DEV = 0, + TYPE_SPI_DEV, + TYPE_HWTIMER_DEV, + TYPE_USB_DEV, + TYPE_CAN_DEV, + TYPE_WDT_DEV, + TYPE_SDIO_DEV, + TYPE_TOUCH_DEV, + TYPE_LCD_DEV, + TYPE_PIN_DEV, + TYPE_RTC_DEV, + TYPE_SERIAL_DEV, + TYPE_DEV_END, +}; + +enum DevState +{ + DEV_INIT = 0, + DEV_INSTALL, + DEV_UNINSTALL, +}; + +enum DriverType_e +{ + TYPE_I2C_DRV = 0, + TYPE_SPI_DRV, + TYPE_HWTIMER_DRV, + TYPE_USB_DRV, + TYPE_CAN_DRV, + TYPE_WDT_DRV, + TYPE_SDIO_DRV, + TYPE_TOUCH_DRV, + TYPE_LCD_DRV, + TYPE_PIN_DRV, + TYPE_RTC_DRV, + TYPE_SERIAL_DRV, + TYPE_DRV_END, +}; + +enum DriverState +{ + DRV_INIT = 0, + DRV_INSTALL, + DRV_UNINSTALL, +}; + +struct BusConfigureInfo +{ + int configure_cmd; + void *private_data; +}; + +struct BusBlockReadParam +{ + x_OffPos pos; + void* buffer; + x_size_t size; + x_size_t read_length; +}; + +struct BusBlockWriteParam +{ + x_OffPos pos; + const void* buffer; + x_size_t size; +}; + +struct HalDevBlockParam +{ + uint32 cmd; + struct DeviceBlockArrange dev_block; + struct DeviceBlockAddr *dev_addr; +}; + +struct HalDevDone +{ + 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 HardwareDev +{ + int8 dev_name[NAME_NUM_MAX]; + enum DevType dev_type; + enum DevState dev_state; + + const struct HalDevDone *dev_done; + + int (*dev_recv_callback) (void *dev, x_size_t length); + int (*dev_block_control) (struct HardwareDev *dev, struct HalDevBlockParam *block_param); + + struct Bus *owner_bus; + void *private_data; + + int32 dev_sem; + + DoubleLinklistType dev_link; +}; + +struct Driver +{ + int8 drv_name[NAME_NUM_MAX]; + enum DriverType_e driver_type; + enum DriverState driver_state; + + uint32 (*configure)(void *drv, struct BusConfigureInfo *configure_info); + + struct Bus *owner_bus; + void *private_data; + + DoubleLinklistType driver_link; +}; + +struct Bus +{ + int8 bus_name[NAME_NUM_MAX]; + enum BusType_e bus_type; + enum BusState bus_state; + + int32 (*match)(struct Driver *driver, struct HardwareDev *device); + + int bus_lock; + + struct HardwareDev *owner_haldev; + struct Driver *owner_driver; + + void *private_data; + + /*manage the drv of the bus*/ + uint8 driver_cnt; + uint8 bus_drvlink_flag; + DoubleLinklistType bus_drvlink; + + /*manage the dev of the bus*/ + uint8 haldev_cnt; + uint8 bus_devlink_flag; + DoubleLinklistType bus_devlink; + + uint8 bus_cnt; + uint8 bus_link_flag; + DoubleLinklistType bus_link; +}; + +/*Register the BUS,manage with the double linklist*/ +int BusRegister(struct Bus *bus); + +/*Release the BUS framework*/ +int BusRelease(struct Bus *bus); + +/*Unregister a certain kind of BUS*/ +int BusUnregister(struct Bus *bus); + +/*Register the driver to the bus*/ +int DriverRegisterToBus(struct Bus *bus, struct Driver *driver); + +/*Register the device to the bus*/ +int DeviceRegisterToBus(struct Bus *bus, struct HardwareDev *device); + +/*Delete the driver from the bus*/ +int DriverDeleteFromBus(struct Bus *bus, struct Driver *driver); + +/*Delete the device from the bus*/ +int DeviceDeleteFromBus(struct Bus *bus, struct HardwareDev *device); + +/*Find the bus with bus name*/ +BusType BusFind(const char *bus_name); + +/*Find the driver of cetain bus*/ +DriverType BusFindDriver(struct Bus *bus, const char *driver_name); + +/*Find the device of certain bus*/ +HardwareDevType BusFindDevice(struct Bus *bus, const char *device_name); + +/*Dev receive data callback function*/ +uint32 BusDevRecvCallback(struct HardwareDev *dev, int (*dev_recv_callback) (void *dev, x_size_t length)); + +/*Open the device of the bus*/ +uint32 BusDevOpen(struct HardwareDev *dev); + +/*Close the device of the bus*/ +uint32 BusDevClose(struct HardwareDev *dev); + +/*Write data to the device*/ +uint32 BusDevWriteData(struct HardwareDev *dev, struct BusBlockWriteParam *write_param); + +/*Read data from the device*/ +uint32 BusDevReadData(struct HardwareDev *dev, struct BusBlockReadParam *read_param); + +/*Configure the driver of the bus*/ +uint32 BusDrvConfigure(struct Driver *drv, struct BusConfigureInfo *configure_info); + +/*Obtain the bus using a certain dev*/ +int DeviceObtainBus(struct Bus *bus, struct HardwareDev *dev, const char *drv_name, struct BusConfigureInfo *configure_info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/APP_Framework/Framework/control/plc/shared/plc.c b/APP_Framework/Framework/control/plc/shared/plc.c index b30206836..c2a194dfd 100755 --- a/APP_Framework/Framework/control/plc/shared/plc.c +++ b/APP_Framework/Framework/control/plc/shared/plc.c @@ -18,15 +18,23 @@ * @date 2021.12.15 */ -#include "../interoperability/opcua/open62541.h" +//#include "open62541.h" #include "plc.h" +#include "plc_bus.h" +#include "plc_dev.h" +#define PLC_BUS_NAME "plc bus" +#define PLC_DRV_NAME "plc driver" struct PlcDevice plc_device; +struct PlcBus plc_bus; +struct PlcDriver plc_drv; + // open and connect PLC device void plc_open(struct PlcDevice *pdev) { + } // close and disconnect PLC device @@ -52,6 +60,15 @@ void plc_ioctl(struct PlcDevice *pdev, int cmd, void *arg) void plc_init(struct PlcDevice *plc_dev) { + PlcBusInit(&plc_bus, PLC_BUS_NAME); + PlcDriverInit(&plc_drv, PLC_DRV_NAME); } +void test_plc_bus(int argc, char *argv[]) +{ + plc_init(NULL); +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), + plc, test_plc_bus, test PLC); diff --git a/APP_Framework/Framework/control/plc/shared/plc.h b/APP_Framework/Framework/control/plc/shared/plc.h index a36ef33b8..d2df78d1f 100755 --- a/APP_Framework/Framework/control/plc/shared/plc.h +++ b/APP_Framework/Framework/control/plc/shared/plc.h @@ -15,10 +15,13 @@ * @brief plc relative definition and structure * @version 1.0 * @author AIIT XUOS Lab - * @date 2021.12.15 + * @date 2022-01-24 */ -#include "xs_klist.h" +#ifndef __PLC_H_ +#define __PLC_H_ + +#include "list.h" #define IP_ADDR_SIZE 32 #define PLC_NAME_SIZE 32 @@ -77,7 +80,7 @@ enum PlcCtlType { enum PlcIndHybridNet { - //PLC Field Bus + // PLC Field Bus PLC_IND_FIELD_MODBUS_485, PLC_IND_FIELD_PROFIBUS, PLC_IND_FIELD_CANOPEN, @@ -91,7 +94,7 @@ enum PlcIndHybridNet PLC_IND_ENET_SERCOS, PLC_IND_ENET_OPCUA, - //PLC wireless net + // PLC wireless net PLC_IND_WIRELESS }; @@ -113,12 +116,13 @@ struct PlcInterface // identify PLC device struct PlcDevice { - const char name[PLC_NAME_SIZE]; /* name of the device */ + char name[PLC_NAME_SIZE]; /* name of the device */ enum PlcCtlType type; /* PLC Control Type */ struct PlcInfo info;/* Plc info, such as vendor name and model name */ union PlcCfg cfg; struct PlcOps ops; /* filesystem-like APIs for data transferring */ struct PlcInterface interface; /* protocols used for transferring data from program to plc */ - DoubleLinklistType link;/* link list node */ + DoublelistType link;/* link list node */ }; +#endif diff --git a/APP_Framework/Framework/control/plc/shared/plc_bus.c b/APP_Framework/Framework/control/plc/shared/plc_bus.c new file mode 100755 index 000000000..5601ea9f8 --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_bus.c @@ -0,0 +1,117 @@ +/* +* 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_plc.c +* @brief register plc bus function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-01-24 +*/ + +#include "plc_bus.h" +#include "plc_dev.h" + +int PlcBusInit(struct PlcBus *plc_bus, const char *bus_name) +{ + NULL_PARAM_CHECK(plc_bus); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + if (BUS_INSTALL != plc_bus->bus.bus_state) { + strncpy(plc_bus->bus.bus_name, bus_name, NAME_NUM_MAX); + + plc_bus->bus.bus_type = TYPE_SPI_BUS; + plc_bus->bus.bus_state = BUS_INSTALL; + plc_bus->bus.private_data = plc_bus->private_data; + + ret = BusRegister(&plc_bus->bus); + if (EOK != ret) { + KPrintf("PlcBusInit BusRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("PlcBusInit BusRegister bus has been register state%u\n", plc_bus->bus.bus_state); + } + + return ret; +} + +int PlcDriverInit(struct PlcDriver *plc_driver, const char *driver_name) +{ + NULL_PARAM_CHECK(plc_driver); + NULL_PARAM_CHECK(driver_name); + + x_err_t ret = EOK; + + if (DRV_INSTALL != plc_driver->driver.driver_state) { + plc_driver->driver.driver_type = TYPE_SPI_DRV; + plc_driver->driver.driver_state = DRV_INSTALL; + + strncpy(plc_driver->driver.drv_name, driver_name, NAME_NUM_MAX); + + plc_driver->driver.configure = plc_driver->configure; + + ret = PlcDriverRegister(&plc_driver->driver); + if (EOK != ret) { + KPrintf("PlcDriverInit DriverRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("PlcDriverInit DriverRegister driver has been register state%u\n", plc_driver->driver.driver_state); + } + + return ret; +} + +int PlcReleaseBus(struct PlcBus *plc_bus) +{ + NULL_PARAM_CHECK(plc_bus); + + return BusRelease(&plc_bus->bus); +} + +int PlcDriverAttachToBus(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("PlcDriverAttachToBus find plc bus error!name %s\n", bus_name); + return ERROR; + } + +// if (TYPE_SPI_BUS == bus->bus_type) { + driver = PlcDriverFind(drv_name, TYPE_SPI_DRV); + if (NONE == driver) { + KPrintf("PlcDriverAttachToBus find plc driver error!name %s\n", drv_name); + return ERROR; + } + + if (TYPE_SPI_DRV == driver->driver_type) { + ret = DriverRegisterToBus(bus, driver); + if (EOK != ret) { + KPrintf("PlcDriverAttachToBus DriverRegisterToBus error %u\n", ret); + return ERROR; + } + } +// } + + return ret; +} diff --git a/APP_Framework/Framework/control/plc/shared/plc_bus.h b/APP_Framework/Framework/control/plc/shared/plc_bus.h new file mode 100755 index 000000000..091bb4a73 --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_bus.h @@ -0,0 +1,65 @@ +/* +* 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_plc.h +* @brief define PLC bus and drv function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-01-24 +*/ + +#ifndef BUS_PLC_H +#define BUS_PLC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "transform.h" +#include "plc.h" + +struct PlcDriver +{ + struct Driver driver; + uint32 (*configure) (void *drv, struct BusConfigureInfo *configure_info); +}; + +struct PlcBus +{ + struct Bus bus; + void *private_data; +}; + +/*Register the plc bus*/ +int PlcBusInit(struct PlcBus *plc_bus, const char *bus_name); + +/*Register the plc driver*/ +int PlcDriverInit(struct PlcDriver *plc_driver, const char *driver_name); + +/*Release the plc device*/ +int PlcReleaseBus(struct PlcBus *plc_bus); + +/*Register the plc driver to the plc bus*/ +int PlcDriverAttachToBus(const char *drv_name, const char *bus_name); + +/*Register the driver, manage with the double linklist*/ +int PlcDriverRegister(struct Driver *driver); + +/*Find the register driver*/ +DriverType PlcDriverFind(const char *drv_name, enum DriverType_e drv_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/APP_Framework/Framework/control/plc/shared/plc_dev.c b/APP_Framework/Framework/control/plc/shared/plc_dev.c new file mode 100755 index 000000000..6c6aebf86 --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_dev.c @@ -0,0 +1,239 @@ +/* +* 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_plc.c +* @brief register plc dev function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-01-24 +*/ + +#include "transform.h" +#include "plc.h" +#include "plc_bus.h" +#include "plc_dev.h" + +static DoublelistType plcdev_linklist; + +/*Create the plc device linklist*/ +static void PlcDeviceLinkInit() +{ + AppInitDoubleList(&plcdev_linklist); +} + +static uint32 PlcDeviceOpen(void *dev) +{ + NULL_PARAM_CHECK(dev); + + PlcDevConfigureCs(dev, 1, 0); + + return EOK; +} + +static uint32 PlcDeviceClose(void *dev) +{ + NULL_PARAM_CHECK(dev); + + PlcDevConfigureCs(dev, 0, 1); + + return EOK; +} + +static uint32 PlcDeviceWrite(void *dev, struct BusBlockWriteParam *write_param) +{ + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(write_param); + + int ret; + struct PlcDevice *plc_dev = (struct PlcDevice *)dev; + struct PlcDataStandard *plc_msg; + + plc_msg = (struct PlcDataStandard *)x_malloc(sizeof(struct PlcDataStandard)); + if (NONE == plc_msg) { + KPrintf("PlcDeviceWrite x_malloc msg error\n"); + x_free(plc_msg); + return ERROR; + } + + //memset(plc_msg, 0, sizeof(struct PlcDataStandard)); + + plc_msg->tx_buff = (uint8 *)write_param->buffer; + plc_msg->rx_buff = NONE; + plc_msg->length = write_param->size; + plc_msg->plc_chip_select = 0; + plc_msg->plc_cs_release = 0; + plc_msg->next = NONE; + + ret = plc_dev->ops.write(plc_dev, plc_msg, plc_msg->length); + x_free(plc_msg); + + return ret; +} + +static uint32 PlcDeviceRead(void *dev, struct BusBlockReadParam *read_param) +{ + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(read_param); + + int ret; + struct PlcDevice *plc_dev = (struct PlcDevice *)dev; + struct PlcDataStandard *plc_msg; + + plc_msg = (struct PlcDataStandard *)x_malloc(sizeof(struct PlcDataStandard)); + if (NONE == plc_msg) { + KPrintf("PlcDeviceRead x_malloc msg error\n"); + x_free(plc_msg); + return ERROR; + } + + //memset(plc_msg, 0, sizeof(struct PlcDataStandard)); + + plc_msg->tx_buff = NONE; + plc_msg->rx_buff = (uint8 *)read_param->buffer; + plc_msg->length = read_param->size; + plc_msg->plc_chip_select = 0; + plc_msg->plc_cs_release = 0; + plc_msg->next = NONE; + + ret = plc_dev->ops.read(plc_dev, plc_msg, plc_msg->length); + x_free(plc_msg); + + return ret; +} + +static const struct HalDevDone dev_done = +{ + .open = PlcDeviceOpen, + .close = PlcDeviceClose, + .write = PlcDeviceWrite, + .read = PlcDeviceRead, +}; + +struct PlcDevice *PlcDeviceFind(const char *dev_name, enum PlcCtlType ctl_type) +{ + NULL_PARAM_CHECK(dev_name); + + struct PlcDevice *plc_dev = NONE; + + DoublelistType *node = NONE; + DoublelistType *head = &plcdev_linklist; + + for (node = head->node_next; node != head; node = node->node_next) { + plc_dev = SYS_DOUBLE_LINKLIST_ENTRY(node, struct PlcDevice, link); + if ((!strcmp(plc_dev->name, dev_name)) && (ctl_type == plc_dev->type)) { + return plc_dev; + } + } + + KPrintf("PlcDeviceFind cannot find the %s device.return NULL\n", dev_name); + return NONE; +} + +int PlcDeviceRegister(struct PlcDevice *plc_device, void *plc_param, const char *device_name) +{ + NULL_PARAM_CHECK(plc_device); + NULL_PARAM_CHECK(device_name); + + x_err_t ret = EOK; + static x_bool dev_link_flag = RET_FALSE; + + if (!dev_link_flag) { + PlcDeviceLinkInit(); + dev_link_flag = RET_TRUE; + } + + if ("" != plc_device->name) { + strncpy(plc_device->name, device_name, PLC_NAME_SIZE); +// plc_device->haldev.dev_type = TYPE_SPI_DEV; +// plc_device->haldev.dev_state = DEV_INSTALL; +// +// //only plc bus dev need to register dev_done +// if (RET_TRUE != plc_device->plc_dev_flag) { +// plc_device->haldev.dev_done = &dev_done; +// } +// +// plc_device->haldev.private_data = plc_param; + + AppDoubleListInsertNodeAfter(&plcdev_linklist, &(plc_device->link)); + } else { +// KPrintf("PlcDeviceRegister device has been register state%u\n", plc_device->haldev.dev_state); + } + + return ret; +} + +int PlcDeviceAttachToBus(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 PlcDevice *device; + struct HardwareDev *hard_dev; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("PlcDeviceAttachToBus find plc bus error!name %s\n", bus_name); + return ERROR; + } + +// if (TYPE_PLC_BUS == bus->bus_type) { + device = PlcDeviceFind(dev_name, PLC_ABILITY_HSC); + if (NONE == device) { + KPrintf("PlcDeviceAttachToBus find plc device error!name %s\n", dev_name); + return ERROR; + } + + if (PLC_ABILITY_HSC == device->type) { + ret = DeviceRegisterToBus(bus, hard_dev); + if (EOK != ret) { + KPrintf("PlcDeviceAttachToBus DeviceRegisterToBus error %u\n", ret); + return ERROR; + } + } +// } + + return EOK; +} + +int PlcDevConfigureCs(struct PlcDevice *dev, uint8 plc_chip_select, uint8 plc_cs_release) +{ + NULL_PARAM_CHECK(dev); + + int ret; + struct PlcDevice *plc_dev = (struct PlcDevice *)dev; + struct PlcDataStandard *msg; + + msg = (struct PlcDataStandard *)x_malloc(sizeof(struct PlcDataStandard)); + if (NONE == msg) { + KPrintf("PlcDevConfigureCs x_malloc msg error\n"); + x_free(msg); + return ERROR; + } + + //memset(msg, 0, sizeof(struct PlcDataStandard)); + msg->length = 0; + msg->rx_buff = NONE; + msg->tx_buff = NONE; + msg->next = NONE; + msg->plc_chip_select = plc_chip_select; + msg->plc_cs_release = plc_cs_release; + + ret = plc_dev->ops.write(plc_dev, msg, msg->length); + + x_free(msg); + return ret; +} + diff --git a/APP_Framework/Framework/control/plc/shared/plc_dev.h b/APP_Framework/Framework/control/plc/shared/plc_dev.h new file mode 100755 index 000000000..778188e94 --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_dev.h @@ -0,0 +1,140 @@ +/* +* 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_plc.h +* @brief define plc dev function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-01-24 +*/ + +#ifndef DEV_PLC_H +#define DEV_PLC_H + +#include + +#ifdef __cpluspluss +extern "C" { +#endif + +#define PLC_MAX_CLOCK 40000000 +#define plc_device_max_num 4 + +#define PLC_LINE_CPHA (1 << 0) +#define PLC_LINE_CPOL (1 << 1) + +#define PLC_LSB (0 << 2) +#define PLC_MSB (1 << 2) + +#define PLC_MASTER (0 << 3) +#define DEV_PLC_SLAVE (1 << 3) + +#define PLC_MODE_0 (0 | 0) +#define PLC_MODE_1 (0 | PLC_LINE_CPHA) +#define PLC_MODE_2 (PLC_LINE_CPOL | 0) +#define PLC_MODE_3 (PLC_LINE_CPOL | PLC_LINE_CPHA) +#define PLC_MODE_MASK (PLC_LINE_CPHA | PLC_LINE_CPOL | PLC_MSB) + +#define PLC_CS_HIGH (1 << 4) +#define PLC_NO_CS (1 << 5) +#define PLC_3WIRE (1 << 6) +#define PLC_READY (1 << 7) + +struct PlcDataStandard +{ + uint8 plc_chip_select; + uint8 plc_cs_release; + + const uint8 *tx_buff; + uint32 tx_len; + + uint8 *rx_buff; + uint32 rx_len; + + uint32 length; + struct PlcDataStandard *next; +}; + +struct PlcMasterParam +{ + uint8 plc_work_mode;//CPOL CPHA + uint8 plc_frame_format;//frame format + uint8 plc_data_bit_width;//bit width + uint8 plc_data_endian;//little endian: big endian + uint32 plc_maxfrequency;//work frequency +}; + +struct PlcDmaParam +{ + uint8 plc_master_id; + uint8 plc_dmac_txchannel; + uint8 plc_dmac_rxchannel; +}; + +struct PlcSlaveParam +{ + uint8 plc_slave_id; + uint8 plc_cs_gpio_pin; + uint8 plc_cs_select_id; +}; + +typedef struct +{ + struct PlcDmaParam *plc_dma_param; + + struct PlcSlaveParam *plc_slave_param; + + struct PlcMasterParam *plc_master_param; + +}PlcDeviceParam; + +struct PlcDevice; + +struct PlcDevDone +{ + uint32 (*dev_open) (struct PlcDevice *dev); + uint32 (*dev_close) (struct PlcDevice *dev); + uint32 (*dev_write) (struct PlcDevice *dev, struct PlcDataStandard *msg); + uint32 (*dev_read) (struct PlcDevice *dev, struct PlcDataStandard *msg); +}; + +struct PlcHardwareDevice +{ + struct HardwareDev haldev; + PlcDeviceParam plc_param; + + x_bool plc_dev_flag; + + const struct PlcDevDone *plc_dev_done; + + void *private_data; +}; + +/*Register the plc device*/ +int PlcDeviceRegister(struct PlcDevice *plc_device, void *plc_param, const char *device_name); + +/*Register the plc device to the plc bus*/ +int PlcDeviceAttachToBus(const char *dev_name, const char *bus_name); + +/*Find the register plc device*/ +struct PlcDevice *PlcDeviceFind(const char *dev_name, enum PlcCtlType dev_type); + +/*Configure the cs pin of plc dev*/ +int PlcDevConfigureCs(struct PlcDevice *dev, uint8 plc_chip_select, uint8 plc_cs_release); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/APP_Framework/Framework/control/plc/shared/plc_drv.c b/APP_Framework/Framework/control/plc/shared/plc_drv.c new file mode 100755 index 000000000..3dee75a2f --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_drv.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_plc.c +* @brief register plc drv function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-01-24 +*/ + +#include "transform.h" +#include "plc_bus.h" +#include "plc_dev.h" + +static DoubleLinklistType plcdrv_linklist; + +/*Create the driver linklist*/ +static void PlcDrvLinkInit() +{ + InitDoubleLinkList(&plcdrv_linklist); +} + +DriverType PlcDriverFind(const char *drv_name, enum DriverType_e drv_type) +{ + NULL_PARAM_CHECK(drv_name); + + struct Driver *driver = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &plcdrv_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("PlcDriverFind cannot find the %s driver.return NULL\n", drv_name); + return NONE; +} + +int PlcDriverRegister(struct Driver *driver) +{ + NULL_PARAM_CHECK(driver); + + x_err_t ret = EOK; + static x_bool driver_link_flag = RET_FALSE; + + if (!driver_link_flag) { + PlcDrvLinkInit(); + driver_link_flag = RET_TRUE; + } + + DoubleLinkListInsertNodeAfter(&plcdrv_linklist, &(driver->driver_link)); + + return ret; +} + diff --git a/APP_Framework/Framework/transform_layer/nuttx/transform.h b/APP_Framework/Framework/transform_layer/nuttx/transform.h index 7f21e332a..38980b450 100644 --- a/APP_Framework/Framework/transform_layer/nuttx/transform.h +++ b/APP_Framework/Framework/transform_layer/nuttx/transform.h @@ -107,7 +107,7 @@ struct PinDevIrq struct PinParam { int cmd;//< cmd:GPIO_CONFIG_MODE/GPIO_IRQ_REGISTER/GPIO_IRQ_FREE/GPIO_IRQ_DISABLE/GPIO_IRQ_ENABLE - long pin;//< pin number + long pin;//< pin number int mode;//< pin mode: input/output struct PinDevIrq irq_set;//< pin irq set uint64 arg; @@ -170,9 +170,6 @@ int PrivMutexDelete(pthread_mutex_t *p_mutex); int PrivMutexObtain(pthread_mutex_t *p_mutex); int PrivMutexAbandon(pthread_mutex_t *p_mutex); - - - /*********************semaphore**********************/ int PrivSemaphoreCreate(sem_t *sem, int pshared, unsigned int value); diff --git a/Ubiquitous/XiUOS/board/ok1052-c/include/pin_mux.h b/Ubiquitous/XiUOS/board/ok1052-c/include/pin_mux.h index 52b54b8c0..f45a8ccc0 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/include/pin_mux.h +++ b/Ubiquitous/XiUOS/board/ok1052-c/include/pin_mux.h @@ -72,6 +72,7 @@ void BOARD_InitBootPins(void); */ void BOARD_InitPins(void); void BOARD_InitI2C1Pins(void); +void BOARD_InitSPIPins(void); #if defined(__cplusplus) } diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/adc_interrupt.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/adc_interrupt.c index ebc2c1f3c..c51cc2c9c 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/adc_interrupt.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/adc_interrupt.c @@ -110,8 +110,6 @@ int test_adc(void) adc_config_t adcConfigStrcut; adc_channel_config_t adcChannelConfigStruct; -// TestAdcInit(); - EnableIRQ(DEMO_ADC_IRQn); adc_print("\r\nADC interrupt Example.\r\n"); @@ -169,9 +167,7 @@ int test_adc(void) for each command. */ ADC_SetChannelConfig(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP, &adcChannelConfigStruct); - while (g_AdcConversionDoneFlag == false) - { - } + while (g_AdcConversionDoneFlag == false); adc_print("ADC Value: %d\r\n", g_AdcConversionValue); adc_print("ADC Interrupt Counter: %d\r\n", g_AdcInterruptCounter); } diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/common/pin_mux.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/common/pin_mux.c index 92a6722c4..118a9529a 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/common/pin_mux.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/common/pin_mux.c @@ -88,6 +88,128 @@ BOARD_InitPins: * Description : Configures pin routing and optionally pin electrical features. * * END ****************************************************************************************************************/ + +void BOARD_InitSPIPins(void){ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 is configured as LPUART1_TX */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 is configured as LPUART1_RX */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_SD_B1_05_FLEXSPIA_DQS, /* GPIO_SD_B1_05 is configured as FLEXSPIA_DQS */ + 1U); /* Software Input On Field: Force input path of pad GPIO_SD_B1_05 */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_SD_B1_06_FLEXSPIA_SS0_B, /* GPIO_SD_B1_06 is configured as FLEXSPIA_SS0_B */ + 1U); /* Software Input On Field: Force input path of pad GPIO_SD_B1_06 */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_SD_B1_07_FLEXSPIA_SCLK, /* GPIO_SD_B1_07 is configured as FLEXSPIA_SCLK */ + 1U); /* Software Input On Field: Force input path of pad GPIO_SD_B1_07 */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_SD_B1_08_FLEXSPIA_DATA00, /* GPIO_SD_B1_08 is configured as FLEXSPIA_DATA00 */ + 1U); /* Software Input On Field: Force input path of pad GPIO_SD_B1_08 */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_SD_B1_09_FLEXSPIA_DATA01, /* GPIO_SD_B1_09 is configured as FLEXSPIA_DATA01 */ + 1U); /* Software Input On Field: Force input path of pad GPIO_SD_B1_09 */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_SD_B1_10_FLEXSPIA_DATA02, /* GPIO_SD_B1_10 is configured as FLEXSPIA_DATA02 */ + 1U); /* Software Input On Field: Force input path of pad GPIO_SD_B1_10 */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_SD_B1_11_FLEXSPIA_DATA03, /* GPIO_SD_B1_11 is configured as FLEXSPIA_DATA03 */ + 1U); /* Software Input On Field: Force input path of pad GPIO_SD_B1_11 */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 PAD functional properties : */ + 0x10B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 PAD functional properties : */ + 0x10B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_SD_B1_05_FLEXSPIA_DQS, /* GPIO_SD_B1_05 PAD functional properties : */ + 0x10F1u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/6 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_SD_B1_06_FLEXSPIA_SS0_B, /* GPIO_SD_B1_06 PAD functional properties : */ + 0x10F1u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/6 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_SD_B1_07_FLEXSPIA_SCLK, /* GPIO_SD_B1_07 PAD functional properties : */ + 0x10F1u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/6 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_SD_B1_08_FLEXSPIA_DATA00, /* GPIO_SD_B1_08 PAD functional properties : */ + 0x10F1u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/6 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_SD_B1_09_FLEXSPIA_DATA01, /* GPIO_SD_B1_09 PAD functional properties : */ + 0x10F1u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/6 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_SD_B1_10_FLEXSPIA_DATA02, /* GPIO_SD_B1_10 PAD functional properties : */ + 0x10F1u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/6 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_SD_B1_11_FLEXSPIA_DATA03, /* GPIO_SD_B1_11 PAD functional properties : */ + 0x10F1u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/6 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ +} + + void BOARD_InitPins(void) { CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */ @@ -297,6 +419,7 @@ void BOARD_InitPins(void) { Pull / Keep Select Field: Pull Pull Up / Down Config. Field: 100K Ohm Pull Up Hyst. Enable Field: Hysteresis Disabled */ + } void BOARD_InitI2C1Pins(void) { diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/Makefile index ec7e13636..6d38bf1de 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/Makefile +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := fsl_lpspi.c lpspi_interrupt.c +SRC_FILES := fsl_lpspi.c lpspi_interrupt.c connect_flash_spi.c flexspi_nor_flash_ops.c flexspi_nor_polling_transfer.c fsl_flexspi.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/app.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/app.h new file mode 100755 index 000000000..c74f6ba10 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/app.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef _APP_H_ +#define _APP_H_ + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*${macro:start}*/ +#define EXAMPLE_FLEXSPI FLEXSPI +#define FLASH_SIZE 0x2000 /* 64Mb/KByte */ +#define EXAMPLE_FLEXSPI_AMBA_BASE FlexSPI_AMBA_BASE +#define FLASH_PAGE_SIZE 256 +#define EXAMPLE_SECTOR 0 +#define SECTOR_SIZE 0x1000 /* 4K */ +#define EXAMPLE_FLEXSPI_CLOCK kCLOCK_FlexSpi + +#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 7 +#define NOR_CMD_LUT_SEQ_IDX_READ_FAST 13 +#define NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD 0 +#define NOR_CMD_LUT_SEQ_IDX_READSTATUS 1 +#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE 2 +#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 3 +#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE 6 +#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD 4 +#define NOR_CMD_LUT_SEQ_IDX_READID 8 +#define NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG 9 +#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10 +#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 11 +#define NOR_CMD_LUT_SEQ_IDX_READSTATUSREG 12 +#define NOR_CMD_LUT_SEQ_IDX_ERASECHIP 5 + +#define CUSTOM_LUT_LENGTH 60 +#define FLASH_QUAD_ENABLE 0x40 +#define FLASH_BUSY_STATUS_POL 1 +#define FLASH_BUSY_STATUS_OFFSET 0 + +/*${macro:end}*/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*${prototype:start}*/ +void BOARD_InitHardware(void); + +static inline void flexspi_clock_init(void) +{ + const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U}; + + CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll); + CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 24); /* Set PLL3 PFD0 clock 360MHZ. */ + CLOCK_SetMux(kCLOCK_FlexspiMux, 0x3); /* Choose PLL3 PFD0 clock as flexspi source clock. */ + CLOCK_SetDiv(kCLOCK_FlexspiDiv, 2); /* flexspi clock 120M. */ +} +/*${prototype:end}*/ + +#endif /* _APP_H_ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/connect_flash_spi.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/connect_flash_spi.c new file mode 100755 index 000000000..f1380dce1 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/connect_flash_spi.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-11-27 SummerGift add spi flash port file + */ + +/** +* @file connect_flash_spi.c +* @brief support stm32f407-st-discovery-board spi flash function and register to bus framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +/************************************************* +File name: connect_flash_spi.c +Description: support stm32f407-st-discovery-board spi flash bus register function +Others: take RT-Thread v4.0.2/bsp/stm32/stm32f407-atk-explorer/board/ports/spi-flash-init.c + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2021-04-25 +Author: AIIT XUOS Lab +Modification: +1. support stm32f407-st-discovery-board spi flash register to spi bus +2. support stm32f407-st-discovery-board spi flash init +*************************************************/ + +//#include "connect_spi.h" +#include "flash_spi.h" + +int FlashW25qxxSpiDeviceInit(void) +{ +#ifdef BSP_USING_SPI1 + +// __IO uint32_t tmpreg = 0x00U; +// RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; +// tmpreg = RCC->AHB1ENR & RCC_AHB1ENR_GPIOBEN; +// (void)tmpreg; +// +// if (EOK != HwSpiDeviceAttach(SPI_BUS_NAME_1, "spi1_dev0", GPIOB, GPIO_Pin_0)) { +// return ERROR; +// } +// +// if (NONE == SpiFlashInit(SPI_BUS_NAME_1, "spi1_dev0", SPI_1_DRV_NAME, "spi1_W25Q64")) { +// return ERROR; +// } + +#endif + + return EOK; +} \ No newline at end of file diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/connect_spi.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/connect_spi.c new file mode 100755 index 000000000..5366f58e8 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/connect_spi.c @@ -0,0 +1,1639 @@ +/* + * Copyright (c) 2020 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-11-5 SummerGift first version + * 2018-12-11 greedyhao Porting for stm32f7xx + * 2019-01-03 zylx modify DMA initialization and spixfer function + * 2020-01-15 whj4674672 Porting for stm32h7xx + * 2020-06-18 thread-liu Porting for stm32mp1xx + * 2020-10-14 Dozingfiretruck Porting for stm32wbxx + */ + +/** +* @file connect_spi.c +* @brief support stm32f407-st-discovery-board spi function and register to bus framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +/************************************************* +File name: connect_spi.c +Description: support stm32f407-st-discovery-board spi configure and spi bus register function +Others: take RT-Thread v4.0.2/bsp/stm32/libraries/HAL_Drivers/drv_spi.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2021-04-25 +Author: AIIT XUOS Lab +Modification: +1. support stm32f407-st-discovery-board spi configure, write and read +2. support stm32f407-st-discovery-board spi bus device and driver register +*************************************************/ + +#include "stm32f4xx.h" +#include "connect_spi.h" +#include "board.h" +#include "misc.h" +#include "hardware_spi.h" +#include "hardware_dma.h" +#include "hardware_gpio.h" +#include "hardware_rcc.h" + +#include +#include + +/* SPI GPIO define */ +#ifdef BSP_USING_SPI1 +#define SPI1_GPIO_NSS GPIO_Pin_4 +#define SPI1_NSS_PIN_SOURCE GPIO_PinSource4 +#define SPI1_GPIO_SCK GPIO_Pin_5 +#define SPI1_SCK_PIN_SOURCE GPIO_PinSource5 +#define SPI1_GPIO_MISO GPIO_Pin_6 +#define SPI1_MISO_PIN_SOURCE GPIO_PinSource6 +#define SPI1_GPIO_MOSI GPIO_Pin_7 +#define SPI1_MOSI_PIN_SOURCE GPIO_PinSource7 +#define SPI1_GPIO GPIOA +#define SPI1_GPIO_RCC RCC_AHB1Periph_GPIOA +#define RCC_APBPeriph_SPI1 RCC_APB2Periph_SPI1 +#endif + +#ifdef BSP_USING_SPI2 +#define SPI2_GPIO_NSS GPIO_Pin_6 +#define SPI2_NSS_PIN_SOURCE GPIO_PinSource6 +#define SPI2_GPIO_SCK GPIO_Pin_13 +#define SPI2_SCK_PIN_SOURCE GPIO_PinSource13 +#define SPI2_GPIO_MISO GPIO_Pin_2 +#define SPI2_MISO_PIN_SOURCE GPIO_PinSource2 +#define SPI2_GPIO_MOSI GPIO_Pin_3 +#define SPI2_MOSI_PIN_SOURCE GPIO_PinSource3 +#define SPI2_GPIO GPIOC +#define SPI2_SCK GPIOB +#define SPI2_GPIO_RCC RCC_AHB1Periph_GPIOC +#define SPI2_GPIO_RCC_SCK RCC_AHB1Periph_GPIOB +#define RCC_APBPeriph_SPI2 RCC_APB1Periph_SPI2 +#endif + +#ifdef BSP_USING_SPI3 +#define SPI3_GPIO_NSS GPIO_Pin_15 +#define SPI3_NSS_PIN_SOURCE GPIO_PinSource15 +#define SPI3_GPIO_SCK GPIO_Pin_10 +#define SPI3_SCK_PIN_SOURCE GPIO_PinSource10 +#define SPI3_GPIO_MISO GPIO_Pin_11 +#define SPI3_MISO_PIN_SOURCE GPIO_PinSource11 +#define SPI3_GPIO_MOSI GPIO_Pin_12 +#define SPI3_MOSI_PIN_SOURCE GPIO_PinSource12 +#define SPI3_GPIO GPIOC +#define SPI3_NSS GPIOA +#define SPI3_GPIO_RCC RCC_AHB1Periph_GPIOC +#define SPI3_GPIO_RCC_NSS RCC_AHB1Periph_GPIOA +#define RCC_APBPeriph_SPI3 RCC_APB2Periph_SPI3 +#endif + +/** + * This function SPI device initialization + * + * @param spi_drv SPI device structure pointer + * + * @param cfg SPI device operating mode configuration structure pointer + * + * @return if successful return EOK + */ + +static x_err_t Stm32SpiInit(struct Stm32Spi *spi_drv, struct SpiMasterParam *cfg) +{ + NULL_PARAM_CHECK(spi_drv); + NULL_PARAM_CHECK(cfg); + + SPI_InitTypeDef *spi_init = &spi_drv->init; + + if (cfg->spi_work_mode & DEV_SPI_SLAVE){ + spi_init->SPI_Mode = SPI_Mode_Slave; + } + else{ + spi_init->SPI_Mode = SPI_Mode_Master; + } + + if (cfg->spi_work_mode & SPI_3WIRE){ + spi_init->SPI_Direction = SPI_Direction_1Line_Rx; + } + else{ + spi_init->SPI_Direction = SPI_Direction_2Lines_FullDuplex; + } + + if (cfg->spi_data_bit_width == 8){ + spi_init->SPI_DataSize = SPI_DataSize_8b; + } + else if (cfg->spi_data_bit_width == 16){ + spi_init->SPI_DataSize = SPI_DataSize_16b; + } + else{ + return EPIO; + } + + if (cfg->spi_work_mode & SPI_LINE_CPHA){ + spi_init->SPI_CPHA = SPI_CPHA_2Edge; + } + else { + spi_init->SPI_CPHA = SPI_CPHA_1Edge; + } + + if (cfg->spi_work_mode & SPI_LINE_CPOL) { + spi_init->SPI_CPOL = SPI_CPOL_High; + } + else{ + spi_init->SPI_CPOL = SPI_CPOL_Low; + } + + if (cfg->spi_work_mode & SPI_NO_CS) { + spi_init->SPI_NSS = SPI_NSS_Soft; + } + else{ + spi_init->SPI_NSS = SPI_NSS_Soft; + } + + uint32_t SPI_APB_CLOCK; + + SPI_APB_CLOCK = system_core_clock>>apb_presc_table[(RCC->CFGR & RCC_CFGR_PPRE2)>> 13U]; + + if (cfg->spi_maxfrequency >= SPI_APB_CLOCK / 2){ + spi_init->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; + } + else if (cfg->spi_maxfrequency >= SPI_APB_CLOCK / 4){ + spi_init->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; + } + else if (cfg->spi_maxfrequency >= SPI_APB_CLOCK / 8){ + spi_init->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; + } + else if (cfg->spi_maxfrequency >= SPI_APB_CLOCK / 16){ + spi_init->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; + } + else if (cfg->spi_maxfrequency >= SPI_APB_CLOCK / 32){ + spi_init->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; + } + else if (cfg->spi_maxfrequency >= SPI_APB_CLOCK / 64){ + spi_init->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; + } + else if (cfg->spi_maxfrequency >= SPI_APB_CLOCK / 128) { + spi_init->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; + } + else { + /* min prescaler 256 */ + spi_init->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; + } + RCC_ClocksTypeDef RCC_ClocksStatus; + RCC_GetClocksFreq(&RCC_ClocksStatus); + + if (cfg->spi_work_mode & SPI_MSB){ + spi_init->SPI_FirstBit = SPI_FirstBit_MSB; /*Highest bit transmit first*/ + } + else{ + spi_init->SPI_FirstBit = SPI_FirstBit_LSB; /*lowest bit transmit first*/ + } + + spi_init->SPI_CRCPolynomial = 7; + + SPI_Init(spi_drv->instance, spi_init); + + SPI_Cmd(spi_drv->instance, ENABLE); + + uint32_t prioritygroup = 0x00U; + /* DMA configuration */ + if (spi_drv->spi_dma_flag & SPI_USING_RX_DMA_FLAG){ + DMA_Init(spi_drv->dma.dma_rx.instance, &spi_drv->dma.dma_rx.init); + + prioritygroup = NVIC_GetPriorityGrouping(); + + NVIC_SetPriority(spi_drv->dma.dma_rx.dma_irq, NVIC_EncodePriority(prioritygroup, 0, 0)); + + NVIC_EnableIRQ(spi_drv->dma.dma_rx.dma_irq); + } + + if (spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG){ + DMA_Init(spi_drv->dma.dma_tx.instance, &spi_drv->dma.dma_tx.init); + + prioritygroup = NVIC_GetPriorityGrouping(); + + NVIC_SetPriority(spi_drv->dma.dma_tx.dma_irq, NVIC_EncodePriority(prioritygroup, 0, 1)); + + NVIC_EnableIRQ(spi_drv->dma.dma_tx.dma_irq); + } + + spi_drv->instance->CR1 |= SPI_CR1_SPE; + + return EOK; +} + +static void DmaSpiConfig(struct SpiBus *spi_bus, uint32_t setting_len, void *rx_base_addr, void *tx_base_addr) +{ + struct Stm32Spi *spi = (struct Stm32Spi *)spi_bus->private_data; + uint32 tmpreg = 0x00U; + NVIC_InitTypeDef NVIC_InitStructure; + + if(spi->spi_dma_flag & SPI_USING_RX_DMA_FLAG) + { + spi->dma.dma_rx.setting_len = setting_len; + DMA_DeInit(spi->dma.dma_rx.instance); + while(DMA_GetCmdStatus(spi->dma.dma_rx.instance) != DISABLE); + spi->dma.dma_rx.init.DMA_Channel = spi->dma.dma_rx.channel; + spi->dma.dma_rx.init.DMA_PeripheralBaseAddr = (uint32_t)&(spi->instance->DR); + spi->dma.dma_rx.init.DMA_Memory0BaseAddr = (uint32_t)rx_base_addr; + spi->dma.dma_rx.init.DMA_DIR = DMA_DIR_PeripheralToMemory; + spi->dma.dma_rx.init.DMA_BufferSize = spi->dma.dma_rx.setting_len; + spi->dma.dma_rx.init.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + spi->dma.dma_rx.init.DMA_MemoryInc = DMA_MemoryInc_Enable; + spi->dma.dma_rx.init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + spi->dma.dma_rx.init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + spi->dma.dma_rx.init.DMA_Mode = DMA_Mode_Normal; + spi->dma.dma_rx.init.DMA_Priority = DMA_Priority_High; + spi->dma.dma_rx.init.DMA_FIFOMode = DMA_FIFOMode_Disable; + spi->dma.dma_rx.init.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; + spi->dma.dma_rx.init.DMA_MemoryBurst = DMA_MemoryBurst_INC4; + spi->dma.dma_rx.init.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4; + DMA_Init(spi->dma.dma_rx.instance, &spi->dma.dma_rx.init); + DMA_ITConfig(spi->dma.dma_rx.instance, DMA_IT_TC, ENABLE); + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); + + DMA_Cmd(spi->dma.dma_rx.instance, ENABLE); + + NVIC_InitStructure.NVIC_IRQChannel = spi->dma.dma_rx.dma_irq; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + tmpreg = 0x00U; + RCC->AHB1ENR |= spi->dma.dma_rx.dma_rcc; + tmpreg = RCC->AHB1ENR & spi->dma.dma_rx.dma_rcc; + (void)tmpreg; + } + + if(spi->spi_dma_flag & SPI_USING_TX_DMA_FLAG) + { + spi->dma.dma_tx.setting_len = setting_len; + DMA_DeInit(spi->dma.dma_tx.instance); + while(DMA_GetCmdStatus(spi->dma.dma_tx.instance) != DISABLE); + spi->dma.dma_tx.init.DMA_PeripheralBaseAddr = (uint32_t)&(spi->instance->DR); + spi->dma.dma_tx.init.DMA_Memory0BaseAddr = (uint32_t)tx_base_addr; + spi->dma.dma_tx.init.DMA_DIR = DMA_DIR_MemoryToPeripheral; + spi->dma.dma_tx.init.DMA_BufferSize = spi->dma.dma_tx.setting_len; + spi->dma.dma_tx.init.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + spi->dma.dma_tx.init.DMA_MemoryInc = DMA_MemoryInc_Enable; + spi->dma.dma_tx.init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + spi->dma.dma_tx.init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + spi->dma.dma_tx.init.DMA_Mode = DMA_Mode_Normal; + spi->dma.dma_tx.init.DMA_Priority = DMA_Priority_Low; + spi->dma.dma_tx.init.DMA_FIFOMode = DMA_FIFOMode_Disable; + spi->dma.dma_tx.init.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; + spi->dma.dma_tx.init.DMA_MemoryBurst = DMA_MemoryBurst_INC4; + spi->dma.dma_tx.init.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4; + DMA_Init(spi->dma.dma_tx.instance, &spi->dma.dma_tx.init); + DMA_ITConfig(spi->dma.dma_tx.instance, DMA_IT_TC, ENABLE); + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); + + DMA_Cmd(spi->dma.dma_tx.instance, ENABLE); + + NVIC_InitStructure.NVIC_IRQChannel = spi->dma.dma_tx.dma_irq; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + tmpreg = 0x00U; + RCC->AHB1ENR |= spi->dma.dma_rx.dma_rcc; + tmpreg = RCC->AHB1ENR & spi->dma.dma_rx.dma_rcc; + (void)tmpreg; + } +} + + +static void DmaRxDoneIsr(struct SpiBus *spi_bus) +{ + struct Stm32Spi *spi = (struct Stm32Spi *) spi_bus->bus.private_data; + x_size_t recv_len; + x_base level; + + if (DMA_GetFlagStatus(spi->dma.dma_rx.instance, spi->spi_dma_flag) != RESET) + { + level = CriticalAreaLock(); + + recv_len = spi->dma.dma_rx.setting_len - spi->dma.dma_rx.last_index; + spi->dma.dma_rx.last_index = 0; + CriticalAreaUnLock(level); + DMA_ClearFlag(spi->dma.dma_rx.instance, spi->spi_dma_flag); + } +} + + +static void DmaTxDoneIsr(struct SpiBus *spi_bus) +{ + struct Stm32Spi *spi = (struct Stm32Spi *) spi_bus->bus.private_data; + x_size_t send_len; + x_base level; + + if (DMA_GetFlagStatus(spi->dma.dma_tx.instance, spi->spi_dma_flag) != RESET) + { + level = CriticalAreaLock(); + + send_len = spi->dma.dma_tx.setting_len - spi->dma.dma_tx.last_index; + spi->dma.dma_tx.last_index = 0; + CriticalAreaUnLock(level); + DMA_ClearFlag(spi->dma.dma_tx.instance, spi->spi_dma_flag); + } +} + + +static int SpiWaitUntilTimeout(SPI_InitTypeDef spi_init, SPI_TypeDef *spi_instance, uint32_t flag, uint32_t state, uint32_t time_out, uint32_t tick_start) +{ + while((((spi_instance->SR & flag) == (flag)) ? SET : RESET) != state) + { + if(time_out != 0xFFFFFFFFU) + { + if((time_out == 0U) || ((CurrentTicksGain() * 1000 / TICK_PER_SECOND-tick_start) >= time_out)) + { + spi_instance->CR2 &= (~(SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR)); + + if((spi_init.SPI_Mode == SPI_Mode_Master)&&((spi_init.SPI_Direction == SPI_Direction_1Line_Rx)||(spi_init.SPI_Direction == SPI_Direction_2Lines_RxOnly))) { + /* Disable SPI peripheral */ + spi_instance->CR1 &= (~SPI_CR1_SPE); + } + + return 3; + } + } + } + return 0; +} +/** + * This function SPI sends data through DMA + * + * @param spi_init SPI Init structure + * + * @param spi_instance SPI control handle + * + * @param dma_init DMA Init structure + * + * @param dma_instance DMA Controller + * + * @param p_data Send data buffer address + * + * @param size Amount of data sent + * + * @return if successful return EOK + */ +int SpiTransmitDma(SPI_InitTypeDef spi_init, SPI_TypeDef *spi_instance, DMA_InitTypeDef dma_init, DMA_Stream_TypeDef *dma_instance, uint8_t *p_data, uint16_t size) +{ + int errorcode = 0; + __IO uint16_t tx_xfer_count; + uint8_t *p_txbuff_ptr; + uint16_t tx_xfer_size; + + if((p_data == NONE) || (size == 0)){ + errorcode = 1; + goto error; + } + + tx_xfer_count = size; + p_txbuff_ptr = (uint8_t *)p_data; + tx_xfer_size = size; + + /* Configure communication direction : 1Line */ + if(spi_init.SPI_Direction == SPI_Direction_1Line_Rx){ + spi_instance->CR1 |= SPI_CR1_BIDIOE; + } + + /* Clear DBM bit */ + dma_instance->CR &= (uint32_t)(~DMA_SxCR_DBM); + + /* Configure DMA Stream data length */ + dma_instance->NDTR = tx_xfer_count; + + /* Memory to Peripheral */ + if((dma_init.DMA_DIR) == DMA_DIR_MemoryToPeripheral) + { + /* Configure DMA Stream destination address */ + dma_instance->PAR = spi_instance->DR; + + /* Configure DMA Stream source address */ + dma_instance->M0AR = *p_txbuff_ptr; + } + /* Peripheral to Memory */ + else + { + /* Configure DMA Stream source address */ + dma_instance->PAR = *p_txbuff_ptr; + + /* Configure DMA Stream destination address */ + dma_instance->M0AR = spi_instance->DR; + } + + /* Enable Common interrupts*/ + dma_instance->CR |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT; + dma_instance->FCR |= DMA_IT_FE; + dma_instance->CR |= DMA_SxCR_EN; + + /* Check if the SPI is already enabled */ + if((spi_instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE){ + /* Enable SPI peripheral */ + spi_instance->CR1 |= SPI_CR1_SPE; + } + + /* Enable the SPI Error Interrupt Bit */ + spi_instance->CR2 |= SPI_CR2_ERRIE; + + /* Enable Tx DMA Request */ + spi_instance->CR2 |=SPI_CR2_TXDMAEN; + +error : + return errorcode; +} +/** + * This function SPI carries out duplex communication through DMA + * + * @param spi_init SPI Init structure + * + * @param spi_instance SPI control handle + * + * @param dmarx_init DMA Init structure---Rx + * + * @param dmarx_instance DMA Controller + * + * @param dmatx_init DMA Init structure---Tx + * + * @param dmatx_instance DMA Controller + * + * @param p_txdata Send data buffer address + * + * @param p_rxdata Receive data buffer address + * + * @param size Amount of data + * + * @return if successful return EOK + */ +int SpiTransmitreceiveDma(SPI_InitTypeDef spi_init, SPI_TypeDef *spi_instance, DMA_InitTypeDef dmarx_init, DMA_Stream_TypeDef *dmarx_instance, DMA_InitTypeDef dmatx_init, DMA_Stream_TypeDef *dmatx_instance, uint8_t *p_txdata, uint8_t *p_rxdata, uint16_t size) +{ + uint32_t tmp = 0U; + int errorcode = 0; + __IO uint16_t tx_xfer_count; + __IO uint16_t rx_xfer_count; + uint8_t *p_txbuff_ptr; + uint8_t *p_rxbuff_ptr; + uint16_t tx_xfer_size; + uint16_t rx_xfer_size; + + tmp = spi_init.SPI_Mode; + if(!((tmp == SPI_Mode_Master) && (spi_init.SPI_Direction == SPI_Direction_2Lines_FullDuplex))) + { + errorcode = 2; + goto error; + } + + if((p_txdata == NONE ) || (p_rxdata == NONE ) || (size == 0)) + { + errorcode = 1; + goto error; + } + + /* Set the transaction information */ + p_txbuff_ptr = (uint8_t*)p_txdata; + tx_xfer_size = size; + tx_xfer_count = size; + p_rxbuff_ptr = (uint8_t*)p_rxdata; + rx_xfer_size = size; + rx_xfer_count = size; + + /* Clear DBM bit */ + dmarx_instance->CR &= (uint32_t)(~DMA_SxCR_DBM); + + /* Configure DMA Stream data length */ + dmarx_instance->NDTR = rx_xfer_count; + + /* Memory to Peripheral */ + if((dmarx_init.DMA_DIR) == DMA_DIR_MemoryToPeripheral) + { + /* Configure DMA Stream destination address */ + dmarx_instance->PAR = spi_instance->DR; + + /* Configure DMA Stream source address */ + dmarx_instance->M0AR = *p_rxbuff_ptr; + } + /* Peripheral to Memory */ + else + { + /* Configure DMA Stream source address */ + dmarx_instance->PAR = *p_rxbuff_ptr; + + /* Configure DMA Stream destination address */ + dmarx_instance->M0AR = spi_instance->DR; + } + + /* Enable Common interrupts*/ + dmarx_instance->CR |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT; + dmarx_instance->FCR |= DMA_IT_FE; + dmarx_instance->CR |= DMA_SxCR_EN; + + /* Enable Rx DMA Request */ + spi_instance->CR2 |= SPI_CR2_RXDMAEN; + + /* Clear DBM bit */ + dmatx_instance->CR &= (uint32_t)(~DMA_SxCR_DBM); + + /* Configure DMA Stream data length */ + dmatx_instance->NDTR = tx_xfer_count; + + /* Memory to Peripheral */ + if((dmatx_init.DMA_DIR) == DMA_DIR_MemoryToPeripheral) + { + /* Configure DMA Stream destination address */ + dmatx_instance->PAR = spi_instance->DR; + + /* Configure DMA Stream source address */ + dmatx_instance->M0AR = *p_txbuff_ptr; + } + /* Peripheral to Memory */ + else{ + /* Configure DMA Stream source address */ + dmatx_instance->PAR = *p_txbuff_ptr; + + /* Configure DMA Stream destination address */ + dmatx_instance->M0AR = spi_instance->DR; + } + + /* Enable Common interrupts*/ + dmatx_instance->CR |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT; + dmatx_instance->FCR |= DMA_IT_FE; + dmatx_instance->CR |= DMA_SxCR_EN; + + /* Check if the SPI is already enabled */ + if((spi_instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE){ + /* Enable SPI peripheral */ + spi_instance->CR1 |= SPI_CR1_SPE; + } + /* Enable the SPI Error Interrupt Bit */ + spi_instance->CR2 |= SPI_CR2_ERRIE; + + /* Enable Tx DMA Request */ + spi_instance->CR2 |= SPI_CR2_TXDMAEN; + +error : + return errorcode; +} +/** + * This function SPI receives data through DMA + * + * @param spi_init SPI Init structure + * + * @param spi_instance SPI control handle + * + * @param dmarx_init DMA Init structure---Rx + * + * @param dmarx_instance DMA Controller + * + * @param dmatx_init DMA Init structure---Tx + * + * @param dmatx_instance DMA Controller + * + * @param p_data Receive data buffer address + * + * @param size Amount of data + * + * @return if successful return EOK + */ +int SpiReceiveDma(SPI_InitTypeDef spi_init, SPI_TypeDef *spi_instance, DMA_InitTypeDef dmarx_init, DMA_Stream_TypeDef *dmarx_instance, DMA_InitTypeDef dmatx_init, DMA_Stream_TypeDef *dmatx_instance, uint8_t *p_data, uint16_t size) +{ + int errorcode = 0; + __IO uint16_t rx_xfer_count; + uint8_t *p_rxbuff_ptr; + uint16_t rx_xfer_size; + + if((spi_init.SPI_Direction == SPI_Direction_2Lines_FullDuplex)&&(spi_init.SPI_Mode == SPI_Mode_Master)) { + /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */ + return SpiTransmitreceiveDma(spi_init, spi_instance, dmarx_init, dmarx_instance, dmatx_init, dmatx_instance, p_data, p_data, size); + } + + if((p_data == NONE) || (size == 0)) + { + errorcode = 1; + goto error; + } + + rx_xfer_count = size; + rx_xfer_size = size; + p_rxbuff_ptr = (uint8_t *)p_data; + + /* Configure communication direction : 1Line */ + if(spi_init.SPI_Direction == SPI_Direction_1Line_Rx) { + spi_instance->CR1 &= (~SPI_CR1_BIDIOE); + } + /* Clear DBM bit */ + dmarx_instance->CR &= (uint32_t)(~DMA_SxCR_DBM); + + /* Configure DMA Stream data length */ + dmarx_instance->NDTR = rx_xfer_count; + + /* Memory to Peripheral */ + if((dmarx_init.DMA_DIR) == DMA_DIR_MemoryToPeripheral){ + /* Configure DMA Stream destination address */ + dmarx_instance->PAR = spi_instance->DR; + /* Configure DMA Stream source address */ + dmarx_instance->M0AR = *p_rxbuff_ptr; + } + /* Peripheral to Memory */ + else + { + /* Configure DMA Stream source address */ + dmarx_instance->PAR = *p_rxbuff_ptr; + + /* Configure DMA Stream destination address */ + dmarx_instance->M0AR = spi_instance->DR; + } + + /* Enable Common interrupts*/ + dmarx_instance->CR |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT; + dmarx_instance->FCR |= DMA_IT_FE; + dmarx_instance->CR |= DMA_SxCR_EN; + + /* Check if the SPI is already enabled */ + if((spi_instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE){ + /* Enable SPI peripheral */ + spi_instance->CR1 |= SPI_CR1_SPE; + } + + /* Enable the SPI Error Interrupt Bit */ + spi_instance->CR2 |= SPI_CR2_ERRIE; + + /* Enable Rx DMA Request */ + spi_instance->CR2 |= SPI_CR2_RXDMAEN; + +error: + return errorcode; +} +/** + * This function SPI receives data + * + * @param spi_init SPI Init structure + * + * @param spi_instance SPI control handle + * + * @param p_data Transmit data buffer address + * + * @param size Amount of data + * + * @param Timeout waiting time + * + * @return if successful return EOK + */ +int SpiTransmit(SPI_InitTypeDef spi_init, SPI_TypeDef *spi_instance, uint8_t *p_data, uint16_t size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + int errorcode = 0; + __IO uint16_t tx_xfer_count; + __IO uint32_t SPITimeout; + + /* Init tickstart for timeout management*/ + tickstart = CurrentTicksGain() * 1000 / TICK_PER_SECOND; + + if((p_data == NONE ) || (size == 0)){ + errorcode = 1; + goto error; + } + + tx_xfer_count = size; + + /* Configure communication direction : 1Line */ + if(spi_init.SPI_Direction == SPI_Direction_1Line_Rx){ + spi_instance->CR1 |= SPI_CR1_BIDIOE; + } + + /* Check if the SPI is already enabled */ + if((spi_instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE){ + /* Enable SPI peripheral */ + spi_instance->CR1 |= SPI_CR1_SPE; + } + + /* Transmit data in 16 Bit mode */ + if(spi_init.SPI_DataSize == SPI_DataSize_16b) + { + if((spi_init.SPI_Mode == SPI_Mode_Slave) || (tx_xfer_count == 0x01)){ + spi_instance->DR = *((uint16_t *)p_data); + + p_data += sizeof(uint16_t); + tx_xfer_count--; + } + /* Transmit data in 16 Bit mode */ + while (tx_xfer_count > 0U) + { + SPITimeout = 0x1000; + /* Wait until TXE flag is set to send data */ + while (SPI_I2S_GetFlagStatus(spi_instance, SPI_I2S_FLAG_TXE) == RESET) + { + if((SPITimeout--) == 0) { + KPrintf("spi time out\n"); + errorcode = 3; + goto error; + } + } + /* Write to the data register and write the data to be written into the transmit buffer */ + spi_instance->DR = *((uint16_t *)p_data); + + p_data += sizeof(uint16_t); + tx_xfer_count--; + } + } + /* Transmit data in 8 Bit mode */ + else + { + if((spi_init.SPI_Mode == SPI_Mode_Slave) || (tx_xfer_count == 0x01U)){ + *((__IO uint8_t*)&spi_instance->DR) = (*p_data); + + p_data += sizeof(uint8_t); + tx_xfer_count--; + } + + while(tx_xfer_count > 0) + { + SPITimeout = 0x1000; + + /* Wait for the send buffer to be empty, TXE event*/ + while (SPI_I2S_GetFlagStatus(spi_instance, SPI_I2S_FLAG_TXE) == RESET) + { + if((SPITimeout--) == 0){ + KPrintf("spi time out\n"); + errorcode = 3; + goto error; + } + } + + /* Write to the data register and write the data to be written into the transmit buffer*/ + *((__IO uint8_t*)&spi_instance->DR) = (*p_data); + + p_data += sizeof(uint8_t); + tx_xfer_count--; + } +} + + /* Wait until TXE flag */ + if(SpiWaitUntilTimeout(spi_init, spi_instance, SPI_FLAG_TXE, SET, Timeout, tickstart) != 0){ + errorcode = 3; + goto error; + } + + /* Check Busy flag */ + if(SpiWaitUntilTimeout(spi_init, spi_instance, SPI_FLAG_BSY, RESET, Timeout, tickstart) != 0){ + errorcode = 1; + goto error; + } + +error: + return errorcode; +} +/** + * This function SPI Transmit and receive + * + * @param spi_init SPI Init structure + * + * @param spi_instance SPI control handle + * + * @param p_txdata Transmit data buffer address + * + * @param p_rxdata receive data buffer address + * + * @param size Amount of data + * + * @param Timeout waiting time + * + * @return if successful return EOK + */ +int SpiTransmitreceive(SPI_InitTypeDef spi_init, SPI_TypeDef *spi_instance, uint8_t *p_txdata, uint8_t *p_rxdata, uint16_t size, uint32_t Timeout) +{ + uint32_t tmp = 0U; + + uint32_t tickstart = 0U; + /* Variable used to alternate Rx and Tx during transfer */ + uint32_t txallowed = 1U; + int errorcode = 0; + __IO uint16_t tx_xfer_count; + __IO uint16_t rx_xfer_count; + + /* Init tickstart for timeout management*/ + tickstart = CurrentTicksGain() * 1000 / TICK_PER_SECOND; + + tmp = spi_init.SPI_Mode; + + if(!((tmp == SPI_Mode_Master) && (spi_init.SPI_Direction == SPI_Direction_2Lines_FullDuplex))){ + errorcode = 2; + goto error; + } + + if((p_txdata == NONE) || (p_rxdata == NONE) || (size == 0)){ + errorcode = 1; + goto error; + } + + tx_xfer_count = size; + rx_xfer_count = size; + + /* Check if the SPI is already enabled */ + if((spi_instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE) { + /* Enable SPI peripheral */ + spi_instance->CR1 |= SPI_CR1_SPE; + } + + /* Transmit and Receive data in 16 Bit mode */ + if(spi_init.SPI_DataSize == SPI_DataSize_16b) + { + if((spi_init.SPI_Mode == SPI_Mode_Slave) || (tx_xfer_count == 0x01U)) { + SPI_I2S_ReceiveData(spi_instance); + spi_instance->DR = *((uint16_t *)p_txdata); + + p_txdata += sizeof(uint16_t); + tx_xfer_count--; + } + while ((tx_xfer_count > 0U) || (rx_xfer_count > 0U)) + { + /* Check TXE flag */ + if(txallowed && (tx_xfer_count > 0U) && (SPI_I2S_GetFlagStatus(spi_instance, SPI_I2S_FLAG_TXE) == SET)) { + SPI_I2S_ReceiveData(spi_instance); + spi_instance->DR = *((uint16_t *)p_txdata); + p_txdata += sizeof(uint16_t); + tx_xfer_count--; + /* Next Data is a reception (Rx). Tx not allowed */ + txallowed = 0U; + } + + /* Check RXNE flag */ + if((rx_xfer_count > 0U) && (SPI_I2S_GetFlagStatus(spi_instance, SPI_I2S_FLAG_RXNE) == SET)) + { + *((uint16_t *)p_rxdata) = spi_instance->DR; + p_rxdata += sizeof(uint16_t); + rx_xfer_count--; + /* Next Data is a Transmission (Tx). Tx is allowed */ + txallowed = 1U; + } + if((Timeout != 0xFFFFFFFFU) && ((CurrentTicksGain() * 1000 / TICK_PER_SECOND-tickstart) >= Timeout)){ + errorcode = 3; + goto error; + } + } + } + /* Transmit and Receive data in 8 Bit mode */ + else + { + if((spi_init.SPI_Mode == SPI_Mode_Slave) || (tx_xfer_count == 0x01U)) + { + SPI_I2S_ReceiveData(spi_instance); + *((__IO uint8_t*)&spi_instance->DR) = (*p_txdata); + + p_txdata += sizeof(uint8_t); + tx_xfer_count--; + } + while((tx_xfer_count > 0U) || (rx_xfer_count > 0U)) + { + /* Wait for the send buffer to be empty, TXE event */ + if (txallowed && (tx_xfer_count > 0U) && (SPI_I2S_GetFlagStatus(spi_instance, SPI_I2S_FLAG_TXE) == SET)) + { + /* Write to the data register and write the data to be written into the transmit buffer */ + SPI_I2S_ReceiveData(spi_instance); + *((__IO uint8_t*)&spi_instance->DR) = (*p_txdata); + + p_txdata += sizeof(uint8_t); + tx_xfer_count--; + txallowed = 0U; + } + + if ((rx_xfer_count > 0U) && SPI_I2S_GetFlagStatus(spi_instance, SPI_I2S_FLAG_RXNE) == SET) + { + *(uint8_t *)p_rxdata = spi_instance->DR; + + p_rxdata += sizeof(uint8_t); + rx_xfer_count--; + txallowed = 1U; + } + if((Timeout != 0xFFFFFFFFU) && ((CurrentTicksGain() * 1000 / TICK_PER_SECOND-tickstart) >= Timeout)) { + errorcode = 3; + goto error; + } + } + } + + /* Wait until TXE flag */ + if(SpiWaitUntilTimeout(spi_init, spi_instance, SPI_FLAG_TXE, SET, Timeout, tickstart) != 0){ + errorcode = 3; + goto error; + } + + /* Check Busy flag */ + if(SpiWaitUntilTimeout(spi_init, spi_instance, SPI_FLAG_BSY, RESET, Timeout, tickstart) != 0){ + errorcode = 1; + goto error; + } + +error : + return errorcode; +} +/** + * This function SPI receive data + * + * @param spi_init SPI Init structure + * + * @param spi_instance SPI control handle + * + * @param p_data data buffer address + * + * @param size Amount of data + * + * @param Timeout waiting time + * + * @return if successful return EOK + */ +int SpiReceive(SPI_InitTypeDef spi_init, SPI_TypeDef *spi_instance, uint8_t *p_data, uint16_t size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + int errorcode = 0; + __IO uint16_t rx_xfer_count; + __IO uint32_t SPITimeout; + + if((spi_init.SPI_Mode == SPI_Mode_Master) && (spi_init.SPI_Direction == SPI_Direction_2Lines_FullDuplex)) { + /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */ + return SpiTransmitreceive(spi_init, spi_instance,p_data,p_data,size,Timeout); + } + + /* Init tickstart for timeout management*/ + tickstart = CurrentTicksGain() * 1000 / TICK_PER_SECOND; + + if((p_data == NONE ) || (size == 0)){ + errorcode = 1; + goto error; + } + + rx_xfer_count = size; + + /* Configure communication direction: 1Line */ + if(spi_init.SPI_Direction == SPI_Direction_1Line_Rx){ + spi_instance->CR1 &= (~SPI_CR1_BIDIOE); + } + + /* Check if the SPI is already enabled */ + if((spi_instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE){ + /* Enable SPI peripheral */ + spi_instance->CR1 |= SPI_CR1_SPE; + } + + /* Receive data in 8 Bit mode */ + if(spi_init.SPI_DataSize == SPI_DataSize_8b) + { + /* Transfer loop */ + while(rx_xfer_count > 0U) + { + SPITimeout = 0x1000; + + /* Wait for the send buffer to be empty, TXE event*/ + while (SPI_I2S_GetFlagStatus(spi_instance, SPI_I2S_FLAG_RXNE) == RESET) + { + if((SPITimeout--) == 0){ + KPrintf("spi time out\n"); + errorcode = 3; + goto error; + } + } + + *(uint8_t *)p_data = spi_instance->DR; + + p_data += sizeof(uint8_t); + rx_xfer_count--; + } + } + else + { + /* Transfer loop */ + while(rx_xfer_count > 0U) + { + SPITimeout = 0x1000; + /* Check the RXNE flag */ + while (SPI_I2S_GetFlagStatus(spi_instance, SPI_I2S_FLAG_RXNE) == RESET) + { + if((SPITimeout--) == 0) + { + KPrintf("spi time out\n"); + errorcode = 3; + goto error; + } + } + *((uint16_t*)p_data) = spi_instance->DR; + p_data += sizeof(uint16_t); + rx_xfer_count--; + } + } + + /* Check the end of the transaction */ + if((spi_init.SPI_Mode == SPI_Mode_Master)&&((spi_init.SPI_Direction == SPI_Direction_1Line_Rx)||(spi_init.SPI_Direction == SPI_Direction_2Lines_RxOnly))) + { + /* Disable SPI peripheral */ + spi_instance->CR1 &= (~SPI_CR1_SPE); + } + +error : + return errorcode; +} + +/** + * This function SPI write data + * + * @param spi_dev SPI device structure handle + * + * @param spi_datacfg SPI device information structure handle + * + * @return datacfg length + */ +static uint32 Stm32SpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg) +{ + int state; + x_size_t message_length, already_send_length; + uint16 send_length; + const uint8 *WriteBuf; + + NULL_PARAM_CHECK(spi_dev); + NULL_PARAM_CHECK(spi_datacfg); + + struct Stm32Spi *StmSpi = CONTAINER_OF(spi_dev->haldev.owner_bus, struct Stm32Spi, spi_bus); + SPI_TypeDef *spi_instance = StmSpi->instance; + SPI_InitTypeDef *spi_init = &StmSpi->init; + struct Stm32HwSpiCs *cs = (struct Stm32HwSpiCs *)spi_dev->private_data; + + while(NONE != spi_datacfg) { + if(spi_datacfg->spi_chip_select) { + GPIO_WriteBit(cs->GPIOx, cs->GPIO_Pin, Bit_RESET); + } + + message_length = spi_datacfg->length; + WriteBuf = spi_datacfg->tx_buff; + while (message_length) { + if (message_length > 65535){ + send_length = 65535; + message_length = message_length - 65535; + } else { + send_length = message_length; + message_length = 0; + } + + /* calculate the start address */ + already_send_length = spi_datacfg->length - send_length - message_length; + WriteBuf = (uint8 *)spi_datacfg->tx_buff + already_send_length; + + /* start once data exchange in DMA mode */ + if (spi_datacfg->tx_buff) { + if (StmSpi->spi_dma_flag & SPI_USING_TX_DMA_FLAG) { + state = SpiTransmitDma(*spi_init, spi_instance, StmSpi->dma.dma_tx.init, StmSpi->dma.dma_tx.instance, (uint8_t *)WriteBuf, send_length); + } else { + state = SpiTransmit(*spi_init, spi_instance, (uint8_t *)WriteBuf, send_length, 1000); + } + } + + if (state != 0) { + KPrintf("spi write error : %d\n", state); + spi_datacfg->length = 0; + } + } + + if (spi_datacfg->spi_cs_release) { + GPIO_WriteBit(cs->GPIOx, cs->GPIO_Pin, Bit_SET); + } + + spi_datacfg = spi_datacfg->next; + } + + return EOK; +} + +/** + * This function SPI read data + * + * @param spi_dev SPI device structure handle + * + * @param spi_datacfg SPI device information structure handle + * + * @return datacfg length + */ +static uint32 Stm32SpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg) +{ + int state; + x_size_t message_length, already_send_length; + uint16 read_length, spi_read_length = 0; + const uint8 *ReadBuf; + + NULL_PARAM_CHECK(spi_dev); + NULL_PARAM_CHECK(spi_datacfg); + + struct Stm32Spi *StmSpi = CONTAINER_OF(spi_dev->haldev.owner_bus, struct Stm32Spi, spi_bus); + SPI_TypeDef *spi_instance = StmSpi->instance; + SPI_InitTypeDef *spi_init = &StmSpi->init; + struct Stm32HwSpiCs *cs = (struct Stm32HwSpiCs *)spi_dev->private_data; + + while (NONE != spi_datacfg) { + if (spi_datacfg->spi_chip_select) { + GPIO_WriteBit(cs->GPIOx, cs->GPIO_Pin, Bit_RESET); + } + + message_length = spi_datacfg->length; + ReadBuf = spi_datacfg->rx_buff; + while (message_length) { + if (message_length > 65535) { + read_length = 65535; + message_length = message_length - 65535; + } else { + read_length = message_length; + message_length = 0; + } + + /* calculate the start address */ + already_send_length = spi_datacfg->length - read_length - message_length; + ReadBuf = (uint8 *)spi_datacfg->rx_buff + already_send_length; + + /* start once data exchange in DMA mode */ + if (spi_datacfg->rx_buff) { + //memset((uint8_t *)ReadBuf, 0xff, read_length); + if (StmSpi->spi_dma_flag & SPI_USING_RX_DMA_FLAG) { + state = SpiReceiveDma(*spi_init, spi_instance, StmSpi->dma.dma_rx.init, StmSpi->dma.dma_rx.instance, StmSpi->dma.dma_tx.init, StmSpi->dma.dma_tx.instance, (uint8_t *)ReadBuf, read_length); + } else { + state = SpiReceive(*spi_init, spi_instance, (uint8_t *)ReadBuf, read_length, 1000); + } + } + + if (state != 0) { + KPrintf("spi read error : %d\n", state); + spi_datacfg->length = 0; + } + } + + if (spi_datacfg->spi_cs_release) { + GPIO_WriteBit(cs->GPIOx, cs->GPIO_Pin, Bit_SET); + } + + spi_read_length += spi_datacfg->length; + spi_datacfg = spi_datacfg->next; + } + + return spi_read_length; +} + +/** + * This function SPI driver initialization function + * + * @param spi_drv SPI driver structure handle + * + * @return if successful return EOK + */ +static uint32 SpiDrvInit(struct SpiDriver *spi_drv) +{ + NULL_PARAM_CHECK(spi_drv); + + SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data); + + struct Stm32Spi *StmSpi = CONTAINER_OF(spi_drv->driver.owner_bus, struct Stm32Spi, spi_bus); + + return Stm32SpiInit(StmSpi, dev_param->spi_master_param); +} + +/** + * This function SPI driver configuration param + * + * @param spi_drv SPI driver structure handle + * + * @param spi_param SPI master param structure handle + * + * @return if successful return EOK + */ +static uint32 SpiDrvConfigure(struct SpiDriver *spi_drv, struct SpiMasterParam *spi_param) +{ + NULL_PARAM_CHECK(spi_drv); + NULL_PARAM_CHECK(spi_param); + + SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data); + + dev_param->spi_master_param = spi_param; + dev_param->spi_master_param->spi_work_mode = dev_param->spi_master_param->spi_work_mode & SPI_MODE_MASK; + + return EOK; +} + +/*Configure the spi device param, make sure struct (configure_info->private_data) = (SpiMasterParam)*/ +static uint32 Stm32SpiDrvConfigure(void *drv, struct BusConfigureInfo *configure_info) +{ + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(configure_info); + + x_err_t ret = EOK; + struct SpiDriver *spi_drv = (struct SpiDriver *)drv; + struct SpiMasterParam *spi_param; + + switch (configure_info->configure_cmd) + { + case OPE_INT: + ret = SpiDrvInit(spi_drv); + break; + case OPE_CFG: + spi_param = (struct SpiMasterParam *)configure_info->private_data; + ret = SpiDrvConfigure(spi_drv, spi_param); + break; + default: + break; + } + + return ret; +} + +/*manage the spi device operations*/ +static const struct SpiDevDone spi_dev_done = +{ + .dev_open = NONE, + .dev_close = NONE, + .dev_write = Stm32SpiWriteData, + .dev_read = Stm32SpiReadData, +}; + +#if defined(BSP_USING_SPI1) +struct Stm32Spi spi1; +#if defined(BSP_SPI1_TX_USING_DMA) +void DMA2_Stream3_IRQHandler(int irq_num, void *arg) +{ + DmaTxDoneIsr(&spi1.spi_bus); +} +DECLARE_HW_IRQ(DMA2_Stream3_IRQn, DMA2_Stream3_IRQHandler, NONE); +#endif + +#if defined(BSP_SPI1_RX_USING_DMA) +void DMA2_Stream0_IRQHandler(int irq_num, void *arg) +{ + DmaRxDoneIsr(&spi1.spi_bus); +} +DECLARE_HW_IRQ(DMA2_Stream0_IRQn, DMA2_Stream0_IRQHandler, NONE); +#endif +#endif + +#if defined(BSP_USING_SPI2) +struct Stm32Spi spi2; +#if defined(BSP_SPI2_TX_USING_DMA) +void DMA1_Stream4_IRQHandler(int irq_num, void *arg) +{ + DmaTxDoneIsr(&spi2.spi_bus); +} +DECLARE_HW_IRQ(DMA1_Stream4_IRQn, DMA1_Stream4_IRQHandler, NONE); +#endif + +#if defined(BSP_SPI2_RX_USING_DMA) +void DMA1_Stream3_IRQHandler(int irq_num, void *arg) +{ + DmaTxDoneIsr(&spi2.spi_bus); +} +DECLARE_HW_IRQ(DMA1_Stream3_IRQn, DMA1_Stream3_IRQHandler, NONE); +#endif +#endif + +#if defined(BSP_USING_SPI3) +struct Stm32Spi spi3; +#if defined(BSP_SPI3_TX_USING_DMA) +void DMA1_Stream7_IRQHandler(int irq_num, void *arg) +{ + DmaTxDoneIsr(&spi3.spi_bus); +} +DECLARE_HW_IRQ(DMA1_Stream7_IRQn, DMA1_Stream7_IRQHandler, NONE); +#endif + +#if defined(BSP_SPI3_RX_USING_DMA) +/** + * This function DMA2 Stream2 Interrupt service function + * + * @return none + */ +void DMA1_Stream2_IRQHandler(int irq_num, void *arg) +{ + DmaRxDoneIsr(&spi3.spi_bus); +} +DECLARE_HW_IRQ(DMA1_Stream2_IRQn, DMA1_Stream2_IRQHandler, NONE); +#endif +#endif + +/** + * This function RCC clock configuration function + * + * @return none + */ +static void RCCConfiguration(void) +{ +#ifdef BSP_USING_SPI1 + RCC_AHB1PeriphClockCmd(SPI1_GPIO_RCC, ENABLE); + + RCC_APB2PeriphClockCmd(RCC_APBPeriph_SPI1, ENABLE); +#endif + +#ifdef BSP_USING_SPI2 + RCC_AHB1PeriphClockCmd(SPI2_GPIO_RCC | SPI2_GPIO_RCC_SCK, ENABLE); + + RCC_APB1PeriphClockCmd(RCC_APBPeriph_SPI2, ENABLE); +#endif + +#ifdef BSP_USING_SPI3 + RCC_AHB1PeriphClockCmd(SPI3_GPIO_RCC | SPI3_GPIO_RCC_NSS, ENABLE); + + RCC_APB2PeriphClockCmd(RCC_APBPeriph_SPI3, ENABLE); +#endif +} +/** + * This function GPIO Configuration function + * + * @return none + */ +static void GPIOConfiguration(void) +{ + GPIO_InitTypeDef gpio_initstructure; + + gpio_initstructure.GPIO_Mode = GPIO_Mode_AF; /* Reuse function */ + gpio_initstructure.GPIO_OType = GPIO_OType_PP; /* Multiplex push-pull*/ + gpio_initstructure.GPIO_PuPd = GPIO_PuPd_UP; /* pull up */ + gpio_initstructure.GPIO_Speed = GPIO_Speed_2MHz; /* Level reversal speed */ + +#ifdef BSP_USING_SPI1 + gpio_initstructure.GPIO_Pin = SPI1_GPIO_NSS | SPI1_GPIO_SCK | SPI1_GPIO_MISO | SPI1_GPIO_MOSI; + /* Connect alternate function */ + GPIO_PinAFConfig(SPI1_GPIO, SPI1_NSS_PIN_SOURCE, GPIO_AF_SPI1); + GPIO_PinAFConfig(SPI1_GPIO, SPI1_SCK_PIN_SOURCE, GPIO_AF_SPI1); + GPIO_PinAFConfig(SPI1_GPIO, SPI1_MISO_PIN_SOURCE, GPIO_AF_SPI1); + GPIO_PinAFConfig(SPI1_GPIO, SPI1_MOSI_PIN_SOURCE, GPIO_AF_SPI1); + + GPIO_Init(SPI1_GPIO, &gpio_initstructure); /*SPI pin initialization*/ +#endif + +#ifdef BSP_USING_SPI2 + gpio_initstructure.GPIO_Pin = SPI2_GPIO_SCK; + /* Connect alternate function */ + GPIO_PinAFConfig(SPI2_SCK, SPI2_SCK_PIN_SOURCE, GPIO_AF_SPI2); + + GPIO_Init(SPI2_SCK, &gpio_initstructure); + + gpio_initstructure.GPIO_Pin = SPI2_GPIO_NSS | SPI2_GPIO_MISO | SPI2_GPIO_MOSI; + /* Connect alternate function */ + GPIO_PinAFConfig(SPI2_GPIO, SPI2_NSS_PIN_SOURCE, GPIO_AF_SPI2); + GPIO_PinAFConfig(SPI2_GPIO, SPI2_MISO_PIN_SOURCE, GPIO_AF_SPI2); + GPIO_PinAFConfig(SPI2_GPIO, SPI2_MOSI_PIN_SOURCE, GPIO_AF_SPI2); + + GPIO_Init(SPI2_GPIO, &gpio_initstructure); +#endif + +#ifdef BSP_USING_SPI3 + gpio_initstructure.GPIO_Pin = SPI3_GPIO_NSS; + /* Connect alternate function */ + GPIO_PinAFConfig(SPI3_NSS, SPI3_NSS_PIN_SOURCE, GPIO_AF_SPI3); + + GPIO_Init(SPI3_NSS, &gpio_initstructure); + + gpio_initstructure.GPIO_Pin = SPI3_GPIO_SCK | SPI3_GPIO_MISO | SPI3_GPIO_MOSI; + GPIO_PinAFConfig(SPI3_GPIO, SPI3_SCK_PIN_SOURCE, GPIO_AF_SPI3); + GPIO_PinAFConfig(SPI3_GPIO, SPI3_MISO_PIN_SOURCE, GPIO_AF_SPI3); + GPIO_PinAFConfig(SPI3_GPIO, SPI3_MOSI_PIN_SOURCE, GPIO_AF_SPI3); + + GPIO_Init(SPI3_GPIO, &gpio_initstructure); +#endif +} + +/** + * This function Init the spi bus 、spi driver and attach to the bus + * + * @param spi_bus Spi bus info pointer + * + * @param spi_driver Spi driver info pointer + * + * @return EOK + */ +static int BoardSpiBusInit(struct Stm32Spi *stm32spi_bus, struct SpiDriver *spi_driver, char* drv_name) +{ + x_err_t ret = EOK; + + /*Init the spi bus */ + ret = SpiBusInit(&stm32spi_bus->spi_bus, stm32spi_bus->bus_name); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiBusInit error %d\n", ret); + return ERROR; + } + + /*Init the spi driver*/ + ret = SpiDriverInit(spi_driver, drv_name); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDriverInit error %d\n", ret); + return ERROR; + } + + /*Attach the spi driver to the spi bus*/ + ret = SpiDriverAttachToBus(drv_name, stm32spi_bus->bus_name); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDriverAttachToBus error %d\n", ret); + return ERROR; + } + + return ret; +} + + +/** + * This function SPI bus initialization + * + * @return EOK + */ +static int Stm32HwSpiBusInit(void) +{ + x_err_t ret = EOK; + struct Stm32Spi *StmSpiBus; + + RCCConfiguration(); + GPIOConfiguration(); + +#ifdef BSP_USING_SPI1 + StmSpiBus = &spi1; + StmSpiBus->instance = SPI1; + StmSpiBus->bus_name = SPI_BUS_NAME_1; + StmSpiBus->spi_bus.private_data = &spi1; + DmaSpiConfig(&StmSpiBus->spi_bus, 0, NONE, NONE); + + static struct SpiDriver spi_driver_1; + memset(&spi_driver_1, 0, sizeof(struct SpiDriver)); + + spi_driver_1.configure = &(Stm32SpiDrvConfigure); + + ret = BoardSpiBusInit(StmSpiBus, &spi_driver_1, SPI_1_DRV_NAME); + if (EOK != ret) { + KPrintf("Board_Spi_Init spi_bus_init %s error ret %u\n", StmSpiBus->bus_name, ret); + return ERROR; + } +#endif + +#ifdef BSP_USING_SPI2 + StmSpiBus = &spi2; + StmSpiBus->instance = SPI2; + StmSpiBus->bus_name = SPI_BUS_NAME_2; + StmSpiBus->spi_bus.private_data = &spi2; + DmaSpiConfig(&StmSpiBus->spi_bus, 0, NONE, NONE); + + static struct SpiDriver spi_driver_2; + memset(&spi_driver_2, 0, sizeof(struct SpiDriver)); + + spi_driver_2.configure = &(Stm32SpiDrvConfigure); + + ret = BoardSpiBusInit(StmSpiBus, &spi_driver_2, SPI_2_DRV_NAME); + if (EOK != ret) { + KPrintf("Board_Spi_Init spi_bus_init %s error ret %u\n", StmSpiBus->bus_name, ret); + return ERROR; + } +#endif + +#ifdef BSP_USING_SPI3 + StmSpiBus = &spi3; + StmSpiBus->instance = SPI3; + StmSpiBus->bus_name = SPI_BUS_NAME_3; + StmSpiBus->spi_bus.private_data = &spi3; + DmaSpiConfig(&StmSpiBus->spi_bus, 0, NONE, NONE); + + static struct SpiDriver spi_driver_3; + memset(&spi_driver_3, 0, sizeof(struct SpiDriver)); + + spi_driver_3.configure = &(Stm32SpiDrvConfigure); + + ret = BoardSpiBusInit(StmSpiBus, &spi_driver_3, SPI_3_DRV_NAME); + if (EOK != ret) { + KPrintf("Board_Spi_Init spi_bus_init %s error ret %u\n", StmSpiBus->bus_name, ret); + return ERROR; + } +#endif + return EOK; +} + +/** + * This function Mount the spi device to the bus + * + * @param bus_name Bus Name + * + * @param device_name spi device name + * + * @param cs_gpiox GPIO pin configuration handle + * + * @param cs_gpio_pin GPIO number + * + * @return EOK + */ +x_err_t HwSpiDeviceAttach(const char *bus_name, const char *device_name, GPIO_TypeDef *cs_gpiox, uint16_t cs_gpio_pin) + +{ + NULL_PARAM_CHECK(bus_name); + NULL_PARAM_CHECK(device_name); + + x_err_t result; + struct SpiHardwareDevice *spi_device; + struct Stm32HwSpiCs *cs_pin_param; + static SpiDeviceParam spi_dev_param; + memset(&spi_dev_param, 0, sizeof(SpiDeviceParam)); + + /* initialize the cs pin && select the slave*/ + GPIO_InitTypeDef GPIO_Initure; + GPIO_Initure.GPIO_Pin = cs_gpio_pin; + GPIO_Initure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_Initure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(cs_gpiox, &GPIO_Initure); + GPIO_WriteBit(cs_gpiox, cs_gpio_pin, Bit_SET); + + /* attach the device to spi bus*/ + spi_device = (struct SpiHardwareDevice *)x_malloc(sizeof(struct SpiHardwareDevice)); + CHECK(spi_device); + memset(spi_device, 0, sizeof(struct SpiHardwareDevice)); + cs_pin_param = (struct Stm32HwSpiCs *)x_malloc(sizeof(struct Stm32HwSpiCs)); + CHECK(cs_pin_param); + memset(cs_pin_param, 0, sizeof(struct Stm32HwSpiCs)); + cs_pin_param->GPIOx = cs_gpiox; + cs_pin_param->GPIO_Pin = cs_gpio_pin; + + spi_device->spi_dev_done = &spi_dev_done; + spi_device->private_data = (void *)cs_pin_param; + + result = SpiDeviceRegister(spi_device, (void *)&spi_dev_param, device_name); + if (result != EOK) { + SYS_ERR("%s device %p register faild, %d\n", device_name, spi_device, result); + } + + result = SpiDeviceAttachToBus(device_name, bus_name); + if (result != EOK) { + SYS_ERR("%s attach to %s faild, %d\n", device_name, bus_name, result); + } + + CHECK(result == EOK); + + return result; +} + +/** + * This function Get DMA information + * + * @return none + */ +static void Stm32GetDmaInfo(void) +{ +#ifdef BSP_SPI1_RX_USING_DMA /*SPI1 uses DMA receive enable*/ + spi1.spi_dma_flag |= SPI_USING_RX_DMA_FLAG; + spi1.dma.dma_rx.instance = DMA2_Stream0; + spi1.dma.dma_rx.dma_rcc = RCC_AHB1ENR_DMA2EN; + spi1.dma.dma_rx.channel = DMA_Channel_3; + spi1.dma.dma_rx.dma_irq = DMA2_Stream0_IRQn; +#endif +#ifdef BSP_SPI1_TX_USING_DMA /*SPI1 uses DMA send enable*/ + spi1.spi_dma_flag |= SPI_USING_TX_DMA_FLAG; + spi1.dma.dma_tx.instance = DMA2_Stream3; + spi1.dma.dma_tx.dma_rcc = RCC_AHB1ENR_DMA2EN; + spi1.dma.dma_tx.channel = DMA_Channel_3; + spi1.dma.dma_tx.dma_irq = DMA2_Stream3_IRQn; +#endif + +#ifdef BSP_SPI2_RX_USING_DMA /*SPI2 uses DMA receive enable*/ + spi2.spi_dma_flag |= SPI_USING_RX_DMA_FLAG; + spi2.dma.dma_rx.instance = DMA1_Stream3; /* DMA1 Data stream 3*/ + spi2.dma.dma_rx.dma_rcc = RCC_AHB1ENR_DMA1EN; + spi2.dma.dma_rx.channel = DMA_Channel_0; + spi2.dma.dma_rx.dma_irq = DMA1_Stream3_IRQn; +#endif +#ifdef BSP_SPI2_TX_USING_DMA /*SPI2 uses DMA send enable*/ + spi2.spi_dma_flag |= SPI_USING_TX_DMA_FLAG; + spi2.dma.dma_tx.instance = DMA1_Stream4; /* DMA1 Data stream 4*/ + spi2.dma.dma_tx.dma_rcc = RCC_AHB1ENR_DMA1EN; + spi2.dma.dma_tx.channel = DMA_Channel_0; + spi2.dma.dma_tx.dma_irq = DMA1_Stream4_IRQn; /*Enable DMA interrupt line*/ +#endif + +#ifdef BSP_SPI3_RX_USING_DMA /*SPI3 uses DMA receive enable*/ + spi3.spi_dma_flag |= SPI_USING_RX_DMA_FLAG; + spi3.dma.dma_rx.instance = DMA1_Stream2; /* DMA1 Data stream 2*/ + spi3.dma.dma_rx.dma_rcc = RCC_AHB1ENR_DMA1EN; + spi3.dma.dma_rx.channel = DMA_Channel_0; + spi3.dma.dma_rx.dma_irq = DMA1_Stream2_IRQn; /*Enable DMA interrupt line*/ +#endif +#ifdef BSP_SPI3_TX_USING_DMA /*SPI3 uses DMA send enable*/ + spi3.spi_dma_flag |= SPI_USING_TX_DMA_FLAG; + spi3.dma.dma_tx.instance = DMA1_Stream7; /* DMA1 Data stream 7*/ + spi3.dma.dma_tx.dma_rcc = RCC_AHB1ENR_DMA1EN; + spi3.dma.dma_tx.channel = DMA_Channel_0; + spi3.dma.dma_tx.dma_irq = DMA1_Stream7_IRQn; /*Enable DMA interrupt line*/ +#endif +} + +/** + * This function hardware spi initialization + * + * @return EOK + */ +int Stm32HwSpiInit(void) +{ + Stm32GetDmaInfo(); + return Stm32HwSpiBusInit(); +} diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/flexspi_nor_flash_ops.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/flexspi_nor_flash_ops.c new file mode 100755 index 000000000..6786d4049 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/flexspi_nor_flash_ops.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_flexspi.h" +#include "app.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + *****************************************************************************/ +extern flexspi_device_config_t deviceconfig; +extern const uint32_t customLUT[CUSTOM_LUT_LENGTH]; +/******************************************************************************* + * Code + ******************************************************************************/ +status_t flexspi_nor_write_enable(FLEXSPI_Type *base, uint32_t baseAddr) +{ + flexspi_transfer_t flashXfer; + status_t status; + + /* Write enable */ + flashXfer.deviceAddress = baseAddr; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Command; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE; + + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + return status; +} + +status_t flexspi_nor_wait_bus_busy(FLEXSPI_Type *base) +{ + /* Wait status ready. */ + bool isBusy; + uint32_t readValue; + status_t status; + flexspi_transfer_t flashXfer; + + flashXfer.deviceAddress = 0; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Read; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READSTATUSREG; + flashXfer.data = &readValue; + flashXfer.dataSize = 1; + + do + { + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + if (status != kStatus_Success) + { + return status; + } + if (FLASH_BUSY_STATUS_POL) + { + if (readValue & (1U << FLASH_BUSY_STATUS_OFFSET)) + { + isBusy = true; + } + else + { + isBusy = false; + } + } + else + { + if (readValue & (1U << FLASH_BUSY_STATUS_OFFSET)) + { + isBusy = false; + } + else + { + isBusy = true; + } + } + + } while (isBusy); + + return status; +} + +status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base) +{ + flexspi_transfer_t flashXfer; + status_t status; + uint32_t writeValue = FLASH_QUAD_ENABLE; + + /* Write enable */ + status = flexspi_nor_write_enable(base, 0); + + if (status != kStatus_Success) + { + return status; + } + + /* Enable quad mode. */ + flashXfer.deviceAddress = 0; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Write; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG; + flashXfer.data = &writeValue; + flashXfer.dataSize = 1; + + status = FLEXSPI_TransferBlocking(base, &flashXfer); + if (status != kStatus_Success) + { + return status; + } + + status = flexspi_nor_wait_bus_busy(base); + + /* Do software reset. */ + FLEXSPI_SoftwareReset(base); + + return status; +} + +status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address) +{ + status_t status; + flexspi_transfer_t flashXfer; + + /* Write enable */ + flashXfer.deviceAddress = address; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Command; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE; + + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + if (status != kStatus_Success) + { + return status; + } + + flashXfer.deviceAddress = address; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Command; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ERASESECTOR; + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + if (status != kStatus_Success) + { + return status; + } + + status = flexspi_nor_wait_bus_busy(base); + + /* Do software reset. */ + FLEXSPI_SoftwareReset(base); + + return status; +} + +status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src) +{ + status_t status; + flexspi_transfer_t flashXfer; + + /* Write enable */ + status = flexspi_nor_write_enable(base, dstAddr); + + if (status != kStatus_Success) + { + return status; + } + + /* Prepare page program command */ + flashXfer.deviceAddress = dstAddr; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Write; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD; + flashXfer.data = (uint32_t *)src; + flashXfer.dataSize = FLASH_PAGE_SIZE; + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + if (status != kStatus_Success) + { + return status; + } + + status = flexspi_nor_wait_bus_busy(base); + + /* Do software reset. */ + FLEXSPI_SoftwareReset(base); + + return status; +} + +status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId) +{ + uint32_t temp; + flexspi_transfer_t flashXfer; + flashXfer.deviceAddress = 0; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Read; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READID; + flashXfer.data = &temp; + flashXfer.dataSize = 1; + + status_t status = FLEXSPI_TransferBlocking(base, &flashXfer); + + *vendorId = temp; + + /* Do software reset. */ + FLEXSPI_SoftwareReset(base); + + return status; +} + +status_t flexspi_nor_erase_chip(FLEXSPI_Type *base) +{ + status_t status; + flexspi_transfer_t flashXfer; + + /* Write enable */ + status = flexspi_nor_write_enable(base, 0); + + if (status != kStatus_Success) + { + return status; + } + + flashXfer.deviceAddress = 0; + flashXfer.port = kFLEXSPI_PortA1; + flashXfer.cmdType = kFLEXSPI_Command; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ERASECHIP; + + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + if (status != kStatus_Success) + { + return status; + } + + status = flexspi_nor_wait_bus_busy(base); + + return status; +} + +void flexspi_nor_flash_init(FLEXSPI_Type *base) +{ + flexspi_config_t config; + + flexspi_clock_init(); + + /*Get FLEXSPI default settings and configure the flexspi. */ + FLEXSPI_GetDefaultConfig(&config); + + /*Set AHB buffer size for reading data through AHB bus. */ + config.ahbConfig.enableAHBPrefetch = true; + config.ahbConfig.enableAHBBufferable = true; + config.ahbConfig.enableReadAddressOpt = true; + config.ahbConfig.enableAHBCachable = true; + config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad; + FLEXSPI_Init(base, &config); + + /* Configure flash settings according to serial flash feature. */ + FLEXSPI_SetFlashConfig(base, &deviceconfig, kFLEXSPI_PortA1); + + /* Update LUT table. */ + FLEXSPI_UpdateLUT(base, 0, customLUT, CUSTOM_LUT_LENGTH); + + /* Do software reset. */ + FLEXSPI_SoftwareReset(base); +} diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/flexspi_nor_polling_transfer.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/flexspi_nor_polling_transfer.c new file mode 100755 index 000000000..c67837b4a --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/flexspi_nor_polling_transfer.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_flexspi.h" +#include "app.h" +#include "fsl_debug_console.h" +#include "fsl_cache.h" + +#include "pin_mux.h" +#include "board.h" +#include "clock_config.h" +#include "fsl_common.h" + +#include + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint8_t s_nor_program_buffer[256]; +static uint8_t s_nor_read_buffer[256]; + +extern status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address); +extern status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src); +extern status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId); +extern status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base); +extern status_t flexspi_nor_erase_chip(FLEXSPI_Type *base); +extern void flexspi_nor_flash_init(FLEXSPI_Type *base); +/******************************************************************************* + * Code + ******************************************************************************/ +flexspi_device_config_t deviceconfig = { + .flexspiRootClk = 120000000, + .flashSize = FLASH_SIZE, + .CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle, + .CSInterval = 2, + .CSHoldTime = 3, + .CSSetupTime = 3, + .dataValidTime = 0, + .columnspace = 0, + .enableWordAddress = 0, + .AWRSeqIndex = 0, + .AWRSeqNumber = 0, + .ARDSeqIndex = NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD, + .ARDSeqNumber = 1, + .AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle, + .AHBWriteWaitInterval = 0, +}; + +const uint32_t customLUT[CUSTOM_LUT_LENGTH] = { + /* Normal read mode -SDR */ + [4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x03, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18), + [4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 1] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0), + + /* Fast read mode - SDR */ + [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0B, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18), + [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST + 1] = FLEXSPI_LUT_SEQ( + kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_1PAD, 0x08, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04), + + /* Fast read quad mode - SDR */ + [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xEB, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x18), + [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD + 1] = FLEXSPI_LUT_SEQ( + kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD, 0x06, kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x04), + + /* Read extend parameters */ + [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUS] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x81, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04), + + /* Write Enable */ + [4 * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0), + + /* Erase Sector */ + [4 * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x20, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18), + + /* Page Program - single mode */ + [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18), + [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE + 1] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0), + + /* Page Program - quad mode */ + [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18), + [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD + 1] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0), + + /* Read ID */ + [4 * NOR_CMD_LUT_SEQ_IDX_READID] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x9F, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04), + + /* Enable Quad mode */ + [4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04), + + /* Enter QPI mode */ + [4 * NOR_CMD_LUT_SEQ_IDX_ENTERQPI] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x35, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0), + + /* Exit QPI mode */ + [4 * NOR_CMD_LUT_SEQ_IDX_EXITQPI] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_4PAD, 0xF5, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0), + + /* Read status register */ + [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x05, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04), + + /* Erase whole chip */ + [4 * NOR_CMD_LUT_SEQ_IDX_ERASECHIP] = + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xC7, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0), +}; + + +int test_nor_flash(void) +{ + uint32_t i = 0; + status_t status; + uint8_t vendorID = 0; + +// BOARD_ConfigMPU(); +// BOARD_InitPins(); +// BOARD_BootClockRUN(); +// BOARD_InitDebugConsole(); + BOARD_InitSPIPins(); +// SCB_DisableDCache(); +// spi_trace(); + flexspi_nor_flash_init(EXAMPLE_FLEXSPI); + + spi_print("\r\nFLEXSPI example started!\r\n"); + + /* Get vendor ID. */ + status = flexspi_nor_get_vendor_id(EXAMPLE_FLEXSPI, &vendorID); + if (status != kStatus_Success) + { + spi_print("flexspi status %d\r\n", status); + return status; + } + spi_print("Vendor ID: 0x%x\r\n", vendorID); + + return 0; +#if !(defined(XIP_EXTERNAL_FLASH)) + /* Erase whole chip . */ + spi_print("Erasing whole chip over FlexSPI...\r\n"); + + status = flexspi_nor_erase_chip(EXAMPLE_FLEXSPI); + if (status != kStatus_Success) + { + return status; + } + spi_print("Erase finished !\r\n"); + +#endif + + /* Enter quad mode. */ + status = flexspi_nor_enable_quad_mode(EXAMPLE_FLEXSPI); + if (status != kStatus_Success) + { + return status; + } + + /* Erase sectors. */ + spi_print("Erasing Serial NOR over FlexSPI...\r\n"); + status = flexspi_nor_flash_erase_sector(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE); + if (status != kStatus_Success) + { + spi_print("Erase sector failure !\r\n"); + return -1; + } + + memset(s_nor_program_buffer, 0xFFU, sizeof(s_nor_program_buffer)); + memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE), + sizeof(s_nor_read_buffer)); + + if (memcmp(s_nor_program_buffer, s_nor_read_buffer, sizeof(s_nor_program_buffer))) + { + spi_print("Erase data - read out data value incorrect !\r\n "); + return -1; + } + else + { + spi_print("Erase data - successfully. \r\n"); + } + + for (i = 0; i < 0xFFU; i++) + { + s_nor_program_buffer[i] = i; + } + + status = + flexspi_nor_flash_page_program(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE, (void *)s_nor_program_buffer); + if (status != kStatus_Success) + { + spi_print("Page program failure !\r\n"); + return -1; + } + + DCACHE_CleanInvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE, FLASH_PAGE_SIZE); + + memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE), + sizeof(s_nor_read_buffer)); + + if (memcmp(s_nor_read_buffer, s_nor_program_buffer, sizeof(s_nor_program_buffer)) != 0) + { + spi_print("Program data - read out data value incorrect !\r\n "); + return -1; + } + else + { + spi_print("Program data - successfully. \r\n"); + } + + while (1) + { + } +} + +SHELL_EXPORT_CMD (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), + nor, test_nor_flash, Nor flash test ); + diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_flexspi.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_flexspi.c new file mode 100755 index 000000000..c10b16f2e --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_flexspi.c @@ -0,0 +1,1063 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_flexspi.h" + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.flexspi" +#endif + +/******************************************************************************* + * Definitations + ******************************************************************************/ + +#define FREQ_1MHz (1000000UL) +#define FLEXSPI_DLLCR_DEFAULT (0x100UL) +#define FLEXSPI_LUT_KEY_VAL (0x5AF05AF0ul) + +enum +{ + kFLEXSPI_DelayCellUnitMin = 75, /* 75ps. */ + kFLEXSPI_DelayCellUnitMax = 225, /* 225ps. */ +}; + +enum +{ + kFLEXSPI_FlashASampleClockSlaveDelayLocked = + FLEXSPI_STS2_ASLVLOCK_MASK, /* Flash A sample clock slave delay line locked. */ + kFLEXSPI_FlashASampleClockRefDelayLocked = + FLEXSPI_STS2_AREFLOCK_MASK, /* Flash A sample clock reference delay line locked. */ + kFLEXSPI_FlashBSampleClockSlaveDelayLocked = + FLEXSPI_STS2_BSLVLOCK_MASK, /* Flash B sample clock slave delay line locked. */ + kFLEXSPI_FlashBSampleClockRefDelayLocked = + FLEXSPI_STS2_BREFLOCK_MASK, /* Flash B sample clock reference delay line locked. */ +}; + +/*! @brief Common sets of flags used by the driver. */ +enum _flexspi_flag_constants +{ + /*! IRQ sources enabled by the non-blocking transactional API. */ + kIrqFlags = kFLEXSPI_IpTxFifoWatermarkEmpltyFlag | kFLEXSPI_IpRxFifoWatermarkAvailableFlag | + kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag | + kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag, + + /*! Errors to check for. */ + kErrorFlags = kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag | + kFLEXSPI_IpCommandGrantTimeoutFlag, +}; + +enum _flexspi_transfer_state +{ + kFLEXSPI_Idle = 0x0U, /*!< Transfer is done. */ + kFLEXSPI_BusyWrite = 0x1U, /*!< FLEXSPI is busy write transfer. */ + kFLEXSPI_BusyRead = 0x2U, /*!< FLEXSPI is busy write transfer. */ +}; + +/*! @brief Typedef for interrupt handler. */ +typedef void (*flexspi_isr_t)(FLEXSPI_Type *base, void *flexspiHandle); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*! + * @brief Get the instance number for FLEXSPI. + * + * @param base FLEXSPI base pointer. + */ +uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base); + +/*! + * @brief Configure flash A/B sample clock DLL. + * + * @param base FLEXSPI base pointer. + * @param config Flash configuration parameters. + */ +static uint32_t FLEXSPI_ConfigureDll(FLEXSPI_Type *base, flexspi_device_config_t *config); + +/*! + * @brief Check and clear IP command execution errors. + * + * @param base FLEXSPI base pointer. + * @param status interrupt status. + */ +status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status); + +/******************************************************************************* + * Variables + ******************************************************************************/ +/*! @brief Pointers to flexspi bases for each instance. */ +static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS; + +/*! @brief Pointers to flexspi IRQ number for each instance. */ +static const IRQn_Type s_flexspiIrqs[] = FLEXSPI_IRQS; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) +/* Clock name array */ +static const clock_ip_name_t s_flexspiClock[] = FLEXSPI_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +#if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ +/*! @brief Pointers to flexspi handles for each instance. */ +static void *s_flexspiHandle[ARRAY_SIZE(s_flexspiBases)]; +#endif + +#if defined(FSL_FEATURE_FLEXSPI_HAS_RESET) && FSL_FEATURE_FLEXSPI_HAS_RESET +/*! @brief Pointers to FLEXSPI resets for each instance. */ +static const reset_ip_name_t s_flexspiResets[] = FLEXSPI_RSTS; +#endif +/******************************************************************************* + * Code + ******************************************************************************/ + +uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base) +{ + uint32_t instance; + + /* Find the instance index from base address mappings. */ + for (instance = 0; instance < ARRAY_SIZE(s_flexspiBases); instance++) + { + if (s_flexspiBases[instance] == base) + { + break; + } + } + + assert(instance < ARRAY_SIZE(s_flexspiBases)); + + return instance; +} + +static uint32_t FLEXSPI_ConfigureDll(FLEXSPI_Type *base, flexspi_device_config_t *config) +{ + bool isUnifiedConfig = true; + uint32_t flexspiDllValue; + uint32_t dllValue; + uint32_t temp; + + uint8_t rxSampleClock = (base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) >> FLEXSPI_MCR0_RXCLKSRC_SHIFT; + switch (rxSampleClock) + { + case kFLEXSPI_ReadSampleClkLoopbackInternally: + case kFLEXSPI_ReadSampleClkLoopbackFromDqsPad: + case kFLEXSPI_ReadSampleClkLoopbackFromSckPad: + isUnifiedConfig = true; + break; + case kFLEXSPI_ReadSampleClkExternalInputFromDqsPad: + if (config->isSck2Enabled) + { + isUnifiedConfig = true; + } + else + { + isUnifiedConfig = false; + } + break; + default: + break; + } + + if (isUnifiedConfig) + { + flexspiDllValue = FLEXSPI_DLLCR_DEFAULT; /* 1 fixed delay cells in DLL delay chain) */ + } + else + { + if (config->flexspiRootClk >= 100 * FREQ_1MHz) + { + /* DLLEN = 1, SLVDLYTARGET = 0xF, */ + flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x0F); + } + else + { + temp = config->dataValidTime * 1000; /* Convert data valid time in ns to ps. */ + dllValue = temp / kFLEXSPI_DelayCellUnitMin; + if (dllValue * kFLEXSPI_DelayCellUnitMin < temp) + { + dllValue++; + } + flexspiDllValue = FLEXSPI_DLLCR_OVRDEN(1) | FLEXSPI_DLLCR_OVRDVAL(dllValue); + } + } + return flexspiDllValue; +} + +status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status) +{ + status_t result = kStatus_Success; + + /* Check for error. */ + status &= kErrorFlags; + if (status) + { + /* Select the correct error code.. */ + if (status & kFLEXSPI_SequenceExecutionTimeoutFlag) + { + result = kStatus_FLEXSPI_SequenceExecutionTimeout; + } + else if (status & kFLEXSPI_IpCommandSequenceErrorFlag) + { + result = kStatus_FLEXSPI_IpCommandSequenceError; + } + else if (status & kFLEXSPI_IpCommandGrantTimeoutFlag) + { + result = kStatus_FLEXSPI_IpCommandGrantTimeout; + } + else + { + assert(false); + } + + /* Clear the flags. */ + FLEXSPI_ClearInterruptStatusFlags(base, status); + + /* Reset fifos. These flags clear automatically. */ + base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK; + base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK; + } + + return result; +} + +/*! + * brief Initializes the FLEXSPI module and internal state. + * + * This function enables the clock for FLEXSPI and also configures the FLEXSPI with the + * input configure parameters. Users should call this function before any FLEXSPI operations. + * + * param base FLEXSPI peripheral base address. + * param config FLEXSPI configure structure. + */ +void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config) +{ + uint32_t configValue = 0; + uint8_t i = 0; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Enable the flexspi clock */ + CLOCK_EnableClock(s_flexspiClock[FLEXSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +#if defined(FSL_FEATURE_FLEXSPI_HAS_RESET) && FSL_FEATURE_FLEXSPI_HAS_RESET + /* Reset the FLEXSPI module */ + RESET_PeripheralReset(s_flexspiResets[FLEXSPI_GetInstance(base)]); +#endif + + /* Reset peripheral before configuring it. */ + base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + FLEXSPI_SoftwareReset(base); + + /* Configure MCR0 configuration items. */ + configValue = FLEXSPI_MCR0_RXCLKSRC(config->rxSampleClock) | FLEXSPI_MCR0_DOZEEN(config->enableDoze) | + FLEXSPI_MCR0_IPGRANTWAIT(config->ipGrantTimeoutCycle) | + FLEXSPI_MCR0_AHBGRANTWAIT(config->ahbConfig.ahbGrantTimeoutCycle) | + FLEXSPI_MCR0_SCKFREERUNEN(config->enableSckFreeRunning) | + FLEXSPI_MCR0_HSEN(config->enableHalfSpeedAccess) | + FLEXSPI_MCR0_COMBINATIONEN(config->enableCombination) | + FLEXSPI_MCR0_ATDFEN(config->ahbConfig.enableAHBWriteIpTxFifo) | + FLEXSPI_MCR0_ARDFEN(config->ahbConfig.enableAHBWriteIpRxFifo) | FLEXSPI_MCR0_MDIS_MASK; + base->MCR0 = configValue; + + /* Configure MCR1 configurations. */ + configValue = + FLEXSPI_MCR1_SEQWAIT(config->seqTimeoutCycle) | FLEXSPI_MCR1_AHBBUSWAIT(config->ahbConfig.ahbBusTimeoutCycle); + base->MCR1 = configValue; + + /* Configure MCR2 configurations. */ + configValue = base->MCR2; + configValue &= ~(FLEXSPI_MCR2_RESUMEWAIT_MASK | FLEXSPI_MCR2_SCKBDIFFOPT_MASK | FLEXSPI_MCR2_SAMEDEVICEEN_MASK | + FLEXSPI_MCR2_CLRAHBBUFOPT_MASK); + configValue |= FLEXSPI_MCR2_RESUMEWAIT(config->ahbConfig.resumeWaitCycle) | + FLEXSPI_MCR2_SCKBDIFFOPT(config->enableSckBDiffOpt) | + FLEXSPI_MCR2_SAMEDEVICEEN(config->enableSameConfigForAll) | + FLEXSPI_MCR2_CLRAHBBUFOPT(config->ahbConfig.enableClearAHBBufferOpt); + + base->MCR2 = configValue; + + /* Configure AHB control items. */ + configValue = base->AHBCR; + configValue &= ~(FLEXSPI_AHBCR_READADDROPT_MASK | FLEXSPI_AHBCR_PREFETCHEN_MASK | FLEXSPI_AHBCR_BUFFERABLEEN_MASK | + FLEXSPI_AHBCR_CACHABLEEN_MASK); + configValue |= FLEXSPI_AHBCR_READADDROPT(config->ahbConfig.enableReadAddressOpt) | + FLEXSPI_AHBCR_PREFETCHEN(config->ahbConfig.enableAHBPrefetch) | + FLEXSPI_AHBCR_BUFFERABLEEN(config->ahbConfig.enableAHBBufferable) | + FLEXSPI_AHBCR_CACHABLEEN(config->ahbConfig.enableAHBCachable); + base->AHBCR = configValue; + + /* Configure AHB rx buffers. */ + for (i = 0; i < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++) + { + configValue = base->AHBRXBUFCR0[i]; + + configValue &= ~(FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK | FLEXSPI_AHBRXBUFCR0_PRIORITY_MASK | + FLEXSPI_AHBRXBUFCR0_MSTRID_MASK | FLEXSPI_AHBRXBUFCR0_BUFSZ_MASK); + configValue |= FLEXSPI_AHBRXBUFCR0_PREFETCHEN(config->ahbConfig.buffer[i].enablePrefetch) | + FLEXSPI_AHBRXBUFCR0_PRIORITY(config->ahbConfig.buffer[i].priority) | + FLEXSPI_AHBRXBUFCR0_MSTRID(config->ahbConfig.buffer[i].masterIndex) | + FLEXSPI_AHBRXBUFCR0_BUFSZ(config->ahbConfig.buffer[i].bufferSize / 8); + base->AHBRXBUFCR0[i] = configValue; + } + + /* Configure IP Fifo watermarks. */ + base->IPRXFCR &= ~FLEXSPI_IPRXFCR_RXWMRK_MASK; + base->IPRXFCR |= FLEXSPI_IPRXFCR_RXWMRK(config->rxWatermark / 8 - 1); + base->IPTXFCR &= ~FLEXSPI_IPTXFCR_TXWMRK_MASK; + base->IPTXFCR |= FLEXSPI_IPTXFCR_TXWMRK(config->txWatermark / 8 - 1); + + /* Reset flash size on all ports */ + for (i = 0; i < kFLEXSPI_PortCount; i++) + { + base->FLSHCR0[i] = 0; + } +} + +/*! + * brief Gets default settings for FLEXSPI. + * + * param config FLEXSPI configuration structure. + */ +void FLEXSPI_GetDefaultConfig(flexspi_config_t *config) +{ + /* Initializes the configure structure to zero. */ + memset(config, 0, sizeof(*config)); + + config->rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally; + config->enableSckFreeRunning = false; + config->enableCombination = false; + config->enableDoze = true; + config->enableHalfSpeedAccess = false; + config->enableSckBDiffOpt = false; + config->enableSameConfigForAll = false; + config->seqTimeoutCycle = 0xFFFFU; + config->ipGrantTimeoutCycle = 0xFFU; + config->txWatermark = 8; + config->rxWatermark = 8; + config->ahbConfig.enableAHBWriteIpTxFifo = false; + config->ahbConfig.enableAHBWriteIpRxFifo = false; + config->ahbConfig.ahbGrantTimeoutCycle = 0xFFU; + config->ahbConfig.ahbBusTimeoutCycle = 0xFFFFU; + config->ahbConfig.resumeWaitCycle = 0x20U; + memset(config->ahbConfig.buffer, 0, sizeof(config->ahbConfig.buffer)); + for (uint8_t i = 0; i < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++) + { + config->ahbConfig.buffer[i].enablePrefetch = true; /* Default enable AHB prefetch. */ + config->ahbConfig.buffer[i].bufferSize = 256; /* Default buffer size 256 bytes*/ + } + config->ahbConfig.enableClearAHBBufferOpt = false; + config->ahbConfig.enableReadAddressOpt = false; + config->ahbConfig.enableAHBPrefetch = false; + config->ahbConfig.enableAHBBufferable = false; + config->ahbConfig.enableAHBCachable = false; +} + +/*! + * brief Deinitializes the FLEXSPI module. + * + * Clears the FLEXSPI state and FLEXSPI module registers. + * param base FLEXSPI peripheral base address. + */ +void FLEXSPI_Deinit(FLEXSPI_Type *base) +{ + /* Reset peripheral. */ + FLEXSPI_SoftwareReset(base); +} + +/*! + * brief Configures the connected device parameter. + * + * This function configures the connected device relevant parameters, such as the size, command, and so on. + * The flash configuration value cannot have a default value. The user needs to configure it according to the + * connected device. + * + * param base FLEXSPI peripheral base address. + * param config Flash configuration parameters. + * param port FLEXSPI Operation port. + */ +void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port) +{ + uint32_t configValue = 0; + uint32_t statusValue = 0; + uint8_t index = port >> 1; /* PortA with index 0, PortB with index 1. */ + + /* Wait for bus idle before change flash configuration. */ + while (!FLEXSPI_GetBusIdleStatus(base)) + { + } + + /* Configure flash size. */ + base->FLSHCR0[port] = config->flashSize; + + /* Configure flash parameters. */ + base->FLSHCR1[port] = FLEXSPI_FLSHCR1_CSINTERVAL(config->CSInterval) | + FLEXSPI_FLSHCR1_CSINTERVALUNIT(config->CSIntervalUnit) | + FLEXSPI_FLSHCR1_TCSH(config->CSHoldTime) | FLEXSPI_FLSHCR1_TCSS(config->CSSetupTime) | + FLEXSPI_FLSHCR1_CAS(config->columnspace) | FLEXSPI_FLSHCR1_WA(config->enableWordAddress); + + /* Configure AHB operation items. */ + configValue = base->FLSHCR2[port]; + + configValue &= ~(FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK | FLEXSPI_FLSHCR2_AWRWAIT_MASK | FLEXSPI_FLSHCR2_AWRSEQNUM_MASK | + FLEXSPI_FLSHCR2_AWRSEQID_MASK | FLEXSPI_FLSHCR2_ARDSEQNUM_MASK | FLEXSPI_FLSHCR2_AWRSEQID_MASK); + + configValue |= + FLEXSPI_FLSHCR2_AWRWAITUNIT(config->AHBWriteWaitUnit) | FLEXSPI_FLSHCR2_AWRWAIT(config->AHBWriteWaitInterval); + + if (config->AWRSeqNumber > 0U) + { + configValue |= + FLEXSPI_FLSHCR2_AWRSEQID(config->AWRSeqIndex) | FLEXSPI_FLSHCR2_AWRSEQNUM(config->AWRSeqNumber - 1U); + } + + if (config->ARDSeqNumber > 0U) + { + configValue |= + FLEXSPI_FLSHCR2_ARDSEQID(config->ARDSeqIndex) | FLEXSPI_FLSHCR2_ARDSEQNUM(config->ARDSeqNumber - 1U); + } + + base->FLSHCR2[port] = configValue; + + /* Configure DLL. */ + configValue = FLEXSPI_ConfigureDll(base, config); + base->DLLCR[index] = configValue; + + /* Configure write mask. */ + if (config->enableWriteMask) + { + base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMOPT1_MASK; + } + else + { + base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMOPT1_MASK; + } + + if (index == 0) /*PortA*/ + { + base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENA_MASK; + base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENA(config->enableWriteMask); + } + else + { + base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENB_MASK; + base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENB(config->enableWriteMask); + } + + /* Exit stop mode. */ + base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + + /* According to ERR011377, need to delay at least 100 NOPs to ensure the DLL is locked. */ + statusValue = (index == 0) ? + (kFLEXSPI_FlashASampleClockSlaveDelayLocked | kFLEXSPI_FlashASampleClockRefDelayLocked) : + (kFLEXSPI_FlashBSampleClockSlaveDelayLocked | kFLEXSPI_FlashBSampleClockRefDelayLocked); + + if (configValue & FLEXSPI_DLLCR_DLLEN_MASK) + { + /* Wait slave delay line locked and slave reference delay line locked. */ + while ((base->STS2 & statusValue) != statusValue) + { + } + + /* Wait at least 100 NOPs*/ + for (uint8_t delay = 100; delay > 0; delay--) + { + __NOP(); + } + } +} + +/*! brief Updates the LUT table. + * + * param base FLEXSPI peripheral base address. + * param index From which index start to update. It could be any index of the LUT table, which + * also allows user to update command content inside a command. Each command consists of up to + * 8 instructions and occupy 4*32-bit memory. + * param cmd Command sequence array. + * param count Number of sequences. + */ +void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count) +{ + assert(index < 64U); + + uint8_t i = 0; + volatile uint32_t *lutBase; + + /* Wait for bus idle before change flash configuration. */ + while (!FLEXSPI_GetBusIdleStatus(base)) + { + } + + /* Unlock LUT for update. */ + base->LUTKEY = FLEXSPI_LUT_KEY_VAL; + base->LUTCR = 0x02; + + lutBase = &base->LUT[index]; + for (i = 0; i < count; i++) + { + *lutBase++ = *cmd++; + } + + /* Lock LUT. */ + base->LUTKEY = FLEXSPI_LUT_KEY_VAL; + base->LUTCR = 0x01; +} + +/*! brief Update read sample clock source + * + * param base FLEXSPI peripheral base address. + * param clockSource clockSource of type #flexspi_read_sample_clock_t + */ +void FLEXSPI_UpdateRxSampleClock(FLEXSPI_Type *base, flexspi_read_sample_clock_t clockSource) +{ + uint32_t mcr0Val; + + /* Wait for bus idle before change flash configuration. */ + while (!FLEXSPI_GetBusIdleStatus(base)) + { + } + + mcr0Val = base->MCR0; + mcr0Val &= ~FLEXSPI_MCR0_RXCLKSRC_MASK; + mcr0Val |= FLEXSPI_MCR0_RXCLKSRC(clockSource); + base->MCR0 = mcr0Val; + + /* Reset peripheral. */ + FLEXSPI_SoftwareReset(base); +} + +/*! + * brief Sends a buffer of data bytes using blocking method. + * note This function blocks via polling until all bytes have been sent. + * param base FLEXSPI peripheral base address + * param buffer The data bytes to send + * param size The number of data bytes to send + * retval kStatus_Success write success without error + * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout + * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequencen error detected + * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected + */ +status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size) +{ + uint8_t txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1; + uint32_t status; + status_t result = kStatus_Success; + uint32_t i = 0; + + /* Send data buffer */ + while (size) + { + /* Wait until there is room in the fifo. This also checks for errors. */ + while (!((status = base->INTR) & kFLEXSPI_IpTxFifoWatermarkEmpltyFlag)) + { + } + + result = FLEXSPI_CheckAndClearError(base, status); + + if (result) + { + return result; + } + + /* Write watermark level data into tx fifo . */ + if (size >= 8 * txWatermark) + { + for (i = 0; i < 2 * txWatermark; i++) + { + base->TFDR[i] = *buffer++; + } + + size = size - 8 * txWatermark; + } + else + { + for (i = 0; i < (size / 4 + 1); i++) + { + base->TFDR[i] = *buffer++; + } + size = 0; + } + + /* Push a watermark level datas into IP TX FIFO. */ + base->INTR |= kFLEXSPI_IpTxFifoWatermarkEmpltyFlag; + } + + return result; +} + +/*! + * brief Receives a buffer of data bytes using a blocking method. + * note This function blocks via polling until all bytes have been sent. + * param base FLEXSPI peripheral base address + * param buffer The data bytes to send + * param size The number of data bytes to receive + * retval kStatus_Success read success without error + * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout + * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequencen error detected + * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected + */ +status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size) +{ + uint8_t rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1; + uint32_t status; + status_t result = kStatus_Success; + uint32_t i = 0; + + /* Send data buffer */ + while (size) + { + if (size >= 8 * rxWatermark) + { + /* Wait until there is room in the fifo. This also checks for errors. */ + while (!((status = base->INTR) & kFLEXSPI_IpRxFifoWatermarkAvailableFlag)) + { + result = FLEXSPI_CheckAndClearError(base, status); + + if (result) + { + return result; + } + } + } + else + { + /* Wait fill level. This also checks for errors. */ + while (size > ((((base->IPRXFSTS) & FLEXSPI_IPRXFSTS_FILL_MASK) >> FLEXSPI_IPRXFSTS_FILL_SHIFT) * 8U)) + { + result = FLEXSPI_CheckAndClearError(base, base->INTR); + + if (result) + { + return result; + } + } + } + + result = FLEXSPI_CheckAndClearError(base, base->INTR); + + if (result) + { + return result; + } + + /* Read watermark level data from rx fifo . */ + if (size >= 8 * rxWatermark) + { + for (i = 0; i < 2 * rxWatermark; i++) + { + *buffer++ = base->RFDR[i]; + } + + size = size - 8 * rxWatermark; + } + else + { + for (i = 0; i < (size / 4 + 1); i++) + { + *buffer++ = base->RFDR[i]; + } + size = 0; + } + + /* Pop out a watermark level datas from IP RX FIFO. */ + base->INTR |= kFLEXSPI_IpRxFifoWatermarkAvailableFlag; + } + + return result; +} + +/*! + * brief Execute command to transfer a buffer data bytes using a blocking method. + * param base FLEXSPI peripheral base address + * param xfer pointer to the transfer structure. + * retval kStatus_Success command transfer success without error + * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout + * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequencen error detected + * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected + */ +status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer) +{ + uint32_t configValue = 0; + status_t result = kStatus_Success; + + /* Clear sequence pointer before sending data to external devices. */ + base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK; + + /* Clear former pending status before start this transfer. */ + base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK | + FLEXSPI_INTR_IPCMDGE_MASK; + + /* Configure base address. */ + base->IPCR0 = xfer->deviceAddress; + + /* Reset fifos. */ + base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK; + base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK; + + /* Configure data size. */ + if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config)) + { + configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize); + } + + /* Configure sequence ID. */ + configValue |= FLEXSPI_IPCR1_ISEQID(xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM(xfer->SeqNumber - 1); + base->IPCR1 = configValue; + + /* Start Transfer. */ + base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK; + + if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config)) + { + result = FLEXSPI_WriteBlocking(base, xfer->data, xfer->dataSize); + } + else if (xfer->cmdType == kFLEXSPI_Read) + { + result = FLEXSPI_ReadBlocking(base, xfer->data, xfer->dataSize); + } + else + { + } + + /* Wait for bus idle. */ + while (!FLEXSPI_GetBusIdleStatus(base)) + { + } + + if (xfer->cmdType == kFLEXSPI_Command) + { + result = FLEXSPI_CheckAndClearError(base, base->INTR); + } + + return result; +} + +/*! + * brief Initializes the FLEXSPI handle which is used in transactional functions. + * + * param base FLEXSPI peripheral base address. + * param handle pointer to flexspi_handle_t structure to store the transfer state. + * param callback pointer to user callback function. + * param userData user parameter passed to the callback function. + */ +void FLEXSPI_TransferCreateHandle(FLEXSPI_Type *base, + flexspi_handle_t *handle, + flexspi_transfer_callback_t callback, + void *userData) +{ + assert(handle); + + uint32_t instance = FLEXSPI_GetInstance(base); + + /* Zero handle. */ + memset(handle, 0, sizeof(*handle)); + + /* Set callback and userData. */ + handle->completionCallback = callback; + handle->userData = userData; + +#if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ + /* Save the context in global variables to support the double weak mechanism. */ + s_flexspiHandle[instance] = handle; +#endif + + /* Enable NVIC interrupt. */ + EnableIRQ(s_flexspiIrqs[instance]); +} + +/*! + * brief Performs a interrupt non-blocking transfer on the FLEXSPI bus. + * + * note Calling the API returns immediately after transfer initiates. The user needs + * to call FLEXSPI_GetTransferCount to poll the transfer status to check whether + * the transfer is finished. If the return status is not kStatus_FLEXSPI_Busy, the transfer + * is finished. For FLEXSPI_Read, the dataSize should be multiple of rx watermark levle, or + * FLEXSPI could not read data properly. + * + * param base FLEXSPI peripheral base address. + * param handle pointer to flexspi_handle_t structure which stores the transfer state. + * param xfer pointer to flexspi_transfer_t structure. + * retval kStatus_Success Successfully start the data transmission. + * retval kStatus_FLEXSPI_Busy Previous transmission still not finished. + */ +status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer) +{ + uint32_t configValue = 0; + status_t result = kStatus_Success; + + assert(handle); + assert(xfer); + + /* Check if the I2C bus is idle - if not return busy status. */ + if (handle->state != kFLEXSPI_Idle) + { + result = kStatus_FLEXSPI_Busy; + } + else + { + handle->data = xfer->data; + handle->dataSize = xfer->dataSize; + handle->transferTotalSize = xfer->dataSize; + handle->state = (xfer->cmdType == kFLEXSPI_Read) ? kFLEXSPI_BusyRead : kFLEXSPI_BusyWrite; + + /* Clear sequence pointer before sending data to external devices. */ + base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK; + + /* Clear former pending status before start this transfer. */ + base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK | + FLEXSPI_INTR_IPCMDGE_MASK; + + /* Configure base address. */ + base->IPCR0 = xfer->deviceAddress; + + /* Reset fifos. */ + base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK; + base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK; + + /* Configure data size. */ + if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write)) + { + configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize); + } + + /* Configure sequence ID. */ + configValue |= FLEXSPI_IPCR1_ISEQID(xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM(xfer->SeqNumber - 1); + base->IPCR1 = configValue; + + /* Start Transfer. */ + base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK; + + if (handle->state == kFLEXSPI_BusyRead) + { + FLEXSPI_EnableInterrupts(base, kFLEXSPI_IpRxFifoWatermarkAvailableFlag | + kFLEXSPI_SequenceExecutionTimeoutFlag | + kFLEXSPI_IpCommandSequenceErrorFlag | + kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag); + } + else + { + FLEXSPI_EnableInterrupts(base, kFLEXSPI_IpTxFifoWatermarkEmpltyFlag | + kFLEXSPI_SequenceExecutionTimeoutFlag | + kFLEXSPI_IpCommandSequenceErrorFlag | + kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag); + } + } + + return result; +} + +/*! + * brief Gets the master transfer status during a interrupt non-blocking transfer. + * + * param base FLEXSPI peripheral base address. + * param handle pointer to flexspi_handle_t structure which stores the transfer state. + * param count Number of bytes transferred so far by the non-blocking transaction. + * retval kStatus_InvalidArgument count is Invalid. + * retval kStatus_Success Successfully return the count. + */ +status_t FLEXSPI_TransferGetCount(FLEXSPI_Type *base, flexspi_handle_t *handle, size_t *count) +{ + assert(handle); + + status_t result = kStatus_Success; + + if (handle->state == kFLEXSPI_Idle) + { + result = kStatus_NoTransferInProgress; + } + else + { + *count = handle->transferTotalSize - handle->dataSize; + } + + return result; +} + +/*! + * brief Aborts an interrupt non-blocking transfer early. + * + * note This API can be called at any time when an interrupt non-blocking transfer initiates + * to abort the transfer early. + * + * param base FLEXSPI peripheral base address. + * param handle pointer to flexspi_handle_t structure which stores the transfer state + */ +void FLEXSPI_TransferAbort(FLEXSPI_Type *base, flexspi_handle_t *handle) +{ + assert(handle); + + FLEXSPI_DisableInterrupts(base, kIrqFlags); + handle->state = kFLEXSPI_Idle; +} + +/*! + * brief Master interrupt handler. + * + * param base FLEXSPI peripheral base address. + * param handle pointer to flexspi_handle_t structure. + */ +void FLEXSPI_TransferHandleIRQ(FLEXSPI_Type *base, flexspi_handle_t *handle) +{ + uint32_t status; + status_t result; + uint32_t intEnableStatus; + uint8_t txWatermark; + uint8_t rxWatermark; + uint8_t i = 0; + + status = base->INTR; + intEnableStatus = base->INTEN; + + /* Check if interrupt is enabled and status is alerted. */ + if ((status & intEnableStatus) == 0U) + { + return; + } + + result = FLEXSPI_CheckAndClearError(base, status); + + if ((result != kStatus_Success) && (handle->completionCallback != NULL)) + { + FLEXSPI_TransferAbort(base, handle); + if (handle->completionCallback) + { + handle->completionCallback(base, handle, result, handle->userData); + } + return; + } + + if ((status & kFLEXSPI_IpRxFifoWatermarkAvailableFlag) && (handle->state == kFLEXSPI_BusyRead)) + { + rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1; + + /* Read watermark level data from rx fifo . */ + if (handle->dataSize >= 8 * rxWatermark) + { + /* Read watermark level data from rx fifo . */ + for (i = 0; i < 2 * rxWatermark; i++) + { + *handle->data++ = base->RFDR[i]; + } + + handle->dataSize = handle->dataSize - 8 * rxWatermark; + } + else + { + for (i = 0; i < (handle->dataSize / 4 + 1); i++) + { + *handle->data++ = base->RFDR[i]; + } + handle->dataSize = 0; + } + /* Pop out a watermark level datas from IP RX FIFO. */ + base->INTR |= kFLEXSPI_IpRxFifoWatermarkAvailableFlag; + } + + if (status & kFLEXSPI_IpCommandExcutionDoneFlag) + { + base->INTR |= kFLEXSPI_IpCommandExcutionDoneFlag; + + FLEXSPI_TransferAbort(base, handle); + + if (handle->completionCallback) + { + handle->completionCallback(base, handle, kStatus_Success, handle->userData); + } + } + + /* TX FIFO empty interrupt, push watermark level data into tx FIFO. */ + if ((status & kFLEXSPI_IpTxFifoWatermarkEmpltyFlag) && (handle->state == kFLEXSPI_BusyWrite)) + { + if (handle->dataSize) + { + txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1; + /* Write watermark level data into tx fifo . */ + if (handle->dataSize >= 8 * txWatermark) + { + for (i = 0; i < 2 * txWatermark; i++) + { + base->TFDR[i] = *handle->data++; + } + + handle->dataSize = handle->dataSize - 8 * txWatermark; + } + else + { + for (i = 0; i < (handle->dataSize / 4 + 1); i++) + { + base->TFDR[i] = *handle->data++; + } + handle->dataSize = 0; + } + + /* Push a watermark level datas into IP TX FIFO. */ + base->INTR |= kFLEXSPI_IpTxFifoWatermarkEmpltyFlag; + } + } + else + { + } +} + +#if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ +#if defined(FLEXSPI) +void FLEXSPI_DriverIRQHandler(void) +{ + FLEXSPI_TransferHandleIRQ(FLEXSPI, s_flexspiHandle[0]); +/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + exception return operation might vector to incorrect interrupt */ +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif +} +#endif + +#if defined(FLEXSPI0) +void FLEXSPI0_DriverIRQHandler(void) +{ + FLEXSPI_TransferHandleIRQ(FLEXSPI0, s_flexspiHandle[0]); +/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + exception return operation might vector to incorrect interrupt */ +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif +} +#endif +#if defined(FLEXSPI1) +void FLEXSPI1_DriverIRQHandler(void) +{ + FLEXSPI_TransferHandleIRQ(FLEXSPI1, s_flexspiHandle[1]); +/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + exception return operation might vector to incorrect interrupt */ +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif +} +#endif + +#if defined(LSIO__FLEXSPI0) +void LSIO_OCTASPI0_INT_DriverIRQHandler(void) +{ + FLEXSPI_TransferHandleIRQ(LSIO__FLEXSPI0, s_flexspiHandle[0]); +/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + exception return operation might vector to incorrect interrupt */ +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif +} +#endif +#if defined(LSIO__FLEXSPI1) +void LSIO_OCTASPI1_INT_DriverIRQHandler(void) +{ + FLEXSPI_TransferHandleIRQ(LSIO__FLEXSPI1, s_flexspiHandle[1]); +/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + exception return operation might vector to incorrect interrupt */ +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif +} +#endif + +#endif diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_flexspi.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_flexspi.h new file mode 100755 index 000000000..908519875 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_flexspi.h @@ -0,0 +1,831 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __FSL_FLEXSPI_H_ +#define __FSL_FLEXSPI_H_ + +#include +#include "fsl_device_registers.h" +#include "fsl_common.h" + +#define spi_print KPrintf +#define spi_trace() KPrintf("lw: [%s][%d] passed!\n", __func__, __LINE__) + +/*! + * @addtogroup flexspi + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief FLEXSPI driver version 2.1.1. */ +#define FSL_FLEXSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) +/*@}*/ + +#define FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNTn(0) + +/*! @breif Formula to form FLEXSPI instructions in LUT table. */ +#define FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \ + (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) | \ + FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1)) + +/*! @brief Status structure of FLEXSPI.*/ +enum _flexspi_status +{ + kStatus_FLEXSPI_Busy = MAKE_STATUS(kStatusGroup_FLEXSPI, 0), /*!< FLEXSPI is busy */ + kStatus_FLEXSPI_SequenceExecutionTimeout = MAKE_STATUS(kStatusGroup_FLEXSPI, 1), /*!< Sequence execution timeout + error occurred during FLEXSPI transfer. */ + kStatus_FLEXSPI_IpCommandSequenceError = MAKE_STATUS(kStatusGroup_FLEXSPI, 2), /*!< IP command Sequence execution + timeout error occurred during FLEXSPI transfer. */ + kStatus_FLEXSPI_IpCommandGrantTimeout = MAKE_STATUS(kStatusGroup_FLEXSPI, 3), /*!< IP command grant timeout error + occurred during FLEXSPI transfer. */ +}; + +/*! @brief CMD definition of FLEXSPI, use to form LUT instruction. */ +enum _flexspi_command +{ + kFLEXSPI_Command_STOP = 0x00U, /*!< Stop execution, deassert CS. */ + kFLEXSPI_Command_SDR = 0x01U, /*!< Transmit Command code to Flash, using SDR mode. */ + kFLEXSPI_Command_RADDR_SDR = 0x02U, /*!< Transmit Row Address to Flash, using SDR mode. */ + kFLEXSPI_Command_CADDR_SDR = 0x03U, /*!< Transmit Column Address to Flash, using SDR mode. */ + kFLEXSPI_Command_MODE1_SDR = 0x04U, /*!< Transmit 1-bit Mode bits to Flash, using SDR mode. */ + kFLEXSPI_Command_MODE2_SDR = 0x05U, /*!< Transmit 2-bit Mode bits to Flash, using SDR mode. */ + kFLEXSPI_Command_MODE4_SDR = 0x06U, /*!< Transmit 4-bit Mode bits to Flash, using SDR mode. */ + kFLEXSPI_Command_MODE8_SDR = 0x07U, /*!< Transmit 8-bit Mode bits to Flash, using SDR mode. */ + kFLEXSPI_Command_WRITE_SDR = 0x08U, /*!< Transmit Programming Data to Flash, using SDR mode. */ + kFLEXSPI_Command_READ_SDR = 0x09U, /*!< Receive Read Data from Flash, using SDR mode. */ + kFLEXSPI_Command_LEARN_SDR = 0x0AU, /*!< Receive Read Data or Preamble bit from Flash, SDR mode. */ + kFLEXSPI_Command_DATSZ_SDR = 0x0BU, /*!< Transmit Read/Program Data size (byte) to Flash, SDR mode. */ + kFLEXSPI_Command_DUMMY_SDR = 0x0CU, /*!< Leave data lines undriven by FlexSPI controller.*/ + kFLEXSPI_Command_DUMMY_RWDS_SDR = 0x0DU, /*!< Leave data lines undriven by FlexSPI controller, + dummy cycles decided by RWDS. */ + kFLEXSPI_Command_DDR = 0x21U, /*!< Transmit Command code to Flash, using DDR mode. */ + kFLEXSPI_Command_RADDR_DDR = 0x22U, /*!< Transmit Row Address to Flash, using DDR mode. */ + kFLEXSPI_Command_CADDR_DDR = 0x23U, /*!< Transmit Column Address to Flash, using DDR mode. */ + kFLEXSPI_Command_MODE1_DDR = 0x24U, /*!< Transmit 1-bit Mode bits to Flash, using DDR mode. */ + kFLEXSPI_Command_MODE2_DDR = 0x25U, /*!< Transmit 2-bit Mode bits to Flash, using DDR mode. */ + kFLEXSPI_Command_MODE4_DDR = 0x26U, /*!< Transmit 4-bit Mode bits to Flash, using DDR mode. */ + kFLEXSPI_Command_MODE8_DDR = 0x27U, /*!< Transmit 8-bit Mode bits to Flash, using DDR mode. */ + kFLEXSPI_Command_WRITE_DDR = 0x28U, /*!< Transmit Programming Data to Flash, using DDR mode. */ + kFLEXSPI_Command_READ_DDR = 0x29U, /*!< Receive Read Data from Flash, using DDR mode. */ + kFLEXSPI_Command_LEARN_DDR = 0x2AU, /*!< Receive Read Data or Preamble bit from Flash, DDR mode. */ + kFLEXSPI_Command_DATSZ_DDR = 0x2BU, /*!< Transmit Read/Program Data size (byte) to Flash, DDR mode. */ + kFLEXSPI_Command_DUMMY_DDR = 0x2CU, /*!< Leave data lines undriven by FlexSPI controller.*/ + kFLEXSPI_Command_DUMMY_RWDS_DDR = 0x2DU, /*!< Leave data lines undriven by FlexSPI controller, + dummy cycles decided by RWDS. */ + kFLEXSPI_Command_JUMP_ON_CS = 0x1FU, /*!< Stop execution, deassert CS and save operand[7:0] as the + instruction start pointer for next sequence */ +}; + +/*! @brief pad definition of FLEXSPI, use to form LUT instruction. */ +typedef enum _flexspi_pad +{ + kFLEXSPI_1PAD = 0x00U, /*!< Transmit command/address and transmit/receive data only through DATA0/DATA1. */ + kFLEXSPI_2PAD = 0x01U, /*!< Transmit command/address and transmit/receive data only through DATA[1:0]. */ + kFLEXSPI_4PAD = 0x02U, /*!< Transmit command/address and transmit/receive data only through DATA[3:0]. */ + kFLEXSPI_8PAD = 0x03U, /*!< Transmit command/address and transmit/receive data only through DATA[7:0]. */ +} flexspi_pad_t; + +/*! @brief FLEXSPI interrupt status flags.*/ +typedef enum _flexspi_flags +{ + kFLEXSPI_SequenceExecutionTimeoutFlag = FLEXSPI_INTEN_SEQTIMEOUTEN_MASK, /*!< Sequence execution timeout. */ + kFLEXSPI_AhbBusTimeoutFlag = FLEXSPI_INTEN_AHBBUSTIMEOUTEN_MASK, /*!< AHB Bus timeout. */ + kFLEXSPI_SckStoppedBecauseTxEmptyFlag = + FLEXSPI_INTEN_SCKSTOPBYWREN_MASK, /*!< SCK is stopped during command + sequence because Async TX FIFO empty. */ + kFLEXSPI_SckStoppedBecauseRxFullFlag = + FLEXSPI_INTEN_SCKSTOPBYRDEN_MASK, /*!< SCK is stopped during command + sequence because Async RX FIFO full. */ +#if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_DATA_LEARN)) && (FSL_FEATURE_FLEXSPI_HAS_NO_DATA_LEARN)) + kFLEXSPI_DataLearningFailedFlag = FLEXSPI_INTEN_DATALEARNFAILEN_MASK, /*!< Data learning failed. */ +#endif + kFLEXSPI_IpTxFifoWatermarkEmpltyFlag = FLEXSPI_INTEN_IPTXWEEN_MASK, /*!< IP TX FIFO WaterMark empty. */ + kFLEXSPI_IpRxFifoWatermarkAvailableFlag = FLEXSPI_INTEN_IPRXWAEN_MASK, /*!< IP RX FIFO WaterMark available. */ + kFLEXSPI_AhbCommandSequenceErrorFlag = + FLEXSPI_INTEN_AHBCMDERREN_MASK, /*!< AHB triggered Command Sequences Error. */ + kFLEXSPI_IpCommandSequenceErrorFlag = FLEXSPI_INTEN_IPCMDERREN_MASK, /*!< IP triggered Command Sequences Error. */ + kFLEXSPI_AhbCommandGrantTimeoutFlag = + FLEXSPI_INTEN_AHBCMDGEEN_MASK, /*!< AHB triggered Command Sequences Grant Timeout. */ + kFLEXSPI_IpCommandGrantTimeoutFlag = + FLEXSPI_INTEN_IPCMDGEEN_MASK, /*!< IP triggered Command Sequences Grant Timeout. */ + kFLEXSPI_IpCommandExcutionDoneFlag = + FLEXSPI_INTEN_IPCMDDONEEN_MASK, /*!< IP triggered Command Sequences Execution finished. */ + kFLEXSPI_AllInterruptFlags = 0xFFFU, /*!< All flags. */ +} flexspi_flags_t; + +/*! @brief FLEXSPI sample clock source selection for Flash Reading.*/ +typedef enum _flexspi_read_sample_clock +{ + kFLEXSPI_ReadSampleClkLoopbackInternally = 0x0U, /*!< Dummy Read strobe generated by FlexSPI Controller + and loopback internally. */ + kFLEXSPI_ReadSampleClkLoopbackFromDqsPad = 0x1U, /*!< Dummy Read strobe generated by FlexSPI Controller + and loopback from DQS pad. */ + kFLEXSPI_ReadSampleClkLoopbackFromSckPad = 0x2U, /*!< SCK output clock and loopback from SCK pad. */ + kFLEXSPI_ReadSampleClkExternalInputFromDqsPad = 0x3U, /*!< Flash provided Read strobe and input from DQS pad. */ +} flexspi_read_sample_clock_t; + +/*! @brief FLEXSPI interval unit for flash device select.*/ +typedef enum _flexspi_cs_interval_cycle_unit +{ + kFLEXSPI_CsIntervalUnit1SckCycle = 0x0U, /*!< Chip selection interval: CSINTERVAL * 1 serial clock cycle. */ + kFLEXSPI_CsIntervalUnit256SckCycle = 0x1U, /*!< Chip selection interval: CSINTERVAL * 256 serial clock cycle. */ +} flexspi_cs_interval_cycle_unit_t; + +/*! @brief FLEXSPI AHB wait interval unit for writting.*/ +typedef enum _flexspi_ahb_write_wait_unit +{ + kFLEXSPI_AhbWriteWaitUnit2AhbCycle = 0x0U, /*!< AWRWAIT unit is 2 ahb clock cycle. */ + kFLEXSPI_AhbWriteWaitUnit8AhbCycle = 0x1U, /*!< AWRWAIT unit is 8 ahb clock cycle. */ + kFLEXSPI_AhbWriteWaitUnit32AhbCycle = 0x2U, /*!< AWRWAIT unit is 32 ahb clock cycle. */ + kFLEXSPI_AhbWriteWaitUnit128AhbCycle = 0x3U, /*!< AWRWAIT unit is 128 ahb clock cycle. */ + kFLEXSPI_AhbWriteWaitUnit512AhbCycle = 0x4U, /*!< AWRWAIT unit is 512 ahb clock cycle. */ + kFLEXSPI_AhbWriteWaitUnit2048AhbCycle = 0x5U, /*!< AWRWAIT unit is 2048 ahb clock cycle. */ + kFLEXSPI_AhbWriteWaitUnit8192AhbCycle = 0x6U, /*!< AWRWAIT unit is 8192 ahb clock cycle. */ + kFLEXSPI_AhbWriteWaitUnit32768AhbCycle = 0x7U, /*!< AWRWAIT unit is 32768 ahb clock cycle. */ +} flexspi_ahb_write_wait_unit_t; + +/*! @brief Error Code when IP command Error detected.*/ +typedef enum _flexspi_ip_error_code +{ + kFLEXSPI_IpCmdErrorNoError = 0x0U, /*!< No error. */ + kFLEXSPI_IpCmdErrorJumpOnCsInIpCmd = 0x2U, /*!< IP command with JMP_ON_CS instruction used. */ + kFLEXSPI_IpCmdErrorUnknownOpCode = 0x3U, /*!< Unknown instruction opcode in the sequence. */ + kFLEXSPI_IpCmdErrorSdrDummyInDdrSequence = 0x4U, /*!< Instruction DUMMY_SDR/DUMMY_RWDS_SDR + used in DDR sequence. */ + kFLEXSPI_IpCmdErrorDdrDummyInSdrSequence = 0x5U, /*!< Instruction DUMMY_DDR/DUMMY_RWDS_DDR + used in SDR sequence. */ + kFLEXSPI_IpCmdErrorInvalidAddress = 0x6U, /*!< Flash access start address exceed the whole + flash address range (A1/A2/B1/B2). */ + kFLEXSPI_IpCmdErrorSequenceExecutionTimeout = 0xEU, /*!< Sequence execution timeout. */ + kFLEXSPI_IpCmdErrorFlashBoundaryAcrosss = 0xFU, /*!< Flash boundary crossed. */ +} flexspi_ip_error_code_t; + +/*! @brief Error Code when AHB command Error detected.*/ +typedef enum _flexspi_ahb_error_code +{ + kFLEXSPI_AhbCmdErrorNoError = 0x0U, /*!< No error. */ + kFLEXSPI_AhbCmdErrorJumpOnCsInWriteCmd = 0x2U, /*!< AHB Write command with JMP_ON_CS instruction + used in the sequence. */ + kFLEXSPI_AhbCmdErrorUnknownOpCode = 0x3U, /*!< Unknown instruction opcode in the sequence. */ + kFLEXSPI_AhbCmdErrorSdrDummyInDdrSequence = 0x4U, /*!< Instruction DUMMY_SDR/DUMMY_RWDS_SDR used + in DDR sequence. */ + kFLEXSPI_AhbCmdErrorDdrDummyInSdrSequence = 0x5U, /*!< Instruction DUMMY_DDR/DUMMY_RWDS_DDR + used in SDR sequence. */ + kFLEXSPI_AhbCmdSequenceExecutionTimeout = 0x6U, /*!< Sequence execution timeout. */ +} flexspi_ahb_error_code_t; + +/*! @brief FLEXSPI operation port select.*/ +typedef enum _flexspi_port +{ + kFLEXSPI_PortA1 = 0x0U, /*!< Access flash on A1 port. */ + kFLEXSPI_PortA2, /*!< Access flash on A2 port. */ + kFLEXSPI_PortB1, /*!< Access flash on B1 port. */ + kFLEXSPI_PortB2, /*!< Access flash on B2 port. */ + kFLEXSPI_PortCount +} flexspi_port_t; + +/*! @brief Trigger source of current command sequence granted by arbitrator.*/ +typedef enum _flexspi_arb_command_source +{ + kFLEXSPI_AhbReadCommand = 0x0U, + kFLEXSPI_AhbWriteCommand = 0x1U, + kFLEXSPI_IpCommand = 0x2U, + kFLEXSPI_SuspendedCommand = 0x3U, +} flexspi_arb_command_source_t; + +typedef enum _flexspi_command_type +{ + kFLEXSPI_Command, /*!< FlexSPI operation: Only command, both TX and Rx buffer are ignored. */ + kFLEXSPI_Config, /*!< FlexSPI operation: Configure device mode, the TX fifo size is fixed in LUT. */ + kFLEXSPI_Read, /* /!< FlexSPI operation: Read, only Rx Buffer is effective. */ + kFLEXSPI_Write, /* /!< FlexSPI operation: Read, only Tx Buffer is effective. */ +} flexspi_command_type_t; + +typedef struct _flexspi_ahbBuffer_config +{ + uint8_t priority; /*!< This priority for AHB Master Read which this AHB RX Buffer is assigned. */ + uint8_t masterIndex; /*!< AHB Master ID the AHB RX Buffer is assigned. */ + uint16_t bufferSize; /*!< AHB buffer size in byte. */ + bool enablePrefetch; /*!< AHB Read Prefetch Enable for current AHB RX Buffer corresponding Master, allows + prefetch disable/enable seperately for each master. */ +} flexspi_ahbBuffer_config_t; + +/*! @brief FLEXSPI configuration structure. */ +typedef struct _flexspi_config +{ + flexspi_read_sample_clock_t rxSampleClock; /*!< Sample Clock source selection for Flash Reading. */ + bool enableSckFreeRunning; /*!< Enable/disable SCK output free-running. */ + bool enableCombination; /*!< Enable/disable combining PORT A and B Data Pins + (SIOA[3:0] and SIOB[3:0]) to support Flash Octal mode. */ + bool enableDoze; /*!< Enable/disable doze mode support. */ + bool enableHalfSpeedAccess; /*!< Enable/disable divide by 2 of the clock for half + speed commands. */ + bool enableSckBDiffOpt; /*!< Enable/disable SCKB pad use as SCKA differential clock + output, when enable, Port B flash access is not available. */ + bool enableSameConfigForAll; /*!< Enable/disable same configuration for all connected devices + when enabled, same configuration in FLASHA1CRx is applied to all. */ + uint16_t seqTimeoutCycle; /*!< Timeout wait cycle for command sequence execution, + timeout after ahbGrantTimeoutCyle*1024 serial root clock cycles. */ + uint8_t ipGrantTimeoutCycle; /*!< Timeout wait cycle for IP command grant, timeout after + ipGrantTimeoutCycle*1024 AHB clock cycles. */ + uint8_t txWatermark; /*!< FLEXSPI IP transmit watermark value. */ + uint8_t rxWatermark; /*!< FLEXSPI receive watermark value. */ + struct + { + bool enableAHBWriteIpTxFifo; /*!< Enable AHB bus write access to IP TX FIFO. */ + bool enableAHBWriteIpRxFifo; /*!< Enable AHB bus write access to IP RX FIFO. */ + uint8_t ahbGrantTimeoutCycle; /*!< Timeout wait cycle for AHB command grant, + timeout after ahbGrantTimeoutCyle*1024 AHB clock cycles. */ + uint16_t ahbBusTimeoutCycle; /*!< Timeout wait cycle for AHB read/write access, + timeout after ahbBusTimeoutCycle*1024 AHB clock cycles. */ + uint8_t resumeWaitCycle; /*!< Wait cycle for idle state before suspended command sequence + resume, timeout after ahbBusTimeoutCycle AHB clock cycles. */ + flexspi_ahbBuffer_config_t buffer[FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT]; /*!< AHB buffer size. */ + bool enableClearAHBBufferOpt; /*!< Enable/disable automatically clean AHB RX Buffer and TX Buffer + when FLEXSPI returns STOP mode ACK. */ + bool enableReadAddressOpt; /*!< Enable/disable remove AHB read burst start address alignment limitation. + when eanble, there is no AHB read burst start address alignment limitation. */ + bool enableAHBPrefetch; /*!< Enable/disable AHB read prefetch feature, when enabled, FLEXSPI + will fetch more data than current AHB burst. */ + bool enableAHBBufferable; /*!< Enable/disable AHB bufferable write access support, when enabled, + FLEXSPI return before waiting for command excution finished. */ + bool enableAHBCachable; /*!< Enable AHB bus cachable read access support. */ + } ahbConfig; +} flexspi_config_t; + +/*! @brief External device configuration items. */ +typedef struct _flexspi_device_config +{ + uint32_t flexspiRootClk; /*!< FLEXSPI serial root clock. */ + bool isSck2Enabled; /*!< FLEXSPI use SCK2. */ + uint32_t flashSize; /*!< Flash size in KByte. */ + flexspi_cs_interval_cycle_unit_t CSIntervalUnit; /*!< CS interval unit, 1 or 256 cycle. */ + uint16_t CSInterval; /*!< CS line assert interval, mutiply CS interval unit to + get the CS line assert interval cycles. */ + uint8_t CSHoldTime; /*!< CS line hold time. */ + uint8_t CSSetupTime; /*!< CS line setup time. */ + uint8_t dataValidTime; /*!< Data valid time for external device. */ + uint8_t columnspace; /*!< Column space size. */ + bool enableWordAddress; /*!< If enable word address.*/ + uint8_t AWRSeqIndex; /*!< Sequence ID for AHB write command. */ + uint8_t AWRSeqNumber; /*!< Sequence number for AHB write command. */ + uint8_t ARDSeqIndex; /*!< Sequence ID for AHB read command. */ + uint8_t ARDSeqNumber; /*!< Sequence number for AHB read command. */ + flexspi_ahb_write_wait_unit_t AHBWriteWaitUnit; /*!< AHB write wait unit. */ + uint16_t AHBWriteWaitInterval; /*!< AHB write wait interval, mutiply AHB write interval + unit to get the AHB write wait cycles. */ + bool enableWriteMask; /*!< Enable/Disable FLEXSPI drive DQS pin as write mask + when writing to external device. */ +} flexspi_device_config_t; + +/*! @brief Transfer structure for FLEXSPI. */ +typedef struct _flexspi_transfer +{ + uint32_t deviceAddress; /*!< Operation device address. */ + flexspi_port_t port; /*!< Operation port. */ + flexspi_command_type_t cmdType; /*!< Execution command type. */ + uint8_t seqIndex; /*!< Sequence ID for command. */ + uint8_t SeqNumber; /*!< Sequence number for command. */ + uint32_t *data; /*!< Data buffer. */ + size_t dataSize; /*!< Data size in bytes. */ +} flexspi_transfer_t; + +/* Forward declaration of the handle typedef. */ +typedef struct _flexspi_handle flexspi_handle_t; + +/*! @brief FLEXSPI transfer callback function. */ +typedef void (*flexspi_transfer_callback_t)(FLEXSPI_Type *base, + flexspi_handle_t *handle, + status_t status, + void *userData); + +/*! @brief Transfer handle structure for FLEXSPI. */ +struct _flexspi_handle +{ + uint32_t state; /*!< Internal state for FLEXSPI transfer */ + uint32_t *data; /*!< Data buffer. */ + size_t dataSize; /*!< Remaining Data size in bytes. */ + size_t transferTotalSize; /*!< Total Data size in bytes. */ + flexspi_transfer_callback_t completionCallback; /*!< Callback for users while transfer finish or error occurred */ + void *userData; /*!< FLEXSPI callback function parameter.*/ +}; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /*_cplusplus. */ + +/*! + * @name Initialization and deinitialization + * @{ + */ +/*! + * @brief Initializes the FLEXSPI module and internal state. + * + * This function enables the clock for FLEXSPI and also configures the FLEXSPI with the + * input configure parameters. Users should call this function before any FLEXSPI operations. + * + * @param base FLEXSPI peripheral base address. + * @param config FLEXSPI configure structure. + */ +void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config); + +/*! + * @brief Gets default settings for FLEXSPI. + * + * @param config FLEXSPI configuration structure. + */ +void FLEXSPI_GetDefaultConfig(flexspi_config_t *config); + +/*! + * @brief Deinitializes the FLEXSPI module. + * + * Clears the FLEXSPI state and FLEXSPI module registers. + * @param base FLEXSPI peripheral base address. + */ +void FLEXSPI_Deinit(FLEXSPI_Type *base); + +/*! + * @brief Configures the connected device parameter. + * + * This function configures the connected device relevant parameters, such as the size, command, and so on. + * The flash configuration value cannot have a default value. The user needs to configure it according to the + * connected device. + * + * @param base FLEXSPI peripheral base address. + * @param config Flash configuration parameters. + * @param port FLEXSPI Operation port. + */ +void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port); + +/*! + * @brief Software reset for the FLEXSPI logic. + * + * This function sets the software reset flags for both AHB and buffer domain and + * resets both AHB buffer and also IP FIFOs. + * + * @param base FLEXSPI peripheral base address. + */ +static inline void FLEXSPI_SoftwareReset(FLEXSPI_Type *base) +{ +//tst by wly + return; + base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK; + while (base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK) + { + } +} + +/*! + * @brief Enables or disables the FLEXSPI module. + * + * @param base FLEXSPI peripheral base address. + * @param enable True means enable FLEXSPI, false means disable. + */ +static inline void FLEXSPI_Enable(FLEXSPI_Type *base, bool enable) +{ + if (enable) + { + base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + } + else + { + base->MCR0 |= FLEXSPI_MCR0_MDIS_MASK; + } +} + +/* @} */ + +/*! + * @name Interrupts + * @{ + */ +/*! + * @brief Enables the FLEXSPI interrupts. + * + * @param base FLEXSPI peripheral base address. + * @param mask FLEXSPI interrupt source. + */ +static inline void FLEXSPI_EnableInterrupts(FLEXSPI_Type *base, uint32_t mask) +{ + base->INTEN |= mask; +} + +/*! + * @brief Disable the FLEXSPI interrupts. + * + * @param base FLEXSPI peripheral base address. + * @param mask FLEXSPI interrupt source. + */ +static inline void FLEXSPI_DisableInterrupts(FLEXSPI_Type *base, uint32_t mask) +{ + base->INTEN &= ~mask; +} + +/* @} */ + +/*! @name DMA control */ +/*@{*/ + +/*! + * @brief Enables or disables FLEXSPI IP Tx FIFO DMA requests. + * + * @param base FLEXSPI peripheral base address. + * @param enable Enable flag for transmit DMA request. Pass true for enable, false for disable. + */ +static inline void FLEXSPI_EnableTxDMA(FLEXSPI_Type *base, bool enable) +{ + if (enable) + { + base->IPTXFCR |= FLEXSPI_IPTXFCR_TXDMAEN_MASK; + } + else + { + base->IPTXFCR &= ~FLEXSPI_IPTXFCR_TXDMAEN_MASK; + } +} + +/*! + * @brief Enables or disables FLEXSPI IP Rx FIFO DMA requests. + * + * @param base FLEXSPI peripheral base address. + * @param enable Enable flag for receive DMA request. Pass true for enable, false for disable. + */ +static inline void FLEXSPI_EnableRxDMA(FLEXSPI_Type *base, bool enable) +{ + if (enable) + { + base->IPRXFCR |= FLEXSPI_IPRXFCR_RXDMAEN_MASK; + } + else + { + base->IPRXFCR &= ~FLEXSPI_IPRXFCR_RXDMAEN_MASK; + } +} + +/*! + * @brief Gets FLEXSPI IP tx fifo address for DMA transfer. + * + * @param base FLEXSPI peripheral base address. + * @retval The tx fifo address. + */ +static inline uint32_t FLEXSPI_GetTxFifoAddress(FLEXSPI_Type *base) +{ + return (uint32_t)&base->TFDR[0]; +} + +/*! + * @brief Gets FLEXSPI IP rx fifo address for DMA transfer. + * + * @param base FLEXSPI peripheral base address. + * @retval The rx fifo address. + */ +static inline uint32_t FLEXSPI_GetRxFifoAddress(FLEXSPI_Type *base) +{ + return (uint32_t)&base->RFDR[0]; +} + +/*@}*/ + +/*! @name FIFO control */ +/*@{*/ + +/*! @brief Clears the FLEXSPI IP FIFO logic. + * + * @param base FLEXSPI peripheral base address. + * @param txFifo Pass true to reset TX FIFO. + * @param rxFifo Pass true to reset RX FIFO. + */ +static inline void FLEXSPI_ResetFifos(FLEXSPI_Type *base, bool txFifo, bool rxFifo) +{ + if (txFifo) + { + base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK; + } + if (rxFifo) + { + base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK; + } +} + +/*! + * @brief Gets the valid data entries in the FLEXSPI FIFOs. + * + * @param base FLEXSPI peripheral base address. + * @param[out] txCount Pointer through which the current number of bytes in the transmit FIFO is returned. + * Pass NULL if this value is not required. + * @param[out] rxCount Pointer through which the current number of bytes in the receive FIFO is returned. + * Pass NULL if this value is not required. + */ +static inline void FLEXSPI_GetFifoCounts(FLEXSPI_Type *base, size_t *txCount, size_t *rxCount) +{ + if (txCount) + { + *txCount = (((base->IPTXFSTS) & FLEXSPI_IPTXFSTS_FILL_MASK) >> FLEXSPI_IPTXFSTS_FILL_SHIFT) * 8U; + } + if (rxCount) + { + *rxCount = (((base->IPRXFSTS) & FLEXSPI_IPRXFSTS_FILL_MASK) >> FLEXSPI_IPRXFSTS_FILL_SHIFT) * 8U; + } +} + +/*@}*/ + +/*! + * @name Status + * @{ + */ +/*! + * @brief Get the FLEXSPI interrupt status flags. + * + * @param base FLEXSPI peripheral base address. + * @retval interrupt status flag, use status flag to AND #flexspi_flags_t could get the related status. + */ +static inline uint32_t FLEXSPI_GetInterruptStatusFlags(FLEXSPI_Type *base) +{ + return base->INTR; +} + +/*! + * @brief Get the FLEXSPI interrupt status flags. + * + * @param base FLEXSPI peripheral base address. + * @param interrupt status flag. + */ +static inline void FLEXSPI_ClearInterruptStatusFlags(FLEXSPI_Type *base, uint32_t mask) +{ + base->INTR |= mask; +} + +#if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_DATA_LEARN)) && (FSL_FEATURE_FLEXSPI_HAS_NO_DATA_LEARN)) +/*! @brief Gets the sampling clock phase selection after Data Learning. + * + * @param base FLEXSPI peripheral base address. + * @param portAPhase Pointer to a uint8_t type variable to receive the selected clock phase on PORTA. + * @param portBPhase Pointer to a uint8_t type variable to receive the selected clock phase on PORTB. + */ +static inline void FLEXSPI_GetDataLearningPhase(FLEXSPI_Type *base, uint8_t *portAPhase, uint8_t *portBPhase) +{ + if (portAPhase) + { + *portAPhase = (base->STS0 & FLEXSPI_STS0_DATALEARNPHASEA_MASK) >> FLEXSPI_STS0_DATALEARNPHASEA_SHIFT; + } + + if (portBPhase) + { + *portBPhase = (base->STS0 & FLEXSPI_STS0_DATALEARNPHASEB_MASK) >> FLEXSPI_STS0_DATALEARNPHASEB_SHIFT; + } +} +#endif + +/*! @brief Gets the trigger source of current command sequence granted by arbitrator. + * + * @param base FLEXSPI peripheral base address. + * @retval trigger source of current command sequence. + */ +static inline flexspi_arb_command_source_t FLEXSPI_GetArbitratorCommandSource(FLEXSPI_Type *base) +{ + return (flexspi_arb_command_source_t)((base->STS0 & FLEXSPI_STS0_ARBCMDSRC_MASK) >> FLEXSPI_STS0_ARBCMDSRC_SHIFT); +} + +/*! @brief Gets the error code when IP command error detected. + * + * @param base FLEXSPI peripheral base address. + * @param index Pointer to a uint8_t type variable to receive the sequence index when error detected. + * @retval error code when IP command error detected. + */ +static inline flexspi_ip_error_code_t FLEXSPI_GetIPCommandErrorCode(FLEXSPI_Type *base, uint8_t *index) +{ + *index = (base->STS1 & FLEXSPI_STS1_IPCMDERRID_MASK) >> FLEXSPI_STS1_IPCMDERRID_SHIFT; + return (flexspi_ip_error_code_t)((base->STS1 & FLEXSPI_STS1_IPCMDERRCODE_MASK) >> FLEXSPI_STS1_IPCMDERRCODE_SHIFT); +} + +/*! @brief Gets the error code when AHB command error detected. + * + * @param base FLEXSPI peripheral base address. + * @param index Pointer to a uint8_t type variable to receive the sequence index when error detected. + * @retval error code when AHB command error detected. + */ +static inline flexspi_ahb_error_code_t FLEXSPI_GetAHBCommandErrorCode(FLEXSPI_Type *base, uint8_t *index) +{ + *index = (base->STS1 & FLEXSPI_STS1_AHBCMDERRID_MASK) >> FLEXSPI_STS1_AHBCMDERRID_SHIFT; + return (flexspi_ahb_error_code_t)((base->STS1 & FLEXSPI_STS1_AHBCMDERRCODE_MASK) >> + FLEXSPI_STS1_AHBCMDERRCODE_SHIFT); +} + +/*! @brief Returns whether the bus is idle. + * + * @param base FLEXSPI peripheral base address. + * @retval true Bus is idle. + * @retval false Bus is busy. + */ +static inline bool FLEXSPI_GetBusIdleStatus(FLEXSPI_Type *base) +{ + return (base->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) && (base->STS0 & FLEXSPI_STS0_SEQIDLE_MASK); +} +/*@}*/ + +/*! + * @name Bus Operations + * @{ + */ + +/*! @brief Update read sample clock source + * + * @param base FLEXSPI peripheral base address. + * @param clockSource clockSource of type #flexspi_read_sample_clock_t + */ +void FLEXSPI_UpdateRxSampleClock(FLEXSPI_Type *base, flexspi_read_sample_clock_t clockSource); + +/*! @brief Enables/disables the FLEXSPI IP command parallel mode. + * + * @param base FLEXSPI peripheral base address. + * @param enable True means enable parallel mode, false means disable parallel mode. + */ +static inline void FLEXSPI_EnableIPParallelMode(FLEXSPI_Type *base, bool enable) +{ + if (enable) + { + base->IPCR1 |= FLEXSPI_IPCR1_IPAREN_MASK; + } + else + { + base->IPCR1 &= ~FLEXSPI_IPCR1_IPAREN_MASK; + } +} + +/*! @brief Enables/disables the FLEXSPI AHB command parallel mode. + * + * @param base FLEXSPI peripheral base address. + * @param enable True means enable parallel mode, false means disable parallel mode. + */ +static inline void FLEXSPI_EnableAHBParallelMode(FLEXSPI_Type *base, bool enable) +{ + if (enable) + { + base->AHBCR |= FLEXSPI_AHBCR_APAREN_MASK; + } + else + { + base->AHBCR &= ~FLEXSPI_AHBCR_APAREN_MASK; + } +} + +/*! @brief Updates the LUT table. + * + * @param base FLEXSPI peripheral base address. + * @param index From which index start to update. It could be any index of the LUT table, which + * also allows user to update command content inside a command. Each command consists of up to + * 8 instructions and occupy 4*32-bit memory. + * @param cmd Command sequence array. + * @param count Number of sequences. + */ +void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count); + +/*! + * @brief Writes data into FIFO. + * + * @param base FLEXSPI peripheral base address + * @param data The data bytes to send + * @param fifoIndex Destination fifo index. + */ +static inline void FLEXSPI_WriteData(FLEXSPI_Type *base, uint32_t data, uint8_t fifoIndex) +{ + base->TFDR[fifoIndex] = data; +} + +/*! + * @brief Receives data from data FIFO. + * + * @param base FLEXSPI peripheral base address + * @param fifoIndex Source fifo index. + * @return The data in the FIFO. + */ +static inline uint32_t FLEXSPI_ReadData(FLEXSPI_Type *base, uint8_t fifoIndex) +{ + return base->RFDR[fifoIndex]; +} + +/*! + * @brief Sends a buffer of data bytes using blocking method. + * @note This function blocks via polling until all bytes have been sent. + * @param base FLEXSPI peripheral base address + * @param buffer The data bytes to send + * @param size The number of data bytes to send + * @retval kStatus_Success write success without error + * @retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout + * @retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequencen error detected + * @retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected + */ +status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size); + +/*! + * @brief Receives a buffer of data bytes using a blocking method. + * @note This function blocks via polling until all bytes have been sent. + * @param base FLEXSPI peripheral base address + * @param buffer The data bytes to send + * @param size The number of data bytes to receive + * @retval kStatus_Success read success without error + * @retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout + * @retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequencen error detected + * @retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected + */ +status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size); + +/*! + * @brief Execute command to transfer a buffer data bytes using a blocking method. + * @param base FLEXSPI peripheral base address + * @param xfer pointer to the transfer structure. + * @retval kStatus_Success command transfer success without error + * @retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout + * @retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequencen error detected + * @retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected + */ +status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer); +/*! @} */ + +/*! + * @name Transactional + * @{ + */ + +/*! + * @brief Initializes the FLEXSPI handle which is used in transactional functions. + * + * @param base FLEXSPI peripheral base address. + * @param handle pointer to flexspi_handle_t structure to store the transfer state. + * @param callback pointer to user callback function. + * @param userData user parameter passed to the callback function. + */ +void FLEXSPI_TransferCreateHandle(FLEXSPI_Type *base, + flexspi_handle_t *handle, + flexspi_transfer_callback_t callback, + void *userData); + +/*! + * @brief Performs a interrupt non-blocking transfer on the FLEXSPI bus. + * + * @note Calling the API returns immediately after transfer initiates. The user needs + * to call FLEXSPI_GetTransferCount to poll the transfer status to check whether + * the transfer is finished. If the return status is not kStatus_FLEXSPI_Busy, the transfer + * is finished. For FLEXSPI_Read, the dataSize should be multiple of rx watermark levle, or + * FLEXSPI could not read data properly. + * + * @param base FLEXSPI peripheral base address. + * @param handle pointer to flexspi_handle_t structure which stores the transfer state. + * @param xfer pointer to flexspi_transfer_t structure. + * @retval kStatus_Success Successfully start the data transmission. + * @retval kStatus_FLEXSPI_Busy Previous transmission still not finished. + */ +status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer); + +/*! + * @brief Gets the master transfer status during a interrupt non-blocking transfer. + * + * @param base FLEXSPI peripheral base address. + * @param handle pointer to flexspi_handle_t structure which stores the transfer state. + * @param count Number of bytes transferred so far by the non-blocking transaction. + * @retval kStatus_InvalidArgument count is Invalid. + * @retval kStatus_Success Successfully return the count. + */ +status_t FLEXSPI_TransferGetCount(FLEXSPI_Type *base, flexspi_handle_t *handle, size_t *count); + +/*! + * @brief Aborts an interrupt non-blocking transfer early. + * + * @note This API can be called at any time when an interrupt non-blocking transfer initiates + * to abort the transfer early. + * + * @param base FLEXSPI peripheral base address. + * @param handle pointer to flexspi_handle_t structure which stores the transfer state + */ +void FLEXSPI_TransferAbort(FLEXSPI_Type *base, flexspi_handle_t *handle); + +/*! + * @brief Master interrupt handler. + * + * @param base FLEXSPI peripheral base address. + * @param handle pointer to flexspi_handle_t structure. + */ +void FLEXSPI_TransferHandleIRQ(FLEXSPI_Type *base, flexspi_handle_t *handle); +/*! @} */ + +#if defined(__cplusplus) +} +#endif /*_cplusplus. */ +/*@}*/ + +#endif /* __FSL_FLEXSPI_H_ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/lpspi_interrupt.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/lpspi_interrupt.c index 7e6458220..cfc7b7ffc 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/lpspi_interrupt.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/lpspi_interrupt.c @@ -56,8 +56,8 @@ #define TRANSFER_SIZE (512U) /*! Transfer dataSize .*/ #define TRANSFER_BAUDRATE (500000U) /*! Transfer baudrate - 500k */ - #define spi_print KPrintf +#define spi_trace() KPrintf("lw: [%s][%d] passed!\n", __func__, __LINE__) /******************************************************************************* * Prototypes @@ -233,45 +233,10 @@ void EXAMPLE_LPSPI_MASTER_IRQHandler(int vector, void *param) DECLARE_HW_IRQ(EXAMPLE_LPSPI_MASTER_IRQN, EXAMPLE_LPSPI_MASTER_IRQHandler, NONE); -/*! - * @brief Main function - */ -int test_spi(void) +void lpspi_config_init(void) { - /*Set clock source for LPSPI*/ - CLOCK_SetMux(kCLOCK_LpspiMux, EXAMPLE_LPSPI_CLOCK_SOURCE_SELECT); - CLOCK_SetDiv(kCLOCK_LpspiDiv, EXAMPLE_LPSPI_CLOCK_SOURCE_DIVIDER); - - spi_print("LPSPI functional interrupt example start.\r\n"); - spi_print("This example use one lpspi instance as master and another as slave on one board.\r\n"); - spi_print("Master uses interrupt way and slave uses interrupt way.\r\n"); - spi_print( - "Note that some LPSPI instances interrupt is in INTMUX ," - "you should set the intmux when you porting this example accordingly \r\n"); - - spi_print("Please make sure you make the correct line connection. Basically, the connection is: \r\n"); - spi_print("LPSPI_master -- LPSPI_slave \r\n"); - spi_print(" CLK -- CLK \r\n"); - spi_print(" PCS -- PCS \r\n"); - spi_print(" SOUT -- SIN \r\n"); - spi_print(" SIN -- SOUT \r\n"); - - uint32_t errorCount; - uint32_t i; lpspi_master_config_t masterConfig; lpspi_slave_config_t slaveConfig; - uint32_t whichPcs; - uint8_t txWatermark; - - /*Set up the transfer data*/ - for (i = 0; i < TRANSFER_SIZE; i++) - { - masterTxData[i] = i % 256; - masterRxData[i] = 0; - - slaveTxData[i] = ~masterTxData[i]; - slaveRxData[i] = 0; - } /*Master config*/ masterConfig.baudRate = TRANSFER_BAUDRATE; @@ -306,6 +271,48 @@ int test_spi(void) LPSPI_SlaveInit(EXAMPLE_LPSPI_SLAVE_BASEADDR, &slaveConfig); +} + +/*! + * @brief Main function + */ +int test_spi(void) +{ + /*Set clock source for LPSPI*/ + CLOCK_SetMux(kCLOCK_LpspiMux, EXAMPLE_LPSPI_CLOCK_SOURCE_SELECT); + CLOCK_SetDiv(kCLOCK_LpspiDiv, EXAMPLE_LPSPI_CLOCK_SOURCE_DIVIDER); + + spi_print("LPSPI functional interrupt example start.\r\n"); + spi_print("This example use one lpspi instance as master and another as slave on one board.\r\n"); + spi_print("Master uses interrupt way and slave uses interrupt way.\r\n"); + spi_print( + "Note that some LPSPI instances interrupt is in INTMUX ," + "you should set the intmux when you porting this example accordingly \r\n"); + + spi_print("Please make sure you make the correct line connection. Basically, the connection is: \r\n"); + spi_print("LPSPI_master -- LPSPI_slave \r\n"); + spi_print(" CLK -- CLK \r\n"); + spi_print(" PCS -- PCS \r\n"); + spi_print(" SOUT -- SIN \r\n"); + spi_print(" SIN -- SOUT \r\n"); + + uint32_t errorCount; + uint32_t i; + uint32_t whichPcs; + uint8_t txWatermark; + + /*Set up the transfer data*/ + for (i = 0; i < TRANSFER_SIZE; i++) + { + masterTxData[i] = i % 256; + masterRxData[i] = 0; + + slaveTxData[i] = ~masterTxData[i]; + slaveRxData[i] = 0; + } + + lpspi_config_init(); + /******************Set up slave first ******************/ isSlaveTransferCompleted = false; slaveTxCount = 0; @@ -352,6 +359,9 @@ int test_spi(void) while (LPSPI_GetTxFifoCount(EXAMPLE_LPSPI_SLAVE_BASEADDR) != 0) { } + + spi_trace(); + /*Fill up the TX data in FIFO */ while (LPSPI_GetTxFifoCount(EXAMPLE_LPSPI_SLAVE_BASEADDR) < g_slaveFifoSize) { @@ -364,6 +374,8 @@ int test_spi(void) break; } } + spi_trace(); + LPSPI_EnableInterrupts(EXAMPLE_LPSPI_SLAVE_BASEADDR, kLPSPI_RxInterruptEnable); /******************Set up master transfer******************/ @@ -412,6 +424,9 @@ int test_spi(void) while (LPSPI_GetTxFifoCount(EXAMPLE_LPSPI_MASTER_BASEADDR) != 0) { } + + spi_trace(); + /*Fill up the TX data in FIFO */ while ((LPSPI_GetTxFifoCount(EXAMPLE_LPSPI_MASTER_BASEADDR) < g_masterFifoSize) && (masterTxCount - masterRxCount < g_masterFifoSize)) @@ -420,11 +435,15 @@ int test_spi(void) LPSPI_WriteData(EXAMPLE_LPSPI_MASTER_BASEADDR, masterTxData[masterTxCount]); ++masterTxCount; + spi_trace(); + if (masterTxCount == TRANSFER_SIZE) { break; } } + spi_trace(); + LPSPI_EnableInterrupts(EXAMPLE_LPSPI_MASTER_BASEADDR, kLPSPI_RxInterruptEnable); /******************Wait for master and slave transfer completed.******************/ @@ -432,6 +451,8 @@ int test_spi(void) { } + spi_trace(); + errorCount = 0; for (i = 0; i < TRANSFER_SIZE; i++) { @@ -462,6 +483,8 @@ int test_spi(void) while (1) { } + spi_trace(); + } SHELL_EXPORT_CMD (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), diff --git a/Ubiquitous/XiUOS/kernel/include/user_api.h b/Ubiquitous/XiUOS/kernel/include/user_api.h index 48e9f8375..6171fbff3 100644 --- a/Ubiquitous/XiUOS/kernel/include/user_api.h +++ b/Ubiquitous/XiUOS/kernel/include/user_api.h @@ -50,11 +50,11 @@ int UserPrintInfo(unsigned long i); struct utask { - char name[NAME_NUM_MAX]; - void *func_entry; - void *func_param; - int32_t stack_size; - uint8_t prio; + char name[NAME_NUM_MAX]; + void *func_entry; + void *func_param; + int32_t stack_size; + uint8_t prio; }; typedef struct utask UtaskType; @@ -109,7 +109,7 @@ typedef int32 EventIdType; EventIdType UserEventCreate(uint8_t flag); void UserEventDelete(EventIdType event); x_err_t UserEventTrigger(EventIdType event, uint32_t set); -x_err_t UserEventProcess(EventIdType event, uint32_t set, uint8_t option, +x_err_t UserEventProcess(EventIdType event, uint32_t set, uint8_t option, int32_t wait_time, uint32_t *Recved); x_err_t UserEventReinit(EventIdType event); #endif @@ -162,7 +162,7 @@ int statfs(const char *path, struct statfs *buf); int Userprintf(const char *fmt, ...); -#define printf Userprintf +#define printf Userprintf #else @@ -172,11 +172,11 @@ int Userprintf(const char *fmt, ...); struct utask { - char name[NAME_NUM_MAX]; - void *func_entry; - void *func_param; - int32_t stack_size; - uint8_t prio; + char name[NAME_NUM_MAX]; + void *func_entry; + void *func_param; + int32_t stack_size; + uint8_t prio; }; typedef struct utask UtaskType; int32_t UserTaskCreate(UtaskType utask); diff --git a/Ubiquitous/XiUOS/resources/include/flash_spi.h b/Ubiquitous/XiUOS/resources/include/flash_spi.h index 3ea08e5ac..f41d40d25 100644 --- a/Ubiquitous/XiUOS/resources/include/flash_spi.h +++ b/Ubiquitous/XiUOS/resources/include/flash_spi.h @@ -13,7 +13,7 @@ /** * @file flash_spi.h * @brief define spi-flash dev function using bus driver framework -* @version 1.0 +* @version 1.0 * @author AIIT XUOS Lab * @date 2021-04-24 */ diff --git a/Ubiquitous/XiUOS/resources/spi/dev_spi.c b/Ubiquitous/XiUOS/resources/spi/dev_spi.c index b2cc0f0ae..8e16da4c5 100644 --- a/Ubiquitous/XiUOS/resources/spi/dev_spi.c +++ b/Ubiquitous/XiUOS/resources/spi/dev_spi.c @@ -13,7 +13,7 @@ /** * @file dev_spi.c * @brief register spi dev function using bus driver framework -* @version 1.0 +* @version 1.0 * @author AIIT XUOS Lab * @date 2021-04-24 */ @@ -36,7 +36,7 @@ static uint32 SpiDeviceOpen(void *dev) SpiDevConfigureCs(dev, 1, 0); return EOK; -} +} static uint32 SpiDeviceClose(void *dev) { @@ -45,7 +45,7 @@ static uint32 SpiDeviceClose(void *dev) SpiDevConfigureCs(dev, 0, 1); return EOK; -} +} static uint32 SpiDeviceWrite(void *dev, struct BusBlockWriteParam *write_param) { @@ -120,7 +120,7 @@ static const struct HalDevDone dev_done = HardwareDevType SpiDeviceFind(const char *dev_name, enum DevType dev_type) { NULL_PARAM_CHECK(dev_name); - + struct HardwareDev *device = NONE; DoubleLinklistType *node = NONE; @@ -142,7 +142,7 @@ int SpiDeviceRegister(struct SpiHardwareDevice *spi_device, void *spi_param, con NULL_PARAM_CHECK(spi_device); NULL_PARAM_CHECK(device_name); - x_err_t ret = EOK; + x_err_t ret = EOK; static x_bool dev_link_flag = RET_FALSE; if (!dev_link_flag) { @@ -164,7 +164,7 @@ int SpiDeviceRegister(struct SpiHardwareDevice *spi_device, void *spi_param, con DoubleLinkListInsertNodeAfter(&spidev_linklist, &(spi_device->haldev.dev_link)); } else { - KPrintf("SpiDeviceRegister device has been register state%u\n", spi_device->haldev.dev_state); + KPrintf("SpiDeviceRegister device has been register state%u\n", spi_device->haldev.dev_state); } return ret; @@ -174,7 +174,7 @@ int SpiDeviceAttachToBus(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; @@ -185,7 +185,7 @@ int SpiDeviceAttachToBus(const char *dev_name, const char *bus_name) KPrintf("SpiDeviceAttachToBus find spi bus error!name %s\n", bus_name); return ERROR; } - + if (TYPE_SPI_BUS == bus->bus_type) { device = SpiDeviceFind(dev_name, TYPE_SPI_DEV); if (NONE == device) {