Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

digitalRead()/analogRead() interference #1006

Merged
merged 2 commits into from
Jun 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
- Fixes to I2C Slave mode implementation with clock stretching enabled [#931](https://github.com/spark/firmware/pull/931)
- `millis()`/`micros()` are now atomic to ensure monotonic values. Fixes [#916](https://github.com/spark/firmware/issues/916) and [#925](https://github.com/spark/firmware/issues/925)
- availableForWrite() was reporting bytes available instead of bytes available for write [#1020](https://github.com/spark/firmware/pull/1020) and [#1017](https://github.com/spark/firmware/issues/1017)

- `digitalRead()` interferes with `analogRead()` [#993](https://github.com/spark/firmware/issues/993)



Expand Down
4 changes: 2 additions & 2 deletions hal/src/core/adc_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ int32_t HAL_ADC_Read(uint16_t pin)

int i = 0;

if (adcChannelConfigured != PIN_MAP[pin].adc_channel)
if (PIN_MAP[pin].pin_mode != AN_INPUT)
{
HAL_GPIO_Save_Pin_Mode(PIN_MAP[pin].pin_mode);
HAL_GPIO_Save_Pin_Mode(pin);
HAL_Pin_Mode(pin, AN_INPUT);
}

Expand Down
42 changes: 35 additions & 7 deletions hal/src/core/gpio_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@

/* Private variables --------------------------------------------------------*/

PinMode digitalPinModeSaved = PIN_MODE_NONE;

/* Extern variables ---------------------------------------------------------*/

/* Private function prototypes ----------------------------------------------*/
Expand Down Expand Up @@ -140,17 +138,47 @@ void HAL_Pin_Mode(pin_t pin, PinMode setMode)
/*
* @brief Saves a pin mode to be recalled later.
*/
void HAL_GPIO_Save_Pin_Mode(PinMode mode)
void HAL_GPIO_Save_Pin_Mode(uint16_t pin)
{
digitalPinModeSaved = mode;
// Save pin mode in STM32_Pin_Info.user_property
STM32_Pin_Info* PIN_MAP = HAL_Pin_Map();
uint32_t uprop = (uint32_t)PIN_MAP[pin].user_property;
uprop = (uprop & 0xFFFF) | (((uint32_t)PIN_MAP[pin].pin_mode & 0xFF) << 16) | (0xAA << 24);
PIN_MAP[pin].user_property = (int32_t)uprop;
}

/*
* @brief Recalls a saved pin mode.
*/
PinMode HAL_GPIO_Recall_Pin_Mode()
PinMode HAL_GPIO_Recall_Pin_Mode(uint16_t pin)
{
return digitalPinModeSaved;
// Recall pin mode in STM32_Pin_Info.user_property
STM32_Pin_Info* PIN_MAP = HAL_Pin_Map();
uint32_t uprop = (uint32_t)PIN_MAP[pin].user_property;
if ((uprop & 0xFF000000) != 0xAA000000)
return PIN_MODE_NONE;

PinMode pm = (PinMode)((uprop & 0x00FF0000) >> 16);

// Safety check
switch(pm)
{
case INPUT:
case OUTPUT:
case INPUT_PULLUP:
case INPUT_PULLDOWN:
case AF_OUTPUT_PUSHPULL:
case AF_OUTPUT_DRAIN:
case AN_INPUT:
case AN_OUTPUT:
break;

default:
pm = PIN_MODE_NONE;
break;
}

return pm;
}

/*
Expand Down Expand Up @@ -181,7 +209,7 @@ int32_t HAL_GPIO_Read(uint16_t pin)
{
if(PIN_MAP[pin].pin_mode == AN_INPUT)
{
PinMode pm = HAL_GPIO_Recall_Pin_Mode();
PinMode pm = HAL_GPIO_Recall_Pin_Mode(pin);
if(pm == PIN_MODE_NONE)
{
return 0;
Expand Down
4 changes: 2 additions & 2 deletions hal/src/core/pinmap_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ typedef struct STM32_Pin_Info {
extern STM32_Pin_Info PIN_MAP[];
STM32_Pin_Info* HAL_Pin_Map(void);

extern void HAL_GPIO_Save_Pin_Mode(PinMode mode);
extern PinMode HAL_GPIO_Recall_Pin_Mode();
extern void HAL_GPIO_Save_Pin_Mode(uint16_t pin);
extern PinMode HAL_GPIO_Recall_Pin_Mode(uint16_t pin);

#define NONE ((uint8_t)0xFF)
#define ADC_CHANNEL_NONE NONE
Expand Down
4 changes: 2 additions & 2 deletions hal/src/stm32f2xx/adc_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ int32_t HAL_ADC_Read(uint16_t pin)
int i = 0;
STM32_Pin_Info* PIN_MAP = HAL_Pin_Map();

if (adcChannelConfigured != PIN_MAP[pin].adc_channel)
if (PIN_MAP[pin].pin_mode != AN_INPUT)
{
HAL_GPIO_Save_Pin_Mode(PIN_MAP[pin].pin_mode);
HAL_GPIO_Save_Pin_Mode(pin);
HAL_Pin_Mode(pin, AN_INPUT);
}

Expand Down
1 change: 1 addition & 0 deletions hal/src/stm32f2xx/dac_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ void HAL_DAC_Write(pin_t pin, uint16_t value)

if (HAL_Get_Pin_Mode(pin) != AN_OUTPUT)
{
HAL_GPIO_Save_Pin_Mode(pin);
HAL_Pin_Mode(pin, AN_OUTPUT);
HAL_DAC_Enable(pin, 1);
}
Expand Down
43 changes: 35 additions & 8 deletions hal/src/stm32f2xx/gpio_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@

/* Private variables --------------------------------------------------------*/

PinMode digitalPinModeSaved = PIN_MODE_NONE;

/* Extern variables ---------------------------------------------------------*/

/* Private function prototypes ----------------------------------------------*/
Expand Down Expand Up @@ -171,17 +169,46 @@ void HAL_Pin_Mode(pin_t pin, PinMode setMode)
/*
* @brief Saves a pin mode to be recalled later.
*/
void HAL_GPIO_Save_Pin_Mode(PinMode mode)
void HAL_GPIO_Save_Pin_Mode(uint16_t pin)
{
digitalPinModeSaved = mode;
// Save pin mode in STM32_Pin_Info.user_property
STM32_Pin_Info* PIN_MAP = HAL_Pin_Map();
uint32_t uprop = (uint32_t)PIN_MAP[pin].user_property;
uprop = (uprop & 0xFFFF) | (((uint32_t)PIN_MAP[pin].pin_mode & 0xFF) << 16) | (0xAA << 24);
PIN_MAP[pin].user_property = (int32_t)uprop;
}

/*
* @brief Recalls a saved pin mode.
*/
PinMode HAL_GPIO_Recall_Pin_Mode()
PinMode HAL_GPIO_Recall_Pin_Mode(uint16_t pin)
{
return digitalPinModeSaved;
// Recall pin mode in STM32_Pin_Info.user_property
STM32_Pin_Info* PIN_MAP = HAL_Pin_Map();
uint32_t uprop = (uint32_t)PIN_MAP[pin].user_property;
if ((uprop & 0xFF000000) != 0xAA000000)
return PIN_MODE_NONE;
PinMode pm = (PinMode)((uprop & 0x00FF0000) >> 16);

// Safety check
switch(pm)
{
case INPUT:
case OUTPUT:
case INPUT_PULLUP:
case INPUT_PULLDOWN:
case AF_OUTPUT_PUSHPULL:
case AF_OUTPUT_DRAIN:
case AN_INPUT:
case AN_OUTPUT:
break;

default:
pm = PIN_MODE_NONE;
break;
}

return pm;
}

/*
Expand Down Expand Up @@ -220,7 +247,7 @@ int32_t HAL_GPIO_Read(uint16_t pin)
STM32_Pin_Info* PIN_MAP = HAL_Pin_Map();
if(PIN_MAP[pin].pin_mode == AN_INPUT)
{
PinMode pm = HAL_GPIO_Recall_Pin_Mode();
PinMode pm = HAL_GPIO_Recall_Pin_Mode(pin);
if(pm == PIN_MODE_NONE)
{
return 0;
Expand All @@ -233,7 +260,7 @@ int32_t HAL_GPIO_Read(uint16_t pin)
}
else if (PIN_MAP[pin].pin_mode == AN_OUTPUT)
{
PinMode pm = HAL_GPIO_Recall_Pin_Mode();
PinMode pm = HAL_GPIO_Recall_Pin_Mode(pin);
if(pm == PIN_MODE_NONE)
{
return 0;
Expand Down
4 changes: 2 additions & 2 deletions hal/src/stm32f2xx/pinmap_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ typedef struct STM32_Pin_Info {

STM32_Pin_Info* HAL_Pin_Map(void);

extern void HAL_GPIO_Save_Pin_Mode(PinMode mode);
extern PinMode HAL_GPIO_Recall_Pin_Mode();
extern void HAL_GPIO_Save_Pin_Mode(uint16_t pin);
extern PinMode HAL_GPIO_Recall_Pin_Mode(uint16_t pin);

#define CHANNEL_NONE ((uint8_t)(0xFF))
#define ADC_CHANNEL_NONE CHANNEL_NONE
Expand Down
27 changes: 27 additions & 0 deletions user/tests/wiring/adc_dac/adc_dac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,31 @@ test(ADC_AnalogReadOnPinWithDACMixedWithDigitalWrite) {
}
assertTrue(errorCount == 0);
}

test(DAC_AnalogWriteWorksMixedWithDigitalRead) {
pin_t pin = DAC;

// when
pinMode(pin, INPUT_PULLUP);
// then
assertEqual(HAL_Get_Pin_Mode(pin), INPUT_PULLUP);

// 2 analogReads
analogWrite(pin, 1000);
assertEqual(HAL_Get_Pin_Mode(pin), AN_OUTPUT);
analogWrite(pin, 2000);
assertEqual(HAL_Get_Pin_Mode(pin), AN_OUTPUT);
// 2 digitalReads
digitalRead(pin);
assertEqual(HAL_Get_Pin_Mode(pin), INPUT_PULLUP);
digitalRead(pin);
assertEqual(HAL_Get_Pin_Mode(pin), INPUT_PULLUP);
// 2 analogReads again
analogWrite(pin, 1000);
assertEqual(HAL_Get_Pin_Mode(pin), AN_OUTPUT);
analogWrite(pin, 500);
assertEqual(HAL_Get_Pin_Mode(pin), AN_OUTPUT);
}


#endif
25 changes: 25 additions & 0 deletions user/tests/wiring/no_fixture/gpio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,28 @@ test(GPIO_pulseIn_TimesOutAfter3Seconds) {
assertMoreOrEqual(millis()-startTime, 2850);
assertLessOrEqual(millis()-startTime, 3150);
}

test(GPIO_AnalogReadWorksMixedWithDigitalRead) {
pin_t pin = A0;

// when
pinMode(pin, INPUT_PULLUP);
// then
assertEqual(HAL_Get_Pin_Mode(pin), INPUT_PULLUP);

// 2 analogReads
analogRead(pin);
assertEqual(HAL_Get_Pin_Mode(pin), AN_INPUT);
analogRead(pin);
assertEqual(HAL_Get_Pin_Mode(pin), AN_INPUT);
// 2 digitalReads
digitalRead(pin);
assertEqual(HAL_Get_Pin_Mode(pin), INPUT_PULLUP);
digitalRead(pin);
assertEqual(HAL_Get_Pin_Mode(pin), INPUT_PULLUP);
// 2 analogReads again
analogRead(pin);
assertEqual(HAL_Get_Pin_Mode(pin), AN_INPUT);
analogRead(pin);
assertEqual(HAL_Get_Pin_Mode(pin), AN_INPUT);
}