//########################################################################### // // 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; }