AnsweredAssumed Answered

STM32F407 Timer2 trigger ADCs and then DMA to SRAM problem

Question asked by li.gavin on Oct 22, 2014
Latest reply on Oct 23, 2014 by Clive One

I want to use TIM2 to trigger tripple ADCs do conversion, and use DMA to transfer ADC values to SRAM. When DMA finished, it should generate an interrupt.
I tested in different steps: the TIM2 interrupt always no problem, ADC over-run interrupt always happen, but no ADC EOC interrupts have been detected, so no DMA interrupt happened. please help me find out what am I missing?

#ifndef __ADC_H__
#define __ADC_H__
  
/* Includes */
#include "config.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_dma.h"
  
#define TOTAL_CHN  8
#define TOTAL_ADC  3
#define ADCBUFSIZE (TOTAL_CHN*TOTAL_ADC)
typedef struct {
    ADC_TypeDef * adc;
    int chn_nr; //total channels
    uint8 chn[TOTAL_CHN];
} ADCDev;
  
/* Function Prototypes */
void adc_init(const ADCDev *dev1, const ADCDev *dev2, const ADCDev *dev3, uint32_t* buf, uint32_t buf_size);
void adc_start(void);
void adc_stop(void);
  
#endif //__ADC_H__
  
  
  
/* Local Includes */
#include "adc.h"
#include "stm32f4xx_syscfg.h"
#include "stdio.h"
#include "string.h"
#include "gpio.h"
/* Local Type Definitions */
/* Local Globals */
/* Local Functions */
static void NVIC_TIM2_init(void);
static void NVIC_ADC_init(void);
static void NVIC_DMA1_init(void);
static void TIM2_init(void);
static void ADC_Common_init(void);
static void ADC_init(const ADCDev *dev);
static void DMA1_init(uint32_t* buf, uint32_t buf_size);
  
static void NVIC_TIM2_init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
static void NVIC_ADC_init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
static void NVIC_DMA1_init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    //Enable DMA1 channel IRQ Channel */
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 14;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
void DMA1_Stream0_IRQHandler(void) // Called at 1 KHz for 200 KHz sample rate, LED Toggles at 500 Hz
{
    /* Test on DMA Stream Half Transfer interrupt */
    if(DMA_GetITStatus(DMA1_Stream0, DMA_IT_HTIF0))
    {
        /* Clear DMA Stream Half Transfer interrupt pending bit */
        DMA_ClearITPendingBit(DMA1_Stream0, DMA_IT_HTIF0);
        /* Turn LED1 off: Half Transfer */
        gpio_write_pin(GPIOPortID_G, GPIOPinID_6, 0);
        // Add code here to process first half of buffer (ping)
    }
  
    /* Test on DMA Stream Transfer Complete interrupt */
    if(DMA_GetITStatus(DMA1_Stream0, DMA_IT_TCIF0))
    {
        /* Clear DMA Stream Transfer Complete interrupt pending bit */
        DMA_ClearITPendingBit(DMA1_Stream0, DMA_IT_TCIF0);
        /* Turn LED1 on: End of Transfer */
        gpio_write_pin(GPIOPortID_G, GPIOPinID_6, 1);
        // Add code here to process second half of buffer (pong)
    }
}
static uint32_t tm_cntr = 0;
static uint32_t tm_cnt = 0;
void TIM2_IRQHandler(void)
{
    uint16_t flag;
    tm_cntr = TIM_GetCounter(TIM2);
    tm_cnt++;
    TIM_ClearFlag(TIM2, 0xFFFF);
    flag = TIM_GetFlagStatus(TIM2, 0xff);
}
static uint32_t adc_cntr  = 0;
static uint32_t adc_cnt1 = 0;
static uint32_t adc_cnt2 = 0;
static uint32_t adc_cnt3 = 0;
void ADC_IRQHandler(void)
{
    uint32_t del, flag1, flag2, flag3;
    adc_cntr = TIM_GetCounter(TIM2);
    del = adc_cntr - tm_cntr;
    flag1 = ADC_GetFlagStatus(ADC1,  ADC_FLAG_EOC);
    flag2 = ADC_GetFlagStatus(ADC2,  ADC_FLAG_EOC);
    flag3 = ADC_GetFlagStatus(ADC3,  ADC_FLAG_EOC);
    if (flag1) adc_cnt1++;
    if (flag2) adc_cnt2++;
    if (flag3) adc_cnt3++;
    ADC_ClearFlag(ADC1, 0xFFFF);
    ADC_ClearFlag(ADC2, 0xFFFF);
    ADC_ClearFlag(ADC3, 0xFFFF);
  
}
static void TIM2_init(void)
{
    TIM_Cmd(TIM2, DISABLE);
  
    NVIC_TIM2_init();
  
    TIM_UpdateRequestConfig(TIM2, TIM_UpdateSource_Regular);
    /* TIM2 TRGO selection */
    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); // ADC_ExternalTrigConv_T2_TRGO
  
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    /* Time base configuration */
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    /// TIM_TimeBaseStructure.TIM_Period = (84000000 / 200000) - 1; // 200 KHz, from 84 MHz TIM2CLK (ie APB1 = HCLK/4, TIM2CLK = HCLK/2)
    TIM_TimeBaseStructure.TIM_Period = (uint32_t)(84000000) *10 - 1; // very long time for test
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  
    //TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
  
    /* TIM2 enable counter */
    //TIM_Cmd(TIM2, ENABLE);
}
  
static void ADC_Common_init(void)
{
    NVIC_ADC_init();
  
    /* ADC Common Init */
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult; /*ADC_Mode_Independent;*/ 
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; // 2 / 3 half-words one by one - 1 then 2 then 3
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);
/// ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
}
static void ADC_init(const ADCDev *dev)
{
    /* ADC Init */
    ADC_InitTypeDef ADC_InitStruct;
  
    ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStruct.ADC_ScanConvMode = ENABLE;
    ADC_InitStruct.ADC_ContinuousConvMode = DISABLE; // Scan on Demand (Trigger)
    ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
    ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
    ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStruct.ADC_NbrOfConversion = dev->chn_nr;
  
    ADC_Init(dev->adc, &ADC_InitStruct);
  
    for (int i=0;i<sizeof(dev->chn_nr);i++)
        ADC_RegularChannelConfig(dev->adc, dev->chn[i], i+1, ADC_SampleTime_56Cycles);
  
    //ADC_ITConfig(dev->adc, ADC_IT_OVR, ENABLE); /* OVR = Over Run */
    //ADC_ITConfig(dev->adc, ADC_IT_EOC, ENABLE); /* EOC = End Of Conversion */
  
    //ADC_Cmd(dev->adc, ENABLE);
    if (dev->adc == ADC1) {
        /* Enable ADC1 DMA since ADC1 is the Master*/
        ///ADC_DMACmd(ADC1, ENABLE);
    }
}
  
static void DMA1_init(uint32_t* buf, uint32_t buf_size)
{
    NVIC_DMA1_init();
  
    DMA_InitTypeDef  DMA_InitStructure;
    DMA_DeInit(DMA1_Stream0);
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(0x40012308);  //ADC CDR_ADDRESS
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buf;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize = buf_size;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA1_Stream0, &DMA_InitStructure);
    // Enable DMA Stream Half / Transfer Complete interrupt
    DMA_ITConfig(DMA1_Stream0, DMA_IT_HT | DMA_IT_TC, ENABLE);
    DMA_Cmd(DMA1_Stream0, ENABLE); //Enable the DMA1 - Channel0
}
/* Exposed API */
void adc_init(const ADCDev *dev1, const ADCDev *dev2, const ADCDev *dev3, uint32_t* buf, uint32_t buf_size)
{
    DMA1_init(buf, buf_size);
    ADC_Common_init();
    ADC_init(dev1);
    ADC_init(dev2);
    ADC_init(dev3);
    ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
    TIM2_init();
}
void adc_start(void)
{
    ///ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
    //  ADC_GetConversionValue(ADC1);
    //  ADC_GetConversionValue(ADC2);
    //  ADC_GetConversionValue(ADC3);
    //  ADC_GetMultiModeConversionValue();
    //  ADC_GetMultiModeConversionValue();
    //  ADC_GetFlagStatus(ADC1, ADC_FLAG_OVR | ADC_FLAG_STRT);
    //  ADC_GetFlagStatus(ADC2, ADC_FLAG_OVR | ADC_FLAG_STRT);
    //  ADC_GetFlagStatus(ADC3, ADC_FLAG_OVR | ADC_FLAG_STRT);
//  TIM_GenerateEvent(TIM2, TIM_EventSource_Update);
    TIM_Cmd(TIM2, ENABLE);
    ADC_Cmd(ADC1, ENABLE);
    ADC_Cmd(ADC2, ENABLE);
    ADC_Cmd(ADC3, ENABLE);
}
void adc_stop(void)
{
    /* TIM8 disable counter */
    TIM_Cmd(TIM2, DISABLE);
//  ADC_MultiModeDMARequestAfterLastTransferCmd(DISABLE);
}
  
  
#include "stm32f4xx.h"
#include "platform.h"
#include "gpfuncs.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "adc.h"
  
  
static const ADCDev adc1 = {ADC1, 8, { 1,  2,  3,  4, 10, 11, 12, 13}};
static const ADCDev adc2 = {ADC2, 8, {10, 11, 12, 13,  1,  2,  3,  4}};
static const ADCDev adc3 = {ADC3, 8, { 4,  5,  6,  7,  8,  9, 14, 15}};
  
volatile uint32_t adc_buf[ADCBUFSIZE];
  
int main(void)
{
    /* Local Globals */
  
    platform_init();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    memset((uint32_t*)adc_buf, 0, ADCBUFSIZE);
    adc_init(&adc1, &adc2, &adc3, (uint32_t*)adc_buf, ADCBUFSIZE);
    adc_start();
    while(TRUE);
}


//platform_comm.c
  
#include "platform.h"
  
// Include Drivers
#include "gpio.h"
#include "i2c.h"
#include "spi.h"
#include "rs232.h"
  
// Include Devices
//#include "device.h"
  
/* Globals */
uint32 gSysTickCount = 0;
  
/* Local Globals */
static int gIsInitialized = FALSE;
  
  
// GPIO pin configuration: Please keep it in order (ports and pins in alphabetical and numerical order) for easy maintainability.
const GPIOPinConfig gPinConfigs[] =
{
    // Port A
    { GPIOPortID_A, GPIOPinID_0,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }, // PA0
/// { GPIOPortID_A, GPIOPinID_1,  GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_CLEAR },  // RMII_REF_CLK
/// { GPIOPortID_A, GPIOPinID_2,  GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_CLEAR },  // MII_MDIO
/// { GPIOPortID_A, GPIOPinID_3,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // AMB TEMP
/// { GPIOPortID_A, GPIOPinID_4,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // ADC12_IN4
    { GPIOPortID_A, GPIOPinID_5,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // ADC12_IN5
    { GPIOPortID_A, GPIOPinID_7,  GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_SET }, // RMII_CRSDV
    { GPIOPortID_A, GPIOPinID_8,  GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_SET }, // MCO
  
    { GPIOPortID_A, GPIOPinID_1,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET },    // ADC123_IN1 Therm1
    { GPIOPortID_A, GPIOPinID_2,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET },    // ADC123_IN2 Therm1
    { GPIOPortID_A, GPIOPinID_3,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET },    // ADC123_IN3 Therm1
    { GPIOPortID_A, GPIOPinID_4,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET },    // ADC12_IN4  Therm1
    // Port B
    { GPIOPortID_B, GPIOPinID_0,  GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_TIM3, GPIO_PIN_SET },   // TIM3 C3 / speed feedback
    { GPIOPortID_B, GPIOPinID_1,  GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_TIM3, GPIO_PIN_SET },   // TIM3 C4 / speed feedback
    { GPIOPortID_B, GPIOPinID_2,  GPIOPinFunction_IN_PD,  GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR },    // BOOT1
    { GPIOPortID_B, GPIOPinID_10, GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_USART3, GPIO_PIN_SET }, // TX3
    { GPIOPortID_B, GPIOPinID_11, GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_USART3, GPIO_PIN_SET }, // RX3
    { GPIOPortID_B, GPIOPinID_14, GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_CLEAR },     // MII_INT
  
    // Port C
/// { GPIOPortID_C, GPIOPinID_1,  GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_SET }, // MII_MDC
    { GPIOPortID_C, GPIOPinID_4,  GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_SET }, // MII_RXD0
    { GPIOPortID_C, GPIOPinID_4,  GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_SET }, // MII_RXD1
    { GPIOPortID_C, GPIOPinID_6,  GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_USART6, GPIO_PIN_SET }, // USART6 TX
    { GPIOPortID_C, GPIOPinID_7,  GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_USART6, GPIO_PIN_SET }, // USART6 RX
    { GPIOPortID_C, GPIOPinID_8,  GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_NONE, GPIO_PIN_SET },   // USART6 TX_EN
  
    { GPIOPortID_C, GPIOPinID_0,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET },         // ADC123_IN10
    { GPIOPortID_C, GPIOPinID_1,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET },         // ADC123_IN11
    { GPIOPortID_C, GPIOPinID_2,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET },         // ADC123_IN12
    { GPIOPortID_C, GPIOPinID_3,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET },         // ADC123_IN13
    { GPIOPortID_C, GPIOPinID_10, GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_USART3, GPIO_PIN_SET }, // TX3
    { GPIOPortID_C, GPIOPinID_11, GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_USART3, GPIO_PIN_SET }, // RX3
    // Port D
    { GPIOPortID_D, GPIOPinID_5,  GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_USART2, GPIO_PIN_SET }, // USART2 TX
    { GPIOPortID_D, GPIOPinID_6,  GPIOPinFunction_ALT_PP_PU, GPIOAltPinFunction_USART2, GPIO_PIN_SET }, // USART2 RX
    { GPIOPortID_D, GPIOPinID_15, GPIOPinFunction_IN_PU, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // POWER LOST INTERRUPT(RISING EDGE)
  
    // Port E
    { GPIOPortID_E, GPIOPinID_0,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }, // LED14
    { GPIOPortID_E, GPIOPinID_1,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }, // LED13
    { GPIOPortID_E, GPIOPinID_2,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }, // LED12
    { GPIOPortID_E, GPIOPinID_3,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }, // LED11
    { GPIOPortID_E, GPIOPinID_4,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }, // LED10
    { GPIOPortID_E, GPIOPinID_5,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }, // LED9
    { GPIOPortID_E, GPIOPinID_6,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }, // LED8
    { GPIOPortID_E, GPIOPinID_7,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }, // LED7
    { GPIOPortID_E, GPIOPinID_8,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }, // LED6
    { GPIOPortID_E, GPIOPinID_9,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_SET },   // LED5 (ON)
  
    // Port F
    { GPIOPortID_F, GPIOPinID_3,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // ADC3_IN9
    { GPIOPortID_F, GPIOPinID_4,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // ADC3_IN14
    { GPIOPortID_F, GPIOPinID_5,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // ADC3_IN15
    { GPIOPortID_F, GPIOPinID_6,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // ADC3_IN4
    { GPIOPortID_F, GPIOPinID_7,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // ADC3_IN5
    { GPIOPortID_F, GPIOPinID_8,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // ADC3_IN6
    { GPIOPortID_F, GPIOPinID_9,  GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // ADC3_IN7
    { GPIOPortID_F, GPIOPinID_10, GPIOPinFunction_ANALOG, GPIOAltPinFunction_SYS, GPIO_PIN_SET }, // ADC3_IN8
  
    // Port G
    { GPIOPortID_G, GPIOPinID_0,  GPIOPinFunction_OUT_OD, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // BOOT0_0
    { GPIOPortID_G, GPIOPinID_1,  GPIOPinFunction_OUT_OD, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // BOOT0_1
    { GPIOPortID_G, GPIOPinID_2,  GPIOPinFunction_OUT_OD, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // BOOT0_2
    { GPIOPortID_G, GPIOPinID_3,  GPIOPinFunction_OUT_OD, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // BOOT0_3
    { GPIOPortID_G, GPIOPinID_4,  GPIOPinFunction_OUT_OD, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // RESET_0
    { GPIOPortID_G, GPIOPinID_5,  GPIOPinFunction_OUT_OD, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // RESET_1
/// { GPIOPortID_G, GPIOPinID_6,  GPIOPinFunction_OUT_OD, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // RESET_2
    { GPIOPortID_G, GPIOPinID_7,  GPIOPinFunction_OUT_OD, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // RESET_3
    { GPIOPortID_G, GPIOPinID_11, GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_SET },  // MII_TX_EN
    { GPIOPortID_G, GPIOPinID_13, GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_SET },  // MII_TXD0
    { GPIOPortID_G, GPIOPinID_14, GPIOPinFunction_ALT_PP, GPIOAltPinFunction_ETH, GPIO_PIN_SET },  // MII_TXD1
  
    { GPIOPortID_G, GPIOPinID_6,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // RESET_2
    { GPIOPortID_G, GPIOPinID_8,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // RESET_2
    // Port H
    { GPIOPortID_H, GPIOPinID_12, GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // FAN PWM (TIM5_CH3)
    { GPIOPortID_H, GPIOPinID_13, GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // FAN POWER
  
  
    // Port I
    { GPIOPortID_I, GPIOPinID_0,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_SET },   // SPI2 NSS
    { GPIOPortID_I, GPIOPinID_1,  GPIOPinFunction_ALT_PP, GPIOAltPinFunction_SPI2, GPIO_PIN_CLEAR }, // SPI2 SCK
    { GPIOPortID_I, GPIOPinID_2,  GPIOPinFunction_ALT_PP, GPIOAltPinFunction_SPI2, GPIO_PIN_CLEAR }, // SPI2 MISO
    { GPIOPortID_I, GPIOPinID_3,  GPIOPinFunction_ALT_PP, GPIOAltPinFunction_SPI2, GPIO_PIN_CLEAR }, // SPI2 MOSI
  
    { GPIOPortID_G, GPIOPinID_9,  GPIOPinFunction_OUT_PP, GPIOAltPinFunction_NONE, GPIO_PIN_SET }, // RESET_2
    // End Marker
    { GPIOPortID_MAX, GPIOPinID_MAX, GPIOPinFunction_UNKNOWN, GPIOAltPinFunction_NONE, GPIO_PIN_CLEAR }
};
  
/* Local Functions */
  
static void do_peripheral_enable()
{
    // Enable clock to the required AHB2 peripherals
    //RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
    RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_CRYP, ENABLE);
    RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, ENABLE);
    RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
    //RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE);
  
    // Enable clock to the required AHB1 peripherals
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOI, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);
    //RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CCMDATARAMEN, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    //RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2D, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC_Tx, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC_Rx, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC_PTP, ENABLE);
    //RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS, ENABLE);
    //RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS_ULPI, ENABLE);
  
    // Enable clock to the required AHB3 peripherals
    //RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);
  
    // Enable clock to the required APB1 peripherals
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //clock for TIM2
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //speed feedback
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //Heater/Blower
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //Pumps
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12, ENABLE); //speed feedback
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, ENABLE); //clock for TIM13
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE); //clock for TIM14
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,  ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3,  ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,  ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,  ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C3,  ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,  ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2,  ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,   ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,  ENABLE);
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,   ENABLE);
  
    // Enable clock to the required APB2 peripherals
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11, ENABLE);
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO,   ENABLE);
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI4, ENABLE);
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI5, ENABLE);
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI6, ENABLE);
  
    // RTC Clock source settings
    //PWR_BackupAccessCmd(ENABLE);
    //RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  
    // Config the required debug behaviours
    //DBGMCU_APB1PeriphConfig(DBGMCU_IWDG_STOP, ENABLE);
    //DBGMCU_APB1PeriphConfig(DBGMCU_WWDG_STOP, ENABLE);
  
    // Explicitly disable the USB peripherals
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_OTG_HS, DISABLE);
    RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_OTG_FS, DISABLE);
}
/*
static void do_interrupt_init()
{
    IRQn_Type irq;
  
    // Disable interrupts globally
    CPU_DISABLE_INTERRUPT();
  
    // Reset the external interrupt controller
    EXTI_DeInit();
  
    // Disable and clear all interrupts in the NVIC
    for ( irq = WWDG_IRQn; irq < FPU_IRQn; irq++)
    {
        NVIC_DisableIRQ(irq);
  
        NVIC_ClearPendingIRQ(irq);
    }
  
    // TODO: move the USART interuppt configuration out of the rs232_init
    // Disable SysTick Timer
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
  
    // Clear any pending systick and SV Interrupt
    SCB->ICSR |= (SCB_ICSR_PENDSVCLR_Msk | SCB_ICSR_PENDSTSET_Msk);
}
*/
static void do_driver_init()
{
  
    gpio_init();
    i2c_init();
    spi_init();
    rs232_init();
  
    // TODO: add other drivers init here
}
  
static void do_device_driver_init()
{
    // Order may be important
  
    //device_init();
  
    // TODO: add device drivers init here
}
  
static void do_pwr_control_init()
{
    /* Ensure that the power control module is enabled */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
  
    /* Put things in a known state */
    PWR_DeInit();
  
    /* Set the regulator to scale mode 1 to permit max clock frequencies */
    PWR_MainRegulatorModeConfig(PWR_Regulator_Voltage_Scale1);
  
    /* Disable the internal power regulator */
    PWR_PVDCmd(DISABLE);
  
    /* Ensure that flash remains powered in stop mode */
    PWR_FlashPowerDownCmd(DISABLE);
  
    /* Ensure that wakeup pin is disabled */
    PWR_WakeUpPinCmd(DISABLE);
  
    /* Ensure that debugger can remain attached when in low power modes */
    DBGMCU_Config(DBGMCU_SLEEP,   ENABLE);
    DBGMCU_Config(DBGMCU_STOP,    ENABLE);
    DBGMCU_Config(DBGMCU_STANDBY, ENABLE);
}
  
static void do_sys_tick_init()
{
    gSysTickCount = 0;
  
    SysTick_Config(SystemCoreClock / 1000);
}
  
void SysTick_Handler()
{
    gSysTickCount++;
}
  
/* Exposed API */
  
void platform_init(void)
{
    if (!gIsInitialized)
    {
        gIsInitialized = TRUE;
  
        // TODO: Determine restart reason (watchdog restart or any other type of restart)???
  
        do_pwr_control_init();
  
        do_peripheral_enable();
  
        //do_interrupt_init();
  
        do_sys_tick_init();
  
        do_driver_init();
  
        do_device_driver_init();
  
    }
    return;
}



 

Outcomes