Page 3 of 4

Re: SPI Slave Driver

Posted: Wed May 31, 2017 2:07 pm
by plyatov
Thanks for you attention Giovanni!

Re: SPI Slave Driver

Posted: Fri Mar 09, 2018 5:14 pm
by Xela
I'd like to bump this thread as I need to do the same thing.

I have implemented plyatov's method of adding a switch in the spiConfig to bypass the hard coded MSTR setting on the SPI_CR1.

I'm not sure which chibi spi methods I should call to handle a transaction of data from the salve to the master.

I use the following in one of my drivers that is in master mode:
spiAcquireBus(spip); // Acquire ownership of the bus.
spiSelect(spip); // Slave Select assertion.
spiSend(spip, headerLength, headerBuffer); // Slave Register Select
spiSend(spip, bodylength, bodyBuffer); // Write operation.
spiUnselect(spip); // Slave Select de-assertion.
spiReleaseBus(spip); // Ownership release.

Though that is not working here.

Should I be using spiStartExchange? Is spiAcquireBus and spiSelect not necessary?

I am just randomly trying methods, it isn't working well. Does anyone know the proper sequence of calls for slave mode transmit?

I basically need something that is going to take a buffer of data, and then wait until the master begins to clock it through and return when complete.

Cheers
Alex

Re: SPI Slave Driver

Posted: Sat Mar 10, 2018 9:10 am
by plyatov
Xela wrote:I'm not sure which chibi spi methods I should call to handle a transaction of data from the salve to the master.


Here is example of how to use my SPI slave patch in ChibiOS applications.
Example communicates with SPI master by means of tl_start_receive() and tl_start_send().
Additionally, assert_dsp_rdy() and clear_dsp_rdy() used for indication of SPI slave readiness to communicate with SPI master. Falling edge of dsp_rdy line generates IRQ for master and it initiates SPI transfer.

Code: Select all

static const SPIConfig spi2_cfg = {
   .slave_mode   = true,
   .end_cb      = NULL,
   .ssport      = GPIOB,
   .sspad      = GPIOB_SPI2_NSS,
   .cr1      = 0 // SPI_MODE_0.
};

#if (SPI_USE_WAIT != TRUE)
#error enable SPI_USE_WAIT in the halconf.h
#endif // SPI_USE_WAIT

/**
 * @brief   Sends data over the SPI bus.
 * @details This synchronous function performs a transmit operation.
 * @pre     In order to use this function the option @p SPI_USE_WAIT must be
 *          enabled.
 * @pre     In order to use this function the driver must have been configured
 *          without callbacks (@p end_cb = @p NULL).
 * @note    The buffers are organized as uint8_t arrays for data sizes below
 *          or equal to 8 bits else it is organized as uint16_t arrays.
 *
 * @param[in] spip      pointer to the @p SPIDriver object
 * @param[in] n         number of words to send
 * @param[in] txbuf     the pointer to the transmit buffer
 *
 * @api
 */
static void sspiSend(SPIDriver *spip, size_t n, const void *txbuf) {

  osalDbgCheck((spip != NULL) && (n > 0U) && (txbuf != NULL));

  osalSysLock();
  osalDbgAssert(spip->state == SPI_READY, "not ready");
  osalDbgAssert(spip->config->end_cb == NULL, "has callback");
  spiStartSendI(spip, n, txbuf);
  assert_dsp_rdy();
  (void) osalThreadSuspendS(&spip->thread);
  clear_dsp_rdy();
  osalSysUnlock();
}

/**
 * @brief   Receives data from the SPI bus.
 * @details This synchronous function performs a receive operation.
 * @pre     In order to use this function the option @p SPI_USE_WAIT must be
 *          enabled.
 * @pre     In order to use this function the driver must have been configured
 *          without callbacks (@p end_cb = @p NULL).
 * @note    The buffers are organized as uint8_t arrays for data sizes below
 *          or equal to 8 bits else it is organized as uint16_t arrays.
 *
 * @param[in] spip      pointer to the @p SPIDriver object
 * @param[in] n         number of words to receive
 * @param[out] rxbuf    the pointer to the receive buffer
 *
 * @api
 */
static void sspiReceive(SPIDriver *spip, size_t n, void *rxbuf) {

  osalDbgCheck((spip != NULL) && (n > 0U) && (rxbuf != NULL));

  osalSysLock();
  osalDbgAssert(spip->state == SPI_READY, "not ready");
  osalDbgAssert(spip->config->end_cb == NULL, "has callback");
  spiStartReceiveI(spip, n, rxbuf);
  assert_dsp_rdy();
  (void) osalThreadSuspendS(&spip->thread);
  clear_dsp_rdy();
  osalSysUnlock();
}

/**
 * tl_start_receive - setup SPI for data reception.
 */
static void tl_start_receive(void)
{
   tl_state = receive_packet;
   spiStart(&SPID2, &spi2_cfg);
   sspiReceive(&SPID2, TL_PACKET_SIZE, tl_buf);
}

/**
 * tl_start_send - setup SPI for data transmission.
 */
static void tl_start_send(void)
{
   tl_state = send_packet;
   spiStart(&SPID2, &spi2_cfg);
   sspiSend(&SPID2, TL_PACKET_SIZE, tl_buf);
}

Re: SPI Slave Driver

Posted: Mon Mar 12, 2018 11:58 am
by Xela
Thank you very much plyatov! That is a great help.

Alex

Re: SPI Slave Driver

Posted: Tue Mar 20, 2018 1:24 pm
by Xela
Now that I have my master side built up, I don't quite have this working yet.

It is likely a configuration issue though I am not 100% certain I understand the behavior of this function in terms of execution and program flow.

This spiStartSendI() will send a byte to the SPI buffer via DMA.
The loading of the SPI data register will be handled by the SPI peripheral on board the STM MCU.
I don't have to worry about the fine low level details of signalling.

I am not entirely confident if i should treat spiStartSendI() as a blocking or non-blocking function.
Will this thread remain suspended until the tx buffer has been read?

I am unfortunately working with hardware that does not have an auxiliary line to use as a DATA_RDY signal (will add one later).

At this point i just need to transmit one byte to confirm the connection works.
I run my slave board code and I assume it loads the SPI data register (LEDs/step through show the function just then waits)
On the master side i then manually execute a transfer (with code that works ok in loopback).

While I triple check every single config detail and brute force different baud rates, could someone confirm I do understand how this function is meant to be used?

Alex

Re: SPI Slave Driver

Posted: Fri Apr 06, 2018 6:47 pm
by plyatov
Xela wrote:It is likely a configuration issue

You should use only SPIx_NSS line as Chip Select. And it must be configured into Alternate mode to behave as NSS pin of corresponding SPI module.
Typically this is made in the board.h file.

Xela wrote:This spiStartSendI() will send a byte to the SPI buffer via DMA.

It will not send. It will only prepare SPI module for DMA tranfer. The transfer will be started by means of HW, only when SPI master assert NSS line of MCU.

Xela wrote:I am not entirely confident if i should treat spiStartSendI() as a blocking or non-blocking function.

It is non blocking and exits nearly immediately after call.

Xela wrote:Will this thread remain suspended until the tx buffer has been read?

Thread will be suspended by osalThreadSuspendS() until SPI transfer is finalized (NSS line is cleared).

It will be quite helpfull if you will use logical analyzer to see SPI diagrams. I recommend "Saleae Logic 16". The "Saleae Logic 8" can be used too, but it is quite limited. Look at saleae.com or better at aliexpress.com for cheaper clones :-)

Re: SPI Slave Driver

Posted: Wed Feb 20, 2019 9:31 am
by alex31
Hello,

I need advice to implement a SPI slave protocol using chibios/stm32

I want to mimic invensense IMU SPI protocol, which themselves mimic I²C protocol to read/write a register table :
The first byte sent select slave register on 7 LSB, and operation (read or write) on 1 MSB. then next bytes are read of written beginning at the selected address, and auto incrementing.

Since SPI does not permit clock stretching, it means that i only have one SPI clock cycle to get the register address, calculate the dma buffer address (an offset), and setup dma slave operation, does that will work ?

I need at least 1Mhz SPI frequency

Thanks for any advice.
Alexandre

Re: SPI Slave Driver

Posted: Wed May 08, 2019 2:17 pm
by asdasd
i am using chibios 19.1 how can i use slave spi
it seen some thing different
:oops: :idea:

Re: SPI Slave Driver

Posted: Wed May 08, 2019 2:46 pm
by Giovanni
asdasd wrote:i am using chibios 19.1 how can i use slave spi
it seen some thing different
:oops: :idea:


Hi,

There is no SPI-slave driver yet in ChibiOS, what is discussed in this thread is a customization.

Giovanni

Re: SPI Slave Driver

Posted: Wed May 08, 2019 3:46 pm
by asdasd
i know that there is no SPI slave driver, but
if i have correct understand , if i have done the spi slave v1 patch witch made by " plyatov "
it must work?? :?:
asd