91x_gpio.c中的函数存在Bug ?
91x_gpio.c中的函数 GPIO_Init的功能是对引脚进行初始化的函数,如果我们需要初始化 P9.0-P9.7,作为输出引脚,那么可以这样对引脚进行初始化:
GPIO_DeInit(GPIO9); GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; GPIO_InitStructure.GPIO_Alternate=GPIO_OutputAlt1; GPIO_Init (GPIO9, &GPIO_InitStructure);
事实上,通过程序单步跟踪可以发现,这样的操作会导致对SCU->GPIOOUT[GPIO_Number] 寄存器的越界访问,详见下面函数的(2)处。因为GPIO_Number的值为9,而实际上SCU->GPIOOUT[] 的下标范围为0..7, 硬件上不存在SCU->GPIOOUT[8]和SCU->GPIOOUT[9]寄存器。
建议增加语句(1),防止越界访问。 我的实验表明这样的越界访问会导致程序通过CAPS+FlashLink下装之后不能够在CAPS的复位控制 下正常运行,好像引脚不是输出态,同时按动板上的复位按键也不能正常。但是,掉电复位之后,可以正常运行。 一旦程序正常运行之后,按动复位按键,程序可以正常重新启动。但是,通过CAPS的复位,程序又不能正常运行。
如果避免了越界访问,那么以上的3种复位都能正常。
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) { /* Select pin direction */ u8 PinNumber = 0; u8 Counter = 0; u8 GPIO_Number = 0;
GPIO_Number = GPIO_GetGPIONumber(GPIOx);
if(GPIO_InitStruct->GPIO_Direction == GPIO_PinOutput) { GPIOx->DDR |= GPIO_InitStruct->GPIO_Pin; } else { GPIOx->DDR &= ~GPIO_InitStruct->GPIO_Pin; } for (Counter = 0; Counter < 8;Counter++) { /*Search pin number*/ PinNumber = (GPIO_InitStruct->GPIO_Pin & (1 <<Counter)); if((PinNumber >> Counter) == 1) { if (GPIO_Number<8 ) //(1) { /*Output ALternate 0*/ SCU->GPIOOUT[GPIO_Number] &= ~(0x3 <<(Counter *2)); if(GPIO_InitStruct->GPIO_Alternate == GPIO_OutputAlt1) { /*Output ALternate 1*/ SCU->GPIOOUT[GPIO_Number] |= 1 << (Counter *2); // (2) } if(GPIO_InitStruct->GPIO_Alternate == GPIO_OutputAlt2) { /*Output ALternate 2*/ SCU->GPIOOUT[GPIO_Number] |= 0x2 << (Counter *2); } if(GPIO_InitStruct->GPIO_Alternate == GPIO_OutputAlt3) { /*Output ALternate 3*/ SCU->GPIOOUT[GPIO_Number] |= 0x3 << (Counter *2); } } /*Type configuration: PushPull or Open Collector*/ SCU->GPIOTYPE[GPIO_Number] &= ~(0x1 << Counter) ; if(GPIO_InitStruct->GPIO_Type == GPIO_Type_OpenCollector) { /*Open Drain configuration*/ SCU->GPIOTYPE[GPIO_Number] |= 0x1 << Counter; }
/*IP Connected disable*/ SCU->GPIOIN[GPIO_Number] &= ~(0x1 << Counter) ; if(GPIO_InitStruct->GPIO_IPConnected == GPIO_IPConnected_Enable) { /*IP Connected enable*/ SCU->GPIOIN[GPIO_Number] |= 0x1 << Counter; } } } } |