[XMC4800] USIC as SPI - MSLS Problem

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

cross mob
Not applicable
Hello,

I would like to use some GPIOs as additional Slave Select signals. But I do get a timing problem with the gpio slave select signal. it is way faster then the hardware slave select signal. My setup is as following.:

I'm using the XMC Llib to control the USIC, and I'm generating a hardware slave select signal which is not exposed to a pin which sets the MSLS Bit in the PSC register and wait till it is cleared. But it seems that that bit is cleared way to fast by the hardware and so my gpio slave select signal has no chance to accomplish the required timing.

Here is a little sample code which illustrates my problem.


while(1U) {
XMC_GPIO_SetOutputLow(SOFT_CS);
XMC_SPI_CH_EnableSlaveSelect(SPI2_CH1, XMC_SPI_CH_SLAVE_SELECT_0);

XMC_SPI_CH_Transmit(SPI2_CH1, 'A', XMC_SPI_CH_MODE_STANDARD);
while((XMC_SPI_CH_GetStatusFlag(SPI2_CH1) & XMC_SPI_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) == 0U);
XMC_SPI_CH_ClearStatusFlag(SPI2_CH1, XMC_SPI_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION);

XMC_SPI_CH_DisableSlaveSelect(SPI2_CH1);

// Wait till MSLS disabled
while((XMC_SPI_CH_GetStatusFlag(SPI2_CH1) & XMC_SPI_CH_STATUS_FLAG_MSLS) == 1U);


XMC_GPIO_SetOutputHigh(SOFT_CS);
}


I'm also attaching a picture of both SPI slave select signals. The first channel is the hardware slave select and second channel is the GPIO slave select.

2532.attach
0 Likes
11 Replies
Not applicable
Hi,

unfotunately I don't have an answer but a question . I would like also to use some extra GPIO's as CS. How did you do it?
Are they hardware controlled and you used the alternative hardware connections?

It yould be very helpful for me to know how. thanks!!
0 Likes
Not applicable
xmc_Nes wrote:
Hi,

unfotunately I don't have an answer but a question . I would like also to use some extra GPIO's as CS. How did you do it?
Are they hardware controlled and you used the alternative hardware connections?

It yould be very helpful for me to know how. thanks!!


I'm setting the CS like in the code snippet via software "XMC_GPIO_SetOutputLow(SOFT_CS)" and "XMC_GPIO_SetOutputHigh(SOFT_CS)".
0 Likes
DRubeša
Employee
Employee
First solution authored First like received
Just a quick question/suggestion...is it OK for both of you to use additional slave select GPIO pins? I mean, I see you´re trying to use random GPIOs to "behave" as a SS/CS line. There are plenty of additional GPIOs that can be used in alternative function as SS/CS. For example, I see that you bdyn-dm use USIC module 2 channel 1; you can select P3.0 or P4.1 as SS/CS line 0, P4.2 as SS/CS line 1, and P4.3 as SS/CS line 2.

Is such a solution acceptable by you (or you xmc_Nes)?

Best regards,
Deni
0 Likes
Not applicable
Hello DRubesa,

The reason why I need the extra GPIO's: I'm developping a load board that should also be Arduino compatible. I need to control up to 6 shields with SPI and (after possibly) with Arduino. On the Arduino pin header in the XMC4700 relaxit, only ONE pin is connected to the arduino header as CS (3.10). I definitely need more. One Solution is to short these pins on my board, which probably works but is not really elegant.
The Other possibility is to change the alternative function of other pins on the header and that's what I'm trying to do. My though is : a CS is a normal GPIO that I need to just set as low or high, so there shouldn't be a problem why it shouldn't work. What do you think?

regards

Ness
0 Likes
Not applicable
DRubeša wrote:
Just a quick question/suggestion...is it OK for both of you to use additional slave select GPIO pins? I mean, I see you´re trying to use random GPIOs to "behave" as a SS/CS line. There are plenty of additional GPIOs that can be used in alternative function as SS/CS. For example, I see that you bdyn-dm use USIC module 2 channel 1; you can select P3.0 or P4.1 as SS/CS line 0, P4.2 as SS/CS line 1, and P4.3 as SS/CS line 2.

Is such a solution acceptable by you (or you xmc_Nes)?

Best regards,
Deni


The problem is that i don't have any free SPI SS/CS Pins, I'm using, POSIF0, POSIF1, UART, two SPI Modules, and the EtherCAT Module.
0 Likes
DRubeša
Employee
Employee
First solution authored First like received
Hi *,

I understand...you both have valid uses cases that really need some other solution to substitute hardware SS/CS line with software controlled SS/CS line. The benefit of using hardware SS/CS pin is obvious, the state of the pin will be set according to the internal state machine and proper timings will be achieved. In your cases, timings are the main issue. I see that you Ness are waiting for the MSLS flag to be cleared. I would assume that is perfectly enough but as I see from your screenshot status flag is cleared some time before hardware CS lines becomes inactive. This comes from the slave select delays I guess; the hardware clears the status flag, but the internal MSLS signal becomes inactive after finishing currently running word transfer and respecting slave select delay.

For this reason I would suggest you to add additional check, wait for status flag PSR.MSLSEV. This should detect level changes and I hope this status bit will be set/reset once the whole transmit is done. After the transmit is done, it´s safe to toggle the software controlled SS/CS line.

Try adding or changing the condition in "while" loop and let me know how it went.

Best regards,
Deni
0 Likes
Not applicable
DRubeša wrote:

For this reason I would suggest you to add additional check, wait for status flag PSR.MSLSEV. This should detect level changes and I hope this status bit will be set/reset once the whole transmit is done. After the transmit is done, it´s safe to toggle the software controlled SS/CS line.


Unfortuently this is not the case :(. So as i understand there is no real solution for this problem, expect to program a software delay?
0 Likes
DRubeša
Employee
Employee
First solution authored First like received
Hi bdyn-dm,

we will not surrender so easily 😉

So, I have a new assumption...in the documentation it says that MSLSEV "indicates that the MSLS signal has changed its state since MSLSEV has been cleared". This second part is important while it says that we should clear MSLSEV before we expect MLSL value change. And I really tested this and this seams to be correct.

So where you have:

XMC_SPI_CH_ClearStatusFlag(SPI2_CH1, XMC_SPI_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION);

change to:

XMC_SPI_CH_ClearStatusFlag(SPI2_CH1, XMC_SPI_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION | XMC_SPI_CH_STATUS_FLAG_MSLS_EVENT_DETECTED);

Now I really hope we will be able to catch transition of MSLS from "1" -> "0" but when it occurs in hardware. It´s said also in the documentation that MSLSEV bit is a gating event for interrupt, so I guess that event should really come from hardware and not from software set/reset.
So, change the "while" condition that you wait while XMC_SPI_CH_STATUS_FLAG_MSLS_EVENT_DETECTED == 0 (we expect value to change to "1" which would mean that MSLS changed value).

Try something like this and let me know how it went 🙂

Best regards,
Deni
0 Likes
jferreira
Employee
Employee
10 sign-ins 5 sign-ins First like received
Hi,

You need to wait for a receive event.

  
XMC_GPIO_SetOutputLow(SPI_SS);

XMC_SPI_CH_SetTransmitMode(XMC_SPI2_CH0, XMC_SPI_CH_MODE_STANDARD);
XMC_SPI_CH_Transmit(XMC_SPI2_CH0, 0xaa, XMC_SPI_CH_MODE_STANDARD);

while((XMC_SPI_CH_GetStatusFlag(XMC_SPI2_CH0) & (XMC_SPI_CH_STATUS_FLAG_RECEIVE_INDICATION | XMC_SPI_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION)) == 0U);
XMC_SPI_CH_ClearStatusFlag(XMC_SPI2_CH0, XMC_SPI_CH_STATUS_FLAG_RECEIVE_INDICATION | XMC_SPI_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION);

XMC_GPIO_SetOutputHigh(SPI_SS);


2550.attach

Regards,
Jesus
0 Likes
Not applicable
Hi Jesus,

thank you for your replay, but i think that your example is not corrent. As you can see in your screenshot your CS signal is already inactive befor the clock signal is finished. And because of that you will not be able to recieve the correct data.

Hi Deni,

I have testet your suggestion and it seems that it is working accaptable for my applications. I have attached the complete example code for other people who might also get in trouble with such kind of problem. I alos have attached some screenshots. The first one is at a baudrate of 100Hz and the second one is at 10MHz.
2553.attach
2554.attach

#include
#include "xmc_spi.h"
#include "xmc_gpio.h"

#define SPI_MOSI P3_8
#define SPI_CS P3_10
#define SPI_CLK P3_9
#define SOFT_CS P2_11

XMC_GPIO_CONFIG_t GPO_Config = {
.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL,
.output_level = XMC_GPIO_OUTPUT_LEVEL_HIGH,
.output_strength = XMC_GPIO_OUTPUT_STRENGTH_WEAK
};

XMC_SPI_CH_CONFIG_t SPI_Config = {
.baudrate = 10000000,
.bus_mode = XMC_SPI_CH_BUS_MODE_MASTER,
.selo_inversion = XMC_SPI_CH_SLAVE_SEL_INV_TO_MSLS,
.parity_mode = XMC_USIC_CH_PARITY_MODE_NONE
};

int main(void) {
// init SPI
XMC_SPI_CH_Init(XMC_SPI2_CH0, &SPI_Config);
XMC_SPI_CH_SetBitOrderMsbFirst(XMC_SPI2_CH0);
XMC_SPI_CH_ConfigureShiftClockOutput(XMC_SPI2_CH0, XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_1_DELAY_DISABLED, XMC_SPI_CH_BRG_SHIFT_CLOCK_OUTPUT_SCLK);
XMC_GPIO_SetMode(SPI_MOSI, XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT1);
XMC_GPIO_SetMode(SPI_CS, XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT1);
XMC_GPIO_SetMode(SPI_CLK, XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT1);
XMC_GPIO_Init(SOFT_CS, &GPO_Config);
XMC_SPI_CH_Start(XMC_SPI2_CH0);

while(1U) {
// enable HW chips select which is not exposed
XMC_SPI_CH_EnableSlaveSelect(XMC_SPI2_CH0, XMC_SPI_CH_SLAVE_SELECT_0);
// enable SW chips selecht wich is exposed
XMC_GPIO_SetOutputLow(SOFT_CS);

XMC_SPI_CH_Transmit(XMC_SPI2_CH0, 'A', XMC_SPI_CH_MODE_STANDARD);
while((XMC_SPI_CH_GetStatusFlag(XMC_SPI2_CH0)
& XMC_SPI_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) == 0U);
XMC_SPI_CH_ClearStatusFlag(XMC_SPI2_CH0,
XMC_SPI_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION
| XMC_SPI_CH_STATUS_FLAG_MSLS_EVENT_DETECTED);

// disable HW chips select
XMC_SPI_CH_DisableSlaveSelect(XMC_SPI2_CH0);
// wait till the MSLS_EVENT bit is set -> indication that HW CS is disabled
while((XMC_SPI_CH_GetStatusFlag(XMC_SPI2_CH0)
& XMC_SPI_CH_STATUS_FLAG_MSLS_EVENT_DETECTED) == 0);

// disable the SW chip select
XMC_GPIO_SetOutputHigh(SOFT_CS);
}
}
0 Likes
jferreira
Employee
Employee
10 sign-ins 5 sign-ins First like received
Hi,

Sorry I used the wrong polarity/phase

#include "xmc_spi.h"
#include "xmc_gpio.h"

#define SPI_MISO P5_1
#define SPI_MOSI P5_0
#define SPI_SCLK P5_2
#define SPI_SS P2_6

const XMC_SPI_CH_CONFIG_t spi_config =
{
.baudrate = 1000000,
.bus_mode = XMC_SPI_CH_BUS_MODE_MASTER,
.parity_mode = XMC_USIC_CH_PARITY_MODE_NONE
};

int main(void)
{
XMC_GPIO_CONFIG_t gpio_config;

XMC_SPI_CH_Init(XMC_SPI2_CH0, &spi_config);

/*Input source selected*/
gpio_config.mode = XMC_GPIO_MODE_INPUT_TRISTATE;
XMC_GPIO_Init(SPI_MISO, &gpio_config);
XMC_SPI_CH_SetInputSource(XMC_SPI2_CH0, XMC_SPI_CH_INPUT_DIN0, USIC2_C0_DX0_P5_1);

XMC_SPI_CH_SetWordLength(XMC_SPI2_CH0, 8);
XMC_SPI_CH_SetFrameLength(XMC_SPI2_CH0, 8);

/* Configure the clock polarity and clock delay */
XMC_SPI_CH_ConfigureShiftClockOutput(XMC_SPI2_CH0, XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_1_DELAY_DISABLED, XMC_SPI_CH_BRG_SHIFT_CLOCK_OUTPUT_SCLK); // CPOL=1, CPHA=0

XMC_SPI_CH_Start(XMC_SPI2_CH0);

gpio_config.output_level = XMC_GPIO_OUTPUT_LEVEL_HIGH;
gpio_config.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL;
XMC_GPIO_Init(SPI_SS, &gpio_config);

gpio_config.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL | P5_0_AF_U2C0_DOUT0;
XMC_GPIO_Init(SPI_MOSI, &gpio_config);

gpio_config.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL | P5_2_AF_U2C0_SCLKOUT;
XMC_GPIO_Init(SPI_SCLK, &gpio_config);

XMC_GPIO_SetOutputLow(SPI_SS);

XMC_SPI_CH_SetTransmitMode(XMC_SPI2_CH0, XMC_SPI_CH_MODE_STANDARD);
XMC_SPI_CH_Transmit(XMC_SPI2_CH0, 0x33, XMC_SPI_CH_MODE_STANDARD);

XMC_SPI_CH_ClearStatusFlag(XMC_SPI2_CH0, XMC_SPI_CH_STATUS_FLAG_RECEIVE_INDICATION | XMC_SPI_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION);

while((XMC_SPI_CH_GetStatusFlag(XMC_SPI2_CH0) & (XMC_SPI_CH_STATUS_FLAG_RECEIVE_INDICATION | XMC_SPI_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION)) == 0U);
XMC_SPI_CH_ClearStatusFlag(XMC_SPI2_CH0, XMC_SPI_CH_STATUS_FLAG_RECEIVE_INDICATION | XMC_SPI_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION);

XMC_GPIO_SetOutputHigh(SPI_SS);

/* Placeholder for user application code. The while loop below can be replaced with user application code. */
while(1U)
{

}
}



2556.attach

Regards,
Jesus
0 Likes