fix all board compile for v3.0

fix all board compile for v3.0
This commit is contained in:
supowang
2021-08-11 16:30:15 +08:00
parent 1f694e2156
commit 8253a953bd
615 changed files with 96466 additions and 80894 deletions

View File

@@ -0,0 +1,180 @@
/**
******************************************************************************
* @file stm32_lpm.c
* @author MCD Application Team
* @brief Low Power Manager
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32_lpm.h"
#include "utilities_conf.h"
/* Private typedef -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
#define UTIL_LPM_NO_BIT_SET (0)
#ifndef UTIL_LPM_INIT_CRITICAL_SECTION
#define UTIL_LPM_INIT_CRITICAL_SECTION( )
#endif
#ifndef UTIL_LPM_ENTER_CRITICAL_SECTION
#define UTIL_LPM_ENTER_CRITICAL_SECTION( ) UTILS_ENTER_CRITICAL_SECTION( )
#endif
#ifndef UTIL_LPM_EXIT_CRITICAL_SECTION
#define UTIL_LPM_EXIT_CRITICAL_SECTION( ) UTILS_EXIT_CRITICAL_SECTION( )
#endif
/* Private function prototypes -----------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static UTIL_LPM_bm_t StopModeDisable = UTIL_LPM_NO_BIT_SET;
static UTIL_LPM_bm_t OffModeDisable = UTIL_LPM_NO_BIT_SET;
/* Global variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Functions Definition ------------------------------------------------------*/
void UTIL_LPM_Init( void )
{
StopModeDisable = UTIL_LPM_NO_BIT_SET;
OffModeDisable = UTIL_LPM_NO_BIT_SET;
UTIL_LPM_INIT_CRITICAL_SECTION( );
}
void UTIL_LPM_DeInit( void )
{
}
void UTIL_LPM_SetStopMode( UTIL_LPM_bm_t lpm_id_bm, UTIL_LPM_State_t state )
{
UTIL_LPM_ENTER_CRITICAL_SECTION( );
switch( state )
{
case UTIL_LPM_DISABLE:
{
StopModeDisable |= lpm_id_bm;
break;
}
case UTIL_LPM_ENABLE:
{
StopModeDisable &= ( ~lpm_id_bm );
break;
}
default:
break;
}
UTIL_LPM_EXIT_CRITICAL_SECTION( );
}
void UTIL_LPM_SetOffMode( UTIL_LPM_bm_t lpm_id_bm, UTIL_LPM_State_t state )
{
UTIL_LPM_ENTER_CRITICAL_SECTION( );
switch(state)
{
case UTIL_LPM_DISABLE:
{
OffModeDisable |= lpm_id_bm;
break;
}
case UTIL_LPM_ENABLE:
{
OffModeDisable &= ( ~lpm_id_bm );
break;
}
default:
break;
}
UTIL_LPM_EXIT_CRITICAL_SECTION( );
}
UTIL_LPM_Mode_t UTIL_LPM_GetMode( void )
{
UTIL_LPM_Mode_t mode_selected;
UTIL_LPM_ENTER_CRITICAL_SECTION( );
if( StopModeDisable != UTIL_LPM_NO_BIT_SET )
{
/**
* At least one user disallows Stop Mode
*/
mode_selected = UTIL_LPM_SLEEPMODE;
}
else
{
if( OffModeDisable != UTIL_LPM_NO_BIT_SET )
{
/**
* At least one user disallows Off Mode
*/
mode_selected = UTIL_LPM_STOPMODE;
}
else
{
mode_selected = UTIL_LPM_OFFMODE;
}
}
UTIL_LPM_EXIT_CRITICAL_SECTION( );
return mode_selected;
}
void UTIL_LPM_EnterLowPower( void )
{
UTIL_LPM_ENTER_CRITICAL_SECTION( );
if( StopModeDisable != UTIL_LPM_NO_BIT_SET )
{
/**
* At least one user disallows Stop Mode
* SLEEP mode is required
*/
UTIL_PowerDriver.EnterSleepMode( );
UTIL_PowerDriver.ExitSleepMode( );
}
else
{
if( OffModeDisable != UTIL_LPM_NO_BIT_SET )
{
/**
* At least one user disallows Off Mode
* STOP mode is required
*/
UTIL_PowerDriver.EnterStopMode( );
UTIL_PowerDriver.ExitStopMode( );
}
else
{
/**
* OFF mode is required
*/
UTIL_PowerDriver.EnterOffMode( );
UTIL_PowerDriver.ExitOffMode( );
}
}
UTIL_LPM_EXIT_CRITICAL_SECTION( );
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,126 @@
/**
******************************************************************************
* @file stm32_lpm.h
* @author MCD Application Team
* @brief Header for stm32_lpm.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32_LPM_H
#define __STM32_LPM_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stdint.h"
typedef uint32_t UTIL_LPM_bm_t;
typedef enum
{
UTIL_LPM_ENABLE=0,
UTIL_LPM_DISABLE,
} UTIL_LPM_State_t;
typedef enum
{
UTIL_LPM_SLEEPMODE,
UTIL_LPM_STOPMODE,
UTIL_LPM_OFFMODE,
} UTIL_LPM_Mode_t;
/*!
* \brief LPM driver definition
*/
struct UTIL_LPM_Driver_s
{
void (* EnterSleepMode) ( void );
void (* ExitSleepMode) ( void );
void (* EnterStopMode) ( void );
void (* ExitStopMode) ( void );
void (* EnterOffMode) ( void );
void (* ExitOffMode) ( void );
};
/*!
*
* \Remark : This structure is defined and initialized in the specific platform
* power implementation
*/
extern const struct UTIL_LPM_Driver_s UTIL_PowerDriver;
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief This API Initializes the LPM resources.
* @param None
* @retval None
*/
void UTIL_LPM_Init( void );
/**
* @brief This API Un-Initializes the LPM resources.
* @param None
* @retval None
*/
void UTIL_LPM_DeInit( void );
/**
* @brief This API returns the Low Power Mode selected that will be applied when the system will enter low power mode
* if there is no update between the time the mode is read with this API and the time the system enters
* low power mode.
* @param None
* @retval UTIL_LPM_Mode_t
*/
UTIL_LPM_Mode_t UTIL_LPM_GetMode( void );
/**
* @brief This API notifies the low power manager if the specified user allows the Stop mode or not.
* The default mode selection for all users is Stop Mode enabled
* @param lpm_id_bm: identifier of the user ( 1 bit per user )
* @param state: Specify whether StopMode is allowed or not by this user
* @retval None
*/
void UTIL_LPM_SetStopMode( UTIL_LPM_bm_t lpm_id_bm, UTIL_LPM_State_t state );
/**
* @brief This API notifies the low power manager if the specified user allows the Off mode or not.
* The default mode selection for all users is Off mode enabled
* @param lpm_id_bm: identifier of the user ( 1 bit per user )
* @param state: Specify whether OffMode is allowed or not by this user
* @retval None
*/
void UTIL_LPM_SetOffMode( UTIL_LPM_bm_t lpm_id_bm, UTIL_LPM_State_t state );
/**
* @brief This API is called by the low power manager in a critical section (PRIMASK bit set) to allow the
* application to implement dedicated code before entering Low Power Mode
* @param None
* @retval None
*/
void UTIL_LPM_EnterLowPower( void );
#ifdef __cplusplus
}
#endif
#endif /*__STM32_LPM_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,65 @@
/**
******************************************************************************
* @file stm32_mem.c
* @author MCD Application Team
* @brief standard memory operation
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stdint.h"
#include "stm32_mem.h"
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Global variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Functions Definition ------------------------------------------------------*/
void UTIL_MEM_cpy_8( void *dst, const void *src, uint16_t size )
{
uint8_t* dst8= (uint8_t *) dst;
uint8_t* src8= (uint8_t *) src;
while( size-- )
{
*dst8++ = *src8++;
}
}
void UTIL_MEM_cpyr_8( void *dst, const void *src, uint16_t size )
{
uint8_t* dst8= (uint8_t *) dst;
uint8_t* src8= (uint8_t *) src;
dst8 = dst8 + ( size - 1 );
while( size-- )
{
*dst8-- = *src8++;
}
}
void UTIL_MEM_set_8( void *dst, uint8_t value, uint16_t size )
{
uint8_t* dst8= (uint8_t *) dst;
while( size-- )
{
*dst8++ = value;
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,76 @@
/**
******************************************************************************
* @file stm32_mem.h
* @author MCD Application Team
* @brief standard memory operation
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32_MEM_H__
#define __STM32_MEM_H__
#ifdef __cplusplus
extern "C"
{
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "utilities_conf.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* ---- Memory mapping macros --------------------------------------- */
#define UTIL_MEM_PLACE_IN_SECTION( __x__ ) UTIL_PLACE_IN_SECTION( __x__ )
#define UTIL_MEM_ALIGN ALIGN
/* Exported functions ------------------------------------------------------- */
/**
* @brief This API copies one buffer to another
* @param dst: output buffer to be filled
* @param src: input buffer
* @param size: size of 8b data
* @retval None
*/
void UTIL_MEM_cpy_8( void *dst, const void *src, uint16_t size );
/**
* @brief This API copies one buffer to another in reverse
* @param dst: output buffer to be filled
* @param src: input buffer
* @param size: size of 8b data
* @retval None
*/
void UTIL_MEM_cpyr_8( void *dst, const void *src, uint16_t size );
/**
* @brief This API copies one value into buffer
* @param dst: output buffer to be filled
* @param value: value
* @param size: size of 8b data
* @retval None
*/
void UTIL_MEM_set_8( void *dst, uint8_t value, uint16_t size );
#ifdef __cplusplus
}
#endif
#endif // __STM32_MEM_H__
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,351 @@
/**
******************************************************************************
* @file stm32_systime.c
* @author MCD Application Team
* @brief System time functions implementation
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include "stm32_systime.h"
#include "rtc_if.h"
#define END_OF_FEBRUARY_LEAP 60 //31+29
#define END_OF_JULY_LEAP 213 //31+29+...
#define END_OF_FEBRUARY_NORM 59 //31+28
#define END_OF_JULY_NORM 212 //31+28+...
#define UNIX_YEAR 68 //1968 is leap year
//UNIX time 0 = start at 01:00:00, 01/01/1970
#define UNIX_HOUR_OFFSET ( ( TM_DAYS_IN_LEAP_YEAR + TM_DAYS_IN_YEAR ) * TM_SECONDS_IN_1DAY )
/*!
* \brief Correction factors
*/
#define DAYS_IN_MONTH_CORRECTION_NORM ( (uint32_t )0x99AAA0 )
#define DAYS_IN_MONTH_CORRECTION_LEAP ( (uint32_t )0x445550 )
/* 365.25 = (366 + 365 + 365 + 365)/4 */
#define DIV_365_25( X ) ( ( ( X ) * 91867 + 22750 ) >> 25 )
#define DIV_APPROX_86400( X ) ( ( ( X ) >> 18 ) + ( ( X ) >> 17 ) )
#define DIV_APPROX_1000( X ) ( ( ( X ) >> 10 ) +( ( X ) >> 16 ) + ( ( X ) >> 17 ) )
#define DIV_APPROX_60( X ) ( ( ( X ) * 17476 ) >> 20 )
#define DIV_APPROX_61( X ) ( ( ( X ) * 68759 ) >> 22 )
#define MODULO_7( X ) ( ( X ) -( ( ( ( ( X ) + 1 ) * 299593 ) >> 21 ) * 7 ) )
/*!
* \brief Calculates ceiling( X / N )
*/
#define DIVC( X, N ) ( ( ( X ) + ( N ) -1 ) / ( N ) )
#define DIVC_BY_4( X ) ( ( ( X ) + 3 ) >>2 )
#define DIVC_BY_2( X ) ( ( ( X ) + 1 ) >> 1 )
static uint32_t CalendarGetMonth( uint32_t days, uint32_t year );
static void CalendarDiv86400( uint32_t in, uint32_t* out, uint32_t* remainder );
static uint32_t CalendarDiv61( uint32_t in );
static void CalendarDiv60( uint32_t in, uint32_t* out, uint32_t* remainder );
const char *WeekDayString[]={ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
SysTime_t SysTimeAdd( SysTime_t a, SysTime_t b )
{
SysTime_t c = { .Seconds = 0, .SubSeconds = 0 };
c.Seconds = a.Seconds + b.Seconds;
c.SubSeconds = a.SubSeconds + b.SubSeconds;
if( c.SubSeconds >= 1000 )
{
c.Seconds++;
c.SubSeconds -= 1000;
}
return c;
}
SysTime_t SysTimeSub( SysTime_t a, SysTime_t b )
{
SysTime_t c = { .Seconds = 0, .SubSeconds = 0 };
c.Seconds = a.Seconds - b.Seconds;
c.SubSeconds = a.SubSeconds - b.SubSeconds;
if( c.SubSeconds < 0 )
{
c.Seconds--;
c.SubSeconds += 1000;
}
return c;
}
void SysTimeSet( SysTime_t sysTime )
{
SysTime_t DeltaTime;
SysTime_t calendarTime = { .Seconds = 0, .SubSeconds = 0 };
calendarTime.Seconds = HW_RTC_GetCalendarTime( ( uint16_t* )&calendarTime.SubSeconds );
// sysTime is epoch
DeltaTime = SysTimeSub( sysTime, calendarTime );
HW_RTC_BKUPWrite( DeltaTime.Seconds, ( uint32_t )DeltaTime.SubSeconds );
}
SysTime_t SysTimeGet( void )
{
SysTime_t calendarTime = { .Seconds = 0, .SubSeconds = 0 };
SysTime_t sysTime = { .Seconds = 0, .SubSeconds = 0 };
SysTime_t DeltaTime;
calendarTime.Seconds = HW_RTC_GetCalendarTime( ( uint16_t* )&calendarTime.SubSeconds );
HW_RTC_BKUPRead( &DeltaTime.Seconds, ( uint32_t* )&DeltaTime.SubSeconds );
sysTime = SysTimeAdd( DeltaTime, calendarTime );
return sysTime;
}
SysTime_t SysTimeGetMcuTime( void )
{
SysTime_t calendarTime = { .Seconds = 0, .SubSeconds = 0 };
calendarTime.Seconds = HW_RTC_GetCalendarTime( ( uint16_t* )&calendarTime.SubSeconds );
return calendarTime;
}
uint32_t SysTimeToMs( SysTime_t sysTime )
{
SysTime_t DeltaTime;
HW_RTC_BKUPRead( &DeltaTime.Seconds, ( uint32_t* )&DeltaTime.SubSeconds );
SysTime_t calendarTime = SysTimeSub( sysTime, DeltaTime );
return calendarTime.Seconds * 1000 + calendarTime.SubSeconds;
}
SysTime_t SysTimeFromMs( uint32_t timeMs )
{
uint32_t seconds = timeMs / 1000;
SysTime_t sysTime = { .Seconds = seconds, .SubSeconds = timeMs - seconds * 1000 };
SysTime_t DeltaTime = { 0 };
HW_RTC_BKUPRead( &DeltaTime.Seconds, ( uint32_t* )&DeltaTime.SubSeconds );
return SysTimeAdd( sysTime, DeltaTime );
}
uint32_t SysTimeMkTime( const struct tm* localtime )
{
uint32_t nbdays;
uint32_t nbsecs;
uint32_t year = localtime->tm_year - UNIX_YEAR;
uint32_t correctionMonth[4] =
{
DAYS_IN_MONTH_CORRECTION_LEAP,
DAYS_IN_MONTH_CORRECTION_NORM,
DAYS_IN_MONTH_CORRECTION_NORM,
DAYS_IN_MONTH_CORRECTION_NORM
};
nbdays = DIVC( ( TM_DAYS_IN_YEAR * 3 + TM_DAYS_IN_LEAP_YEAR ) * year, 4 );
nbdays += ( DIVC_BY_2( ( localtime->tm_mon ) * ( 30 + 31 ) ) -
( ( ( correctionMonth[year % 4] >> ( ( localtime->tm_mon ) * 2 ) ) & 0x03 ) ) );
nbdays += ( localtime->tm_mday - 1 );
// Convert from days to seconds
nbsecs = nbdays * TM_SECONDS_IN_1DAY;
nbsecs += ( ( uint32_t )localtime->tm_sec +
( ( uint32_t )localtime->tm_min * TM_SECONDS_IN_1MINUTE ) +
( ( uint32_t )localtime->tm_hour * TM_SECONDS_IN_1HOUR ) );
return nbsecs - UNIX_HOUR_OFFSET;
}
void SysTimeLocalTime( const uint32_t timestamp, struct tm *localtime )
{
uint32_t correctionMonth[4] =
{
DAYS_IN_MONTH_CORRECTION_LEAP,
DAYS_IN_MONTH_CORRECTION_NORM,
DAYS_IN_MONTH_CORRECTION_NORM,
DAYS_IN_MONTH_CORRECTION_NORM
};
uint32_t weekDays = 1; // Monday 1st January 1968
uint32_t seconds;
uint32_t minutes;
uint32_t days;
uint32_t divOut;
uint32_t divReminder;
CalendarDiv86400( timestamp + UNIX_HOUR_OFFSET, &days, &seconds );
// Calculates seconds
CalendarDiv60( seconds, &minutes, &divReminder );
localtime->tm_sec = ( uint8_t )divReminder;
// Calculates minutes and hours
CalendarDiv60( minutes, &divOut, &divReminder);
localtime->tm_min = ( uint8_t )divReminder;
localtime->tm_hour = ( uint8_t )divOut;
// Calculates year
localtime->tm_year = DIV_365_25( days );
days-= DIVC_BY_4( ( TM_DAYS_IN_YEAR * 3 + TM_DAYS_IN_LEAP_YEAR ) * localtime->tm_year );
localtime->tm_yday = days;
// Calculates month
localtime->tm_mon = CalendarGetMonth( days, localtime->tm_year );
// calculates weekdays
weekDays += DIVC_BY_4( ( localtime->tm_year * 5 ) );
weekDays += days;
localtime->tm_wday = MODULO_7( weekDays );
days -= ( DIVC_BY_2( ( localtime->tm_mon ) * ( 30 + 31 ) ) -
( ( ( correctionMonth[localtime->tm_year % 4] >> ( ( localtime->tm_mon ) * 2 ) ) & 0x03 ) ) );
// Convert 0 to 1 indexed.
localtime->tm_mday = days + 1;
localtime->tm_year += UNIX_YEAR;
localtime->tm_isdst = -1;
}
static uint32_t CalendarGetMonth( uint32_t days, uint32_t year )
{
uint32_t month;
if( ( year % 4 ) == 0 )
{ /*leap year*/
if( days < END_OF_FEBRUARY_LEAP )
{ // January or February
// month = days * 2 / ( 30 + 31 );
month = CalendarDiv61( days * 2 );
}
else if( days < END_OF_JULY_LEAP )
{
month = CalendarDiv61( ( days - END_OF_FEBRUARY_LEAP ) * 2 ) + 2;
}
else
{
month = CalendarDiv61( ( days - END_OF_JULY_LEAP ) * 2 ) + 7;
}
}
else
{
if( days < END_OF_FEBRUARY_NORM )
{ // January or February
month = CalendarDiv61( days * 2 );
}
else if( days < END_OF_JULY_NORM )
{
month = CalendarDiv61( ( days - END_OF_FEBRUARY_NORM ) * 2 ) + 2;
}
else
{
month = CalendarDiv61( ( days - END_OF_JULY_NORM ) * 2 ) + 7;
}
}
return month;
}
static void CalendarDiv86400( uint32_t in, uint32_t* out, uint32_t* remainder )
{
#if 0
*remainder = in % SECONDS_IN_1DAY;
*out = in / SECONDS_IN_1DAY;
#else
uint32_t outTemp = 0;
uint32_t divResult = DIV_APPROX_86400( in );
while( divResult >=1 )
{
outTemp += divResult;
in -= divResult * 86400;
divResult= DIV_APPROX_86400( in );
}
if( in >= 86400 )
{
outTemp += 1;
in -= 86400;
}
*remainder = in;
*out = outTemp;
#endif
}
static uint32_t CalendarDiv61( uint32_t in )
{
#if 0
return( in / 61 );
#else
uint32_t outTemp = 0;
uint32_t divResult = DIV_APPROX_61( in );
while( divResult >=1 )
{
outTemp += divResult;
in -= divResult * 61;
divResult = DIV_APPROX_61( in );
}
if( in >= 61 )
{
outTemp += 1;
in -= 61;
}
return outTemp;
#endif
}
static void CalendarDiv60( uint32_t in, uint32_t* out, uint32_t* remainder )
{
#if 0
*remainder = in % 60;
*out = in / 60;
#else
uint32_t outTemp = 0;
uint32_t divResult = DIV_APPROX_60( in );
while( divResult >=1 )
{
outTemp += divResult;
in -= divResult * 60;
divResult = DIV_APPROX_60( in );
}
if( in >= 60 )
{
outTemp += 1;
in -= 60;
}
*remainder = in;
*out = outTemp;
#endif
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,175 @@
/**
******************************************************************************
* @file stm32_systime.h
* @author MCD Application Team
* @brief System time functions implementation
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32_SYS_TIME_H__
#define __STM32_SYS_TIME_H__
#ifdef __cplusplus
extern "C"
{
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "time.h"
/* Exported constants --------------------------------------------------------*/
/*!
* @brief Days, Hours, Minutes and seconds of systime.h
*/
#define TM_DAYS_IN_LEAP_YEAR ( ( uint32_t ) 366U )
#define TM_DAYS_IN_YEAR ( ( uint32_t ) 365U )
#define TM_SECONDS_IN_1DAY ( ( uint32_t )86400U )
#define TM_SECONDS_IN_1HOUR ( ( uint32_t ) 3600U )
#define TM_SECONDS_IN_1MINUTE ( ( uint32_t ) 60U )
#define TM_MINUTES_IN_1HOUR ( ( uint32_t ) 60U )
#define TM_HOURS_IN_1DAY ( ( uint32_t ) 24U )
/*!
* @brief Months of systime.h
*/
#define TM_MONTH_JANUARY ( ( uint8_t ) 0U )
#define TM_MONTH_FEBRUARY ( ( uint8_t ) 1U )
#define TM_MONTH_MARCH ( ( uint8_t ) 2U )
#define TM_MONTH_APRIL ( ( uint8_t ) 3U )
#define TM_MONTH_MAY ( ( uint8_t ) 4U )
#define TM_MONTH_JUNE ( ( uint8_t ) 5U )
#define TM_MONTH_JULY ( ( uint8_t ) 6U )
#define TM_MONTH_AUGUST ( ( uint8_t ) 7U )
#define TM_MONTH_SEPTEMBER ( ( uint8_t ) 8U )
#define TM_MONTH_OCTOBER ( ( uint8_t ) 9U )
#define TM_MONTH_NOVEMBER ( ( uint8_t )10U )
#define TM_MONTH_DECEMBER ( ( uint8_t )11U )
/*!
* @brief Week days of systime.h
*/
#define TM_WEEKDAY_SUNDAY ( ( uint8_t )0U )
#define TM_WEEKDAY_MONDAY ( ( uint8_t )1U )
#define TM_WEEKDAY_TUESDAY ( ( uint8_t )2U )
#define TM_WEEKDAY_WEDNESDAY ( ( uint8_t )3U )
#define TM_WEEKDAY_THURSDAY ( ( uint8_t )4U )
#define TM_WEEKDAY_FRIDAY ( ( uint8_t )5U )
#define TM_WEEKDAY_SATURDAY ( ( uint8_t )6U )
/*!
* @brief Number of seconds elapsed between Unix and GPS epoch
*/
#define UNIX_GPS_EPOCH_OFFSET 315964800
/* External variables --------------------------------------------------------*/
/*!
* @brief Structure holding the system time in seconds and milliseconds.
*/
typedef struct SysTime_s
{
uint32_t Seconds;
int16_t SubSeconds;
}SysTime_t;
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*!
* @brief Adds 2 SysTime_t values
*
* @param a Value
* @param b Value to added
*
* @retval result Addition result (SysTime_t value)
*/
SysTime_t SysTimeAdd( SysTime_t a, SysTime_t b );
/*!
* @brief Subtracts 2 SysTime_t values
*
* @param a Value
* @param b Value to be subtracted
*
* @retval result Subtraction result (SysTime_t value)
*/
SysTime_t SysTimeSub( SysTime_t a, SysTime_t b );
/*!
* @brief Sets new system time
*
* @param sysTime New seconds/sub-seconds since UNIX epoch origin
*/
void SysTimeSet( SysTime_t sysTime );
/*!
* @brief Gets current system time
*
* @retval sysTime Current seconds/sub-seconds since UNIX epoch origin
*/
SysTime_t SysTimeGet( void );
/*!
* @brief Gets current MCU system time
*
* @retval sysTime Current seconds/sub-seconds since Mcu started
*/
SysTime_t SysTimeGetMcuTime( void );
/*!
* Converts the given SysTime to the equivalent RTC value in milliseconds
*
* @param [IN] sysTime System time to be converted
*
* @retval timeMs The RTC converted time value in ms
*/
uint32_t SysTimeToMs( SysTime_t sysTime );
/*!
* Converts the given RTC value in milliseconds to the equivalent SysTime
*
* \param [IN] timeMs The RTC time value in ms to be converted
*
* \retval sysTime Converted system time
*/
SysTime_t SysTimeFromMs( uint32_t timeMs );
/*!
* @brief Convert a calendar time into time since UNIX epoch as a uint32_t.
*
* @param [IN] localtime Pointer to the object containing the calendar time
* @retval timestamp The calendar time as seconds since UNIX epoch.
*/
uint32_t SysTimeMkTime( const struct tm* localtime );
/*!
* @brief Converts a given time in seconds since UNIX epoch into calendar time.
*
* @param [IN] timestamp The time since UNIX epoch to convert into calendar time.
* @param [OUT] localtime Pointer to the calendar time object which will contain
the result of the conversion.
*/
void SysTimeLocalTime( const uint32_t timestamp, struct tm *localtime );
#ifdef __cplusplus
}
#endif
#endif // __STM32_SYS_TIME_H__
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,976 @@
/******************************************************************************
* @file stm32_tiny_sscanf.c
* @author MCD Application Team
* @brief Tiny implementation of sscanf
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/*
* This code is derived from
* https://github.com/rapid7/metasploit-payloads/, in c/meterpreter/source/bionic/libc/stdio/sscanf.c
* It has been derived in order to optimize code size. In this context
* all the formats are not supported. Current supported formats are
* %hx, %hhx, %ul, %d,...
* when TINY_SSCANF is defined
*
* When TINY_NO_OX is defined, this is not possible to sscanf("%x") of "0xab",
* only "ab" is possible
*
* When TINY_SPACE_NOT_SPECIALCASE is defined, "space" is not a special character.
* That means that we expect a single space, and not any of ispace() character
* (space, tabs,...)
*/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
#include "stm32_tiny_sscanf.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define TINY_SSCANF
#define TINY_NO_OX
#define TINY_SPACE_NOT_SPECIALCASE
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Functions Definition ------------------------------------------------------*/
#ifdef FLOATING_POINT
#include "floatio.h"
#endif
#define BUF 513 /* Maximum length of numeric string. */
/*
* Flags used during conversion.
*/
#define LONG 0x00001 /* l: long or double */
#define SHORT 0x00004 /* h: short */
#define SHORTSHORT 0x00008 /* hh: 8 bit integer */
#define UNSIGNED 0x00800 /* %[oupxX] conversions */
#ifdef TINY_SSCANF
#else
#define LONGDBL 0x00002 /* L: long double; unimplemented */
#define LLONG 0x00010 /* ll: long long (+ deprecated q: quad) */
#define POINTER 0x00020 /* p: void * (as hex) */
#define SIZEINT 0x00040 /* z: (signed) size_t */
#define MAXINT 0x00080 /* j: intmax_t */
#define PTRINT 0x00100 /* t: ptrdiff_t */
#define NOSKIP 0x00200 /* [ or c: do not skip blanks */
#define SUPPRESS 0x00400 /* *: suppress assignment */
#endif
/*
* The following are used in numeric conversions only:
* SIGNOK, HAVESIGN, NDIGITS, DPTOK, and EXPOK are for floating point;
* SIGNOK, HAVESIGN, NDIGITS, PFXOK, and NZDIGITS are for integral.
*/
#define SIGNOK 0x01000 /* +/- is (still) legal */
#define HAVESIGN 0x02000 /* sign detected */
#define NDIGITS 0x04000 /* no digits detected */
#define DPTOK 0x08000 /* (float) decimal point is still legal */
#define EXPOK 0x10000 /* (float) exponent (e+3, etc) still legal */
#ifdef TINY_NO_OX
#else
#define PFXOK 0x08000 /* 0x prefix is (still) legal */
#define NZDIGITS 0x10000 /* no zero digits detected */
#endif
/*
* Conversion types.
*/
#define CT_INT 3 /* integer, i.e., strtoimax or strtoumax */
#define CT_FLOAT 4 /* floating, i.e., strtod */
#ifdef TINY_SSCANF
#else
#define CT_CHAR 0 /* %c conversion */
#define CT_CCL 1 /* %[...] conversion */
#define CT_STRING 2 /* %s conversion */
#endif
#define u_char unsigned char
#define u_long unsigned long
#ifdef TINY_SSCANF
#else
static u_char *__sccl(char *, u_char *);
#endif
#define VFSCANF tiny_vfscanf
#if !defined(VFSCANF)
#define VFSCANF vfscanf
#endif
#define __srefill(_x) 1
#define ungetc(_c, _fp) do { (_c), fp_p--; fp_r++; } while (0)
/*
* vfscanf
*/
static inline int
VFSCANF(const char *str, const char *fmt0, __Va_list ap)
{
u_char *fmt = (u_char *)fmt0;
int c; /* character from format, or conversion */
size_t width; /* field width, or 0 */
char *p; /* points into all kinds of strings */
int flags; /* flags as defined above */
int nassigned; /* number of fields assigned */
int nread; /* number of characters consumed from fp */
int base; /* base argument to strtoimax/strtouimax */
char buf[BUF]; /* buffer for numeric conversions */
const char *fp_p;
int fp_r;
uintmax_t value;
int sign_minus;
#ifdef TINY_SSCANF
#else
int n; /* handy integer */
char *p0; /* saves original value of p when necessary */
char ccltab[256]; /* character class table for %[...] */
#endif
/* `basefix' is used to avoid `if' tests in the integer scanner */
#ifdef TINY_SSCANF
/* basefix[] can be removed as we do not support %i */
#else
static short basefix[17] =
{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
#endif
fp_p = str;
fp_r = strlen(str);
nassigned = 0;
nread = 0;
base = 0; /* XXX just to keep gcc happy */
for (;;) {
c = *fmt++;
if (c == 0)
return (nassigned);
#ifdef TINY_SPACE_NOT_SPECIALCASE
#else
if (isspace(c)) {
while ((fp_r > 0 || __srefill(fp) == 0) &&
isspace(*fp_p))
nread++, fp_r--, fp_p++;
continue;
}
#endif
if (c != '%')
goto literal;
width = 0;
flags = 0;
/*
* switch on the format. continue if done;
* break once format type is derived.
*/
again: c = *fmt++;
switch (c) {
case '%':
literal:
if (fp_r <= 0 && __srefill(fp))
goto input_failure;
if (*fp_p != c)
goto match_failure;
fp_r--, fp_p++;
nread++;
continue;
#ifdef TINY_SSCANF
#else
case '*':
flags |= SUPPRESS;
goto again;
case 'j':
flags |= MAXINT;
goto again;
case 'L':
flags |= LONGDBL;
goto again;
#endif
case 'h':
if (*fmt == 'h') {
fmt++;
flags |= SHORTSHORT;
} else {
flags |= SHORT;
}
goto again;
case 'l':
#ifdef TINY_SSCANF
/* %ll not supported */
flags |= LONG;
goto again;
#else
if (*fmt == 'l') {
fmt++;
flags |= LLONG;
} else {
flags |= LONG;
}
goto again;
#endif
#ifdef TINY_SSCANF
#else
case 'q':
flags |= LLONG; /* deprecated */
goto again;
case 't':
flags |= PTRINT;
goto again;
case 'z':
flags |= SIZEINT;
goto again;
#endif
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
width = width * 10 + c - '0';
goto again;
/*
* Conversions.
* Those marked `compat' are for 4.[123]BSD compatibility.
*
* (According to ANSI, E and X formats are supposed
* to the same as e and x. Sorry about that.)
*/
case 'D': /* compat */
flags |= LONG;
/* FALLTHROUGH */
case 'd':
c = CT_INT;
base = 10;
break;
#ifdef TINY_SSCANF
/*
* We do not support %i to remove potential base=8 in the following
* Hence basefix can be removed
*/
#else
case 'i':
c = CT_INT;
base = 0;
break;
#endif
#ifdef TINY_SSCANF
#else
case 'O': /* compat */
flags |= LONG;
/* FALLTHROUGH */
case 'o':
c = CT_INT;
flags |= UNSIGNED;
base = 8;
break;
#endif
case 'u':
c = CT_INT;
flags |= UNSIGNED;
base = 10;
break;
case 'X':
case 'x':
#ifdef TINY_NO_OX
#else
flags |= PFXOK; /* enable 0x prefixing */
#endif
c = CT_INT;
flags |= UNSIGNED;
base = 16;
break;
#ifdef FLOATING_POINT
case 'E':
case 'G':
case 'e':
case 'f':
case 'g':
c = CT_FLOAT;
break;
#endif
#ifdef TINY_SSCANF
#else
case 's':
c = CT_STRING;
break;
case '[':
fmt = __sccl(ccltab, fmt);
flags |= NOSKIP;
c = CT_CCL;
break;
case 'c':
flags |= NOSKIP;
c = CT_CHAR;
break;
case 'p': /* pointer format is like hex */
flags |= POINTER | PFXOK;
c = CT_INT;
flags |= UNSIGNED;
base = 16;
break;
case 'n':
if (flags & SUPPRESS)
continue;
if (flags & SHORTSHORT)
*va_arg(ap, char *) = nread;
else if (flags & SHORT)
*va_arg(ap, short *) = nread;
else if (flags & LONG)
*va_arg(ap, long *) = nread;
else if (flags & SIZEINT)
*va_arg(ap, size_t *) = nread;
else if (flags & PTRINT)
*va_arg(ap, ptrdiff_t *) = nread;
else if (flags & LLONG)
*va_arg(ap, long long *) = nread;
else if (flags & MAXINT)
*va_arg(ap, intmax_t *) = nread;
else
*va_arg(ap, int *) = nread;
continue;
#endif
/*
* Disgusting backwards compatibility hacks. XXX
*/
case '\0': /* compat */
return (EOF);
default: /* compat */
#ifdef TINY_SSCANF
#else
if (isupper(c))
flags |= LONG;
c = CT_INT;
base = 10;
#endif
break;
}
/*
* We have a conversion that requires input.
*/
if (fp_r <= 0 && __srefill(fp))
goto input_failure;
/*
* Consume leading white space, except for formats
* that suppress this.
*/
#ifdef TINY_SSCANF
#else
if ((flags & NOSKIP) == 0) {
while (isspace(*fp_p)) {
nread++;
if (--fp_r > 0)
fp_p++;
else if (__srefill(fp))
goto input_failure;
}
/*
* Note that there is at least one character in
* the buffer, so conversions that do not set NOSKIP
* ca no longer result in an input failure.
*/
}
#endif
/*
* Do the conversion.
*/
switch (c) {
#ifdef TINY_SSCANF
#else
case CT_CHAR:
/* scan arbitrary characters (sets NOSKIP) */
if (width == 0)
width = 1;
if (flags & SUPPRESS) {
size_t sum = 0;
for (;;) {
if ((n = fp_r) < (int)width) {
sum += n;
width -= n;
fp_p += n;
if (__srefill(fp)) {
if (sum == 0)
goto input_failure;
break;
}
} else {
sum += width;
fp_r -= width;
fp_p += width;
break;
}
}
nread += sum;
} else {
size_t r = fread((void *)va_arg(ap, char *), 1,
width, fp);
if (r == 0)
goto input_failure;
nread += r;
nassigned++;
}
break;
#endif
#ifdef TINY_SSCANF
#else
case CT_CCL:
/* scan a (nonempty) character class (sets NOSKIP) */
if (width == 0)
width = (size_t)~0; /* `infinity' */
/* take only those things in the class */
if (flags & SUPPRESS) {
n = 0;
while (ccltab[*fp_p]) {
n++, fp_r--, fp_p++;
if (--width == 0)
break;
if (fp_r <= 0 && __srefill(fp)) {
if (n == 0)
goto input_failure;
break;
}
}
if (n == 0)
goto match_failure;
} else {
p0 = p = va_arg(ap, char *);
while (ccltab[*fp_p]) {
fp_r--;
*p++ = *fp_p++;
if (--width == 0)
break;
if (fp_r <= 0 && __srefill(fp)) {
if (p == p0)
goto input_failure;
break;
}
}
n = p - p0;
if (n == 0)
goto match_failure;
*p = '\0';
nassigned++;
}
nread += n;
break;
#endif
#ifdef TINY_SSCANF
#else
case CT_STRING:
/* like CCL, but zero-length string OK, & no NOSKIP */
if (width == 0)
width = (size_t)~0;
if (flags & SUPPRESS) {
n = 0;
while (!isspace(*fp_p)) {
n++, fp_r--, fp_p++;
if (--width == 0)
break;
if (fp_r <= 0 && __srefill(fp))
break;
}
nread += n;
} else {
p0 = p = va_arg(ap, char *);
while (!isspace(*fp_p)) {
fp_r--;
*p++ = *fp_p++;
if (--width == 0)
break;
if (fp_r <= 0 && __srefill(fp))
break;
}
*p = '\0';
nread += p - p0;
nassigned++;
}
continue;
#endif
case CT_INT:
/* scan an integer as if by strtoimax/strtoumax */
#ifdef hardway
if (width == 0 || width > sizeof(buf) - 1)
width = sizeof(buf) - 1;
#else
/* size_t is unsigned, hence this optimisation */
if (--width > sizeof(buf) - 2)
width = sizeof(buf) - 2;
width++;
#endif
#ifdef TINY_NO_OX
flags |= SIGNOK | NDIGITS;
#else
flags |= SIGNOK | NDIGITS | NZDIGITS;
#endif
sign_minus = 0;
value = 0;
for (p = buf; width; width--) {
c = *fp_p;
/*
* Switch on the character; `goto ok'
* if we accept it as a part of number.
*/
switch (c) {
/*
* The digit 0 is always legal, but is
* special. For %i conversions, if no
* digits (zero or nonzero) have been
* scanned (only signs), we will have
* base==0. In that case, we should set
* it to 8 and enable 0x prefixing.
* Also, if we have not scanned zero digits
* before this, do not turn off prefixing
* (someone else will turn it off if we
* have scanned any nonzero digits).
*/
case '0':
#ifdef TINY_NO_OX
/* FALLTHROUGH */
#else
#ifdef TINY_SSCANF
#else
if (base == 0) {
base = 8;
flags |= PFXOK;
}
#endif
if (!(flags & NDIGITS)) {
value = value * base;
}
if (flags & NZDIGITS)
flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
else
flags &= ~(SIGNOK|PFXOK|NDIGITS);
goto ok;
#endif
#ifdef TINY_SSCANF
/* we only support base 10 and 16 */
case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
case '8': case '9':
#ifdef TINY_NO_OX
flags &= ~(SIGNOK | NDIGITS);
#else
flags &= ~(SIGNOK | PFXOK | NDIGITS);
#endif
value = value * base + c - '0';
goto ok;
#else
/* 1 through 7 always legal */
case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
base = basefix[base];
flags &= ~(SIGNOK | PFXOK | NDIGITS);
value = value * base + c - '0';
goto ok;
/* digits 8 and 9 ok iff decimal or hex */
case '8': case '9':
base = basefix[base];
if (base <= 8)
break; /* not legal here */
flags &= ~(SIGNOK | PFXOK | NDIGITS);
value = value * base + c - '0';
goto ok;
#endif
/* letters ok iff hex */
case 'A': case 'B': case 'C':
case 'D': case 'E': case 'F':
/* no need to fix base here */
if (base <= 10)
break; /* not legal here */
#ifdef TINY_NO_OX
flags &= ~(SIGNOK | NDIGITS);
#else
flags &= ~(SIGNOK | PFXOK | NDIGITS);
#endif
value = value * base + c - 'A' + 10;
goto ok;
case 'a': case 'b': case 'c':
case 'd': case 'e': case 'f':
/* no need to fix base here */
if (base <= 10)
break; /* not legal here */
#ifdef TINY_NO_OX
flags &= ~(SIGNOK | NDIGITS);
#else
flags &= ~(SIGNOK | PFXOK | NDIGITS);
#endif
value = value * base + c - 'a' + 10;
goto ok;
/* sign ok only as first character */
case '-':
if (!(flags & HAVESIGN)) {
sign_minus = 1;
}
/* FALLTHROUGH */
case '+':
if (flags & SIGNOK) {
flags &= ~SIGNOK;
flags |= HAVESIGN;
goto ok;
}
break;
/*
* x ok iff flag still set and 2nd char (or
* 3rd char if we have a sign).
*/
#ifdef TINY_NO_OX
#else
case 'x': case 'X':
if ((flags & PFXOK) && p ==
buf + 1 + !!(flags & HAVESIGN)) {
base = 16; /* if %i */
flags &= ~PFXOK;
goto ok;
}
break;
#endif
}
/*
* If we got here, c is not a legal character
* for a number. Stop accumulating digits.
*/
break;
ok:
/*
* c is legal: store it and look at the next.
*/
*p++ = c;
if (--fp_r > 0)
fp_p++;
else if (__srefill(fp))
break; /* EOF */
}
/*
* If we had only a sign, it is no good; push
* back the sign. If the number ends in `x',
* it was [sign] '0' 'x', so push back the x
* and treat it as [sign] '0'.
*/
if (flags & NDIGITS) {
if (p > buf)
{
--c;
--p;
ungetc(c++, fp);
/* There is a dummy post-increment to
avoid an unused value warning */
}
goto match_failure;
}
#ifdef TINY_NO_OX
#else
c = ((u_char *)p)[-1];
if (c == 'x' || c == 'X') {
--p;
ungetc(c, fp);
}
#endif
#ifdef TINY_SSCANF
{
#else
if ((flags & SUPPRESS) == 0) {
#endif
*p = '\0';
if (sign_minus)
value = -value;
#ifdef TINY_SSCANF
#else
if (flags & POINTER)
*va_arg(ap, void **) =
(void *)(uintptr_t)value;
else if (flags & MAXINT)
*va_arg(ap, intmax_t *) = value;
else if (flags & LLONG)
*va_arg(ap, long long *) = value;
else if (flags & SIZEINT)
*va_arg(ap, size_t *) = value;
else if (flags & PTRINT)
*va_arg(ap, ptrdiff_t *) = value;
else
#endif
if (flags & LONG)
*va_arg(ap, long *) = value;
else if (flags & SHORT)
*va_arg(ap, short *) = value;
else if (flags & SHORTSHORT)
*va_arg(ap, char *) = value;
else
*va_arg(ap, int *) = value;
nassigned++;
}
nread += p - buf;
break;
#ifdef FLOATING_POINT
case CT_FLOAT:
/* scan a floating point number as if by strtod */
#ifdef hardway
if (width == 0 || width > sizeof(buf) - 1)
width = sizeof(buf) - 1;
#else
/* size_t is unsigned, hence this optimisation */
if (--width > sizeof(buf) - 2)
width = sizeof(buf) - 2;
width++;
#endif
flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
for (p = buf; width; width--) {
c = *fp->_p;
/*
* This code mimicks the integer conversion
* code, but is much simpler.
*/
switch (c) {
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
case '8': case '9':
flags &= ~(SIGNOK | NDIGITS);
goto fok;
case '+': case '-':
if (flags & SIGNOK) {
flags &= ~SIGNOK;
goto fok;
}
break;
case '.':
if (flags & DPTOK) {
flags &= ~(SIGNOK | DPTOK);
goto fok;
}
break;
case 'e': case 'E':
/* no exponent without some digits */
if ((flags&(NDIGITS|EXPOK)) == EXPOK) {
flags =
(flags & ~(EXPOK|DPTOK)) |
SIGNOK | NDIGITS;
goto fok;
}
break;
}
break;
fok:
*p++ = c;
if (--fp->_r > 0)
fp->_p++;
else if (__srefill(fp))
break; /* EOF */
}
/*
* If no digits, might be missing exponent digits
* (just give back the exponent) or might be missing
* regular digits, but had sign and/or decimal point.
*/
if (flags & NDIGITS) {
if (flags & EXPOK) {
/* no digits at all */
while (p > buf)
ungetc(*(u_char *)--p, fp);
goto match_failure;
}
/* just a bad exponent (e and maybe sign) */
c = *(u_char *)--p;
if (c != 'e' && c != 'E') {
(void) ungetc(c, fp);/* sign */
c = *(u_char *)--p;
}
(void) ungetc(c, fp);
}
if ((flags & SUPPRESS) == 0) {
double res;
*p = '\0';
res = strtod(buf, (char **) NULL);
if (flags & LONGDBL)
*va_arg(ap, long double *) = res;
else if (flags & LONG)
*va_arg(ap, double *) = res;
else
*va_arg(ap, float *) = res;
nassigned++;
}
nread += p - buf;
break;
#endif /* FLOATING_POINT */
}
}
input_failure:
return (nassigned ? nassigned : -1);
match_failure:
return (nassigned);
}
#ifdef TINY_SSCANF
#else
/*
* Fill in the given table from the scanset at the given format
* (just after `['). Return a pointer to the character past the
* closing `]'. The table has a 1 wherever characters should be
* considered part of the scanset.
*/
static u_char *
__sccl(char *tab, u_char *fmt)
{
int c, n, v;
/* first `clear' the whole table */
c = *fmt++; /* first char hat => negated scanset */
if (c == '^') {
v = 1; /* default => accept */
c = *fmt++; /* get new first char */
} else
v = 0; /* default => reject */
/* should probably use memset here */
for (n = 0; n < 256; n++)
tab[n] = v;
if (c == 0)
return (fmt - 1);/* format ended before closing ] */
/*
* Now set the entries corresponding to the actual scanset
* to the opposite of the above.
*
* The first character may be ']' (or '-') without being special;
* the last character may be '-'.
*/
v = 1 - v;
for (;;) {
tab[c] = v; /* take character c */
doswitch:
n = *fmt++; /* and examine the next */
switch (n) {
case 0: /* format ended too soon */
return (fmt - 1);
case '-':
/*
* A scanset of the form
* [01+-]
* is defined as `the digit 0, the digit 1,
* the character +, the character -', but
* the effect of a scanset such as
* [a-zA-Z0-9]
* is implementation defined. The V7 Unix
* scanf treats `a-z' as `the letters a through
* z', but treats `a-a' as `the letter a, the
* character -, and the letter a'.
*
* For compatibility, the `-' is not considerd
* to define a range if the character following
* it is either a close bracket (required by ANSI)
* or is not numerically greater than the character
* we just stored in the table (c).
*/
n = *fmt;
if (n == ']' || n < c) {
c = '-';
break; /* resume the for(;;) */
}
fmt++;
do { /* fill in the range */
tab[++c] = v;
} while (c < n);
#if 1 /* XXX another disgusting compatibility hack */
/*
* Alas, the V7 Unix scanf also treats formats
* such as [a-c-e] as `the letters a through e'.
* This too is permitted by the standard....
*/
goto doswitch;
#else
c = *fmt++;
if (c == 0)
return (fmt - 1);
if (c == ']')
return (fmt);
#endif
break;
case ']': /* end of scanset */
return (fmt);
default: /* just another character */
c = n;
break;
}
}
/* NOTREACHED */
}
#endif
int
tiny_sscanf(const char *str, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = tiny_vfscanf(str, fmt, ap);
va_end(ap);
return (ret);
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,67 @@
/*******************************************************************************
* @file stm32_tiny_sscanf.h
* @author MCD Application Team
* @brief Header for driver tiny_sscanf.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32_TINY_SSCANF_H__
#define __STM32_TINY_SSCANF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Read formatted data from string
*
* Reads data from s and stores them according to parameter format into the
* locations given by the additional arguments, as if scanf was used, but
* reading from s instead of the standard input (stdin).
*
* The additional arguments should point to already allocated objects of the
* type specified by their corresponding format specifier within the format string.
*
* @param C string that the function processes as its source to retrieve the data.
* @param C string that contains a format string that follows the same specifications
* as format in scanf (see scanf for details).
* @param Depending on the format string, the function may expect a sequence of
* additional arguments, each containing a pointer to allocated storage
* where the interpretation of the extracted characters is stored with
* the appropriate type.
* There should be at least as many of these arguments as the number of
* values stored by the format specifiers. Additional arguments are
* ignored by the function.
* @retval The number of items in the argument list successfully filled. This
* count can match the expected number of items or be less (even zero)
* in the case of a matching failure
* @note Current supported formats are %hx, %hhx, %ul, %d,...
*/
int tiny_sscanf(const char *str, const char *fmt, ...);
#ifdef __cplusplus
}
#endif
#endif /* __STM32_TINY_SSCANF_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,669 @@
/******************************************************************************
* @file stm32_tiny_vsnprintf.c
* @author MCD Application Team
* @brief Tiny implementation of vsnprintf like function
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/*
* Following implementation is adapted from original one
* https://github.com/jpbonn/coremark_lm32/blob/master/ee_printf.c
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32_tiny_vsnprintf.h"
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
#define TINY_PRINTF
#define ZEROPAD (1<<0) /* Pad with zero */
#define SIGN (1<<1) /* Unsigned/signed long */
#define UPPERCASE (1<<6) /* 'ABCDEF' */
#ifdef TINY_PRINTF
#else
#define PLUS (1<<2) /* Show plus */
#define HEX_PREP (1<<5) /* 0x */
#define SPACE (1<<3) /* Spacer */
#define LEFT (1<<4) /* Left justified */
#endif
#define is_digit(c) ((c) >= '0' && (c) <= '9')
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Global variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static char *lower_digits = "0123456789abcdefghijklmnopqrstuvwxyz";
static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/* Functions Definition ------------------------------------------------------*/
#ifdef TINY_PRINTF
#else
static size_t strnlen(const char *s, size_t count);
static size_t strnlen(const char *s, size_t count)
{
const char *sc;
for (sc = s; *sc != '\0' && count--; ++sc);
return sc - s;
}
#endif
static int ee_skip_atoi(const char **s)
{
int i = 0;
while (is_digit(**s)) i = i*10 + *((*s)++) - '0';
return i;
}
#define ASSIGN_STR(_c) do { *str++ = (_c); max_size--; if (max_size == 0) return str; } while (0)
static char *ee_number(char *str, int max_size, long num, int base, int size, int precision, int type)
{
char c;
char sign, tmp[66];
char *dig = lower_digits;
int i;
if (type & UPPERCASE) dig = upper_digits;
#ifdef TINY_PRINTF
#else
if (type & LEFT) type &= ~ZEROPAD;
#endif
if (base < 2 || base > 36) return 0;
c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
if (type & SIGN)
{
if (num < 0)
{
sign = '-';
num = -num;
size--;
}
#ifdef TINY_PRINTF
#else
else if (type & PLUS)
{
sign = '+';
size--;
}
else if (type & SPACE)
{
sign = ' ';
size--;
}
#endif
}
#ifdef TINY_PRINTF
#else
if (type & HEX_PREP)
{
if (base == 16)
size -= 2;
else if (base == 8)
size--;
}
#endif
i = 0;
if (num == 0)
tmp[i++] = '0';
else
{
while (num != 0)
{
tmp[i++] = dig[((unsigned long) num) % (unsigned) base];
num = ((unsigned long) num) / (unsigned) base;
}
}
if (i > precision) precision = i;
size -= precision;
if (!(type & (ZEROPAD /* TINY option | LEFT */))) while (size-- > 0) ASSIGN_STR(' ');
if (sign) ASSIGN_STR(sign);
#ifdef TINY_PRINTF
#else
if (type & HEX_PREP)
{
if (base == 8)
ASSIGN_STR('0');
else if (base == 16)
{
ASSIGN_STR('0');
ASSIGN_STR(lower_digits[33]);
}
}
#endif
#ifdef TINY_PRINTF
while (size-- > 0) ASSIGN_STR(c);
#else
if (!(type & LEFT)) while (size-- > 0) ASSIGN_STR(c);
#endif
while (i < precision--) ASSIGN_STR('0');
while (i-- > 0) ASSIGN_STR(tmp[i]);
while (size-- > 0) ASSIGN_STR(' ');
return str;
}
#ifdef TINY_PRINTF
#else
static char *eaddr(char *str, unsigned char *addr, int size, int precision, int type)
{
char tmp[24];
char *dig = lower_digits;
int i, len;
if (type & UPPERCASE) dig = upper_digits;
len = 0;
for (i = 0; i < 6; i++)
{
if (i != 0) tmp[len++] = ':';
tmp[len++] = dig[addr[i] >> 4];
tmp[len++] = dig[addr[i] & 0x0F];
}
if (!(type & LEFT)) while (len < size--) *str++ = ' ';
for (i = 0; i < len; ++i) *str++ = tmp[i];
while (len < size--) *str++ = ' ';
return str;
}
static char *iaddr(char *str, unsigned char *addr, int size, int precision, int type)
{
char tmp[24];
int i, n, len;
len = 0;
for (i = 0; i < 4; i++)
{
if (i != 0) tmp[len++] = '.';
n = addr[i];
if (n == 0)
tmp[len++] = lower_digits[0];
else
{
if (n >= 100)
{
tmp[len++] = lower_digits[n / 100];
n = n % 100;
tmp[len++] = lower_digits[n / 10];
n = n % 10;
}
else if (n >= 10)
{
tmp[len++] = lower_digits[n / 10];
n = n % 10;
}
tmp[len++] = lower_digits[n];
}
}
if (!(type & LEFT)) while (len < size--) *str++ = ' ';
for (i = 0; i < len; ++i) *str++ = tmp[i];
while (len < size--) *str++ = ' ';
return str;
}
#endif
#ifdef HAS_FLOAT
char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
static void ee_bufcpy(char *d, char *s, int count);
void ee_bufcpy(char *pd, char *ps, int count) {
char *pe=ps+count;
while (ps!=pe)
*pd++=*ps++;
}
static void parse_float(double value, char *buffer, char fmt, int precision)
{
int decpt, sign, exp, pos;
char *fdigits = NULL;
char cvtbuf[80];
int capexp = 0;
int magnitude;
if (fmt == 'G' || fmt == 'E')
{
capexp = 1;
fmt += 'a' - 'A';
}
if (fmt == 'g')
{
fdigits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf);
magnitude = decpt - 1;
if (magnitude < -4 || magnitude > precision - 1)
{
fmt = 'e';
precision -= 1;
}
else
{
fmt = 'f';
precision -= decpt;
}
}
if (fmt == 'e')
{
fdigits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf);
if (sign) *buffer++ = '-';
*buffer++ = *fdigits;
if (precision > 0) *buffer++ = '.';
ee_bufcpy(buffer, fdigits + 1, precision);
buffer += precision;
*buffer++ = capexp ? 'E' : 'e';
if (decpt == 0)
{
if (value == 0.0)
exp = 0;
else
exp = -1;
}
else
exp = decpt - 1;
if (exp < 0)
{
*buffer++ = '-';
exp = -exp;
}
else
*buffer++ = '+';
buffer[2] = (exp % 10) + '0';
exp = exp / 10;
buffer[1] = (exp % 10) + '0';
exp = exp / 10;
buffer[0] = (exp % 10) + '0';
buffer += 3;
}
else if (fmt == 'f')
{
fdigits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf);
if (sign) *buffer++ = '-';
if (*fdigits)
{
if (decpt <= 0)
{
*buffer++ = '0';
*buffer++ = '.';
for (pos = 0; pos < -decpt; pos++) *buffer++ = '0';
while (*fdigits) *buffer++ = *fdigits++;
}
else
{
pos = 0;
while (*fdigits)
{
if (pos++ == decpt) *buffer++ = '.';
*buffer++ = *fdigits++;
}
}
}
else
{
*buffer++ = '0';
if (precision > 0)
{
*buffer++ = '.';
for (pos = 0; pos < precision; pos++) *buffer++ = '0';
}
}
}
*buffer = '\0';
}
static void decimal_point(char *buffer)
{
while (*buffer)
{
if (*buffer == '.') return;
if (*buffer == 'e' || *buffer == 'E') break;
buffer++;
}
if (*buffer)
{
int n = strnlen(buffer,256);
while (n > 0)
{
buffer[n + 1] = buffer[n];
n--;
}
*buffer = '.';
}
else
{
*buffer++ = '.';
*buffer = '\0';
}
}
static void cropzeros(char *buffer)
{
char *stop;
while (*buffer && *buffer != '.') buffer++;
if (*buffer++)
{
while (*buffer && *buffer != 'e' && *buffer != 'E') buffer++;
stop = buffer--;
while (*buffer == '0') buffer--;
if (*buffer == '.') buffer--;
while (buffer!=stop)
*++buffer=0;
}
}
static char *flt(char *str, double num, int size, int precision, char fmt, int flags)
{
char tmp[80];
char c, sign;
int n, i;
// Left align means no zero padding
#ifdef TINY_PRINTF
#else
if (flags & LEFT) flags &= ~ZEROPAD;
#endif
// Determine padding and sign char
c = (flags & ZEROPAD) ? '0' : ' ';
sign = 0;
if (flags & SIGN)
{
if (num < 0.0)
{
sign = '-';
num = -num;
size--;
}
#ifdef TINY_PRINTF
#else
else if (flags & PLUS)
{
sign = '+';
size--;
}
else if (flags & SPACE)
{
sign = ' ';
size--;
}
#endif
}
// Compute the precision value
if (precision < 0)
precision = 6; // Default precision: 6
// Convert floating point number to text
parse_float(num, tmp, fmt, precision);
#ifdef TINY_PRINTF
#else
if ((flags & HEX_PREP) && precision == 0) decimal_point(tmp);
#endif
if (fmt == 'g' && !(flags & HEX_PREP)) cropzeros(tmp);
n = strnlen(tmp,256);
// Output number with alignment and padding
size -= n;
if (!(flags & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' ';
if (sign) *str++ = sign;
if (!(flags & LEFT)) while (size-- > 0) *str++ = c;
for (i = 0; i < n; i++) *str++ = tmp[i];
while (size-- > 0) *str++ = ' ';
return str;
}
#endif
#define CHECK_STR_SIZE(_buf, _str, _size) \
if ((((_str) - (_buf)) >= ((_size)-1))) { break; }
int tiny_vsnprintf_like(char *buf, const int size, const char *fmt, va_list args)
{
unsigned long num;
int base;
char *str;
int len;
int i;
char *s;
int flags; // Flags to number()
int field_width; // Width of output field
int precision; // Min. # of digits for integers; max number of chars for from string
int qualifier; // 'h', 'l', or 'L' for integer fields
if (size <= 0)
{
return 0;
}
for (str = buf; *fmt || ((str - buf) >= size-1); fmt++)
{
CHECK_STR_SIZE(buf, str, size);
if (*fmt != '%')
{
*str++ = *fmt;
continue;
}
// Process flags
flags = 0;
#ifdef TINY_PRINTF
/* Support %0, but not %-, %+, %space and %# */
fmt++;
if (*fmt == '0')
{
flags |= ZEROPAD;
}
#else
repeat:
fmt++; // This also skips first '%'
switch (*fmt)
{
case '-': flags |= LEFT; goto repeat;
case '+': flags |= PLUS; goto repeat;
case ' ': flags |= SPACE; goto repeat;
case '#': flags |= HEX_PREP; goto repeat;
case '0': flags |= ZEROPAD; goto repeat;
}
#endif
// Get field width
field_width = -1;
if (is_digit(*fmt))
field_width = ee_skip_atoi(&fmt);
#ifdef TINY_PRINTF
/* Does not support %* */
#else
else if (*fmt == '*')
{
fmt++;
field_width = va_arg(args, int);
if (field_width < 0)
{
field_width = -field_width;
flags |= LEFT;
}
}
#endif
// Get the precision
precision = -1;
#ifdef TINY_PRINTF
/* Does not support %. */
#else
if (*fmt == '.')
{
++fmt;
if (is_digit(*fmt))
precision = ee_skip_atoi(&fmt);
else if (*fmt == '*')
{
++fmt;
precision = va_arg(args, int);
}
if (precision < 0) precision = 0;
}
#endif
// Get the conversion qualifier
qualifier = -1;
#ifdef TINY_PRINTF
/* Does not support %l and %L */
#else
if (*fmt == 'l' || *fmt == 'L')
{
qualifier = *fmt;
fmt++;
}
#endif
// Default base
base = 10;
switch (*fmt)
{
case 'c':
#ifdef TINY_PRINTF
#else
if (!(flags & LEFT))
#endif
while (--field_width > 0) *str++ = ' ';
*str++ = (unsigned char) va_arg(args, int);
#ifdef TINY_PRINTF
#else
while (--field_width > 0) *str++ = ' ';
#endif
continue;
case 's':
s = va_arg(args, char *);
if (!s) s = "<NULL>";
#ifdef TINY_PRINTF
len = strlen(s);
#else
len = strnlen(s, precision);
if (!(flags & LEFT))
#endif
while (len < field_width--) *str++ = ' ';
for (i = 0; i < len; ++i) *str++ = *s++;
#ifdef TINY_PRINTF
#else
while (len < field_width--) *str++ = ' ';
#endif
continue;
#ifdef TINY_PRINTF
/* Does not support %p, %A, %a, %o */
#else
case 'p':
if (field_width == -1)
{
field_width = 2 * sizeof(void *);
flags |= ZEROPAD;
}
str = ee_number(str, (size - (str - buf)), (unsigned long) va_arg(args, void *), 16, field_width, precision, flags);
continue;
case 'A':
flags |= UPPERCASE;
case 'a':
if (qualifier == 'l')
str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
else
str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
continue;
// Integer number formats - set up the flags and "break"
case 'o':
base = 8;
break;
#endif
case 'X':
flags |= UPPERCASE;
case 'x':
base = 16;
break;
case 'd':
case 'i':
flags |= SIGN;
case 'u':
break;
#ifdef HAS_FLOAT
case 'f':
str = flt(str, va_arg(args, double), field_width, precision, *fmt, flags | SIGN);
continue;
#endif
default:
if (*fmt != '%') *str++ = '%';
CHECK_STR_SIZE(buf, str, size);
if (*fmt)
*str++ = *fmt;
else
--fmt;
CHECK_STR_SIZE(buf, str, size);
continue;
}
if (qualifier == 'l')
num = va_arg(args, unsigned long);
else if (flags & SIGN)
num = va_arg(args, int);
else
num = va_arg(args, unsigned int);
str = ee_number(str, ((size - 1) - (str - buf)), num, base, field_width, precision, flags);
}
*str = '\0';
return str - buf;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,62 @@
/******************************************************************************
* @file tiny_vsnprintf.h
* @author MCD Application Team
* @brief Header for tiny_vsnprintf.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32_TINY_VSNPRINTF_H__
#define __STM32_TINY_VSNPRINTF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdarg.h>
#include <string.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Tiny implementation of vsnprintf() like function
*
* It has been adapted so that:
* - Tiny implementation, when defining TINY_PRINTF, is available. In such as case,
* not all the format are available. Instead, only %02X, %x, %d, %u, %s and %c are available.
* %f,, %+, %#, %- and others are excluded
* - Provide a snprintf like implementation. The size of the buffer is provided,
* and the length of the filled buffer is returned (not including the final '\0' char).
* The string may be truncated
* @param Pointer to a buffer where the resulting C-string is stored. The buffer should have a size of
* at least n characters.
* @param Maximum number of bytes to be used in the buffer. The generated string has a length of at
* most n-1, leaving space for the additional terminating null character.
* @param C string that contains a format string that follows the same specifications as format
* in printf (see printf for details).
* @param A value identifying a variable arguments list initialized with va_start.
* @retval The number of written char (note that this is different from vsnprintf()
*/
int tiny_vsnprintf_like(char *buf, const int size, const char *fmt, va_list args);
#ifdef __cplusplus
}
#endif
#endif /* __STM32_TINY_VSNPRINTF_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/