Skip to content

Commit 8c32bf9

Browse files
authored
Merge pull request #45 from RudolphRiedel/main
Reworked SPI class with direct register access to fix #28 for R_SPI
2 parents 3441adc + 1cb3111 commit 8c32bf9

File tree

2 files changed

+154
-78
lines changed

2 files changed

+154
-78
lines changed

libraries/SPI/SPI.cpp

+154-77
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void ArduinoSPI::begin()
102102
_cb_event_idx = _channel;
103103

104104
_spi_cfg.p_extend = &_spi_ext_cfg;
105-
_spi_cfg.p_callback = spi_callback;
105+
_spi_cfg.p_callback = nullptr;
106106
}
107107

108108
/* SPI configuration for SPI HAL driver. */
@@ -164,22 +164,8 @@ void ArduinoSPI::begin()
164164
init_ok = false;
165165
}
166166
}
167-
else
168-
{
169-
SpiMasterIrqReq_t irq_req
170-
{
171-
.ctrl = &_spi_ctrl,
172-
.cfg = &_spi_cfg,
173-
.hw_channel = (uint8_t)_channel,
174-
};
175-
init_ok &= IRQManager::getInstance().addPeripheral(IRQ_SPI_MASTER, &irq_req);
176167

177-
if (FSP_SUCCESS == _open(&_spi_ctrl, &_spi_cfg)) {
178-
init_ok &= true;
179-
} else {
180-
init_ok = false;
181-
}
182-
}
168+
/* not using FSP for SPI anymore and no interrupts */
183169

184170
_is_initialized = init_ok;
185171
}
@@ -196,24 +182,31 @@ void ArduinoSPI::end()
196182

197183
uint8_t ArduinoSPI::transfer(uint8_t data)
198184
{
199-
uint8_t rxbuf;
200-
_spi_cb_event[_cb_event_idx] = SPI_EVENT_TRANSFER_ABORTED;
201-
if (_is_sci) {
202-
_write_then_read(&_spi_sci_ctrl, &data, &rxbuf, 1, SPI_BIT_WIDTH_8_BITS);
203-
} else {
204-
_write_then_read(&_spi_ctrl, &data, &rxbuf, 1, SPI_BIT_WIDTH_8_BITS);
205-
}
185+
uint8_t rxbuf;
186+
187+
if (_is_sci) {
188+
_spi_cb_event[_cb_event_idx] = SPI_EVENT_TRANSFER_ABORTED;
189+
190+
_write_then_read(&_spi_sci_ctrl, &data, &rxbuf, 1, SPI_BIT_WIDTH_8_BITS);
191+
192+
for (auto const start = millis();
193+
(SPI_EVENT_TRANSFER_COMPLETE != _spi_cb_event[_cb_event_idx]) && (millis() - start < 1000); )
194+
{
195+
__NOP();
196+
}
197+
if (SPI_EVENT_TRANSFER_ABORTED == _spi_cb_event[_cb_event_idx])
198+
{
199+
end();
200+
return 0;
201+
}
202+
}
203+
else
204+
{
205+
_spi_ctrl.p_regs->SPDR_BY = data;
206+
while (0U == _spi_ctrl.p_regs->SPSR_b.SPRF) {}
207+
rxbuf = _spi_ctrl.p_regs->SPDR_BY;
208+
}
206209

207-
for (auto const start = millis();
208-
(SPI_EVENT_TRANSFER_COMPLETE != _spi_cb_event[_cb_event_idx]) && (millis() - start < 1000); )
209-
{
210-
__NOP();
211-
}
212-
if (SPI_EVENT_TRANSFER_ABORTED == _spi_cb_event[_cb_event_idx])
213-
{
214-
end();
215-
return 0;
216-
}
217210
return rxbuf;
218211
}
219212

@@ -234,23 +227,78 @@ uint16_t ArduinoSPI::transfer16(uint16_t data)
234227

235228
void ArduinoSPI::transfer(void *buf, size_t count)
236229
{
237-
_spi_cb_event[_cb_event_idx] = SPI_EVENT_TRANSFER_ABORTED;
230+
if (NULL == buf) {
231+
return;
232+
}
238233

239-
if (_is_sci) {
240-
_write_then_read(&_spi_sci_ctrl, buf, buf, count, SPI_BIT_WIDTH_8_BITS);
241-
} else {
242-
_write_then_read(&_spi_ctrl, buf, buf, count, SPI_BIT_WIDTH_8_BITS);
243-
}
234+
if (_is_sci) {
235+
_spi_cb_event[_cb_event_idx] = SPI_EVENT_TRANSFER_ABORTED;
244236

245-
for (auto const start = millis();
246-
(SPI_EVENT_TRANSFER_COMPLETE != _spi_cb_event[_cb_event_idx]) && (millis() - start < 1000); )
247-
{
248-
__NOP();
249-
}
250-
if (SPI_EVENT_TRANSFER_ABORTED == _spi_cb_event[_cb_event_idx])
251-
{
252-
end();
253-
}
237+
_write_then_read(&_spi_sci_ctrl, buf, buf, count, SPI_BIT_WIDTH_8_BITS);
238+
239+
for (auto const start = millis();
240+
(SPI_EVENT_TRANSFER_COMPLETE != _spi_cb_event[_cb_event_idx]) && (millis() - start < 1000); )
241+
{
242+
__NOP();
243+
}
244+
if (SPI_EVENT_TRANSFER_ABORTED == _spi_cb_event[_cb_event_idx])
245+
{
246+
end();
247+
}
248+
}
249+
else {
250+
uint32_t *buffer32 = (uint32_t *) buf;
251+
size_t index_rx = 0;
252+
size_t index_tx = 0;
253+
size_t const n32 = count / 4U;
254+
uint8_t const bytes_remaining = (uint8_t) (count & 3U);
255+
256+
if (n32 != 0U) {
257+
_spi_ctrl.p_regs->SPCR_b.SPE = 0; /* disable SPI unit */
258+
_spi_ctrl.p_regs->SPDCR = R_SPI0_SPDCR_SPLW_Msk; /* SPI word access */
259+
_spi_ctrl.p_regs->SPCMD_b[0].SPB = 2; /* spi bit width = 32 */
260+
_spi_ctrl.p_regs->SPCR_b.SPE = 1; /* enable SPI unit */
261+
262+
while ((index_tx < 2U) && (index_tx < n32)) {
263+
if (_spi_ctrl.p_regs->SPSR_b.SPTEF) {
264+
_spi_ctrl.p_regs->SPDR = buffer32[index_tx];
265+
index_tx++;
266+
}
267+
}
268+
269+
while (index_tx < n32) {
270+
if (_spi_ctrl.p_regs->SPSR_b.SPRF) {
271+
uint32_t tmp = _spi_ctrl.p_regs->SPDR;
272+
_spi_ctrl.p_regs->SPDR = buffer32[index_tx];
273+
buffer32[index_rx] = tmp;
274+
index_rx++;
275+
index_tx++;
276+
}
277+
}
278+
279+
while (index_rx < n32) { /* collect the last word received */
280+
if (_spi_ctrl.p_regs->SPSR_b.SPRF) {
281+
uint32_t tmp = _spi_ctrl.p_regs->SPDR;
282+
buffer32[index_rx] = tmp;
283+
index_rx++;
284+
}
285+
}
286+
287+
_spi_ctrl.p_regs->SPCR_b.SPE = 0; /* disable SPI unit */
288+
_spi_ctrl.p_regs->SPDCR = R_SPI0_SPDCR_SPBYT_Msk; /* SPI byte access */
289+
_spi_ctrl.p_regs->SPCMD_b[0].SPB = 7; /* spi bit width = 8 */
290+
_spi_ctrl.p_regs->SPCR_b.SPE = 1; /* enable SPI unit */
291+
}
292+
293+
/* send the remaining bytes with 8-bit transfers */
294+
uint8_t *buffer = (uint8_t *) &buffer32[index_rx];
295+
296+
for (uint8_t index = 0; index < bytes_remaining; index++) {
297+
_spi_ctrl.p_regs->SPDR_BY = buffer[index];
298+
while (0U == _spi_ctrl.p_regs->SPSR_b.SPRF) {}
299+
buffer[index] = _spi_ctrl.p_regs->SPDR_BY;
300+
}
301+
}
254302
}
255303

256304
void ArduinoSPI::beginTransaction(arduino::SPISettings settings)
@@ -366,29 +414,71 @@ void ArduinoSPI::configSpiSettings(arduino::SPISettings const & settings)
366414

367415
void ArduinoSPI::configSpi(arduino::SPISettings const & settings)
368416
{
369-
auto [clk_phase, clk_polarity, bit_order] = toFspSpiConfig(settings);
417+
/** SPI base register access macro. */
418+
#define SPI_REG(channel) ((R_SPI0_Type *) ((uint32_t) R_SPI0 + \
419+
((uint32_t) R_SPI1 - (uint32_t) R_SPI0) * (channel)))
370420

371-
rspck_div_setting_t spck_div = _spi_ext_cfg.spck_div;
372-
R_SPI_CalculateBitrate(settings.getClockFreq(), &spck_div);
421+
_spi_ctrl.p_cfg = &_spi_cfg;
422+
_spi_ctrl.p_callback = _spi_cfg.p_callback;
423+
_spi_ctrl.p_context = _spi_cfg.p_context;
424+
_spi_ctrl.p_callback_memory = NULL;
425+
_spi_ctrl.p_regs = SPI_REG(_spi_ctrl.p_cfg->channel);
373426

374-
uint32_t spcmd0 = _spi_ctrl.p_regs->SPCMD[0];
427+
auto [clk_phase, clk_polarity, bit_order] = toFspSpiConfig(settings);
428+
rspck_div_setting_t spck_div = _spi_ext_cfg.spck_div;
429+
R_SPI_CalculateBitrate(settings.getClockFreq(), &spck_div);
375430

376-
/* Configure CPHA setting. */
377-
spcmd0 |= (uint32_t) clk_phase;
431+
_spi_ctrl.p_regs->SPCR = 0; /* disable SPI unit */
378432

379-
/* Configure CPOL setting. */
380-
spcmd0 |= (uint32_t) clk_polarity << 1;
433+
/* Power up the SPI module. */
434+
R_BSP_MODULE_START(FSP_IP_SPI, _spi_cfg.channel);
381435

382-
/* Configure Bit Order (MSB,LSB) */
383-
spcmd0 |= (uint32_t) bit_order << 12;
436+
/* configure SSLn polarity setting. */
437+
uint32_t sslp = 0;
438+
sslp |= (uint32_t) _spi_ext_cfg.ssl_polarity << _spi_ext_cfg.ssl_select;
439+
_spi_ctrl.p_regs->SSLP = (uint8_t) sslp;
384440

385-
/* Configure the Bit Rate Division Setting */
386-
spcmd0 &= ~(((uint32_t) 3) << 2);
387-
spcmd0 |= (uint32_t) spck_div.brdv << 2;
441+
uint32_t sppcr = 0;
442+
/* set MOSI idle value to low */
443+
sppcr |= R_SPI0_SPPCR_MOIFE_Msk;
444+
_spi_ctrl.p_regs->SPPCR = (uint8_t) sppcr;
388445

389-
/* Update settings. */
390-
_spi_ctrl.p_regs->SPCMD[0] = (uint16_t) spcmd0;
391-
_spi_ctrl.p_regs->SPBR = (uint8_t) spck_div.spbr;
446+
/* configure bit rate */
447+
_spi_ctrl.p_regs->SPBR = (uint8_t) spck_div.spbr;
448+
449+
/* the SPBYT bit in SPDCR is documented only by "Technical Update" */
450+
_spi_ctrl.p_regs->SPDCR_b.SPBYT = 1; /* SPI byte access */
451+
452+
/* register undocumented for the RA4M1 but found to be working and necessary */
453+
/* BYSW - Byte Swap Operating Mode Select - 1 = Byte Swap ON - essential for 32 bit transfers */
454+
_spi_ctrl.p_regs->SPDCR2_b.BYSW = 1;
455+
456+
_spi_ctrl.p_regs->SPCKD = 0;
457+
458+
_spi_ctrl.p_regs->SSLND = 0;
459+
460+
_spi_ctrl.p_regs->SPND = 0;
461+
462+
_spi_ctrl.p_regs->SPCR2 = R_SPI0_SPCR2_SCKASE_Msk;
463+
464+
/* SPMS = 0 -> SPI operation, TXMD = 0 -> full-duplex, SPxIE = 0 -> no interrupts */
465+
if (SPI_MODE_MASTER == _spi_cfg.operating_mode) {
466+
_spi_ctrl.p_regs->SPCR_b.MSTR = 1;
467+
}
468+
469+
_spi_ctrl.p_regs->SPCMD[0] = 0;
470+
_spi_ctrl.p_regs->SPCMD_b[0].CPHA = clk_phase;
471+
_spi_ctrl.p_regs->SPCMD_b[0].CPOL = clk_polarity;
472+
_spi_ctrl.p_regs->SPCMD_b[0].BRDV = spck_div.brdv; /* set bit rate division */
473+
_spi_ctrl.p_regs->SPCMD_b[0].SPB = 7; /* spi bit width = 8 */
474+
_spi_ctrl.p_regs->SPCMD_b[0].LSBF = bit_order;
475+
476+
_spi_ctrl.p_regs->SPSR; /* read to clear OVRF */
477+
_spi_ctrl.p_regs->SPSR = 0; /* clear status register */
478+
479+
_spi_ctrl.p_regs->SPCR_b.SPE = 1; /* enable SPI unit */
480+
481+
_spi_ctrl.open = (0x52535049ULL); /* "SPI" in ASCII, used to determine if channel is open. */
392482
}
393483

394484
void ArduinoSPI::configSpiSci(arduino::SPISettings const & settings)
@@ -459,19 +549,6 @@ std::tuple<spi_clk_phase_t, spi_clk_polarity_t, spi_bit_order_t> ArduinoSPI::toF
459549
* CALLBACKS FOR FSP FRAMEWORK
460550
**************************************************************************************/
461551

462-
void spi_callback(spi_callback_args_t *p_args)
463-
{
464-
if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
465-
{
466-
_spi_cb_event[p_args->channel] = SPI_EVENT_TRANSFER_COMPLETE;
467-
}
468-
else
469-
{
470-
/* Updating the flag here to capture and handle all other error events */
471-
_spi_cb_event[p_args->channel] = SPI_EVENT_TRANSFER_ABORTED;
472-
}
473-
}
474-
475552
void sci_spi_callback(spi_callback_args_t *p_args)
476553
{
477554
int const spi_master_offset = SPI_MAX_SPI_CHANNELS;

libraries/SPI/SPI.h

-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
**************************************************************************************/
3535

3636
extern "C" {
37-
void spi_callback(spi_callback_args_t *p_args);
3837
void sci_spi_callback(spi_callback_args_t *p_args);
3938
}
4039

0 commit comments

Comments
 (0)