| /******************************************************************************* | |
| * (c) Copyright 2008 Actel Corporation. All rights reserved. | |
| * | |
| * SmartFusion microcontroller subsystem GPIO bare metal driver implementation. | |
| * | |
| * SVN $Revision: 1753 $ | |
| * SVN $Date: 2009-12-11 15:12:18 +0000 (Fri, 11 Dec 2009) $ | |
| */ | |
| #include "mss_gpio.h" | |
| #include "../../CMSIS/mss_assert.h" | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
| /*-------------------------------------------------------------------------*//** | |
| * | |
| */ | |
| #define GPIO_INT_ENABLE_MASK (uint32_t)0x00000008UL | |
| #define OUTPUT_BUFFER_ENABLE_MASK 0x00000004UL | |
| #define NB_OF_GPIO (uint32_t)32 | |
| /*-------------------------------------------------------------------------*//** | |
| * Lookup table of GPIO configuration registers address indexed on GPIO ID. | |
| */ | |
| static uint32_t volatile * const g_config_reg_lut[NB_OF_GPIO] = | |
| { | |
| &(GPIO->GPIO_0_CFG), | |
| &(GPIO->GPIO_1_CFG), | |
| &(GPIO->GPIO_2_CFG), | |
| &(GPIO->GPIO_3_CFG), | |
| &(GPIO->GPIO_4_CFG), | |
| &(GPIO->GPIO_5_CFG), | |
| &(GPIO->GPIO_6_CFG), | |
| &(GPIO->GPIO_7_CFG), | |
| &(GPIO->GPIO_8_CFG), | |
| &(GPIO->GPIO_9_CFG), | |
| &(GPIO->GPIO_10_CFG), | |
| &(GPIO->GPIO_11_CFG), | |
| &(GPIO->GPIO_12_CFG), | |
| &(GPIO->GPIO_13_CFG), | |
| &(GPIO->GPIO_14_CFG), | |
| &(GPIO->GPIO_15_CFG), | |
| &(GPIO->GPIO_16_CFG), | |
| &(GPIO->GPIO_17_CFG), | |
| &(GPIO->GPIO_18_CFG), | |
| &(GPIO->GPIO_19_CFG), | |
| &(GPIO->GPIO_20_CFG), | |
| &(GPIO->GPIO_21_CFG), | |
| &(GPIO->GPIO_22_CFG), | |
| &(GPIO->GPIO_23_CFG), | |
| &(GPIO->GPIO_24_CFG), | |
| &(GPIO->GPIO_25_CFG), | |
| &(GPIO->GPIO_26_CFG), | |
| &(GPIO->GPIO_27_CFG), | |
| &(GPIO->GPIO_28_CFG), | |
| &(GPIO->GPIO_29_CFG), | |
| &(GPIO->GPIO_30_CFG), | |
| &(GPIO->GPIO_31_CFG) | |
| }; | |
| /*-------------------------------------------------------------------------*//** | |
| * Lookup table of Cortex-M3 GPIO interrupt number indexed on GPIO ID. | |
| */ | |
| static const IRQn_Type g_gpio_irqn_lut[NB_OF_GPIO] = | |
| { | |
| GPIO0_IRQn, | |
| GPIO1_IRQn, | |
| GPIO2_IRQn, | |
| GPIO3_IRQn, | |
| GPIO4_IRQn, | |
| GPIO5_IRQn, | |
| GPIO6_IRQn, | |
| GPIO7_IRQn, | |
| GPIO8_IRQn, | |
| GPIO9_IRQn, | |
| GPIO10_IRQn, | |
| GPIO11_IRQn, | |
| GPIO12_IRQn, | |
| GPIO13_IRQn, | |
| GPIO14_IRQn, | |
| GPIO15_IRQn, | |
| GPIO16_IRQn, | |
| GPIO17_IRQn, | |
| GPIO18_IRQn, | |
| GPIO19_IRQn, | |
| GPIO20_IRQn, | |
| GPIO21_IRQn, | |
| GPIO22_IRQn, | |
| GPIO23_IRQn, | |
| GPIO24_IRQn, | |
| GPIO25_IRQn, | |
| GPIO26_IRQn, | |
| GPIO27_IRQn, | |
| GPIO28_IRQn, | |
| GPIO29_IRQn, | |
| GPIO30_IRQn, | |
| GPIO31_IRQn | |
| }; | |
| /*-------------------------------------------------------------------------*//** | |
| * MSS_GPIO_init | |
| * See "mss_gpio.h" for details of how to use this function. | |
| */ | |
| void MSS_GPIO_init( void ) | |
| { | |
| uint32_t i; | |
| /* reset MSS GPIO hardware */ | |
| SYSREG->SOFT_RST_CR |= SYSREG_GPIO_SOFTRESET_MASK; | |
| /* Clear any previously pended MSS GPIO interrupt */ | |
| for ( i = 0U; i < NB_OF_GPIO; ++i ) | |
| { | |
| NVIC_ClearPendingIRQ( g_gpio_irqn_lut[i] ); | |
| } | |
| /* Take MSS GPIO hardware out of reset. */ | |
| SYSREG->SOFT_RST_CR &= ~SYSREG_GPIO_SOFTRESET_MASK; | |
| } | |
| /*-------------------------------------------------------------------------*//** | |
| * MSS_GPIO_config | |
| * See "mss_gpio.h" for details of how to use this function. | |
| */ | |
| void MSS_GPIO_config | |
| ( | |
| mss_gpio_id_t port_id, | |
| uint32_t config | |
| ) | |
| { | |
| uint32_t gpio_idx = (uint32_t)port_id; | |
| ASSERT( gpio_idx < NB_OF_GPIO ); | |
| if ( gpio_idx < NB_OF_GPIO ) | |
| { | |
| *(g_config_reg_lut[gpio_idx]) = config; | |
| } | |
| } | |
| /*-------------------------------------------------------------------------*//** | |
| * MSS_GPIO_set_output | |
| * See "mss_gpio.h" for details of how to use this function. | |
| */ | |
| void MSS_GPIO_set_output | |
| ( | |
| mss_gpio_id_t port_id, | |
| uint8_t value | |
| ) | |
| { | |
| uint32_t gpio_idx = (uint32_t)port_id; | |
| ASSERT( gpio_idx < NB_OF_GPIO ); | |
| if ( gpio_idx < NB_OF_GPIO ) | |
| { | |
| GPIO_BITBAND->GPIO_OUT[gpio_idx] = (uint32_t)value; | |
| } | |
| } | |
| /*-------------------------------------------------------------------------*//** | |
| * MSS_GPIO_drive_inout | |
| * See "mss_gpio.h" for details of how to use this function. | |
| */ | |
| void MSS_GPIO_drive_inout | |
| ( | |
| mss_gpio_id_t port_id, | |
| mss_gpio_inout_state_t inout_state | |
| ) | |
| { | |
| uint32_t outputs_state; | |
| uint32_t config; | |
| uint32_t gpio_idx = (uint32_t)port_id; | |
| ASSERT( gpio_idx < NB_OF_GPIO ); | |
| if ( gpio_idx < NB_OF_GPIO ) | |
| { | |
| switch( inout_state ) | |
| { | |
| case MSS_GPIO_DRIVE_HIGH: | |
| /* Set output high */ | |
| outputs_state = GPIO->GPIO_OUT; | |
| outputs_state |= (uint32_t)1 << gpio_idx; | |
| GPIO->GPIO_OUT = outputs_state; | |
| /* Enable output buffer */ | |
| config = *(g_config_reg_lut[gpio_idx]); | |
| config |= OUTPUT_BUFFER_ENABLE_MASK; | |
| *(g_config_reg_lut[gpio_idx]) = config; | |
| break; | |
| case MSS_GPIO_DRIVE_LOW: | |
| /* Set output low */ | |
| outputs_state = GPIO->GPIO_OUT; | |
| outputs_state &= ~((uint32_t)((uint32_t)1 << gpio_idx)); | |
| GPIO->GPIO_OUT = outputs_state; | |
| /* Enable output buffer */ | |
| config = *(g_config_reg_lut[gpio_idx]); | |
| config |= OUTPUT_BUFFER_ENABLE_MASK; | |
| *(g_config_reg_lut[gpio_idx]) = config; | |
| break; | |
| case MSS_GPIO_HIGH_Z: | |
| /* Disable output buffer */ | |
| config = *(g_config_reg_lut[gpio_idx]); | |
| config &= ~OUTPUT_BUFFER_ENABLE_MASK; | |
| *(g_config_reg_lut[gpio_idx]) = config; | |
| break; | |
| default: | |
| ASSERT(0); | |
| break; | |
| } | |
| } | |
| } | |
| /*-------------------------------------------------------------------------*//** | |
| * MSS_GPIO_enable_irq | |
| * See "mss_gpio.h" for details of how to use this function. | |
| */ | |
| void MSS_GPIO_enable_irq | |
| ( | |
| mss_gpio_id_t port_id | |
| ) | |
| { | |
| uint32_t cfg_value; | |
| uint32_t gpio_idx = (uint32_t)port_id; | |
| ASSERT( gpio_idx < NB_OF_GPIO ); | |
| if ( gpio_idx < NB_OF_GPIO ) | |
| { | |
| cfg_value = *(g_config_reg_lut[gpio_idx]); | |
| *(g_config_reg_lut[gpio_idx]) = (cfg_value | GPIO_INT_ENABLE_MASK); | |
| NVIC_EnableIRQ( g_gpio_irqn_lut[gpio_idx] ); | |
| } | |
| } | |
| /*-------------------------------------------------------------------------*//** | |
| * MSS_GPIO_disable_irq | |
| * See "mss_gpio.h" for details of how to use this function. | |
| */ | |
| void MSS_GPIO_disable_irq | |
| ( | |
| mss_gpio_id_t port_id | |
| ) | |
| { | |
| uint32_t cfg_value; | |
| uint32_t gpio_idx = (uint32_t)port_id; | |
| ASSERT( gpio_idx < NB_OF_GPIO ); | |
| if ( gpio_idx < NB_OF_GPIO ) | |
| { | |
| cfg_value = *(g_config_reg_lut[gpio_idx]); | |
| *(g_config_reg_lut[gpio_idx]) = (cfg_value & ~GPIO_INT_ENABLE_MASK); | |
| } | |
| } | |
| /*-------------------------------------------------------------------------*//** | |
| * MSS_GPIO_clear_irq | |
| * See "mss_gpio.h" for details of how to use this function. | |
| */ | |
| void MSS_GPIO_clear_irq | |
| ( | |
| mss_gpio_id_t port_id | |
| ) | |
| { | |
| uint32_t gpio_idx = (uint32_t)port_id; | |
| ASSERT( gpio_idx < NB_OF_GPIO ); | |
| if ( gpio_idx < NB_OF_GPIO ) | |
| { | |
| GPIO->GPIO_IRQ = ((uint32_t)1) << gpio_idx; | |
| NVIC_ClearPendingIRQ( g_gpio_irqn_lut[gpio_idx] ); | |
| } | |
| } | |
| #ifdef __cplusplus | |
| } | |
| #endif | |