How to share IO between SPI module and I/O Pin functionality during runtime

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

cross mob
RuGl_1600761
Employee
Employee
25 replies posted 25 sign-ins 10 replies posted

In my application Psoc4 has to serve a device that could be configured  in SPI or parallel mode during runtime. In SPI mode pin named D0 has to be configured as MTSR, D1 has to be configured as SS,  D2 has to be configured as SCLK and  D3 has to be configured as MRST. In parallel mode  D0...D3 are part of the parallel IO (D0...D7) offering bidirectional IO. How to implement this switch on the fly?

rgl
0 Likes
1 Solution
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi @RuGl_1600761

 

To achieve this, you need to write the registers of the GPIO manually for it to behave as a software controlled GPIO. You need to set the HSIOM so that the functionality is firmware controlled GPIO, set the drive modes and write the data registers for output/read the PS register for input. 

The following code toggles between UART and normal GPIO functionality on pin P3.0 and P3.1 - 

        if(mode == 0)
        {
            /* Write the HSIOM for UART functinality */
            val = CY_GET_REG32(CYREG_HSIOM_PORT_SEL3);
            val = val | 0x00000099;
            CY_SET_REG32(CYREG_HSIOM_PORT_SEL3, val);
            
            /* Set the drive mode */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_PC);
            val = val | 0x01;
            val = val & 0xFFFFFFFE;
            CY_SET_REG32(CYREG_GPIO_PRT3_PC, val);
            
            UART_Start();
            UART_SpiUartPutArray("Hello", 6);
            CyDelay(100);
        }
        if(mode == 1)
        {
            UART_Stop();
            /* Write the HSIOM for software controlled GPIO functinality */
            val = CY_GET_REG32(CYREG_HSIOM_PORT_SEL3);
            val = val &0xFFFFFF00;
            CY_SET_REG32(CYREG_HSIOM_PORT_SEL3, val);
            
            /* Set the drive mode */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_PC);
            val = val | 0x3F;
            val = val & 0xFFFFFFF6;
            CY_SET_REG32(CYREG_GPIO_PRT3_PC, val);
            
            /*Write the data register for toggling the pin */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_DR);
            val = val |0x03;
            CY_SET_REG32(CYREG_GPIO_PRT3_DR, val);
            CyDelay(500);
            /*Write the data register for toggling the pin */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_DR);
            val = val & 0xFC;
            CY_SET_REG32(CYREG_GPIO_PRT3_DR, val);
            CyDelay(500);
            
        }

 

Best regards, 
Hari

View solution in original post

0 Likes
16 Replies
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi @RuGl_1600761

 

To achieve this, you need to write the registers of the GPIO manually for it to behave as a software controlled GPIO. You need to set the HSIOM so that the functionality is firmware controlled GPIO, set the drive modes and write the data registers for output/read the PS register for input. 

The following code toggles between UART and normal GPIO functionality on pin P3.0 and P3.1 - 

        if(mode == 0)
        {
            /* Write the HSIOM for UART functinality */
            val = CY_GET_REG32(CYREG_HSIOM_PORT_SEL3);
            val = val | 0x00000099;
            CY_SET_REG32(CYREG_HSIOM_PORT_SEL3, val);
            
            /* Set the drive mode */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_PC);
            val = val | 0x01;
            val = val & 0xFFFFFFFE;
            CY_SET_REG32(CYREG_GPIO_PRT3_PC, val);
            
            UART_Start();
            UART_SpiUartPutArray("Hello", 6);
            CyDelay(100);
        }
        if(mode == 1)
        {
            UART_Stop();
            /* Write the HSIOM for software controlled GPIO functinality */
            val = CY_GET_REG32(CYREG_HSIOM_PORT_SEL3);
            val = val &0xFFFFFF00;
            CY_SET_REG32(CYREG_HSIOM_PORT_SEL3, val);
            
            /* Set the drive mode */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_PC);
            val = val | 0x3F;
            val = val & 0xFFFFFFF6;
            CY_SET_REG32(CYREG_GPIO_PRT3_PC, val);
            
            /*Write the data register for toggling the pin */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_DR);
            val = val |0x03;
            CY_SET_REG32(CYREG_GPIO_PRT3_DR, val);
            CyDelay(500);
            /*Write the data register for toggling the pin */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_DR);
            val = val & 0xFC;
            CY_SET_REG32(CYREG_GPIO_PRT3_DR, val);
            CyDelay(500);
            
        }

 

Best regards, 
Hari

0 Likes
RuGl_1600761
Employee
Employee
25 replies posted 25 sign-ins 10 replies posted

 


@Hari wrote:

Hi @RuGl_1600761

 

To achieve this, you need to write the registers of the GPIO manually for it to behave as a software controlled GPIO. You need to set the HSIOM so that the functionality is firmware controlled GPIO, set the drive modes and write the data registers for output/read the PS register for input. 

The following code toggles between UART and normal GPIO functionality on pin P3.0 and P3.1 - 

        if(mode == 0)
        {
            /* Write the HSIOM for UART functinality */
            val = CY_GET_REG32(CYREG_HSIOM_PORT_SEL3);
            val = val | 0x00000099;
            CY_SET_REG32(CYREG_HSIOM_PORT_SEL3, val);
            
            /* Set the drive mode */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_PC);
            val = val | 0x01;
            val = val & 0xFFFFFFFE;
            CY_SET_REG32(CYREG_GPIO_PRT3_PC, val);
            
            UART_Start();
            UART_SpiUartPutArray("Hello", 6);
            CyDelay(100);
        }
        if(mode == 1)
        {
            UART_Stop();
            /* Write the HSIOM for software controlled GPIO functinality */
            val = CY_GET_REG32(CYREG_HSIOM_PORT_SEL3);
            val = val &0xFFFFFF00;
            CY_SET_REG32(CYREG_HSIOM_PORT_SEL3, val);
            
            /* Set the drive mode */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_PC);
            val = val | 0x3F;
            val = val & 0xFFFFFFF6;
            CY_SET_REG32(CYREG_GPIO_PRT3_PC, val);
            
            /*Write the data register for toggling the pin */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_DR);
            val = val |0x03;
            CY_SET_REG32(CYREG_GPIO_PRT3_DR, val);
            CyDelay(500);
            /*Write the data register for toggling the pin */
            val = CY_GET_REG32(CYREG_GPIO_PRT3_DR);
            val = val & 0xFC;
            CY_SET_REG32(CYREG_GPIO_PRT3_DR, val);
            CyDelay(500);
            
        }

 

Best regards, 
Hari


thanks Hari.

I found the documentation of HSIOM register. But how to connect the SPI is not clear  to me

RuGl_1600761_1-1614931616089.png

I can not find the description of ACT_1 in data sheet. All I can find in datasheet about using port pins is this list

RuGl_1600761_2-1614931770885.png

but no explanation how to use.  Could you help me how to connect SCLK to P0.4 ?

 

 

rgl
0 Likes

My two SPI connects this way. Second SPI module (master) connects

P0.3 MTSR; P0.4 SCLK; P0.5 MRS;

third SPI Module (slave) having only MRST (SDI input) on P0.6

The sclk  and slave select of third spi is shared with second spi. The slave select  is avaliable on P4.2

rgl
0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

You can take a look at the architecture trm for the device. In my case, I tried in a 4000S device and the architecture trm shows the hsiom matrix.

Hari_0-1614941129600.png

 

Best regards.

Hari

0 Likes
RuGl_1600761
Employee
Employee
25 replies posted 25 sign-ins 10 replies posted

ok  I find this table that tells me ACTIVE_1 is the connection to SPI (SCB)....There are several SPI available having connections to outside world (MISO,MOSI,SCLK,SS)

RuGl_1600761_1-1614943225224.png

 

RuGl_1600761_0-1614943172751.png

In The SCB chapter I find everything about the SPI module but not how to connect to the IO pins.... I think the only possibility for  would be to do bit bang 😫

I will try to generate a schematic (TopDesign) and search for the HSIOM setting  in the project.... Hoping to find the register settings....somehow reverse engineering 😡

 

 

rgl
0 Likes

I searched the files (trying reverse engineering) found a lot of defines in the cyfitter.h  and some routines that might set the ports in cyfitter_cfg.c... but nothing that I can identify  how to connect the sclk of SPIM_2  to the dedicated pin (p0.4) 

rgl
0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi @RuGl_1600761 

 

Note that fixed function SCB (non-UDB) has dedicated output pins that can be connected to the specific GPIO. This means the SPI.SS can be connected to specific pins only, MOSI to certain pins, and so on. 

In your case as well, you can see that you need to assign a value of 15 or 0xF, to the HSIOM register if you need to use SPI functionality in a particular pin. You can check this data, for the functionality supported by each pin, in the datasheet under the Pinouts tab. 

 

Having said that, this is applicable if you are not using DSI. If you are using DSI for connection (not fixed function block), then this does not hold true and it becomes easier to simply look at the value that PSoC Creator assigns and copy the same. You can check the default value of a pin, if you want to see how PSoC Creator assigns the value, in the cyfitter_cfg.c file inside the cyfitter_cfg function. In my case, you can see the HSIOM default configuration here - 

Hari_0-1614947926333.png

 

You can see that the default HSIOM configuration for port 2, where I put an SPI slave block, is "CY_SET_REG32((void *)(CYREG_HSIOM_PORT_SEL2), 0x0000FFFFu);", that is 0xFFFF. P2.0, 2.1, 2.2, and 2.3 are the SPI pins in my case and it has assigned a value of 0xF for each of those pins. 


Please let me know if you face any further difficulty.

 

Best regards, 
Hari

0 Likes
RuGl_1600761
Employee
Employee
25 replies posted 25 sign-ins 10 replies posted

I found some thing similar in the cyfitter_cfg.c

/* HSIOM Starting address: CYDEV_HSIOM_BASE */
CY_SET_REG32((void *)(CYDEV_HSIOM_BASE), 0x00330000u);
CY_SET_REG32((void *)(CYREG_HSIOM_PORT_SEL2), 0x00000333u);
CY_SET_REG32((void *)(CYREG_HSIOM_PORT_SEL3), 0x0000EE00u);
CY_SET_REG32((void *)(CYREG_HSIOM_PORT_SEL4), 0x00300000u);
CY_SET_REG32((void *)(CYREG_HSIOM_PORT_SEL5), 0x00300000u);

CYDEV_HSIOM_BASE seem to be the same as CYREG_HSIOM_PORT_SEL0 (port 0) but the 0x00330000 does not fit to my assignment SPIM_2 -> (p0.03=out(MOSI); po.4=OUT(SCLK);  p0.5=IN(MISO))

Using the table for HSIOM_PORT_SEL0 I get the 3 for P0.4 and P.5 and the 3 is DSI_GPIO and a 0 for all the other pin -> GPIO... what is DSI_GPIO ?? SO I do not think that this is the right place ???

rgl
0 Likes

#define CYDEV_HSIOM_BASE 0x40020000u

#define CYREG_HSIOM_PORT_SEL0 0x40020000u

rgl
0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi @RuGl_1600761 

 

I tried a similar configuration and the MISO line is getting an HSIOM value of 0. All others are having HSIOM config of 3. Can you check if P0.3 is connected to MISO or MOSI?

 

And I tried debugging and the configuration is the same as the one given in cyfitter_cfg API. 

Can you try this out and let me know it works? You can use the same value of HSIOM for SPI configuration. 

 

Best regards, 
Hari

0 Likes
RuGl_1600761
Employee
Employee
25 replies posted 25 sign-ins 10 replies posted

0.3 is MISO and 0.4 is MOSI. I will do the configuration and try to catch the register setting by debugging...

rgl
0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi @RuGl_1600761 

 

In that case, the configuration is correct. You need to write 0x03 on all lines and 0x00 on MISO line. 

Note that you are seeing this difference because the SCB is implemented using the UDB block and not the fixed function SCB component present in PSoC. 

 

Best regards, 
Hari

0 Likes

I just set up my target configuration. I need two Receive and one transmit channel. So I have to use a slave and a master SPI, sharing ss and sclk.

RuGl_1600761_0-1615182431875.png

unfortunately this does not work for the shared ss and sclk pins gives errors. So is bit bang than the only solution ?

 

rgl
0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Do you require the SS and SCLK pins also to be used as firmware-controlled pins? The idea is still applicable if you require only the MOSI and MISO lines to be used by firmware. 

 

Best regards, 

Hari

0 Likes
RuGl_1600761
Employee
Employee
25 replies posted 25 sign-ins 10 replies posted

Connecting SS and sclk of slave SPI and master  SPI and connecting both to port pins to connect to my DUT (SPI slave 2 inputs and two outputs) the fitter gives an error for I can not connect one sclk output of master spi to pin (for external spi slave)  and to slave spi (internal)

rgl
0 Likes
RuGl_1600761
Employee
Employee
25 replies posted 25 sign-ins 10 replies posted

thanks for your reply.  This will solve my problem.

On competitor datasheet such information is contained in the data sheet. It would be great to easily find such an information  by browsing to the device page, finding a link with a brief description... eg other vendor often has a list of links pointing to detailed description (with detailed examples)  of the peripheral and how to use it in several modes while the datasheet itself has a reduced version.

rgl
0 Likes