diff --git a/APP_Framework/Applications/lv_app/Makefile b/APP_Framework/Applications/lv_app/Makefile index 14e833cfa..0bb488e32 100644 --- a/APP_Framework/Applications/lv_app/Makefile +++ b/APP_Framework/Applications/lv_app/Makefile @@ -1,4 +1,4 @@ SRC_FILES := lv_init.c lv_demo.c lv_demo_calendar.c -SRC_FILES += lv_sensor_info.c lv_sensor_update_info.c lv_sensor_info_update_demo.c +# SRC_FILES += lv_sensor_info.c lv_sensor_update_info.c lv_sensor_info_update_demo.c include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Applications/lv_app/lv_demo_calendar.c b/APP_Framework/Applications/lv_app/lv_demo_calendar.c index 49855cd54..0bad80f8e 100644 --- a/APP_Framework/Applications/lv_app/lv_demo_calendar.c +++ b/APP_Framework/Applications/lv_app/lv_demo_calendar.c @@ -39,7 +39,7 @@ static void event_handler(lv_event_t * e) void lv_demo_calendar(void) { lv_obj_t * calendar = lv_calendar_create(lv_scr_act()); - lv_obj_set_size(calendar, 800, 480);//lv_obj_set_size(calendar, 800, 480); + lv_obj_set_size(calendar, 320, 320);//lv_obj_set_size(calendar, 800, 480); lv_obj_align(calendar, LV_ALIGN_CENTER, 0, 0); lv_obj_add_event_cb(calendar, event_handler, LV_EVENT_ALL, NULL); diff --git a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/board.c b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/board.c index 5888283ff..d267826a5 100644 --- a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/board.c +++ b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/board.c @@ -15,23 +15,23 @@ /** * @file board.c -* @brief support aiit-riscv64-board init configure and start-up +* @brief support edu-riscv64 board init configure and start-up * @version 1.0 * @author AIIT XUOS Lab -* @date 2021-04-25 +* @date 2022-10-25 */ /************************************************* File name: board.c -Description: support aiit-riscv64-board init configure and driver/task/... init +Description: support edu-riscv64 board init configure and driver/task/... init Others: https://canaan-creative.com/developer History: -1. Date: 2021-04-25 +1. Date: 2022-10-25 Author: AIIT XUOS Lab Modification: -1. support aiit-riscv64-board InitBoardHardware -2. support aiit-riscv64-board Kd233Start -3. support aiit-riscv64-board shell cmd, include reboot, shutdown +1. support edu-riscv64 board InitBoardHardware +2. support edu-riscv64 board Kd233Start +3. support edu-riscv64 board shell cmd, include reboot, shutdown *************************************************/ #include diff --git a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/gpio/drv_io_config.c b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/gpio/drv_io_config.c index c7501895c..e954517c9 100755 --- a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/gpio/drv_io_config.c +++ b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/gpio/drv_io_config.c @@ -10,21 +10,21 @@ /** * @file drv_io_config.c -* @brief support aiit-riscv64-board io configure +* @brief support edu-riscv64 board io configure * @version 1.0 * @author AIIT XUOS Lab -* @date 2021-04-25 +* @date 2022-10-25 */ /************************************************* File name: drv_io_config.c -Description: support aiit-riscv64-board io configure +Description: support edu-riscv64 board io configure Others: take RT-Thread v4.0.2/bsp/k210/driver/drv_io_config.c for references https://github.com/RT-Thread/rt-thread/tree/v4.0.2 History: -1. Date: 2021-04-25 +1. Date: 2022-10-25 Author: AIIT XUOS Lab -Modification: support aiit-riscv64-board io configure +Modification: support edu-riscv64 board io configure *************************************************/ #include diff --git a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/connect_lcd.h b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/connect_lcd.h index 1fe935c07..46f145c0e 100644 --- a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/connect_lcd.h +++ b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/connect_lcd.h @@ -15,21 +15,21 @@ /** * @file connect_lcd.h -* @brief define aiit-riscv64-board lcd function +* @brief define edu-riscv64 board lcd function * @version 1.0 * @author AIIT XUOS Lab -* @date 2021-04-25 +* @date 2022-10-25 */ /************************************************* File name: connect_lcd.h -Description: define aiit-riscv64-board lcd function +Description: define edu-riscv64 board lcd function Others: https://canaan-creative.com/developer History: -1. Date: 2021-04-25 +1. Date: 2022-10-25 Author: AIIT XUOS Lab Modification: -1. add aiit-riscv64-board lcd function +1. add edu-riscv64 board lcd function *************************************************/ #ifndef CONNECT_LCD_H diff --git a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/connect_spi.h b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/connect_spi.h index cd746d016..89c56fcd5 100644 --- a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/connect_spi.h +++ b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/connect_spi.h @@ -12,10 +12,10 @@ /** * @file connect_spi.h -* @brief define aiit-riscv64-board spi function and struct +* @brief define edu-riscv64 board spi function and struct * @version 1.0 * @author AIIT XUOS Lab -* @date 2021-04-25 +* @date 2022-10-25 */ #ifndef CONNECT_SPI_H diff --git a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/graphic.h b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/graphic.h index a57a5eb06..286c616ce 100644 --- a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/graphic.h +++ b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/graphic.h @@ -9,21 +9,21 @@ /** * @file graphic.h -* @brief define aiit-riscv64-board lcd operation +* @brief define edu-riscv64 board lcd operation * @version 1.0 * @author AIIT XUOS Lab -* @date 2021-04-25 +* @date 2022-10-25 */ /************************************************* File name: graphic.h -Description: define aiit-riscv64-board lcd operation +Description: define edu-riscv64 board lcd operation Others: take RT-Thread v4.0.2/include/rtdef.h for references https://github.com/RT-Thread/rt-thread/tree/v4.0.2 History: -1. Date: 2021-04-25 +1. Date: 2022-10-25 Author: AIIT XUOS Lab -Modification: add aiit-riscv64-board lcd configure and operation function +Modification: add edu-riscv64 board lcd configure and operation function *************************************************/ #ifndef GRAPHIC_H diff --git a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/hardware_spi.h b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/hardware_spi.h index 4d3fd3599..8e37ad21b 100644 --- a/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/hardware_spi.h +++ b/Ubiquitous/XiZi_IIoT/board/aiit-riscv64-board/third_party_driver/include/hardware_spi.h @@ -19,7 +19,7 @@ * https://canaan-creative.com/developer * @version 1.0 * @author AIIT XUOS Lab -* @date 2021-04-25 +* @date 2022-10-25 */ #ifndef __HARDWARE_SPI_H__ diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c index a788091b3..6dd32085d 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c @@ -58,6 +58,8 @@ extern int IoConfigInit(void); extern int HwI2cInit(void); extern int HwTouchInit(void); extern int HwCh376Init(void); +extern int HwLcdInit(void); +extern int HwSpiInit(void); #ifdef FS_CH376 #include @@ -170,7 +172,12 @@ struct InitSequenceDesc _board_init[] = #ifdef BSP_USING_I2C { "hw_i2c", HwI2cInit }, #endif - +#ifdef BSP_USING_SPI + { "hw_spi", HwSpiInit }, +#endif +#ifdef BSP_USING_LCD + { "hw_lcd", HwLcdInit }, +#endif #ifdef BSP_USING_USB { "hw_usb", HwCh376Init}, #endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig index bc5e43c0b..4b4572352 100755 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig @@ -1,63 +1,80 @@ menuconfig BSP_USING_CH376 -bool "Using CH376 device" -default n -select FS_VFS -select FS_CH376 -if BSP_USING_CH376 -source "$BSP_DIR/third_party_driver/ch376/Kconfig" -endif + bool "Using CH376 device" + default n + select FS_VFS + select FS_CH376 + if BSP_USING_CH376 + source "$BSP_DIR/third_party_driver/ch376/Kconfig" + endif +menuconfig BSP_USING_SPI + bool "Using SPI device" + default n + select RESOURCES_SPI + select BSP_USING_DMA + if BSP_USING_SPI + source "$BSP_DIR/third_party_driver/spi/Kconfig" + endif + +menuconfig BSP_USING_LCD + bool "Using LCD device" + default n + select BSP_USING_SPI + select RESOURCES_LCD + if BSP_USING_LCD + source "$BSP_DIR/third_party_driver/lcd/Kconfig" + endif menuconfig BSP_USING_DMA -bool "Using DMA device" -default y -if BSP_USING_DMA -source "$BSP_DIR/third_party_driver/dma/Kconfig" -endif + bool "Using DMA device" + default y + if BSP_USING_DMA + source "$BSP_DIR/third_party_driver/dma/Kconfig" + endif menuconfig BSP_USING_GPIO -bool "Using GPIO device" -default y -select RESOURCES_PIN -if BSP_USING_GPIO -source "$BSP_DIR/third_party_driver/gpio/Kconfig" -endif + bool "Using GPIO device" + default y + select RESOURCES_PIN + if BSP_USING_GPIO + source "$BSP_DIR/third_party_driver/gpio/Kconfig" + endif menuconfig BSP_USING_I2C -bool "Using I2C device" -default n -select RESOURCES_I2C -if BSP_USING_I2C -source "$BSP_DIR/third_party_driver/i2c/Kconfig" -endif + bool "Using I2C device" + default n + select RESOURCES_I2C + if BSP_USING_I2C + source "$BSP_DIR/third_party_driver/i2c/Kconfig" + endif menuconfig BSP_USING_TOUCH -bool "Using TOUCH device" -default n -select RESOURCES_TOUCH -select BSP_USING_I2C -if BSP_USING_TOUCH -source "$BSP_DIR/third_party_driver/touch/Kconfig" -endif + bool "Using TOUCH device" + default n + select BSP_USING_I2C + select RESOURCES_TOUCH + if BSP_USING_TOUCH + source "$BSP_DIR/third_party_driver/touch/Kconfig" + endif menuconfig BSP_USING_PLIC -bool "Using PLIC device" -default y -if BSP_USING_PLIC -source "$BSP_DIR/third_party_driver/plic/Kconfig" -endif + bool "Using PLIC device" + default y + if BSP_USING_PLIC + source "$BSP_DIR/third_party_driver/plic/Kconfig" + endif menuconfig BSP_USING_SYSCLOCK -bool "Using SYSCLOCK device" -default y -if BSP_USING_SYSCLOCK -source "$BSP_DIR/third_party_driver/sys_clock/Kconfig" -endif + bool "Using SYSCLOCK device" + default y + if BSP_USING_SYSCLOCK + source "$BSP_DIR/third_party_driver/sys_clock/Kconfig" + endif menuconfig BSP_USING_UART -bool "Using UART device" -default y -select RESOURCES_SERIAL -if BSP_USING_UART -source "$BSP_DIR/third_party_driver/uart/Kconfig" -endif + bool "Using UART device" + default y + select RESOURCES_SERIAL + if BSP_USING_UART + source "$BSP_DIR/third_party_driver/uart/Kconfig" + endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile index e4bacecfc..dd458fd0c 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile @@ -12,6 +12,10 @@ ifeq ($(CONFIG_BSP_USING_GPIO),y) SRC_DIR += gpio endif +ifeq ($(CONFIG_BSP_USING_SPI),y) + SRC_DIR += spi +endif + ifeq ($(CONFIG_BSP_USING_I2C),y) SRC_DIR += i2c endif @@ -32,4 +36,8 @@ ifeq ($(CONFIG_BSP_USING_UART),y) SRC_DIR += uart endif +ifeq ($(CONFIG_BSP_USING_LCD),y) + SRC_DIR += lcd +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c index cebb2f360..2211e5832 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c @@ -46,7 +46,8 @@ static struct io_config #ifdef BSP_USING_LCD IOCONFIG(BSP_LCD_CS_PIN, FUNC_SPI0_SS0), IOCONFIG(BSP_LCD_WR_PIN, FUNC_SPI0_SCLK), - IOCONFIG(BSP_LCD_DC_PIN, HS_GPIO(LCD_DC_PIN)), + IOCONFIG(BSP_LCD_DC_PIN, HS_GPIO(FPIOA_LCD_DC)), + IOCONFIG(BSP_LCD_RST_PIN, HS_GPIO(FPIOA_LCD_RST)), #endif #ifdef BSP_USING_SPI1 diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_lcd.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_lcd.h new file mode 100644 index 000000000..1fe935c07 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_lcd.h @@ -0,0 +1,52 @@ +/* Copyright 2018 Canaan Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** +* @file connect_lcd.h +* @brief define aiit-riscv64-board lcd function +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +/************************************************* +File name: connect_lcd.h +Description: define aiit-riscv64-board lcd function +Others: https://canaan-creative.com/developer +History: +1. Date: 2021-04-25 +Author: AIIT XUOS Lab +Modification: +1. add aiit-riscv64-board lcd function +*************************************************/ + +#ifndef CONNECT_LCD_H +#define CONNECT_LCD_H + +#include +#include "hardware_spi.h" +#include + +#ifdef BSP_USING_TOUCH +#include "connect_touch.h" +#endif + +void DrvLcdClear(uint16_t color); +void LcdDrawLine(uint16 x1, uint16 y1, uint16 x2, uint16 y2,uint16 color); +void LcdDrawRectangle(uint16 x1, uint16 y1, uint16 x2, uint16 y2,uint16 color); +void LcdDrawCircle(uint16 x0,uint16 y0,uint8 r,uint16 color); + +int HwLcdInit(void); +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_spi.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_spi.h new file mode 100644 index 000000000..cd746d016 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_spi.h @@ -0,0 +1,36 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_spi.h +* @brief define aiit-riscv64-board spi function and struct +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +#ifndef CONNECT_SPI_H +#define CONNECT_SPI_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int HwSpiInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/graphic.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/graphic.h new file mode 100644 index 000000000..a57a5eb06 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/graphic.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +/** +* @file graphic.h +* @brief define aiit-riscv64-board lcd operation +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +/************************************************* +File name: graphic.h +Description: define aiit-riscv64-board lcd operation +Others: take RT-Thread v4.0.2/include/rtdef.h for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2021-04-25 +Author: AIIT XUOS Lab +Modification: add aiit-riscv64-board lcd configure and operation function +*************************************************/ + +#ifndef GRAPHIC_H +#define GRAPIHC_H + +#include + +#define GRAPHIC_CTRL_RECT_UPDATE 0 +#define GRAPHIC_CTRL_POWERON 1 +#define GRAPHIC_CTRL_POWEROFF 2 +#define GRAPHIC_CTRL_GET_INFO 3 +#define GRAPHIC_CTRL_SET_MODE 4 +#define GRAPHIC_CTRL_GET_EXT 5 + +enum +{ + PIXEL_FORMAT_MONO = 0, + PIXEL_FORMAT_GRAY4, + PIXEL_FORMAT_GRAY16, + PIXEL_FORMAT_RGB332, + PIXEL_FORMAT_RGB444, + PIXEL_FORMAT_RGB565 , + PIXEL_FORMAT_RGB565P, + PIXEL_FORMAT_BGR565 = PIXEL_FORMAT_RGB565P, + PIXEL_FORMAT_RGB666, + PIXEL_FORMAT_RGB888, + PIXEL_FORMAT_ARGB888, + PIXEL_FORMAT_ABGR888, + PIXEL_FORMAT_ARGB565, + PIXEL_FORMAT_ALPHA, + PIXEL_FORMAT_COLOR, +}; + +struct DeviceLcdInfo +{ + uint8 pixel_format; + uint8 bits_per_pixel; + uint16 reserved; + + uint16 width; + uint16 height; + + uint8 *framebuffer; +}; + +struct DeviceRectInfo +{ + uint16 x; + uint16 y; + uint16 width; + uint16 height; +}; + +struct DeviceGraphicDone +{ + void (*set_pixel) (const char *pixel, int x, int y); + void (*get_pixel) (char *pixel, int x, int y); + + void (*draw_hline) (const char *pixel, int x1, int x2, int y); + void (*draw_vline) (const char *pixel, int x, int y1, int y2); + + void (*blit_line) (const char *pixel, int x, int y, x_size_t size); +}; + +#define GraphixDone(device) ((struct DeviceGraphicDone *)(device->UserData)) + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/hardware_spi.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/hardware_spi.h new file mode 100644 index 000000000..4d3fd3599 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/hardware_spi.h @@ -0,0 +1,494 @@ +/* Copyright 2018 Canaan Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** +* @file hardware_spi.h +* @brief add from Canaan k210 SDK +* https://canaan-creative.com/developer +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +#ifndef __HARDWARE_SPI_H__ +#define __HARDWARE_SPI_H__ + +#include "dmac.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* clang-format off */ +typedef struct _spi +{ + /* SPI Control Register 0 (0x00)*/ + volatile uint32_t ctrlr0; + /* SPI Control Register 1 (0x04)*/ + volatile uint32_t ctrlr1; + /* SPI Enable Register (0x08)*/ + volatile uint32_t ssienr; + /* SPI Microwire Control Register (0x0c)*/ + volatile uint32_t mwcr; + /* SPI Slave Enable Register (0x10)*/ + volatile uint32_t ser; + /* SPI Baud Rate Select (0x14)*/ + volatile uint32_t baudr; + /* SPI Transmit FIFO Threshold Level (0x18)*/ + volatile uint32_t txftlr; + /* SPI Receive FIFO Threshold Level (0x1c)*/ + volatile uint32_t rxftlr; + /* SPI Transmit FIFO Level Register (0x20)*/ + volatile uint32_t txflr; + /* SPI Receive FIFO Level Register (0x24)*/ + volatile uint32_t rxflr; + /* SPI Status Register (0x28)*/ + volatile uint32_t sr; + /* SPI Interrupt Mask Register (0x2c)*/ + volatile uint32_t imr; + /* SPI Interrupt Status Register (0x30)*/ + volatile uint32_t isr; + /* SPI Raw Interrupt Status Register (0x34)*/ + volatile uint32_t risr; + /* SPI Transmit FIFO Overflow Interrupt Clear Register (0x38)*/ + volatile uint32_t txoicr; + /* SPI Receive FIFO Overflow Interrupt Clear Register (0x3c)*/ + volatile uint32_t rxoicr; + /* SPI Receive FIFO Underflow Interrupt Clear Register (0x40)*/ + volatile uint32_t rxuicr; + /* SPI Multi-Master Interrupt Clear Register (0x44)*/ + volatile uint32_t msticr; + /* SPI Interrupt Clear Register (0x48)*/ + volatile uint32_t icr; + /* SPI DMA Control Register (0x4c)*/ + volatile uint32_t dmacr; + /* SPI DMA Transmit Data Level (0x50)*/ + volatile uint32_t dmatdlr; + /* SPI DMA Receive Data Level (0x54)*/ + volatile uint32_t dmardlr; + /* SPI Identification Register (0x58)*/ + volatile uint32_t idr; + /* SPI DWC_ssi component version (0x5c)*/ + volatile uint32_t ssic_version_id; + /* SPI Data Register 0-36 (0x60 -- 0xec)*/ + volatile uint32_t dr[36]; + /* SPI RX Sample Delay Register (0xf0)*/ + volatile uint32_t rx_sample_delay; + /* SPI SPI Control Register (0xf4)*/ + volatile uint32_t spi_ctrlr0; + /* reserved (0xf8)*/ + volatile uint32_t resv; + /* SPI XIP Mode bits (0xfc)*/ + volatile uint32_t xip_mode_bits; + /* SPI XIP INCR transfer opcode (0x100)*/ + volatile uint32_t xip_incr_inst; + /* SPI XIP WRAP transfer opcode (0x104)*/ + volatile uint32_t xip_wrap_inst; + /* SPI XIP Control Register (0x108)*/ + volatile uint32_t xip_ctrl; + /* SPI XIP Slave Enable Register (0x10c)*/ + volatile uint32_t xip_ser; + /* SPI XIP Receive FIFO Overflow Interrupt Clear Register (0x110)*/ + volatile uint32_t xrxoicr; + /* SPI XIP time out register for continuous transfers (0x114)*/ + volatile uint32_t xip_cnt_time_out; + volatile uint32_t endian; +} __attribute__((packed, aligned(4))) spi_t; +/* clang-format on */ + +typedef enum _spi_device_num +{ + SPI_DEVICE_0, + SPI_DEVICE_1, + SPI_DEVICE_2, + SPI_DEVICE_3, + SPI_DEVICE_MAX, +} spi_device_num_t; + +typedef enum _spi_work_mode +{ + SPI_WORK_MODE_0, + SPI_WORK_MODE_1, + SPI_WORK_MODE_2, + SPI_WORK_MODE_3, +} spi_work_mode_t; + +typedef enum _spi_frame_format +{ + SPI_FF_STANDARD, + SPI_FF_DUAL, + SPI_FF_QUAD, + SPI_FF_OCTAL +} spi_frame_format_t; + +typedef enum _spi_instruction_address_trans_mode +{ + SPI_AITM_STANDARD, + SPI_AITM_ADDR_STANDARD, + SPI_AITM_AS_FRAME_FORMAT +} spi_instruction_address_trans_mode_t; + +typedef enum _spi_transfer_mode +{ + SPI_TMOD_TRANS_RECV, + SPI_TMOD_TRANS, + SPI_TMOD_RECV, + SPI_TMOD_EEROM +} spi_transfer_mode_t; + + +typedef enum _spi_transfer_width +{ + SPI_TRANS_CHAR = 0x1, + SPI_TRANS_SHORT = 0x2, + SPI_TRANS_INT = 0x4, +} spi_transfer_width_t; + +typedef enum _spi_chip_select +{ + SPI_CHIP_SELECT_0, + SPI_CHIP_SELECT_1, + SPI_CHIP_SELECT_2, + SPI_CHIP_SELECT_3, + SPI_CHIP_SELECT_MAX, +} spi_chip_select_t; + +typedef enum +{ + WRITE_CONFIG, + READ_CONFIG, + WRITE_DATA_BYTE, + READ_DATA_BYTE, + WRITE_DATA_BLOCK, + READ_DATA_BLOCK, +} spi_slave_command_e; + +typedef struct +{ + uint8_t cmd; + uint8_t err; + uint32_t addr; + uint32_t len; +} spi_slave_command_t; + +typedef enum +{ + IDLE, + COMMAND, + TRANSFER, +} spi_slave_status_e; + +typedef int (*spi_slave_receive_callback_t)(void *ctx); + +typedef struct _spi_slave_instance +{ + uint8_t int_pin; + uint8_t ready_pin; + dmac_channel_number_t dmac_channel; + uint8_t dfs; + uint8_t slv_oe; + uint8_t work_mode; + size_t data_bit_length; + volatile spi_slave_status_e status; + volatile spi_slave_command_t command; + volatile uint8_t *config_ptr; + uint32_t config_len; + spi_slave_receive_callback_t callback; +} spi_slave_instance_t; + +typedef struct _spi_data_t +{ + dmac_channel_number_t tx_channel; + dmac_channel_number_t rx_channel; + uint32_t *tx_buf; + size_t tx_len; + uint32_t *rx_buf; + size_t rx_len; + spi_transfer_mode_t TransferMode; + bool fill_mode; +} spi_data_t; + +extern volatile spi_t *const spi[4]; + +/** + * @brief Set spi configuration + * + * @param[in] spi_num Spi bus number + * @param[in] mode Spi mode + * @param[in] frame_format Spi frame format + * @param[in] data_bit_length Spi data bit length + * @param[in] endian 0:little-endian 1:big-endian + * + * @return Void + */ +void spi_init(spi_device_num_t spi_num, spi_work_mode_t work_mode, spi_frame_format_t frame_format, + size_t data_bit_length, uint32_t endian); + +/** + * @brief Set multiline configuration + * + * @param[in] spi_num Spi bus number + * @param[in] instruction_length Instruction length + * @param[in] address_length Address length + * @param[in] wait_cycles Wait cycles + * @param[in] instruction_address_trans_mode Spi transfer mode + * + */ +void spi_init_non_standard(spi_device_num_t spi_num, uint32_t instruction_length, uint32_t address_length, + uint32_t wait_cycles, spi_instruction_address_trans_mode_t instruction_address_trans_mode); + +/** + * @brief Spi send data + * + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] CmdBuff Spi command buffer point + * @param[in] CmdLen Spi command length + * @param[in] tx_buff Spi transmit buffer point + * @param[in] tx_len Spi transmit buffer length + * + * @return Result + * - 0 Success + * - Other Fail + */ +void spi_send_data_standard(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *CmdBuff, + size_t CmdLen, const uint8_t *tx_buff, size_t tx_len); + +/** + * @brief Spi receive data + * + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] CmdBuff Spi command buffer point + * @param[in] CmdLen Spi command length + * @param[in] rx_buff Spi receive buffer point + * @param[in] rx_len Spi receive buffer length + * + * @return Result + * - 0 Success + * - Other Fail + */ +void spi_receive_data_standard(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *CmdBuff, + size_t CmdLen, uint8_t *rx_buff, size_t rx_len); + +/** + * @brief Spi special receive data + * + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] CmdBuff Spi command buffer point + * @param[in] CmdLen Spi command length + * @param[in] rx_buff Spi receive buffer point + * @param[in] rx_len Spi receive buffer length + * + * @return Result + * - 0 Success + * - Other Fail + */ +void spi_receive_data_multiple(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *CmdBuff, + size_t CmdLen, uint8_t *rx_buff, size_t rx_len); + +/** + * @brief Spi special send data + * + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] CmdBuff Spi command buffer point + * @param[in] CmdLen Spi command length + * @param[in] tx_buff Spi transmit buffer point + * @param[in] tx_len Spi transmit buffer length + * + * @return Result + * - 0 Success + * - Other Fail + */ +void spi_send_data_multiple(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *CmdBuff, + size_t CmdLen, const uint8_t *tx_buff, size_t tx_len); + +/** + * @brief Spi send data by dma + * + * @param[in] channel_num Dmac channel number + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] CmdBuff Spi command buffer point + * @param[in] CmdLen Spi command length + * @param[in] tx_buff Spi transmit buffer point + * @param[in] tx_len Spi transmit buffer length + * + * @return Result + * - 0 Success + * - Other Fail + */ +void spi_send_data_standard_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num, + spi_chip_select_t chip_select, + const uint8_t *CmdBuff, size_t CmdLen, const uint8_t *tx_buff, size_t tx_len); + +/** + * @brief Spi receive data by dma + * + * @param[in] w_channel_num Dmac write channel number + * @param[in] r_channel_num Dmac read channel number + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] CmdBuff Spi command buffer point + * @param[in] CmdLen Spi command length + * @param[in] rx_buff Spi receive buffer point + * @param[in] rx_len Spi receive buffer length + * + * @return Result + * - 0 Success + * - Other Fail + */ +void spi_receive_data_standard_dma(dmac_channel_number_t dma_send_channel_num, + dmac_channel_number_t dma_receive_channel_num, + spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *CmdBuff, + size_t CmdLen, uint8_t *rx_buff, size_t rx_len); + +/** + * @brief Spi special send data by dma + * + * @param[in] channel_num Dmac channel number + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] CmdBuff Spi command buffer point + * @param[in] CmdLen Spi command length + * @param[in] tx_buff Spi transmit buffer point + * @param[in] tx_len Spi transmit buffer length + * + * @return Result + * - 0 Success + * - Other Fail + */ +void spi_send_data_multiple_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num, + spi_chip_select_t chip_select, + const uint32_t *CmdBuff, size_t CmdLen, const uint8_t *tx_buff, size_t tx_len); + +/** + * @brief Spi special receive data by dma + * + * @param[in] dma_send_channel_num Dmac write channel number + * @param[in] dma_receive_channel_num Dmac read channel number + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] CmdBuff Spi command buffer point + * @param[in] CmdLen Spi command length + * @param[in] rx_buff Spi receive buffer point + * @param[in] rx_len Spi receive buffer length + * + * @return Result + * - 0 Success + * - Other Fail + */ +void spi_receive_data_multiple_dma(dmac_channel_number_t dma_send_channel_num, + dmac_channel_number_t dma_receive_channel_num, + spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *CmdBuff, + size_t CmdLen, uint8_t *rx_buff, size_t rx_len); + +/** + * @brief Spi fill dma + * + * @param[in] channel_num Dmac channel number + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] tx_buff Spi command buffer point + * @param[in] tx_len Spi command length + * + * @return Result + * - 0 Success + * - Other Fail + */ +void spi_fill_data_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num, spi_chip_select_t chip_select, + const uint32_t *tx_buff, size_t tx_len); + +/** + * @brief Spi normal send by dma + * + * @param[in] channel_num Dmac channel number + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] tx_buff Spi transmit buffer point + * @param[in] tx_len Spi transmit buffer length + * @param[in] stw Spi transfer width + * + * @return Result + * - 0 Success + * - Other Fail + */ +void spi_send_data_normal_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num, + spi_chip_select_t chip_select, + const void *tx_buff, size_t tx_len, spi_transfer_width_t spi_transfer_width); + +/** + * @brief Spi normal send by dma + * + * @param[in] spi_num Spi bus number + * @param[in] spi_clk Spi clock rate + * + * @return The real spi clock rate + */ +uint32_t spi_set_clk_rate(spi_device_num_t spi_num, uint32_t spi_clk); + +/** + * @brief Spi full duplex send receive data by dma + * + * @param[in] dma_send_channel_num Dmac write channel number + * @param[in] dma_receive_channel_num Dmac read channel number + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] tx_buf Spi send buffer + * @param[in] tx_len Spi send buffer length + * @param[in] rx_buf Spi receive buffer + * @param[in] rx_len Spi receive buffer length + * + */ +void spi_dup_send_receive_data_dma(dmac_channel_number_t dma_send_channel_num, + dmac_channel_number_t dma_receive_channel_num, + spi_device_num_t spi_num, spi_chip_select_t chip_select, + const uint8_t *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len); + +/** + * @brief Set spi slave configuration + * + * @param[in] int_pin SPI master starts sending data interrupt. + * @param[in] ready_pin SPI slave ready. + * @param[in] dmac_channel Dmac channel number for block. + * @param[in] data_bit_length Spi data bit length + * @param[in] data SPI slave device data buffer. + * @param[in] len The length of SPI slave device data buffer. + * @param[in] callback Callback of spi slave. + * + * @return Void + */ +void spi_slave_config(uint8_t int_pin, uint8_t ready_pin, dmac_channel_number_t dmac_channel, size_t data_bit_length, uint8_t *data, uint32_t len, spi_slave_receive_callback_t callback); + +/** + * @brief Spi handle transfer data operations + * + * @param[in] spi_num Spi bus number + * @param[in] chip_select Spi chip select + * @param[in] data Spi transfer data information + * @param[in] cb Spi DMA callback + * + */ +void spi_handle_data_dma(spi_device_num_t spi_num, spi_chip_select_t chip_select, spi_data_t data, plic_interrupt_t *cb); + +#ifdef __cplusplus +} +#endif + +#endif /* __HARDWARE_SPI_H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/lcd/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/lcd/Kconfig new file mode 100644 index 000000000..ed8ca6bad --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/lcd/Kconfig @@ -0,0 +1,36 @@ + +if BSP_USING_LCD + config LCD_BUS_NAME + string "lcd bus name" + default "lcd" + config LCD_DRV_NAME + string "lcd bus driver name" + default "lcd_drv" + config LCD_DEVICE_NAME + string "lcd bus device name" + default "lcd_dev" + config BSP_LCD_CS_PIN + int "CS pin number of 8080 interface" + default 37 + config BSP_LCD_WR_PIN + int "WR pin number of 8080 interface" + default 38 + config BSP_LCD_DC_PIN + int "DC pin number of 8080 interface" + default 39 + config BSP_LCD_RST_PIN + int "RST pin number of 8080 interface" + default 36 + config FPIOA_LCD_DC + int "DC FPIOA number of 8080 interface" + default 9 + config FPIOA_LCD_RST + int "RST FPIOA number of 8080 interface" + default 10 + config BSP_LCD_X_MAX + int "LCD Height" + default 320 + config BSP_LCD_Y_MAX + int "LCD Width" + default 320 +endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/lcd/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/lcd/Makefile new file mode 100644 index 000000000..05bd917f0 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/lcd/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := connect_lcd.c + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/lcd/connect_lcd.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/lcd/connect_lcd.c new file mode 100644 index 000000000..8595bca05 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/lcd/connect_lcd.c @@ -0,0 +1,704 @@ +/* Copyright 2018 Canaan Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** +* @file connect_lcd.c +* @brief support aiit-riscv64-board lcd function and register to bus framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +/************************************************* +File name: connect_lcd.c +Description: support aiit-riscv64-board lcd configure and lcd bus register function +Others: https://canaan-creative.com/developer +History: +1. Date: 2021-04-25 +Author: AIIT XUOS Lab +Modification: +1. support aiit-riscv64-board lcd configure, write and read +2. support aiit-riscv64-board lcd bus device and driver register +*************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NO_OPERATION 0x00 +#define SOFTWARE_RESET 0x01 +#define READ_ID 0x04 +#define READ_STATUS 0x09 +#define READ_POWER_MODE 0x0A +#define READ_MADCTL 0x0B +#define READ_PIXEL_FORMAT 0x0C +#define READ_IMAGE_FORMAT 0x0D +#define READ_SIGNAL_MODE 0x0E +#define READ_SELT_DIAG_RESULT 0x0F +#define SLEEP_ON 0x10 +#define SLEEP_OFF 0x11 +#define PARTIAL_DISPALY_ON 0x12 +#define NORMAL_DISPALY_ON 0x13 +#define INVERSION_DISPALY_OFF 0x20 +#define INVERSION_DISPALY_ON 0x21 +#define GAMMA_SET 0x26 +#define DISPALY_OFF 0x28 +#define DISPALY_ON 0x29 +#define HORIZONTAL_ADDRESS_SET 0x2A +#define VERTICAL_ADDRESS_SET 0x2B +#define MEMORY_WRITE 0x2C +#define COLOR_SET 0x2D +#define MEMORY_READ 0x2E +#define PARTIAL_AREA 0x30 +#define VERTICAL_SCROL_DEFINE 0x33 +#define TEAR_EFFECT_LINE_OFF 0x34 +#define TEAR_EFFECT_LINE_ON 0x35 +#define MEMORY_ACCESS_CTL 0x36 +#define VERTICAL_SCROL_S_ADD 0x37 +#define IDLE_MODE_OFF 0x38 +#define IDLE_MODE_ON 0x39 +#define PIXEL_FORMAT_SET 0x3A +#define WRITE_MEMORY_CONTINUE 0x3C +#define READ_MEMORY_CONTINUE 0x3E +#define SET_TEAR_SCANLINE 0x44 +#define GET_SCANLINE 0x45 +#define WRITE_BRIGHTNESS 0x51 +#define READ_BRIGHTNESS 0x52 +#define WRITE_CTRL_DISPALY 0x53 +#define READ_CTRL_DISPALY 0x54 +#define WRITE_BRIGHTNESS_CTL 0x55 +#define READ_BRIGHTNESS_CTL 0x56 +#define WRITE_MIN_BRIGHTNESS 0x5E +#define READ_MIN_BRIGHTNESS 0x5F +#define READ_ID1 0xDA +#define READ_ID2 0xDB +#define READ_ID3 0xDC +#define RGB_IF_SIGNAL_CTL 0xB0 +#define NORMAL_FRAME_CTL 0xB1 +#define IDLE_FRAME_CTL 0xB2 +#define PARTIAL_FRAME_CTL 0xB3 +#define INVERSION_CTL 0xB4 +#define BLANK_PORCH_CTL 0xB5 +#define DISPALY_FUNCTION_CTL 0xB6 +#define ENTRY_MODE_SET 0xB7 +#define BACKLIGHT_CTL1 0xB8 +#define BACKLIGHT_CTL2 0xB9 +#define BACKLIGHT_CTL3 0xBA +#define BACKLIGHT_CTL4 0xBB +#define BACKLIGHT_CTL5 0xBC +#define BACKLIGHT_CTL7 0xBE +#define BACKLIGHT_CTL8 0xBF +#define POWER_CTL1 0xC0 +#define POWER_CTL2 0xC1 +#define VCOM_CTL1 0xC5 +#define VCOM_CTL2 0xC7 +#define NV_MEMORY_WRITE 0xD0 +#define NV_MEMORY_PROTECT_KEY 0xD1 +#define NV_MEMORY_STATUS_READ 0xD2 +#define READ_ID4 0xD3 +#define POSITIVE_GAMMA_CORRECT 0xE0 +#define NEGATIVE_GAMMA_CORRECT 0xE1 +#define DIGITAL_GAMMA_CTL1 0xE2 +#define DIGITAL_GAMMA_CTL2 0xE3 +#define INTERFACE_CTL 0xF6 + +typedef enum _lcd_dir +{ + DIR_XY_RLUD = 0x00, + DIR_YX_RLUD = 0x20, + DIR_XY_LRUD = 0x40, + DIR_YX_LRUD = 0x60, + DIR_XY_RLDU = 0x80, + DIR_YX_RLDU = 0xA0, + DIR_XY_LRDU = 0xC0, + DIR_YX_LRDU = 0xE0, + DIR_XY_MASK = 0x20, + DIR_MASK = 0xE0, +} lcd_dir_t; + +#define LCD_SPI_CHANNEL SPI_DEVICE_0 +#define LCD_SPI_CHIP_SELECT SPI_CHIP_SELECT_0 + +typedef struct Lcd8080Device +{ + struct LcdBus lcd_bus; + struct DeviceLcdInfo lcd_info; + int spi_channel; + int cs; + int dc_pin; + int dma_channel; +} * Lcd8080DeviceType; + +Lcd8080DeviceType aiit_lcd ; + +static void DrvLcdCmd(uint8 cmd) +{ + gpiohs_set_pin(aiit_lcd->dc_pin, GPIO_PV_LOW); + spi_init(aiit_lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0); + spi_init_non_standard(aiit_lcd->spi_channel/*spi num*/, 8 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/, + SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/); + spi_send_data_normal_dma(aiit_lcd->dma_channel, aiit_lcd->spi_channel, aiit_lcd->cs, &cmd, 1, SPI_TRANS_CHAR); +} + +static void DrvLcdDataByte(uint8 *data_buf, uint32 length) +{ + gpiohs_set_pin(aiit_lcd->dc_pin, GPIO_PV_HIGH); + spi_init(aiit_lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0); + spi_init_non_standard(aiit_lcd->spi_channel, 8 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/, + SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/); + spi_send_data_normal_dma(aiit_lcd->dma_channel, aiit_lcd->spi_channel, aiit_lcd->cs, data_buf, length, SPI_TRANS_CHAR); +} + +static void DrvLcdDataHalfWord(uint16 *data_buf, uint32 length) +{ + gpiohs_set_pin(aiit_lcd->dc_pin, GPIO_PV_HIGH); + spi_init(aiit_lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 16, 0); + spi_init_non_standard(aiit_lcd->spi_channel, 16 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/, + SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/); + spi_send_data_normal_dma(aiit_lcd->dma_channel, aiit_lcd->spi_channel, aiit_lcd->cs, data_buf, length, SPI_TRANS_SHORT); +} + +static void DrvLcdDataWord(uint32 *data_buf, uint32 length) +{ + gpiohs_set_pin(aiit_lcd->dc_pin, GPIO_PV_HIGH); + /*spi num Polarity and phase mode Multi-line mode Data bit width little endian */ + spi_init(aiit_lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0); + +/* spi num instrction length address length wait cycles spi address trans mode*/ + spi_init_non_standard(aiit_lcd->spi_channel, 0 , 32, 0 ,SPI_AITM_AS_FRAME_FORMAT ); + + /*dma channel spi num chip_selete tx_buff tx_len spi_trans_data_width */ + spi_send_data_normal_dma(aiit_lcd->dma_channel, aiit_lcd->spi_channel, aiit_lcd->cs, data_buf, length, SPI_TRANS_INT); +} + +static void DrvLcdHwInit(Lcd8080DeviceType lcd) +{ + gpiohs_set_drive_mode(lcd->dc_pin, GPIO_DM_OUTPUT); + gpiohs_set_pin(lcd->dc_pin, GPIO_PV_HIGH); + spi_init(lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0); + spi_set_clk_rate(lcd->spi_channel, 25000000); +} + +static void DrvLcdSetDirection(lcd_dir_t dir) +{ +#if !BOARD_LICHEEDAN + dir |= 0x08; +#endif + if (dir & DIR_XY_MASK) { + aiit_lcd->lcd_info.width = BSP_LCD_Y_MAX; + aiit_lcd->lcd_info.height = BSP_LCD_X_MAX; + } else { + aiit_lcd->lcd_info.width = BSP_LCD_X_MAX; + aiit_lcd->lcd_info.height = BSP_LCD_Y_MAX; + } + + DrvLcdCmd(MEMORY_ACCESS_CTL); + DrvLcdDataByte((uint8 *)&dir, 1); +} + +static void DrvLcdSetArea(uint16 x1, uint16 y1, uint16 x2, uint16 y2) +{ + uint8 data[4] = {0}; + + data[0] = (uint8)(x1 >> 8); + data[1] = (uint8)(x1); + data[2] = (uint8)(x2 >> 8); + data[3] = (uint8)(x2); + DrvLcdCmd(HORIZONTAL_ADDRESS_SET); + DrvLcdDataByte(data, 4); + + data[0] = (uint8)(y1 >> 8); + data[1] = (uint8)(y1); + data[2] = (uint8)(y2 >> 8); + data[3] = (uint8)(y2); + DrvLcdCmd(VERTICAL_ADDRESS_SET); + DrvLcdDataByte(data, 4); + + DrvLcdCmd(MEMORY_WRITE); +} + +static void DrvLcdSetPixel(uint16_t x, uint16_t y, uint16_t color) +{ + DrvLcdSetArea(x, y, x, y); + DrvLcdDataHalfWord(&color, 1); +} + +static void DrvLcdSetPixelDot(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,void* color) +{ + uint32 size = 0; + size = (x2- x1 + 1)*(y2 - y1 + 1); + DrvLcdSetArea(x1, y1, x2, y2); + DrvLcdDataHalfWord(color, size); +} + +void LcdShowChar(uint16 x,uint16 y,uint8 num,uint8 size,uint16 color,uint16 back_color) +{ + uint8 temp,t1,t; + uint16 y0=y; + uint8 csize=(size/8+((size%8)?1:0))*(size/2); + num=num-' '; + for (t = 0;t < csize;t ++) { + if (size==12) + temp=asc2_1206[num][t]; //1206 + else if (size==16) + temp=asc2_1608[num][t]; //1608 + else if (size==24) + temp=asc2_2412[num][t]; //2412 + else if (size==32) + temp=asc2_3216[num][t]; //3216 + else + return; + + for(t1 = 0;t1 < 8;t1 ++) { + if (temp&0x80) + DrvLcdSetPixel(x,y,color); + else + DrvLcdSetPixel(x,y,back_color); + + temp<<=1; + y++; + if(y>=aiit_lcd->lcd_info.height) + return; + if ((y-y0) == size) { + y=y0; + x++; + if(x>=aiit_lcd->lcd_info.width) + return; + break; + } + } + } +} + +void LcdShowString(uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint8 size,uint8 *p,uint16_t color,uint16_t back_color) +{ + uint16_t x0 = x; + width += x; + height += y; + while ((*p<='~')&&(*p>=' ')) { + if (x>=width) { + x=x0; + y+=size; + } + if(y>=height) + break; + LcdShowChar(x,y,*p,size,color,back_color); + x += size/2; + p++; + } +} + +/* +* clear lcd by color +* para color +* return none +*/ +void DrvLcdClear(uint16 color) +{ + uint32 data = ((uint32)color << 16) | (uint32)color; + + DrvLcdSetArea(0, 0, aiit_lcd->lcd_info.width - 1, aiit_lcd->lcd_info.height - 1); + gpiohs_set_pin(aiit_lcd->dc_pin, GPIO_PV_HIGH); + spi_init(aiit_lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0); + spi_init_non_standard(aiit_lcd->spi_channel, + 0 /*instrction length*/, + 32 /*address length */, + 0 /*wait cycles */, + SPI_AITM_AS_FRAME_FORMAT ); + spi_fill_data_dma(aiit_lcd->dma_channel, aiit_lcd->spi_channel, aiit_lcd->cs, (const uint32_t *)&data, aiit_lcd->lcd_info.width * aiit_lcd->lcd_info.height / 2); +} + +static void DrvLcdRectUpdate(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height) +{ + static uint16 * rect_buffer = NONE; + if (!rect_buffer) { + rect_buffer = x_malloc(aiit_lcd->lcd_info.height * aiit_lcd->lcd_info.width * (aiit_lcd->lcd_info.bits_per_pixel / 8)); + if (!rect_buffer) { + return; + } + } + if (x1 == 0 && y1 == 0 && width == aiit_lcd->lcd_info.width && height == aiit_lcd->lcd_info.height) { + DrvLcdSetArea(x1, y1, x1 + width - 1, y1 + height - 1); + DrvLcdDataWord((uint32 *)aiit_lcd->lcd_info.framebuffer, width * height / (aiit_lcd->lcd_info.bits_per_pixel / 8)); + } else { + DrvLcdSetArea(x1, y1, x1 + width - 1, y1 + height - 1); + DrvLcdDataWord((uint32 *)rect_buffer, width * height / 2); + } +} + +x_err_t DrvLcdInit(Lcd8080DeviceType dev) +{ + x_err_t ret = EOK; + aiit_lcd = (Lcd8080DeviceType)dev; + uint8 data = 0; + + if (!aiit_lcd) + { + return -ERROR; + } + DrvLcdHwInit(aiit_lcd); + /* reset LCD */ + DrvLcdCmd(SOFTWARE_RESET); + MdelayKTask(100); + + /* Enter normal status */ + DrvLcdCmd(SLEEP_OFF); + MdelayKTask(100); + + /* pixel format rgb565 */ + DrvLcdCmd(PIXEL_FORMAT_SET); + data = 0x55; + DrvLcdDataByte(&data, 1); + + /* set direction */ + DrvLcdSetDirection(DIR_YX_RLUD); + + aiit_lcd->lcd_info.framebuffer = x_malloc(aiit_lcd->lcd_info.height * aiit_lcd->lcd_info.width * (aiit_lcd->lcd_info.bits_per_pixel / 8)); + CHECK(aiit_lcd->lcd_info.framebuffer); + + /*display on*/ + DrvLcdCmd(DISPALY_ON); + + return ret; +} + +static uint32 drv_lcd_control(void* drv, struct BusConfigureInfo *configure_info) +{ + x_err_t ret = EOK; + struct LcdDriver *lcddrv = (struct LcdDriver *)drv; + + struct DeviceRectInfo* rect_info; + NULL_PARAM_CHECK(drv); + + switch (configure_info->configure_cmd) + { + case GRAPHIC_CTRL_RECT_UPDATE: + rect_info = (struct DeviceRectInfo*)configure_info->private_data; + if(!rect_info) + { + SYS_ERR("GRAPHIC_CTRL_RECT_UPDATE error args"); + return -ERROR; + } + DrvLcdRectUpdate(rect_info->x, rect_info->y, rect_info->width, rect_info->height); + break; + + case GRAPHIC_CTRL_POWERON: + /* Todo: power on */ + ret = -ENONESYS; + break; + + case GRAPHIC_CTRL_POWEROFF: + /* Todo: power off */ + ret = -ENONESYS; + break; + + case GRAPHIC_CTRL_GET_INFO: + *(struct DeviceLcdInfo *)configure_info->private_data = aiit_lcd->lcd_info; + break; + + case GRAPHIC_CTRL_SET_MODE: + ret = -ENONESYS; + break; + case GRAPHIC_CTRL_GET_EXT: + ret = -ENONESYS; + break; + default: + SYS_ERR("drv_lcd_control cmd: %d", configure_info->configure_cmd); + break; + } + + return ret; +} + +void ClearHandwriting (void) +{ + //clear the lcd + DrvLcdClear(WHITE); + + LcdShowString(10, 10, 100, 24, 24, "RST ", RED, WHITE); +} + +#ifdef CONFIG_TOUCH +void HandTest(unsigned short *x_pos, unsigned short *y_pos) +{ + float x1,y1; + TpReadXy(x_pos,y_pos); //address + float a = 12.1875,b = 16.25; + x1 = 320 - (*x_pos)/a +10; + y1 = (* y_pos)/b; + + if ((*x_pos> 500)&&(*y_pos<500)) { + ClearHandwriting(); + } else { + DrvLcdSetPixel(x1, y1, RED); + DrvLcdSetPixel(x1+1, y1, RED); + DrvLcdSetPixel(x1-1, y1, RED); + + DrvLcdSetPixel(x1, y1+1, RED); + DrvLcdSetPixel(x1, y1-1, RED); + + DrvLcdSetPixel(x1+1, y1+1, RED); + DrvLcdSetPixel(x1-1, y1-1, RED); + + DrvLcdSetPixel(x1+1, y1-1, RED); + DrvLcdSetPixel(x1-1, y1+1, RED); + } +} +#endif + +static uint32 LcdWrite(void *dev, struct BusBlockWriteParam *write_param) +{ + if (write_param == NONE) { + return -ERROR; + } + LcdWriteParam * show = (LcdWriteParam *)write_param->buffer; + // KPrintf("DEBUG TYPE %d X1:%d X2:%d Y1:%d Y2:%d\n",show->type,show->pixel_info.x_startpos, show->pixel_info.x_endpos,show->pixel_info.y_startpos, show->pixel_info.y_endpos); + if(0 == show->type) //output string + { + LcdShowString(show->string_info.x_pos,show->string_info.y_pos,show->string_info.width,show->string_info.height,show->string_info.font_size,show->string_info.addr,show->string_info.font_color,show->string_info.back_color); + return EOK; + } + else if(1 == show->type) //output dot + { + // DrvLcdSetPixel(show->pixel_info.x_pos, show->pixel_info.y_pos, show->pixel_info.pixel_color); + DrvLcdSetPixelDot(show->pixel_info.x_startpos,show->pixel_info.y_startpos, show->pixel_info.x_endpos, show->pixel_info.y_endpos,show->pixel_info.pixel_color); + return EOK; + } + else + { + return -ERROR; + } +} + +uint32 DrvLcdClearDone(void * dev, struct BusConfigureInfo *configure_info) +{ + uint16 color = 0; + color =(uint16)(configure_info->configure_cmd |0x0000ffff ); + DrvLcdClear( color); + return 0; +} + +const struct LcdDevDone lcd_dev_done = +{ + .open = NONE, + .close = NONE, + .write = LcdWrite, + .read = NONE +}; + +static int BoardLcdBusInit(struct LcdBus * lcd_bus, struct LcdDriver * lcd_driver,const char *bus_name, const char *drv_name) +{ + x_err_t ret = EOK; + + /*Init the lcd bus */ + ret = LcdBusInit( lcd_bus, bus_name); + if (EOK != ret) { + KPrintf("Board_lcd_init LcdBusInit error %d\n", ret); + return -ERROR; + } + + /*Init the lcd driver*/ + ret = LcdDriverInit( lcd_driver, drv_name); + if (EOK != ret) { + KPrintf("Board_LCD_init LcdDriverInit error %d\n", ret); + return -ERROR; + } + + /*Attach the lcd driver to the lcd bus*/ + ret = LcdDriverAttachToBus(drv_name, bus_name); + if (EOK != ret) { + KPrintf("Board_LCD_init LcdDriverAttachToBus error %d\n", ret); + return -ERROR; + } + + return ret; +} + +/*Attach the lcd device to the lcd bus*/ +static int BoardLcdDevBend(struct LcdHardwareDevice *lcd_device, void *param, const char *bus_name, const char *dev_name) +{ + x_err_t ret = EOK; + + ret = LcdDeviceRegister(lcd_device, NONE, dev_name); + if (EOK != ret) { + KPrintf("Board_LCD_init LcdDeviceInit device %s error %d\n", dev_name, ret); + return -ERROR; + } + + ret = LcdDeviceAttachToBus(dev_name, bus_name); + if (EOK != ret) { + KPrintf("Board_LCD_init LcdDeviceAttachToBus device %s error %d\n", dev_name, ret); + return -ERROR; + } + + return ret; +} + +int HwLcdInit(void) +{ + x_err_t ret = EOK; + + static struct LcdDriver lcd_driver; + memset(&lcd_driver, 0, sizeof(struct LcdDriver)); + + Lcd8080DeviceType lcd_dev = (Lcd8080DeviceType )x_malloc(sizeof( struct Lcd8080Device)); + if (!lcd_dev) + { + return -ERROR; + } + + memset(lcd_dev, 0, sizeof(struct Lcd8080Device)); + + // FpioaSetFunction(BSP_LCD_DC_PIN, FUNC_GPIOHS9); //DC order/data + // FpioaSetFunction(BSP_LCD_BL_PIN, FUNC_GPIOHS10); //BL + // FpioaSetFunction(BSP_LCD_CS_PIN, FUNC_SPI0_SS0); //chip select + // FpioaSetFunction(BSP_LCD_WR_PIN, FUNC_SPI0_SCLK); //clk + + lcd_dev->cs = SPI_CHIP_SELECT_0; + lcd_dev->dc_pin = FPIOA_LCD_DC; + lcd_dev->dma_channel = DMAC_CHANNEL0; + lcd_dev->spi_channel = SPI_DEVICE_0; + lcd_dev->lcd_info.bits_per_pixel = 16; + lcd_dev->lcd_info.pixel_format = PIXEL_FORMAT_BGR565; + + sysctl_set_power_mode(SYSCTL_POWER_BANK6, SYSCTL_POWER_V18); + sysctl_set_power_mode(SYSCTL_POWER_BANK7, SYSCTL_POWER_V18); + + sysctl_set_spi0_dvp_data(1); //open the lcd interface with spi0 + + lcd_driver.configure = &drv_lcd_control; + + ret = BoardLcdBusInit(&lcd_dev->lcd_bus, &lcd_driver, LCD_BUS_NAME, LCD_DRV_NAME); //init lcd bus + if (EOK != ret) + { + KPrintf("Board_lcd_Init error ret %u\n", ret); + x_free(lcd_dev); + return -ERROR; + } + + static struct LcdHardwareDevice lcd_device; + memset(&lcd_device, 0, sizeof(struct LcdHardwareDevice)); + + lcd_device.dev_done = &(lcd_dev_done); + + ret = BoardLcdDevBend(&lcd_device, NONE, LCD_BUS_NAME, LCD_DEVICE_NAME); //init lcd device + if (EOK != ret) + { + KPrintf("BoardLcdDevBend error ret %u\n", ret); + x_free(lcd_dev); + return -ERROR; + } + + gpiohs_set_drive_mode(FPIOA_LCD_RST, GPIO_DM_OUTPUT); + gpiohs_set_pin(FPIOA_LCD_RST, GPIO_PV_LOW); + MdelayKTask(100); + gpiohs_set_pin(FPIOA_LCD_RST, GPIO_PV_HIGH); + MdelayKTask(100); + + KPrintf("LCD driver inited ...\r\n"); + + DrvLcdInit(lcd_dev); + + return ret; +} + +//x1,y1:start +//x2,y2:end +void LcdDrawLine(uint16 x1, uint16 y1, uint16 x2, uint16 y2,uint16 color) +{ + uint16 t; + int xerr = 0, yerr = 0, delta_x, delta_y, distance; + int incx,incy,uRow,uCol; + delta_x = x2 - x1; + delta_y = y2 - y1; + uRow = x1; + uCol = y1; + + if(delta_x>0) + incx = 1; + else if(delta_x==0) + incx = 0; + else { + incx = -1; + delta_x = -delta_x; + } + + if(delta_y>0) + incy = 1; + else if(delta_y==0) + incy = 0; + else { + incy= -1; + delta_y = -delta_y; + } + + if (delta_x>delta_y) + distance=delta_x; + else + distance=delta_y; + + for(t = 0;t <= distance+1;t ++ ) { + DrvLcdSetPixel(uRow,uCol,color); + xerr += delta_x ; + yerr += delta_y ; + if (xerr>distance) { + xerr-=distance; + uRow+=incx; + } + if (yerr>distance) { + yerr-=distance; + uCol+=incy; + } + } +} + +void LcdDrawRectangle(uint16 x1, uint16 y1, uint16 x2, uint16 y2,uint16 color) +{ + LcdDrawLine(x1,y1,x2,y1,color); + LcdDrawLine(x1,y1,x1,y2,color); + LcdDrawLine(x1,y2,x2,y2,color); + LcdDrawLine(x2,y1,x2,y2,color); +} + +void LcdDrawCircle(uint16 x0,uint16 y0,uint8 r,uint16 color) +{ + int a,b; + int di; + a = 0; + b = r; + di = 3-(r<<1); + while(a <= b) { + DrvLcdSetPixel(x0+a,y0-b,color); //5 + DrvLcdSetPixel(x0+b,y0-a,color); //0 + DrvLcdSetPixel(x0+b,y0+a,color); //4 + DrvLcdSetPixel(x0+a,y0+b,color); //6 + DrvLcdSetPixel(x0-a,y0+b,color); //1 + DrvLcdSetPixel(x0-b,y0+a,color); + DrvLcdSetPixel(x0-a,y0-b,color); //2 + DrvLcdSetPixel(x0-b,y0-a,color); //7 + a++; + //Bresenham + if(di<0) + di += 4*a+6; + else { + di += 10+4*(a-b); + b--; + } + } +} diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig new file mode 100644 index 000000000..de61c1ef5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig @@ -0,0 +1,125 @@ +config BSP_USING_SPI1 +bool "Using spi1 " +default y + + +if BSP_USING_SPI1 + config SPI_BUS_NAME_1 + string "spi bus 1 name" + default "spi1" + config SPI_1_DRV_NAME + string "spi bus 1 driver name" + default "spi1_drv" + config BSP_SPI1_CLK_PIN + int "spi1 clk pin number" + default 6 + config BSP_SPI1_D0_PIN + int "spi1 d0 pin number" + default 8 + config BSP_SPI1_D1_PIN + int "spi1 d1 pin number" + default 7 + menuconfig BSP_SPI1_USING_SS0 + bool "SPI1 Enable SS0" + default y + if BSP_SPI1_USING_SS0 + config SPI_1_DEVICE_NAME_0 + string "spi bus 1 device 0 name" + default "spi1_dev0" + config BSP_SPI1_SS0_PIN + int "spi1 ss0 pin number" + default 9 + menuconfig RESOURCES_SPI_LORA + bool "Using spi lora function" + default n + if RESOURCES_SPI_LORA + config SX12XX_DEVICE_NAME + string "SX1278 lora device name" + default "spi1_lora" + config SX12XX_DEVICE_RST_PIN + int + default 10 + + config SX12XX_DEVICE_DO0_PIN + int + default 10 + + config SX12XX_DEVICE_DO1_PIN + int + default 10 + + config SX12XX_DEVICE_DO2_PIN + int + default 10 + + config SX12XX_DEVICE_DO3_PIN + int + default 10 + + config SX12XX_DEVICE_DO4_PIN + int + default 10 + + config SX12XX_DEVICE_DO5_PIN + int + default 10 + endif + endif + menuconfig BSP_SPI1_USING_SS1 + bool "SPI1 Enable SS1" + default y + if BSP_SPI1_USING_SS1 + config SPI_1_DEVICE_NAME_1 + string "spi bus 1 device 1 name" + default "spi1_dev1" + config BSP_SPI1_SS1_PIN + int "spi1 ss1 pin number" + default 33 + endif + menuconfig BSP_SPI1_USING_SS2 + bool "SPI1 Enable SS2" + default n + if BSP_SPI1_USING_SS2 + config SPI_1_DEVICE_NAME_2 + string "spi bus 1 device 2 name" + default "spi1_dev2" + config BSP_SPI1_SS2_PIN + int "spi1 ss2 pin number" + default 26 + endif + menuconfig BSP_SPI1_USING_SS3 + bool "SPI1 Enable SS3" + default n + if BSP_SPI1_USING_SS3 + config SPI_1_DEVICE_NAME_3 + string "spi bus 1 device 3 name" + default "spi1_dev3" + config BSP_SPI1_SS3_PIN + int "spi1 ss3 pin number" + default 27 + endif +endif + +config BSP_USING_TP +bool "Using LCD touch " +default n + +if BSP_USING_TP + config BSP_TP_SCK_PIN + int "TP SCK pin number" + default 42 + config BSP_TP_NCS_PIN + int "TP NCS pin number" + default 43 + config BSP_TP_MISO_PIN + int "TP MISO pin number" + default 44 + config BSP_TP_IRQ_PIN + int "TP IRQ pin number" + default 45 + config BSP_TP_MOSI_PIN + int "TP MOSI pin number" + default 46 + +endif + diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Makefile new file mode 100644 index 000000000..f64c853be --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Makefile @@ -0,0 +1,9 @@ +SRC_FILES := connect_spi.c hardware_spi.c + + +ifeq ($(CONFIG_RESOURCES_SPI_LORA),y) + SRC_DIR += third_party_spi_lora + SRC_FILES += connect_lora_spi.c +endif + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/connect_spi.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/connect_spi.c new file mode 100644 index 000000000..c2a7ee5fb --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/connect_spi.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2020 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-03-18 ZYH first version + */ + +/** +* @file connect_spi.c +* @brief support aiit-riscv64-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 aiit-riscv64-board spi configure and spi bus register function +Others: take RT-Thread v4.0.2/bsp/k210/driver/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 aiit-riscv64-board spi configure, write and read +2. support aiit-riscv64-board spi bus device and driver register +*************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BSP_SPI1_USING_SS0 +#define SPI_DEVICE_SLAVE_ID_0 0 +#endif + +#ifdef BSP_SPI1_USING_SS1 +#define SPI_DEVICE_SLAVE_ID_1 1 +#endif + +#ifdef BSP_SPI1_USING_SS2 +#define SPI_DEVICE_SLAVE_ID_2 2 +#endif + +#ifdef BSP_SPI1_USING_SS3 +#define SPI_DEVICE_SLAVE_ID_3 3 +#endif + +static volatile spi_t *const spi_instance[4] = +{ + (volatile spi_t *)SPI0_BASE_ADDR, + (volatile spi_t *)SPI1_BASE_ADDR, + (volatile spi_t *)SPI_SLAVE_BASE_ADDR, + (volatile spi_t *)SPI3_BASE_ADDR +}; + +void __spi_set_tmod(uint8_t spi_num, uint32_t tmod) +{ + CHECK(spi_num < SPI_DEVICE_MAX); + volatile spi_t *spi_handle = spi[spi_num]; + uint8_t tmod_offset = 0; + switch(spi_num) + { + case 0: + case 1: + case 2: + tmod_offset = 8; + break; + case 3: + default: + tmod_offset = 10; + break; + } + set_bit(&spi_handle->ctrlr0, 3 << tmod_offset, tmod << tmod_offset); +} + +/*Init the spi sdk intetface */ +static uint32 SpiSdkInit(struct SpiDriver *spi_drv) +{ + NULL_PARAM_CHECK(spi_drv); + uint8 cs_gpio_pin, cs_select_id; + uint32 max_frequency; + + SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data); + + cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin; + cs_select_id = dev_param->spi_slave_param->spi_cs_select_id; + + gpiohs_set_drive_mode(cs_select_id, GPIO_DM_OUTPUT);//Set the cs pin as output + gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH);//set the cs gpio high + + spi_init(dev_param->spi_dma_param->spi_master_id, + dev_param->spi_master_param->spi_work_mode & SPI_MODE_3, + dev_param->spi_master_param->spi_frame_format, + dev_param->spi_master_param->spi_data_bit_width, + dev_param->spi_master_param->spi_data_endian); + + max_frequency = (dev_param->spi_master_param->spi_maxfrequency < SPI_MAX_CLOCK) ? dev_param->spi_master_param->spi_maxfrequency : SPI_MAX_CLOCK; + + uint32 real_freq = spi_set_clk_rate(dev_param->spi_dma_param->spi_master_id, max_frequency); + + return EOK; +} + +static uint32 SpiSdkCfg(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; + dev_param->spi_master_param->spi_frame_format = SPI_FF_STANDARD; + + return EOK; +} + +/*Configure the spi device param, make sure struct (configure_info->private_data) = (SpiMasterParam)*/ +static uint32 SpiDrvConfigure(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 = SpiSdkInit(spi_drv); + break; + case OPE_CFG: + spi_param = (struct SpiMasterParam *)configure_info->private_data; + ret = SpiSdkCfg(spi_drv, spi_param); + break; + default: + break; + } + + return ret; +} + +static uint32 SpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg) +{ + SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data); + + uint8 device_id = dev_param->spi_slave_param->spi_slave_id; + uint8 device_master_id = dev_param->spi_dma_param->spi_master_id; + uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin; + + while (NONE != spi_datacfg) + { + uint32_t * tx_buff = NONE; + int i; + x_ubase dummy = 0xFFFFFFFFU; + + __spi_set_tmod(device_master_id, SPI_TMOD_TRANS_RECV); + + if (spi_datacfg->spi_chip_select) { + gpiohs_set_pin(cs_gpio_pin, GPIO_PV_LOW); + } + + if (spi_datacfg->length) { + spi_instance[device_master_id]->dmacr = 0x3; + spi_instance[device_master_id]->ssienr = 0x01; + + sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_txchannel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + device_master_id * 2); + sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_rxchannel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + device_master_id* 2); + + dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), &dummy, DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length); + + if (!spi_datacfg->tx_buff) { + dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_txchannel, &dummy, (void *)(&spi_instance[device_master_id]->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, spi_datacfg->length); + } else { + tx_buff = x_malloc(spi_datacfg->length * 4); + if (!tx_buff) { + goto transfer_done; + } + for (i = 0; i < spi_datacfg->length; i++) { + tx_buff[i] = ((uint8_t *)spi_datacfg->tx_buff)[i]; + } + dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_txchannel, tx_buff, (void *)(&spi_instance[device_master_id]->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, spi_datacfg->length); + } + + spi_instance[device_master_id]->ser = 1U << dev_param->spi_slave_param->spi_cs_select_id; + dmac_wait_done(dev_param->spi_dma_param->spi_dmac_txchannel); + dmac_wait_done(dev_param->spi_dma_param->spi_dmac_rxchannel); + spi_instance[device_master_id]->ser = 0x00; + spi_instance[device_master_id]->ssienr = 0x00; + + transfer_done: + if (tx_buff) { + x_free(tx_buff); + } + } + + if (spi_datacfg->spi_cs_release) { + gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH); + } + + spi_datacfg = spi_datacfg->next; + } + + return EOK; +} + +static uint32 SpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg) +{ + SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data); + + uint32 spi_read_length = 0;; + uint8 device_id = dev_param->spi_slave_param->spi_slave_id; + uint8 device_master_id = dev_param->spi_dma_param->spi_master_id; + uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin; + + while (NONE != spi_datacfg) + { + uint32_t * rx_buff = NONE; + int i; + x_ubase dummy = 0xFFFFFFFFU; + + __spi_set_tmod(device_master_id, SPI_TMOD_TRANS_RECV); + + if (spi_datacfg->spi_chip_select) { + gpiohs_set_pin(cs_gpio_pin, GPIO_PV_LOW); + } + if (spi_datacfg->length) { + spi_instance[device_master_id]->dmacr = 0x3; + spi_instance[device_master_id]->ssienr = 0x01; + + sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_txchannel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + device_master_id * 2); + sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_rxchannel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + device_master_id* 2); + + dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_txchannel, &dummy, (void *)(&spi_instance[device_master_id]->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, spi_datacfg->length); + + if (!spi_datacfg->rx_buff) { + dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), &dummy, DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length); + } else { + rx_buff = x_calloc(spi_datacfg->length * 4, 1); + if(!rx_buff) + { + goto transfer_done; + } + + dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length); + } + + spi_instance[device_master_id]->ser = 1U << dev_param->spi_slave_param->spi_cs_select_id; + dmac_wait_done(dev_param->spi_dma_param->spi_dmac_txchannel); + dmac_wait_done(dev_param->spi_dma_param->spi_dmac_rxchannel); + spi_instance[device_master_id]->ser = 0x00; + spi_instance[device_master_id]->ssienr = 0x00; + + if (spi_datacfg->rx_buff) { + for (i = 0; i < spi_datacfg->length; i++) { + ((uint8_t *)spi_datacfg->rx_buff)[i] = (uint8_t)rx_buff[i]; + } + } + + transfer_done: + if (rx_buff) { + x_free(rx_buff); + } + } + + if (spi_datacfg->spi_cs_release) { + gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH); + } + + spi_read_length += spi_datacfg->length; + spi_datacfg = spi_datacfg->next; + } + + return spi_read_length; +} + +/*manage the spi device operations*/ +static const struct SpiDevDone spi_dev_done = +{ + .dev_open = NONE, + .dev_close = NONE, + .dev_write = SpiWriteData, + .dev_read = SpiReadData, +}; + +static int BoardSpiBusInit(struct SpiBus *spi_bus, struct SpiDriver *spi_driver) +{ + x_err_t ret = EOK; + + /*Init the spi bus */ + ret = SpiBusInit(spi_bus, SPI_BUS_NAME_1); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiBusInit error %d\n", ret); + return ERROR; + } + + /*Init the spi driver*/ + ret = SpiDriverInit(spi_driver, SPI_1_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(SPI_1_DRV_NAME, SPI_BUS_NAME_1); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDriverAttachToBus error %d\n", ret); + return ERROR; + } + + return ret; +} + +/*Attach the spi device to the spi bus*/ +static int BoardSpiDevBend(struct SpiDmaParam *spi_initparam) +{ + x_err_t ret = EOK; + +#ifdef BSP_SPI1_USING_SS0 + static struct SpiHardwareDevice spi_device0; + memset(&spi_device0, 0, sizeof(struct SpiHardwareDevice)); + + static struct SpiSlaveParam spi_slaveparam0; + memset(&spi_slaveparam0, 0, sizeof(struct SpiSlaveParam)); + + spi_slaveparam0.spi_slave_id = SPI_DEVICE_SLAVE_ID_0; + spi_slaveparam0.spi_cs_gpio_pin = SPI1_CS0_PIN; + spi_slaveparam0.spi_cs_select_id = SPI_CHIP_SELECT_0; + + spi_device0.spi_param.spi_dma_param = spi_initparam; + spi_device0.spi_param.spi_slave_param = &spi_slaveparam0; + + spi_device0.spi_dev_done = &(spi_dev_done); + + ret = SpiDeviceRegister(&spi_device0, (void *)(&spi_device0.spi_param), SPI_1_DEVICE_NAME_0); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_0, ret); + return ERROR; + } + + ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_0, SPI_BUS_NAME_1); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_0, ret); + return ERROR; + } +#endif + +#ifdef BSP_SPI1_USING_SS1 + static struct SpiHardwareDevice spi_device1; + memset(&spi_device1, 0, sizeof(struct SpiHardwareDevice)); + + static struct SpiSlaveParam spi_slaveparam1; + memset(&spi_slaveparam1, 0, sizeof(struct SpiSlaveParam)); + + spi_slaveparam1.spi_slave_id = SPI_DEVICE_SLAVE_ID_1; + spi_slaveparam1.spi_cs_gpio_pin = SPI1_CS1_PIN; + spi_slaveparam1.spi_cs_select_id = SPI_CHIP_SELECT_1; + + spi_device1.spi_param.spi_dma_param = spi_initparam; + spi_device1.spi_param.spi_slave_param = &spi_slaveparam1; + + spi_device1.spi_dev_done = &(spi_dev_done); + + ret = SpiDeviceRegister(&spi_device1, (void *)(&spi_device1.spi_param), SPI_1_DEVICE_NAME_1); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_1, ret); + return ERROR; + } + + ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_1, SPI_BUS_NAME_1); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_1, ret); + return ERROR; + } +#endif + +#ifdef BSP_SPI1_USING_SS2 + static struct SpiHardwareDevice spi_device2; + memset(&spi_device2, 0, sizeof(struct SpiHardwareDevice)); + + spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_2] = SPI_DEVICE_SLAVE_ID_2; + spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_2] = SPI1_CS2_PIN; + spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_2] = SPI_CHIP_SELECT_2; + + spi_device2.spi_dev_done = &(spi_dev_done); + + ret = SpiDeviceRegister(&spi_device2, (void *)(&spi_device2.spi_param), SPI_1_DEVICE_NAME_2); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_2, ret); + return ERROR; + } + + ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_2, SPI_BUS_NAME_1); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_2, ret); + return ERROR; + } +#endif + +#ifdef BSP_SPI1_USING_SS3 + static struct SpiHardwareDevice spi_device3; + memset(&spi_device3, 0, sizeof(struct SpiHardwareDevice)); + + spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_3] = SPI_DEVICE_SLAVE_ID_3; + spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_3] = SPI1_CS3_PIN; + spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_3] = SPI_CHIP_SELECT_3; + + spi_device3.spi_dev_done = &(spi_dev_done); + + ret = SpiDeviceRegister(&spi_device3, (void *)(&spi_device3.spi_param), SPI_1_DEVICE_NAME_3); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_3, ret); + return ERROR; + } + + ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_3, SPI_BUS_NAME_1); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_3, ret); + return ERROR; + } +#endif + return ret; +} + +/*RISC-V 64 BOARD SPI INIT*/ +int HwSpiInit(void) +{ + x_err_t ret = EOK; + static struct SpiDmaParam spi_initparam; + memset(&spi_initparam, 0, sizeof(struct SpiDmaParam)); + +#ifdef BSP_USING_SPI1 + + static struct SpiBus spi_bus; + memset(&spi_bus, 0, sizeof(struct SpiBus)); + + static struct SpiDriver spi_driver; + memset(&spi_driver, 0, sizeof(struct SpiDriver)); + + spi_initparam.spi_master_id = SPI_DEVICE_1; + spi_initparam.spi_dmac_txchannel = DMAC_CHANNEL1; + spi_initparam.spi_dmac_rxchannel = DMAC_CHANNEL2; + + spi_driver.configure = &(SpiDrvConfigure); + + ret = BoardSpiBusInit(&spi_bus, &spi_driver); + if (EOK != ret) { + KPrintf("Board_Spi_Init error ret %u\n", ret); + return ERROR; + } + + ret = BoardSpiDevBend(&spi_initparam); + if (EOK != ret) { + KPrintf("Board_Spi_Init error ret %u\n", ret); + return ERROR; + } +#endif + return ret; +} diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/hardware_spi.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/hardware_spi.c new file mode 100644 index 000000000..2947682d3 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/hardware_spi.c @@ -0,0 +1,1523 @@ +/* Copyright 2018 Canaan Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** +* @file hardware_spi.c +* @brief add from Canaan k210 SDK +* https://canaan-creative.com/developer +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +volatile spi_t *const spi[4] = +{ + (volatile spi_t *)SPI0_BASE_ADDR, + (volatile spi_t *)SPI1_BASE_ADDR, + (volatile spi_t *)SPI_SLAVE_BASE_ADDR, + (volatile spi_t *)SPI3_BASE_ADDR +}; + +typedef struct _spi_dma_context +{ + uint8_t *buffer; + size_t BufLen; + uint32_t *MallocBuffer; + spi_transfer_mode_t IntMode; + dmac_channel_number_t dmac_channel; + spi_device_num_t spi_num; + plic_instance_t spi_int_instance; +} spi_dma_context_t; + +spi_dma_context_t spi_dma_context[4]; + +typedef struct _spi_instance_t +{ + spi_device_num_t spi_num; + spi_transfer_mode_t TransferMode; + dmac_channel_number_t dmac_channel; + plic_instance_t spi_int_instance; + spinlock_t lock; +} spi_instance_t; + +static spi_instance_t g_spi_instance[4]; + +static spi_slave_instance_t g_instance; + +static spi_frame_format_t spi_get_frame_format(spi_device_num_t spi_num) +{ + uint8_t frf_offset; + switch(spi_num) + { + case 0: + case 1: + frf_offset = 21; + break; + case 2: + configASSERT(!"Spi Bus 2 Not Support!"); + break; + case 3: + default: + frf_offset = 22; + break; + } + volatile spi_t *spi_adapter = spi[spi_num]; + return ((spi_adapter->ctrlr0 >> frf_offset) & 0x3); +} + +static spi_transfer_width_t spi_get_frame_size(size_t data_bit_length) +{ + if (data_bit_length < 8) + return SPI_TRANS_CHAR; + else if (data_bit_length < 16) + return SPI_TRANS_SHORT; + return SPI_TRANS_INT; +} + +static int spi_dma_irq(void *ctx) +{ + spi_instance_t *v_instance = (spi_instance_t *)ctx; + volatile spi_t *spi_handle = spi[v_instance->spi_num]; + dmac_irq_unregister(v_instance->dmac_channel); + while ((spi_handle->sr & 0x05) != 0x04); + spi_handle->ser = 0x00; + spi_handle->ssienr = 0x00; + spinlock_unlock(&v_instance->lock); + if(v_instance->spi_int_instance.callback) + { + v_instance->spi_int_instance.callback(v_instance->spi_int_instance.ctx); + } + return 0; +} + +static int spi_clk_init(uint8_t spi_num) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + if(spi_num == 3) + sysctl_clock_set_clock_select(SYSCTL_CLOCK_SELECT_SPI3, 1); + sysctl_clock_enable(SYSCTL_CLOCK_SPI0 + spi_num); + sysctl_clock_set_threshold(SYSCTL_THRESHOLD_SPI0 + spi_num, 0); + return 0; +} + +static void spi_set_tmod(uint8_t spi_num, uint32_t tmod) +{ + configASSERT(spi_num < SPI_DEVICE_MAX); + volatile spi_t *spi_handle = spi[spi_num]; + uint8_t tmod_offset = 0; + switch(spi_num) + { + case 0: + case 1: + case 2: + tmod_offset = 8; + break; + case 3: + default: + tmod_offset = 10; + break; + } + set_bit(&spi_handle->ctrlr0, 3 << tmod_offset, tmod << tmod_offset); +} + +void spi_init(spi_device_num_t spi_num, spi_work_mode_t work_mode, spi_frame_format_t frame_format, + size_t data_bit_length, uint32_t endian) +{ + configASSERT(data_bit_length >= 4 && data_bit_length <= 32); + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + spi_clk_init(spi_num); + + uint8_t dfs_offset, frf_offset, work_mode_offset; + switch(spi_num) + { + case 0: + case 1: + dfs_offset = 16; + frf_offset = 21; + work_mode_offset = 6; + break; + case 2: + configASSERT(!"Spi Bus 2 Not Support!"); + break; + case 3: + default: + dfs_offset = 0; + frf_offset = 22; + work_mode_offset = 8; + break; + } + + switch (frame_format) + { + case SPI_FF_DUAL: + configASSERT(data_bit_length % 2 == 0); + break; + case SPI_FF_QUAD: + configASSERT(data_bit_length % 4 == 0); + break; + case SPI_FF_OCTAL: + configASSERT(data_bit_length % 8 == 0); + break; + default: + break; + } + volatile spi_t *spi_adapter = spi[spi_num]; + if(spi_adapter->baudr == 0) + spi_adapter->baudr = 0x14; + spi_adapter->imr = 0x00; + spi_adapter->dmacr = 0x00; + spi_adapter->dmatdlr = 0x10; + spi_adapter->dmardlr = 0x00; + spi_adapter->ser = 0x00; + spi_adapter->ssienr = 0x00; + spi_adapter->ctrlr0 = (work_mode << work_mode_offset) | (frame_format << frf_offset) | ((data_bit_length - 1) << dfs_offset); + spi_adapter->spi_ctrlr0 = 0; + spi_adapter->endian = endian; +} + +void spi_init_non_standard(spi_device_num_t spi_num, uint32_t instruction_length, uint32_t address_length, + uint32_t wait_cycles, spi_instruction_address_trans_mode_t instruction_address_trans_mode) +{ + configASSERT(wait_cycles < (1 << 5)); + configASSERT(instruction_address_trans_mode < 3); + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + volatile spi_t *spi_handle = spi[spi_num]; + uint32_t inst_l = 0; + switch (instruction_length) + { + case 0: + inst_l = 0; + break; + case 4: + inst_l = 1; + break; + case 8: + inst_l = 2; + break; + case 16: + inst_l = 3; + break; + default: + configASSERT(!"Invalid instruction length"); + break; + } + + configASSERT(address_length % 4 == 0 && address_length <= 60); + uint32_t addr_l = address_length / 4; + + spi_handle->spi_ctrlr0 = (wait_cycles << 11) | (inst_l << 8) | (addr_l << 2) | instruction_address_trans_mode; +} + +uint32_t spi_set_clk_rate(spi_device_num_t spi_num, uint32_t spi_clk) +{ + uint32_t spi_baudr = SysctlClockGetFreq(SYSCTL_CLOCK_SPI0 + spi_num) / spi_clk; + if(spi_baudr < 2 ) + { + spi_baudr = 2; + } + else if(spi_baudr > 65534) + { + spi_baudr = 65534; + } + volatile spi_t *spi_adapter = spi[spi_num]; + spi_adapter->baudr = spi_baudr; + return SysctlClockGetFreq(SYSCTL_CLOCK_SPI0 + spi_num) / spi_baudr; +} + +void spi_send_data_normal(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *tx_buff, size_t tx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + + size_t index, fifo_len; + spi_set_tmod(spi_num, SPI_TMOD_TRANS); + + volatile spi_t *spi_handle = spi[spi_num]; + + uint8_t dfs_offset; + switch(spi_num) + { + case 0: + case 1: + dfs_offset = 16; + break; + case 2: + configASSERT(!"Spi Bus 2 Not Support!"); + break; + case 3: + default: + dfs_offset = 0; + break; + } + uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F; + spi_transfer_width_t frame_width = spi_get_frame_size(data_bit_length); + + uint8_t v_misalign_flag = 0; + uint32_t v_send_data; + if((uintptr_t)tx_buff % frame_width) + v_misalign_flag = 1; + + spi_handle->ssienr = 0x01; + spi_handle->ser = 1U << chip_select; + uint32_t i = 0; + while (tx_len) + { + fifo_len = 32 - spi_handle->txflr; + fifo_len = fifo_len < tx_len ? fifo_len : tx_len; + switch(frame_width) + { + case SPI_TRANS_INT: + fifo_len = fifo_len / 4 * 4; + if(v_misalign_flag) + { + for(index = 0; index < fifo_len; index +=4) + { + memcpy(&v_send_data, tx_buff + i , 4); + spi_handle->dr[0] = v_send_data; + i += 4; + } + } + else + { + for (index = 0; index < fifo_len / 4; index++) + spi_handle->dr[0] = ((uint32_t *)tx_buff)[i++]; + } + break; + case SPI_TRANS_SHORT: + fifo_len = fifo_len / 2 * 2; + if(v_misalign_flag) + { + for(index = 0; index < fifo_len; index +=2) + { + memcpy(&v_send_data, tx_buff + i, 2); + spi_handle->dr[0] = v_send_data; + i += 2; + } + } + else + { + for (index = 0; index < fifo_len / 2; index++) + spi_handle->dr[0] = ((uint16_t *)tx_buff)[i++]; + } + break; + default: + for (index = 0; index < fifo_len; index++) + spi_handle->dr[0] = tx_buff[i++]; + break; + } + tx_len -= fifo_len; + } + while ((spi_handle->sr & 0x05) != 0x04) + ; + spi_handle->ser = 0x00; + spi_handle->ssienr = 0x00; + +} + +void spi_send_data_standard(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *CmdBuff, + size_t CmdLen, const uint8_t *tx_buff, size_t tx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + uint8_t *v_buf = malloc(CmdLen + tx_len); + size_t i; + for(i = 0; i < CmdLen; i++) + v_buf[i] = CmdBuff[i]; + for(i = 0; i < tx_len; i++) + v_buf[CmdLen + i] = tx_buff[i]; + + spi_send_data_normal(spi_num, chip_select, v_buf, CmdLen + tx_len); + free((void *)v_buf); +} + +void spi_send_data_standard_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num, + spi_chip_select_t chip_select, + const uint8_t *CmdBuff, size_t CmdLen, const uint8_t *tx_buff, size_t tx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + + volatile spi_t *spi_handle = spi[spi_num]; + + uint8_t dfs_offset; + switch(spi_num) + { + case 0: + case 1: + dfs_offset = 16; + break; + case 2: + configASSERT(!"Spi Bus 2 Not Support!"); + break; + case 3: + default: + dfs_offset = 0; + break; + } + uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F; + spi_transfer_width_t frame_width = spi_get_frame_size(data_bit_length); + + uint32_t *buf; + size_t v_send_len; + int i; + switch(frame_width) + { + case SPI_TRANS_INT: + buf = malloc(CmdLen + tx_len); + for(i = 0; i < CmdLen / 4; i++) + buf[i] = ((uint32_t *)CmdBuff)[i]; + for(i = 0; i < tx_len / 4; i++) + buf[CmdLen / 4 + i] = ((uint32_t *)tx_buff)[i]; + v_send_len = (CmdLen + tx_len) / 4; + break; + case SPI_TRANS_SHORT: + buf = malloc((CmdLen + tx_len) / 2 * sizeof(uint32_t)); + for(i = 0; i < CmdLen / 2; i++) + buf[i] = ((uint16_t *)CmdBuff)[i]; + for(i = 0; i < tx_len / 2; i++) + buf[CmdLen / 2 + i] = ((uint16_t *)tx_buff)[i]; + v_send_len = (CmdLen + tx_len) / 2; + break; + default: + buf = malloc((CmdLen + tx_len) * sizeof(uint32_t)); + for(i = 0; i < CmdLen; i++) + buf[i] = CmdBuff[i]; + for(i = 0; i < tx_len; i++) + buf[CmdLen + i] = tx_buff[i]; + v_send_len = CmdLen + tx_len; + break; + } + + spi_send_data_normal_dma(channel_num, spi_num, chip_select, buf, v_send_len, SPI_TRANS_INT); + + free((void *)buf); +} + +void spi_send_data_normal_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num, + spi_chip_select_t chip_select, + const void *tx_buff, size_t tx_len, spi_transfer_width_t spi_transfer_width) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + spi_set_tmod(spi_num, SPI_TMOD_TRANS); + volatile spi_t *spi_handle = spi[spi_num]; + uint32_t *buf; + int i; + switch(spi_transfer_width) + { + case SPI_TRANS_SHORT: + buf = malloc((tx_len) * sizeof(uint32_t)); + for(i = 0; i < tx_len; i++) + buf[i] = ((uint16_t *)tx_buff)[i]; + break; + case SPI_TRANS_INT: + buf = (uint32_t *)tx_buff; + break; + case SPI_TRANS_CHAR: + default: + buf = malloc((tx_len) * sizeof(uint32_t)); + for(i = 0; i < tx_len; i++) + buf[i] = ((uint8_t *)tx_buff)[i]; + break; + } + spi_handle->dmacr = 0x2; /*enable dma transmit*/ + spi_handle->ssienr = 0x01; + + sysctl_dma_select((sysctl_dma_channel_t) channel_num, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2); + dmac_set_single_mode(channel_num, buf, (void *)(&spi_handle->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, tx_len); + spi_handle->ser = 1U << chip_select; + dmac_wait_done(channel_num); + if(spi_transfer_width != SPI_TRANS_INT) + free((void *)buf); + + while ((spi_handle->sr & 0x05) != 0x04) + ; + spi_handle->ser = 0x00; + spi_handle->ssienr = 0x00; +} + +void spi_dup_send_receive_data_dma(dmac_channel_number_t dma_send_channel_num, + dmac_channel_number_t dma_receive_channel_num, + spi_device_num_t spi_num, spi_chip_select_t chip_select, + const uint8_t *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) +{ + spi_set_tmod(spi_num, SPI_TMOD_TRANS_RECV); + volatile spi_t *spi_handle = spi[spi_num]; + + uint8_t dfs_offset; + switch(spi_num) + { + case 0: + case 1: + dfs_offset = 16; + break; + case 2: + configASSERT(!"Spi Bus 2 Not Support!"); + break; + case 3: + default: + dfs_offset = 0; + break; + } + uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F; + spi_transfer_width_t frame_width = spi_get_frame_size(data_bit_length); + size_t v_tx_len = tx_len / frame_width; + size_t v_rx_len = rx_len / frame_width; + + size_t v_max_len = v_tx_len > v_rx_len ? v_tx_len : v_rx_len; + + uint32_t *v_tx_buf = malloc(v_max_len * 4); + uint32_t *v_rx_buf = malloc(v_max_len * 4); + uint32_t i = 0; + switch(frame_width) + { + case SPI_TRANS_INT: + for(i = 0; i < v_tx_len; i++) + { + v_tx_buf[i] = ((uint32_t *)tx_buf)[i]; + } + if(v_max_len > v_tx_len) + { + while(i < v_max_len) + { + v_tx_buf[i++] = 0xFFFFFFFF; + } + } + break; + case SPI_TRANS_SHORT: + for(i = 0; i < v_tx_len; i++) + { + v_tx_buf[i] = ((uint16_t *)tx_buf)[i]; + } + if(v_max_len > v_tx_len) + { + while(i < v_max_len) + { + v_tx_buf[i++] = 0xFFFFFFFF; + } + } + break; + default: + for(i = 0; i < v_tx_len; i++) + { + v_tx_buf[i] = tx_buf[i]; + } + if(v_max_len > v_tx_len) + { + while(i < v_max_len) + { + v_tx_buf[i++] = 0xFFFFFFFF; + } + } + break; + } + + spi_handle->dmacr = 0x3; + spi_handle->ssienr = 0x01; + + sysctl_dma_select((sysctl_dma_channel_t)dma_send_channel_num, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2); + sysctl_dma_select((sysctl_dma_channel_t)dma_receive_channel_num, SYSCTL_DMA_SELECT_SSI0_RX_REQ + spi_num * 2); + + dmac_set_single_mode(dma_receive_channel_num, (void *)(&spi_handle->dr[0]), v_rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, v_max_len); + + dmac_set_single_mode(dma_send_channel_num, v_tx_buf, (void *)(&spi_handle->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, v_max_len); + + spi_handle->ser = 1U << chip_select; + dmac_wait_done(dma_send_channel_num); + dmac_wait_done(dma_receive_channel_num); + + spi_handle->ser = 0x00; + spi_handle->ssienr = 0x00; + + switch(frame_width) + { + case SPI_TRANS_INT: + for(i = 0; i < v_rx_len; i++) + ((uint32_t *)rx_buf)[i] = v_rx_buf[i]; + break; + case SPI_TRANS_SHORT: + for(i = 0; i < v_rx_len; i++) + ((uint16_t *)rx_buf)[i] = v_rx_buf[i]; + break; + default: + for(i = 0; i < v_rx_len; i++) + rx_buf[i] = v_rx_buf[i]; + break; + } + free(v_tx_buf); + free(v_rx_buf); +} + +void spi_receive_data_standard(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *CmdBuff, + size_t CmdLen, uint8_t *rx_buff, size_t rx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + size_t index, fifo_len; + if(CmdLen == 0) + spi_set_tmod(spi_num, SPI_TMOD_RECV); + else + spi_set_tmod(spi_num, SPI_TMOD_EEROM); + volatile spi_t *spi_handle = spi[spi_num]; + + uint8_t dfs_offset; + switch(spi_num) + { + case 0: + case 1: + dfs_offset = 16; + break; + case 2: + configASSERT(!"Spi Bus 2 Not Support!"); + break; + case 3: + default: + dfs_offset = 0; + break; + } + uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F; + spi_transfer_width_t frame_width = spi_get_frame_size(data_bit_length); + + uint32_t i = 0; + size_t v_cmd_len = CmdLen / frame_width; + uint32_t v_rx_len = rx_len / frame_width; + + spi_handle->ctrlr1 = (uint32_t)(v_rx_len - 1); + spi_handle->ssienr = 0x01; + + while (v_cmd_len) + { + fifo_len = 32 - spi_handle->txflr; + fifo_len = fifo_len < v_cmd_len ? fifo_len : v_cmd_len; + switch(frame_width) + { + case SPI_TRANS_INT: + for (index = 0; index < fifo_len; index++) + spi_handle->dr[0] = ((uint32_t *)CmdBuff)[i++]; + break; + case SPI_TRANS_SHORT: + for (index = 0; index < fifo_len; index++) + spi_handle->dr[0] = ((uint16_t *)CmdBuff)[i++]; + break; + default: + for (index = 0; index < fifo_len; index++) + spi_handle->dr[0] = CmdBuff[i++]; + break; + } + spi_handle->ser = 1U << chip_select; + v_cmd_len -= fifo_len; + } + + if(CmdLen == 0) + { + spi_handle->dr[0] = 0xffffffff; + spi_handle->ser = 1U << chip_select; + } + + i = 0; + while (v_rx_len) + { + fifo_len = spi_handle->rxflr; + fifo_len = fifo_len < v_rx_len ? fifo_len : v_rx_len; + switch(frame_width) + { + case SPI_TRANS_INT: + for (index = 0; index < fifo_len; index++) + ((uint32_t *)rx_buff)[i++] = spi_handle->dr[0]; + break; + case SPI_TRANS_SHORT: + for (index = 0; index < fifo_len; index++) + ((uint16_t *)rx_buff)[i++] = (uint16_t)spi_handle->dr[0]; + break; + default: + for (index = 0; index < fifo_len; index++) + rx_buff[i++] = (uint8_t)spi_handle->dr[0]; + break; + } + + v_rx_len -= fifo_len; + } + + spi_handle->ser = 0x00; + spi_handle->ssienr = 0x00; +} + +void spi_receive_data_normal_dma(dmac_channel_number_t dma_send_channel_num, + dmac_channel_number_t dma_receive_channel_num, + spi_device_num_t spi_num, spi_chip_select_t chip_select, const void *CmdBuff, + size_t CmdLen, void *rx_buff, size_t rx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + + if(CmdLen == 0) + spi_set_tmod(spi_num, SPI_TMOD_RECV); + else + spi_set_tmod(spi_num, SPI_TMOD_EEROM); + + volatile spi_t *spi_handle = spi[spi_num]; + + spi_handle->ctrlr1 = (uint32_t)(rx_len - 1); + spi_handle->dmacr = 0x3; + spi_handle->ssienr = 0x01; + if(CmdLen) + sysctl_dma_select((sysctl_dma_channel_t)dma_send_channel_num, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2); + sysctl_dma_select((sysctl_dma_channel_t)dma_receive_channel_num, SYSCTL_DMA_SELECT_SSI0_RX_REQ + spi_num * 2); + + dmac_set_single_mode(dma_receive_channel_num, (void *)(&spi_handle->dr[0]), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, rx_len); + if(CmdLen) + dmac_set_single_mode(dma_send_channel_num, CmdBuff, (void *)(&spi_handle->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, CmdLen); + if(CmdLen == 0 && spi_get_frame_format(spi_num) == SPI_FF_STANDARD) + spi[spi_num]->dr[0] = 0xffffffff; + spi_handle->ser = 1U << chip_select; + if(CmdLen) + dmac_wait_done(dma_send_channel_num); + dmac_wait_done(dma_receive_channel_num); + + spi_handle->ser = 0x00; + spi_handle->ssienr = 0x00; +} + + +void spi_receive_data_standard_dma(dmac_channel_number_t dma_send_channel_num, + dmac_channel_number_t dma_receive_channel_num, + spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *CmdBuff, + size_t CmdLen, uint8_t *rx_buff, size_t rx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + volatile spi_t *spi_handle = spi[spi_num]; + + uint8_t dfs_offset; + switch(spi_num) + { + case 0: + case 1: + dfs_offset = 16; + break; + case 2: + configASSERT(!"Spi Bus 2 Not Support!"); + break; + case 3: + default: + dfs_offset = 0; + break; + } + uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F; + spi_transfer_width_t frame_width = spi_get_frame_size(data_bit_length); + + size_t i; + + uint32_t *write_cmd; + uint32_t *ReadBuf; + size_t v_recv_len; + size_t v_cmd_len; + switch(frame_width) + { + case SPI_TRANS_INT: + write_cmd = malloc(CmdLen + rx_len); + for(i = 0; i < CmdLen / 4; i++) + write_cmd[i] = ((uint32_t *)CmdBuff)[i]; + ReadBuf = &write_cmd[i]; + v_recv_len = rx_len / 4; + v_cmd_len = CmdLen / 4; + break; + case SPI_TRANS_SHORT: + write_cmd = malloc((CmdLen + rx_len) /2 * sizeof(uint32_t)); + for(i = 0; i < CmdLen / 2; i++) + write_cmd[i] = ((uint16_t *)CmdBuff)[i]; + ReadBuf = &write_cmd[i]; + v_recv_len = rx_len / 2; + v_cmd_len = CmdLen / 2; + break; + default: + write_cmd = malloc((CmdLen + rx_len) * sizeof(uint32_t)); + for(i = 0; i < CmdLen; i++) + write_cmd[i] = CmdBuff[i]; + ReadBuf = &write_cmd[i]; + v_recv_len = rx_len; + v_cmd_len = CmdLen; + break; + } + + spi_receive_data_normal_dma(dma_send_channel_num, dma_receive_channel_num, spi_num, chip_select, write_cmd, v_cmd_len, ReadBuf, v_recv_len); + + switch(frame_width) + { + case SPI_TRANS_INT: + for(i = 0; i < v_recv_len; i++) + ((uint32_t *)rx_buff)[i] = ReadBuf[i]; + break; + case SPI_TRANS_SHORT: + for(i = 0; i < v_recv_len; i++) + ((uint16_t *)rx_buff)[i] = ReadBuf[i]; + break; + default: + for(i = 0; i < v_recv_len; i++) + rx_buff[i] = ReadBuf[i]; + break; + } + + free(write_cmd); +} + +void spi_receive_data_multiple(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *CmdBuff, + size_t CmdLen, uint8_t *rx_buff, size_t rx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + + size_t index, fifo_len; + if(CmdLen == 0) + spi_set_tmod(spi_num, SPI_TMOD_RECV); + else + spi_set_tmod(spi_num, SPI_TMOD_EEROM); + volatile spi_t *spi_handle = spi[spi_num]; + + uint8_t dfs_offset; + switch(spi_num) + { + case 0: + case 1: + dfs_offset = 16; + break; + case 2: + configASSERT(!"Spi Bus 2 Not Support!"); + break; + case 3: + default: + dfs_offset = 0; + break; + } + uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F; + spi_transfer_width_t frame_width = spi_get_frame_size(data_bit_length); + + uint32_t v_cmd_len = CmdLen; + uint32_t i = 0; + + uint32_t v_rx_len = rx_len / frame_width; + + spi_handle->ctrlr1 = (uint32_t)(v_rx_len - 1); + spi_handle->ssienr = 0x01; + + while (v_cmd_len) + { + fifo_len = 32 - spi_handle->txflr; + fifo_len = fifo_len < v_cmd_len ? fifo_len : v_cmd_len; + + for (index = 0; index < fifo_len; index++) + spi_handle->dr[0] = *CmdBuff++; + + spi_handle->ser = 1U << chip_select; + v_cmd_len -= fifo_len; + } + + if(CmdLen == 0) + { + spi_handle->ser = 1U << chip_select; + } + + while (v_rx_len) + { + fifo_len = spi_handle->rxflr; + fifo_len = fifo_len < v_rx_len ? fifo_len : v_rx_len; + switch(frame_width) + { + case SPI_TRANS_INT: + for (index = 0; index < fifo_len; index++) + ((uint32_t *)rx_buff)[i++] = spi_handle->dr[0]; + break; + case SPI_TRANS_SHORT: + for (index = 0; index < fifo_len; index++) + ((uint16_t *)rx_buff)[i++] = (uint16_t)spi_handle->dr[0]; + break; + default: + for (index = 0; index < fifo_len; index++) + rx_buff[i++] = (uint8_t)spi_handle->dr[0]; + break; + } + + v_rx_len -= fifo_len; + } + + spi_handle->ser = 0x00; + spi_handle->ssienr = 0x00; + +} + +void spi_receive_data_multiple_dma(dmac_channel_number_t dma_send_channel_num, + dmac_channel_number_t dma_receive_channel_num, + spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *CmdBuff, + size_t CmdLen, uint8_t *rx_buff, size_t rx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + + volatile spi_t *spi_handle = spi[spi_num]; + + uint8_t dfs_offset; + switch(spi_num) + { + case 0: + case 1: + dfs_offset = 16; + break; + case 2: + configASSERT(!"Spi Bus 2 Not Support!"); + break; + case 3: + default: + dfs_offset = 0; + break; + } + uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F; + spi_transfer_width_t frame_width = spi_get_frame_size(data_bit_length); + + size_t i; + + uint32_t *write_cmd = NULL; + uint32_t *ReadBuf; + size_t v_recv_len; + switch(frame_width) + { + case SPI_TRANS_INT: + v_recv_len = rx_len / 4; + break; + case SPI_TRANS_SHORT: + write_cmd = malloc(CmdLen + rx_len /2 * sizeof(uint32_t)); + for(i = 0; i < CmdLen; i++) + write_cmd[i] = CmdBuff[i]; + ReadBuf = &write_cmd[i]; + v_recv_len = rx_len / 2; + break; + default: + write_cmd = malloc(CmdLen + rx_len * sizeof(uint32_t)); + for(i = 0; i < CmdLen; i++) + write_cmd[i] = CmdBuff[i]; + ReadBuf = &write_cmd[i]; + v_recv_len = rx_len; + break; + } + if(frame_width == SPI_TRANS_INT) + spi_receive_data_normal_dma(dma_send_channel_num, dma_receive_channel_num, spi_num, chip_select, CmdBuff, CmdLen, rx_buff, v_recv_len); + else + spi_receive_data_normal_dma(dma_send_channel_num, dma_receive_channel_num, spi_num, chip_select, write_cmd, CmdLen, ReadBuf, v_recv_len); + + switch(frame_width) + { + case SPI_TRANS_INT: + break; + case SPI_TRANS_SHORT: + for(i = 0; i < v_recv_len; i++) + ((uint16_t *)rx_buff)[i] = ReadBuf[i]; + break; + default: + for(i = 0; i < v_recv_len; i++) + rx_buff[i] = ReadBuf[i]; + break; + } + + if(frame_width != SPI_TRANS_INT) + free(write_cmd); +} + +void spi_send_data_multiple(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *CmdBuff, + size_t CmdLen, const uint8_t *tx_buff, size_t tx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + + size_t index, fifo_len; + spi_set_tmod(spi_num, SPI_TMOD_TRANS); + volatile spi_t *spi_handle = spi[spi_num]; + spi_handle->ssienr = 0x01; + spi_handle->ser = 1U << chip_select; + + size_t v_cmd_len = CmdLen * 4; + while(v_cmd_len) + { + fifo_len = 32 - spi_handle->txflr; + fifo_len = fifo_len < v_cmd_len ? fifo_len : v_cmd_len; + fifo_len = fifo_len / 4 * 4; + for (index = 0; index < fifo_len / 4; index++) + spi_handle->dr[0] = *CmdBuff++; + v_cmd_len -= fifo_len; + } + spi_send_data_normal(spi_num, chip_select, tx_buff, tx_len); +} + +void spi_send_data_multiple_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num, + spi_chip_select_t chip_select, + const uint32_t *CmdBuff, size_t CmdLen, const uint8_t *tx_buff, size_t tx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + volatile spi_t *spi_handle = spi[spi_num]; + + uint8_t dfs_offset; + switch(spi_num) + { + case 0: + case 1: + dfs_offset = 16; + break; + case 2: + configASSERT(!"Spi Bus 2 Not Support!"); + break; + case 3: + default: + dfs_offset = 0; + break; + } + uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F; + spi_transfer_width_t frame_width = spi_get_frame_size(data_bit_length); + + uint32_t *buf; + size_t v_send_len; + int i; + switch(frame_width) + { + case SPI_TRANS_INT: + buf = malloc(CmdLen * sizeof(uint32_t) + tx_len); + for(i = 0; i < CmdLen; i++) + buf[i] = CmdBuff[i]; + for(i = 0; i < tx_len / 4; i++) + buf[CmdLen + i] = ((uint32_t *)tx_buff)[i]; + v_send_len = CmdLen + tx_len / 4; + break; + case SPI_TRANS_SHORT: + buf = malloc(CmdLen * sizeof(uint32_t) + tx_len / 2 * sizeof(uint32_t)); + for(i = 0; i < CmdLen; i++) + buf[i] = CmdBuff[i]; + for(i = 0; i < tx_len / 2; i++) + buf[CmdLen + i] = ((uint16_t *)tx_buff)[i]; + v_send_len = CmdLen + tx_len / 2; + break; + default: + buf = malloc((CmdLen + tx_len) * sizeof(uint32_t)); + for(i = 0; i < CmdLen; i++) + buf[i] = CmdBuff[i]; + for(i = 0; i < tx_len; i++) + buf[CmdLen + i] = tx_buff[i]; + v_send_len = CmdLen + tx_len; + break; + } + + spi_send_data_normal_dma(channel_num, spi_num, chip_select, buf, v_send_len, SPI_TRANS_INT); + + free((void *)buf); +} + +void spi_fill_data_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num, spi_chip_select_t chip_select, + const uint32_t *tx_buff, size_t tx_len) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + + spi_set_tmod(spi_num, SPI_TMOD_TRANS); + volatile spi_t *spi_handle = spi[spi_num]; + spi_handle->dmacr = 0x2; /*enable dma transmit*/ + spi_handle->ssienr = 0x01; + + sysctl_dma_select((sysctl_dma_channel_t)channel_num, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2); + dmac_set_single_mode(channel_num, tx_buff, (void *)(&spi_handle->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, tx_len); + spi_handle->ser = 1U << chip_select; + dmac_wait_done(channel_num); + + while ((spi_handle->sr & 0x05) != 0x04) + ; + spi_handle->ser = 0x00; + spi_handle->ssienr = 0x00; +} + +static int spi_slave_irq(void *ctx) +{ + volatile spi_t *spi_handle = spi[2]; + + spi_handle->imr = 0x00; + *(volatile uint32_t *)((uintptr_t)spi_handle->icr); + if (g_instance.status == IDLE) + g_instance.status = COMMAND; + return 0; +} + +static void spi_slave_idle_mode(void) +{ + volatile spi_t *spi_handle = spi[2]; + uint32_t DataWidth = g_instance.data_bit_length / 8; + g_instance.status = IDLE; + spi_handle->ssienr = 0x00; + spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((g_instance.data_bit_length - 1) << g_instance.dfs); + spi_handle->rxftlr = 0x08 / DataWidth - 1; + + spi_handle->dmacr = 0x00; + spi_handle->imr = 0x10; + spi_handle->ssienr = 0x01; + gpiohs_set_pin(g_instance.ready_pin, GPIO_PV_HIGH); +} + +static void spi_slave_command_mode(void) +{ + volatile spi_t *spi_handle = spi[2]; + uint8_t CmdData[8], sum = 0; + + spi_transfer_width_t frame_width = spi_get_frame_size(g_instance.data_bit_length - 1); + uint32_t DataWidth = g_instance.data_bit_length / 8; + spi_device_num_t spi_num = SPI_DEVICE_2; + switch(frame_width) + { + case SPI_TRANS_INT: + for (uint32_t i = 0; i < 8 / 4; i++) + ((uint32_t *)CmdData)[i] = spi_handle->dr[0]; + break; + case SPI_TRANS_SHORT: + for (uint32_t i = 0; i < 8 / 2; i++) + ((uint16_t *)CmdData)[i] = spi_handle->dr[0]; + break; + default: + for (uint32_t i = 0; i < 8; i++) + CmdData[i] = spi_handle->dr[0]; + break; + } + + for (uint32_t i = 0; i < 7; i++) + { + sum += CmdData[i]; + } + if (CmdData[7] != sum) + { + spi_slave_idle_mode(); + return; + } + g_instance.command.cmd = CmdData[0]; + g_instance.command.addr = CmdData[1] | (CmdData[2] << 8) | (CmdData[3] << 16) | (CmdData[4] << 24); + g_instance.command.len = CmdData[5] | (CmdData[6] << 8); + if (g_instance.command.len == 0) + g_instance.command.len = 65536; + if ((g_instance.command.cmd < WRITE_DATA_BLOCK) && (g_instance.command.len > 8)) + { + spi_slave_idle_mode(); + return; + } + g_instance.status = TRANSFER; + spi_handle->ssienr = 0x00; + if (g_instance.command.cmd == WRITE_CONFIG) + { + spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((g_instance.data_bit_length - 1) << g_instance.dfs); + spi[2]->rxftlr = g_instance.command.len / DataWidth - 1; + spi_handle->imr = 0x00; + spi_handle->ssienr = 0x01; + } + else if (g_instance.command.cmd == READ_CONFIG) + { + spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x0 << g_instance.slv_oe) | ((g_instance.data_bit_length - 1) << g_instance.dfs); + spi_set_tmod(2, SPI_TMOD_TRANS); + spi_handle->txftlr = 0x00; + spi_handle->imr = 0x00; + spi_handle->ssienr = 0x01; + switch(frame_width) + { + case SPI_TRANS_INT: + for (uint32_t i = 0; i < g_instance.command.len / 4; i++) + { + spi_handle->dr[0] = ((uint32_t *)&g_instance.config_ptr[g_instance.command.addr])[i]; + } + break; + case SPI_TRANS_SHORT: + for (uint32_t i = 0; i < g_instance.command.len / 2; i++) + { + spi_handle->dr[0] = ((uint16_t *)&g_instance.config_ptr[g_instance.command.addr])[i]; + } + break; + default: + for (uint32_t i = 0; i < g_instance.command.len; i++) + { + spi_handle->dr[0] = ((uint8_t *)&g_instance.config_ptr[g_instance.command.addr])[i]; + } + break; + } + } + else if (g_instance.command.cmd == WRITE_DATA_BYTE) + { + spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((g_instance.data_bit_length - 1) << g_instance.dfs); + spi[2]->rxftlr = g_instance.command.len / DataWidth - 1; + spi_handle->imr = 0x00; + spi_handle->ssienr = 0x01; + } + else if (g_instance.command.cmd == READ_DATA_BYTE) + { + spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x0 << g_instance.slv_oe) | ((g_instance.data_bit_length - 1) << g_instance.dfs); + spi_set_tmod(2, SPI_TMOD_TRANS); + spi_handle->txftlr = 0x00; + spi_handle->imr = 0x00; + spi_handle->ssienr = 0x01; + switch(frame_width) + { + case SPI_TRANS_INT: + for (uint32_t i = 0; i < g_instance.command.len / 4; i++) + { + spi_handle->dr[0] = ((uint32_t *)(uintptr_t)g_instance.command.addr)[i]; + } + break; + case SPI_TRANS_SHORT: + for (uint32_t i = 0; i < g_instance.command.len / 2; i++) + { + spi_handle->dr[0] = ((uint16_t *)(uintptr_t)g_instance.command.addr)[i]; + } + break; + default: + for (uint32_t i = 0; i < g_instance.command.len; i++) + { + spi_handle->dr[0] = ((uint8_t *)(uintptr_t)g_instance.command.addr)[i]; + } + break; + } + } + else if (g_instance.command.cmd == WRITE_DATA_BLOCK) + { + spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((32 - 1) << g_instance.dfs); + + spi_handle->dmacr = 0x01; + spi_handle->imr = 0x00; + spi_handle->ssienr = 0x01; + + sysctl_dma_select(g_instance.dmac_channel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + spi_num * 2); + + dmac_set_single_mode(g_instance.dmac_channel, (void *)(&spi_handle->dr[0]), (void *)((uintptr_t)g_instance.command.addr & 0xFFFFFFF0), DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, g_instance.command.len * 4); + } + else if (g_instance.command.cmd == READ_DATA_BLOCK) + { + spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x0 << g_instance.slv_oe) | ((32 - 1) << g_instance.dfs); + spi_set_tmod(2, SPI_TMOD_TRANS); + spi_handle->dmacr = 0x02; + spi_handle->imr = 0x00; + spi_handle->ssienr = 0x01; + + sysctl_dma_select(g_instance.dmac_channel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2); + dmac_set_single_mode(g_instance.dmac_channel, (void *)((uintptr_t)g_instance.command.addr & 0xFFFFFFF0), (void *)(&spi_handle->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, g_instance.command.len * 4); + } + else + { + spi_slave_idle_mode(); + return; + } + gpiohs_set_pin(g_instance.ready_pin, GPIO_PV_LOW); +} + +static void spi_slave_transfer_mode(void) +{ + spi_transfer_width_t frame_width = spi_get_frame_size(g_instance.data_bit_length - 1); + uint32_t command_len = 0; + + switch(frame_width) + { + case SPI_TRANS_INT: + command_len = g_instance.command.len / 4; + break; + case SPI_TRANS_SHORT: + command_len = g_instance.command.len / 2; + break; + default: + command_len = g_instance.command.len; + break; + } + volatile spi_t *spi_handle = spi[2]; + g_instance.command.err = 0; + if (g_instance.command.cmd == WRITE_CONFIG || g_instance.command.cmd == WRITE_DATA_BYTE) + { + if (spi_handle->rxflr < command_len - 1) + g_instance.command.err = 1; + } + else if (g_instance.command.cmd == READ_CONFIG || g_instance.command.cmd == READ_DATA_BYTE) + { + if (spi_handle->txflr != 0) + g_instance.command.err = 2; + } else if (g_instance.command.cmd == WRITE_DATA_BLOCK || g_instance.command.cmd == READ_DATA_BLOCK) + { + if (dmac->channel[g_instance.dmac_channel].intstatus != 0x02) + g_instance.command.err = 3; + } + else + { + spi_slave_idle_mode(); + return; + } + + if (g_instance.command.err == 0) + { + if (g_instance.command.cmd == WRITE_CONFIG) + { + switch(frame_width) + { + case SPI_TRANS_INT: + for (uint32_t i = 0; i < command_len; i++) + { + ((uint32_t *)&g_instance.config_ptr[g_instance.command.addr])[i] = spi_handle->dr[0]; + } + break; + case SPI_TRANS_SHORT: + for (uint32_t i = 0; i < command_len; i++) + { + ((uint16_t *)&g_instance.config_ptr[g_instance.command.addr])[i] = spi_handle->dr[0]; + } + break; + default: + for (uint32_t i = 0; i < command_len; i++) + { + ((uint8_t *)&g_instance.config_ptr[g_instance.command.addr])[i] = spi_handle->dr[0]; + } + break; + } + } + else if (g_instance.command.cmd == WRITE_DATA_BYTE) + { + switch(frame_width) + { + case SPI_TRANS_INT: + for (uint32_t i = 0; i < command_len; i++) + { + ((uint32_t *)(uintptr_t)g_instance.command.addr)[i] = spi_handle->dr[0]; + } + break; + case SPI_TRANS_SHORT: + for (uint32_t i = 0; i < command_len; i++) + { + ((uint16_t *)(uintptr_t)g_instance.command.addr)[i] = spi_handle->dr[0]; + } + break; + default: + for (uint32_t i = 0; i < command_len; i++) + { + ((uint8_t *)(uintptr_t)g_instance.command.addr)[i] = spi_handle->dr[0]; + } + break; + } + } + } + if(g_instance.callback != NULL) + { + g_instance.callback((void *)&g_instance.command); + } + spi_slave_idle_mode(); +} + +static void spi_slave_cs_irq(void) +{ + if (g_instance.status == IDLE) + spi_slave_idle_mode(); + else if (g_instance.status == COMMAND) + spi_slave_command_mode(); + else if (g_instance.status == TRANSFER) + spi_slave_transfer_mode(); +} + +void spi_slave_config(uint8_t int_pin, uint8_t ready_pin, dmac_channel_number_t dmac_channel, size_t data_bit_length, uint8_t *data, uint32_t len, spi_slave_receive_callback_t callback) +{ + g_instance.status = IDLE; + g_instance.config_ptr = data; + g_instance.config_len = len; + g_instance.work_mode = 6; + g_instance.slv_oe = 10; + g_instance.dfs = 16; + g_instance.data_bit_length = data_bit_length; + g_instance.ready_pin = ready_pin; + g_instance.int_pin = int_pin; + g_instance.callback = callback; + g_instance.dmac_channel = dmac_channel; + sysctl_reset(SYSCTL_RESET_SPI2); + sysctl_clock_enable(SYSCTL_CLOCK_SPI2); + sysctl_clock_set_threshold(SYSCTL_THRESHOLD_SPI2, 9); + + uint32_t DataWidth = data_bit_length / 8; + volatile spi_t *spi_handle = spi[2]; + spi_handle->ssienr = 0x00; + spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((data_bit_length - 1) << g_instance.dfs); + spi_handle->dmatdlr = 0x04; + spi_handle->dmardlr = 0x03; + spi_handle->dmacr = 0x00; + spi_handle->txftlr = 0x00; + spi_handle->rxftlr = 0x08 / DataWidth - 1; + spi_handle->imr = 0x10; + spi_handle->ssienr = 0x01; + + gpiohs_set_drive_mode(g_instance.ready_pin, GPIO_DM_OUTPUT); + gpiohs_set_pin(g_instance.ready_pin, GPIO_PV_HIGH); + + gpiohs_set_drive_mode(g_instance.int_pin, GPIO_DM_INPUT_PULL_UP); + gpiohs_set_pin_edge(g_instance.int_pin, GPIO_PE_RISING); + gpiohs_set_irq(g_instance.int_pin, 3, spi_slave_cs_irq); + + plic_set_priority(IRQN_SPI_SLAVE_INTERRUPT, 4); + plic_irq_enable(IRQN_SPI_SLAVE_INTERRUPT); + plic_irq_register(IRQN_SPI_SLAVE_INTERRUPT, spi_slave_irq, NULL); +} + +void spi_handle_data_dma(spi_device_num_t spi_num, spi_chip_select_t chip_select, spi_data_t data, plic_interrupt_t *cb) +{ + configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2); + configASSERT(chip_select < SPI_CHIP_SELECT_MAX); + switch(data.TransferMode) + { + case SPI_TMOD_TRANS_RECV: + case SPI_TMOD_EEROM: + configASSERT(data.tx_buf && data.tx_len && data.rx_buf && data.rx_len); + break; + case SPI_TMOD_TRANS: + configASSERT(data.tx_buf && data.tx_len); + break; + case SPI_TMOD_RECV: + configASSERT(data.rx_buf && data.rx_len); + break; + default: + configASSERT(!"Transfer Mode ERR"); + break; + } + configASSERT(data.tx_channel < DMAC_CHANNEL_MAX && data.rx_channel < DMAC_CHANNEL_MAX); + volatile spi_t *spi_handle = spi[spi_num]; + + spinlock_lock(&g_spi_instance[spi_num].lock); + if(cb) + { + g_spi_instance[spi_num].spi_int_instance.callback = cb->callback; + g_spi_instance[spi_num].spi_int_instance.ctx = cb->ctx; + } + switch(data.TransferMode) + { + case SPI_TMOD_RECV: + spi_set_tmod(spi_num, SPI_TMOD_RECV); + if(data.rx_len > 65536) + data.rx_len = 65536; + spi_handle->ctrlr1 = (uint32_t)(data.rx_len - 1); + spi_handle->dmacr = 0x03; + spi_handle->ssienr = 0x01; + if(spi_get_frame_format(spi_num) == SPI_FF_STANDARD) + spi_handle->dr[0] = 0xffffffff; + if(cb) + { + dmac_irq_register(data.rx_channel, spi_dma_irq, &g_spi_instance[spi_num], cb->priority); + g_spi_instance[spi_num].dmac_channel = data.rx_channel; + } + sysctl_dma_select((sysctl_dma_channel_t)data.rx_channel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + spi_num * 2); + dmac_set_single_mode(data.rx_channel, (void *)(&spi_handle->dr[0]), (void *)data.rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len); + spi_handle->ser = 1U << chip_select; + if(!cb) + dmac_wait_idle(data.rx_channel); + break; + case SPI_TMOD_TRANS: + spi_set_tmod(spi_num, SPI_TMOD_TRANS); + spi_handle->dmacr = 0x2; /*enable dma transmit*/ + spi_handle->ssienr = 0x01; + + if(cb) + { + dmac_irq_register(data.tx_channel, spi_dma_irq, &g_spi_instance[spi_num], cb->priority); + g_spi_instance[spi_num].dmac_channel = data.tx_channel; + } + sysctl_dma_select(data.tx_channel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2); + if(data.fill_mode) + dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&spi_handle->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, data.tx_len); + else + dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&spi_handle->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, data.tx_len); + spi_handle->ser = 1U << chip_select; + if(!cb) + { + dmac_wait_idle(data.tx_channel); + while ((spi_handle->sr & 0x05) != 0x04) + ; + } + break; + case SPI_TMOD_EEROM: + spi_set_tmod(spi_num, SPI_TMOD_EEROM); + if(data.rx_len > 65536) + data.rx_len = 65536; + spi_handle->ctrlr1 = (uint32_t)(data.rx_len - 1); + spi_handle->dmacr = 0x3; + spi_handle->ssienr = 0x01; + sysctl_dma_select(data.tx_channel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2); + if(data.fill_mode) + dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&spi_handle->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, data.tx_len); + else + dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&spi_handle->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, data.tx_len); + if(cb) + { + dmac_irq_register(data.rx_channel, spi_dma_irq, &g_spi_instance[spi_num], cb->priority); + g_spi_instance[spi_num].dmac_channel = data.rx_channel; + } + sysctl_dma_select(data.rx_channel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + spi_num * 2); + dmac_set_single_mode(data.rx_channel, (void *)(&spi_handle->dr[0]), (void *)data.rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len); + spi_handle->ser = 1U << chip_select; + if(!cb) + dmac_wait_idle(data.rx_channel); + break; + case SPI_TMOD_TRANS_RECV: + spi_set_tmod(spi_num, SPI_TMOD_TRANS_RECV); + if(data.rx_len > 65536) + data.rx_len = 65536; + + if(cb) + { + if(data.tx_len > data.rx_len) + { + dmac_irq_register(data.tx_channel, spi_dma_irq, &g_spi_instance[spi_num], cb->priority); + g_spi_instance[spi_num].dmac_channel = data.tx_channel; + } + else + { + dmac_irq_register(data.rx_channel, spi_dma_irq, &g_spi_instance[spi_num], cb->priority); + g_spi_instance[spi_num].dmac_channel = data.rx_channel; + } + } + spi_handle->ctrlr1 = (uint32_t)(data.rx_len - 1); + spi_handle->dmacr = 0x3; + spi_handle->ssienr = 0x01; + sysctl_dma_select(data.tx_channel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2); + if(data.fill_mode) + dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&spi_handle->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, data.tx_len); + else + dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&spi_handle->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE, + DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, data.tx_len); + sysctl_dma_select(data.rx_channel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + spi_num * 2); + dmac_set_single_mode(data.rx_channel, (void *)(&spi_handle->dr[0]), (void *)data.rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len); + spi_handle->ser = 1U << chip_select; + if(!cb) + { + dmac_wait_idle(data.tx_channel); + dmac_wait_idle(data.rx_channel); + } + break; + } + if(!cb) + { + spinlock_unlock(&g_spi_instance[spi_num].lock); + spi_handle->ser = 0x00; + spi_handle->ssienr = 0x00; + } +} +