Browse Source

把龙芯1c的SPI接口改为RTT统一的SPI接口

勤为本 7 năm trước cách đây
mục cha
commit
1bbe09df94

+ 229 - 0
bsp/ls1cdev/drivers/drv_spi.c

@@ -0,0 +1,229 @@
+/*
+ * File      : drv_spi.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-11-02     勤为本       first version
+ */
+
+#include <rtthread.h>
+#include <drivers/spi.h>
+#include "drv_spi.h"
+
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define DEBUG_PRINTF(...)           rt_kprintf(__VA_ARGS__)
+#else
+#define DEBUG_PRINTF(...)
+#endif
+
+
+static rt_err_t configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
+static rt_uint32_t xfer(struct rt_spi_device *device, struct rt_spi_message *message);
+
+
+static struct rt_spi_ops ls1c_spi_ops = 
+{
+    .configure  = configure,
+    .xfer       = xfer
+};
+
+
+static rt_err_t configure(struct rt_spi_device *device, 
+                          struct rt_spi_configuration *configuration)
+{
+    struct rt_spi_bus *spi_bus = NULL;
+    struct ls1c_spi *ls1c_spi = NULL;
+    unsigned char SPIx = 0;
+    void *spi_base = NULL;
+    unsigned char cpol = 0;
+    unsigned char cpha = 0;
+    unsigned char val = 0;
+
+    RT_ASSERT(NULL != device);
+    RT_ASSERT(NULL != configuration);
+
+    spi_bus = device->bus;
+    ls1c_spi = (struct ls1c_spi *)spi_bus->parent.user_data;
+    SPIx = ls1c_spi->SPIx;
+    spi_base = ls1c_spi_get_base(SPIx);
+
+    {
+        // 使能SPI控制器,master模式,关闭中断
+        reg_write_8(0x53, spi_base + LS1C_SPI_SPCR_OFFSET);
+
+        // 清空状态寄存器
+        reg_write_8(0xc0, spi_base + LS1C_SPI_SPSR_OFFSET);
+
+        // 1字节产生中断,采样(读)与发送(写)时机同时
+        reg_write_8(0x03, spi_base + LS1C_SPI_SPER_OFFSET);
+
+        // 关闭SPI flash
+        val = reg_read_8(spi_base + LS1C_SPI_SFC_PARAM_OFFSET);
+        val &= 0xfe;
+        reg_write_8(val, spi_base + LS1C_SPI_SFC_PARAM_OFFSET);
+
+        // spi flash时序控制寄存器
+        reg_write_8(0x05, spi_base + LS1C_SPI_SFC_TIMING_OFFSET);
+    }
+    
+    // baudrate
+    ls1c_spi_set_clock(spi_base, configuration->max_hz);
+
+    // 设置通信模式(时钟极性和相位)
+    if (configuration->mode & RT_SPI_CPOL)      // cpol
+    {
+        cpol = SPI_CPOL_1;
+    }
+    else
+    {
+        cpol = SPI_CPOL_0;
+    }
+    if (configuration->mode & RT_SPI_CPHA)      // cpha
+    {
+        cpha = SPI_CPHA_1;
+    }
+    else
+    {
+        cpha = SPI_CPHA_0;
+    }
+    ls1c_spi_set_mode(spi_base, cpol, cpha);
+
+    DEBUG_PRINTF("ls1c spi%d configuration\n", SPIx);
+
+    return RT_EOK;
+}
+
+
+static rt_uint32_t xfer(struct rt_spi_device *device, 
+                        struct rt_spi_message *message)
+{
+    struct rt_spi_bus *spi_bus = NULL;
+    struct ls1c_spi *ls1c_spi = NULL;
+    void *spi_base = NULL;
+    unsigned char SPIx = 0;
+    struct ls1c_spi_cs *ls1c_spi_cs = NULL;
+    unsigned char cs = 0;
+    rt_uint32_t size = 0;
+    const rt_uint8_t *send_ptr = NULL;
+    rt_uint8_t *recv_ptr = NULL;
+    rt_uint8_t data = 0;
+
+    RT_ASSERT(NULL != device);
+    RT_ASSERT(NULL != message);
+
+    spi_bus = device->bus;
+    ls1c_spi = spi_bus->parent.user_data;
+    SPIx = ls1c_spi->SPIx;
+    spi_base = ls1c_spi_get_base(SPIx);
+    ls1c_spi_cs = device->parent.user_data;
+    cs = ls1c_spi_cs->cs;
+    size = message->length;
+
+    DEBUG_PRINTF("[%s] SPIx=%d, cs=%d\n", __FUNCTION__, SPIx, cs);
+
+    // take cs
+    if (message->cs_take)
+    {
+        ls1c_spi_set_cs(spi_base, cs, 0);
+    }
+
+    // 收发数据
+    send_ptr = message->send_buf;
+    recv_ptr = message->recv_buf;
+    while (size--)
+    {
+        data = 0xFF;
+        if (NULL != send_ptr)
+        {
+            data = *send_ptr++;
+        }
+
+        if (NULL != recv_ptr)
+        {
+            *recv_ptr++ = ls1c_spi_txrx_byte(spi_base, data);
+        }
+        else
+        {
+            ls1c_spi_txrx_byte(spi_base, data);
+        }
+    }
+
+    // release cs
+    if (message->cs_release)
+    {
+        ls1c_spi_set_cs(spi_base, cs, 1);
+    }
+
+    return message->length;
+}
+
+
+#ifdef RT_USING_SPI0
+struct ls1c_spi ls1c_spi0 = 
+{
+    .SPIx = LS1C_SPI_0,
+};
+
+static struct rt_spi_bus spi0_bus;
+#endif
+
+
+#ifdef RT_USING_SPI1
+struct ls1c_spi ls1c_spi1 = 
+{
+    .SPIx = LS1C_SPI_1,
+};
+
+static struct rt_spi_bus spi1_bus;
+#endif
+
+
+/*
+ * 初始化并注册龙芯1c的spi总线
+ * @SPI SPI总线,比如LS1C_SPI_0, LS1C_SPI_1
+ * @spi_bus_name 总线名字
+ * @ret 
+ */
+rt_err_t ls1c_spi_bus_register(rt_uint8_t SPI, const char *spi_bus_name)
+{
+    struct rt_spi_bus *spi_bus = NULL;
+
+#ifdef RT_USING_SPI0
+    if (LS1C_SPI_0 == SPI)
+    {
+        spi_bus = &spi0_bus;
+        spi_bus->parent.user_data = &ls1c_spi0;
+    }
+#endif
+
+#ifdef RT_USING_SPI1
+    if (LS1C_SPI_1 == SPI)
+    {
+        spi_bus = &spi1_bus;
+        spi_bus->parent.user_data = &ls1c_spi1;
+    }
+#endif
+
+    return rt_spi_bus_register(spi_bus, spi_bus_name, &ls1c_spi_ops);
+}
+
+

+ 55 - 0
bsp/ls1cdev/drivers/drv_spi.h

@@ -0,0 +1,55 @@
+/*
+ * File      : drv_spi.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-11-02     勤为本       first version
+ */
+
+#ifndef LS1C_DRV_SPI_H
+#define LS1C_DRV_SPI_H
+
+
+#include "../libraries/ls1c_spi.h"
+
+
+struct ls1c_spi
+{
+    unsigned char SPIx;     // LS1C_SPI_0 or LS1C_SPI_1
+};
+
+
+struct ls1c_spi_cs
+{
+    unsigned char cs;       // LS1C_SPI_CS_0, LS1C_SPI_CS_1, LS1C_SPI_CS_2 or LS1C_SPI_CS_3
+};
+
+
+
+/*
+ * 初始化并注册龙芯1c的spi总线
+ * @SPI SPI总线,比如LS1C_SPI_0, LS1C_SPI_1
+ * @spi_bus_name 总线名字
+ * @ret 
+ */
+rt_err_t ls1c_spi_bus_register(rt_uint8_t SPI, const char *spi_bus_name);
+
+
+#endif
+

+ 0 - 40
bsp/ls1cdev/drivers/led.c

@@ -1,40 +0,0 @@
-// led接口
-// 使用低电平点亮led,高电平熄灭led
-
-
-#include "ls1c_gpio.h"
-
-
-// 初始化led
-// @led_gpio led所在gpio引脚
-void led_init(unsigned int led_gpio)
-{
-    gpio_init(led_gpio, gpio_mode_output);
-    gpio_set(led_gpio, gpio_level_high);        // 指示灯默认熄灭
-
-    return ;
-}
-
-
-// 点亮led
-// @led_gpio led所在gpio引脚
-void led_on(unsigned int led_gpio)
-{
-    gpio_set(led_gpio, gpio_level_low);
-
-    return ;
-}
-
-
-// 熄灭led
-// @led_gpio
-void led_off(unsigned int led_gpio)
-{
-    gpio_set(led_gpio, gpio_level_high);
-
-    return ;
-}
-
-
-
-

+ 0 - 27
bsp/ls1cdev/drivers/led.h

@@ -1,27 +0,0 @@
-// led接口
-// 使用低电平点亮led,高电平熄灭led
-
-#ifndef __OPENLOONGSON_LED_H
-#define __OPENLOONGSON_LED_H
-
-
-// 初始化led
-// @led_gpio led所在gpio引脚
-void led_init(unsigned int led_gpio);
-
-
-// 点亮led
-// @led_gpio led所在gpio引脚
-void led_on(unsigned int led_gpio);
-
-
-// 熄灭led
-// @led_gpio
-void led_off(unsigned int led_gpio);
-
-
-
-
-
-#endif
-

+ 29 - 112
bsp/ls1cdev/libraries/ls1c_spi.c

@@ -32,53 +32,13 @@
 #include "ls1c_spi.h"
 
 
-// 寄存器偏移
-#define LS1C_SPI_SPCR_OFFSET                (0)     // 控制寄存器
-#define LS1C_SPI_SPSR_OFFSET                (1)     // 状态寄存器
-#define LS1C_SPI_TxFIFO_OFFSET              (2)     // 发送的数据寄存器,与接收数据寄存器的偏移相同
-#define LS1C_SPI_RxFIFO_OFFSET              (2)     // 接收的数据寄存器,与发送数据寄存器的偏移相同
-#define LS1C_SPI_SPER_OFFSET                (3)     // 外部寄存器
-#define LS1C_SPI_SFC_PARAM_OFFSET           (4)     // 参数控制寄存器
-#define LS1C_SPI_SFC_SOFTCS_OFFSET          (5)     // 片选控制寄存器
-#define LS1C_SPI_SFC_TIMING_OFFSET          (6)     // 时序控制寄存器
-
-// 寄存器SPCR中的位域
-#define LS1C_SPI_SPCR_SPIE_BIT              (7)
-#define LS1C_SPI_SPCR_SPIE_MASK             (0x01 << LS1C_SPI_SPCR_SPIE_BIT)
-#define LS1C_SPI_SPCR_SPE_BIT               (6)
-#define LS1C_SPI_SPCR_SPE_MASK              (0x01 << LS1C_SPI_SPCR_SPE_BIT)
-#define LS1C_SPI_SPCR_CPOL_BIT              (3)
-#define LS1C_SPI_SPCR_CPOL_MASK             (0x01 << LS1C_SPI_SPCR_CPOL_BIT)
-#define LS1C_SPI_SPCR_CPHA_BIT              (2)
-#define LS1C_SPI_SPCR_CPHA_MASK             (0x01 << LS1C_SPI_SPCR_CPHA_BIT)
-#define LS1C_SPI_SPCR_SPR_BIT               (0)
-#define LS1C_SPI_SPCR_SPR_MASK              (0x03 << LS1C_SPI_SPCR_SPR_BIT)
-
-// 寄存器SPSR中的位域
-#define LS1C_SPI_SPSR_SPIF_BIT              (7)
-#define LS1C_SPI_SPSR_SPIF_MASK             (0x01 << LS1C_SPI_SPSR_SPIF_BIT)
-#define LS1C_SPI_SPSR_WCOL_BIT              (6)
-#define LS1C_SPI_SPSR_WCOL_MASK             (0x01 << LS1C_SPI_SPSR_WCOL_BIT)
-
-// 寄存器SPER中的位域
-#define LS1C_SPI_SPER_SPRE_BIT              (0)
-#define LS1C_SPI_SPER_SPRE_MASK             (0x3 << LS1C_SPI_SPER_SPRE_BIT)
-
-// 寄存器SFC_SOFTCS的位域
-#define LS1C_SPI_SFC_SOFTCS_CSN_BIT         (4)
-#define LS1C_SPI_SFC_SOFTCS_CSN_MASK        (0x0f << LS1C_SPI_SFC_SOFTCS_CSN_BIT)
-#define LS1C_SPI_SFC_SOFTCS_CSEN_BIT        (0)
-#define LS1C_SPI_SFC_SOFTCS_CSEN_MASK       (0x0f << LS1C_SPI_SFC_SOFTCS_CSEN_BIT)
-
-// 发送超时的门限值
-#define LS1C_SPI_TX_TIMEOUT                 (20000)
 
 
 /*
  * 获取指定SPI模块的基地址
  * @SPIx SPI模块的编号
  */
-inline void *spi_get_base(ls1c_spi_t SPIx)
+inline void *ls1c_spi_get_base(unsigned char SPIx)
 {
     void *base = NULL;
 
@@ -103,15 +63,12 @@ inline void *spi_get_base(ls1c_spi_t SPIx)
 
 /*
  * 打印指定SPI模块的所有寄存器的值
- * @spi_info_p SPI模块信息
+ * @spi_base 基地址
  */
-void spi_print_all_regs_info(ls1c_spi_info_t *spi_info_p)
+void ls1c_spi_print_all_regs_info(void *spi_base)
 {
-    void *spi_base = spi_get_base(spi_info_p->SPIx);
-
-    rt_kprintf("[%s] SPI%d's info:\r\n\
-              SPCR=0x%x, SPSR=0x%x, SPER=0x%x, SFC_PARAM=0x%x, SFC_SOFTCS=0x%x, SFC_TIMING=0x%x\r\n",
-              __FUNCTION__, spi_info_p->SPIx,
+    rt_kprintf("[%s] SPCR=0x%x, SPSR=0x%x, SPER=0x%x, SFC_PARAM=0x%x, SFC_SOFTCS=0x%x, SFC_TIMING=0x%x\r\n",
+              __FUNCTION__, 
               reg_read_8(spi_base + LS1C_SPI_SPCR_OFFSET),
               reg_read_8(spi_base + LS1C_SPI_SPSR_OFFSET),
               reg_read_8(spi_base + LS1C_SPI_SPER_OFFSET),
@@ -128,7 +85,7 @@ void spi_print_all_regs_info(ls1c_spi_info_t *spi_info_p)
  * @max_speed_hz SPI最大通信速度
  * @ret 分频系数
  */
-unsigned int spi_get_div(unsigned int max_speed_hz)
+unsigned int ls1c_spi_get_div(unsigned int max_speed_hz)
 {
     unsigned long clk = 0;
     unsigned int div = 0;
@@ -189,16 +146,16 @@ unsigned int spi_get_div(unsigned int max_speed_hz)
 
 /*
  * 设置时钟
- * @spi_info_p SPI模块信息
+ * @spi_base 基地址
+ * @max_hz 最大频率,单位hz
  */
-void spi_set_clock(ls1c_spi_info_t *spi_info_p)
+void ls1c_spi_set_clock(void *spi_base, unsigned long max_hz)
 {
-    void *spi_base = spi_get_base(spi_info_p->SPIx);
     unsigned int div = 0;
     unsigned char val = 0;
 
     // 获取分频系数
-    div = spi_get_div(spi_info_p->max_speed_hz);
+    div = ls1c_spi_get_div(max_hz);
 
     // 设置spr
     val = reg_read_8(spi_base + LS1C_SPI_SPCR_OFFSET);
@@ -218,22 +175,23 @@ void spi_set_clock(ls1c_spi_info_t *spi_info_p)
 
 /*
  * 设置通信模式(时钟极性和相位)
- * @spi_info_p SPI模块信息
+ * @spi_base 基地址
+ * @cpol 时钟极性
+ * @cpha 时钟相位
  */
-void spi_set_mode(ls1c_spi_info_t *spi_info_p)
+void ls1c_spi_set_mode(void *spi_base, unsigned char cpol, unsigned char cpha)
 {
-    void *spi_base = spi_get_base(spi_info_p->SPIx);
     unsigned char val = 0;
 
     val = reg_read_8(spi_base + LS1C_SPI_SPCR_OFFSET);
     
     // 设置时钟极性--cpol
-    val &= (~LS1C_SPI_SPCR_CPOL_MASK);                      // cpol清0
-    val |= (spi_info_p->cpol << LS1C_SPI_SPCR_CPOL_BIT);    // 写入新的cpol
+    val &= (~LS1C_SPI_SPCR_CPOL_MASK);                  // cpol清0
+    val |= (cpol << LS1C_SPI_SPCR_CPOL_BIT);            // 写入新的cpol
     
     // 设置时钟相位--cpha
-    val &= (~LS1C_SPI_SPCR_CPHA_MASK);                      // cpha清0
-    val |= (spi_info_p->cpha << LS1C_SPI_SPCR_CPHA_BIT);    // 写入新的cpha
+    val &= (~LS1C_SPI_SPCR_CPHA_MASK);                  // cpha清0
+    val |= (cpha << LS1C_SPI_SPCR_CPHA_BIT);            // 写入新的cpha
     
     reg_write_8(val, spi_base + LS1C_SPI_SPCR_OFFSET);
 
@@ -243,13 +201,12 @@ void spi_set_mode(ls1c_spi_info_t *spi_info_p)
 
 /*
  * 设置指定片选为指定状态
- * @spi_info_p SPI模块信息
+ * @spi_base 基地址
+ * @cs 片选
  * @new_status 片选引脚的新状态,取值为0或1,即高电平或低电平
  */
-void spi_set_cs(ls1c_spi_info_t *spi_info_p, int new_status)
+void ls1c_spi_set_cs(void *spi_base, unsigned char cs, int new_status)
 {
-    void *spi_base = spi_get_base(spi_info_p->SPIx);
-    unsigned char cs = spi_info_p->cs;
     unsigned char val = 0;
 
     val = 0xf0 | (0x01 << cs);          // 全部csn=1,指定的csen=1
@@ -267,51 +224,12 @@ void spi_set_cs(ls1c_spi_info_t *spi_info_p, int new_status)
 }
 
 
-/*
- * 初始化指定SPI模块
- * @spi_info_p SPI模块信息
- */
-void spi_init(ls1c_spi_info_t *spi_info_p)
-{
-    void *spi_base = spi_get_base(spi_info_p->SPIx);
-    unsigned char val = 0;
-
-    // 使能SPI控制器,master模式,关闭中断
-    reg_write_8(0x53, spi_base + LS1C_SPI_SPCR_OFFSET);
-
-    // 清空状态寄存器
-    reg_write_8(0xc0, spi_base + LS1C_SPI_SPSR_OFFSET);
-
-    // 1字节产生中断,采样(读)与发送(写)时机同时
-    reg_write_8(0x03, spi_base + LS1C_SPI_SPER_OFFSET);
-
-    // 关闭SPI flash
-    val = reg_read_8(spi_base + LS1C_SPI_SFC_PARAM_OFFSET);
-    val &= 0xfe;
-    reg_write_8(val, spi_base + LS1C_SPI_SFC_PARAM_OFFSET);
-
-    // spi flash时序控制寄存器
-    reg_write_8(0x05, spi_base + LS1C_SPI_SFC_TIMING_OFFSET);
-
-    // 设置时钟
-    spi_set_clock(spi_info_p);
-
-    // 设置通信模式(时钟极性和相位)
-    spi_set_mode(spi_info_p);
-
-    // 打印寄存器信息(用于调试)
-//    spi_print_all_regs_info(spi_info_p);
-
-    return ;
-}
-
-
 /*
  * 等待收发完成
+ * @spi_base 基地址
  */
-inline void spi_wait_txrx_done(ls1c_spi_info_t *spi_info_p)
+inline void ls1c_spi_wait_txrx_done(void *spi_base)
 {
-    void *spi_base = spi_get_base(spi_info_p->SPIx);
     int timeout = LS1C_SPI_TX_TIMEOUT;
 
     while (timeout--)
@@ -326,10 +244,10 @@ inline void spi_wait_txrx_done(ls1c_spi_info_t *spi_info_p)
 
 /*
  * 清中断和标志位
+ * @spi_base 基地址
  */
-inline void spi_clear(ls1c_spi_info_t *spi_info_p)
+inline void ls1c_spi_clear(void *spi_base)
 {
-    void *spi_base = spi_get_base(spi_info_p->SPIx);
     unsigned char val = 0;
 
     // 清中断
@@ -356,20 +274,19 @@ inline void spi_clear(ls1c_spi_info_t *spi_info_p)
  * 注意,在多任务的系统中,此函数需要互斥。
  * 即保证在和某个从设备收发某个字节的过程中,不能被切换到其它任务同时与另外的在同一个SPI总线上的从设备通信
  * 因为龙芯1c的每路SPI上可能接有不同的从设备,通信频率、模式等可能不同
- * @spi_info_p SPI接口
+ * @spi_base 基地址
  * @tx_ch 待发送的数据
  * @ret 收到的数据
  */
-unsigned char spi_txrx_byte(ls1c_spi_info_t *spi_info_p, unsigned char tx_ch)
+unsigned char ls1c_spi_txrx_byte(void *spi_base, unsigned char tx_ch)
 {
-    void *spi_base = spi_get_base(spi_info_p->SPIx);
     unsigned char rx_ch = 0;
 
     // 收发数据
     reg_write_8(tx_ch, spi_base + LS1C_SPI_TxFIFO_OFFSET);      // 开始发送
-    spi_wait_txrx_done(spi_info_p);                             // 等待收发完成
+    ls1c_spi_wait_txrx_done(spi_base);                          // 等待收发完成
     rx_ch = reg_read_8(spi_base + LS1C_SPI_RxFIFO_OFFSET);      // 读取收到的数据
-    spi_clear(spi_info_p);                                      // 清中断和标志位
+    ls1c_spi_clear(spi_base);                                   // 清中断和标志位
 
     return rx_ch;
 }

+ 71 - 25
bsp/ls1cdev/libraries/ls1c_spi.h

@@ -29,15 +29,10 @@
 
 
 // SPI模块编号
-typedef enum
-{
-    LS1C_SPI_0 = 0,
-    LS1C_SPI_1,
-}ls1c_spi_t;
-
+#define LS1C_SPI_0                      (0)
+#define LS1C_SPI_1                      (1)
 
 // 片选
-#define LS1C_SPI_INVALID_CS             (-1)
 #define LS1C_SPI_CS_0                   (0)
 #define LS1C_SPI_CS_1                   (1)
 #define LS1C_SPI_CS_2                   (2)
@@ -50,31 +45,80 @@ typedef enum
 #define SPI_CPHA_0                      (0)
 
 
-// 硬件SPI信息
-typedef struct
-{
-    ls1c_spi_t SPIx;                    // SPI模块编号
-    unsigned long max_speed_hz;         // 最大通信速度,单位hz
-    unsigned char cs;                   // 片选
-    unsigned char cpol;                 // 时钟极性
-    unsigned char cpha;                 // 时钟相位
-}ls1c_spi_info_t;
+// 寄存器偏移
+#define LS1C_SPI_SPCR_OFFSET                (0)     // 控制寄存器
+#define LS1C_SPI_SPSR_OFFSET                (1)     // 状态寄存器
+#define LS1C_SPI_TxFIFO_OFFSET              (2)     // 发送的数据寄存器,与接收数据寄存器的偏移相同
+#define LS1C_SPI_RxFIFO_OFFSET              (2)     // 接收的数据寄存器,与发送数据寄存器的偏移相同
+#define LS1C_SPI_SPER_OFFSET                (3)     // 外部寄存器
+#define LS1C_SPI_SFC_PARAM_OFFSET           (4)     // 参数控制寄存器
+#define LS1C_SPI_SFC_SOFTCS_OFFSET          (5)     // 片选控制寄存器
+#define LS1C_SPI_SFC_TIMING_OFFSET          (6)     // 时序控制寄存器
+
+// 寄存器SPCR中的位域
+#define LS1C_SPI_SPCR_SPIE_BIT              (7)
+#define LS1C_SPI_SPCR_SPIE_MASK             (0x01 << LS1C_SPI_SPCR_SPIE_BIT)
+#define LS1C_SPI_SPCR_SPE_BIT               (6)
+#define LS1C_SPI_SPCR_SPE_MASK              (0x01 << LS1C_SPI_SPCR_SPE_BIT)
+#define LS1C_SPI_SPCR_CPOL_BIT              (3)
+#define LS1C_SPI_SPCR_CPOL_MASK             (0x01 << LS1C_SPI_SPCR_CPOL_BIT)
+#define LS1C_SPI_SPCR_CPHA_BIT              (2)
+#define LS1C_SPI_SPCR_CPHA_MASK             (0x01 << LS1C_SPI_SPCR_CPHA_BIT)
+#define LS1C_SPI_SPCR_SPR_BIT               (0)
+#define LS1C_SPI_SPCR_SPR_MASK              (0x03 << LS1C_SPI_SPCR_SPR_BIT)
+
+// 寄存器SPSR中的位域
+#define LS1C_SPI_SPSR_SPIF_BIT              (7)
+#define LS1C_SPI_SPSR_SPIF_MASK             (0x01 << LS1C_SPI_SPSR_SPIF_BIT)
+#define LS1C_SPI_SPSR_WCOL_BIT              (6)
+#define LS1C_SPI_SPSR_WCOL_MASK             (0x01 << LS1C_SPI_SPSR_WCOL_BIT)
+
+// 寄存器SPER中的位域
+#define LS1C_SPI_SPER_SPRE_BIT              (0)
+#define LS1C_SPI_SPER_SPRE_MASK             (0x3 << LS1C_SPI_SPER_SPRE_BIT)
+
+// 寄存器SFC_SOFTCS的位域
+#define LS1C_SPI_SFC_SOFTCS_CSN_BIT         (4)
+#define LS1C_SPI_SFC_SOFTCS_CSN_MASK        (0x0f << LS1C_SPI_SFC_SOFTCS_CSN_BIT)
+#define LS1C_SPI_SFC_SOFTCS_CSEN_BIT        (0)
+#define LS1C_SPI_SFC_SOFTCS_CSEN_MASK       (0x0f << LS1C_SPI_SFC_SOFTCS_CSEN_BIT)
+
+// 发送超时的门限值
+#define LS1C_SPI_TX_TIMEOUT                 (20000)
+
+
 
+/*
+ * 获取指定SPI模块的基地址
+ * @SPIx SPI模块的编号
+ */
+inline void *ls1c_spi_get_base(unsigned char SPIx);
 
 
 /*
- * 初始化指定SPI模块
- * @spi_info_p SPI模块信息
+ * 设置时钟
+ * @spi_base 基地址
+ * @max_hz 最大频率,单位hz
  */
-void spi_init(ls1c_spi_info_t *spi_info_p);
+void ls1c_spi_set_clock(void *spi_base, unsigned long max_hz);
+
+
+/*
+ * 设置通信模式(时钟极性和相位)
+ * @spi_base 基地址
+ * @cpol 时钟极性
+ * @cpha 时钟相位
+ */
+void ls1c_spi_set_mode(void *spi_base, unsigned char cpol, unsigned char cpha);
 
 
 /*
  * 设置指定片选为指定状态
- * @spi_info_p SPI模块信息
+ * @spi_base 基地址
+ * @cs 片选
  * @new_status 片选引脚的新状态,取值为0或1,即高电平或低电平
  */
-void spi_set_cs(ls1c_spi_info_t *spi_info_p, int new_status);
+void ls1c_spi_set_cs(void *spi_base, unsigned char cs, int new_status);
 
 
 /*
@@ -82,18 +126,20 @@ void spi_set_cs(ls1c_spi_info_t *spi_info_p, int new_status);
  * 注意,在多任务的系统中,此函数需要互斥。
  * 即保证在和某个从设备收发某个字节的过程中,不能被切换到其它任务同时与另外的在同一个SPI总线上的从设备通信
  * 因为龙芯1c的每路SPI上可能接有不同的从设备,通信频率、模式等可能不同
- * @spi_info_p SPI接口
+ * @spi_base 基地址
  * @tx_ch 待发送的数据
  * @ret 收到的数据
  */
-unsigned char spi_txrx_byte(ls1c_spi_info_t *spi_info_p, unsigned char tx_ch);
+unsigned char ls1c_spi_txrx_byte(void *spi_base, unsigned char tx_ch);
 
 
 /*
  * 打印指定SPI模块的所有寄存器的值
- * @spi_info_p SPI模块信息
+ * @spi_base 基地址
  */
-void spi_print_all_regs_info(ls1c_spi_info_t *spi_info_p);
+void ls1c_spi_print_all_regs_info(void *spi_base);
+
+
 
 
 #endif

+ 5 - 0
bsp/ls1cdev/rtconfig.h

@@ -227,6 +227,11 @@
 #define RTGUI_IMAGE_BMP
 // </section>
 
+#define RT_USING_SPI
+#define RT_USING_SPI0
+#define RT_USING_SPI1
+
+
 // </RDTConfigurator>
 
 #endif