初版适配和修改
This commit is contained in:
336
GCC_COMPAT/runtime.c
Normal file
336
GCC_COMPAT/runtime.c
Normal file
@@ -0,0 +1,336 @@
|
||||
#include "stm32f4xx.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *buffer;
|
||||
size_t capacity;
|
||||
size_t length;
|
||||
} OutputBuffer;
|
||||
|
||||
static void output_char(OutputBuffer *output, char value)
|
||||
{
|
||||
if (output->capacity != 0U && output->length + 1U < output->capacity)
|
||||
{
|
||||
output->buffer[output->length] = value;
|
||||
}
|
||||
output->length++;
|
||||
}
|
||||
|
||||
static void output_unsigned(OutputBuffer *output, uint32_t value, unsigned int base,
|
||||
unsigned int width, char pad, int uppercase)
|
||||
{
|
||||
char digits[16];
|
||||
unsigned int count = 0U;
|
||||
const char *alphabet = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
|
||||
do
|
||||
{
|
||||
digits[count++] = alphabet[value % base];
|
||||
value /= base;
|
||||
} while (value != 0U);
|
||||
|
||||
while (count < width)
|
||||
{
|
||||
output_char(output, pad);
|
||||
width--;
|
||||
}
|
||||
while (count != 0U)
|
||||
{
|
||||
output_char(output, digits[--count]);
|
||||
}
|
||||
}
|
||||
|
||||
int vsnprintf(char *buffer, size_t size, const char *format, va_list args)
|
||||
{
|
||||
OutputBuffer output = {buffer, size, 0U};
|
||||
|
||||
while (*format != '\0')
|
||||
{
|
||||
unsigned int width = 0U;
|
||||
char pad = ' ';
|
||||
int is_long = 0;
|
||||
char specifier;
|
||||
|
||||
if (*format != '%')
|
||||
{
|
||||
output_char(&output, *format++);
|
||||
continue;
|
||||
}
|
||||
format++;
|
||||
if (*format == '%')
|
||||
{
|
||||
output_char(&output, *format++);
|
||||
continue;
|
||||
}
|
||||
if (*format == '0')
|
||||
{
|
||||
pad = '0';
|
||||
format++;
|
||||
}
|
||||
while (*format >= '0' && *format <= '9')
|
||||
{
|
||||
width = width * 10U + (unsigned int)(*format++ - '0');
|
||||
}
|
||||
if (*format == 'l')
|
||||
{
|
||||
is_long = 1;
|
||||
format++;
|
||||
}
|
||||
specifier = *format++;
|
||||
if (specifier == 's')
|
||||
{
|
||||
const char *text = va_arg(args, const char *);
|
||||
if (text == NULL)
|
||||
{
|
||||
text = "(null)";
|
||||
}
|
||||
while (*text != '\0')
|
||||
{
|
||||
output_char(&output, *text++);
|
||||
}
|
||||
}
|
||||
else if (specifier == 'c')
|
||||
{
|
||||
output_char(&output, (char)va_arg(args, int));
|
||||
}
|
||||
else if (specifier == 'd' || specifier == 'i')
|
||||
{
|
||||
int32_t value = is_long ? (int32_t)va_arg(args, long) : (int32_t)va_arg(args, int);
|
||||
uint32_t magnitude;
|
||||
if (value < 0)
|
||||
{
|
||||
output_char(&output, '-');
|
||||
magnitude = 0U - (uint32_t)value;
|
||||
if (width != 0U)
|
||||
{
|
||||
width--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
magnitude = (uint32_t)value;
|
||||
}
|
||||
output_unsigned(&output, magnitude, 10U, width, pad, 0);
|
||||
}
|
||||
else if (specifier == 'u' || specifier == 'x' || specifier == 'X')
|
||||
{
|
||||
uint32_t value = is_long ? (uint32_t)va_arg(args, unsigned long)
|
||||
: (uint32_t)va_arg(args, unsigned int);
|
||||
unsigned int base = specifier == 'u' ? 10U : 16U;
|
||||
output_unsigned(&output, value, base, width, pad, specifier == 'X');
|
||||
}
|
||||
else if (specifier == 'p')
|
||||
{
|
||||
uintptr_t value = (uintptr_t)va_arg(args, void *);
|
||||
output_char(&output, '0');
|
||||
output_char(&output, 'x');
|
||||
output_unsigned(&output, (uint32_t)value, 16U, 8U, '0', 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
output_char(&output, '%');
|
||||
output_char(&output, specifier);
|
||||
}
|
||||
}
|
||||
|
||||
if (output.capacity != 0U)
|
||||
{
|
||||
size_t terminator = output.length < output.capacity ? output.length : output.capacity - 1U;
|
||||
output.buffer[terminator] = '\0';
|
||||
}
|
||||
return (int)output.length;
|
||||
}
|
||||
|
||||
int snprintf(char *buffer, size_t size, const char *format, ...)
|
||||
{
|
||||
int result;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
result = vsnprintf(buffer, size, format, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sprintf(char *buffer, const char *format, ...)
|
||||
{
|
||||
int result;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
result = vsnprintf(buffer, (size_t)-1, format, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
int printf(const char *format, ...)
|
||||
{
|
||||
char buffer[192];
|
||||
int result;
|
||||
size_t count;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
result = vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
va_end(args);
|
||||
count = result < 0 ? 0U : (size_t)result;
|
||||
if (count >= sizeof(buffer))
|
||||
{
|
||||
count = sizeof(buffer) - 1U;
|
||||
}
|
||||
for (size_t index = 0U; index < count; index++)
|
||||
{
|
||||
while ((USART2->SR & USART_SR_TC) == 0U)
|
||||
{
|
||||
}
|
||||
USART2->DR = (uint8_t)buffer[index];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void *memcpy(void *destination, const void *source, size_t count)
|
||||
{
|
||||
uint8_t *to = (uint8_t *)destination;
|
||||
const uint8_t *from = (const uint8_t *)source;
|
||||
while (count-- != 0U)
|
||||
{
|
||||
*to++ = *from++;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
void *memset(void *destination, int value, size_t count)
|
||||
{
|
||||
uint8_t *to = (uint8_t *)destination;
|
||||
while (count-- != 0U)
|
||||
{
|
||||
*to++ = (uint8_t)value;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
int memcmp(const void *left, const void *right, size_t count)
|
||||
{
|
||||
const uint8_t *lhs = (const uint8_t *)left;
|
||||
const uint8_t *rhs = (const uint8_t *)right;
|
||||
while (count-- != 0U)
|
||||
{
|
||||
if (*lhs != *rhs)
|
||||
{
|
||||
return (int)*lhs - (int)*rhs;
|
||||
}
|
||||
lhs++;
|
||||
rhs++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t strlen(const char *string)
|
||||
{
|
||||
const char *end = string;
|
||||
while (*end != '\0')
|
||||
{
|
||||
end++;
|
||||
}
|
||||
return (size_t)(end - string);
|
||||
}
|
||||
|
||||
char *strcpy(char *destination, const char *source)
|
||||
{
|
||||
char *result = destination;
|
||||
do
|
||||
{
|
||||
*destination++ = *source;
|
||||
} while (*source++ != '\0');
|
||||
return result;
|
||||
}
|
||||
|
||||
int abs(int value)
|
||||
{
|
||||
return value < 0 ? -value : value;
|
||||
}
|
||||
|
||||
double sqrt(double value)
|
||||
{
|
||||
double estimate;
|
||||
if (value <= 0.0)
|
||||
{
|
||||
return value == 0.0 ? 0.0 : (0.0 / 0.0);
|
||||
}
|
||||
estimate = value > 1.0 ? value : 1.0;
|
||||
for (unsigned int iteration = 0U; iteration < 12U; iteration++)
|
||||
{
|
||||
estimate = 0.5 * (estimate + value / estimate);
|
||||
}
|
||||
return estimate;
|
||||
}
|
||||
|
||||
double pow(double base, double exponent)
|
||||
{
|
||||
int power = (int)exponent;
|
||||
unsigned int magnitude;
|
||||
double result = 1.0;
|
||||
if ((double)power != exponent)
|
||||
{
|
||||
return 0.0 / 0.0;
|
||||
}
|
||||
magnitude = power < 0 ? (unsigned int)(-power) : (unsigned int)power;
|
||||
while (magnitude != 0U)
|
||||
{
|
||||
if ((magnitude & 1U) != 0U)
|
||||
{
|
||||
result *= base;
|
||||
}
|
||||
base *= base;
|
||||
magnitude >>= 1U;
|
||||
}
|
||||
return power < 0 ? 1.0 / result : result;
|
||||
}
|
||||
|
||||
double atan(double value)
|
||||
{
|
||||
const double half_pi = 1.5707963267948966;
|
||||
const double quarter_pi = 0.7853981633974483;
|
||||
double sign = 1.0;
|
||||
double result;
|
||||
if (value < 0.0)
|
||||
{
|
||||
value = -value;
|
||||
sign = -1.0;
|
||||
}
|
||||
if (value > 1.0)
|
||||
{
|
||||
double reciprocal = 1.0 / value;
|
||||
result = half_pi - reciprocal * (quarter_pi + 0.273 * (1.0 - reciprocal));
|
||||
}
|
||||
else
|
||||
{
|
||||
result = value * (quarter_pi + 0.273 * (1.0 - value));
|
||||
}
|
||||
return sign * result;
|
||||
}
|
||||
|
||||
double tan(double value)
|
||||
{
|
||||
const double pi = 3.1415926535897932;
|
||||
double squared;
|
||||
double sine;
|
||||
double cosine;
|
||||
while (value > 1.5707963267948966)
|
||||
{
|
||||
value -= pi;
|
||||
}
|
||||
while (value < -1.5707963267948966)
|
||||
{
|
||||
value += pi;
|
||||
}
|
||||
squared = value * value;
|
||||
sine = value * (1.0 + squared * (-1.0 / 6.0 + squared * (1.0 / 120.0 +
|
||||
squared * (-1.0 / 5040.0 + squared * (1.0 / 362880.0)))));
|
||||
cosine = 1.0 + squared * (-1.0 / 2.0 + squared * (1.0 / 24.0 +
|
||||
squared * (-1.0 / 720.0 + squared * (1.0 / 40320.0))));
|
||||
return sine / cosine;
|
||||
}
|
||||
Reference in New Issue
Block a user