Writing to a PSoC3 GPIO – Various options | Cypress Semiconductor
Writing to a PSoC3 GPIO – Various options
Any microcontroller project will have the need to control a GPIO pin using a CPU. Applications could be simple ones like switching On/Off an LED, a relay, a buzzer etc to complex ones like generating a software PWM, bit-banging I2C protocol etc.
There are many options to control a PSoC3 GPIO in firmware. Let us take a look at some of these options and their pros and cons.
Option-1: Use Port in APIs
When a Digital Output Port component is placed in the project, the PSoC Creator generates API functions to control the port pin. The function used to write to the pin is <Pin Name>_Write. For example, for a Port 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 the ease of programming and portability.
Cons: The disadvantage of using this method is the high number of processor cycles taken to update the pin. Following is the listing of the Output1_Write function.
; void Out1_Write(uint8 value)
; SOURCE LINE # 34
; SOURCE LINE # 35
; uint8 staticBits = Out1_DR & ~Out1_MASK;
; SOURCE LINE # 36
; Out1_DR = staticBits | ((value << Out1_SHIFT) & Out1_MASK);
; SOURCE LINE # 37
; SOURCE LINE # 38
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 <Pin Name>.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 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 less processor cycles than the API function call. The example code #1 above results in the below compiled code.
; Out1_DR |= Out1_MASK;
; SOURCE LINE # 41
This takes 13 CPU cycles, about 4 times faster than the Port pin API function call.
Cons: There isn’t any great disadvantage of using this method other than the fact that this method is still slower than Option-3 below, and sacrifices some amount of 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 SFRPRT0DR register controls the state of P0.
SFRPRTxSEL: Setting the corresponding bit in this register, enables the control of the port pin through the SFRPRTxDR register. For example, if Bit5 of SFRPRT0SEL is set, then the state of P0 is controlled by the value of Bit5 of SFRPRT0DR register. If the bit is cleared, the port can be controlled only through the PHUB interface.
These registers are declared in PSoC3_8051.h header file under the cy_boot folder in the workspace explorer. Details of these registers may be found in PSoC3 Technical Reference Manual under Section 4.6.4 – I/O Port Access SFRs.
For example, to switch On/Off P1
// First enable SFR access for P1. 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 3 CPU cycles to execute.
Cons: Not portable. If you relocate a Port Pin component in the schematic to a different GPIO port, then all the code that access the pin through SFRs have to be rewritten.
1. If the project does not have any timing restrictions and you prefer readability over execution time, use Option-1
2. If you are working on time critical application where every processor cycle counts, and readability or portability is not important, use Option-3.
3. Option-2 is the ideal solution where it has 4x speed over Option-1 and does not sacrifice portability.