Controlling a PSoC® 3 and 5LP GPIO in Firmware – KBA82883

Version: **


Question: How do you control a PSoC® 3 and 5LP GPIO in firmware?



There are many options to control a PSoC 3 and 5LP GPIO in firmware. Here are some of these options and their pros and cons.

Option 1: Use Pins Component APIs

When a Digital Output Pin Component is placed in the project, PSoC Creator™ generates API functions to control the port pin. The function used to write to the pin is _Write. For example, for a Digital Output Pin Component named Out1:

Out1_Write(1); // Set the pin Out1_Write(0); // Clear the pin

Pros: The advantage of using the API function is ease of programming and portability.

Cons: The disadvantage of using this method is the high number of processor cycles taken to update the pin. The following is a listing of the Output1_Write function. (Note: This is for PSoC 3. It is different for PSoC 5LP since the compiler is different, but the concept is similar.)

; void Out1_Write(uint8 value) RSEG ?PR?_Out1_Write?OUT1 _Out1_Write: USING 0 ; SOURCE LINE # 34 MOV DPTR,#value?040 MOV A,R7 MOVX @DPTR,A ; { ; SOURCE LINE # 35 ; uint8 staticBits = Out1_DR & ~Out1_MASK; MOV DPTR,#05100H MOVX A,@DPTR MOV R7,A MOV A,R7 ANL A,#0EFH MOV R7,A MOV DPTR,#staticBits?041 MOV A,R7 MOVX @DPTR,A ; Out1_DR = staticBits | ((value << Out1_SHIFT) & Out1_MASK); ; SOURCE LINE # 37 MOV DPTR,#value?040 MOVX A,@DPTR MOV R7,A MOV A,R7 SWAP A ANL A,#0F0H MOV R7,A MOV A,R7 ANL A,#010H MOV R7,A MOV DPTR,#staticBits?041 MOVX A,@DPTR MOV R6,A MOV A,R7 ORL A,R6 MOV R7,A MOV DPTR,#05100H MOV A,R7 MOVX @DPTR,A ; } ; SOURCE LINE # 38 ?C0001: RET

The above code takes 58 CPU cycles, including the call and return.

Option 2: Use Port Data Register and Mask

In this method, the port data register is accessed in the external data memory space using the PHUB. For every Port Pin placed in the schematic, a header file .h has the declarations for the port data register and the mask. For a Port Pin named Out1, the port data register and the mask are Out1_DR and Out1_MASK respectively. For example:

Out1_DR |= Out1_MASK; // Set the pin Out1_DR &= ~Out1_MASK; // Clear the pin

Pros: This type of access takes fewer processor cycles than the API function call. The example code from Option 1 results in the following compiled code. (Note: This is for PSoC 3. It is different for PSoC 5LP since the compiler is different, but the concept is similar.)


This takes 13 CPU cycles, about four times faster than the Pins Component API function call.

Cons: There is no great disadvantage to using this method. However, it is still slower than Option 3, and sacrifices some readability compared to Option 1.

Option 3: Control the Pin using the SFR Register Space

In this method, the port data register is accessed directly in the SFR register space. There are two SFRs that need to be controlled.

SFRPRTxDR: The register bits control the bits of the corresponding port. For example, the value in Bit5 of the SFRPRT0DR register controls the state of P0[5].

SFRPRTxSEL: Setting the corresponding bit in this register enables control of the port pin through the SFRPRTxDR register. For example, if Bit5 of SFRPRT0SEL is set, then the state of P0[5] is controlled by the value of Bit5 of the SFRPRT0DR register. If the bit is cleared, then the port can be controlled only through the PHUB interface.

These registers are declared in the PSoC3_8051.h header file under the “cy_boot” folder in Workspace Explorer. Details of these registers may be found in the PSoC 3 TRM under Section 4.6.4 – I/O Port Access SFRs.

For example, to switch On/Off P1[5]:

// First enable SFR access for P1[5]. This has to be done only once in the beginning of code SFRPRT1SEL |= 0x20; // To switch on SFRPRT1DR |= 0x20; // To switch off SFRPRT1DR &= ~0x20; // To toggle SFRPRT1DR ^= 0x20;

Pros: This is the fastest way to modify the port pin state. This takes a single direct memory access instruction and takes three CPU cycles to execute.

Cons: It is not portable. If you relocate a Port Pin component in the schematic to a different GPIO port, then all the code that accesses the pin through SFRs has to be rewritten. The portability can be increased by using macros—for example:

#define LEDON ( SFRPRT1DR |= 0x20; )

Now this macro can be called anywhere in the code to switch on the GPIO. Any changes need to be done only to the macro. Enabling the SFR access through the SFRPRTxSEL register still has to be done.


  •   If the project does not have any timing restrictions and you prefer readability over execution time, use Option 1.
  •   If you are working on a time-critical application where every processor cycle counts, and readability or portability is not important,use Option 3.
  •   Option 2 is a great compromise because it has four times the speed of Option 1 and does not sacrifice portability.
  •   For more information on GPIO usage in PSoC 3 and PSoC 5LP, please refer to AN72382 - Using PSoC® 3 and PSoC 5LP GPIO Pins.