Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
jamesk
Level 3
Level 3
First solution authored 5 replies posted 5 sign-ins

I am using an XMC4800 as SPI Master communicating with a radio where the typical SPI communication is to transmit a short command and  receive some number of bytes in response.

I have the SPI configured for DMA TX and INTERRUPT RX.

When using SPI_MASTER_Transfer(), the response data is successfully received.  In this case the same buffer for TX and RX is used, the command sequence written to the start of the buffer, the rest of the bytes are filled with 0xff, and the command response is copied out from the buffer from the bytes following the command bytes.  I don't care about the MISO bytes returned over the command bytes.

Instead of populating a transfer buffer I would like to just transmit the command and read the expected number of response bytes to eliminate the buffer filling and copy-out.  I've tried the following sequence instead but the received bytes are always incorrect.

SPI_MASTER_Transmit(&SPI_MASTER_RADIO, &cmd, sizeof(cmd));
SPI_MASTER_Receive(&SPI_MASTER_RADIO, dst, len);

I believe the nCS is de-asserted between the commands which is terminating the radio command.

How can I keep the nCS asserted between the commands?

0 Likes
1 Solution
ncbs
Moderator
Moderator
Moderator
500 replies posted 50 likes received 250 sign-ins

Hi @jamesk,

You can use a dedicated GPIO pin connected to CS instead of that of the SPI APP. You may configure the pin to "input/output" direction, "push pull" output mode. The logic states of the pin may be defined just before the SPI data transfer happens.

Let us know if this helps.

Regards,
Nikhil

View solution in original post

0 Likes
5 Replies
ncbs
Moderator
Moderator
Moderator
500 replies posted 50 likes received 250 sign-ins

Hi @jamesk,

Could you provide more details about DMA TX and INTERRUPT RX?

SPI_MASTER_Transfer requires 2 separate buffers for Tx and Rx. How is the same buffer being used? I believe this would result in some loss of data.

Does the application require knowing only the length of the received data (from slave) and not the data itself?

If possible, can you confirm if the CS enters unknown/undesired state through oscilloscope? During such situations, we can assign a GPIO to CS and manually control the GPIO.

Thanks and regards,
Nikhil

0 Likes
jamesk
Level 3
Level 3
First solution authored 5 replies posted 5 sign-ins

DAVE configuration, provided to me, has the option for selecting transfer method on SPI.  The resulting config is​

.transmit_mode = SPI_MASTER_TRANSFER_MODE_DMA,
.receive_mode = SPI_MASTER_TRANSFER_MODE_INTERRUPT,

For reducing memory requirements with separate buffers, the same pointer is given to SPI_MASTER_Transfer for tx and rx.  As with all SPI implementation the data clocked out from the tx happens before the data clocked in is written to the buffer so there is no loss of data.

The application already knows how many bytes will come from the slave for each command request.

I've come to the conclusion that it is the CS because I see the radio is treating the fill byte, 0xFF, as the radio's NOP command and always returning the status byte instead of the bytes from the previous command.

Yes please, how do I go about manually controlling the CS?

I've tried wrapping my Transmit and Receive with the following commands but still no luck.

XMC_SPI_CH_EnableFEM(SPI_MASTER_RADIO.channel);
SPI_MASTER_EnableSlaveSelectSignal(&SPI_MASTER_RADIO, SPI_MASTER_SS_SIGNAL_0);

SPI_MASTER_DisableSlaveSelectSignal(&SPI_MASTER_RADIO);
XMC_SPI_CH_DisableFEM(SPI_MASTER_RADIO.channel);

Here is how the CS is configured in the Dave Generated SPI conf.c

 

const SPI_MASTER_GPIO_t SPI_MASTER_RADIO_SS_0 =
{
.port = (XMC_GPIO_PORT_t *)PORT0_BASE,
.pin = (uint8_t)12
};
const SPI_MASTER_GPIO_CONFIG_t SPI_MASTER_RADIO_SS_0_Config =
{
.port_config =
{
    .mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT2,
    .output_level = XMC_GPIO_OUTPUT_LEVEL_HIGH,
    .output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_SOFT_EDGE
  },
  .slave_select_ch = XMC_SPI_CH_SLAVE_SELECT_0
};


const SPI_MASTER_CONFIG_t SPI_MASTER_RADIO_Config  = 
{

  .slave_select_pin        = {&SPI_MASTER_RADIO_SS_0, NULL,
                              NULL, NULL,
                              NULL, NULL,
                              NULL, NULL
                             },
  .slave_select_pin_config = {&SPI_MASTER_RADIO_SS_0_Config, NULL,
                              NULL, NULL,
                              NULL, NULL,
                              NULL, NULL
                             },
};

 

 

0 Likes
ncbs
Moderator
Moderator
Moderator
500 replies posted 50 likes received 250 sign-ins

Hi @jamesk,

You can use a dedicated GPIO pin connected to CS instead of that of the SPI APP. You may configure the pin to "input/output" direction, "push pull" output mode. The logic states of the pin may be defined just before the SPI data transfer happens.

Let us know if this helps.

Regards,
Nikhil

0 Likes
jamesk
Level 3
Level 3
First solution authored 5 replies posted 5 sign-ins

I don't know what you mean.  The pin in the configuration above is dedicated to the radio CS.

Are you saying I can and have to decouple the CS from the SPI APP manually before I can use the SPI_MASTER_DisableSlaveSelectSignal()/SPI_MASTER_EnableSlaveSelectSignal() APIs?

Would the change be to replace the SPI_MASTER_RADIO_SS_0* entries for .slave_select_pin and .slave_select_pin_config with NULL?  And then manually initialize the pin with some other API instead?

Do you have some example to explain how I change the generated code to gain more control?

0 Likes
ncbs
Moderator
Moderator
Moderator
500 replies posted 50 likes received 250 sign-ins

Hi @jamesk,

Yes, disconnect the CS signal from the SPI APP and connect an external GPIO. 

Manually initialize a GPIO pin and control it in your application.

Regards,
Nikhil

0 Likes