mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-17 23:48:13 +08:00
修复mico-sdk错误
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,27 +1,27 @@
|
||||
#
|
||||
# UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
# Copyright (c) 2016 MXCHIP Inc.
|
||||
#
|
||||
# The contents of this file may not be disclosed to third parties, copied or
|
||||
# duplicated in any form, in whole or in part, without the prior written
|
||||
# permission of MXCHIP Corporation.
|
||||
#
|
||||
|
||||
NAME = STM32F4xx_Peripheral_Drivers
|
||||
|
||||
GLOBAL_INCLUDES := .
|
||||
|
||||
# Include STM32F2xx Standard Peripheral Libraries
|
||||
$(NAME)_COMPONENTS += MCU/STM32F4xx/peripherals/libraries
|
||||
|
||||
$(NAME)_SOURCES := platform_adc.c \
|
||||
platform_rtc.c \
|
||||
platform_gpio.c \
|
||||
platform_i2c.c \
|
||||
platform_rng.c \
|
||||
platform_mcu_powersave.c \
|
||||
platform_pwm.c \
|
||||
platform_flash.c \
|
||||
platform_spi.c \
|
||||
platform_uart.c \
|
||||
platform_watchdog.c
|
||||
#
|
||||
# UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
# Copyright (c) 2016 MXCHIP Inc.
|
||||
#
|
||||
# The contents of this file may not be disclosed to third parties, copied or
|
||||
# duplicated in any form, in whole or in part, without the prior written
|
||||
# permission of MXCHIP Corporation.
|
||||
#
|
||||
|
||||
NAME = STM32F4xx_Peripheral_Drivers
|
||||
|
||||
GLOBAL_INCLUDES := .
|
||||
|
||||
# Include STM32F2xx Standard Peripheral Libraries
|
||||
$(NAME)_COMPONENTS += MCU/STM32F4xx/peripherals/libraries
|
||||
|
||||
$(NAME)_SOURCES := platform_adc.c \
|
||||
platform_rtc.c \
|
||||
platform_gpio.c \
|
||||
platform_i2c.c \
|
||||
platform_rng.c \
|
||||
platform_mcu_powersave.c \
|
||||
platform_pwm.c \
|
||||
platform_flash.c \
|
||||
platform_spi.c \
|
||||
platform_uart.c \
|
||||
platform_watchdog.c
|
||||
|
||||
@@ -1,161 +1,161 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_adc.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide ADC driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "platform_peripheral.h"
|
||||
#include "platform_logging.h"
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
static const uint16_t adc_sampling_cycle[] =
|
||||
{
|
||||
[ADC_SampleTime_3Cycles ] = 3,
|
||||
[ADC_SampleTime_15Cycles ] = 15,
|
||||
[ADC_SampleTime_28Cycles ] = 28,
|
||||
[ADC_SampleTime_56Cycles ] = 56,
|
||||
[ADC_SampleTime_84Cycles ] = 84,
|
||||
[ADC_SampleTime_112Cycles] = 112,
|
||||
[ADC_SampleTime_144Cycles] = 144,
|
||||
[ADC_SampleTime_480Cycles] = 480,
|
||||
};
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
|
||||
|
||||
OSStatus platform_adc_init( const platform_adc_t* adc, uint32_t sample_cycle )
|
||||
{
|
||||
GPIO_InitTypeDef gpio_init_structure;
|
||||
ADC_InitTypeDef adc_init_structure;
|
||||
ADC_CommonInitTypeDef adc_common_init_structure;
|
||||
uint8_t a;
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( adc != NULL, exit, err = kParamErr);
|
||||
|
||||
/* Enable peripheral clock for this port */
|
||||
err = platform_gpio_enable_clock( adc->pin );
|
||||
require_noerr(err, exit);
|
||||
|
||||
/* Initialize the associated GPIO */
|
||||
gpio_init_structure.GPIO_Pin = (uint32_t)( 1 << adc->pin->pin_number );;
|
||||
gpio_init_structure.GPIO_Speed = (GPIOSpeed_TypeDef) 0;
|
||||
gpio_init_structure.GPIO_Mode = GPIO_Mode_AN;
|
||||
gpio_init_structure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
gpio_init_structure.GPIO_OType = GPIO_OType_OD;
|
||||
GPIO_Init( adc->pin->port, &gpio_init_structure );
|
||||
|
||||
RCC_APB2PeriphClockCmd( adc->adc_peripheral_clock, ENABLE );
|
||||
|
||||
/* Initialize the ADC */
|
||||
ADC_StructInit( &adc_init_structure );
|
||||
adc_init_structure.ADC_Resolution = ADC_Resolution_12b;
|
||||
adc_init_structure.ADC_ScanConvMode = DISABLE;
|
||||
adc_init_structure.ADC_ContinuousConvMode = DISABLE;
|
||||
adc_init_structure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
|
||||
adc_init_structure.ADC_DataAlign = ADC_DataAlign_Right;
|
||||
adc_init_structure.ADC_NbrOfConversion = 1;
|
||||
ADC_Init( adc->port, &adc_init_structure );
|
||||
|
||||
ADC_CommonStructInit( &adc_common_init_structure );
|
||||
adc_common_init_structure.ADC_Mode = ADC_Mode_Independent;
|
||||
adc_common_init_structure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
|
||||
adc_common_init_structure.ADC_Prescaler = ADC_Prescaler_Div2;
|
||||
adc_common_init_structure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
|
||||
ADC_CommonInit( &adc_common_init_structure );
|
||||
|
||||
ADC_Cmd( adc->port, ENABLE );
|
||||
|
||||
/* Find the closest supported sampling time by the MCU */
|
||||
for ( a = 0; ( a < sizeof( adc_sampling_cycle ) / sizeof(uint16_t) ) && adc_sampling_cycle[a] < sample_cycle; a++ )
|
||||
{
|
||||
}
|
||||
|
||||
/* Initialize the ADC channel */
|
||||
ADC_RegularChannelConfig( adc->port, adc->channel, adc->rank, a );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_adc_take_sample( const platform_adc_t* adc, uint16_t* output )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( adc != NULL, exit, err = kParamErr);
|
||||
|
||||
/* Start conversion */
|
||||
ADC_SoftwareStartConv( adc->port );
|
||||
|
||||
/* Wait until end of conversion */
|
||||
while ( ADC_GetFlagStatus( adc->port, ADC_FLAG_EOC ) == RESET )
|
||||
{
|
||||
}
|
||||
|
||||
/* Read ADC conversion result */
|
||||
*output = ADC_GetConversionValue( adc->port );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_adc_take_sample_stream( const platform_adc_t* adc, void* buffer, uint16_t buffer_length )
|
||||
{
|
||||
UNUSED_PARAMETER(adc);
|
||||
UNUSED_PARAMETER(buffer);
|
||||
UNUSED_PARAMETER(buffer_length);
|
||||
platform_log("unimplemented");
|
||||
return kNotPreparedErr;
|
||||
}
|
||||
|
||||
OSStatus platform_adc_deinit( const platform_adc_t* adc )
|
||||
{
|
||||
UNUSED_PARAMETER(adc);
|
||||
platform_log("unimplemented");
|
||||
return kNotPreparedErr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_adc.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide ADC driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "platform_peripheral.h"
|
||||
#include "platform_logging.h"
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
static const uint16_t adc_sampling_cycle[] =
|
||||
{
|
||||
[ADC_SampleTime_3Cycles ] = 3,
|
||||
[ADC_SampleTime_15Cycles ] = 15,
|
||||
[ADC_SampleTime_28Cycles ] = 28,
|
||||
[ADC_SampleTime_56Cycles ] = 56,
|
||||
[ADC_SampleTime_84Cycles ] = 84,
|
||||
[ADC_SampleTime_112Cycles] = 112,
|
||||
[ADC_SampleTime_144Cycles] = 144,
|
||||
[ADC_SampleTime_480Cycles] = 480,
|
||||
};
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
|
||||
|
||||
OSStatus platform_adc_init( const platform_adc_t* adc, uint32_t sample_cycle )
|
||||
{
|
||||
GPIO_InitTypeDef gpio_init_structure;
|
||||
ADC_InitTypeDef adc_init_structure;
|
||||
ADC_CommonInitTypeDef adc_common_init_structure;
|
||||
uint8_t a;
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( adc != NULL, exit, err = kParamErr);
|
||||
|
||||
/* Enable peripheral clock for this port */
|
||||
err = platform_gpio_enable_clock( adc->pin );
|
||||
require_noerr(err, exit);
|
||||
|
||||
/* Initialize the associated GPIO */
|
||||
gpio_init_structure.GPIO_Pin = (uint32_t)( 1 << adc->pin->pin_number );;
|
||||
gpio_init_structure.GPIO_Speed = (GPIOSpeed_TypeDef) 0;
|
||||
gpio_init_structure.GPIO_Mode = GPIO_Mode_AN;
|
||||
gpio_init_structure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
gpio_init_structure.GPIO_OType = GPIO_OType_OD;
|
||||
GPIO_Init( adc->pin->port, &gpio_init_structure );
|
||||
|
||||
RCC_APB2PeriphClockCmd( adc->adc_peripheral_clock, ENABLE );
|
||||
|
||||
/* Initialize the ADC */
|
||||
ADC_StructInit( &adc_init_structure );
|
||||
adc_init_structure.ADC_Resolution = ADC_Resolution_12b;
|
||||
adc_init_structure.ADC_ScanConvMode = DISABLE;
|
||||
adc_init_structure.ADC_ContinuousConvMode = DISABLE;
|
||||
adc_init_structure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
|
||||
adc_init_structure.ADC_DataAlign = ADC_DataAlign_Right;
|
||||
adc_init_structure.ADC_NbrOfConversion = 1;
|
||||
ADC_Init( adc->port, &adc_init_structure );
|
||||
|
||||
ADC_CommonStructInit( &adc_common_init_structure );
|
||||
adc_common_init_structure.ADC_Mode = ADC_Mode_Independent;
|
||||
adc_common_init_structure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
|
||||
adc_common_init_structure.ADC_Prescaler = ADC_Prescaler_Div2;
|
||||
adc_common_init_structure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
|
||||
ADC_CommonInit( &adc_common_init_structure );
|
||||
|
||||
ADC_Cmd( adc->port, ENABLE );
|
||||
|
||||
/* Find the closest supported sampling time by the MCU */
|
||||
for ( a = 0; ( a < sizeof( adc_sampling_cycle ) / sizeof(uint16_t) ) && adc_sampling_cycle[a] < sample_cycle; a++ )
|
||||
{
|
||||
}
|
||||
|
||||
/* Initialize the ADC channel */
|
||||
ADC_RegularChannelConfig( adc->port, adc->channel, adc->rank, a );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_adc_take_sample( const platform_adc_t* adc, uint16_t* output )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( adc != NULL, exit, err = kParamErr);
|
||||
|
||||
/* Start conversion */
|
||||
ADC_SoftwareStartConv( adc->port );
|
||||
|
||||
/* Wait until end of conversion */
|
||||
while ( ADC_GetFlagStatus( adc->port, ADC_FLAG_EOC ) == RESET )
|
||||
{
|
||||
}
|
||||
|
||||
/* Read ADC conversion result */
|
||||
*output = ADC_GetConversionValue( adc->port );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_adc_take_sample_stream( const platform_adc_t* adc, void* buffer, uint16_t buffer_length )
|
||||
{
|
||||
UNUSED_PARAMETER(adc);
|
||||
UNUSED_PARAMETER(buffer);
|
||||
UNUSED_PARAMETER(buffer_length);
|
||||
platform_log("unimplemented");
|
||||
return kNotPreparedErr;
|
||||
}
|
||||
|
||||
OSStatus platform_adc_deinit( const platform_adc_t* adc )
|
||||
{
|
||||
UNUSED_PARAMETER(adc);
|
||||
platform_log("unimplemented");
|
||||
return kNotPreparedErr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
2400
mico-os/platform/MCU/STM32F4xx/peripherals/platform_flash.c
Executable file → Normal file
2400
mico-os/platform/MCU/STM32F4xx/peripherals/platform_flash.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,284 +1,284 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_mcu_peripheral.h
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide all the headers of functions for stm32f2xx platform
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stm32f4xx.h"
|
||||
#include "stm32f4xx_dma.h"
|
||||
#include "stm32f4xx_adc.h"
|
||||
#include "stm32f4xx_rcc.h"
|
||||
#include "stm32f4xx_gpio.h"
|
||||
#include "stm32f4xx_tim.h"
|
||||
#include "stm32f4xx_rtc.h"
|
||||
#include "stm32f4xx_pwr.h"
|
||||
#include "stm32f4xx_rng.h"
|
||||
|
||||
#include "mico_rtos.h"
|
||||
#include "RingBufferUtils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* Macros
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
/* GPIOA to I */
|
||||
#define NUMBER_OF_GPIO_PORTS (8)
|
||||
|
||||
/* Interrupt line 0 to 15. Each line is shared among the same numbered pins across all GPIO ports */
|
||||
#define NUMBER_OF_GPIO_IRQ_LINES (16)
|
||||
|
||||
/* USART1 to 6 */
|
||||
#define NUMBER_OF_UART_PORTS (6)
|
||||
|
||||
|
||||
/* Invalid UART port number */
|
||||
#define INVALID_UART_PORT_NUMBER (0xff)
|
||||
|
||||
/* SPI1 to SPI3 */
|
||||
#define NUMBER_OF_SPI_PORTS (3)
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/* GPIO port */
|
||||
typedef GPIO_TypeDef platform_gpio_port_t;
|
||||
|
||||
/* UART port */
|
||||
typedef USART_TypeDef platform_uart_port_t;
|
||||
|
||||
/* SPI port */
|
||||
typedef SPI_TypeDef platform_spi_port_t;
|
||||
|
||||
/* QSPI port */
|
||||
#if defined(STM32F412xG) || defined(STM32F446xx) || defined(STM32F469_479xx)
|
||||
typedef QUADSPI_TypeDef platform_qspi_port_t;
|
||||
#endif
|
||||
|
||||
/* I2C port */
|
||||
typedef I2C_TypeDef platform_i2c_port_t;
|
||||
|
||||
/* GPIO alternate function */
|
||||
typedef uint8_t platform_gpio_alternate_function_t;
|
||||
|
||||
/* Peripheral clock function */
|
||||
typedef void (*platform_peripheral_clock_function_t)(uint32_t clock, FunctionalState state );
|
||||
|
||||
typedef DMA_TypeDef dma_registers_t;
|
||||
typedef FunctionalState functional_state_t;
|
||||
typedef uint32_t peripheral_clock_t;
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
typedef struct
|
||||
{
|
||||
DMA_TypeDef* controller;
|
||||
DMA_Stream_TypeDef* stream;
|
||||
uint32_t channel;
|
||||
IRQn_Type irq_vector;
|
||||
uint32_t complete_flags;
|
||||
uint32_t error_flags;
|
||||
} platform_dma_config_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_gpio_port_t* port;
|
||||
uint8_t pin_number;
|
||||
} platform_gpio_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ADC_TypeDef* port;
|
||||
uint8_t channel;
|
||||
uint32_t adc_peripheral_clock;
|
||||
uint8_t rank;
|
||||
const platform_gpio_t* pin;
|
||||
} platform_adc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TIM_TypeDef* tim;
|
||||
uint8_t channel;
|
||||
uint32_t tim_peripheral_clock;
|
||||
uint8_t gpio_af;
|
||||
const platform_gpio_t* pin;
|
||||
} platform_pwm_t;
|
||||
|
||||
#if defined(STM32F412xG) || defined(STM32F446xx) || defined(STM32F469_479xx)
|
||||
typedef struct
|
||||
{
|
||||
platform_qspi_port_t* port;
|
||||
uint32_t FSelect;
|
||||
uint32_t peripheral_clock_reg;
|
||||
platform_peripheral_clock_function_t peripheral_clock_func;
|
||||
const platform_gpio_t* pin_d0;
|
||||
const platform_gpio_t* pin_d1;
|
||||
const platform_gpio_t* pin_d2;
|
||||
const platform_gpio_t* pin_d3;
|
||||
const platform_gpio_t* pin_clock;
|
||||
const platform_gpio_t* pin_cs;
|
||||
platform_dma_config_t dma;
|
||||
uint8_t gpio_af_d0;
|
||||
uint8_t gpio_af_d1;
|
||||
uint8_t gpio_af_d2;
|
||||
uint8_t gpio_af_d3;
|
||||
uint8_t gpio_af_clk;
|
||||
uint8_t gpio_af_cs;
|
||||
} platform_qspi_t;
|
||||
#endif
|
||||
|
||||
/* DMA can be enabled by setting SPI_USE_DMA */
|
||||
typedef struct
|
||||
{
|
||||
platform_spi_port_t* port;
|
||||
uint8_t gpio_af;
|
||||
uint32_t peripheral_clock_reg;
|
||||
platform_peripheral_clock_function_t peripheral_clock_func;
|
||||
const platform_gpio_t* pin_mosi;
|
||||
const platform_gpio_t* pin_miso;
|
||||
const platform_gpio_t* pin_clock;
|
||||
platform_dma_config_t tx_dma;
|
||||
platform_dma_config_t rx_dma;
|
||||
} platform_spi_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_spi_t* peripheral;
|
||||
mico_mutex_t spi_mutex;
|
||||
} platform_spi_driver_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t unimplemented;
|
||||
} platform_spi_slave_driver_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_i2c_port_t* port;
|
||||
const platform_gpio_t* pin_scl;
|
||||
const platform_gpio_t* pin_sda;
|
||||
uint32_t peripheral_clock_reg;
|
||||
dma_registers_t* tx_dma;
|
||||
peripheral_clock_t tx_dma_peripheral_clock;
|
||||
DMA_Stream_TypeDef* tx_dma_stream;
|
||||
DMA_Stream_TypeDef* rx_dma_stream;
|
||||
int tx_dma_stream_id;
|
||||
int rx_dma_stream_id;
|
||||
uint32_t tx_dma_channel;
|
||||
uint32_t rx_dma_channel;
|
||||
uint8_t gpio_af_scl;
|
||||
uint8_t gpio_af_sda;
|
||||
} platform_i2c_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mico_mutex_t i2c_mutex;
|
||||
} platform_i2c_driver_t;
|
||||
|
||||
typedef void (* wakeup_irq_handler_t)(void *arg);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_uart_port_t* port;
|
||||
const platform_gpio_t* pin_tx;
|
||||
const platform_gpio_t* pin_rx;
|
||||
const platform_gpio_t* pin_cts;
|
||||
const platform_gpio_t* pin_rts;
|
||||
platform_dma_config_t tx_dma_config;
|
||||
platform_dma_config_t rx_dma_config;
|
||||
} platform_uart_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_uart_t* peripheral;
|
||||
ring_buffer_t* rx_buffer;
|
||||
mico_semaphore_t rx_complete;
|
||||
mico_semaphore_t tx_complete;
|
||||
mico_mutex_t tx_mutex;
|
||||
mico_semaphore_t sem_wakeup;
|
||||
volatile uint32_t tx_size;
|
||||
volatile uint32_t rx_size;
|
||||
volatile OSStatus last_receive_result;
|
||||
volatile OSStatus last_transmit_result;
|
||||
volatile bool initialized;
|
||||
volatile bool is_flow_control;
|
||||
volatile bool is_recv_over_flow;
|
||||
} platform_uart_driver_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flash_type;
|
||||
uint32_t flash_start_addr;
|
||||
uint32_t flash_length;
|
||||
uint32_t flash_protect_opt;
|
||||
} platform_flash_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const platform_flash_t* peripheral;
|
||||
mico_mutex_t flash_mutex;
|
||||
volatile bool initialized;
|
||||
} platform_flash_driver_t;
|
||||
|
||||
/******************************************************
|
||||
* Global Variables
|
||||
******************************************************/
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
OSStatus platform_gpio_irq_manager_init ( void );
|
||||
uint8_t platform_gpio_get_port_number ( platform_gpio_port_t* gpio_port );
|
||||
OSStatus platform_gpio_enable_clock ( const platform_gpio_t* gpio );
|
||||
OSStatus platform_gpio_set_alternate_function( platform_gpio_port_t* gpio_port, uint8_t pin_number, GPIOOType_TypeDef output_type, GPIOPuPd_TypeDef pull_up_down_type, uint8_t alternation_function );
|
||||
|
||||
OSStatus platform_mcu_powersave_init ( void );
|
||||
|
||||
OSStatus platform_rtc_init ( void );
|
||||
OSStatus platform_rtc_enter_powersave ( void );
|
||||
OSStatus platform_rtc_abort_powersave ( void );
|
||||
OSStatus platform_rtc_exit_powersave ( uint32_t requested_sleep_time, uint32_t *cpu_sleep_time );
|
||||
|
||||
uint8_t platform_uart_get_port_number ( platform_uart_port_t* uart );
|
||||
void platform_uart_irq ( platform_uart_driver_t* driver );
|
||||
void platform_uart_tx_dma_irq ( platform_uart_driver_t* driver );
|
||||
void platform_uart_rx_dma_irq ( platform_uart_driver_t* driver );
|
||||
|
||||
uint8_t platform_spi_get_port_number ( platform_spi_port_t* spi );
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_mcu_peripheral.h
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide all the headers of functions for stm32f2xx platform
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stm32f4xx.h"
|
||||
#include "stm32f4xx_dma.h"
|
||||
#include "stm32f4xx_adc.h"
|
||||
#include "stm32f4xx_rcc.h"
|
||||
#include "stm32f4xx_gpio.h"
|
||||
#include "stm32f4xx_tim.h"
|
||||
#include "stm32f4xx_rtc.h"
|
||||
#include "stm32f4xx_pwr.h"
|
||||
#include "stm32f4xx_rng.h"
|
||||
|
||||
#include "mico_rtos.h"
|
||||
#include "RingBufferUtils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* Macros
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
/* GPIOA to I */
|
||||
#define NUMBER_OF_GPIO_PORTS (8)
|
||||
|
||||
/* Interrupt line 0 to 15. Each line is shared among the same numbered pins across all GPIO ports */
|
||||
#define NUMBER_OF_GPIO_IRQ_LINES (16)
|
||||
|
||||
/* USART1 to 6 */
|
||||
#define NUMBER_OF_UART_PORTS (6)
|
||||
|
||||
|
||||
/* Invalid UART port number */
|
||||
#define INVALID_UART_PORT_NUMBER (0xff)
|
||||
|
||||
/* SPI1 to SPI3 */
|
||||
#define NUMBER_OF_SPI_PORTS (3)
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/* GPIO port */
|
||||
typedef GPIO_TypeDef platform_gpio_port_t;
|
||||
|
||||
/* UART port */
|
||||
typedef USART_TypeDef platform_uart_port_t;
|
||||
|
||||
/* SPI port */
|
||||
typedef SPI_TypeDef platform_spi_port_t;
|
||||
|
||||
/* QSPI port */
|
||||
#if defined(STM32F412xG) || defined(STM32F446xx) || defined(STM32F469_479xx)
|
||||
typedef QUADSPI_TypeDef platform_qspi_port_t;
|
||||
#endif
|
||||
|
||||
/* I2C port */
|
||||
typedef I2C_TypeDef platform_i2c_port_t;
|
||||
|
||||
/* GPIO alternate function */
|
||||
typedef uint8_t platform_gpio_alternate_function_t;
|
||||
|
||||
/* Peripheral clock function */
|
||||
typedef void (*platform_peripheral_clock_function_t)(uint32_t clock, FunctionalState state );
|
||||
|
||||
typedef DMA_TypeDef dma_registers_t;
|
||||
typedef FunctionalState functional_state_t;
|
||||
typedef uint32_t peripheral_clock_t;
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
typedef struct
|
||||
{
|
||||
DMA_TypeDef* controller;
|
||||
DMA_Stream_TypeDef* stream;
|
||||
uint32_t channel;
|
||||
IRQn_Type irq_vector;
|
||||
uint32_t complete_flags;
|
||||
uint32_t error_flags;
|
||||
} platform_dma_config_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_gpio_port_t* port;
|
||||
uint8_t pin_number;
|
||||
} platform_gpio_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ADC_TypeDef* port;
|
||||
uint8_t channel;
|
||||
uint32_t adc_peripheral_clock;
|
||||
uint8_t rank;
|
||||
const platform_gpio_t* pin;
|
||||
} platform_adc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TIM_TypeDef* tim;
|
||||
uint8_t channel;
|
||||
uint32_t tim_peripheral_clock;
|
||||
uint8_t gpio_af;
|
||||
const platform_gpio_t* pin;
|
||||
} platform_pwm_t;
|
||||
|
||||
#if defined(STM32F412xG) || defined(STM32F446xx) || defined(STM32F469_479xx)
|
||||
typedef struct
|
||||
{
|
||||
platform_qspi_port_t* port;
|
||||
uint32_t FSelect;
|
||||
uint32_t peripheral_clock_reg;
|
||||
platform_peripheral_clock_function_t peripheral_clock_func;
|
||||
const platform_gpio_t* pin_d0;
|
||||
const platform_gpio_t* pin_d1;
|
||||
const platform_gpio_t* pin_d2;
|
||||
const platform_gpio_t* pin_d3;
|
||||
const platform_gpio_t* pin_clock;
|
||||
const platform_gpio_t* pin_cs;
|
||||
platform_dma_config_t dma;
|
||||
uint8_t gpio_af_d0;
|
||||
uint8_t gpio_af_d1;
|
||||
uint8_t gpio_af_d2;
|
||||
uint8_t gpio_af_d3;
|
||||
uint8_t gpio_af_clk;
|
||||
uint8_t gpio_af_cs;
|
||||
} platform_qspi_t;
|
||||
#endif
|
||||
|
||||
/* DMA can be enabled by setting SPI_USE_DMA */
|
||||
typedef struct
|
||||
{
|
||||
platform_spi_port_t* port;
|
||||
uint8_t gpio_af;
|
||||
uint32_t peripheral_clock_reg;
|
||||
platform_peripheral_clock_function_t peripheral_clock_func;
|
||||
const platform_gpio_t* pin_mosi;
|
||||
const platform_gpio_t* pin_miso;
|
||||
const platform_gpio_t* pin_clock;
|
||||
platform_dma_config_t tx_dma;
|
||||
platform_dma_config_t rx_dma;
|
||||
} platform_spi_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_spi_t* peripheral;
|
||||
mico_mutex_t spi_mutex;
|
||||
} platform_spi_driver_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t unimplemented;
|
||||
} platform_spi_slave_driver_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_i2c_port_t* port;
|
||||
const platform_gpio_t* pin_scl;
|
||||
const platform_gpio_t* pin_sda;
|
||||
uint32_t peripheral_clock_reg;
|
||||
dma_registers_t* tx_dma;
|
||||
peripheral_clock_t tx_dma_peripheral_clock;
|
||||
DMA_Stream_TypeDef* tx_dma_stream;
|
||||
DMA_Stream_TypeDef* rx_dma_stream;
|
||||
int tx_dma_stream_id;
|
||||
int rx_dma_stream_id;
|
||||
uint32_t tx_dma_channel;
|
||||
uint32_t rx_dma_channel;
|
||||
uint8_t gpio_af_scl;
|
||||
uint8_t gpio_af_sda;
|
||||
} platform_i2c_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mico_mutex_t i2c_mutex;
|
||||
} platform_i2c_driver_t;
|
||||
|
||||
typedef void (* wakeup_irq_handler_t)(void *arg);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_uart_port_t* port;
|
||||
const platform_gpio_t* pin_tx;
|
||||
const platform_gpio_t* pin_rx;
|
||||
const platform_gpio_t* pin_cts;
|
||||
const platform_gpio_t* pin_rts;
|
||||
platform_dma_config_t tx_dma_config;
|
||||
platform_dma_config_t rx_dma_config;
|
||||
} platform_uart_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_uart_t* peripheral;
|
||||
ring_buffer_t* rx_buffer;
|
||||
mico_semaphore_t rx_complete;
|
||||
mico_semaphore_t tx_complete;
|
||||
mico_mutex_t tx_mutex;
|
||||
mico_semaphore_t sem_wakeup;
|
||||
volatile uint32_t tx_size;
|
||||
volatile uint32_t rx_size;
|
||||
volatile OSStatus last_receive_result;
|
||||
volatile OSStatus last_transmit_result;
|
||||
volatile bool initialized;
|
||||
volatile bool is_flow_control;
|
||||
volatile bool is_recv_over_flow;
|
||||
} platform_uart_driver_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t flash_type;
|
||||
uint32_t flash_start_addr;
|
||||
uint32_t flash_length;
|
||||
uint32_t flash_protect_opt;
|
||||
} platform_flash_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const platform_flash_t* peripheral;
|
||||
mico_mutex_t flash_mutex;
|
||||
volatile bool initialized;
|
||||
} platform_flash_driver_t;
|
||||
|
||||
/******************************************************
|
||||
* Global Variables
|
||||
******************************************************/
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
OSStatus platform_gpio_irq_manager_init ( void );
|
||||
uint8_t platform_gpio_get_port_number ( platform_gpio_port_t* gpio_port );
|
||||
OSStatus platform_gpio_enable_clock ( const platform_gpio_t* gpio );
|
||||
OSStatus platform_gpio_set_alternate_function( platform_gpio_port_t* gpio_port, uint8_t pin_number, GPIOOType_TypeDef output_type, GPIOPuPd_TypeDef pull_up_down_type, uint8_t alternation_function );
|
||||
|
||||
OSStatus platform_mcu_powersave_init ( void );
|
||||
|
||||
OSStatus platform_rtc_init ( void );
|
||||
OSStatus platform_rtc_enter_powersave ( void );
|
||||
OSStatus platform_rtc_abort_powersave ( void );
|
||||
OSStatus platform_rtc_exit_powersave ( uint32_t requested_sleep_time, uint32_t *cpu_sleep_time );
|
||||
|
||||
uint8_t platform_uart_get_port_number ( platform_uart_port_t* uart );
|
||||
void platform_uart_irq ( platform_uart_driver_t* driver );
|
||||
void platform_uart_tx_dma_irq ( platform_uart_driver_t* driver );
|
||||
void platform_uart_rx_dma_irq ( platform_uart_driver_t* driver );
|
||||
|
||||
uint8_t platform_spi_get_port_number ( platform_spi_port_t* spi );
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,464 +1,464 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_mcu_powersave.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide functions called by MICO to drive stm32f2xx
|
||||
* platform: - e.g. power save, reboot, platform initialize
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include "platform_peripheral.h"
|
||||
#include "platform.h"
|
||||
#include "platform_config.h"
|
||||
#include "platform_logging.h"
|
||||
#include <string.h> // For memcmp
|
||||
#include "crt0.h"
|
||||
#include "platform_init.h"
|
||||
|
||||
/******************************************************
|
||||
* Macros
|
||||
******************************************************/
|
||||
|
||||
#define NUMBER_OF_LSE_TICKS_PER_MILLISECOND(scale_factor) ( 32768 / 1000 / scale_factor )
|
||||
#define CONVERT_FROM_TICKS_TO_MS( n,s ) ( n / NUMBER_OF_LSE_TICKS_PER_MILLISECOND(s) )
|
||||
|
||||
#define ENABLE_INTERRUPTS __asm("CPSIE i") /**< Enable interrupts to start task switching in MICO RTOS. */
|
||||
#define DISABLE_INTERRUPTS __asm("CPSID i") /**< Disable interrupts to stop task switching in MICO RTOS. */
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
#define RTC_INTERRUPT_EXTI_LINE EXTI_Line22
|
||||
#define WUT_COUNTER_MAX 0xFFFF
|
||||
#define CK_SPRE_CLOCK_SOURCE_SELECTED 0xFFFF
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
|
||||
/* Default RTC time. Set to 12:20:30 08/04/2013 Monday */
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
static const platform_rtc_time_t default_rtc_time =
|
||||
{
|
||||
.sec = 30,
|
||||
.min = 20,
|
||||
.hr = 12,
|
||||
.weekday = 1,
|
||||
.date = 8,
|
||||
.month = 4,
|
||||
.year = 13,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
static unsigned long stop_mode_power_down_hook( unsigned long sleep_ms );
|
||||
static OSStatus select_wut_prescaler_calculate_wakeup_time( unsigned long* wakeup_time, unsigned long sleep_ms, unsigned long* scale_factor );
|
||||
#else
|
||||
static unsigned long idle_power_down_hook( unsigned long sleep_ms );
|
||||
#endif
|
||||
//void wake_up_interrupt_notify( void );
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
static bool wake_up_interrupt_triggered = false;
|
||||
static unsigned long rtc_timeout_start_time = 0;
|
||||
static int32_t stm32f2_clock_needed_counter = 0;
|
||||
#endif /* #ifndef MICO_DISABLE_MCU_POWERSAVE */
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
|
||||
OSStatus platform_mcu_powersave_init(void)
|
||||
{
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
EXTI_InitTypeDef EXTI_InitStructure;
|
||||
RTC_InitTypeDef RTC_InitStruct;
|
||||
|
||||
//RTC_DeInit( );
|
||||
|
||||
RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
|
||||
|
||||
/* RTC ticks every second */
|
||||
RTC_InitStruct.RTC_AsynchPrediv = 0x7F;
|
||||
RTC_InitStruct.RTC_SynchPrediv = 0xFF;
|
||||
|
||||
RTC_Init( &RTC_InitStruct );
|
||||
|
||||
/* Enable the PWR clock */
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
|
||||
|
||||
/* RTC clock source configuration ------------------------------------------*/
|
||||
/* Allow access to BKP Domain */
|
||||
PWR_BackupAccessCmd(ENABLE);
|
||||
PWR_BackupRegulatorCmd(ENABLE);
|
||||
|
||||
/* Enable the LSE OSC */
|
||||
RCC_LSEConfig(RCC_LSE_ON);
|
||||
/* Wait till LSE is ready */
|
||||
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
|
||||
{
|
||||
}
|
||||
|
||||
/* Select the RTC Clock Source */
|
||||
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
|
||||
|
||||
/* Enable the RTC Clock */
|
||||
RCC_RTCCLKCmd(ENABLE);
|
||||
|
||||
|
||||
/* RTC configuration -------------------------------------------------------*/
|
||||
/* Wait for RTC APB registers synchronisation */
|
||||
RTC_WaitForSynchro();
|
||||
|
||||
RTC_WakeUpCmd( DISABLE );
|
||||
EXTI_ClearITPendingBit( RTC_INTERRUPT_EXTI_LINE );
|
||||
PWR_ClearFlag(PWR_FLAG_WU);
|
||||
RTC_ClearFlag(RTC_FLAG_WUTF);
|
||||
|
||||
RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div2);
|
||||
|
||||
EXTI_ClearITPendingBit( RTC_INTERRUPT_EXTI_LINE );
|
||||
EXTI_InitStructure.EXTI_Line = RTC_INTERRUPT_EXTI_LINE;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init(&EXTI_InitStructure);
|
||||
|
||||
NVIC_EnableIRQ( RTC_WKUP_IRQn );
|
||||
|
||||
RTC_ITConfig(RTC_IT_WUT, DISABLE);
|
||||
|
||||
/* Prepare Stop-Mode but leave disabled */
|
||||
//PWR_ClearFlag(PWR_FLAG_WU);
|
||||
PWR->CR |= PWR_CR_LPDS;
|
||||
PWR->CR &= (unsigned long)(~(PWR_CR_PDDS));
|
||||
SCB->SCR |= ((unsigned long)SCB_SCR_SLEEPDEEP_Msk);
|
||||
|
||||
#ifdef USE_RTC_BKP
|
||||
if (RTC_ReadBackupRegister(RTC_BKP_DR0) != USE_RTC_BKP) {
|
||||
/* set it to 12:20:30 08/04/2013 monday */
|
||||
platform_rtc_set_time(&default_rtc_time);
|
||||
RTC_WriteBackupRegister(RTC_BKP_DR0, USE_RTC_BKP);
|
||||
}
|
||||
#else
|
||||
//#ifdef RTC_ENABLED
|
||||
/* application must have mico_application_default_time structure declared somewhere, otherwise it wont compile */
|
||||
/* write default application time inside rtc */
|
||||
platform_rtc_set_time( &default_rtc_time );
|
||||
//#endif /* RTC_ENABLED */
|
||||
#endif
|
||||
return kNoErr;
|
||||
#else
|
||||
return kUnsupportedErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
OSStatus platform_mcu_powersave_disable( void )
|
||||
{
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
DISABLE_INTERRUPTS;
|
||||
if ( stm32f2_clock_needed_counter <= 0 )
|
||||
{
|
||||
SCB->SCR &= (~((unsigned long)SCB_SCR_SLEEPDEEP_Msk));
|
||||
stm32f2_clock_needed_counter = 0;
|
||||
}
|
||||
stm32f2_clock_needed_counter++;
|
||||
ENABLE_INTERRUPTS;
|
||||
|
||||
return kNoErr;
|
||||
#else
|
||||
return kUnsupportedErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
OSStatus platform_mcu_powersave_enable( void )
|
||||
{
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
DISABLE_INTERRUPTS;
|
||||
stm32f2_clock_needed_counter--;
|
||||
if ( stm32f2_clock_needed_counter <= 0 )
|
||||
{
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
stm32f2_clock_needed_counter = 0;
|
||||
}
|
||||
ENABLE_INTERRUPTS;
|
||||
|
||||
return kNoErr;
|
||||
#else
|
||||
return kUnsupportedErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void platform_mcu_powersave_exit_notify( void )
|
||||
{
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
UNUSED_PARAMETER( wake_up_interrupt_triggered );
|
||||
wake_up_interrupt_triggered = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
static OSStatus select_wut_prescaler_calculate_wakeup_time( unsigned long* wakeup_time, unsigned long sleep_ms, unsigned long* scale_factor )
|
||||
{
|
||||
unsigned long temp;
|
||||
bool scale_factor_is_found = false;
|
||||
int i = 0;
|
||||
|
||||
static unsigned long int available_wut_prescalers[] =
|
||||
{
|
||||
RTC_WakeUpClock_RTCCLK_Div2,
|
||||
RTC_WakeUpClock_RTCCLK_Div4,
|
||||
RTC_WakeUpClock_RTCCLK_Div8,
|
||||
RTC_WakeUpClock_RTCCLK_Div16
|
||||
};
|
||||
static unsigned long scale_factor_values[] = { 2, 4, 8, 16 };
|
||||
|
||||
if ( sleep_ms == 0xFFFFFFFF )
|
||||
{
|
||||
/* wake up in a 100ms, since currently there may be no tasks to run, but after a few milliseconds */
|
||||
/* some of them can get unblocked( for example a task is blocked on mutex with unspecified ) */
|
||||
*scale_factor = 2;
|
||||
RTC_WakeUpClockConfig( RTC_WakeUpClock_RTCCLK_Div2 );
|
||||
*wakeup_time = NUMBER_OF_LSE_TICKS_PER_MILLISECOND( scale_factor_values[0] ) * 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
temp = NUMBER_OF_LSE_TICKS_PER_MILLISECOND( scale_factor_values[i] ) * sleep_ms;
|
||||
if ( temp < WUT_COUNTER_MAX )
|
||||
{
|
||||
scale_factor_is_found = true;
|
||||
*wakeup_time = temp;
|
||||
*scale_factor = scale_factor_values[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( scale_factor_is_found )
|
||||
{
|
||||
/* set new prescaler for wakeup timer */
|
||||
RTC_WakeUpClockConfig( available_wut_prescalers[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* scale factor can not be picked up for delays more that 32 seconds when RTCLK is selected as a clock source for the wakeup timer
|
||||
* for delays more than 32 seconds change from RTCCLK to 1Hz ck_spre clock source( used to update calendar registers ) */
|
||||
RTC_WakeUpClockConfig( RTC_WakeUpClock_CK_SPRE_16bits );
|
||||
|
||||
/* with 1Hz ck_spre clock source the resolution changes to seconds */
|
||||
*wakeup_time = ( sleep_ms / 1000 ) + 1;
|
||||
*scale_factor = CK_SPRE_CLOCK_SOURCE_SELECTED;
|
||||
|
||||
return kGeneralErr;
|
||||
}
|
||||
}
|
||||
|
||||
return kNoErr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************
|
||||
* RTOS Powersave Hooks
|
||||
******************************************************/
|
||||
|
||||
void platform_idle_hook( void )
|
||||
{
|
||||
__asm("wfi");
|
||||
}
|
||||
|
||||
uint32_t platform_power_down_hook( uint32_t sleep_ms )
|
||||
{
|
||||
#ifdef MICO_DISABLE_MCU_POWERSAVE
|
||||
/* If MCU powersave feature is disabled, enter idle mode when powerdown hook is called by the RTOS */
|
||||
return idle_power_down_hook( sleep_ms );
|
||||
|
||||
#else
|
||||
/* If MCU powersave feature is enabled, enter STOP mode when powerdown hook is called by the RTOS */
|
||||
return stop_mode_power_down_hook( sleep_ms );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MICO_DISABLE_MCU_POWERSAVE
|
||||
/* MCU Powersave is disabled */
|
||||
static unsigned long idle_power_down_hook( unsigned long sleep_ms )
|
||||
{
|
||||
UNUSED_PARAMETER( sleep_ms );
|
||||
ENABLE_INTERRUPTS;
|
||||
__asm("wfi");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static unsigned long stop_mode_power_down_hook( unsigned long sleep_ms )
|
||||
{
|
||||
unsigned long retval;
|
||||
unsigned long wut_ticks_passed;
|
||||
unsigned long scale_factor = 0;
|
||||
UNUSED_PARAMETER(sleep_ms);
|
||||
UNUSED_PARAMETER(rtc_timeout_start_time);
|
||||
UNUSED_PARAMETER(scale_factor);
|
||||
|
||||
if ( ( ( SCB->SCR & (unsigned long)SCB_SCR_SLEEPDEEP_Msk) != 0) && sleep_ms < 5 ){
|
||||
SCB->SCR &= (~((unsigned long)SCB_SCR_SLEEPDEEP_Msk));
|
||||
__asm("wfi");
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
/* Note: We return 0 ticks passed because system tick is still going when wfi instruction gets executed */
|
||||
ENABLE_INTERRUPTS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ( ( SCB->SCR & (unsigned long)SCB_SCR_SLEEPDEEP_Msk) ) != 0 )
|
||||
{
|
||||
/* pick up the appropriate prescaler for a requested delay */
|
||||
select_wut_prescaler_calculate_wakeup_time(&rtc_timeout_start_time, sleep_ms, &scale_factor );
|
||||
|
||||
DISABLE_INTERRUPTS;
|
||||
|
||||
SysTick->CTRL &= (~(SysTick_CTRL_TICKINT_Msk|SysTick_CTRL_ENABLE_Msk)); /* systick IRQ off */
|
||||
RTC_ITConfig(RTC_IT_WUT, ENABLE);
|
||||
|
||||
EXTI_ClearITPendingBit( RTC_INTERRUPT_EXTI_LINE );
|
||||
PWR_ClearFlag(PWR_FLAG_WU);
|
||||
RTC_ClearFlag(RTC_FLAG_WUTF);
|
||||
|
||||
RTC_SetWakeUpCounter( rtc_timeout_start_time );
|
||||
RTC_WakeUpCmd( ENABLE );
|
||||
platform_rtc_enter_powersave();
|
||||
|
||||
DBGMCU->CR |= 0x03; /* Enable debug in stop mode */
|
||||
|
||||
/* This code will be running with BASEPRI register value set to 0, the main intention behind that is that */
|
||||
/* all interrupts must be allowed to wake the CPU from the power-down mode */
|
||||
/* the PRIMASK is set to 1( see DISABLE_INTERRUPTS), thus we disable all interrupts before entering the power-down mode */
|
||||
/* This may sound contradictory, however according to the ARM CM3 documentation power-management unit */
|
||||
/* takes into account only the contents of the BASEPRI register and it is an external from the CPU core unit */
|
||||
/* PRIMASK register value doesn't affect its operation. */
|
||||
/* So, if the interrupt has been triggered just before the wfi instruction */
|
||||
/* it remains pending and wfi instruction will be treated as a nop */
|
||||
__asm("wfi");
|
||||
|
||||
/* After CPU exits powerdown mode, the processer will not execute the interrupt handler(PRIMASK is set to 1) */
|
||||
/* Disable rtc for now */
|
||||
RTC_WakeUpCmd( DISABLE );
|
||||
RTC_ITConfig(RTC_IT_WUT, DISABLE);
|
||||
|
||||
/* Initialise the clocks again */
|
||||
init_clocks( );
|
||||
|
||||
/* Enable CPU ticks */
|
||||
SysTick->CTRL |= (SysTick_CTRL_TICKINT_Msk|SysTick_CTRL_ENABLE_Msk);
|
||||
|
||||
/* Get the time of how long the sleep lasted */
|
||||
wut_ticks_passed = rtc_timeout_start_time - RTC_GetWakeUpCounter();
|
||||
UNUSED_VARIABLE(wut_ticks_passed);
|
||||
platform_rtc_exit_powersave( sleep_ms, (uint32_t *)&retval );
|
||||
/* as soon as interrupts are enabled, we will go and execute the interrupt handler */
|
||||
/* which triggered a wake up event */
|
||||
ENABLE_INTERRUPTS;
|
||||
wake_up_interrupt_triggered = false;
|
||||
return retval;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNUSED_PARAMETER(wut_ticks_passed);
|
||||
ENABLE_INTERRUPTS;
|
||||
__asm("wfi");
|
||||
|
||||
/* Note: We return 0 ticks passed because system tick is still going when wfi instruction gets executed */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* MICO_DISABLE_MCU_POWERSAVE */
|
||||
|
||||
|
||||
void platform_mcu_enter_standby(uint32_t secondsToWakeup)
|
||||
{
|
||||
platform_rtc_time_t time;
|
||||
uint32_t currentSecond;
|
||||
RTC_AlarmTypeDef RTC_AlarmStructure;
|
||||
|
||||
#if defined(STM32F410xx) || defined(STM32F412xG) ||defined(STM32F446xx)
|
||||
PWR_WakeUpPinCmd(PWR_WakeUp_Pin,ENABLE);
|
||||
#endif
|
||||
|
||||
#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F411xE)
|
||||
PWR_WakeUpPinCmd(ENABLE);
|
||||
#endif
|
||||
|
||||
if(secondsToWakeup == MICO_WAIT_FOREVER)
|
||||
PWR_EnterSTANDBYMode();
|
||||
|
||||
platform_log("Wake up in %ld seconds", secondsToWakeup);
|
||||
|
||||
platform_rtc_get_time(&time);
|
||||
currentSecond = time.hr*3600 + time.min*60 + time.sec;
|
||||
currentSecond += secondsToWakeup;
|
||||
RTC_AlarmStructure.RTC_AlarmTime.RTC_H12 = RTC_HourFormat_24;
|
||||
RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours = currentSecond/3600%24;
|
||||
RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = currentSecond/60%60;
|
||||
RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = currentSecond%60;
|
||||
RTC_AlarmStructure.RTC_AlarmDateWeekDay = 0x31;
|
||||
RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
|
||||
RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay ;
|
||||
|
||||
RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
|
||||
/* Disable the Alarm A */
|
||||
RTC_ITConfig(RTC_IT_ALRA, DISABLE);
|
||||
|
||||
/* Clear RTC Alarm Flag */
|
||||
RTC_ClearFlag(RTC_FLAG_ALRAF);
|
||||
|
||||
RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure);
|
||||
|
||||
/* Enable RTC Alarm A Interrupt: this Interrupt will wake-up the system from
|
||||
STANDBY mode (RTC Alarm IT not enabled in NVIC) */
|
||||
RTC_ITConfig(RTC_IT_ALRA, ENABLE);
|
||||
|
||||
/* Enable the Alarm A */
|
||||
RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
|
||||
|
||||
PWR_EnterSTANDBYMode();
|
||||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
* IRQ Handlers Definition & Mapping
|
||||
******************************************************/
|
||||
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
MICO_RTOS_DEFINE_ISR( RTC_WKUP_irq )
|
||||
{
|
||||
EXTI_ClearITPendingBit( RTC_INTERRUPT_EXTI_LINE );
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_mcu_powersave.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide functions called by MICO to drive stm32f2xx
|
||||
* platform: - e.g. power save, reboot, platform initialize
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include "platform_peripheral.h"
|
||||
#include "platform.h"
|
||||
#include "platform_config.h"
|
||||
#include "platform_logging.h"
|
||||
#include <string.h> // For memcmp
|
||||
#include "crt0.h"
|
||||
#include "platform_init.h"
|
||||
|
||||
/******************************************************
|
||||
* Macros
|
||||
******************************************************/
|
||||
|
||||
#define NUMBER_OF_LSE_TICKS_PER_MILLISECOND(scale_factor) ( 32768 / 1000 / scale_factor )
|
||||
#define CONVERT_FROM_TICKS_TO_MS( n,s ) ( n / NUMBER_OF_LSE_TICKS_PER_MILLISECOND(s) )
|
||||
|
||||
#define ENABLE_INTERRUPTS __asm("CPSIE i") /**< Enable interrupts to start task switching in MICO RTOS. */
|
||||
#define DISABLE_INTERRUPTS __asm("CPSID i") /**< Disable interrupts to stop task switching in MICO RTOS. */
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
#define RTC_INTERRUPT_EXTI_LINE EXTI_Line22
|
||||
#define WUT_COUNTER_MAX 0xFFFF
|
||||
#define CK_SPRE_CLOCK_SOURCE_SELECTED 0xFFFF
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
|
||||
/* Default RTC time. Set to 12:20:30 08/04/2013 Monday */
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
static const platform_rtc_time_t default_rtc_time =
|
||||
{
|
||||
.sec = 30,
|
||||
.min = 20,
|
||||
.hr = 12,
|
||||
.weekday = 1,
|
||||
.date = 8,
|
||||
.month = 4,
|
||||
.year = 13,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
static unsigned long stop_mode_power_down_hook( unsigned long sleep_ms );
|
||||
static OSStatus select_wut_prescaler_calculate_wakeup_time( unsigned long* wakeup_time, unsigned long sleep_ms, unsigned long* scale_factor );
|
||||
#else
|
||||
static unsigned long idle_power_down_hook( unsigned long sleep_ms );
|
||||
#endif
|
||||
//void wake_up_interrupt_notify( void );
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
static bool wake_up_interrupt_triggered = false;
|
||||
static unsigned long rtc_timeout_start_time = 0;
|
||||
static int32_t stm32f2_clock_needed_counter = 0;
|
||||
#endif /* #ifndef MICO_DISABLE_MCU_POWERSAVE */
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
|
||||
OSStatus platform_mcu_powersave_init(void)
|
||||
{
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
EXTI_InitTypeDef EXTI_InitStructure;
|
||||
RTC_InitTypeDef RTC_InitStruct;
|
||||
|
||||
//RTC_DeInit( );
|
||||
|
||||
RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
|
||||
|
||||
/* RTC ticks every second */
|
||||
RTC_InitStruct.RTC_AsynchPrediv = 0x7F;
|
||||
RTC_InitStruct.RTC_SynchPrediv = 0xFF;
|
||||
|
||||
RTC_Init( &RTC_InitStruct );
|
||||
|
||||
/* Enable the PWR clock */
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
|
||||
|
||||
/* RTC clock source configuration ------------------------------------------*/
|
||||
/* Allow access to BKP Domain */
|
||||
PWR_BackupAccessCmd(ENABLE);
|
||||
PWR_BackupRegulatorCmd(ENABLE);
|
||||
|
||||
/* Enable the LSE OSC */
|
||||
RCC_LSEConfig(RCC_LSE_ON);
|
||||
/* Wait till LSE is ready */
|
||||
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
|
||||
{
|
||||
}
|
||||
|
||||
/* Select the RTC Clock Source */
|
||||
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
|
||||
|
||||
/* Enable the RTC Clock */
|
||||
RCC_RTCCLKCmd(ENABLE);
|
||||
|
||||
|
||||
/* RTC configuration -------------------------------------------------------*/
|
||||
/* Wait for RTC APB registers synchronisation */
|
||||
RTC_WaitForSynchro();
|
||||
|
||||
RTC_WakeUpCmd( DISABLE );
|
||||
EXTI_ClearITPendingBit( RTC_INTERRUPT_EXTI_LINE );
|
||||
PWR_ClearFlag(PWR_FLAG_WU);
|
||||
RTC_ClearFlag(RTC_FLAG_WUTF);
|
||||
|
||||
RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div2);
|
||||
|
||||
EXTI_ClearITPendingBit( RTC_INTERRUPT_EXTI_LINE );
|
||||
EXTI_InitStructure.EXTI_Line = RTC_INTERRUPT_EXTI_LINE;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init(&EXTI_InitStructure);
|
||||
|
||||
NVIC_EnableIRQ( RTC_WKUP_IRQn );
|
||||
|
||||
RTC_ITConfig(RTC_IT_WUT, DISABLE);
|
||||
|
||||
/* Prepare Stop-Mode but leave disabled */
|
||||
//PWR_ClearFlag(PWR_FLAG_WU);
|
||||
PWR->CR |= PWR_CR_LPDS;
|
||||
PWR->CR &= (unsigned long)(~(PWR_CR_PDDS));
|
||||
SCB->SCR |= ((unsigned long)SCB_SCR_SLEEPDEEP_Msk);
|
||||
|
||||
#ifdef USE_RTC_BKP
|
||||
if (RTC_ReadBackupRegister(RTC_BKP_DR0) != USE_RTC_BKP) {
|
||||
/* set it to 12:20:30 08/04/2013 monday */
|
||||
platform_rtc_set_time(&default_rtc_time);
|
||||
RTC_WriteBackupRegister(RTC_BKP_DR0, USE_RTC_BKP);
|
||||
}
|
||||
#else
|
||||
//#ifdef RTC_ENABLED
|
||||
/* application must have mico_application_default_time structure declared somewhere, otherwise it wont compile */
|
||||
/* write default application time inside rtc */
|
||||
platform_rtc_set_time( &default_rtc_time );
|
||||
//#endif /* RTC_ENABLED */
|
||||
#endif
|
||||
return kNoErr;
|
||||
#else
|
||||
return kUnsupportedErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
OSStatus platform_mcu_powersave_disable( void )
|
||||
{
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
DISABLE_INTERRUPTS;
|
||||
if ( stm32f2_clock_needed_counter <= 0 )
|
||||
{
|
||||
SCB->SCR &= (~((unsigned long)SCB_SCR_SLEEPDEEP_Msk));
|
||||
stm32f2_clock_needed_counter = 0;
|
||||
}
|
||||
stm32f2_clock_needed_counter++;
|
||||
ENABLE_INTERRUPTS;
|
||||
|
||||
return kNoErr;
|
||||
#else
|
||||
return kUnsupportedErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
OSStatus platform_mcu_powersave_enable( void )
|
||||
{
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
DISABLE_INTERRUPTS;
|
||||
stm32f2_clock_needed_counter--;
|
||||
if ( stm32f2_clock_needed_counter <= 0 )
|
||||
{
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
stm32f2_clock_needed_counter = 0;
|
||||
}
|
||||
ENABLE_INTERRUPTS;
|
||||
|
||||
return kNoErr;
|
||||
#else
|
||||
return kUnsupportedErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void platform_mcu_powersave_exit_notify( void )
|
||||
{
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
UNUSED_PARAMETER( wake_up_interrupt_triggered );
|
||||
wake_up_interrupt_triggered = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
static OSStatus select_wut_prescaler_calculate_wakeup_time( unsigned long* wakeup_time, unsigned long sleep_ms, unsigned long* scale_factor )
|
||||
{
|
||||
unsigned long temp;
|
||||
bool scale_factor_is_found = false;
|
||||
int i = 0;
|
||||
|
||||
static unsigned long int available_wut_prescalers[] =
|
||||
{
|
||||
RTC_WakeUpClock_RTCCLK_Div2,
|
||||
RTC_WakeUpClock_RTCCLK_Div4,
|
||||
RTC_WakeUpClock_RTCCLK_Div8,
|
||||
RTC_WakeUpClock_RTCCLK_Div16
|
||||
};
|
||||
static unsigned long scale_factor_values[] = { 2, 4, 8, 16 };
|
||||
|
||||
if ( sleep_ms == 0xFFFFFFFF )
|
||||
{
|
||||
/* wake up in a 100ms, since currently there may be no tasks to run, but after a few milliseconds */
|
||||
/* some of them can get unblocked( for example a task is blocked on mutex with unspecified ) */
|
||||
*scale_factor = 2;
|
||||
RTC_WakeUpClockConfig( RTC_WakeUpClock_RTCCLK_Div2 );
|
||||
*wakeup_time = NUMBER_OF_LSE_TICKS_PER_MILLISECOND( scale_factor_values[0] ) * 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
temp = NUMBER_OF_LSE_TICKS_PER_MILLISECOND( scale_factor_values[i] ) * sleep_ms;
|
||||
if ( temp < WUT_COUNTER_MAX )
|
||||
{
|
||||
scale_factor_is_found = true;
|
||||
*wakeup_time = temp;
|
||||
*scale_factor = scale_factor_values[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( scale_factor_is_found )
|
||||
{
|
||||
/* set new prescaler for wakeup timer */
|
||||
RTC_WakeUpClockConfig( available_wut_prescalers[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* scale factor can not be picked up for delays more that 32 seconds when RTCLK is selected as a clock source for the wakeup timer
|
||||
* for delays more than 32 seconds change from RTCCLK to 1Hz ck_spre clock source( used to update calendar registers ) */
|
||||
RTC_WakeUpClockConfig( RTC_WakeUpClock_CK_SPRE_16bits );
|
||||
|
||||
/* with 1Hz ck_spre clock source the resolution changes to seconds */
|
||||
*wakeup_time = ( sleep_ms / 1000 ) + 1;
|
||||
*scale_factor = CK_SPRE_CLOCK_SOURCE_SELECTED;
|
||||
|
||||
return kGeneralErr;
|
||||
}
|
||||
}
|
||||
|
||||
return kNoErr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************
|
||||
* RTOS Powersave Hooks
|
||||
******************************************************/
|
||||
|
||||
void platform_idle_hook( void )
|
||||
{
|
||||
__asm("wfi");
|
||||
}
|
||||
|
||||
uint32_t platform_power_down_hook( uint32_t sleep_ms )
|
||||
{
|
||||
#ifdef MICO_DISABLE_MCU_POWERSAVE
|
||||
/* If MCU powersave feature is disabled, enter idle mode when powerdown hook is called by the RTOS */
|
||||
return idle_power_down_hook( sleep_ms );
|
||||
|
||||
#else
|
||||
/* If MCU powersave feature is enabled, enter STOP mode when powerdown hook is called by the RTOS */
|
||||
return stop_mode_power_down_hook( sleep_ms );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MICO_DISABLE_MCU_POWERSAVE
|
||||
/* MCU Powersave is disabled */
|
||||
static unsigned long idle_power_down_hook( unsigned long sleep_ms )
|
||||
{
|
||||
UNUSED_PARAMETER( sleep_ms );
|
||||
ENABLE_INTERRUPTS;
|
||||
__asm("wfi");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static unsigned long stop_mode_power_down_hook( unsigned long sleep_ms )
|
||||
{
|
||||
unsigned long retval;
|
||||
unsigned long wut_ticks_passed;
|
||||
unsigned long scale_factor = 0;
|
||||
UNUSED_PARAMETER(sleep_ms);
|
||||
UNUSED_PARAMETER(rtc_timeout_start_time);
|
||||
UNUSED_PARAMETER(scale_factor);
|
||||
|
||||
if ( ( ( SCB->SCR & (unsigned long)SCB_SCR_SLEEPDEEP_Msk) != 0) && sleep_ms < 5 ){
|
||||
SCB->SCR &= (~((unsigned long)SCB_SCR_SLEEPDEEP_Msk));
|
||||
__asm("wfi");
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
/* Note: We return 0 ticks passed because system tick is still going when wfi instruction gets executed */
|
||||
ENABLE_INTERRUPTS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ( ( SCB->SCR & (unsigned long)SCB_SCR_SLEEPDEEP_Msk) ) != 0 )
|
||||
{
|
||||
/* pick up the appropriate prescaler for a requested delay */
|
||||
select_wut_prescaler_calculate_wakeup_time(&rtc_timeout_start_time, sleep_ms, &scale_factor );
|
||||
|
||||
DISABLE_INTERRUPTS;
|
||||
|
||||
SysTick->CTRL &= (~(SysTick_CTRL_TICKINT_Msk|SysTick_CTRL_ENABLE_Msk)); /* systick IRQ off */
|
||||
RTC_ITConfig(RTC_IT_WUT, ENABLE);
|
||||
|
||||
EXTI_ClearITPendingBit( RTC_INTERRUPT_EXTI_LINE );
|
||||
PWR_ClearFlag(PWR_FLAG_WU);
|
||||
RTC_ClearFlag(RTC_FLAG_WUTF);
|
||||
|
||||
RTC_SetWakeUpCounter( rtc_timeout_start_time );
|
||||
RTC_WakeUpCmd( ENABLE );
|
||||
platform_rtc_enter_powersave();
|
||||
|
||||
DBGMCU->CR |= 0x03; /* Enable debug in stop mode */
|
||||
|
||||
/* This code will be running with BASEPRI register value set to 0, the main intention behind that is that */
|
||||
/* all interrupts must be allowed to wake the CPU from the power-down mode */
|
||||
/* the PRIMASK is set to 1( see DISABLE_INTERRUPTS), thus we disable all interrupts before entering the power-down mode */
|
||||
/* This may sound contradictory, however according to the ARM CM3 documentation power-management unit */
|
||||
/* takes into account only the contents of the BASEPRI register and it is an external from the CPU core unit */
|
||||
/* PRIMASK register value doesn't affect its operation. */
|
||||
/* So, if the interrupt has been triggered just before the wfi instruction */
|
||||
/* it remains pending and wfi instruction will be treated as a nop */
|
||||
__asm("wfi");
|
||||
|
||||
/* After CPU exits powerdown mode, the processer will not execute the interrupt handler(PRIMASK is set to 1) */
|
||||
/* Disable rtc for now */
|
||||
RTC_WakeUpCmd( DISABLE );
|
||||
RTC_ITConfig(RTC_IT_WUT, DISABLE);
|
||||
|
||||
/* Initialise the clocks again */
|
||||
init_clocks( );
|
||||
|
||||
/* Enable CPU ticks */
|
||||
SysTick->CTRL |= (SysTick_CTRL_TICKINT_Msk|SysTick_CTRL_ENABLE_Msk);
|
||||
|
||||
/* Get the time of how long the sleep lasted */
|
||||
wut_ticks_passed = rtc_timeout_start_time - RTC_GetWakeUpCounter();
|
||||
UNUSED_VARIABLE(wut_ticks_passed);
|
||||
platform_rtc_exit_powersave( sleep_ms, (uint32_t *)&retval );
|
||||
/* as soon as interrupts are enabled, we will go and execute the interrupt handler */
|
||||
/* which triggered a wake up event */
|
||||
ENABLE_INTERRUPTS;
|
||||
wake_up_interrupt_triggered = false;
|
||||
return retval;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNUSED_PARAMETER(wut_ticks_passed);
|
||||
ENABLE_INTERRUPTS;
|
||||
__asm("wfi");
|
||||
|
||||
/* Note: We return 0 ticks passed because system tick is still going when wfi instruction gets executed */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* MICO_DISABLE_MCU_POWERSAVE */
|
||||
|
||||
|
||||
void platform_mcu_enter_standby(uint32_t secondsToWakeup)
|
||||
{
|
||||
platform_rtc_time_t time;
|
||||
uint32_t currentSecond;
|
||||
RTC_AlarmTypeDef RTC_AlarmStructure;
|
||||
|
||||
#if defined(STM32F410xx) || defined(STM32F412xG) ||defined(STM32F446xx)
|
||||
PWR_WakeUpPinCmd(PWR_WakeUp_Pin,ENABLE);
|
||||
#endif
|
||||
|
||||
#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F411xE)
|
||||
PWR_WakeUpPinCmd(ENABLE);
|
||||
#endif
|
||||
|
||||
if(secondsToWakeup == MICO_WAIT_FOREVER)
|
||||
PWR_EnterSTANDBYMode();
|
||||
|
||||
platform_log("Wake up in %ld seconds", secondsToWakeup);
|
||||
|
||||
platform_rtc_get_time(&time);
|
||||
currentSecond = time.hr*3600 + time.min*60 + time.sec;
|
||||
currentSecond += secondsToWakeup;
|
||||
RTC_AlarmStructure.RTC_AlarmTime.RTC_H12 = RTC_HourFormat_24;
|
||||
RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours = currentSecond/3600%24;
|
||||
RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = currentSecond/60%60;
|
||||
RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = currentSecond%60;
|
||||
RTC_AlarmStructure.RTC_AlarmDateWeekDay = 0x31;
|
||||
RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
|
||||
RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay ;
|
||||
|
||||
RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
|
||||
/* Disable the Alarm A */
|
||||
RTC_ITConfig(RTC_IT_ALRA, DISABLE);
|
||||
|
||||
/* Clear RTC Alarm Flag */
|
||||
RTC_ClearFlag(RTC_FLAG_ALRAF);
|
||||
|
||||
RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure);
|
||||
|
||||
/* Enable RTC Alarm A Interrupt: this Interrupt will wake-up the system from
|
||||
STANDBY mode (RTC Alarm IT not enabled in NVIC) */
|
||||
RTC_ITConfig(RTC_IT_ALRA, ENABLE);
|
||||
|
||||
/* Enable the Alarm A */
|
||||
RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
|
||||
|
||||
PWR_EnterSTANDBYMode();
|
||||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
* IRQ Handlers Definition & Mapping
|
||||
******************************************************/
|
||||
|
||||
#ifndef MICO_DISABLE_MCU_POWERSAVE
|
||||
MICO_RTOS_DEFINE_ISR( RTC_WKUP_irq )
|
||||
{
|
||||
EXTI_ClearITPendingBit( RTC_INTERRUPT_EXTI_LINE );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,173 +1,173 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_pwm.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide PWM driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "platform_peripheral.h"
|
||||
#include "debug.h"
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
|
||||
OSStatus platform_pwm_init( const platform_pwm_t* pwm, uint32_t frequency, float duty_cycle )
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef tim_time_base_structure;
|
||||
TIM_OCInitTypeDef tim_oc_init_structure;
|
||||
RCC_ClocksTypeDef rcc_clock_frequencies;
|
||||
uint16_t period = 0;
|
||||
float adjusted_duty_cycle = ( ( duty_cycle > 100.0f ) ? 100.0f : duty_cycle );
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
require_action_quiet( pwm != NULL, exit, err = kParamErr);
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
RCC_GetClocksFreq( &rcc_clock_frequencies );
|
||||
|
||||
if ( pwm->tim == TIM1 || pwm->tim == TIM8 || pwm->tim == TIM9 || pwm->tim == TIM10 || pwm->tim == TIM11 )
|
||||
{
|
||||
RCC_APB2PeriphClockCmd( pwm->tim_peripheral_clock, ENABLE );
|
||||
if( rcc_clock_frequencies.PCLK2_Frequency == rcc_clock_frequencies.HCLK_Frequency )
|
||||
period = (uint16_t)( rcc_clock_frequencies.PCLK2_Frequency / 20 / frequency - 1 ); /* Auto-reload value counts from 0; hence the minus 1 */
|
||||
else
|
||||
period = (uint16_t)( rcc_clock_frequencies.PCLK2_Frequency * 2 / 20 / frequency - 1 ); /* Auto-reload value counts from 0; hence the minus 1 */
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC_APB1PeriphClockCmd( pwm->tim_peripheral_clock, ENABLE );
|
||||
if( rcc_clock_frequencies.PCLK1_Frequency == rcc_clock_frequencies.HCLK_Frequency )
|
||||
period = (uint16_t)( rcc_clock_frequencies.PCLK1_Frequency / 20 / frequency - 1 ); /* Auto-reload value counts from 0; hence the minus 1 */
|
||||
else
|
||||
period = (uint16_t)( rcc_clock_frequencies.PCLK1_Frequency * 2 / 20 / frequency - 1 ); /* Auto-reload value counts from 0; hence the minus 1 */
|
||||
}
|
||||
|
||||
/* Set alternate function */
|
||||
platform_gpio_set_alternate_function( pwm->pin->port, pwm->pin->pin_number, GPIO_OType_PP, GPIO_PuPd_UP, pwm->gpio_af );
|
||||
|
||||
/* Time base configuration */
|
||||
tim_time_base_structure.TIM_Period = (uint32_t) period;
|
||||
tim_time_base_structure.TIM_Prescaler = (uint16_t) 19; /* Divide clock by 19 + 1 to enable a count of high cycle + low cycle = 1 PWM cycle */
|
||||
tim_time_base_structure.TIM_ClockDivision = 0;
|
||||
tim_time_base_structure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
tim_time_base_structure.TIM_RepetitionCounter = 0;
|
||||
TIM_TimeBaseInit( pwm->tim, &tim_time_base_structure );
|
||||
|
||||
/* PWM1 Mode configuration */
|
||||
tim_oc_init_structure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
tim_oc_init_structure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
tim_oc_init_structure.TIM_OutputNState = TIM_OutputNState_Enable;
|
||||
tim_oc_init_structure.TIM_Pulse = (uint16_t) ( adjusted_duty_cycle * (float) period / 100.0f );
|
||||
tim_oc_init_structure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||
tim_oc_init_structure.TIM_OCNPolarity = TIM_OCNPolarity_High;
|
||||
tim_oc_init_structure.TIM_OCIdleState = TIM_OCIdleState_Reset;
|
||||
tim_oc_init_structure.TIM_OCNIdleState = TIM_OCIdleState_Set;
|
||||
|
||||
switch ( pwm->channel )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
TIM_OC1Init( pwm->tim, &tim_oc_init_structure );
|
||||
TIM_OC1PreloadConfig( pwm->tim, TIM_OCPreload_Enable );
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
TIM_OC2Init( pwm->tim, &tim_oc_init_structure );
|
||||
TIM_OC2PreloadConfig( pwm->tim, TIM_OCPreload_Enable );
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
TIM_OC3Init( pwm->tim, &tim_oc_init_structure );
|
||||
TIM_OC3PreloadConfig( pwm->tim, TIM_OCPreload_Enable );
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
TIM_OC4Init( pwm->tim, &tim_oc_init_structure );
|
||||
TIM_OC4PreloadConfig( pwm->tim, TIM_OCPreload_Enable );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_pwm_start( const platform_pwm_t* pwm )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( pwm != NULL, exit, err = kParamErr);
|
||||
|
||||
TIM_Cmd( pwm->tim, ENABLE );
|
||||
TIM_CtrlPWMOutputs( pwm->tim, ENABLE );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_pwm_stop( const platform_pwm_t* pwm )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( pwm != NULL, exit, err = kParamErr);
|
||||
|
||||
TIM_CtrlPWMOutputs( pwm->tim, DISABLE );
|
||||
TIM_Cmd( pwm->tim, DISABLE );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_pwm.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide PWM driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "platform_peripheral.h"
|
||||
#include "debug.h"
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
|
||||
OSStatus platform_pwm_init( const platform_pwm_t* pwm, uint32_t frequency, float duty_cycle )
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef tim_time_base_structure;
|
||||
TIM_OCInitTypeDef tim_oc_init_structure;
|
||||
RCC_ClocksTypeDef rcc_clock_frequencies;
|
||||
uint16_t period = 0;
|
||||
float adjusted_duty_cycle = ( ( duty_cycle > 100.0f ) ? 100.0f : duty_cycle );
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
require_action_quiet( pwm != NULL, exit, err = kParamErr);
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
RCC_GetClocksFreq( &rcc_clock_frequencies );
|
||||
|
||||
if ( pwm->tim == TIM1 || pwm->tim == TIM8 || pwm->tim == TIM9 || pwm->tim == TIM10 || pwm->tim == TIM11 )
|
||||
{
|
||||
RCC_APB2PeriphClockCmd( pwm->tim_peripheral_clock, ENABLE );
|
||||
if( rcc_clock_frequencies.PCLK2_Frequency == rcc_clock_frequencies.HCLK_Frequency )
|
||||
period = (uint16_t)( rcc_clock_frequencies.PCLK2_Frequency / 20 / frequency - 1 ); /* Auto-reload value counts from 0; hence the minus 1 */
|
||||
else
|
||||
period = (uint16_t)( rcc_clock_frequencies.PCLK2_Frequency * 2 / 20 / frequency - 1 ); /* Auto-reload value counts from 0; hence the minus 1 */
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC_APB1PeriphClockCmd( pwm->tim_peripheral_clock, ENABLE );
|
||||
if( rcc_clock_frequencies.PCLK1_Frequency == rcc_clock_frequencies.HCLK_Frequency )
|
||||
period = (uint16_t)( rcc_clock_frequencies.PCLK1_Frequency / 20 / frequency - 1 ); /* Auto-reload value counts from 0; hence the minus 1 */
|
||||
else
|
||||
period = (uint16_t)( rcc_clock_frequencies.PCLK1_Frequency * 2 / 20 / frequency - 1 ); /* Auto-reload value counts from 0; hence the minus 1 */
|
||||
}
|
||||
|
||||
/* Set alternate function */
|
||||
platform_gpio_set_alternate_function( pwm->pin->port, pwm->pin->pin_number, GPIO_OType_PP, GPIO_PuPd_UP, pwm->gpio_af );
|
||||
|
||||
/* Time base configuration */
|
||||
tim_time_base_structure.TIM_Period = (uint32_t) period;
|
||||
tim_time_base_structure.TIM_Prescaler = (uint16_t) 19; /* Divide clock by 19 + 1 to enable a count of high cycle + low cycle = 1 PWM cycle */
|
||||
tim_time_base_structure.TIM_ClockDivision = 0;
|
||||
tim_time_base_structure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
tim_time_base_structure.TIM_RepetitionCounter = 0;
|
||||
TIM_TimeBaseInit( pwm->tim, &tim_time_base_structure );
|
||||
|
||||
/* PWM1 Mode configuration */
|
||||
tim_oc_init_structure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
tim_oc_init_structure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
tim_oc_init_structure.TIM_OutputNState = TIM_OutputNState_Enable;
|
||||
tim_oc_init_structure.TIM_Pulse = (uint16_t) ( adjusted_duty_cycle * (float) period / 100.0f );
|
||||
tim_oc_init_structure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||
tim_oc_init_structure.TIM_OCNPolarity = TIM_OCNPolarity_High;
|
||||
tim_oc_init_structure.TIM_OCIdleState = TIM_OCIdleState_Reset;
|
||||
tim_oc_init_structure.TIM_OCNIdleState = TIM_OCIdleState_Set;
|
||||
|
||||
switch ( pwm->channel )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
TIM_OC1Init( pwm->tim, &tim_oc_init_structure );
|
||||
TIM_OC1PreloadConfig( pwm->tim, TIM_OCPreload_Enable );
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
TIM_OC2Init( pwm->tim, &tim_oc_init_structure );
|
||||
TIM_OC2PreloadConfig( pwm->tim, TIM_OCPreload_Enable );
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
TIM_OC3Init( pwm->tim, &tim_oc_init_structure );
|
||||
TIM_OC3PreloadConfig( pwm->tim, TIM_OCPreload_Enable );
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
TIM_OC4Init( pwm->tim, &tim_oc_init_structure );
|
||||
TIM_OC4PreloadConfig( pwm->tim, TIM_OCPreload_Enable );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_pwm_start( const platform_pwm_t* pwm )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( pwm != NULL, exit, err = kParamErr);
|
||||
|
||||
TIM_Cmd( pwm->tim, ENABLE );
|
||||
TIM_CtrlPWMOutputs( pwm->tim, ENABLE );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus platform_pwm_stop( const platform_pwm_t* pwm )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( pwm != NULL, exit, err = kParamErr);
|
||||
|
||||
TIM_CtrlPWMOutputs( pwm->tim, DISABLE );
|
||||
TIM_Cmd( pwm->tim, DISABLE );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,74 +1,74 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_rng.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide RNG driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform_peripheral.h"
|
||||
#include "platform.h"
|
||||
|
||||
/******************************************************
|
||||
* Macros
|
||||
******************************************************/
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Variables
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
|
||||
OSStatus platform_random_number_read( void *inBuffer, int inByteCount )
|
||||
{
|
||||
// PLATFORM_TO_DO
|
||||
// PLATFORM_TO_DO
|
||||
int idx;
|
||||
uint32_t *pWord = inBuffer;
|
||||
uint32_t tempRDM;
|
||||
uint8_t *pByte = NULL;
|
||||
int inWordCount;
|
||||
int remainByteCount;
|
||||
|
||||
inWordCount = inByteCount/4;
|
||||
remainByteCount = inByteCount%4;
|
||||
pByte = (uint8_t *)pWord+inWordCount*4;
|
||||
|
||||
for(idx = 0; idx<inWordCount; idx++, pWord++){
|
||||
srand(mico_rtos_get_time());
|
||||
*pWord = rand();
|
||||
}
|
||||
|
||||
if(remainByteCount){
|
||||
srand(mico_rtos_get_time());
|
||||
tempRDM = rand();
|
||||
memcpy(pByte, &tempRDM, (size_t)remainByteCount);
|
||||
}
|
||||
|
||||
return kNoErr;
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_rng.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide RNG driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform_peripheral.h"
|
||||
#include "platform.h"
|
||||
|
||||
/******************************************************
|
||||
* Macros
|
||||
******************************************************/
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Variables
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
|
||||
OSStatus platform_random_number_read( void *inBuffer, int inByteCount )
|
||||
{
|
||||
// PLATFORM_TO_DO
|
||||
// PLATFORM_TO_DO
|
||||
int idx;
|
||||
uint32_t *pWord = inBuffer;
|
||||
uint32_t tempRDM;
|
||||
uint8_t *pByte = NULL;
|
||||
int inWordCount;
|
||||
int remainByteCount;
|
||||
|
||||
inWordCount = inByteCount/4;
|
||||
remainByteCount = inByteCount%4;
|
||||
pByte = (uint8_t *)pWord+inWordCount*4;
|
||||
|
||||
for(idx = 0; idx<inWordCount; idx++, pWord++){
|
||||
srand(mico_rtos_get_time());
|
||||
*pWord = rand();
|
||||
}
|
||||
|
||||
if(remainByteCount){
|
||||
srand(mico_rtos_get_time());
|
||||
tempRDM = rand();
|
||||
memcpy(pByte, &tempRDM, (size_t)remainByteCount);
|
||||
}
|
||||
|
||||
return kNoErr;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,475 +1,475 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_spi.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide SPI driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "platform_config.h"
|
||||
#include "platform_peripheral.h"
|
||||
#include "debug.h"
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
#define MAX_NUM_SPI_PRESCALERS (8)
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t factor;
|
||||
uint16_t prescaler_value;
|
||||
} spi_baudrate_division_mapping_t;
|
||||
|
||||
/******************************************************
|
||||
* Static Function Declarations
|
||||
******************************************************/
|
||||
|
||||
static OSStatus calculate_prescaler( uint32_t speed, uint16_t* prescaler );
|
||||
static uint16_t spi_transfer ( const platform_spi_t* spi, uint16_t data );
|
||||
static OSStatus spi_dma_transfer ( const platform_spi_t* spi, const platform_spi_config_t* config );
|
||||
static void spi_dma_config ( const platform_spi_t* spi, const platform_spi_message_segment_t* message );
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
static const spi_baudrate_division_mapping_t spi_baudrate_prescalers[MAX_NUM_SPI_PRESCALERS] =
|
||||
{
|
||||
{ 2, SPI_BaudRatePrescaler_2 },
|
||||
{ 4, SPI_BaudRatePrescaler_4 },
|
||||
{ 8, SPI_BaudRatePrescaler_8 },
|
||||
{ 16, SPI_BaudRatePrescaler_16 },
|
||||
{ 32, SPI_BaudRatePrescaler_32 },
|
||||
{ 64, SPI_BaudRatePrescaler_64 },
|
||||
{ 128, SPI_BaudRatePrescaler_128 },
|
||||
{ 256, SPI_BaudRatePrescaler_256 },
|
||||
};
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
uint8_t platform_spi_get_port_number( platform_spi_port_t* spi )
|
||||
{
|
||||
if ( spi == SPI1 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if ( spi == SPI2 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if ( spi == SPI3 )
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_dma_irq_status( DMA_Stream_TypeDef* stream )
|
||||
{
|
||||
if ( stream <= DMA1_Stream3 )
|
||||
{
|
||||
return DMA1->LISR;
|
||||
}
|
||||
else if ( stream <= DMA1_Stream7 )
|
||||
{
|
||||
return DMA1->HISR;
|
||||
}
|
||||
else if ( stream <= DMA2_Stream3 )
|
||||
{
|
||||
return DMA2->LISR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DMA2->HISR;
|
||||
}
|
||||
}
|
||||
|
||||
OSStatus platform_spi_init( platform_spi_driver_t* driver, const platform_spi_t* peripheral, const platform_spi_config_t* config )
|
||||
{
|
||||
SPI_InitTypeDef spi_init;
|
||||
OSStatus err;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( ( driver != NULL ) && ( peripheral != NULL ) && ( config != NULL ), exit, err = kParamErr);
|
||||
|
||||
/* Calculate prescaler */
|
||||
err = calculate_prescaler( config->speed, &spi_init.SPI_BaudRatePrescaler );
|
||||
require_noerr(err, exit);
|
||||
|
||||
/* Configure data-width */
|
||||
if ( config->bits == 8 )
|
||||
{
|
||||
spi_init.SPI_DataSize = SPI_DataSize_8b;
|
||||
}
|
||||
else if ( config->bits == 16 )
|
||||
{
|
||||
require_action( !(config->mode & SPI_USE_DMA), exit, err = kUnsupportedErr);
|
||||
spi_init.SPI_DataSize = SPI_DataSize_16b;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = kUnsupportedErr;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Configure MSB or LSB */
|
||||
if ( config->mode & SPI_MSB_FIRST )
|
||||
{
|
||||
spi_init.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||
}
|
||||
else
|
||||
{
|
||||
spi_init.SPI_FirstBit = SPI_FirstBit_LSB;
|
||||
}
|
||||
|
||||
/* Configure mode CPHA and CPOL */
|
||||
if ( config->mode & SPI_CLOCK_IDLE_HIGH )
|
||||
{
|
||||
spi_init.SPI_CPOL = SPI_CPOL_High;
|
||||
}
|
||||
else
|
||||
{
|
||||
spi_init.SPI_CPOL = SPI_CPOL_Low;
|
||||
}
|
||||
|
||||
if ( config->mode & SPI_CLOCK_RISING_EDGE )
|
||||
{
|
||||
spi_init.SPI_CPHA = ( config->mode & SPI_CLOCK_IDLE_HIGH ) ? SPI_CPHA_2Edge : SPI_CPHA_1Edge;
|
||||
}
|
||||
else
|
||||
{
|
||||
spi_init.SPI_CPHA = ( config->mode & SPI_CLOCK_IDLE_HIGH ) ? SPI_CPHA_1Edge : SPI_CPHA_2Edge;
|
||||
}
|
||||
|
||||
driver->peripheral = (platform_spi_t *)peripheral;
|
||||
|
||||
/* Init SPI GPIOs */
|
||||
platform_gpio_set_alternate_function( peripheral->pin_clock->port, peripheral->pin_clock->pin_number, GPIO_OType_PP, GPIO_PuPd_NOPULL, peripheral->gpio_af );
|
||||
platform_gpio_set_alternate_function( peripheral->pin_mosi->port, peripheral->pin_mosi->pin_number, GPIO_OType_PP, GPIO_PuPd_NOPULL, peripheral->gpio_af );
|
||||
platform_gpio_set_alternate_function( peripheral->pin_miso->port, peripheral->pin_miso->pin_number, GPIO_OType_PP, GPIO_PuPd_UP, peripheral->gpio_af );
|
||||
|
||||
/* Init the chip select GPIO */
|
||||
platform_gpio_init( config->chip_select, OUTPUT_PUSH_PULL );
|
||||
platform_gpio_output_high( config->chip_select );
|
||||
|
||||
|
||||
/* Enable SPI peripheral clock */
|
||||
(peripheral->peripheral_clock_func)( peripheral->peripheral_clock_reg, ENABLE );
|
||||
(peripheral->peripheral_clock_func)( peripheral->peripheral_clock_reg, ENABLE );
|
||||
|
||||
SPI_I2S_DeInit( peripheral->port );
|
||||
|
||||
spi_init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||
spi_init.SPI_Mode = SPI_Mode_Master;
|
||||
spi_init.SPI_NSS = SPI_NSS_Soft;
|
||||
spi_init.SPI_CRCPolynomial = 0x7; /* reset value */
|
||||
SPI_CalculateCRC( peripheral->port, DISABLE );
|
||||
|
||||
/* Init and enable SPI */
|
||||
SPI_Init( peripheral->port, &spi_init );
|
||||
|
||||
SPI_I2S_DMACmd( peripheral->port, SPI_I2S_DMAReq_Rx, DISABLE );
|
||||
SPI_I2S_DMACmd( peripheral->port, SPI_I2S_DMAReq_Tx, DISABLE );
|
||||
|
||||
SPI_Cmd ( peripheral->port, ENABLE );
|
||||
|
||||
if ( config->mode & SPI_USE_DMA ){
|
||||
DMA_DeInit( peripheral->rx_dma.stream );
|
||||
DMA_DeInit( peripheral->tx_dma.stream );
|
||||
|
||||
if ( peripheral->tx_dma.controller == DMA1 )
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1Periph_DMA1;
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1Periph_DMA2;
|
||||
}
|
||||
|
||||
if ( peripheral->rx_dma.controller == DMA1 )
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1Periph_DMA1;
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1Periph_DMA2;
|
||||
}
|
||||
SPI_I2S_DMACmd( peripheral->port, SPI_I2S_DMAReq_Rx, ENABLE );
|
||||
SPI_I2S_DMACmd( peripheral->port, SPI_I2S_DMAReq_Tx, ENABLE );
|
||||
}
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
OSStatus platform_spi_deinit( platform_spi_driver_t* driver )
|
||||
{
|
||||
UNUSED_PARAMETER( driver );
|
||||
/* TODO: unimplemented */
|
||||
return kUnsupportedErr;
|
||||
}
|
||||
|
||||
|
||||
OSStatus platform_spi_transfer( platform_spi_driver_t* driver, const platform_spi_config_t* config, const platform_spi_message_segment_t* segments, uint16_t number_of_segments )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
uint32_t count = 0;
|
||||
uint16_t i;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( ( driver != NULL ) && ( config != NULL ) && ( segments != NULL ) && ( number_of_segments != 0 ), exit, err = kParamErr);
|
||||
|
||||
/* Activate chip select */
|
||||
platform_gpio_output_low( config->chip_select );
|
||||
|
||||
for ( i = 0; i < number_of_segments; i++ )
|
||||
{
|
||||
/* Check if we are using DMA */
|
||||
if ( config->mode & SPI_USE_DMA )
|
||||
{
|
||||
if( segments[ i ].length != 0){
|
||||
//platform_log( "length: %d, i:%d", segments[ i ].length, i );
|
||||
|
||||
spi_dma_config( driver->peripheral, &segments[ i ] );
|
||||
|
||||
err = spi_dma_transfer( driver->peripheral, config );
|
||||
require_noerr(err, cleanup_transfer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
count = segments[i].length;
|
||||
|
||||
/* in interrupt-less mode */
|
||||
if ( config->bits == 8 )
|
||||
{
|
||||
const uint8_t* send_ptr = ( const uint8_t* )segments[i].tx_buffer;
|
||||
uint8_t* rcv_ptr = ( uint8_t* )segments[i].rx_buffer;
|
||||
|
||||
while ( count-- )
|
||||
{
|
||||
uint16_t data = 0xFF;
|
||||
|
||||
if ( send_ptr != NULL )
|
||||
{
|
||||
data = *send_ptr++;
|
||||
}
|
||||
|
||||
data = spi_transfer( driver->peripheral, data );
|
||||
|
||||
if ( rcv_ptr != NULL )
|
||||
{
|
||||
*rcv_ptr++ = (uint8_t)data;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( config->bits == 16 )
|
||||
{
|
||||
const uint16_t* send_ptr = (const uint16_t *) segments[i].tx_buffer;
|
||||
uint16_t* rcv_ptr = (uint16_t *) segments[i].rx_buffer;
|
||||
|
||||
/* Check that the message length is a multiple of 2 */
|
||||
|
||||
require_action_quiet( ( count % 2 ) == 0, cleanup_transfer, err = kSizeErr);
|
||||
|
||||
/* Transmit/receive data stream, 16-bit at time */
|
||||
while ( count != 0 )
|
||||
{
|
||||
uint16_t data = 0xFFFF;
|
||||
|
||||
if ( send_ptr != NULL )
|
||||
{
|
||||
data = *send_ptr++;
|
||||
}
|
||||
|
||||
data = spi_transfer( driver->peripheral, data );
|
||||
|
||||
if ( rcv_ptr != NULL )
|
||||
{
|
||||
*rcv_ptr++ = data;
|
||||
}
|
||||
|
||||
count -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup_transfer:
|
||||
/* Deassert chip select */
|
||||
platform_gpio_output_high( config->chip_select );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable( );
|
||||
return err;
|
||||
}
|
||||
|
||||
static uint16_t spi_transfer( const platform_spi_t* spi, uint16_t data )
|
||||
{
|
||||
/* Wait until the transmit buffer is empty */
|
||||
while ( SPI_I2S_GetFlagStatus( spi->port, SPI_I2S_FLAG_TXE ) == RESET )
|
||||
{
|
||||
}
|
||||
|
||||
/* Send the byte */
|
||||
SPI_I2S_SendData( spi->port, data );
|
||||
|
||||
/* Wait until a data is received */
|
||||
while ( SPI_I2S_GetFlagStatus( spi->port, SPI_I2S_FLAG_RXNE ) == RESET )
|
||||
{
|
||||
}
|
||||
|
||||
/* Get the received data */
|
||||
return SPI_I2S_ReceiveData( spi->port );
|
||||
}
|
||||
|
||||
|
||||
static OSStatus calculate_prescaler( uint32_t speed, uint16_t* prescaler )
|
||||
{
|
||||
uint8_t i;
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
require_action_quiet( prescaler != NULL, exit, err = kParamErr);
|
||||
|
||||
for( i = 0 ; i < MAX_NUM_SPI_PRESCALERS ; i++ )
|
||||
{
|
||||
if( ( 100000000 / spi_baudrate_prescalers[i].factor ) <= speed )
|
||||
{
|
||||
*prescaler = spi_baudrate_prescalers[i].prescaler_value;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static OSStatus spi_dma_transfer( const platform_spi_t* spi, const platform_spi_config_t* config )
|
||||
{
|
||||
/* Enable dma channels that have just been configured */
|
||||
DMA_Cmd( spi->rx_dma.stream, ENABLE );
|
||||
DMA_Cmd( spi->tx_dma.stream, ENABLE );
|
||||
|
||||
/* Wait for DMA to complete */
|
||||
/* TODO: This should wait on a semaphore that is triggered from an IRQ */
|
||||
while ( ( get_dma_irq_status( spi->rx_dma.stream ) & spi->rx_dma.complete_flags ) == 0 )
|
||||
{
|
||||
}
|
||||
|
||||
return kNoErr;
|
||||
}
|
||||
|
||||
static void spi_dma_config( const platform_spi_t* spi, const platform_spi_message_segment_t* message )
|
||||
{
|
||||
DMA_InitTypeDef dma_init;
|
||||
static uint8_t dummy = 0xFF;
|
||||
|
||||
/* Setup DMA for SPI TX if it is enabled */
|
||||
DMA_DeInit( spi->tx_dma.stream );
|
||||
|
||||
/* Setup DMA stream for TX */
|
||||
dma_init.DMA_Channel = spi->tx_dma.channel;
|
||||
dma_init.DMA_PeripheralBaseAddr = ( uint32_t )&spi->port->DR;
|
||||
dma_init.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||
dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
dma_init.DMA_BufferSize = message->length;
|
||||
dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
dma_init.DMA_Mode = DMA_Mode_Normal;
|
||||
dma_init.DMA_Priority = DMA_Priority_VeryHigh;
|
||||
dma_init.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
dma_init.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
dma_init.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
dma_init.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
|
||||
if ( message->tx_buffer != NULL )
|
||||
{
|
||||
dma_init.DMA_Memory0BaseAddr = ( uint32_t )message->tx_buffer;
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
}
|
||||
else
|
||||
{
|
||||
dma_init.DMA_Memory0BaseAddr = ( uint32_t )(&dummy);
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Disable;
|
||||
}
|
||||
|
||||
DMA_Init( spi->tx_dma.stream, &dma_init );
|
||||
|
||||
/* Activate SPI DMA mode for transmission */
|
||||
|
||||
|
||||
/* TODO: Init TX DMA finished semaphore */
|
||||
|
||||
/* Setup DMA for SPI RX stream */
|
||||
DMA_DeInit( spi->rx_dma.stream );
|
||||
dma_init.DMA_Channel = spi->rx_dma.channel;
|
||||
dma_init.DMA_PeripheralBaseAddr = ( uint32_t )&spi->port->DR;
|
||||
dma_init.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
dma_init.DMA_BufferSize = message->length;
|
||||
dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
dma_init.DMA_Mode = DMA_Mode_Normal;
|
||||
dma_init.DMA_Priority = DMA_Priority_VeryHigh;
|
||||
dma_init.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
dma_init.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
dma_init.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
dma_init.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
if ( message->rx_buffer != NULL )
|
||||
{
|
||||
dma_init.DMA_Memory0BaseAddr = (uint32_t)message->rx_buffer;
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
}
|
||||
else
|
||||
{
|
||||
dma_init.DMA_Memory0BaseAddr = (uint32_t)&dummy;
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Disable;
|
||||
}
|
||||
|
||||
/* Init and activate RX DMA channel */
|
||||
DMA_Init( spi->rx_dma.stream, &dma_init );
|
||||
|
||||
|
||||
/* TODO: Init RX DMA finish semaphore */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_spi.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide SPI driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "platform_config.h"
|
||||
#include "platform_peripheral.h"
|
||||
#include "debug.h"
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
#define MAX_NUM_SPI_PRESCALERS (8)
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t factor;
|
||||
uint16_t prescaler_value;
|
||||
} spi_baudrate_division_mapping_t;
|
||||
|
||||
/******************************************************
|
||||
* Static Function Declarations
|
||||
******************************************************/
|
||||
|
||||
static OSStatus calculate_prescaler( uint32_t speed, uint16_t* prescaler );
|
||||
static uint16_t spi_transfer ( const platform_spi_t* spi, uint16_t data );
|
||||
static OSStatus spi_dma_transfer ( const platform_spi_t* spi, const platform_spi_config_t* config );
|
||||
static void spi_dma_config ( const platform_spi_t* spi, const platform_spi_message_segment_t* message );
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
static const spi_baudrate_division_mapping_t spi_baudrate_prescalers[MAX_NUM_SPI_PRESCALERS] =
|
||||
{
|
||||
{ 2, SPI_BaudRatePrescaler_2 },
|
||||
{ 4, SPI_BaudRatePrescaler_4 },
|
||||
{ 8, SPI_BaudRatePrescaler_8 },
|
||||
{ 16, SPI_BaudRatePrescaler_16 },
|
||||
{ 32, SPI_BaudRatePrescaler_32 },
|
||||
{ 64, SPI_BaudRatePrescaler_64 },
|
||||
{ 128, SPI_BaudRatePrescaler_128 },
|
||||
{ 256, SPI_BaudRatePrescaler_256 },
|
||||
};
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
uint8_t platform_spi_get_port_number( platform_spi_port_t* spi )
|
||||
{
|
||||
if ( spi == SPI1 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if ( spi == SPI2 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if ( spi == SPI3 )
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_dma_irq_status( DMA_Stream_TypeDef* stream )
|
||||
{
|
||||
if ( stream <= DMA1_Stream3 )
|
||||
{
|
||||
return DMA1->LISR;
|
||||
}
|
||||
else if ( stream <= DMA1_Stream7 )
|
||||
{
|
||||
return DMA1->HISR;
|
||||
}
|
||||
else if ( stream <= DMA2_Stream3 )
|
||||
{
|
||||
return DMA2->LISR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DMA2->HISR;
|
||||
}
|
||||
}
|
||||
|
||||
OSStatus platform_spi_init( platform_spi_driver_t* driver, const platform_spi_t* peripheral, const platform_spi_config_t* config )
|
||||
{
|
||||
SPI_InitTypeDef spi_init;
|
||||
OSStatus err;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( ( driver != NULL ) && ( peripheral != NULL ) && ( config != NULL ), exit, err = kParamErr);
|
||||
|
||||
/* Calculate prescaler */
|
||||
err = calculate_prescaler( config->speed, &spi_init.SPI_BaudRatePrescaler );
|
||||
require_noerr(err, exit);
|
||||
|
||||
/* Configure data-width */
|
||||
if ( config->bits == 8 )
|
||||
{
|
||||
spi_init.SPI_DataSize = SPI_DataSize_8b;
|
||||
}
|
||||
else if ( config->bits == 16 )
|
||||
{
|
||||
require_action( !(config->mode & SPI_USE_DMA), exit, err = kUnsupportedErr);
|
||||
spi_init.SPI_DataSize = SPI_DataSize_16b;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = kUnsupportedErr;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Configure MSB or LSB */
|
||||
if ( config->mode & SPI_MSB_FIRST )
|
||||
{
|
||||
spi_init.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||
}
|
||||
else
|
||||
{
|
||||
spi_init.SPI_FirstBit = SPI_FirstBit_LSB;
|
||||
}
|
||||
|
||||
/* Configure mode CPHA and CPOL */
|
||||
if ( config->mode & SPI_CLOCK_IDLE_HIGH )
|
||||
{
|
||||
spi_init.SPI_CPOL = SPI_CPOL_High;
|
||||
}
|
||||
else
|
||||
{
|
||||
spi_init.SPI_CPOL = SPI_CPOL_Low;
|
||||
}
|
||||
|
||||
if ( config->mode & SPI_CLOCK_RISING_EDGE )
|
||||
{
|
||||
spi_init.SPI_CPHA = ( config->mode & SPI_CLOCK_IDLE_HIGH ) ? SPI_CPHA_2Edge : SPI_CPHA_1Edge;
|
||||
}
|
||||
else
|
||||
{
|
||||
spi_init.SPI_CPHA = ( config->mode & SPI_CLOCK_IDLE_HIGH ) ? SPI_CPHA_1Edge : SPI_CPHA_2Edge;
|
||||
}
|
||||
|
||||
driver->peripheral = (platform_spi_t *)peripheral;
|
||||
|
||||
/* Init SPI GPIOs */
|
||||
platform_gpio_set_alternate_function( peripheral->pin_clock->port, peripheral->pin_clock->pin_number, GPIO_OType_PP, GPIO_PuPd_NOPULL, peripheral->gpio_af );
|
||||
platform_gpio_set_alternate_function( peripheral->pin_mosi->port, peripheral->pin_mosi->pin_number, GPIO_OType_PP, GPIO_PuPd_NOPULL, peripheral->gpio_af );
|
||||
platform_gpio_set_alternate_function( peripheral->pin_miso->port, peripheral->pin_miso->pin_number, GPIO_OType_PP, GPIO_PuPd_UP, peripheral->gpio_af );
|
||||
|
||||
/* Init the chip select GPIO */
|
||||
platform_gpio_init( config->chip_select, OUTPUT_PUSH_PULL );
|
||||
platform_gpio_output_high( config->chip_select );
|
||||
|
||||
|
||||
/* Enable SPI peripheral clock */
|
||||
(peripheral->peripheral_clock_func)( peripheral->peripheral_clock_reg, ENABLE );
|
||||
(peripheral->peripheral_clock_func)( peripheral->peripheral_clock_reg, ENABLE );
|
||||
|
||||
SPI_I2S_DeInit( peripheral->port );
|
||||
|
||||
spi_init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||
spi_init.SPI_Mode = SPI_Mode_Master;
|
||||
spi_init.SPI_NSS = SPI_NSS_Soft;
|
||||
spi_init.SPI_CRCPolynomial = 0x7; /* reset value */
|
||||
SPI_CalculateCRC( peripheral->port, DISABLE );
|
||||
|
||||
/* Init and enable SPI */
|
||||
SPI_Init( peripheral->port, &spi_init );
|
||||
|
||||
SPI_I2S_DMACmd( peripheral->port, SPI_I2S_DMAReq_Rx, DISABLE );
|
||||
SPI_I2S_DMACmd( peripheral->port, SPI_I2S_DMAReq_Tx, DISABLE );
|
||||
|
||||
SPI_Cmd ( peripheral->port, ENABLE );
|
||||
|
||||
if ( config->mode & SPI_USE_DMA ){
|
||||
DMA_DeInit( peripheral->rx_dma.stream );
|
||||
DMA_DeInit( peripheral->tx_dma.stream );
|
||||
|
||||
if ( peripheral->tx_dma.controller == DMA1 )
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1Periph_DMA1;
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1Periph_DMA2;
|
||||
}
|
||||
|
||||
if ( peripheral->rx_dma.controller == DMA1 )
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1Periph_DMA1;
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1Periph_DMA2;
|
||||
}
|
||||
SPI_I2S_DMACmd( peripheral->port, SPI_I2S_DMAReq_Rx, ENABLE );
|
||||
SPI_I2S_DMACmd( peripheral->port, SPI_I2S_DMAReq_Tx, ENABLE );
|
||||
}
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
OSStatus platform_spi_deinit( platform_spi_driver_t* driver )
|
||||
{
|
||||
UNUSED_PARAMETER( driver );
|
||||
/* TODO: unimplemented */
|
||||
return kUnsupportedErr;
|
||||
}
|
||||
|
||||
|
||||
OSStatus platform_spi_transfer( platform_spi_driver_t* driver, const platform_spi_config_t* config, const platform_spi_message_segment_t* segments, uint16_t number_of_segments )
|
||||
{
|
||||
OSStatus err = kNoErr;
|
||||
uint32_t count = 0;
|
||||
uint16_t i;
|
||||
|
||||
platform_mcu_powersave_disable();
|
||||
|
||||
require_action_quiet( ( driver != NULL ) && ( config != NULL ) && ( segments != NULL ) && ( number_of_segments != 0 ), exit, err = kParamErr);
|
||||
|
||||
/* Activate chip select */
|
||||
platform_gpio_output_low( config->chip_select );
|
||||
|
||||
for ( i = 0; i < number_of_segments; i++ )
|
||||
{
|
||||
/* Check if we are using DMA */
|
||||
if ( config->mode & SPI_USE_DMA )
|
||||
{
|
||||
if( segments[ i ].length != 0){
|
||||
//platform_log( "length: %d, i:%d", segments[ i ].length, i );
|
||||
|
||||
spi_dma_config( driver->peripheral, &segments[ i ] );
|
||||
|
||||
err = spi_dma_transfer( driver->peripheral, config );
|
||||
require_noerr(err, cleanup_transfer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
count = segments[i].length;
|
||||
|
||||
/* in interrupt-less mode */
|
||||
if ( config->bits == 8 )
|
||||
{
|
||||
const uint8_t* send_ptr = ( const uint8_t* )segments[i].tx_buffer;
|
||||
uint8_t* rcv_ptr = ( uint8_t* )segments[i].rx_buffer;
|
||||
|
||||
while ( count-- )
|
||||
{
|
||||
uint16_t data = 0xFF;
|
||||
|
||||
if ( send_ptr != NULL )
|
||||
{
|
||||
data = *send_ptr++;
|
||||
}
|
||||
|
||||
data = spi_transfer( driver->peripheral, data );
|
||||
|
||||
if ( rcv_ptr != NULL )
|
||||
{
|
||||
*rcv_ptr++ = (uint8_t)data;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( config->bits == 16 )
|
||||
{
|
||||
const uint16_t* send_ptr = (const uint16_t *) segments[i].tx_buffer;
|
||||
uint16_t* rcv_ptr = (uint16_t *) segments[i].rx_buffer;
|
||||
|
||||
/* Check that the message length is a multiple of 2 */
|
||||
|
||||
require_action_quiet( ( count % 2 ) == 0, cleanup_transfer, err = kSizeErr);
|
||||
|
||||
/* Transmit/receive data stream, 16-bit at time */
|
||||
while ( count != 0 )
|
||||
{
|
||||
uint16_t data = 0xFFFF;
|
||||
|
||||
if ( send_ptr != NULL )
|
||||
{
|
||||
data = *send_ptr++;
|
||||
}
|
||||
|
||||
data = spi_transfer( driver->peripheral, data );
|
||||
|
||||
if ( rcv_ptr != NULL )
|
||||
{
|
||||
*rcv_ptr++ = data;
|
||||
}
|
||||
|
||||
count -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup_transfer:
|
||||
/* Deassert chip select */
|
||||
platform_gpio_output_high( config->chip_select );
|
||||
|
||||
exit:
|
||||
platform_mcu_powersave_enable( );
|
||||
return err;
|
||||
}
|
||||
|
||||
static uint16_t spi_transfer( const platform_spi_t* spi, uint16_t data )
|
||||
{
|
||||
/* Wait until the transmit buffer is empty */
|
||||
while ( SPI_I2S_GetFlagStatus( spi->port, SPI_I2S_FLAG_TXE ) == RESET )
|
||||
{
|
||||
}
|
||||
|
||||
/* Send the byte */
|
||||
SPI_I2S_SendData( spi->port, data );
|
||||
|
||||
/* Wait until a data is received */
|
||||
while ( SPI_I2S_GetFlagStatus( spi->port, SPI_I2S_FLAG_RXNE ) == RESET )
|
||||
{
|
||||
}
|
||||
|
||||
/* Get the received data */
|
||||
return SPI_I2S_ReceiveData( spi->port );
|
||||
}
|
||||
|
||||
|
||||
static OSStatus calculate_prescaler( uint32_t speed, uint16_t* prescaler )
|
||||
{
|
||||
uint8_t i;
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
require_action_quiet( prescaler != NULL, exit, err = kParamErr);
|
||||
|
||||
for( i = 0 ; i < MAX_NUM_SPI_PRESCALERS ; i++ )
|
||||
{
|
||||
if( ( 100000000 / spi_baudrate_prescalers[i].factor ) <= speed )
|
||||
{
|
||||
*prescaler = spi_baudrate_prescalers[i].prescaler_value;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static OSStatus spi_dma_transfer( const platform_spi_t* spi, const platform_spi_config_t* config )
|
||||
{
|
||||
/* Enable dma channels that have just been configured */
|
||||
DMA_Cmd( spi->rx_dma.stream, ENABLE );
|
||||
DMA_Cmd( spi->tx_dma.stream, ENABLE );
|
||||
|
||||
/* Wait for DMA to complete */
|
||||
/* TODO: This should wait on a semaphore that is triggered from an IRQ */
|
||||
while ( ( get_dma_irq_status( spi->rx_dma.stream ) & spi->rx_dma.complete_flags ) == 0 )
|
||||
{
|
||||
}
|
||||
|
||||
return kNoErr;
|
||||
}
|
||||
|
||||
static void spi_dma_config( const platform_spi_t* spi, const platform_spi_message_segment_t* message )
|
||||
{
|
||||
DMA_InitTypeDef dma_init;
|
||||
static uint8_t dummy = 0xFF;
|
||||
|
||||
/* Setup DMA for SPI TX if it is enabled */
|
||||
DMA_DeInit( spi->tx_dma.stream );
|
||||
|
||||
/* Setup DMA stream for TX */
|
||||
dma_init.DMA_Channel = spi->tx_dma.channel;
|
||||
dma_init.DMA_PeripheralBaseAddr = ( uint32_t )&spi->port->DR;
|
||||
dma_init.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||
dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
dma_init.DMA_BufferSize = message->length;
|
||||
dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
dma_init.DMA_Mode = DMA_Mode_Normal;
|
||||
dma_init.DMA_Priority = DMA_Priority_VeryHigh;
|
||||
dma_init.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
dma_init.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
dma_init.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
dma_init.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
|
||||
if ( message->tx_buffer != NULL )
|
||||
{
|
||||
dma_init.DMA_Memory0BaseAddr = ( uint32_t )message->tx_buffer;
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
}
|
||||
else
|
||||
{
|
||||
dma_init.DMA_Memory0BaseAddr = ( uint32_t )(&dummy);
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Disable;
|
||||
}
|
||||
|
||||
DMA_Init( spi->tx_dma.stream, &dma_init );
|
||||
|
||||
/* Activate SPI DMA mode for transmission */
|
||||
|
||||
|
||||
/* TODO: Init TX DMA finished semaphore */
|
||||
|
||||
/* Setup DMA for SPI RX stream */
|
||||
DMA_DeInit( spi->rx_dma.stream );
|
||||
dma_init.DMA_Channel = spi->rx_dma.channel;
|
||||
dma_init.DMA_PeripheralBaseAddr = ( uint32_t )&spi->port->DR;
|
||||
dma_init.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
dma_init.DMA_BufferSize = message->length;
|
||||
dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
dma_init.DMA_Mode = DMA_Mode_Normal;
|
||||
dma_init.DMA_Priority = DMA_Priority_VeryHigh;
|
||||
dma_init.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
dma_init.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
dma_init.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
dma_init.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
if ( message->rx_buffer != NULL )
|
||||
{
|
||||
dma_init.DMA_Memory0BaseAddr = (uint32_t)message->rx_buffer;
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
}
|
||||
else
|
||||
{
|
||||
dma_init.DMA_Memory0BaseAddr = (uint32_t)&dummy;
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Disable;
|
||||
}
|
||||
|
||||
/* Init and activate RX DMA channel */
|
||||
DMA_Init( spi->rx_dma.stream, &dma_init );
|
||||
|
||||
|
||||
/* TODO: Init RX DMA finish semaphore */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1348
mico-os/platform/MCU/STM32F4xx/peripherals/platform_uart.c
Executable file → Normal file
1348
mico-os/platform/MCU/STM32F4xx/peripherals/platform_uart.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,243 +1,243 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_watchdog.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide WDG driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "platform_config.h"
|
||||
#include "platform_peripheral.h"
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
static __IO uint32_t LsiFreq = 0;
|
||||
static __IO uint32_t CaptureNumber = 0, PeriodValue = 0;
|
||||
static mico_semaphore_t _measureLSIComplete_SEM = NULL;
|
||||
uint16_t tmpCC4[2] = {0, 0};
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
static uint32_t GetLSIFrequency(void);
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
|
||||
OSStatus platform_watchdog_init( uint32_t timeout_ms )
|
||||
{
|
||||
// PLATFORM_TO_DO
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
OSStatus err = kNoErr;
|
||||
uint32_t reloadTick;
|
||||
timeout_ms += 1000;
|
||||
/* Get the LSI frequency: TIM5 is used to measure the LSI frequency */
|
||||
LsiFreq = GetLSIFrequency();
|
||||
|
||||
/* Set counter reload value to obtain timeout_ms IWDG TimeOut.
|
||||
Counter Reload Value = timeout_s /IWDG counter clock period
|
||||
= timeout_ms * (LSI/256) / 1000
|
||||
*/
|
||||
reloadTick = (LsiFreq*timeout_ms)/256000;
|
||||
require_action( reloadTick <= 0xFFF, exit, err = kParamErr );
|
||||
|
||||
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
|
||||
|
||||
/* IWDG counter clock: LSI/256 */
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_256);
|
||||
|
||||
IWDG_SetReload(reloadTick);
|
||||
|
||||
/* Reload IWDG counter */
|
||||
IWDG_ReloadCounter();
|
||||
|
||||
/* Enable IWDG (the LSI oscillator will be enabled by hardware) */
|
||||
IWDG_Enable();
|
||||
|
||||
exit:
|
||||
return err;
|
||||
#else
|
||||
UNUSED_PARAMETER( timeout_ms );
|
||||
return kUnsupportedErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
OSStatus platform_watchdog_deinit( void )
|
||||
{
|
||||
// PLATFORM_TO_DO
|
||||
return kNoErr;
|
||||
}
|
||||
|
||||
OSStatus platform_watchdog_kick( void )
|
||||
{
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
IWDG_ReloadCounter();
|
||||
return kNoErr;
|
||||
#else
|
||||
return kUnsupportedErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
/**
|
||||
* @brief Configures TIM5 to measure the LSI oscillator frequency.
|
||||
* @param None
|
||||
* @retval LSI Frequency
|
||||
*/
|
||||
uint32_t GetLSIFrequency(void)
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
TIM_ICInitTypeDef TIM_ICInitStructure;
|
||||
RCC_ClocksTypeDef RCC_ClockFreq;
|
||||
|
||||
mico_rtos_init_semaphore(&_measureLSIComplete_SEM, 1);
|
||||
|
||||
/* Enable the LSI oscillator ************************************************/
|
||||
RCC_LSICmd(ENABLE);
|
||||
|
||||
/* Wait till LSI is ready */
|
||||
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
|
||||
{}
|
||||
|
||||
/* TIM5 configuration *******************************************************/
|
||||
/* Enable TIM5 clock */
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
|
||||
|
||||
/* Connect internally the TIM5_CH4 Input Capture to the LSI clock output */
|
||||
TIM_RemapConfig(TIM5, TIM5_LSI);
|
||||
|
||||
/* Configure TIM5 presclaer */
|
||||
TIM_PrescalerConfig(TIM5, 0, TIM_PSCReloadMode_Immediate);
|
||||
|
||||
/* TIM5 configuration: Input Capture mode ---------------------
|
||||
The LSI oscillator is connected to TIM5 CH4
|
||||
The Rising edge is used as active edge,
|
||||
The TIM5 CCR4 is used to compute the frequency value
|
||||
------------------------------------------------------------ */
|
||||
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
|
||||
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
|
||||
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
|
||||
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV8;
|
||||
TIM_ICInitStructure.TIM_ICFilter = 0;
|
||||
TIM_ICInit(TIM5, &TIM_ICInitStructure);
|
||||
|
||||
/* Enable TIM5 Interrupt channel */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
/* Enable TIM5 counter */
|
||||
TIM_Cmd(TIM5, ENABLE);
|
||||
|
||||
/* Reset the flags */
|
||||
TIM5->SR = 0;
|
||||
|
||||
/* Enable the CC4 Interrupt Request */
|
||||
TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE);
|
||||
|
||||
/* Wait until the TIM5 get 2 LSI edges (refer to TIM5_IRQHandler()) *********/
|
||||
mico_rtos_get_semaphore(&_measureLSIComplete_SEM, MICO_WAIT_FOREVER);
|
||||
mico_rtos_deinit_semaphore( &_measureLSIComplete_SEM );
|
||||
_measureLSIComplete_SEM = NULL;
|
||||
|
||||
/* Deinitialize the TIM5 peripheral registers to their default reset values */
|
||||
TIM_ITConfig(TIM5, TIM_IT_CC4, DISABLE);
|
||||
TIM_DeInit(TIM5);
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 8;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
/* Compute the LSI frequency, depending on TIM5 input clock frequency (PCLK1)*/
|
||||
/* Get SYSCLK, HCLK and PCLKx frequency */
|
||||
RCC_GetClocksFreq(&RCC_ClockFreq);
|
||||
|
||||
/* Get PCLK1 prescaler */
|
||||
if ((RCC->CFGR & RCC_CFGR_PPRE1) == 0)
|
||||
{
|
||||
/* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */
|
||||
return ((RCC_ClockFreq.PCLK1_Frequency / PeriodValue) * 8);
|
||||
}
|
||||
else
|
||||
{ /* PCLK1 prescaler different from 1 => TIMCLK = 2 * PCLK1 */
|
||||
return (((2 * RCC_ClockFreq.PCLK1_Frequency) / PeriodValue) * 8) ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles TIM5 global interrupt request.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void TIM5_IRQHandler(void)
|
||||
{
|
||||
if (TIM_GetITStatus(TIM5, TIM_IT_CC4) != RESET)
|
||||
{
|
||||
/* Clear CC4 Interrupt pending bit */
|
||||
TIM_ClearITPendingBit(TIM5, TIM_IT_CC4);
|
||||
if (CaptureNumber >= 2)
|
||||
return;
|
||||
|
||||
/* Get the Input Capture value */
|
||||
tmpCC4[CaptureNumber++] = TIM_GetCapture4(TIM5);
|
||||
|
||||
if (CaptureNumber == 2)
|
||||
{
|
||||
/* Compute the period length */
|
||||
PeriodValue = (uint16_t)(0xFFFF - tmpCC4[0] + tmpCC4[1] + 1);
|
||||
if(_measureLSIComplete_SEM != NULL){
|
||||
mico_rtos_set_semaphore(&_measureLSIComplete_SEM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool platform_watchdog_check_last_reset( void )
|
||||
{
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
if ( RCC->CSR & RCC_CSR_WDGRSTF )
|
||||
{
|
||||
/* Clear the flag and return */
|
||||
RCC->CSR |= RCC_CSR_RMVF;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file platform_watchdog.c
|
||||
* @author William Xu
|
||||
* @version V1.0.0
|
||||
* @date 05-May-2014
|
||||
* @brief This file provide WDG driver functions.
|
||||
******************************************************************************
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "platform_config.h"
|
||||
#include "platform_peripheral.h"
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Variables Definitions
|
||||
******************************************************/
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
static __IO uint32_t LsiFreq = 0;
|
||||
static __IO uint32_t CaptureNumber = 0, PeriodValue = 0;
|
||||
static mico_semaphore_t _measureLSIComplete_SEM = NULL;
|
||||
uint16_t tmpCC4[2] = {0, 0};
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
static uint32_t GetLSIFrequency(void);
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* Function Definitions
|
||||
******************************************************/
|
||||
|
||||
OSStatus platform_watchdog_init( uint32_t timeout_ms )
|
||||
{
|
||||
// PLATFORM_TO_DO
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
OSStatus err = kNoErr;
|
||||
uint32_t reloadTick;
|
||||
timeout_ms += 1000;
|
||||
/* Get the LSI frequency: TIM5 is used to measure the LSI frequency */
|
||||
LsiFreq = GetLSIFrequency();
|
||||
|
||||
/* Set counter reload value to obtain timeout_ms IWDG TimeOut.
|
||||
Counter Reload Value = timeout_s /IWDG counter clock period
|
||||
= timeout_ms * (LSI/256) / 1000
|
||||
*/
|
||||
reloadTick = (LsiFreq*timeout_ms)/256000;
|
||||
require_action( reloadTick <= 0xFFF, exit, err = kParamErr );
|
||||
|
||||
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
|
||||
|
||||
/* IWDG counter clock: LSI/256 */
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_256);
|
||||
|
||||
IWDG_SetReload(reloadTick);
|
||||
|
||||
/* Reload IWDG counter */
|
||||
IWDG_ReloadCounter();
|
||||
|
||||
/* Enable IWDG (the LSI oscillator will be enabled by hardware) */
|
||||
IWDG_Enable();
|
||||
|
||||
exit:
|
||||
return err;
|
||||
#else
|
||||
UNUSED_PARAMETER( timeout_ms );
|
||||
return kUnsupportedErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
OSStatus platform_watchdog_deinit( void )
|
||||
{
|
||||
// PLATFORM_TO_DO
|
||||
return kNoErr;
|
||||
}
|
||||
|
||||
OSStatus platform_watchdog_kick( void )
|
||||
{
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
IWDG_ReloadCounter();
|
||||
return kNoErr;
|
||||
#else
|
||||
return kUnsupportedErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
/**
|
||||
* @brief Configures TIM5 to measure the LSI oscillator frequency.
|
||||
* @param None
|
||||
* @retval LSI Frequency
|
||||
*/
|
||||
uint32_t GetLSIFrequency(void)
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
TIM_ICInitTypeDef TIM_ICInitStructure;
|
||||
RCC_ClocksTypeDef RCC_ClockFreq;
|
||||
|
||||
mico_rtos_init_semaphore(&_measureLSIComplete_SEM, 1);
|
||||
|
||||
/* Enable the LSI oscillator ************************************************/
|
||||
RCC_LSICmd(ENABLE);
|
||||
|
||||
/* Wait till LSI is ready */
|
||||
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
|
||||
{}
|
||||
|
||||
/* TIM5 configuration *******************************************************/
|
||||
/* Enable TIM5 clock */
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
|
||||
|
||||
/* Connect internally the TIM5_CH4 Input Capture to the LSI clock output */
|
||||
TIM_RemapConfig(TIM5, TIM5_LSI);
|
||||
|
||||
/* Configure TIM5 presclaer */
|
||||
TIM_PrescalerConfig(TIM5, 0, TIM_PSCReloadMode_Immediate);
|
||||
|
||||
/* TIM5 configuration: Input Capture mode ---------------------
|
||||
The LSI oscillator is connected to TIM5 CH4
|
||||
The Rising edge is used as active edge,
|
||||
The TIM5 CCR4 is used to compute the frequency value
|
||||
------------------------------------------------------------ */
|
||||
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
|
||||
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
|
||||
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
|
||||
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV8;
|
||||
TIM_ICInitStructure.TIM_ICFilter = 0;
|
||||
TIM_ICInit(TIM5, &TIM_ICInitStructure);
|
||||
|
||||
/* Enable TIM5 Interrupt channel */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
/* Enable TIM5 counter */
|
||||
TIM_Cmd(TIM5, ENABLE);
|
||||
|
||||
/* Reset the flags */
|
||||
TIM5->SR = 0;
|
||||
|
||||
/* Enable the CC4 Interrupt Request */
|
||||
TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE);
|
||||
|
||||
/* Wait until the TIM5 get 2 LSI edges (refer to TIM5_IRQHandler()) *********/
|
||||
mico_rtos_get_semaphore(&_measureLSIComplete_SEM, MICO_WAIT_FOREVER);
|
||||
mico_rtos_deinit_semaphore( &_measureLSIComplete_SEM );
|
||||
_measureLSIComplete_SEM = NULL;
|
||||
|
||||
/* Deinitialize the TIM5 peripheral registers to their default reset values */
|
||||
TIM_ITConfig(TIM5, TIM_IT_CC4, DISABLE);
|
||||
TIM_DeInit(TIM5);
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 8;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
/* Compute the LSI frequency, depending on TIM5 input clock frequency (PCLK1)*/
|
||||
/* Get SYSCLK, HCLK and PCLKx frequency */
|
||||
RCC_GetClocksFreq(&RCC_ClockFreq);
|
||||
|
||||
/* Get PCLK1 prescaler */
|
||||
if ((RCC->CFGR & RCC_CFGR_PPRE1) == 0)
|
||||
{
|
||||
/* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */
|
||||
return ((RCC_ClockFreq.PCLK1_Frequency / PeriodValue) * 8);
|
||||
}
|
||||
else
|
||||
{ /* PCLK1 prescaler different from 1 => TIMCLK = 2 * PCLK1 */
|
||||
return (((2 * RCC_ClockFreq.PCLK1_Frequency) / PeriodValue) * 8) ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles TIM5 global interrupt request.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void TIM5_IRQHandler(void)
|
||||
{
|
||||
if (TIM_GetITStatus(TIM5, TIM_IT_CC4) != RESET)
|
||||
{
|
||||
/* Clear CC4 Interrupt pending bit */
|
||||
TIM_ClearITPendingBit(TIM5, TIM_IT_CC4);
|
||||
if (CaptureNumber >= 2)
|
||||
return;
|
||||
|
||||
/* Get the Input Capture value */
|
||||
tmpCC4[CaptureNumber++] = TIM_GetCapture4(TIM5);
|
||||
|
||||
if (CaptureNumber == 2)
|
||||
{
|
||||
/* Compute the period length */
|
||||
PeriodValue = (uint16_t)(0xFFFF - tmpCC4[0] + tmpCC4[1] + 1);
|
||||
if(_measureLSIComplete_SEM != NULL){
|
||||
mico_rtos_set_semaphore(&_measureLSIComplete_SEM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool platform_watchdog_check_last_reset( void )
|
||||
{
|
||||
#ifndef MICO_DISABLE_WATCHDOG
|
||||
if ( RCC->CSR & RCC_CSR_WDGRSTF )
|
||||
{
|
||||
/* Clear the flag and return */
|
||||
RCC->CSR |= RCC_CSR_RMVF;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user