Not applicable
Mar 05, 2017
02:40 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 05, 2017
02:40 AM
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.
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.
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.
11 Replies
Not applicable
Mar 06, 2017
01:17 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 06, 2017
01:17 AM
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!!
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!!
Not applicable
Mar 06, 2017
06:22 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 06, 2017
06:22 AM
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)".
Mar 07, 2017
02:16 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 07, 2017
02:16 AM
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
Is such a solution acceptable by you (or you xmc_Nes)?
Best regards,
Deni
Not applicable
Mar 07, 2017
05:01 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 07, 2017
05:01 AM
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
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
Not applicable
Mar 07, 2017
06:47 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 07, 2017
06:47 AM
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.
Mar 07, 2017
08:58 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 07, 2017
08:58 AM
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
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
Not applicable
Mar 08, 2017
04:50 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 08, 2017
04:50 AM
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?
Mar 16, 2017
12:51 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 16, 2017
12:51 PM
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
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
Mar 17, 2017
07:00 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 17, 2017
07:00 AM
Hi,
You need to wait for a receive event.
Regards,
Jesus
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);
Regards,
Jesus
Not applicable
Mar 20, 2017
01:08 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 20, 2017
01:08 AM
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.
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.
#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);
}
}
Mar 20, 2017
06:46 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 20, 2017
06:46 AM
Hi,
Sorry I used the wrong polarity/phase
Regards,
Jesus
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)
{
}
}
Regards,
Jesus