• Ecos3.0 Spi Driver for Leon3


    为了对原来的spi裸驱进行升级,将移植到leon3的ecos版本从2.0升级到3.0,并利用ecos的io系统编写新的spi驱动,以提高io吞吐率,保证线程安全。

    Ecos spi驱动作为spi基本的字符驱动进行编写。

    1.建立系统目录。

      在./ecos-3.0/packages/devs/spi目录下建立driver packagedir。我的目录结构如下:

    xiaoyang@xiaoyang leon$ tree -L 5
    .
    `-- DE2-70
        `-- v3_0
            |-- cdl
            |   |-- spi_leon3.cdl
            |-- ChangeLog
            |-- include
            |   |-- spi_leon3.h
            |-- src
            |   |-- spi_leon3.c
            `-- tests
                |-- compile.log
                |-- loopback.c
                `-- spi_test.c

    6 directories, 19 files

    2.编写CDL配置脚本

      

     1 ##=============================================================================
    2 ##
    3 ## spi_leon3.cdl
    4 ##
    5 ## LEON3-WSN SPI driver configuration options.
    6 ##
    7 ##=============================================================================
    8 #######DESCRIPTIONBEGIN####
    9 ##
    10 ## Author(s): xiaoyang.yi
    11 ## Date: 2012-2-27
    12 ## Purpose: Configure leon3-wsn SPI driver.
    13 ##
    14 ######DESCRIPTIONEND####
    15 ##=============================================================================
    16
    17 cdl_package CYGPKG_DEVS_SPI_LEON3 {
    18 display "SPI driver for Leon3"
    19 include_dir cyg/io
    20 requires CYGPKG_IO
    21 compile -library=libextras.a spi_leon3.c
    22 description "SPI driver for Leon3"
    23
    24 cdl_component CYGPKG_DEVS_SPI_LEON3_OPTIONS {
    25 display "Compile Options"
    26 flavor none
    27 no_define
    28
    29 cdl_option CYGPKG_DEVS_SPI_LEON3_CFLAGS {
    30 display "Additional compiler flags"
    31 flavor data
    32 no_define
    33 default_value { "" }
    34 description "
    35 This option modifies the set of compiler flags for
    36 building the spi driver package. These flags
    37 are used in addition to the set of global flags."
    38 }
    39
    40 cdl_option CYGDAT_DEVS_SPI_LEON3_NAME {
    41 display "Device name for the spi driver"
    42 flavor data
    43 default_value {"\"/dev/spi\""}
    44 description " This option specifies the name of the spi device"
    45 }
    46
    47 cdl_option CYGNUM_DEVS_SPI_LEON3_DEBUG_MODE {
    48 display "Debug Message"
    49 default_value 0
    50 description "
    51 This option will enable the debug message outputing if set to 1,
    52 will disable the outputing if set to 0."
    53 }
    54 }
    55
    56 cdl_component CYGHWR_DEVS_SPI_LEON3_OPTIONS {
    57 display "Connection Options"
    58 flavor none
    59 no_define
    60
    61 cdl_option CYGNUM_DEVS_SPI_LEON3_EVENT_BUFFER_SIZE {
    62 display "Number of events the driver can buffer"
    63 flavor data
    64 legal_values 1 to 512
    65 default_value 32
    66 description "
    67 This option defines the size of the keypad device internal
    68 buffer. The cyg_io_read() function will return as many of these
    69 as there is space for in the buffer passed."
    70 }
    71
    72 cdl_option CYGNUM_DEVS_SPI_LEON3_MODE_SELECT {
    73 display "SPI Master/Slave Mode Select"
    74 flavor data
    75 legal_values { "MASTER" "SLAVE" }
    76 default_value {"MASTER"}
    77 description "
    78 This option select Master or Slave mode."
    79 }
    80 }
    81 }
    82 # EOF spi_leon3.cdl

      在configtool下的效果如下图:

      

     

    3.编写驱动程序代码.由于本工程原有的裸驱还未加上中断模式,所以ecos spi沿袭之前驱动代码并未提供中断模式供选择。

      头文件spi_leon3.h:

       

     1 /*
    2 * SPI deriver for ecos on DE2-70
    3 * xiaoyang
    4 * 2012-2-26 11:03 create it.
    5 * 2012-3-1 16:44 test ok.
    6 */
    7
    8 #ifndef CYGONCE_DEVS_SPI_LEON3_H
    9 #define CYGONCE_DEVS_SPI_LEON3_H
    10
    11 /* leon3 bus address*/
    12 #define SPI0_BASE 0x80000600
    13
    14 #define REG32(x) *((volatile unsigned long*)(x))
    15
    16 /* SPICTL Registers APB Address Offset */
    17 #define SPI_CAP 0x0
    18 #define SPI_MOD 0x20
    19 #define SPI_EVE 0x24
    20 #define SPI_MSK 0x28
    21 #define SPI_CMD 0x2C
    22 #define SPI_TX 0x30
    23 #define SPI_RX 0x34
    24 #define SPI_SLV 0x38
    25 /* Bit Definition of SPICTL Capability Register */
    26 #define SPI_CAP_REV 0x7F
    27 #define SPI_CAP_FDEPTH 0xFF00
    28 #define SPI_CAP_SSEN 0x10000
    29 #define SPI_CAP_ASELA 0x20000
    30 #define SPI_CAP_AMODE 0x40000
    31 #define SPI_CAP_TWEN 0x80000
    32 #define SPI_CAP_MAXWLEN 0xF00000
    33 #define SPI_CAP_SSSZ 0xFF000000
    34 /* Bit Definition of SPICTL Mode Register */
    35 #define SPI_MOD_TAC 0x10
    36 #define SPI_MOD_ASELDEL 0x60
    37 #define SPI_MOD_CG 0x780
    38 #define SPI_MOD_OD 0x1000
    39 #define SPI_MOD_FACT 0x2000
    40 #define SPI_MOD_ASEL 0x4000
    41 #define SPI_MOD_TW 0x8000
    42 #define SPI_MOD_PM 0xF0000 /* Prescale Module*/
    43 #define SPI_MOD_LEN 0xF00000
    44 #define SPI_MOD_EN 0x1000000
    45 #define SPI_MOD_MS 0x2000000 /* Master/Slave */
    46 #define SPI_MOD_REV 0x4000000
    47 #define SPI_MOD_DIV16 0x8000000
    48 #define SPI_MOD_CPHA 0x10000000
    49 #define SPI_MOD_CPOL 0x20000000
    50 #define SPI_MOD_LOOP 0x40000000
    51 #define SPI_MOD_AMEN 0x80000000
    52 /* Bit Definition of SPICTL Event Register */
    53 #define SPI_EVE_NF 0x100
    54 #define SPI_EVE_NE 0x200
    55 #define SPI_EVE_MME 0x400
    56 #define SPI_EVE_UR 0x800
    57 #define SPI_EVE_OV 0x1000
    58 #define SPI_EVE_LT 0x4000
    59 #define SPI_EVE_TIP 0x80000000 /* Transfer in Progress */
    60 /* Bit Definition of SPICTL Mask Register */
    61 #define SPI_MSK_NFE 0x100
    62 #define SPI_MSK_NEE 0x200
    63 #define SPI_MSK_MMEE 0x400
    64 #define SPI_MSK_UNE 0x800
    65 #define SPI_MSK_OVE 0x1000
    66 #define SPI_MSK_LTE 0x4000
    67 #define SPI_MSK_TIPE 0x80000000
    68 /* Bit Definition of SPICTL Command Register */
    69 #define SPI_CMD_LST 0x400000
    70 /* Bit Definition of SPICTL Slave Select Register */
    71 #define SPI_SLV_SSSZ 1
    72 #define SPI_SLV_SLVSEL (1<<SPI_SLV_SSSZ)-1
    73
    74 /* Some useful routines */
    75 #define SLV_SELECT() REG32(SPI_BASE+SPI_SLV) &= ~SPI_SLV_SLVSEL
    76 #define SLV_DESELECT() REG32(SPI_BASE+SPI_SLV) |= SPI_SLV_SLVSEL
    77
    78 #endif // CYGONCE_DEVS_SPI_CORTEXM_LEON3_H

     

    驱动主文件spi_leon3.c:

      1 /*
    2 * SPI deriver for ecos on DE2-70
    3 * xiaoyang
    4 * 2012-2-26 11:03 create it.
    5 * 2012-3-1 16:44 test ok.
    6 */
    7
    8 #include <pkgconf/hal.h> /*hal 的宏头文件,由系统自动生成*/
    9 #include <pkgconf/devs_spi_leon3.h> /* spi 驱动 cdl 文件宏头文件,由系统自动生成*/
    10 #include <cyg/infra/cyg_type.h> /* 定义类型*/
    11 #include <cyg/hal/hal_intr.h> /* 定义中断相关宏*/
    12 #include <cyg/hal/drv_api.h> /* 驱动程序头文件*/
    13 #include <cyg/error/codes.h> /* 定义错误常量,如 ENOERR*/
    14
    15 #if CYGNUM_DEVS_SPI_LEON3_DEBUG_MODE == 1
    16 #include <cyg/infra/testcase.h> /* 测试宏定义,如 CYG_TEST_CHECK*/
    17 #include <cyg/infra/diag.h> /* diag 函数声明*/
    18 #include <stdio.h> /* 调试函数如 printf 等声明*/
    19 #endif
    20
    21 #include <cyg/io/devtab.h> /* 设备 I/O 入口表定义及声明*/
    22 #include <cyg/io/spi_leon3.h> /* 定义 LEON3 的 SPI 模块相关常量,这里含 key*/
    23
    24 //-----------------------------------------------------------------------------------//
    25
    26 #define SPI0_REV 1 /* Reverse data*/
    27
    28 //-----------------------------------------------------------------------------------//
    29 // Functions in this module
    30 static Cyg_ErrNo spi_write (cyg_io_handle_t handle, void *buffer, cyg_uint32 * len);
    31 static Cyg_ErrNo spi_read (cyg_io_handle_t handle, void *buffer, cyg_uint32 * len);
    32 static Cyg_ErrNo spi_set_config (cyg_io_handle_t handle, cyg_uint32 key, const void *buffer, cyg_uint32 * len);
    33 static Cyg_ErrNo spi_get_config (cyg_io_handle_t handle, cyg_uint32 key, const void *buffer, cyg_uint32 * len);
    34 static bool spi_init (struct cyg_devtab_entry *tab);
    35 static Cyg_ErrNo spi_lookup (struct cyg_devtab_entry **tab, struct cyg_devtab_entry *st, const char *name);
    36
    37 /*old interface*/
    38 static void old_spi_init(unsigned long spi_base);
    39 static cyg_uint8 old_spi_xmit8(unsigned long spi_base, cyg_uint8 val);
    40
    41 /*xiaoyang add*/
    42 static cyg_bool _SPIDrv_is_open;
    43 static cyg_uint8 TxFlag,RxFlag;
    44 static cyg_sem_t sem_spi_data;
    45
    46 //-----------------------------------------------------------------------------------//
    47 CHAR_DEVIO_TABLE (
    48 leon3_spi_handlers, // SPI 设备 I/O 函数表句柄
    49 spi_write, // SPI 设备写函数
    50 spi_read, // SPI 设备读函数
    51 NULL, //
    52 spi_get_config, // SPI 读设备设置状态函数
    53 spi_set_config // SPI 设备设置函数
    54 );
    55
    56 CHAR_DEVTAB_ENTRY (
    57 leon3_spi_device, // SPI 设备表入口句柄
    58 CYGDAT_DEVS_SPI_LEON3_NAME, // 设备名,在 cdl 文件中进行宏定义
    59 NULL, //
    60 &leon3_spi_handlers, // SPI 设备 I/O 函数表句柄指针
    61 spi_init, // SPI 初始化函数
    62 spi_lookup, // SPI 设备查找函数
    63 NULL);
    64
    65 //-----------------------------------------------------------------------------------//
    66 static cyg_uint32 spi_INTService (cyg_uint32 vector, CYG_ADDRWORD data)
    67 {
    68 #if CYGNUM_DEVS_SPI_LEON3_DEBUG_MODE == 1
    69 /* check is ISR installed ok*/
    70 //CYG_TEST_CHECK (ISR_DATA == data, "Bad data passed to ISR");
    71 /* check IRQ43 INT*/
    72 CYG_TEST_CHECK (43 == vector, "Bad vector passed to ISR");
    73 printf ("Debug - spi Int Services\n");
    74 #endif
    75
    76 /* handling IRQ INT*/
    77 HAL_INTERRUPT_ACKNOWLEDGE (vector);
    78 /* if SND*/
    79 if (TxFlag == 1)
    80 {
    81 /* if SND_INT*/
    82 if ( 0)
    83 {
    84
    85 }
    86 }
    87 /* if REV*/
    88 if (RxFlag == 1)
    89 {
    90 /* if RCV_INT*/
    91 if (0)
    92 {
    93
    94 }
    95 }
    96 /* ISR return */
    97 return CYG_ISR_HANDLED;
    98 }
    99
    100 static Cyg_ErrNo spi_write (cyg_io_handle_t handle, void *buffer, cyg_uint32 * len)
    101 {
    102 #if CYGNUM_DEVS_SPI_LEON3_DEBUG_MODE == 1
    103 printf ("Debug - spi write data\n");
    104 #endif
    105
    106 cyg_uint8 *bp = (cyg_uint8 *)buffer;
    107 int i = 0;
    108
    109 /*wait semaphore*/
    110 cyg_semaphore_wait(&sem_spi_data);
    111
    112 for(i = 0; i < (*len); i++){
    113 old_spi_xmit8(SPI0_BASE,bp[i]);
    114 }
    115
    116 /*release semaphore*/
    117 cyg_semaphore_post(&sem_spi_data);
    118
    119 return ENOERR;
    120 }
    121
    122 /*
    123 * handle:
    124 * buffer: data
    125 * len: count byte of data to read
    126 */
    127 static Cyg_ErrNo spi_read (cyg_io_handle_t handle, void *buffer, cyg_uint32 * len)
    128 {
    129 #if CYGNUM_DEVS_SPI_LEON3_DEBUG_MODE == 1
    130 printf ("Debug - spi read data\n");
    131 #endif
    132
    133 cyg_uint8 *bp = (cyg_uint8 *)buffer;
    134 int i = 0;
    135
    136 /*wait semaphore*/
    137 cyg_semaphore_wait(&sem_spi_data);
    138
    139 for(i = 0; i < (*len); i++){
    140 bp[i] = old_spi_xmit8(SPI0_BASE,0);
    141 }
    142
    143 /*release semaphore*/
    144 cyg_semaphore_post(&sem_spi_data);
    145 return ENOERR;
    146 }
    147
    148
    149 /*
    150 * handle:
    151 * buffer: data
    152 * len: count byte of data to write
    153 */
    154 static Cyg_ErrNo spi_set_config (cyg_io_handle_t handle, cyg_uint32 key, const void *buffer, cyg_uint32 * len)
    155 {
    156 #if CYGNUM_DEVS_SPI_LEON3_DEBUG_MODE == 1
    157 printf ("Debug - spi Set Config\n");
    158 #endif
    159
    160 return ENOERR;
    161 }
    162
    163 static Cyg_ErrNo spi_get_config (cyg_io_handle_t handle, cyg_uint32 key, const void *buffer, cyg_uint32 * len)
    164 {
    165 return ENOERR;
    166 }
    167
    168 static bool spi_init (struct cyg_devtab_entry *tab)
    169 {
    170 #if CYGNUM_DEVS_SPI_LEON3_DEBUG_MODE == 1
    171 printf ("Debug - spi init\n");
    172 #endif
    173
    174 /*old spi init*/
    175 old_spi_init(SPI0_BASE);
    176
    177 /* init a semaphore*/
    178 cyg_semaphore_init(&sem_spi_data,0);
    179 /*
    180 * WARNNING:
    181 * release semaphore,you should do it for waking up the thread
    182 * who uses the semaphore.
    183 */
    184 cyg_semaphore_post(&sem_spi_data);
    185 return true;
    186 }
    187 /*
    188 *
    189 */
    190 static Cyg_ErrNo spi_lookup (struct cyg_devtab_entry **tab, struct cyg_devtab_entry *st, const char *name)
    191 {
    192 #if CYGNUM_DEVS_SPI_LEON3_DEBUG_MODE == 1
    193 printf ("Debug - spi Lookup\n");
    194 #endif
    195 return ENOERR;
    196 }
    197
    198
    199 //-----------------------------------------------------------------------------------//
    200 /*old complete*/
    201 /******************************************************************
    202 * Initialize the SPI Controller
    203 *
    204 *****************************************************************/
    205 void old_spi_init(unsigned long spi_base) {
    206 REG32(spi_base+SPI_CAP) = 0x01018002;
    207 /* Configure the capability register */
    208 /* SPI_CAP_FDEPTH = 0x80 => Support FIFO size = 128 */
    209 /* SPI_CAP_SSEN = 1 */
    210 /* SPI_CAP_MAXWLEN = 0x0 => Support 32-bit length */
    211 /* SPI_CAP_SSSZ = 0x01 */
    212
    213 #if SPI0_REV
    214 REG32(spi_base+SPI_MOD) |= 0x06740000;
    215 /* Configure the mode register */
    216 /* SPI_MOD_FACT = 0*/
    217 /* SPI_MOD_PM = 4 */
    218 /* SPI_MOD_LEN = 7 */
    219 /* SPI_MOD_EN = 0 */
    220 /* SPI_MOD_MS = 1 */
    221 /* SPI_MOD_REV = 0 */
    222 /* SPI_MOD_DIV16 = 0 */
    223 /* SPI_MOD_CPHA = 0 */
    224 /* SPI_MOD_CPOL = 0 */
    225 /* SPI_MOD_REV = 1 */ /* MSB transmitted first */
    226 // REG32(spi_base+SPI_MOD) |= SPI_MOD_CPOL;
    227 // REG32(spi_base+SPI_MOD) |= SPI_MOD_CPHA;
    228 #else //SPI_MOD_REV = 0, LSB transmitted first
    229 REG32(spi_base+SPI_MOD) |= 0x02740000;
    230 #endif // REV
    231 REG32(spi_base+SPI_MSK) = 0x0; /* Disable all interrupts */
    232 REG32(spi_base+SPI_MOD) |= SPI_MOD_EN; /* Activate Core */
    233 }
    234
    235 /********************************************************************
    236 * SPI TX and RX
    237 *
    238 *******************************************************************/
    239 cyg_uint8 old_spi_xmit8(unsigned long spi_base,cyg_uint8 val) {
    240 cyg_uint32 reg32;
    241 /* Wait for room */
    242 while(!(REG32(spi_base+SPI_EVE)&SPI_EVE_NF));
    243
    244 #if SPI0_REV
    245 REG32(spi_base+SPI_TX) = val<<24&0xFF000000;
    246 #else
    247 REG32(spi_base+SPI_TX) = val;
    248 #endif // REV
    249 //while(!(REG32(spi_base+SPI_EVE)&SPI_EVE_NE)); /* Wait for transmitting over */
    250 //while(!((REG32(spi_base+SPI_EVE)&SPI_EVE_LT)));
    251 while((REG32(spi_base+SPI_EVE)&SPI_EVE_TIP));
    252 reg32 = REG32(spi_base+SPI_RX);
    253 //printf("1st: 0x%x\n",reg32);
    254
    255 #if SPI0_REV
    256 return (cyg_uint8)((reg32>>16)&0xFF);
    257 #else
    258 return (cyg_uint8)((reg32>>8)&0xFF);
    259 #endif // REV
    260 }
    261
    262 cyg_uint16 old_spi_xmit16(unsigned long spi_base, cyg_uint16 val)
    263 {
    264 while(!(REG32(spi_base+SPI_EVE)&SPI_EVE_NF));
    265 #if SPI0_REV
    266 REG32(spi_base+SPI_TX) = val<<16&0xFFFF0000;
    267 #else
    268 REG32(spi_base+SPI_TX) = val;
    269 #endif // REV
    270 while((REG32(spi_base+SPI_EVE)&SPI_EVE_TIP));
    271 cyg_uint32 reg32 = REG32(spi_base+SPI_RX);
    272 //printf("back32: 0x%8x\n",reg32);
    273 #if SPI0_REV
    274 return (cyg_uint16)((reg32>>16)&0xFFFF);
    275 #else
    276 return (cyg_uint16)(reg32&0xFFFF);
    277 #endif // REV
    278 }
    279
    280 /*******************************************************************
    281 * Reconfigure SPI Mode Register
    282 *
    283 ******************************************************************/
    284 cyg_uint8 old_spi_reconfig(unsigned long spi_base,cyg_uint32 mask, cyg_uint32 val)
    285 {
    286 cyg_uint32 mod;
    287 if(REG32(spi_base+SPI_EVE)&SPI_EVE_TIP) {
    288 return -1;
    289 }
    290 /* Disable the SPI core */
    291 REG32(spi_base+SPI_MOD) &= (~SPI_MOD_EN);
    292
    293 mod = REG32(spi_base+SPI_MOD);
    294 mod = (mod & ~mask) | val;
    295 REG32(spi_base+SPI_MOD) = mod;
    296
    297 REG32(spi_base+SPI_MOD) |= SPI_MOD_EN;
    298 return 0;
    299 }
    300
    301
    302 //-----------------------------------------------------------------------------------//
    303 //end of file//
    304 //-----------------------------------------------------------------------------------//

    (如果想使用原生的spi驱动包可以使用ecosconfig工具建立ecc编译文件,./ecosconfig add CYGPKG_IO_SPI命令加入包)

    最后使用configtool将spi模块加载进去进行编译即可使用此驱动。

     

    下面是测试代码,即使用spi驱动的方法:

     1 // 定义 SPI 线程的句柄
    2 cyg_io_handle_t hDrvSPI;
    3
    4 // 通过 SPI 线程进行发送和接收数据
    5 void spi_thread(cyg_addrword_t data)
    6 {
    7 cyg_uint32 len = 1;
    8 cyg_uint32 RxData[1];
    9 cyg_uint32 TxData[1];
    10 TxData[0]=66;
    11 if (ENOERR != cyg_io_lookup("/dev/spi", &hDrvSPI))
    12 {
    13 CYG_TEST_FAIL_FINISH("Error opening /dev/spi");
    14 }
    15 printf("Open /dev/spi OK\n");
    16 while(true)
    17 {
    18 len = 1;
    19 // 通过 SPI 线程进行发送和接收数据
    20 if(ENOERR != cyg_io_write(hDrvSPI, TxData, &len))
    21 {
    22 CYG_TEST_FINISH("Error write /dev/spi");
    23 }
    24 printf("SPI TxNum = %d\n",len); // 返回实际发送数据量
    25 if(len != 0)
    26 {
    27 printf("SPI TxData = %d\n", TxData[0]);
    28 }
    29 // 调用 cyg_io_ read 接收数据
    30 if(ENOERR != cyg_io_read(hDrvSPI, RxData, &len))
    31 {
    32 CYG_TEST_FINISH("Error Read /dev/spi");
    33 }
    34 if(len != 0)
    35 {
    36 printf("SPI RxData = %d\n", RxData[0]);
    37 }
    38 // 线程睡眠
    39 cyg_thread_delay(10);
    40 }
    41 }


    spi驱动代码详情可在git-hub中找到:https://github.com/yixiaoyang/leon-wsn/tree/master/driver



  • 相关阅读:
    【Java】快速排序、归并排序、堆排序、基数排序实现总结
    【Java】二分查找、插值查找、斐波那契查找的实现,及分析
    【Java】Java实现常见的七种排序
    【C】常见的排序
    栈,迷宫问题
    海量数据处理问题
    【C】 布隆过滤器BloomFilter
    哈希变形---位图
    C实现Hash表,链式结构
    C实现Hash表,开放定址法
  • 原文地址:https://www.cnblogs.com/yixiaoyang/p/2375981.html
Copyright © 2020-2023  润新知