guowenxue
2024-09-27 10a1a347aa6fa60aa0dd667a4d892aaced108121
commit | author | age
1e563e 1 /*********************************************************************************
G 2  *      Copyright:  (C) 2024 LingYun IoT System Studio
3  *                  All rights reserved.
4  *
5  *       Filename:  spi_test.c
6  *    Description:  This file is SPI loop test program
7  *
8  *        Version:  1.0.0(05/23/2024)
9  *         Author:  Guo Wenxue <guowenxue@gmail.com>
10  *      ChangeLog:  1, Release initial version on "05/23/2024 07:51:06 PM"
11  *
12  ********************************************************************************/
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdint.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <getopt.h>
21 #include <libgen.h>
22 #include <fcntl.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <sys/ioctl.h>
26 #include <linux/spi/spidev.h>
27
28 typedef struct spi_ctx_s
29 {
30     int         fd;
31     char        dev[64];
32     uint8_t     bits;
33     uint16_t    delay;
34     uint32_t    mode;
35     uint32_t    speed;
36 } spi_ctx_t;
37
38 static int spi_init(spi_ctx_t *spi_ctx);
39 static int transfer(spi_ctx_t *spi_ctx, uint8_t const *tx, uint8_t const *rx, size_t len);
40
41 static void program_usage(char *progname)
42 {
43     printf("Usage: %s [OPTION]...\n", progname);
44     printf(" %s is a program to test IGKBoard loop spi\n", progname);
45
46     printf("\nMandatory arguments to long options are mandatory for short options too:\n");
47     printf(" -d[device  ]  Specify SPI device, such as: /dev/spidev0.0\n");
48     printf(" -s[speed   ]  max speed (Hz), such as: -s 500000\n");
49     printf(" -p[print   ]  Send data (such as: -p 1234/xde/xad)\n");
50
51     printf("\n%s version 1.0\n", progname);
52     return;
53 }
54
55 int main(int argc,char * argv[])
56 {
57     spi_ctx_t          spi_ctx;
58     uint32_t           spi_speed = 500000;  // Default SPI speed 500KHz
59     char              *spi_dev = "/dev/spidev0.0"; // Default SPI device
60     char              *input_tx = "Hello LingYun"; // Default transfer data
61     uint8_t            rx_buffer[128];
62     int                opt;
63     char               *progname=NULL;
64
65     struct option long_options[] = {
66         {"device", required_argument, NULL, 'd'},
67         {"speed", required_argument, NULL, 's'},
68         {"print", required_argument, NULL, 'p'},
69         {"help", no_argument, NULL, 'h'},
70         {NULL, 0, NULL, 0}
71     };
72
73     progname = (char *)basename(argv[0]);
74
75     while((opt = getopt_long(argc, argv, "d:s:p:h", long_options, NULL)) != -1)
76     {
77         switch (opt)
78         {
79         case 'd':
80             spi_dev = optarg;
81             break;
82
83         case 's':
84             spi_speed = atoi(optarg);
85             break;
86
87         case 'p':
88             input_tx = optarg;
89             break;
90
91         case 'h':
92             program_usage(progname);
93             return 0;
94
95         default:
96             break;
97         }
98     }
99
100     memset(&spi_ctx, 0, sizeof(spi_ctx));
101     strncpy(spi_ctx.dev, spi_dev, sizeof(spi_ctx.dev));
102     spi_ctx.bits = 8;
103     spi_ctx.delay = 100;
104     spi_ctx.mode = SPI_MODE_2;
105     spi_ctx.speed = spi_speed;
106
107     if( spi_init(&spi_ctx) < 0 )
108     {
109         printf("Initial SPI device '%s' failed.\n", spi_ctx.dev);
110         return -1;
111     }
112     printf("Initial SPI device '%s' okay.\n", spi_ctx.dev);
113
114     if ( transfer(&spi_ctx, input_tx, rx_buffer, strlen(input_tx)) < 0 )
115     {
116         printf("spi transfer error\n");
117         return -2;
118     }
119
120     printf("tx_buffer: | %s |\n", input_tx);
121     printf("rx_buffer: | %s |\n", rx_buffer);
122
123     return 0;
124 }
125
126 int transfer(spi_ctx_t *spi_ctx, uint8_t const *tx, uint8_t const *rx, size_t len)
127 {
128     struct spi_ioc_transfer tr = {
129         .tx_buf = (unsigned long )tx,
130         .rx_buf = (unsigned long )rx,
131         .len = len,
132         .delay_usecs = spi_ctx->delay,
133         .speed_hz = spi_ctx->speed,
134         .bits_per_word = spi_ctx->bits,
135     };
136
137     if( ioctl(spi_ctx->fd, SPI_IOC_MESSAGE(1), &tr) < 0)
138     {
139         printf("ERROR: SPI transfer failure: %s\n ", strerror(errno));
140         return -1;
141     }
142
143     return 0;
144 }
145
146 int spi_init(spi_ctx_t *spi_ctx)
147 {
148     int ret;
149     spi_ctx->fd = open(spi_ctx->dev, O_RDWR);
150     if(spi_ctx->fd < 0)
151     {
152         printf("open %s error\n", spi_ctx->dev);
153         return -1;
154     }
155
156     ret = ioctl(spi_ctx->fd, SPI_IOC_RD_MODE, &spi_ctx->mode);
157     if( ret < 0 )
158     {
159         printf("ERROR: SPI set SPI_IOC_RD_MODE [0x%x] failure: %s\n ", spi_ctx->mode, strerror(errno));
160         goto cleanup;
161     }
162
163     ret = ioctl(spi_ctx->fd, SPI_IOC_WR_MODE, &spi_ctx->mode);
164     if( ret < 0 )
165     {
166         printf("ERROR: SPI set SPI_IOC_WR_MODE [0x%x] failure: %s\n ", spi_ctx->mode, strerror(errno));
167         goto cleanup;
168     }
169
170     ret = ioctl(spi_ctx->fd, SPI_IOC_RD_BITS_PER_WORD, &spi_ctx->bits);
171     if( ret < 0 )
172     {
173         printf("ERROR: SPI set SPI_IOC_RD_BITS_PER_WORD [%d] failure: %s\n ", spi_ctx->bits, strerror(errno));
174         goto cleanup;
175     }
176     ret = ioctl(spi_ctx->fd, SPI_IOC_WR_BITS_PER_WORD, &spi_ctx->bits);
177     if( ret < 0 )
178     {
179         printf("ERROR: SPI set SPI_IOC_WR_BITS_PER_WORD [%d] failure: %s\n ", spi_ctx->bits, strerror(errno));
180         goto cleanup;
181     }
182
183     ret = ioctl(spi_ctx->fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_ctx->speed);
184     if( ret == -1)
185     {
186         printf("ERROR: SPI set SPI_IOC_WR_MAX_SPEED_HZ [%d] failure: %s\n ", spi_ctx->speed, strerror(errno));
187         goto cleanup;
188     }
189     ret = ioctl(spi_ctx->fd, SPI_IOC_RD_MAX_SPEED_HZ, &spi_ctx->speed);
190     if( ret == -1)
191     {
192         printf("ERROR: SPI set SPI_IOC_RD_MAX_SPEED_HZ [%d] failure: %s\n ", spi_ctx->speed, strerror(errno));
193         goto cleanup;
194     }
195
196     printf("spi mode: 0x%x\n", spi_ctx->mode);
197     printf("bits per word: %d\n", spi_ctx->bits);
198     printf("max speed: %d Hz (%d KHz)\n", spi_ctx->speed, spi_ctx->speed / 1000);
199
200    return spi_ctx->fd;
201
202 cleanup:
203    close(spi_ctx->fd);
204    return -1;
205 }