yincheng.zhong
2024-08-27 fc78430a35be252a1cd5a29b5b66290a68cd9ca3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/*
 * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and
 * its subsidiaries and affiliates (collectly called MKSEMI).
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into an MKSEMI
 *    integrated circuit in a product or a software update for such product,
 *    must reproduce the above copyright notice, this list of conditions and
 *    the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of MKSEMI nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    MKSEMI integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be
 *    reverse engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY MKSEMI "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL MKSEMI OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
#ifndef MK_SPI_H_
#define MK_SPI_H_
 
#include "mk_common.h"
#include "mk_dma.h"
 
#ifndef SPI_INT_MODE_EN
#define SPI_INT_MODE_EN (1)
#endif
 
#ifndef SPI_DMA_MODE_EN
#define SPI_DMA_MODE_EN (1)
#endif
 
#ifndef SPI_POLL_MODE_EN
#define SPI_POLL_MODE_EN (1)
#endif
 
/**
 * @addtogroup MK8000_SPI
 * @{
 */
 
#define SPI_SCR_MAX (255)
#define SPI_SCR_MIN (0)
 
#define SPI_CPSDVSR_MAX (254)
#define SPI_CPSDVSR_MIN (2)
 
#define SPI_DATA_BITS_MAX (16)
#define SPI_DATA_BITS_MIN (4)
 
#define SPI_DMA_ABORT_TX (1 << 0)
#define SPI_DMA_ABORT_RX (1 << 1)
 
/**
 * @brief SPI device IDs enumeration
 */
enum SPI_DEV_T
{
    SPI_ID0 = 0,
    SPI_ID1,
    SPI_MAX_NUM
};
 
/**
 * @brief SPI state enumeration
 */
enum SPI_STATE_T
{
    SPI_STATE_RESET = 0x00U,      /*!< Peripheral not Initialized */
    SPI_STATE_READY = 0x01U,      /*!< Peripheral Initialized and ready for use */
    SPI_STATE_BUSY_TX = 0x10U,    /*!< Data Transmission process is ongoing */
    SPI_STATE_BUSY_RX = 0x20U,    /*!< Data Reception process is ongoing */
    SPI_STATE_BUSY_TX_RX = 0x30U, /*!< Data Transmission and Reception process is ongoing */
    SPI_STATE_TIMEOUT = 0x40U,    /*!< SPI timeout */
    SPI_STATE_ERROR = 0x80U,      /*!< SPI error state */
};
 
/**
 * @brief SPI config structure
 */
struct SPI_CFG_T
{
    uint32_t bit_rate;        /*!< Specifies the bit rate */
    uint8_t data_bits;        /*!< Specifies the data bits. \n
                                      This parameter ranges from SPI_DATA_BITS_MIN to SPI_DATA_BITS_MAX.
                              */
    uint8_t slave : 1;        /*!< Specifies the SPI operating mode. \n
                                      This parameter will be one of the following values:
                                          @arg 0 master mode
                                          @arg 1 slave mode
                              */
    uint8_t clk_phase : 1;    /*!< Specifies the clock active edge for the bit capture. \n
                                      This parameter will be one of the following values:
                                          @arg 0 first edge
                                          @arg 1 second edge
                              */
    uint8_t clk_polarity : 1; /*!< Specifies the serial clock steady state. \n
                                      This parameter will be one of the following values:
                                          @arg 0 low level
                                          @arg 1 high level
                              */
    uint8_t ti_mode : 1;      /*!< Specifies whether the TI mode is enabled or disabled. \n
                                      This parameter will be one of the following values:
                                          @arg 0 disabled
                                          @arg 1 enabled
                               */
    uint8_t dma_rx : 1;       /*!< Specifies whether the dma Rx is enabled or disabled. \n
                                      This parameter will be one of the following values:
                                          @arg 0 disabled
                                          @arg 1 enabled
                              */
    uint8_t dma_tx : 1;       /*!< Specifies whether the dma Tx is enabled or disabled. \n
                                      This parameter will be one of the following values:
                                          @arg 0 disabled
                                          @arg 1 enabled
                              */
    uint8_t int_rx : 1;       /*!< Specifies whether Rx interupt in the NVIC interrupt controller is enabled or disabled. \n
                                      This parameter will be one of the following values:
                                          @arg 0 disabled
                                          @arg 1 enabled
                              */
    uint8_t int_tx : 1;       /*!< Specifies whether Tx interupt in the NVIC interrupt controller is enabled or disabled. \n
                                      This parameter will be one of the following values:
                                          @arg 0 disabled
                                          @arg 1 enabled
                              */
    uint8_t reserved[2];      /*!< reserved */
};
 
/**
 * @brief  SPI handle Structure
 */
struct SPI_HANDLE_T
{
    SPI_TypeDef *const base;          /*!< SPI registers base address */
    const IRQn_Type irq;              /*!< SPI interupt number */
    enum DMA_CH_T dma_rx_ch;          /*!< SPI dma Rx channel */
    enum DMA_CH_T dma_tx_ch;          /*!< SPI dma Tx channel */
    __IOM enum SPI_STATE_T state;     /*!< SPI state */
    uint8_t slave : 1;                /*!< SPI operating mode switch */
    uint8_t dma_rx : 1;               /*!< SPI dma Rx switch */
    uint8_t dma_tx : 1;               /*!< SPI dma Tx switch */
    uint8_t int_rx : 1;               /*!< SPI Rx interupt switch */
    uint8_t int_tx : 1;               /*!< SPI Tx interupt switch */
    uint8_t reserved0 : 3;            /*!< reserved */
    uint8_t reserved1;                /*!< reserved */
    uint16_t tx_dummy;                /*!< SPI send data when receive data only */
    uint8_t *tx_buff;                 /*!< Pointer to SPI Tx transfer Buffer */
    uint32_t tx_size;                 /*!< SPI Tx Transfer size */
    __IOM uint32_t tx_count;          /*!< SPI Tx Transfer Counter */
    uint8_t *rx_buff;                 /*!< Pointer to SPI Rx transfer Buffer */
    uint32_t rx_size;                 /*!< SPI Rx Transfer size */
    __IOM uint32_t rx_count;          /*!< SPI Rx Transfer Counter */
    drv_callback_t tx_callback;       /*!< Pointer to SPI Tx Callback function */
    drv_callback_t rx_callback;       /*!< Pointer to SPI Rx Callback function */
    drv_callback_t tx_abort_callback; /*!< Pointer to SPI Tx abort Callback function */
    drv_callback_t rx_abort_callback; /*!< Pointer to SPI Rx abort Callback function */
};
 
#ifdef __cplusplus
extern "C" {
#endif
 
/**
 * @brief  open SPI
 * @param[in] id        SPI device ID. \n
 *                      This parameter should be one of the SPI_DEV_T enum values as below
 *                      @arg SPI_ID0 spi0
 *                      @arg SPI_ID1 spi1
 * @param[in] config    pointer to a SPI_CFG_T structure that contains the configuration information for SPI. \n
 * @return
 *         @arg DRV_ERROR   error id
 *         @arg DEV_OK      open succeed
 */
int spi_open(enum SPI_DEV_T id, struct SPI_CFG_T *config);
 
/**
 * @brief  close SPI
 * @param[in] id        SPI device ID. \n
 *                      This parameter should be one of the SPI_DEV_T enum values as below
 *                      @arg SPI_ID0 spi0
 *                      @arg SPI_ID1 spi1
 * @return
 *         @arg DRV_ERROR   error id
 *         @arg DEV_OK      open succeed
 */
int spi_close(enum SPI_DEV_T id);
 
/**
 * @brief  Sends an amount of data.
 * @param[in] id        SPI device ID. \n
 *                      This parameter should be one of the SPI_DEV_T enum values as below
 *                      @arg SPI_ID0 spi0
 *                      @arg SPI_ID1 spi1
 * @param[in] tx_buf    Pointer to data buffer
 * @param[in] len       Bytes of data to be sent
 * @param[in] callback  Pointer to SPI Tx Callback function.
 * @return
 *         @arg DRV_ERROR   error id
 *         @arg DRV_BUSY    send failed because of SPI Tx is busy
 *         @arg DEV_OK      send succeed
 */
int spi_send(enum SPI_DEV_T id, uint8_t *tx_buf, uint32_t len, drv_callback_t callback);
 
/**
 * @brief  Receive an amount of data.
 * @param[in] id        SPI device ID. \n
 *                      This parameter should be one of the SPI_DEV_T enum values as below
 *                      @arg SPI_ID0 spi0
 *                      @arg SPI_ID1 spi1
 * @param[out] rx_buf   Pointer to data buffer
 * @param[in] len       Bytes of data to be received
 * @param[in] callback  Pointer to SPI Rx Callback function.
 * @return
 *         @arg DRV_ERROR   error id
 *         @arg DRV_BUSY    send failed because of SPI Tx is busy
 *         @arg DEV_OK      send succeed
 */
int spi_receive(enum SPI_DEV_T id, uint8_t *rx_buf, uint32_t len, drv_callback_t callback);
 
/**
 * @brief  Send and Receive an amount of data.
 * @param[in] id        SPI device ID. \n
 *                      This parameter should be one of the SPI_DEV_T enum values as below
 *                      @arg SPI_ID0 spi0
 *                      @arg SPI_ID1 spi1
 * @param[in] tx_buf    Pointer to data buffer
 * @param[out] rx_buf   Pointer to data buffer
 * @param[in] len       Bytes of data to be sent and received
 * @param[in] callback  Pointer to SPI transfter Callback function.
 * @return
 *         @arg DRV_ERROR   error id
 *         @arg DRV_BUSY    send failed because of SPI Tx is busy
 *         @arg DEV_OK      send succeed
 */
int spi_transfer(enum SPI_DEV_T id, uint8_t *tx_buf, uint8_t *rx_buf, uint32_t len, drv_callback_t callback);
 
/**
 * @brief  Check whether the SPI is busy
 * @param[in] id        SPI device ID. \n
 *                      This parameter should be one of the SPI_DEV_T enum values as below
 *                      @arg SPI_ID0 spi0
 *                      @arg SPI_ID1 spi1
 * @return
 *         @arg true   SPI is busy
 *         @arg false  SPI is idle
 */
bool spi_is_busy(enum SPI_DEV_T id);
 
/**
 * @brief  Get SPI state
 * @param[in] id        SPI device ID. \n
 *                      This parameter should be one of the SPI_DEV_T enum values as below
 *                      @arg SPI_ID0 uart0
 *                      @arg SPI_ID1 uart1
 * @return
 *         @arg SPI_STATE_T    SPI state
 */
enum SPI_STATE_T spi_state_get(enum SPI_DEV_T id);
 
/**
 * @brief  Abort ongoing transfer
 * @param[in] id        SPI device ID. \n
 *                      This parameter should be one of the SPI_DEV_T enum values as below
 *                      @arg SPI_ID0 spi0
 *                      @arg SPI_ID1 spi1
 * @note This function is used to terminate the ongoing spi tx and rx communication,
 *       if the tx or rx communication is completed before spi dma abort, the callback function
 *       will not be called.
 * @param[in] abort_direction           SPI_DMA_ABORT_TX abort spi dma tx, SPI_DMA_ABORT_RX abort spi dma rx
 * @param[in] abort_tx_callback         DMA SPI tx communication abort callback
 * @param[in] abort_rx_callback         DMA SPI rx communication abort callback
 * @return @arg DRV_ERROR   Abort error
 *         @arg DEV_OK      Disable SPI DMA tx/rx request succeed
 */
int spi_abort_dma(enum SPI_DEV_T id, uint32_t abort_direction, drv_callback_t abort_tx_callback, drv_callback_t abort_rx_callback);
 
/**
 * @brief This function handles SP0 interrupt.
 */
void SPI0_IRQHandler(void);
 
/**
 * @brief This function handles SP1 interrupt.
 */
void SPI1_IRQHandler(void);
 
#ifdef __cplusplus
}
#endif
 
/**
 * @}
 */
 
#endif /* MK_SPI_H_ */