1 /**
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 * Description: SPI Sample Source. \n
16 *
17 * History: \n
18 * 2023-06-25, Create file. \n
19 */
20 #include "pinctrl.h"
21 #include "spi.h"
22 #include "soc_osal.h"
23 #include "app_init.h"
24
25 #define SPI_SLAVE_NUM 1
26 #define SPI_FREQUENCY 2
27 #define SPI_CLK_POLARITY 0
28 #define SPI_CLK_PHASE 0
29 #define SPI_FRAME_FORMAT 0
30 #define SPI_FRAME_FORMAT_STANDARD 0
31 #define SPI_FRAME_SIZE_8 0x1f
32 #define SPI_TMOD 0
33 #define SPI_WAIT_CYCLES 0x10
34 #if defined(CONFIG_SPI_SUPPORT_DMA) && !(defined(CONFIG_SPI_SUPPORT_POLL_AND_DMA_AUTO_SWITCH))
35 #define SPI_DMA_WIDTH 2
36 #endif
37
38 #define SPI_TASK_DURATION_MS 500
39 #define SPI_TASK_PRIO 24
40 #define SPI_TASK_STACK_SIZE 0x1000
41
app_spi_init_pin(void)42 static void app_spi_init_pin(void)
43 {
44 uapi_pin_set_mode(CONFIG_SPI_DI_SLAVE_PIN, CONFIG_SPI_SLAVE_PIN_MODE);
45 uapi_pin_set_mode(CONFIG_SPI_DO_SLAVE_PIN, CONFIG_SPI_SLAVE_PIN_MODE);
46 uapi_pin_set_mode(CONFIG_SPI_CLK_SLAVE_PIN, CONFIG_SPI_SLAVE_PIN_MODE);
47 uapi_pin_set_mode(CONFIG_SPI_CS_SLAVE_PIN, CONFIG_SPI_SLAVE_PIN_MODE);
48 }
49
50 #if defined(CONFIG_SPI_SUPPORT_INTERRUPT) && (CONFIG_SPI_SUPPORT_INTERRUPT == 1)
app_spi_slave_write_int_handler(const void * buffer,uint32_t length)51 static void app_spi_slave_write_int_handler(const void *buffer, uint32_t length)
52 {
53 unused(buffer);
54 unused(length);
55 osal_printk("spi slave write interrupt start!\r\n");
56 }
57
app_spi_slave_rx_callback(const void * buffer,uint32_t length,bool error)58 static void app_spi_slave_rx_callback(const void *buffer, uint32_t length, bool error)
59 {
60 if (buffer == NULL || length == 0) {
61 osal_printk("spi slave transfer illegal data!\r\n");
62 return;
63 }
64 if (error) {
65 osal_printk("app_spi_slave_read_int error!\r\n");
66 return;
67 }
68
69 uint8_t *buff = (uint8_t *)buffer;
70 for (uint32_t i = 0; i < length; i++) {
71 osal_printk("buff[%d] = %x\r\n", i, buff[i]);
72 }
73 osal_printk("app_spi_slave_read_int success!\r\n");
74 }
75 #endif /* CONFIG_SPI_SUPPORT_INTERRUPT */
76
app_spi_slave_init_config(void)77 static void app_spi_slave_init_config(void)
78 {
79 spi_attr_t config = { 0 };
80 spi_extra_attr_t ext_config = { 0 };
81
82 config.is_slave = true;
83 config.slave_num = SPI_SLAVE_NUM;
84 config.bus_clk = SPI_CLK_FREQ;
85 config.freq_mhz = SPI_FREQUENCY;
86 config.clk_polarity = SPI_CLK_POLARITY;
87 config.clk_phase = SPI_CLK_PHASE;
88 config.frame_format = SPI_FRAME_FORMAT;
89 config.spi_frame_format = HAL_SPI_FRAME_FORMAT_STANDARD;
90 config.frame_size = SPI_FRAME_SIZE_8;
91 config.tmod = SPI_TMOD;
92 config.sste = 1;
93
94 ext_config.qspi_param.wait_cycles = SPI_WAIT_CYCLES;
95
96 uapi_spi_init(CONFIG_SPI_SLAVE_BUS_ID, &config, &ext_config);
97 #if defined(CONFIG_SPI_SUPPORT_DMA) && (CONFIG_SPI_SUPPORT_DMA == 1)
98 uapi_dma_init();
99 uapi_dma_open();
100 #ifndef CONFIG_SPI_SUPPORT_POLL_AND_DMA_AUTO_SWITCH
101 spi_dma_config_t dma_cfg = {
102 .src_width = SPI_DMA_WIDTH,
103 .dest_width = SPI_DMA_WIDTH,
104 .burst_length = 0,
105 .priority = 0
106 };
107 if (uapi_spi_set_dma_mode(CONFIG_SPI_SLAVE_BUS_ID, true, &dma_cfg) != ERRCODE_SUCC) {
108 osal_printk("spi%d slave set dma mode fail!\r\n");
109 }
110 #endif
111 #endif /* CONFIG_SPI_SUPPORT_DMA */
112
113 #if defined(CONFIG_SPI_SUPPORT_INTERRUPT) && (CONFIG_SPI_SUPPORT_INTERRUPT == 1)
114 if (uapi_spi_set_irq_mode(CONFIG_SPI_SLAVE_BUS_ID, true, app_spi_slave_rx_callback,
115 app_spi_slave_write_int_handler) == ERRCODE_SUCC) {
116 osal_printk("spi%d slave set irq mode succ!\r\n", CONFIG_SPI_SLAVE_BUS_ID);
117 }
118 #endif /* CONFIG_SPI_SUPPORT_INTERRUPT */
119 }
120
spi_slave_task(const char * arg)121 static void *spi_slave_task(const char *arg)
122 {
123 unused(arg);
124 /* SPI pinmux. */
125 app_spi_init_pin();
126
127 /* SPI slave init config. */
128 app_spi_slave_init_config();
129
130 /* SPI data config. */
131 uint8_t tx_data[CONFIG_SPI_TRANSFER_LEN] = { 0 };
132 for (uint32_t loop = 0; loop < CONFIG_SPI_TRANSFER_LEN; loop++) {
133 tx_data[loop] = (loop & 0xFF);
134 }
135 uint8_t rx_data[CONFIG_SPI_TRANSFER_LEN] = { 0 };
136 spi_xfer_data_t data = {
137 .tx_buff = tx_data,
138 .tx_bytes = CONFIG_SPI_TRANSFER_LEN,
139 .rx_buff = rx_data,
140 .rx_bytes = CONFIG_SPI_TRANSFER_LEN,
141 };
142
143 while (1) {
144 osal_msleep(SPI_TASK_DURATION_MS);
145 osal_printk("spi%d slave receive start!\r\n", CONFIG_SPI_SLAVE_BUS_ID);
146 if (uapi_spi_slave_read(CONFIG_SPI_SLAVE_BUS_ID, &data, 0xFFFFFFFF) == ERRCODE_SUCC) {
147 #ifndef CONFIG_SPI_SUPPORT_INTERRUPT
148 for (uint32_t i = 0; i < data.rx_bytes; i++) {
149 osal_printk("spi%d slave receive data is %x\r\n", CONFIG_SPI_SLAVE_BUS_ID, data.rx_buff[i]);
150 }
151 #endif
152 osal_printk("spi%d slave receive succ!\r\n", CONFIG_SPI_SLAVE_BUS_ID);
153 } else {
154 continue;
155 }
156 osal_printk("spi%d slave send start!\r\n", CONFIG_SPI_SLAVE_BUS_ID);
157 if (uapi_spi_slave_write(CONFIG_SPI_SLAVE_BUS_ID, &data, 0xFFFFFFFF) == ERRCODE_SUCC) {
158 osal_printk("spi%d slave send succ!\r\n", CONFIG_SPI_SLAVE_BUS_ID);
159 }
160 }
161
162 return NULL;
163 }
164
spi_slave_entry(void)165 static void spi_slave_entry(void)
166 {
167 osal_task *task_handle = NULL;
168 osal_kthread_lock();
169 task_handle = osal_kthread_create((osal_kthread_handler)spi_slave_task, 0, "SpiSlaveTask", SPI_TASK_STACK_SIZE);
170 if (task_handle != NULL) {
171 osal_kthread_set_priority(task_handle, SPI_TASK_PRIO);
172 osal_kfree(task_handle);
173 }
174 osal_kthread_unlock();
175 }
176
177 /* Run the spi_slave_entry. */
178 app_run(spi_slave_entry);