27
27
#include "sl_si91x_host_interface.h"
28
28
#include "sl_si91x_ncp_utility.h"
29
29
#include "sl_si91x_status.h"
30
+ #include "sl_spidrv_exp_config.h"
31
+ #include "sl_spidrv_instances.h"
30
32
#include "sl_status.h"
31
33
#include "sl_wifi_constants.h"
34
+ #include "spidrv.h"
32
35
#include <platform/silabs/wifi/SiWx/ncp/sl_board_configuration.h>
33
36
#include <platform/silabs/wifi/ncp/spi_multiplex.h>
34
37
#include <stdbool.h>
42
45
#include "sl_board_control.h"
43
46
#endif // SL_BOARD_NAME
44
47
45
- static bool dma_callback (unsigned int channel , unsigned int sequenceNo , void * userParam );
48
+ #define LDMA_MAX_TRANSFER_LENGTH 4096
49
+ #define LDMA_DESCRIPTOR_ARRAY_LENGTH (LDMA_MAX_TRANSFER_LENGTH / 2048)
50
+ #define SPI_HANDLE sl_spidrv_exp_handle
51
+ #define MAX_DATA_PACKET_SIZE 1800
52
+
53
+ // use SPI handle for EXP header (configured in project settings)
54
+ extern SPIDRV_Handle_t sl_spidrv_exp_handle ;
55
+ static uint8_t dummy_buffer [MAX_DATA_PACKET_SIZE ] = { 0 };
56
+ static sl_si91x_host_init_configuration init_config = { 0 };
46
57
47
58
uint32_t rx_ldma_channel ;
48
59
uint32_t tx_ldma_channel ;
49
60
osMutexId_t ncp_transfer_mutex = 0 ;
50
61
51
- static uint32_t dummy_buffer ;
52
- static sl_si91x_host_init_configuration init_config = { 0 };
53
-
54
- // LDMA descriptor and transfer configuration structures for USART TX channel
55
- LDMA_Descriptor_t ldmaTXDescriptor ;
56
- LDMA_TransferCfg_t ldmaTXConfig ;
57
-
58
- // LDMA descriptor and transfer configuration structures for USART RX channel
59
- LDMA_Descriptor_t ldmaRXDescriptor ;
60
- LDMA_TransferCfg_t ldmaRXConfig ;
61
-
62
62
static osSemaphoreId_t transfer_done_semaphore = NULL ;
63
63
64
- static bool dma_callback ([[maybe_unused ]] unsigned int channel , [[maybe_unused ]] unsigned int sequenceNo ,
65
- [[maybe_unused ]] void * userParam )
66
- {
67
- #if defined(SL_CATLOG_POWER_MANAGER_PRESENT )
68
- sl_power_manager_remove_em_requirement (SL_POWER_MANAGER_EM1 );
69
- #endif
70
- osSemaphoreRelease (transfer_done_semaphore );
71
- return false;
72
- }
73
-
74
64
static void gpio_interrupt ([[maybe_unused ]] uint8_t interrupt_number )
75
65
{
76
66
if (NULL != init_config .rx_irq )
@@ -79,54 +69,27 @@ static void gpio_interrupt([[maybe_unused]] uint8_t interrupt_number)
79
69
}
80
70
}
81
71
82
- static void efx32_spi_init ( void )
72
+ static void spi_dma_callback ( struct SPIDRV_HandleData * handle , Ecode_t transferStatus , int itemsTransferred )
83
73
{
84
- // Default asynchronous initializer (master mode, 1 Mbps, 8-bit data)
85
- USART_InitSync_TypeDef init = USART_INITSYNC_DEFAULT ;
74
+ UNUSED_PARAMETER (handle );
75
+ UNUSED_PARAMETER (transferStatus );
76
+ UNUSED_PARAMETER (itemsTransferred );
77
+ #if defined(SL_CATLOG_POWER_MANAGER_PRESENT )
78
+ sl_power_manager_remove_em_requirement (SL_POWER_MANAGER_EM1 );
79
+ #endif
80
+ osSemaphoreRelease (transfer_done_semaphore );
81
+ return ;
82
+ }
86
83
87
- init . msbf = true; // MSB first transmission for SPI compatibility
88
- init . autoCsEnable = false;
89
- init . baudrate = USART_INITSYNC_BAUDRATE ;
84
+ static void efx32_spi_init ( void )
85
+ {
86
+ SPIDRV_SetBitrate ( SPI_HANDLE , USART_INITSYNC_BAUDRATE ) ;
90
87
91
88
// Configure SPI bus pins
92
89
GPIO_PinModeSet (SPI_MISO_PIN .port , SPI_MISO_PIN .pin , gpioModeInput , 0 );
93
90
GPIO_PinModeSet (SPI_MOSI_PIN .port , SPI_MOSI_PIN .pin , gpioModePushPull , 0 );
94
91
GPIO_PinModeSet (SPI_CLOCK_PIN .port , SPI_CLOCK_PIN .pin , gpioModePushPullAlternate , 0 );
95
92
GPIO_PinModeSet (SPI_CS_PIN .port , SPI_CS_PIN .pin , gpioModePushPull , 1 );
96
- // Enable clock (not needed on xG21)
97
- CMU_ClockEnable (SPI_USART_CMU_CLOCK , true);
98
-
99
- /*
100
- * Route USART RX, TX, and CLK to the specified pins. Note that CS is
101
- * not controlled by USART so there is no write to the corresponding
102
- * USARTROUTE register to do this.
103
- */
104
- GPIO -> USARTROUTE [SPI_USART_ROUTE_INDEX ].RXROUTE =
105
- (SPI_MISO_PIN .port << _GPIO_USART_RXROUTE_PORT_SHIFT ) | (SPI_MISO_PIN .pin << _GPIO_USART_RXROUTE_PIN_SHIFT );
106
- GPIO -> USARTROUTE [SPI_USART_ROUTE_INDEX ].TXROUTE =
107
- (SPI_MOSI_PIN .port << _GPIO_USART_TXROUTE_PORT_SHIFT ) | (SPI_MOSI_PIN .pin << _GPIO_USART_TXROUTE_PIN_SHIFT );
108
- GPIO -> USARTROUTE [SPI_USART_ROUTE_INDEX ].CLKROUTE =
109
- (SPI_CLOCK_PIN .port << _GPIO_USART_CLKROUTE_PORT_SHIFT ) | (SPI_CLOCK_PIN .pin << _GPIO_USART_CLKROUTE_PIN_SHIFT );
110
- GPIO -> USARTROUTE [SPI_USART_ROUTE_INDEX ].CSROUTE =
111
- (SPI_CS_PIN .port << _GPIO_USART_CSROUTE_PORT_SHIFT ) | (SPI_CS_PIN .pin << _GPIO_USART_CSROUTE_PIN_SHIFT );
112
-
113
- // Enable USART interface pins
114
- GPIO -> USARTROUTE [SPI_USART_ROUTE_INDEX ].ROUTEEN = GPIO_USART_ROUTEEN_RXPEN | // MISO
115
- GPIO_USART_ROUTEEN_TXPEN | // MOSI
116
- #if !SL_SPICTRL_MUX
117
- GPIO_USART_ROUTEEN_CSPEN |
118
- #endif
119
- GPIO_USART_ROUTEEN_CLKPEN ;
120
-
121
- // Set slew rate for alternate usage pins
122
- GPIO_SlewrateSet (SPI_CLOCK_PIN .port , 7 , 7 );
123
-
124
- // Configure and enable USART
125
- USART_InitSync (SPI_USART , & init );
126
-
127
- SPI_USART -> TIMING |= USART_TIMING_TXDELAY_ONE | USART_TIMING_CSSETUP_ONE | USART_TIMING_CSHOLD_ONE ;
128
-
129
- // SPI_USART->CTRL_SET |= USART_CTRL_SMSDELAY;
130
93
131
94
// configure packet pending interrupt priority
132
95
NVIC_SetPriority (GPIO_ODD_IRQn , PACKET_PENDING_INT_PRI );
@@ -135,6 +98,46 @@ static void efx32_spi_init(void)
135
98
GPIO_ExtIntConfig (INTERRUPT_PIN .port , INTERRUPT_PIN .pin , INTERRUPT_PIN .pin , true, false, true);
136
99
}
137
100
101
+ Ecode_t si91x_SPIDRV_MTransfer (SPIDRV_Handle_t handle , const void * txBuffer , void * rxBuffer , int count ,
102
+ SPIDRV_Callback_t callback )
103
+ {
104
+ USART_TypeDef * usart = handle -> initData .port ;
105
+ uint8_t * tx = (txBuffer != NULL ) ? (uint8_t * ) txBuffer : dummy_buffer ;
106
+ uint8_t * rx = (rxBuffer != NULL ) ? (uint8_t * ) rxBuffer : dummy_buffer ;
107
+
108
+ // For transfers less than 16 bytes, directly interacting with USART buffers is faster than using DMA
109
+ if (count < 16 )
110
+ {
111
+ while (count > 0 )
112
+ {
113
+ while (!(usart -> STATUS & USART_STATUS_TXBL ))
114
+ {
115
+ }
116
+ usart -> TXDATA = (uint32_t ) * tx ;
117
+ while (!(usart -> STATUS & USART_STATUS_TXC ))
118
+ {
119
+ }
120
+ * rx = (uint8_t ) usart -> RXDATA ;
121
+ if (txBuffer != NULL )
122
+ {
123
+ tx ++ ;
124
+ }
125
+ if (rxBuffer != NULL )
126
+ {
127
+ rx ++ ;
128
+ }
129
+ count -- ;
130
+ }
131
+ // callback(handle, ECODE_EMDRV_SPIDRV_OK, 0);
132
+ return ECODE_EMDRV_SPIDRV_OK ;
133
+ }
134
+ else
135
+ {
136
+ SPIDRV_MTransfer (handle , tx , rx , count , callback );
137
+ }
138
+ return ECODE_EMDRV_SPIDRV_BUSY ;
139
+ }
140
+
138
141
void sl_si91x_host_set_sleep_indicator (void )
139
142
{
140
143
GPIO_PinOutSet (SLEEP_CONFIRM_PIN .port , SLEEP_CONFIRM_PIN .pin );
@@ -160,15 +163,16 @@ sl_status_t sl_si91x_host_init(const sl_si91x_host_init_configuration * config)
160
163
return status ;
161
164
}
162
165
#endif // SL_SPICTRL_MUX
163
- init_config .rx_irq = config -> rx_irq ;
164
- init_config .rx_done = config -> rx_done ;
166
+ init_config .rx_irq = config -> rx_irq ;
167
+ init_config .rx_done = config -> rx_done ;
168
+ init_config .boot_option = config -> boot_option ;
165
169
166
170
// Enable clock (not needed on xG21)
167
171
CMU_ClockEnable (cmuClock_GPIO , true);
168
172
169
173
#if SL_SPICTRL_MUX
170
174
spi_board_init ();
171
- #endif
175
+ #endif // SL_SPICTRL_MUX
172
176
173
177
if (transfer_done_semaphore == NULL )
174
178
{
@@ -189,10 +193,6 @@ sl_status_t sl_si91x_host_init(const sl_si91x_host_init_configuration * config)
189
193
GPIO_PinModeSet (SLEEP_CONFIRM_PIN .port , SLEEP_CONFIRM_PIN .pin , gpioModeWiredOrPullDown , 1 );
190
194
GPIO_PinModeSet (WAKE_INDICATOR_PIN .port , WAKE_INDICATOR_PIN .pin , gpioModeWiredOrPullDown , 0 );
191
195
192
- DMADRV_Init ();
193
- DMADRV_AllocateChannel ((unsigned int * ) & rx_ldma_channel , NULL );
194
- DMADRV_AllocateChannel ((unsigned int * ) & tx_ldma_channel , NULL );
195
-
196
196
return SL_STATUS_OK ;
197
197
}
198
198
@@ -223,68 +223,8 @@ sl_status_t sl_si91x_host_spi_transfer(const void * tx_buffer, void * rx_buffer,
223
223
sl_wfx_host_spi_cs_assert ();
224
224
#endif // SL_SPICTRL_MUX
225
225
226
- if (buffer_length < 16 )
226
+ if (ECODE_EMDRV_SPIDRV_BUSY == si91x_SPIDRV_MTransfer ( SPI_HANDLE , tx_buffer , rx_buffer , buffer_length , spi_dma_callback ) )
227
227
{
228
- uint8_t * tx = (tx_buffer != NULL ) ? (uint8_t * ) tx_buffer : (uint8_t * ) & dummy_buffer ;
229
- uint8_t * rx = (rx_buffer != NULL ) ? (uint8_t * ) rx_buffer : (uint8_t * ) & dummy_buffer ;
230
- while (buffer_length > 0 )
231
- {
232
- while (!(SPI_USART -> STATUS & USART_STATUS_TXBL ))
233
- {
234
- }
235
- SPI_USART -> TXDATA = (uint32_t ) * tx ;
236
- while (!(SPI_USART -> STATUS & USART_STATUS_TXC ))
237
- {
238
- }
239
- * rx = (uint8_t ) SPI_USART -> RXDATA ;
240
- if (tx_buffer != NULL )
241
- {
242
- tx ++ ;
243
- }
244
- if (rx_buffer != NULL )
245
- {
246
- rx ++ ;
247
- }
248
- buffer_length -- ;
249
- }
250
- }
251
- else
252
- {
253
- if (tx_buffer == NULL )
254
- {
255
- dummy_buffer = 0 ;
256
- ldmaTXDescriptor =
257
- (LDMA_Descriptor_t ) LDMA_DESCRIPTOR_SINGLE_P2P_BYTE (& dummy_buffer , & (SPI_USART -> TXDATA ), buffer_length );
258
- }
259
- else
260
- {
261
- ldmaTXDescriptor = (LDMA_Descriptor_t ) LDMA_DESCRIPTOR_SINGLE_M2P_BYTE (tx_buffer , & (SPI_USART -> TXDATA ), buffer_length );
262
- }
263
-
264
- if (rx_buffer == NULL )
265
- {
266
- ldmaRXDescriptor =
267
- (LDMA_Descriptor_t ) LDMA_DESCRIPTOR_SINGLE_P2P_BYTE (& (SPI_USART -> RXDATA ), & dummy_buffer , buffer_length );
268
- }
269
- else
270
- {
271
- ldmaRXDescriptor = (LDMA_Descriptor_t ) LDMA_DESCRIPTOR_SINGLE_P2M_BYTE (& (SPI_USART -> RXDATA ), rx_buffer , buffer_length );
272
- }
273
-
274
- // Transfer a byte on free space in the USART buffer
275
- ldmaTXConfig = (LDMA_TransferCfg_t ) LDMA_TRANSFER_CFG_PERIPHERAL (SPI_USART_LDMA_TX );
276
-
277
- // Transfer a byte on receive data valid
278
- ldmaRXConfig = (LDMA_TransferCfg_t ) LDMA_TRANSFER_CFG_PERIPHERAL (SPI_USART_LDMA_RX );
279
-
280
- #if defined(SL_CATLOG_POWER_MANAGER_PRESENT )
281
- sl_power_manager_remove_em_requirement (SL_POWER_MANAGER_EM1 );
282
- #endif
283
-
284
- // Start both channels
285
- DMADRV_LdmaStartTransfer (rx_ldma_channel , & ldmaRXConfig , & ldmaRXDescriptor , dma_callback , NULL );
286
- DMADRV_LdmaStartTransfer (tx_ldma_channel , & ldmaTXConfig , & ldmaTXDescriptor , NULL , NULL );
287
-
288
228
if (osSemaphoreAcquire (transfer_done_semaphore , 1000 ) != osOK )
289
229
{
290
230
BREAKPOINT ();
@@ -300,7 +240,6 @@ sl_status_t sl_si91x_host_spi_transfer(const void * tx_buffer, void * rx_buffer,
300
240
301
241
void sl_si91x_host_hold_in_reset (void )
302
242
{
303
- GPIO_PinModeSet (RESET_PIN .port , RESET_PIN .pin , gpioModePushPull , 1 );
304
243
GPIO_PinOutClear (RESET_PIN .port , RESET_PIN .pin );
305
244
}
306
245
0 commit comments