1212#include <zephyr/shell/shell.h>
1313#include <zephyr/sys/util.h>
1414
15- #define TXRX_ARGV_BYTES (1)
16- #define CONF_ARGV_DEV (1)
17- #define CONF_ARGV_FREQUENCY (2)
18- #define CONF_ARGV_SETTINGS (3)
15+ #define TXRX_ARGV_DEV (1)
16+ #define TXRX_ARGV_BYTES (2)
1917
2018/* Maximum bytes we can write and read at once */
2119#define MAX_SPI_BYTES MIN((CONFIG_SHELL_ARGC_MAX - TXRX_ARGV_BYTES), 32)
2220
23- static struct device * spi_device ;
24- static struct spi_config config = {.frequency = 1000000 ,
25- .operation = SPI_OP_MODE_MASTER | SPI_WORD_SET (8 )};
21+ #define SPIDEV_INST (node_id ) \
22+ { \
23+ .dev = DEVICE_DT_GET(node_id), \
24+ .spi = SPI_DT_SPEC_GET(node_id, SPI_WORD_SET(8) | SPI_OP_MODE_MASTER, 0), \
25+ },
2626
27- static void device_name_get (size_t idx , struct shell_static_entry * entry )
28- {
29- const struct device * dev = shell_device_lookup (idx , "spi" );
27+ #define IS_SPIDEV_NODE (node_id ) \
28+ COND_CODE_1(DT_NODE_HAS_PROP(node_id, spi_max_frequency), (SPIDEV_INST(node_id)), ())
29+
30+ static struct spidev {
31+ const struct device * dev ;
32+ const struct spi_dt_spec spi ;
3033
31- entry -> syntax = (dev != NULL ) ? dev -> name : NULL ;
32- entry -> handler = NULL ;
33- entry -> help = NULL ;
34- entry -> subcmd = NULL ;
34+ } spidev_list [] = {DT_FOREACH_STATUS_OKAY_NODE (IS_SPIDEV_NODE )};
35+
36+ static void get_spidev_comp (size_t idx , struct shell_static_entry * entry )
37+ {
38+ if (idx < ARRAY_SIZE (spidev_list )) {
39+ entry -> syntax = spidev_list [idx ].dev -> name ;
40+ entry -> handler = NULL ;
41+ entry -> subcmd = NULL ;
42+ entry -> help = "Select spi device." ;
43+ } else {
44+ entry -> syntax = NULL ;
45+ }
3546}
47+ SHELL_DYNAMIC_CMD_CREATE (dsub_spidev , get_spidev_comp );
3648
37- SHELL_DYNAMIC_CMD_CREATE (dsub_device_name , device_name_get );
49+ static struct spidev * get_spidev (const char * device_label )
50+ {
51+ for (int i = 0 ; i < ARRAY_SIZE (spidev_list ); i ++ ) {
52+ if (!strcmp (device_label , spidev_list [i ].dev -> name )) {
53+ return & spidev_list [i ];
54+ }
55+ }
3856
39- static int cmd_spi_transceive (const struct shell * ctx , size_t argc , char * * argv )
57+ /* This will never happen because was prompted by shell */
58+ __ASSERT_NO_MSG (false);
59+ return NULL ;
60+ }
61+ static int cmd_spi_transceive_dt (const struct shell * ctx , size_t argc , char * * argv )
4062{
4163 uint8_t rx_buffer [MAX_SPI_BYTES ] = {0 };
4264 uint8_t tx_buffer [MAX_SPI_BYTES ] = {0 };
4365
44- if (spi_device == NULL ) {
45- shell_error (ctx , "SPI device isn't configured. Use `spi conf`" );
46- return - ENODEV ;
47- }
66+ struct spidev * spidev = get_spidev (argv [TXRX_ARGV_DEV ]);
4867
4968 int bytes_to_send = argc - TXRX_ARGV_BYTES ;
50-
5169 for (int i = 0 ; i < bytes_to_send ; i ++ ) {
5270 tx_buffer [i ] = strtol (argv [TXRX_ARGV_BYTES + i ], NULL , 16 );
5371 }
@@ -58,8 +76,7 @@ static int cmd_spi_transceive(const struct shell *ctx, size_t argc, char **argv)
5876 const struct spi_buf_set tx_buf_set = {.buffers = & tx_buffers , .count = 1 };
5977 const struct spi_buf_set rx_buf_set = {.buffers = & rx_buffers , .count = 1 };
6078
61- int ret = spi_transceive (spi_device , & config , & tx_buf_set , & rx_buf_set );
62-
79+ int ret = spi_transceive_dt (& spidev -> spi , & tx_buf_set , & rx_buf_set );
6380 if (ret < 0 ) {
6481 shell_error (ctx , "spi_transceive returned %d" , ret );
6582 return ret ;
@@ -74,82 +91,12 @@ static int cmd_spi_transceive(const struct shell *ctx, size_t argc, char **argv)
7491 return ret ;
7592}
7693
77- static int cmd_spi_conf (const struct shell * ctx , size_t argc , char * * argv )
78- {
79- spi_operation_t operation = SPI_WORD_SET (8 ) | SPI_OP_MODE_MASTER ;
80-
81- /* warning: initialization discards 'const' qualifier from pointer */
82- /* target type */
83- struct device * dev = (struct device * )device_get_binding (argv [CONF_ARGV_DEV ]);
84-
85- if (dev == NULL ) {
86- shell_error (ctx , "device %s not found." , argv [CONF_ARGV_DEV ]);
87- return - ENODEV ;
88- }
89-
90- uint32_t frequency = strtol (argv [CONF_ARGV_FREQUENCY ], NULL , 10 );
91-
92- if (!IN_RANGE (frequency , 100 * 1000 , 80 * 1000 * 1000 )) {
93- shell_error (ctx , "frequency must be between 100000 and 80000000" );
94- return - EINVAL ;
95- }
96-
97- /* no settings */
98- if (argc == (CONF_ARGV_FREQUENCY + 1 )) {
99- goto out ;
100- }
101-
102- char * opts = argv [CONF_ARGV_SETTINGS ];
103- bool all_opts_is_valid = true;
104-
105- while (* opts != '\0' ) {
106- switch (* opts ) {
107- case 'o' :
108- operation |= SPI_MODE_CPOL ;
109- break ;
110- case 'h' :
111- operation |= SPI_MODE_CPHA ;
112- break ;
113- case 'l' :
114- operation |= SPI_TRANSFER_LSB ;
115- break ;
116- case 'T' :
117- operation |= SPI_FRAME_FORMAT_TI ;
118- break ;
119- default :
120- all_opts_is_valid = false;
121- shell_error (ctx , "invalid setting %c" , * opts );
122- }
123- opts ++ ;
124- }
125-
126- if (!all_opts_is_valid ) {
127- return - EINVAL ;
128- }
129-
130- out :
131- config .frequency = frequency ;
132- config .operation = operation ;
133- spi_device = dev ;
134-
135- return 0 ;
136- }
137-
138- SHELL_STATIC_SUBCMD_SET_CREATE (sub_spi_cmds ,
139- SHELL_CMD_ARG (conf , & dsub_device_name ,
140- "Configure SPI\n"
141- "Usage: spi conf <device> <frequency> [<settings>]\n"
142- "<settings> - any sequence of letters:\n"
143- "o - SPI_MODE_CPOL\n"
144- "h - SPI_MODE_CPHA\n"
145- "l - SPI_TRANSFER_LSB\n"
146- "T - SPI_FRAME_FORMAT_TI\n"
147- "example: spi conf spi1 1000000 ol" ,
148- cmd_spi_conf , 3 , 1 ),
149- SHELL_CMD_ARG (transceive , NULL ,
150- "Transceive data to and from an SPI device\n"
151- "Usage: spi transceive <TX byte 1> [<TX byte 2> ...]" ,
152- cmd_spi_transceive , 2 , MAX_SPI_BYTES - 1 ),
153- SHELL_SUBCMD_SET_END );
94+ SHELL_STATIC_SUBCMD_SET_CREATE (
95+ sub_spi_cmds ,
96+ SHELL_CMD_ARG (transceive , & dsub_spidev ,
97+ "Transceive data to and from an SPI device\n"
98+ "Usage: spi transceive <node> <TX byte 1> [<TX byte 2> ...]" ,
99+ cmd_spi_transceive_dt , 3 , MAX_SPI_BYTES - 1 ),
100+ SHELL_SUBCMD_SET_END );
154101
155102SHELL_CMD_REGISTER (spi , & sub_spi_cmds , "SPI commands" , NULL );
0 commit comments