Browse Source

Only set up SPI pins as needed (#19372)

Victor Oliveira 4 years ago
parent
commit
79d4123319
No account linked to committer's email address
1 changed files with 53 additions and 49 deletions
  1. 53
    49
      Marlin/src/HAL/LPC1768/HAL_SPI.cpp

+ 53
- 49
Marlin/src/HAL/LPC1768/HAL_SPI.cpp View File

39
  * Some of the LCD interfaces/adapters result in the LCD SPI and the SD card
39
  * Some of the LCD interfaces/adapters result in the LCD SPI and the SD card
40
  * SPI sharing pins. The SCK, MOSI & MISO pins can NOT be set/cleared with
40
  * SPI sharing pins. The SCK, MOSI & MISO pins can NOT be set/cleared with
41
  * WRITE nor digitalWrite when the hardware SPI module within the LPC17xx is
41
  * WRITE nor digitalWrite when the hardware SPI module within the LPC17xx is
42
- * active.  If any of these pins are shared then the software SPI must be used.
42
+ * active. If any of these pins are shared then the software SPI must be used.
43
  *
43
  *
44
- * A more sophisticated hardware SPI can be found at the following link.  This
45
- * implementation has not been fully debugged.
44
+ * A more sophisticated hardware SPI can be found at the following link.
45
+ * This implementation has not been fully debugged.
46
  * https://github.com/MarlinFirmware/Marlin/tree/071c7a78f27078fd4aee9a3ef365fcf5e143531e
46
  * https://github.com/MarlinFirmware/Marlin/tree/071c7a78f27078fd4aee9a3ef365fcf5e143531e
47
  */
47
  */
48
 
48
 
170
   while (SSP_GetStatus(spi_d, SSP_STAT_BUSY) == SET) { /* nada */ }     // wait until BSY=0
170
   while (SSP_GetStatus(spi_d, SSP_STAT_BUSY) == SET) { /* nada */ }     // wait until BSY=0
171
 }
171
 }
172
 
172
 
173
+// Retain the pin init state of the SPI, to avoid init more than once,
174
+// even if more instances of SPIClass exist
175
+static bool spiInitialised[BOARD_NR_SPI] = { false };
176
+
173
 SPIClass::SPIClass(uint8_t device) {
177
 SPIClass::SPIClass(uint8_t device) {
174
   // Init things specific to each SPI device
178
   // Init things specific to each SPI device
175
   // clock divider setup is a bit of hack, and needs to be improved at a later date.
179
   // clock divider setup is a bit of hack, and needs to be improved at a later date.
176
 
180
 
177
-  PINSEL_CFG_Type PinCfg;  // data structure to hold init values
178
   #if BOARD_NR_SPI >= 1
181
   #if BOARD_NR_SPI >= 1
179
     _settings[0].spi_d = LPC_SSP0;
182
     _settings[0].spi_d = LPC_SSP0;
180
     _settings[0].dataMode = SPI_MODE0;
183
     _settings[0].dataMode = SPI_MODE0;
181
     _settings[0].dataSize = DATA_SIZE_8BIT;
184
     _settings[0].dataSize = DATA_SIZE_8BIT;
182
     _settings[0].clock = SPI_CLOCK_MAX;
185
     _settings[0].clock = SPI_CLOCK_MAX;
183
-    // _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
184
-    PinCfg.Funcnum = 2;
185
-    PinCfg.OpenDrain = 0;
186
-    PinCfg.Pinmode = 0;
187
-    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_SCK_PIN);
188
-    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_SCK_PIN);
189
-    PINSEL_ConfigPin(&PinCfg);
190
-    SET_OUTPUT(BOARD_SPI1_SCK_PIN);
191
-
192
-    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_MISO_PIN);
193
-    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_MISO_PIN);
194
-    PINSEL_ConfigPin(&PinCfg);
195
-    SET_INPUT(BOARD_SPI1_MISO_PIN);
196
-
197
-    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_MOSI_PIN);
198
-    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_MOSI_PIN);
199
-    PINSEL_ConfigPin(&PinCfg);
200
-    SET_OUTPUT(BOARD_SPI1_MOSI_PIN);
186
+    //_settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
201
   #endif
187
   #endif
202
 
188
 
203
   #if BOARD_NR_SPI >= 2
189
   #if BOARD_NR_SPI >= 2
205
     _settings[1].dataMode = SPI_MODE0;
191
     _settings[1].dataMode = SPI_MODE0;
206
     _settings[1].dataSize = DATA_SIZE_8BIT;
192
     _settings[1].dataSize = DATA_SIZE_8BIT;
207
     _settings[1].clock = SPI_CLOCK_MAX;
193
     _settings[1].clock = SPI_CLOCK_MAX;
208
-    // _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
194
+    //_settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
195
+  #endif
196
+
197
+  setModule(device);
198
+
199
+  // Init the GPDMA controller
200
+  // TODO: call once in the constructor? or each time?
201
+  GPDMA_Init();
202
+}
203
+
204
+void SPIClass::begin() {
205
+  // Init the SPI pins in the first begin call
206
+  if ((_currentSetting->spi_d == LPC_SSP0 && spiInitialised[0] == false) ||
207
+      (_currentSetting->spi_d == LPC_SSP1 && spiInitialised[1] == false)) {
208
+    pin_t sck, miso, mosi;
209
+    if (_currentSetting->spi_d == LPC_SSP0) {
210
+      sck = BOARD_SPI1_SCK_PIN;
211
+      miso = BOARD_SPI1_MISO_PIN;
212
+      mosi = BOARD_SPI1_MOSI_PIN;
213
+      spiInitialised[0] = true;
214
+    }
215
+    else if (_currentSetting->spi_d == LPC_SSP1) {
216
+      sck = BOARD_SPI2_SCK_PIN;
217
+      miso = BOARD_SPI2_MISO_PIN;
218
+      mosi = BOARD_SPI2_MOSI_PIN;
219
+      spiInitialised[1] = true;
220
+    }
221
+    PINSEL_CFG_Type PinCfg;  // data structure to hold init values
209
     PinCfg.Funcnum = 2;
222
     PinCfg.Funcnum = 2;
210
     PinCfg.OpenDrain = 0;
223
     PinCfg.OpenDrain = 0;
211
     PinCfg.Pinmode = 0;
224
     PinCfg.Pinmode = 0;
212
-    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_SCK_PIN);
213
-    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_SCK_PIN);
225
+    PinCfg.Pinnum = LPC176x::pin_bit(sck);
226
+    PinCfg.Portnum = LPC176x::pin_port(sck);
214
     PINSEL_ConfigPin(&PinCfg);
227
     PINSEL_ConfigPin(&PinCfg);
215
-    SET_OUTPUT(BOARD_SPI2_SCK_PIN);
228
+    SET_OUTPUT(sck);
216
 
229
 
217
-    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_MISO_PIN);
218
-    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_MISO_PIN);
230
+    PinCfg.Pinnum = LPC176x::pin_bit(miso);
231
+    PinCfg.Portnum = LPC176x::pin_port(miso);
219
     PINSEL_ConfigPin(&PinCfg);
232
     PINSEL_ConfigPin(&PinCfg);
220
-    SET_INPUT(BOARD_SPI2_MISO_PIN);
233
+    SET_INPUT(miso);
221
 
234
 
222
-    PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_MOSI_PIN);
223
-    PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_MOSI_PIN);
235
+    PinCfg.Pinnum = LPC176x::pin_bit(mosi);
236
+    PinCfg.Portnum = LPC176x::pin_port(mosi);
224
     PINSEL_ConfigPin(&PinCfg);
237
     PINSEL_ConfigPin(&PinCfg);
225
-    SET_OUTPUT(BOARD_SPI2_MOSI_PIN);
226
-  #endif
227
-
228
-  setModule(device);
229
-
230
-  /* Initialize GPDMA controller */
231
-  //TODO: call once in the constructor? or each time?
232
-  GPDMA_Init();
233
-}
238
+    SET_OUTPUT(mosi);
239
+  }
234
 
240
 
235
-void SPIClass::begin() {
236
   updateSettings();
241
   updateSettings();
237
   SSP_Cmd(_currentSetting->spi_d, ENABLE);  // start SSP running
242
   SSP_Cmd(_currentSetting->spi_d, ENABLE);  // start SSP running
238
 }
243
 }
246
 }
251
 }
247
 
252
 
248
 uint8_t SPIClass::transfer(const uint16_t b) {
253
 uint8_t SPIClass::transfer(const uint16_t b) {
249
-  /* send and receive a single byte */
254
+  // Send and receive a single byte
250
   SSP_ReceiveData(_currentSetting->spi_d); // read any previous data
255
   SSP_ReceiveData(_currentSetting->spi_d); // read any previous data
251
   SSP_SendData(_currentSetting->spi_d, b);
256
   SSP_SendData(_currentSetting->spi_d, b);
252
   waitSpiTxEnd(_currentSetting->spi_d);  // wait for it to finish
257
   waitSpiTxEnd(_currentSetting->spi_d);  // wait for it to finish
254
 }
259
 }
255
 
260
 
256
 uint16_t SPIClass::transfer16(const uint16_t data) {
261
 uint16_t SPIClass::transfer16(const uint16_t data) {
257
-  return (transfer((data >> 8) & 0xFF) << 8)
258
-       | (transfer(data & 0xFF) & 0xFF);
262
+  return (transfer((data >> 8) & 0xFF) << 8) | (transfer(data & 0xFF) & 0xFF);
259
 }
263
 }
260
 
264
 
261
 void SPIClass::end() {
265
 void SPIClass::end() {
294
   // Enable dma on SPI
298
   // Enable dma on SPI
295
   SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, ENABLE);
299
   SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, ENABLE);
296
 
300
 
297
-  // only increase memory if minc is true
301
+  // Only increase memory if minc is true
298
   GPDMACfg.MemoryIncrease = (minc ? GPDMA_DMACCxControl_SI : 0);
302
   GPDMACfg.MemoryIncrease = (minc ? GPDMA_DMACCxControl_SI : 0);
299
 
303
 
300
   // Setup channel with given parameter
304
   // Setup channel with given parameter
301
   GPDMA_Setup(&GPDMACfg);
305
   GPDMA_Setup(&GPDMACfg);
302
 
306
 
303
-  // enabled dma
307
+  // Enable DMA
304
   GPDMA_ChannelCmd(0, ENABLE);
308
   GPDMA_ChannelCmd(0, ENABLE);
305
 
309
 
306
-  // wait data transfer
310
+  // Wait for data transfer
307
   while (!GPDMA_IntGetStatus(GPDMA_STAT_RAWINTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_RAWINTERR, 0)) { }
311
   while (!GPDMA_IntGetStatus(GPDMA_STAT_RAWINTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_RAWINTERR, 0)) { }
308
 
312
 
309
-  // clear err and int
313
+  // Clear err and int
310
   GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
314
   GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
311
   GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);
315
   GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);
312
 
316
 
313
-  // dma disable
317
+  // Disable DMA
314
   GPDMA_ChannelCmd(0, DISABLE);
318
   GPDMA_ChannelCmd(0, DISABLE);
315
 
319
 
316
   waitSpiTxEnd(_currentSetting->spi_d);
320
   waitSpiTxEnd(_currentSetting->spi_d);

Loading…
Cancel
Save