I am trying to find a way to set the GPIO Port output high or low(1 or 0) with direct bit access, reading the S1JA Manual it seems that you can do this with the following code :
R_PFS->P205PFS_b.PODR = 1; // High
R_PFS->P205PFS_b.PODR = 0; // Low
None of these seem to work, I was wondering if anyone can assist me in doing this.
PS. I am writing my own driver for a device connected to different pins on different ports and therefore need to be able to set these high and low directly, I want bit access as I don't want to affect other pins on the same ports.
Regards,
Ronald
Ronald,
There are actually 3 ways to toggle an I/O port pin.
The code below shows the 3 ways. Running this code on the S1JA-TB toggles the LED, attached to port 2.5.
You have discovered yourself the protection function of the PFS registers.
Hope this is of interest.
Regards
Richard
/* HAL-only entry function */#include "hal_data.h"typedef enum e_pwpr_access{ PFS_WRITE_DISABLE = 0, ///< Disable PFS write access PFS_WRITE_ENABLE = 1 ///< Enable PFS write access} pwpr_access_t;void user_ioport_pfs_access (pwpr_access_t value);void hal_entry(void){ /* TODO: add your own code here */ /* Ensure P2.5 is an output pin */ R_IOPORT2->PCNTR1 |= 0x00000020; // b[31:16] Output data, b[15:0] input / output select while(1) { for( uint8_t loop=0; loop<3; loop++) { /* Toggle via PFS */ /* ************** */ user_ioport_pfs_access( PFS_WRITE_ENABLE ); R_PFS->P205PFS_b.PODR = 1; // High R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS); // delay so user can see the LED change state R_PFS->P205PFS_b.PODR = 0; // Low R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS); // delay so user can see the LED change state user_ioport_pfs_access( PFS_WRITE_ENABLE ); } R_BSP_SoftwareDelay(2000, BSP_DELAY_UNITS_MILLISECONDS); // long delay so user can see the the change in toggle method for( uint8_t loop=0; loop<6; loop++) { /* Toggle via PCNTR1 */ /* ***************** */ // Set high R_IOPORT2->PCNTR1 |= 0x00200000; // b[31:16] Output data, b[15:0] input / output select R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS); // Set low R_IOPORT2->PCNTR1 &= (uint32_t)~0x00200000; // b[31:16] Output data, b[15:0] input / output select R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS); } R_BSP_SoftwareDelay(2000, BSP_DELAY_UNITS_MILLISECONDS); for( uint8_t loop=0; loop<9; loop++) { /* Toggle via PCNTR3 */ /* ***************** */ // Set high R_IOPORT2->PCNTR3 |= 0x00000020; // b[31:16] Output Reset, b[15:0] Output Set R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS); // Set low R_IOPORT2->PCNTR3 |= 0x00200000; // b[31:16] Output Reset, b[15:0] Output Set R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS); } R_BSP_SoftwareDelay(2000, BSP_DELAY_UNITS_MILLISECONDS); }}void user_ioport_pfs_access (pwpr_access_t value){ if (PFS_WRITE_ENABLE == value) { R_PMISC->PWPR = 0; //< Clear BOWI bit - writing to PFSWE bit enabled R_PMISC->PWPR = 0x40; //< Set PFSWE bit - writing to PFS register enabled } else { R_PMISC->PWPR = 0; //< Clear PFSWE bit - writing to PFS register disabled R_PMISC->PWPR = 0x80; //< Set BOWI bit - writing to PFSWE bit disabled }}
Hello Ronald,
I'll just leave a note here that accessing PMISC registers directly without any critical section and counter is not a recommended approach. Here's how IOPORT driver performs locking and unlocking of these registers:
Use of critical section ensures uninterrupted access for the duration of PMISC access. Reference counter is used to make sure that only the last context to call PFSAccessDisable will actually lock the registers. It's highly recommended that these functions are invoked or recreated in your code to prevent any potential issues associated with different threads/interrupts performing PFS access.