Help Changing Electron ADC mode

Hello Particle community,
I’m working in a project similar to the open energy monitor (https://openenergymonitor.org) in order to measure voltage and current to get readings of instant, active and reactive power.
I would like to take advantage of the advanced ADC implemented in the STM32F205 of my electron. As far as I know, it is possible to set the MCU in Dual regular simultaneous Mode where two analog signals could
be sampled and converted at the same time ( http://www.st.com/content/ccc/resource/technical/document/application_note/c4/63/a9/f4/ae/f2/48/5d/CD00258017.pdf/files/CD00258017.pdf/jcr:content/translations/en.CD00258017.pdf Section 2.1.2) .
I found a source where the MCU mode is configured to this mode: https://github.com/g4lvanix/STM32F1-workarea/tree/master/Project/STM32F10x_StdPeriph_Examples/ADC/RegSimul_DualMode.
After reading some posts I can conclude that the MCU default mode is slow-interleaved mode ( Interesting results from various ADC sample times, Why dual slow interleaved?, https://github.com/spark/firmware/pull/258)
Based on the first code and the @nottheoilrig post I write a code that changes the mode. However when I tried to build the source code locally (using the instructions of https://github.com/spark/firmware/blob/master/docs/build.md) including the libraries in the user space I got a lot of errors.
This is the code I’m trying to compile:

#include "application.h"

#define ADC1_DR_Address ((uint32_t) 0x4001244c)
uint16_t ADC_ConvertedValue[20];

void setup()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;

    RCC_ADCCLKConfig(RCC_PCLK2_Div4);

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    DMA_DeInit(DMA1_Channel1);
    DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &ADC_ConvertedValue;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = 10;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);

    DMA_Cmd(DMA1_Channel1, ENABLE);

    ADC_InitStructure.ADC_Mode = ADC_Mode_SlowInterl;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5);

    ADC_InitStructure.ADC_Mode = ADC_Mode_SlowInterl;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_Init(ADC2, &ADC_InitStructure);

    ADC_RegularChannelConfig(ADC2, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5);

    ADC_ExternalTrigConvCmd(ADC2, ENABLE);

    ADC_DMACmd(ADC1, ENABLE);

    ADC_Cmd(ADC1, ENABLE);

    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1));

    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1));

    ADC_Cmd(ADC2, ENABLE);

    ADC_ResetCalibration(ADC2);
    while (ADC_GetResetCalibrationStatus(ADC2));

    ADC_StartCalibration(ADC2);
    while (ADC_GetCalibrationStatus(ADC2));

    long start = micros();

    ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    while (!DMA_GetFlagStatus(DMA1_FLAG_TC1));
    DMA_ClearFlag(DMA1_FLAG_TC1);
}

, this is my make command:

luballe@MacBook-Pro:~/spark/firmware/main$  make all APP=ADCdualMode program-dfu PARTICLE_SERIAL_DEV=/dev/cu.usbmodem641 PLATFORM=electron

And this is the output:

/Applications/Xcode.app/Contents/Developer/usr/bin/make -C ../modules/electron/user-part all program-dfu
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C ../../../user
Building file: applications/ADCdualMode/main.cpp
Invoking: ARM GCC CPP Compiler
mkdir -p ../build/target/user/platform-10-m/applications/ADCdualMode/applications/ADCdualMode/
arm-none-eabi-gcc -DSTM32_DEVICE -DSTM32F2XX -DPLATFORM_THREADING=1 -DPLATFORM_ID=10 -DPLATFORM_NAME=electron -DUSBD_VID_SPARK=0x2B04 -DUSBD_PID_DFU=0xD00A -DUSBD_PID_CDC=0xC00A -DSPARK_PLATFORM -g3 -gdwarf-2 -Os -mcpu=cortex-m3 -mthumb -DINCLUDE_PLATFORM=1 -DPRODUCT_ID=10 -DPRODUCT_FIRMWARE_VERSION=65535 -DUSE_STDPERIPH_DRIVER -DDFU_BUILD_ENABLE -DSYSTEM_VERSION_STRING=0.5.1 -DRELEASE_BUILD -I./inc -I../wiring/inc -I../system/inc -I../services/inc -I../communication/src -I../hal/inc -I../hal/shared -I/rtos/FreeRTOSv8.2.2/FreeRTOS/Source/include -I/rtos/FreeRTOSv8.2.2/FreeRTOS/Source/portable/GCC/ARM_CM3 -I../hal/src/electron -I../hal/src/stm32f2xx -I../hal/src/stm32 -I../platform/shared/inc -I../platform/MCU/STM32F2xx/CMSIS/Include -I../platform/MCU/STM32F2xx/CMSIS/Device/ST/Include -I../platform/MCU/STM32F2xx/SPARK_Firmware_Driver/inc -I../platform/MCU/shared/STM32/inc -I../platform/MCU/STM32F2xx/STM32_StdPeriph_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_Device_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_Host_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_OTG_Driver/inc -I../dynalib/inc -I./applications/ADCdualMode -I./libraries -I. -MD -MP -MF ../build/target/user/platform-10-m/applications/ADCdualMode/applications/ADCdualMode/main.o.d -ffunction-sections -fdata-sections -Wall -Wno-switch -Wno-error=deprecated-declarations -fmessage-length=0 -fno-strict-aliasing -DSPARK=1 -DPARTICLE=1 -DSTART_DFU_FLASHER_SERIAL_SPEED=14400 -DSTART_YMODEM_FLASHER_SERIAL_SPEED=28800 -DSPARK_PLATFORM_NET=UBLOXSARA -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc  -DUSER_FIRMWARE_IMAGE_SIZE=0x20000 -DUSER_FIRMWARE_IMAGE_LOCATION=0x8080000 -DMODULAR_FIRMWARE=1 -DMODULE_VERSION=4 -DMODULE_FUNCTION=5 -DMODULE_INDEX=1 -DMODULE_DEPENDENCY=4,2,15 -D_GNU_SOURCE -D_WINSOCK_H  -fno-exceptions -fno-rtti -fcheck-new -std=gnu++11 -c -o ../build/target/user/platform-10-m/applications/ADCdualMode4/applications/ADCdualMode/main.o applications/ADCdualMode/main.cpp
applications/ADCdualMode/main.cpp: In function 'void setup()':
applications/ADCdualMode/main.cpp:15:22: error: 'RCC_PCLK2_Div4' was not declared in this scope
     RCC_ADCCLKConfig(RCC_PCLK2_Div4);
                      ^
applications/ADCdualMode/main.cpp:15:36: error: 'RCC_ADCCLKConfig' was not declared in this scope
     RCC_ADCCLKConfig(RCC_PCLK2_Div4);
                                    ^
applications/ADCdualMode/main.cpp:17:27: error: 'RCC_AHBPeriph_DMA1' was not declared in this scope
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
                           ^
applications/ADCdualMode/main.cpp:17:53: error: 'RCC_AHBPeriphClockCmd' was not declared in this scope
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
                                                     ^
applications/ADCdualMode/main.cpp:19:28: error: 'RCC_APB2Periph_GPIOA' was not declared in this scope
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE);
                            ^
applications/ADCdualMode/main.cpp:25:16: error: 'DMA1_Channel1' was not declared in this scope
     DMA_DeInit(DMA1_Channel1);
                ^
applications/ADCdualMode/main.cpp:27:23: error: 'struct DMA_InitTypeDef' has no member named 'DMA_MemoryBaseAddr'
     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &ADC_ConvertedValue;
                       ^
applications/ADCdualMode/main.cpp:28:33: error: 'DMA_DIR_PeripheralSRC' was not declared in this scope
     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
                                 ^
applications/ADCdualMode/main.cpp:36:23: error: 'struct DMA_InitTypeDef' has no member named 'DMA_M2M'
     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
                       ^
applications/ADCdualMode/main.cpp:36:33: error: 'DMA_M2M_Disable' was not declared in this scope
     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
                                 ^
applications/ADCdualMode/main.cpp:41:23: error: 'struct ADC_InitTypeDef' has no member named 'ADC_Mode'
     ADC_InitStructure.ADC_Mode = ADC_Mode_SlowInterl;
                       ^
applications/ADCdualMode/main.cpp:41:34: error: 'ADC_Mode_SlowInterl' was not declared in this scope
     ADC_InitStructure.ADC_Mode = ADC_Mode_SlowInterl;
                                  ^
applications/ADCdualMode/main.cpp:44:46: error: 'ADC_ExternalTrigConv_None' was not declared in this scope
     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
                                              ^
applications/ADCdualMode/main.cpp:46:23: error: 'struct ADC_InitTypeDef' has no member named 'ADC_NbrOfChannel'
     ADC_InitStructure.ADC_NbrOfChannel = 1;
                       ^
applications/ADCdualMode/main.cpp:49:54: error: 'ADC_SampleTime_7Cycles5' was not declared in this scope
     ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5);
                                                      ^
applications/ADCdualMode/main.cpp:51:23: error: 'struct ADC_InitTypeDef' has no member named 'ADC_Mode'
     ADC_InitStructure.ADC_Mode = ADC_Mode_SlowInterl;
                       ^
applications/ADCdualMode/main.cpp:56:23: error: 'struct ADC_InitTypeDef' has no member named 'ADC_NbrOfChannel'
     ADC_InitStructure.ADC_NbrOfChannel = 1;
                       ^
applications/ADCdualMode/main.cpp:61:41: error: 'ADC_ExternalTrigConvCmd' was not declared in this scope
     ADC_ExternalTrigConvCmd(ADC2, ENABLE);
                                         ^
applications/ADCdualMode4/main.cpp:67:30: error: 'ADC_ResetCalibration' was not declared in this scope
     ADC_ResetCalibration(ADC1);
                              ^
applications/ADCdualMode/main.cpp:68:46: error: 'ADC_GetResetCalibrationStatus' was not declared in this scope
     while (ADC_GetResetCalibrationStatus(ADC1));
                                              ^
applications/ADCdualMode/main.cpp:70:30: error: 'ADC_StartCalibration' was not declared in this scope
     ADC_StartCalibration(ADC1);
                              ^
applications/ADCdualMode/main.cpp:71:41: error: 'ADC_GetCalibrationStatus' was not declared in this scope
     while (ADC_GetCalibrationStatus(ADC1));
                                         ^
applications/ADCdualMode/main.cpp:76:46: error: 'ADC_GetResetCalibrationStatus' was not declared in this scope
     while (ADC_GetResetCalibrationStatus(ADC2));
                                              ^
applications/ADCdualMode/main.cpp:79:41: error: 'ADC_GetCalibrationStatus' was not declared in this scope
     while (ADC_GetCalibrationStatus(ADC2));
                                         ^
applications/ADCdualMode/main.cpp:85:42: error: 'ADC_SoftwareStartConvCmd' was not declared in this scope
     ADC_SoftwareStartConvCmd(ADC1, ENABLE);
                                          ^
applications/ADCdualMode/main.cpp:87:31: error: 'DMA1_FLAG_TC1' was not declared in this scope
     while (!DMA_GetFlagStatus(DMA1_FLAG_TC1));
                               ^
applications/ADCdualMode/main.cpp:88:19: error: 'DMA1_FLAG_TC1' was not declared in this scope
     DMA_ClearFlag(DMA1_FLAG_TC1);
                   ^
make[2]: *** [../build/target/user/platform-10-m/applications/ADCdualMode/applications/ADCdualMode/main.o] Error 1
make[1]: *** [user] Error 2
make: *** [modules/electron/user-part] Error 2

My question is: What am I doing wrong? Is there anything I’m missing?

I do really appreciate any help with this issue.

Luis Ballesteros

Hello, just linking to my reply from this thread as well.

Hi @nottheoilrig!
Thanks a lot for your time this morning building the source and answering my question.
Effectively when I compile with the PLATFORM=core flag it works. I will follow your suggestions and start working porting the examples.

Your answer really helps me out. As soon as I get any good result I’ll post it.
Thanks again.

Luis Ballesteros