There are two bits to select one of four possible connections for each GPIO pin.
How to control those two bits?
There are two bits to select one of four possible connections for each GPIO pin.
How to control those two bits?
If it helps, Here is a function I wrote to provide the control I needed for GPIO or Peripherals connecting to the physical pin.
#define FOS_PORT_A_FER_REGISTER 0x20040000
#define FOS_PORT_A_MUX_REGISTER 0x20040030
#define FOS_PORT_B_FER_REGISTER 0x20040080
#define FOS_PORT_B_MUX_REGISTER 0x200400B0
#define FOS_PORT_C_FER_REGISTER 0x20040100
#define FOS_PORT_C_MUX_REGISTER 0x20040130
/*******************************************************************************
*
* Function: fosGpioPinControl
*
* Inputs: int gpio The Pin number to setup 0-47
* int forceAsPeripheral Flag that indicates GPIO or Peripheral 0 or 1
* u32 peripheralMux The mux value of the peripherail. 0,1,2 or 3
*
* Outputs: -1 for error, otherwise 0
*
* Description: This function will setup the pin to work as a GPIO or as
* a peripheral. If it is a peripheral, it will set the correct
* mux value to get the correct peripheral out to the pin.
* Pin number 0-15 portA 0:15, 16-31 portB 0:15, 32-47 portC 0:15
*
* Cautions: None
*
******************************************************************************/
int fosGpioPinControl(int gpio, int forceAsPeripheral, u32 peripheralMux)
{
u32 gpioMask;
u32 gpioMuxMask;
volatile u32* gpioFerRegister;
volatile u32* gpioMuxRegister;
u32 data;
/* There is not any looping going on. The while loop allows for
* a convenient way to find the condition and then exit out.
*/
do
{
if (gpio < 16)
{ /* Port F is 0 to 15 */
gpioFerRegister = (volatile u32*) FOS_PORT_A_FER_REGISTER;
gpioMuxRegister = (volatile u32*) FOS_PORT_A_MUX_REGISTER;
break;
}
if (gpio < 32)
{/* Port G is 16 to 31 */
gpioFerRegister = (volatile u32*) FOS_PORT_B_FER_REGISTER;
gpioMuxRegister = (volatile u32*) FOS_PORT_B_MUX_REGISTER;
gpio -= 16;
break;
}
if (gpio < 48)
{/* Port H is 32 to 47 */
gpioFerRegister = (volatile u32*) FOS_PORT_C_FER_REGISTER;
gpioMuxRegister = (volatile u32*) FOS_PORT_C_MUX_REGISTER;
gpio -= 32;
break;
}
return -1; /* The gpio value is out of range */
} while(1); /* End fake while loop */
gpioMask = (0x1 << gpio);
gpioMuxMask = (0x3 << (gpio * 2));
peripheralMux &= 0x3; /* limit the mask to 2 bits */
peripheralMux = (peripheralMux << (gpio * 2));
if (forceAsPeripheral == 1)
{
/* Connect the peripherial to the external pin */
data = *gpioFerRegister;
data |= gpioMask;
*gpioFerRegister = data;
asm("ssync;");
/* Calculate and set the requested mux level */
data = *gpioMuxRegister;
/* Clear out old mux bits first */
data &= ~(gpioMuxMask);
/* Set GPIO pins for the requested mux function */
data |= peripheralMux;
*gpioMuxRegister = data;
asm("ssync;");
}
else
{
/* Connect the GPIO functionality to the external pin */
data = *gpioFerRegister;
data &= ~(gpioMask);
*gpioFerRegister = data;
asm("ssync;");
}
return 0;
}
If it helps, Here is a function I wrote to provide the control I needed for GPIO or Peripherals connecting to the physical pin.
#define FOS_PORT_A_FER_REGISTER 0x20040000
#define FOS_PORT_A_MUX_REGISTER 0x20040030
#define FOS_PORT_B_FER_REGISTER 0x20040080
#define FOS_PORT_B_MUX_REGISTER 0x200400B0
#define FOS_PORT_C_FER_REGISTER 0x20040100
#define FOS_PORT_C_MUX_REGISTER 0x20040130
/*******************************************************************************
*
* Function: fosGpioPinControl
*
* Inputs: int gpio The Pin number to setup 0-47
* int forceAsPeripheral Flag that indicates GPIO or Peripheral 0 or 1
* u32 peripheralMux The mux value of the peripherail. 0,1,2 or 3
*
* Outputs: -1 for error, otherwise 0
*
* Description: This function will setup the pin to work as a GPIO or as
* a peripheral. If it is a peripheral, it will set the correct
* mux value to get the correct peripheral out to the pin.
* Pin number 0-15 portA 0:15, 16-31 portB 0:15, 32-47 portC 0:15
*
* Cautions: None
*
******************************************************************************/
int fosGpioPinControl(int gpio, int forceAsPeripheral, u32 peripheralMux)
{
u32 gpioMask;
u32 gpioMuxMask;
volatile u32* gpioFerRegister;
volatile u32* gpioMuxRegister;
u32 data;
/* There is not any looping going on. The while loop allows for
* a convenient way to find the condition and then exit out.
*/
do
{
if (gpio < 16)
{ /* Port F is 0 to 15 */
gpioFerRegister = (volatile u32*) FOS_PORT_A_FER_REGISTER;
gpioMuxRegister = (volatile u32*) FOS_PORT_A_MUX_REGISTER;
break;
}
if (gpio < 32)
{/* Port G is 16 to 31 */
gpioFerRegister = (volatile u32*) FOS_PORT_B_FER_REGISTER;
gpioMuxRegister = (volatile u32*) FOS_PORT_B_MUX_REGISTER;
gpio -= 16;
break;
}
if (gpio < 48)
{/* Port H is 32 to 47 */
gpioFerRegister = (volatile u32*) FOS_PORT_C_FER_REGISTER;
gpioMuxRegister = (volatile u32*) FOS_PORT_C_MUX_REGISTER;
gpio -= 32;
break;
}
return -1; /* The gpio value is out of range */
} while(1); /* End fake while loop */
gpioMask = (0x1 << gpio);
gpioMuxMask = (0x3 << (gpio * 2));
peripheralMux &= 0x3; /* limit the mask to 2 bits */
peripheralMux = (peripheralMux << (gpio * 2));
if (forceAsPeripheral == 1)
{
/* Connect the peripherial to the external pin */
data = *gpioFerRegister;
data |= gpioMask;
*gpioFerRegister = data;
asm("ssync;");
/* Calculate and set the requested mux level */
data = *gpioMuxRegister;
/* Clear out old mux bits first */
data &= ~(gpioMuxMask);
/* Set GPIO pins for the requested mux function */
data |= peripheralMux;
*gpioMuxRegister = data;
asm("ssync;");
}
else
{
/* Connect the GPIO functionality to the external pin */
data = *gpioFerRegister;
data &= ~(gpioMask);
*gpioFerRegister = data;
asm("ssync;");
}
return 0;
}