Merge pull request #3056 from LMESTM/fix_stm32_pull_overwrite

Fix stm32 pull overwrite
pull/3076/head
Sam Grove 2016-10-19 05:50:30 -05:00 committed by GitHub
commit f1d678f8a4
16 changed files with 199 additions and 55 deletions

View File

@ -127,6 +127,7 @@ static void gpio_irq2(void) {
}
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
IRQn_Type irq_n = (IRQn_Type)0;
@ -196,8 +197,8 @@ void gpio_irq_free(gpio_irq_t *obj) {
gpio_channel->channel_gpio[gpio_idx] = 0;
gpio_channel->channel_pin[gpio_idx] = 0;
// Disable EXTI line
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
// Disable EXTI line, but don't change pull-up config
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
obj->event = EDGE_NONE;
}
@ -245,7 +246,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
}
}
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
pin_function_gpiomode(obj->pin, mode);
}
void gpio_irq_enable(gpio_irq_t *obj) {

View File

@ -138,5 +138,20 @@ void pin_mode(PinName pin, PinMode mode) {
if (pupd > 2) pupd = 0; // Open-drain = No pull-up/No pull-down
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
}
/* Internal function for setting the gpiomode/function
* without changing Pull mode
*/
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
/* Read current pull state from HW to avoid over-write*/
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
uint32_t temp = gpio->PUPDR;
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
/* Then re-use global function for updating the mode part*/
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
}

View File

@ -163,6 +163,7 @@ static void gpio_irq6(void)
}
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
{
@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
gpio_channel->channel_gpio[gpio_idx] = 0;
gpio_channel->channel_pin[gpio_idx] = 0;
// Disable EXTI line
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
// Disable EXTI line, but don't change pull-up config
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
obj->event = EDGE_NONE;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
uint32_t mode = STM_MODE_IT_EVT_RESET;
uint32_t pull = GPIO_NOPULL;
if (enable) {
if (event == IRQ_RISE) {
@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
}
}
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
pin_function_gpiomode(obj->pin, mode);
}
void gpio_irq_enable(gpio_irq_t *obj)

View File

@ -162,10 +162,19 @@ void pin_mode(PinName pin, PinMode mode)
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
// Enable GPIO clock
uint32_t gpio_add = Set_GPIO_Clock(port_index);
GPIO_TypeDef *gpio = (GPIO_TypeDef *)gpio_add;
__IO uint32_t* gpio_reg_hl;//gpio register depends on bit index (high or low)
uint32_t shift;
if (pin_index < 8) {
shift = (pin_index * 4);
gpio_reg_hl = &(gpio->CRL);
} else {
shift = (pin_index % 8) * 4;
gpio_reg_hl = &(gpio->CRH);
}
// Configure open-drain and pull-up/down
switch (mode) {
@ -174,16 +183,9 @@ void pin_mode(PinName pin, PinMode mode)
case PullUp:
case PullDown:
// Set pull-up / pull-down for Input mode
if (pin_index < 8) {
if ((gpio->CRL & (0x03 << (pin_index * 4))) == 0) { // MODE bits = Input mode
gpio->CRL |= (0x08 << (pin_index * 4)); // Set pull-up / pull-down
gpio->CRL &= ~(0x04 << (pin_index * 4)); // ENSURES GPIOx_CRL.CNFx.bit0 = 0
}
} else {
if ((gpio->CRH & (0x03 << ((pin_index % 8) * 4))) == 0) { // MODE bits = Input mode
gpio->CRH |= (0x08 << ((pin_index % 8) * 4)); // Set pull-up / pull-down
gpio->CRH &= ~(0x04 << ((pin_index % 8) * 4)); // ENSURES GPIOx_CRH.CNFx.bit0 = 0
}
if ((*gpio_reg_hl & (0x03 << shift)) == 0) { // MODE bits = Input mode
*gpio_reg_hl |= (0x08 << shift); // Set pull-up / pull-down
*gpio_reg_hl &= ~(0x04 << shift); // ENSURES GPIOx_CRL.CNFx.bit0 = 0
}
// Now it's time to setup properly if pullup or pulldown. This is done in ODR register:
// set pull-up => bit=1, set pull-down => bit = 0
@ -195,17 +197,51 @@ void pin_mode(PinName pin, PinMode mode)
break;
case OpenDrain:
// Set open-drain for Output mode (General Purpose or Alternate Function)
if (pin_index < 8) {
if ((gpio->CRL & (0x03 << (pin_index * 4))) > 0) { // MODE bits = Output mode
gpio->CRL |= (0x04 << (pin_index * 4)); // Set open-drain
}
} else {
if ((gpio->CRH & (0x03 << ((pin_index % 8) * 4))) > 0) { // MODE bits = Output mode
gpio->CRH |= (0x04 << ((pin_index % 8) * 4)); // Set open-drain
}
if ((*gpio_reg_hl & (0x03 << shift)) > 0) { // MODE bits = Output mode
*gpio_reg_hl |= (0x04 << shift); // Set open-drain
}
break;
default:
break;
}
}
/* Internal function for setting the gpiomode/function
* without changing Pull mode
*/
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
/* Read current pull state from HW to avoid over-write*/
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
uint32_t pull = PullNone;
__IO uint32_t* gpio_reg_hl;//gpio register depends on bit index (high or low)
uint32_t shift;
if (pin_index < 8) {
shift = (pin_index * 4);
gpio_reg_hl = &(gpio->CRL);
} else {
shift = (pin_index % 8) * 4;
gpio_reg_hl = &(gpio->CRH);
}
/* Check if pull/pull down is active */
if ((!(*gpio_reg_hl & (0x03 << shift))) // input
&& (!!(*gpio_reg_hl & (0x08 << shift))) // pull-up / down
&& (!(*gpio_reg_hl & (0x04 << shift)))) { // GPIOx_CRL.CNFx.bit0 = 0
if (!!(gpio->ODR & (0x01 << pin_index))) {
pull = PullUp;
} else {
pull = PullDown;
}
} else { //output
if (!!(*gpio_reg_hl & (0x04 << shift))) { //open drain
pull = OpenDrain;
}
}
/* Then re-use global function for updating the mode part*/
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
}

View File

@ -163,6 +163,7 @@ static void gpio_irq6(void)
}
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
{
@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
gpio_channel->channel_gpio[gpio_idx] = 0;
gpio_channel->channel_pin[gpio_idx] = 0;
// Disable EXTI line
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
// Disable EXTI line, but don't change pull-up config
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
obj->event = EDGE_NONE;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
uint32_t mode = STM_MODE_IT_EVT_RESET;
uint32_t pull = GPIO_NOPULL;
if (enable) {
if (event == IRQ_RISE) {
@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
}
}
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
pin_function_gpiomode(obj->pin, mode);
}
void gpio_irq_enable(gpio_irq_t *obj)

View File

@ -178,5 +178,20 @@ void pin_mode(PinName pin, PinMode mode)
}
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
}
/* Internal function for setting the gpiomode/function
* without changing Pull mode
*/
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
/* Read current pull state from HW to avoid over-write*/
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
uint32_t temp = gpio->PUPDR;
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
/* Then re-use global function for updating the mode part*/
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
}

View File

@ -163,6 +163,7 @@ static void gpio_irq6(void)
}
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
{
@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
gpio_channel->channel_gpio[gpio_idx] = 0;
gpio_channel->channel_pin[gpio_idx] = 0;
// Disable EXTI line
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
// Disable EXTI line, but don't change pull-up config
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
obj->event = EDGE_NONE;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
uint32_t mode = STM_MODE_IT_EVT_RESET;
uint32_t pull = GPIO_NOPULL;
if (enable) {
if (event == IRQ_RISE) {
@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
}
}
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
pin_function_gpiomode(obj->pin, mode);
}
void gpio_irq_enable(gpio_irq_t *obj)

View File

@ -177,3 +177,19 @@ void pin_mode(PinName pin, PinMode mode)
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
}
/* Internal function for setting the gpiomode/function
* without changing Pull mode
*/
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
/* Read current pull state from HW to avoid over-write*/
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
uint32_t temp = gpio->PUPDR;
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
/* Then re-use global function for updating the mode part*/
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
}

View File

@ -163,6 +163,7 @@ static void gpio_irq6(void)
}
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
{
@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
gpio_channel->channel_gpio[gpio_idx] = 0;
gpio_channel->channel_pin[gpio_idx] = 0;
// Disable EXTI line
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
// Disable EXTI line, but don't change pull-up config
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
obj->event = EDGE_NONE;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
uint32_t mode = STM_MODE_IT_EVT_RESET;
uint32_t pull = GPIO_NOPULL;
if (enable) {
if (event == IRQ_RISE) {
@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
}
}
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
pin_function_gpiomode(obj->pin, mode);
}
void gpio_irq_enable(gpio_irq_t *obj)

View File

@ -177,5 +177,20 @@ void pin_mode(PinName pin, PinMode mode)
pupd = 0; // Open-drain = No pull-up/No pull-down
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
}
/* Internal function for setting the gpiomode/function
* without changing Pull mode
*/
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
/* Read current pull state from HW to avoid over-write*/
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
uint32_t temp = gpio->PUPDR;
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
/* Then re-use global function for updating the mode part*/
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
}

View File

@ -131,6 +131,7 @@ static void gpio_irq2(void)
}
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
{
@ -202,15 +203,14 @@ void gpio_irq_free(gpio_irq_t *obj)
gpio_channel->channel_gpio[gpio_idx] = 0;
gpio_channel->channel_pin[gpio_idx] = 0;
// Disable EXTI line
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
// Disable EXTI line, but don't change pull-up config
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
obj->event = EDGE_NONE;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
uint32_t mode = STM_MODE_IT_EVT_RESET;
uint32_t pull = GPIO_NOPULL;
if (enable) {
if (event == IRQ_RISE) {
@ -252,7 +252,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
}
}
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
pin_function_gpiomode(obj->pin, mode);
}
void gpio_irq_enable(gpio_irq_t *obj)

View File

@ -146,5 +146,20 @@ void pin_mode(PinName pin, PinMode mode)
}
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPD0 << (pin_index * 2)));
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
}
/* Internal function for setting the gpiomode/function
* without changing Pull mode
*/
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
/* Read current pull state from HW to avoid over-write*/
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
uint32_t temp = gpio->PUPDR;
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPD0;
/* Then re-use global function for updating the mode part*/
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
}

View File

@ -163,6 +163,7 @@ static void gpio_irq6(void)
}
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
{
@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
gpio_channel->channel_gpio[gpio_idx] = 0;
gpio_channel->channel_pin[gpio_idx] = 0;
// Disable EXTI line
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
// Disable EXTI line, but don't change pull-up config
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
obj->event = EDGE_NONE;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
uint32_t mode = STM_MODE_IT_EVT_RESET;
uint32_t pull = GPIO_NOPULL;
if (enable) {
if (event == IRQ_RISE) {
@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
}
}
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
pin_function_gpiomode(obj->pin, mode);
}
void gpio_irq_enable(gpio_irq_t *obj)

View File

@ -139,5 +139,20 @@ void pin_mode(PinName pin, PinMode mode)
}
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
}
/* Internal function for setting the gpiomode/function
* without changing Pull mode
*/
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
/* Read current pull state from HW to avoid over-write*/
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
uint32_t temp = gpio->PUPDR;
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
/* Then re-use global function for updating the mode part*/
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
}

View File

@ -163,6 +163,7 @@ static void gpio_irq6(void)
}
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
{
@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
gpio_channel->channel_gpio[gpio_idx] = 0;
gpio_channel->channel_pin[gpio_idx] = 0;
// Disable EXTI line
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
// Disable EXTI line, but don't change pull-up config
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
obj->event = EDGE_NONE;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
uint32_t mode = STM_MODE_IT_EVT_RESET;
uint32_t pull = GPIO_NOPULL;
if (enable) {
if (event == IRQ_RISE) {
@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
}
}
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
pin_function_gpiomode(obj->pin, mode);
}
void gpio_irq_enable(gpio_irq_t *obj)

View File

@ -149,3 +149,19 @@ void pin_mode(PinName pin, PinMode mode)
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
}
/* Internal function for setting the gpiomode/function
* without changing Pull mode
*/
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
/* Read current pull state from HW to avoid over-write*/
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
uint32_t temp = gpio->PUPDR;
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
/* Then re-use global function for updating the mode part*/
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
}