]> granicus.if.org Git - esp-idf/blob - examples/peripherals/spi_slave/receiver/main/app_main.c
spi_slave: fix a example issue caused by word alignment
[esp-idf] / examples / peripherals / spi_slave / receiver / main / app_main.c
1 /* SPI Slave example, receiver (uses SPI Slave driver to communicate with sender)
2
3    This example code is in the Public Domain (or CC0 licensed, at your option.)
4
5    Unless required by applicable law or agreed to in writing, this
6    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7    CONDITIONS OF ANY KIND, either express or implied.
8 */
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <stddef.h>
12 #include <string.h>
13
14 #include "freertos/FreeRTOS.h"
15 #include "freertos/task.h"
16 #include "freertos/semphr.h"
17 #include "freertos/queue.h"
18
19 #include "lwip/sockets.h"
20 #include "lwip/dns.h"
21 #include "lwip/netdb.h"
22 #include "lwip/igmp.h"
23
24 #include "esp_wifi.h"
25 #include "esp_system.h"
26 #include "esp_event.h"
27 #include "esp_event_loop.h"
28 #include "nvs_flash.h"
29 #include "soc/rtc_periph.h"
30 #include "esp32/rom/cache.h"
31 #include "driver/spi_slave.h"
32 #include "esp_log.h"
33 #include "esp_spi_flash.h"
34 #include "driver/gpio.h"
35
36
37
38
39 /*
40 SPI receiver (slave) example.
41
42 This example is supposed to work together with the SPI sender. It uses the standard SPI pins (MISO, MOSI, SCLK, CS) to
43 transmit data over in a full-duplex fashion, that is, while the master puts data on the MOSI pin, the slave puts its own
44 data on the MISO pin.
45
46 This example uses one extra pin: GPIO_HANDSHAKE is used as a handshake pin. After a transmission has been set up and we're
47 ready to send/receive data, this code uses a callback to set the handshake pin high. The sender will detect this and start
48 sending a transaction. As soon as the transaction is done, the line gets set low again.
49 */
50
51 /*
52 Pins in use. The SPI Master can use the GPIO mux, so feel free to change these if needed.
53 */
54 #define GPIO_HANDSHAKE 2
55 #define GPIO_MOSI 12
56 #define GPIO_MISO 13
57 #define GPIO_SCLK 15
58 #define GPIO_CS 14
59
60
61 //Called after a transaction is queued and ready for pickup by master. We use this to set the handshake line high.
62 void my_post_setup_cb(spi_slave_transaction_t *trans) {
63     WRITE_PERI_REG(GPIO_OUT_W1TS_REG, (1<<GPIO_HANDSHAKE));
64 }
65
66 //Called after transaction is sent/received. We use this to set the handshake line low.
67 void my_post_trans_cb(spi_slave_transaction_t *trans) {
68     WRITE_PERI_REG(GPIO_OUT_W1TC_REG, (1<<GPIO_HANDSHAKE));
69 }
70
71 //Main application
72 void app_main()
73 {
74     int n=0;
75     esp_err_t ret;
76
77     //Configuration for the SPI bus
78     spi_bus_config_t buscfg={
79         .mosi_io_num=GPIO_MOSI,
80         .miso_io_num=GPIO_MISO,
81         .sclk_io_num=GPIO_SCLK
82     };
83
84     //Configuration for the SPI slave interface
85     spi_slave_interface_config_t slvcfg={
86         .mode=0,
87         .spics_io_num=GPIO_CS,
88         .queue_size=3,
89         .flags=0,
90         .post_setup_cb=my_post_setup_cb,
91         .post_trans_cb=my_post_trans_cb
92     };
93
94     //Configuration for the handshake line
95     gpio_config_t io_conf={
96         .intr_type=GPIO_INTR_DISABLE,
97         .mode=GPIO_MODE_OUTPUT,
98         .pin_bit_mask=(1<<GPIO_HANDSHAKE)
99     };
100
101     //Configure handshake line as output
102     gpio_config(&io_conf);
103     //Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected.
104     gpio_set_pull_mode(GPIO_MOSI, GPIO_PULLUP_ONLY);
105     gpio_set_pull_mode(GPIO_SCLK, GPIO_PULLUP_ONLY);
106     gpio_set_pull_mode(GPIO_CS, GPIO_PULLUP_ONLY);
107
108     //Initialize SPI slave interface
109     ret=spi_slave_initialize(HSPI_HOST, &buscfg, &slvcfg, 1);
110     assert(ret==ESP_OK);
111
112     WORD_ALIGNED_ATTR char sendbuf[129]="";
113     WORD_ALIGNED_ATTR char recvbuf[129]="";
114     memset(recvbuf, 0, 33);
115     spi_slave_transaction_t t;
116     memset(&t, 0, sizeof(t));
117
118     while(1) {
119         //Clear receive buffer, set send buffer to something sane
120         memset(recvbuf, 0xA5, 129);
121         sprintf(sendbuf, "This is the receiver, sending data for transmission number %04d.", n);
122
123         //Set up a transaction of 128 bytes to send/receive
124         t.length=128*8;
125         t.tx_buffer=sendbuf;
126         t.rx_buffer=recvbuf;
127         /* This call enables the SPI slave interface to send/receive to the sendbuf and recvbuf. The transaction is
128         initialized by the SPI master, however, so it will not actually happen until the master starts a hardware transaction
129         by pulling CS low and pulsing the clock etc. In this specific example, we use the handshake line, pulled up by the
130         .post_setup_cb callback that is called as soon as a transaction is ready, to let the master know it is free to transfer
131         data.
132         */
133         ret=spi_slave_transmit(HSPI_HOST, &t, portMAX_DELAY);
134
135         //spi_slave_transmit does not return until the master has done a transmission, so by here we have sent our data and
136         //received data from the master. Print it.
137         printf("Received: %s\n", recvbuf);
138         n++;
139     }
140
141 }
142
143