488 lines
12 KiB
C
488 lines
12 KiB
C
|
//###########################################################################
|
||
|
//
|
||
|
// FILE: gpio.c
|
||
|
//
|
||
|
// TITLE: C28x GPIO driver.
|
||
|
//
|
||
|
//###########################################################################
|
||
|
// $Copyright:
|
||
|
// Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com
|
||
|
//
|
||
|
// Redistribution and use in source and binary forms, with or without
|
||
|
// modification, are permitted provided that the following conditions
|
||
|
// are met:
|
||
|
//
|
||
|
// Redistributions of source code must retain the above copyright
|
||
|
// notice, this list of conditions and the following disclaimer.
|
||
|
//
|
||
|
// Redistributions in binary form must reproduce the above copyright
|
||
|
// notice, this list of conditions and the following disclaimer in the
|
||
|
// documentation and/or other materials provided with the
|
||
|
// distribution.
|
||
|
//
|
||
|
// Neither the name of Texas Instruments Incorporated nor the names of
|
||
|
// its contributors may be used to endorse or promote products derived
|
||
|
// from this software without specific prior written permission.
|
||
|
//
|
||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
// $
|
||
|
//###########################################################################
|
||
|
|
||
|
#include "gpio.h"
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_setDirectionMode
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
GPIO_setDirectionMode(uint32_t pin, GPIO_Direction pinIO)
|
||
|
{
|
||
|
volatile uint32_t *gpioBaseAddr;
|
||
|
uint32_t pinMask;
|
||
|
|
||
|
//
|
||
|
// Check the arguments.
|
||
|
//
|
||
|
ASSERT(GPIO_isPinValid(pin));
|
||
|
|
||
|
gpioBaseAddr = (uint32_t *)GPIOCTRL_BASE +
|
||
|
((pin / 32U) * GPIO_CTRL_REGS_STEP);
|
||
|
pinMask = (uint32_t)1U << (pin % 32U);
|
||
|
|
||
|
EALLOW;
|
||
|
|
||
|
//
|
||
|
// Set the data direction
|
||
|
//
|
||
|
if(pinIO == GPIO_DIR_MODE_OUT)
|
||
|
{
|
||
|
//
|
||
|
// Output
|
||
|
//
|
||
|
gpioBaseAddr[GPIO_GPxDIR_INDEX] |= pinMask;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Input
|
||
|
//
|
||
|
gpioBaseAddr[GPIO_GPxDIR_INDEX] &= ~pinMask;
|
||
|
}
|
||
|
|
||
|
EDIS;
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_getDirectionMode
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
GPIO_Direction
|
||
|
GPIO_getDirectionMode(uint32_t pin)
|
||
|
{
|
||
|
volatile uint32_t *gpioBaseAddr;
|
||
|
|
||
|
//
|
||
|
// Check the arguments.
|
||
|
//
|
||
|
ASSERT(GPIO_isPinValid(pin));
|
||
|
|
||
|
gpioBaseAddr = (uint32_t *)GPIOCTRL_BASE +
|
||
|
((pin / 32U) * GPIO_CTRL_REGS_STEP);
|
||
|
|
||
|
return((GPIO_Direction)((uint32_t)((gpioBaseAddr[GPIO_GPxDIR_INDEX] >>
|
||
|
(pin % 32U)) & 1U)));
|
||
|
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_setInterruptPin
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
GPIO_setInterruptPin(uint32_t pin, GPIO_ExternalIntNum extIntNum)
|
||
|
{
|
||
|
XBAR_InputNum input;
|
||
|
|
||
|
//
|
||
|
// Check the arguments.
|
||
|
//
|
||
|
ASSERT(GPIO_isPinValid(pin));
|
||
|
|
||
|
//
|
||
|
// Pick the X-BAR input that corresponds to the requested XINT.
|
||
|
//
|
||
|
switch(extIntNum)
|
||
|
{
|
||
|
case GPIO_INT_XINT1:
|
||
|
input = XBAR_INPUT4;
|
||
|
break;
|
||
|
|
||
|
case GPIO_INT_XINT2:
|
||
|
input = XBAR_INPUT5;
|
||
|
break;
|
||
|
|
||
|
case GPIO_INT_XINT3:
|
||
|
input = XBAR_INPUT6;
|
||
|
break;
|
||
|
|
||
|
case GPIO_INT_XINT4:
|
||
|
input = XBAR_INPUT13;
|
||
|
break;
|
||
|
|
||
|
case GPIO_INT_XINT5:
|
||
|
input = XBAR_INPUT14;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
//
|
||
|
// Invalid interrupt. Shouldn't happen if enum value is used.
|
||
|
// XBAR_INPUT1 isn't tied to an XINT, so we'll use it to check for
|
||
|
// a bad value.
|
||
|
//
|
||
|
input = XBAR_INPUT1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(input != XBAR_INPUT1)
|
||
|
{
|
||
|
XBAR_setInputPin(input, (uint16_t)pin);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_setPadConfig
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
GPIO_setPadConfig(uint32_t pin, uint32_t pinType)
|
||
|
{
|
||
|
volatile uint32_t *gpioBaseAddr;
|
||
|
uint32_t pinMask;
|
||
|
|
||
|
//
|
||
|
// Check the arguments.
|
||
|
//
|
||
|
ASSERT(GPIO_isPinValid(pin));
|
||
|
|
||
|
gpioBaseAddr = (uint32_t *)GPIOCTRL_BASE +
|
||
|
((pin / 32U) * GPIO_CTRL_REGS_STEP);
|
||
|
pinMask = (uint32_t)1U << (pin % 32U);
|
||
|
|
||
|
EALLOW;
|
||
|
|
||
|
//
|
||
|
// Enable open drain if necessary
|
||
|
//
|
||
|
if((pinType & GPIO_PIN_TYPE_OD) != 0U)
|
||
|
{
|
||
|
gpioBaseAddr[GPIO_GPxODR_INDEX] |= pinMask;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gpioBaseAddr[GPIO_GPxODR_INDEX] &= ~pinMask;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Enable pull-up if necessary
|
||
|
//
|
||
|
if((pinType & GPIO_PIN_TYPE_PULLUP) != 0U)
|
||
|
{
|
||
|
gpioBaseAddr[GPIO_GPxPUD_INDEX] &= ~pinMask;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gpioBaseAddr[GPIO_GPxPUD_INDEX] |= pinMask;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Invert polarity if necessary
|
||
|
//
|
||
|
if((pinType & GPIO_PIN_TYPE_INVERT) != 0U)
|
||
|
{
|
||
|
gpioBaseAddr[GPIO_GPxINV_INDEX] |= pinMask;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gpioBaseAddr[GPIO_GPxINV_INDEX] &= ~pinMask;
|
||
|
}
|
||
|
|
||
|
EDIS;
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_getPadConfig
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
uint32_t
|
||
|
GPIO_getPadConfig(uint32_t pin)
|
||
|
{
|
||
|
volatile uint32_t *gpioBaseAddr;
|
||
|
uint32_t pinMask;
|
||
|
uint32_t pinTypeRes;
|
||
|
|
||
|
//
|
||
|
// Check the arguments.
|
||
|
//
|
||
|
ASSERT(GPIO_isPinValid(pin));
|
||
|
|
||
|
gpioBaseAddr = (uint32_t *)GPIOCTRL_BASE +
|
||
|
((pin / 32U) * GPIO_CTRL_REGS_STEP);
|
||
|
pinMask = (uint32_t)1U << (pin % 32U);
|
||
|
|
||
|
pinTypeRes = GPIO_PIN_TYPE_STD;
|
||
|
|
||
|
//
|
||
|
// Get open drain value
|
||
|
//
|
||
|
if((gpioBaseAddr[GPIO_GPxODR_INDEX] & pinMask) != 0U)
|
||
|
{
|
||
|
pinTypeRes |= GPIO_PIN_TYPE_OD;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get pull-up value
|
||
|
//
|
||
|
if((gpioBaseAddr[GPIO_GPxPUD_INDEX] & pinMask) == 0U)
|
||
|
{
|
||
|
pinTypeRes |= GPIO_PIN_TYPE_PULLUP;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get polarity value
|
||
|
//
|
||
|
if((gpioBaseAddr[GPIO_GPxINV_INDEX] & pinMask) != 0U)
|
||
|
{
|
||
|
pinTypeRes |= GPIO_PIN_TYPE_INVERT;
|
||
|
}
|
||
|
|
||
|
return(pinTypeRes);
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_setQualificationMode
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
GPIO_setQualificationMode(uint32_t pin, GPIO_QualificationMode qualification)
|
||
|
{
|
||
|
volatile uint32_t *gpioBaseAddr;
|
||
|
uint32_t qSelIndex;
|
||
|
uint32_t shiftAmt;
|
||
|
|
||
|
//
|
||
|
// Check the arguments.
|
||
|
//
|
||
|
ASSERT(GPIO_isPinValid(pin));
|
||
|
|
||
|
gpioBaseAddr = (uint32_t *)GPIOCTRL_BASE +
|
||
|
((pin / 32U) * GPIO_CTRL_REGS_STEP);
|
||
|
shiftAmt = (uint32_t)GPIO_GPAQSEL1_GPIO1_S * (pin % 16U);
|
||
|
qSelIndex = GPIO_GPxQSEL_INDEX + ((pin % 32U) / 16U);
|
||
|
|
||
|
//
|
||
|
// Write the input qualification mode to the register.
|
||
|
//
|
||
|
EALLOW;
|
||
|
|
||
|
gpioBaseAddr[qSelIndex] &= ~((uint32_t)GPIO_GPAQSEL1_GPIO0_M << shiftAmt);
|
||
|
gpioBaseAddr[qSelIndex] |= (uint32_t)qualification << shiftAmt;
|
||
|
|
||
|
EDIS;
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_getQualificationMode
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
GPIO_QualificationMode
|
||
|
GPIO_getQualificationMode(uint32_t pin)
|
||
|
{
|
||
|
volatile uint32_t *gpioBaseAddr;
|
||
|
uint32_t qSelIndex;
|
||
|
uint32_t qualRes;
|
||
|
uint32_t shiftAmt;
|
||
|
|
||
|
//
|
||
|
// Check the arguments.
|
||
|
//
|
||
|
ASSERT(GPIO_isPinValid(pin));
|
||
|
|
||
|
gpioBaseAddr = (uint32_t *)GPIOCTRL_BASE +
|
||
|
((pin / 32U) * GPIO_CTRL_REGS_STEP);
|
||
|
shiftAmt = (uint32_t)GPIO_GPAQSEL1_GPIO1_S * (pin % 16U);
|
||
|
qSelIndex = GPIO_GPxQSEL_INDEX + ((pin % 32U) / 16U);
|
||
|
|
||
|
//
|
||
|
// Read the qualification mode register and shift and mask to get the
|
||
|
// value for the specified pin.
|
||
|
//
|
||
|
qualRes = (gpioBaseAddr[qSelIndex] >> shiftAmt) &
|
||
|
(uint32_t)GPIO_GPAQSEL1_GPIO0_M;
|
||
|
return((GPIO_QualificationMode)qualRes);
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_setQualificationPeriod
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
GPIO_setQualificationPeriod(uint32_t pin, uint32_t divider)
|
||
|
{
|
||
|
volatile uint32_t *gpioBaseAddr;
|
||
|
uint32_t pinMask, regVal, shiftAmt;
|
||
|
|
||
|
//
|
||
|
// Check the arguments.
|
||
|
//
|
||
|
ASSERT(GPIO_isPinValid(pin));
|
||
|
ASSERT((divider >= 1U) && (divider <= 510U));
|
||
|
|
||
|
shiftAmt = (pin % 32U) & ~((uint32_t)0x7U);
|
||
|
pinMask = (uint32_t)0xFFU << shiftAmt;
|
||
|
|
||
|
//
|
||
|
// Divide divider by two to get the value that needs to go into the field.
|
||
|
// Then shift it into the right place.
|
||
|
//
|
||
|
regVal = (divider / 2U) << shiftAmt;
|
||
|
|
||
|
//
|
||
|
// Write the divider parameter into the register.
|
||
|
//
|
||
|
gpioBaseAddr = (uint32_t *)GPIOCTRL_BASE +
|
||
|
((pin / 32U) * GPIO_CTRL_REGS_STEP);
|
||
|
|
||
|
EALLOW;
|
||
|
gpioBaseAddr[GPIO_GPxCTRL_INDEX] &= ~pinMask;
|
||
|
gpioBaseAddr[GPIO_GPxCTRL_INDEX] |= regVal;
|
||
|
EDIS;
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_setControllerCore
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
GPIO_setControllerCore(uint32_t pin, GPIO_CoreSelect core)
|
||
|
{
|
||
|
volatile uint32_t *gpioBaseAddr;
|
||
|
uint32_t cSelIndex;
|
||
|
uint32_t shiftAmt;
|
||
|
|
||
|
//
|
||
|
// Check the arguments.
|
||
|
//
|
||
|
ASSERT(GPIO_isPinValid(pin));
|
||
|
|
||
|
gpioBaseAddr = (uint32_t *)GPIOCTRL_BASE +
|
||
|
((pin / 32U) * GPIO_CTRL_REGS_STEP);
|
||
|
shiftAmt = (uint32_t)GPIO_GPACSEL1_GPIO1_S * (pin % 8U);
|
||
|
cSelIndex = GPIO_GPxCSEL_INDEX + ((pin % 32U) / 8U);
|
||
|
|
||
|
//
|
||
|
// Write the core parameter into the register.
|
||
|
//
|
||
|
EALLOW;
|
||
|
gpioBaseAddr[cSelIndex] &= ~((uint32_t)GPIO_GPACSEL1_GPIO0_M << shiftAmt);
|
||
|
gpioBaseAddr[cSelIndex] |= (uint32_t)core << shiftAmt;
|
||
|
EDIS;
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_setAnalogMode
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
GPIO_setAnalogMode(uint32_t pin, GPIO_AnalogMode mode)
|
||
|
{
|
||
|
volatile uint32_t *gpioBaseAddr;
|
||
|
uint32_t pinMask;
|
||
|
|
||
|
//
|
||
|
// Check the arguments.
|
||
|
//
|
||
|
ASSERT((pin == 42U) || (pin == 43U));
|
||
|
|
||
|
pinMask = (uint32_t)1U << (pin % 32U);
|
||
|
gpioBaseAddr = (uint32_t *)GPIOCTRL_BASE +
|
||
|
((pin / 32U) * GPIO_CTRL_REGS_STEP);
|
||
|
|
||
|
EALLOW;
|
||
|
|
||
|
//
|
||
|
// Set the analog mode selection.
|
||
|
//
|
||
|
if(mode == GPIO_ANALOG_ENABLED)
|
||
|
{
|
||
|
//
|
||
|
// Enable analog mode
|
||
|
//
|
||
|
gpioBaseAddr[GPIO_GPxAMSEL_INDEX] |= pinMask;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Disable analog mode
|
||
|
//
|
||
|
gpioBaseAddr[GPIO_GPxAMSEL_INDEX] &= ~pinMask;
|
||
|
}
|
||
|
|
||
|
EDIS;
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO_setPinConfig
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
GPIO_setPinConfig(uint32_t pinConfig)
|
||
|
{
|
||
|
uint32_t muxRegAddr;
|
||
|
uint32_t pinMask, shiftAmt;
|
||
|
|
||
|
muxRegAddr = (uint32_t)GPIOCTRL_BASE + (pinConfig >> 16);
|
||
|
shiftAmt = ((pinConfig >> 8) & (uint32_t)0xFFU);
|
||
|
pinMask = (uint32_t)0x3U << shiftAmt;
|
||
|
|
||
|
EALLOW;
|
||
|
|
||
|
//
|
||
|
// Clear fields in MUX register first to avoid glitches
|
||
|
//
|
||
|
HWREG(muxRegAddr) &= ~pinMask;
|
||
|
|
||
|
//
|
||
|
// Write value into GMUX register
|
||
|
//
|
||
|
HWREG(muxRegAddr + GPIO_MUX_TO_GMUX) =
|
||
|
(HWREG(muxRegAddr + GPIO_MUX_TO_GMUX) & ~pinMask) |
|
||
|
(((pinConfig >> 2) & (uint32_t)0x3U) << shiftAmt);
|
||
|
|
||
|
//
|
||
|
// Write value into MUX register
|
||
|
//
|
||
|
HWREG(muxRegAddr) |= ((pinConfig & (uint32_t)0x3U) << shiftAmt);
|
||
|
EDIS;
|
||
|
}
|