diff --git a/.config b/.config index 73aec0c..94bc8d5 100644 --- a/.config +++ b/.config @@ -220,7 +220,7 @@ CONFIG_ULOG_ASYNC_OUTPUT_THREAD_PRIORITY=30 # # log format # -# CONFIG_ULOG_OUTPUT_FLOAT is not set +CONFIG_ULOG_OUTPUT_FLOAT=y CONFIG_ULOG_USING_COLOR=y CONFIG_ULOG_OUTPUT_TIME=y # CONFIG_ULOG_TIME_USING_TIMESTAMP is not set @@ -322,6 +322,8 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_AGILE_FTP is not set # CONFIG_PKG_USING_EMBEDDEDPROTO is not set # CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_RYANMQTT is not set +# CONFIG_PKG_USING_RYANW5500 is not set # CONFIG_PKG_USING_LORA_PKT_FWD is not set # CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set @@ -329,6 +331,7 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_SMALL_MODBUS is not set # CONFIG_PKG_USING_NET_SERVER is not set # CONFIG_PKG_USING_ZFTP is not set +# CONFIG_PKG_USING_WOL is not set # # security packages @@ -420,7 +423,6 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set -# CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set # CONFIG_PKG_USING_ADBD is not set # CONFIG_PKG_USING_COREMARK is not set @@ -454,7 +456,6 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_CBOX is not set # CONFIG_PKG_USING_SNOWFLAKE is not set # CONFIG_PKG_USING_HASH_MATCH is not set -# CONFIG_PKG_USING_FIRE_PID_CURVE is not set # CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set # CONFIG_PKG_USING_VOFA_PLUS is not set @@ -467,7 +468,15 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # # CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set -# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set +CONFIG_PKG_USING_RT_VSNPRINTF_FULL=y +CONFIG_PKG_RT_VSNPRINTF_FULL_PATH="/packages/system/enhanced-kservice/rt_vsnprintf_full" +# CONFIG_RT_VSNPRINTF_FULL_REPLACING_SPRINTF is not set +# CONFIG_RT_VSNPRINTF_FULL_REPLACING_SNPRINTF is not set +# CONFIG_RT_VSNPRINTF_FULL_REPLACING_PRINTF is not set +# CONFIG_RT_VSNPRINTF_FULL_REPLACING_VSPRINTF is not set +# CONFIG_RT_VSNPRINTF_FULL_REPLACING_VSNPRINTF is not set +CONFIG_PKG_USING_RT_VSNPRINTF_FULL_LATEST_VERSION=y +CONFIG_PKG_RT_VSNPRINTF_FULL_VER="latest" # # acceleration: Assembly language or algorithmic acceleration packages @@ -531,15 +540,88 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # # peripheral libraries and drivers # -# CONFIG_PKG_USING_SENSORS_DRIVERS is not set -# CONFIG_PKG_USING_REALTEK_AMEBA is not set + +# +# sensors drivers +# +# CONFIG_PKG_USING_LSM6DSM is not set +# CONFIG_PKG_USING_LSM6DSL is not set +# CONFIG_PKG_USING_LPS22HB is not set +# CONFIG_PKG_USING_HTS221 is not set +# CONFIG_PKG_USING_LSM303AGR is not set +# CONFIG_PKG_USING_BME280 is not set +# CONFIG_PKG_USING_BME680 is not set +# CONFIG_PKG_USING_BMA400 is not set +# CONFIG_PKG_USING_BMI160_BMX160 is not set +# CONFIG_PKG_USING_SPL0601 is not set +# CONFIG_PKG_USING_MS5805 is not set +# CONFIG_PKG_USING_DA270 is not set +# CONFIG_PKG_USING_DF220 is not set +# CONFIG_PKG_USING_HSHCAL001 is not set +# CONFIG_PKG_USING_BH1750 is not set +# CONFIG_PKG_USING_MPU6XXX is not set +# CONFIG_PKG_USING_AHT10 is not set +# CONFIG_PKG_USING_AP3216C is not set +# CONFIG_PKG_USING_TSL4531 is not set +# CONFIG_PKG_USING_DS18B20 is not set +# CONFIG_PKG_USING_DHT11 is not set +# CONFIG_PKG_USING_DHTXX is not set +# CONFIG_PKG_USING_GY271 is not set +# CONFIG_PKG_USING_GP2Y10 is not set +# CONFIG_PKG_USING_SGP30 is not set +# CONFIG_PKG_USING_HDC1000 is not set +# CONFIG_PKG_USING_BMP180 is not set +# CONFIG_PKG_USING_BMP280 is not set +# CONFIG_PKG_USING_SHTC1 is not set +# CONFIG_PKG_USING_BMI088 is not set +# CONFIG_PKG_USING_HMC5883 is not set +# CONFIG_PKG_USING_MAX6675 is not set +# CONFIG_PKG_USING_TMP1075 is not set +# CONFIG_PKG_USING_SR04 is not set +# CONFIG_PKG_USING_CCS811 is not set +# CONFIG_PKG_USING_PMSXX is not set +# CONFIG_PKG_USING_RT3020 is not set +# CONFIG_PKG_USING_MLX90632 is not set +# CONFIG_PKG_USING_MLX90393 is not set +# CONFIG_PKG_USING_MLX90392 is not set +# CONFIG_PKG_USING_MLX90397 is not set +# CONFIG_PKG_USING_MS5611 is not set +# CONFIG_PKG_USING_MAX31865 is not set +# CONFIG_PKG_USING_VL53L0X is not set +# CONFIG_PKG_USING_INA260 is not set +# CONFIG_PKG_USING_MAX30102 is not set +# CONFIG_PKG_USING_INA226 is not set +# CONFIG_PKG_USING_LIS2DH12 is not set +# CONFIG_PKG_USING_HS300X is not set +# CONFIG_PKG_USING_ZMOD4410 is not set +# CONFIG_PKG_USING_ISL29035 is not set +# CONFIG_PKG_USING_MMC3680KJ is not set +# CONFIG_PKG_USING_QMP6989 is not set +# CONFIG_PKG_USING_BALANCE is not set # CONFIG_PKG_USING_SHT2X is not set # CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AD7746 is not set # CONFIG_PKG_USING_ADT74XX is not set +# CONFIG_PKG_USING_MAX17048 is not set # CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_CW2015 is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_PAJ7620 is not set + +# +# touch drivers +# +# CONFIG_PKG_USING_GT9147 is not set +# CONFIG_PKG_USING_GT1151 is not set +# CONFIG_PKG_USING_GT917S is not set +# CONFIG_PKG_USING_GT911 is not set +# CONFIG_PKG_USING_FT6206 is not set +# CONFIG_PKG_USING_FT5426 is not set +# CONFIG_PKG_USING_FT6236 is not set +# CONFIG_PKG_USING_XPT2046_TOUCH is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_STM32_SDIO is not set # CONFIG_PKG_USING_ESP_IDF is not set -# CONFIG_PKG_USING_ICM20608 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set # CONFIG_PKG_USING_SX12XX is not set @@ -562,12 +644,9 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_AGILE_LED is not set # CONFIG_PKG_USING_AT24CXX is not set # CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set -# CONFIG_PKG_USING_AD7746 is not set # CONFIG_PKG_USING_PCA9685 is not set # CONFIG_PKG_USING_I2C_TOOLS is not set # CONFIG_PKG_USING_NRF24L01 is not set -# CONFIG_PKG_USING_TOUCH_DRIVERS is not set -# CONFIG_PKG_USING_MAX17048 is not set # CONFIG_PKG_USING_RPLIDAR is not set # CONFIG_PKG_USING_AS608 is not set # CONFIG_PKG_USING_RC522 is not set @@ -582,7 +661,6 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_CAN_YMODEM is not set # CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set # CONFIG_PKG_USING_QLED is not set -# CONFIG_PKG_USING_PAJ7620 is not set # CONFIG_PKG_USING_AGILE_CONSOLE is not set # CONFIG_PKG_USING_LD3320 is not set # CONFIG_PKG_USING_WK2124 is not set @@ -613,10 +691,11 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set -# CONFIG_PKG_USING_CW2015 is not set # CONFIG_PKG_USING_RFM300 is not set # CONFIG_PKG_USING_IO_INPUT_FILTER is not set # CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set +# CONFIG_PKG_USING_LRF_NV7LIDAR is not set +# CONFIG_PKG_USING_FINGERPRINT is not set # # AI packages @@ -631,6 +710,12 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_QUEST is not set # CONFIG_PKG_USING_NAXOS is not set +# +# Signal Processing and Control Algorithm Packages +# +# CONFIG_PKG_USING_FIRE_PID_CURVE is not set +# CONFIG_PKG_USING_UKAL is not set + # # miscellaneous packages # @@ -682,7 +767,6 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set @@ -693,27 +777,165 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_SLCAN2RTT is not set # CONFIG_PKG_USING_SOEM is not set # CONFIG_PKG_USING_QPARAM is not set +# CONFIG_PKG_USING_CorevMCU_CLI is not set +# CONFIG_PKG_USING_GET_IRQ_PRIORITY is not set # # Arduino libraries # # CONFIG_PKG_USING_RTDUINO is not set +# +# Projects +# +# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set +# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set + # # Sensors # -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set -# CONFIG_PKG_USING_ARDUINO_DHT_SENSOR is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set # CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set +# CONFIG_PKG_USING_ADAFRUIT_MAX31855 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set +# CONFIG_PKG_USING_ADAFRUIT_MSA301 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set +# CONFIG_PKG_USING_SEEED_ITG3200 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set +# CONFIG_PKG_USING_SEEED_MP503 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set # # Display # # CONFIG_PKG_USING_ARDUINO_U8G2 is not set +# CONFIG_PKG_USING_SEEED_TM1637 is not set # # Timing @@ -721,10 +943,47 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set # -# Projects +# Data Processing +# +# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set +# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set + +# +# Data Storage +# + +# +# Communication +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set + +# +# Device Control +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set + +# +# Other +# + +# +# Signal IO +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set + +# +# Uncategorized # -# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set -# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set CONFIG_SOC_FAMILY_STM32=y CONFIG_SOC_SERIES_STM32F4=y diff --git a/.gitignore b/.gitignore index 7221bde..3d051c6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ build Debug documentation/html -packages/ *~ *.o *.obj @@ -40,3 +39,4 @@ RTE/ settings/ *.uvguix* cconfig.h +packages/packages.dbsqlite diff --git a/iap/iap.c b/iap/iap.c index 645db2a..2dea004 100644 --- a/iap/iap.c +++ b/iap/iap.c @@ -116,10 +116,60 @@ rt_err_t port_rx_ind(rt_device_t dev, rt_size_t size) #define RT_BUF_SIZE (1024) +/* + * 固件格式: + * + * 作用 & 说明 + * - 记录固件对应硬件 & 版本信息 + * - 简便起见,不包含校验信息 + * + * index len desc + * 0 4 'XYFC' + * 4 4 固件信息长度 + * 8 N 固件信息 ('类型'-'版本') + * 8+N M 固件数据 + */ +static const char FIXED_HEAD[] = {'X', 'Y', 'F', 'C'}; +extern const char IAP_BIN_PREFIX[]; + +static int _check_head(const rt_uint8_t *buf, rt_size_t len) +{ + if (len < 8) + { + return -1; + } + + for (int i = 0; i < sizeof(FIXED_HEAD); i++) + { + if (FIXED_HEAD[i] != buf[i]) + { + return -2; + } + } + + rt_uint32_t real = *((const rt_uint32_t *)&buf[4]); + rt_uint32_t want = rt_strlen(IAP_BIN_PREFIX); + if (real <= want || len - 8 < real) + { + return -3; + } + + for(int i = 0; i < want; i++) + { + if (IAP_BIN_PREFIX[i] != buf[8 + i]) + { + return -4; + } + } + + return real + 8; +} + struct custom_ctx { struct rym_ctx parent; int32_t file_size; int32_t w_index; + int32_t recevied_head; const struct fal_partition *flash; rt_uint8_t ck_buffer[RT_BUF_SIZE]; }; @@ -167,11 +217,8 @@ static enum rym_code _rym_recv_begin( return RYM_CODE_CAN; } - if (fal_partition_erase(cctx->flash, 0, cctx->file_size) < 0) - { - return RYM_CODE_CAN; - } cctx->w_index = 0; + cctx->recevied_head = 0; return RYM_CODE_ACK; } @@ -185,6 +232,23 @@ static enum rym_code _rym_recv_data( RT_ASSERT(cctx); RT_ASSERT(len <= RT_BUF_SIZE); + int offset = 0; + if (cctx->recevied_head == 0) + { + offset = _check_head(buf, len); + if (offset < 0) + { + return RYM_ERR_FILE; + } + + if (fal_partition_erase(cctx->flash, 0, cctx->file_size) < 0) + { + return RYM_CODE_CAN; + } + + cctx->recevied_head = 1; + } + if (cctx->w_index >= cctx->file_size) { return RYM_CODE_ACK; @@ -195,22 +259,22 @@ static enum rym_code _rym_recv_data( len = cctx->file_size - cctx->w_index; } - if (fal_partition_write(cctx->flash, cctx->w_index, buf, len) <= 0) + if (fal_partition_write(cctx->flash, cctx->w_index, &buf[offset], len - offset) <= 0) { return RYM_CODE_CAN; } - if (fal_partition_read(cctx->flash, cctx->w_index, cctx->ck_buffer, len) <= 0) + if (fal_partition_read(cctx->flash, cctx->w_index, cctx->ck_buffer, len - offset) <= 0) { return RYM_CODE_CAN; } - for (int i = 0; i < len; i++) + for (int i = 0; i < len - offset; i++) { - if (cctx->ck_buffer[i] != buf[i]) + if (cctx->ck_buffer[i] != buf[i + offset]) return RYM_CODE_CAN; } - cctx->w_index += len; + cctx->w_index += len - offset; return RYM_CODE_ACK; } @@ -309,6 +373,8 @@ int iap_main_entry(void) return _iap_entry(RT_TRUE); } +#include "shell.h" + static int _iap_entry(rt_bool_t is_boot) { if (IapAppAddr && is_boot) @@ -316,6 +382,11 @@ static int _iap_entry(rt_bool_t is_boot) return 0; } + if ((!IapAppAddr) && is_boot) + { + finsh_set_prompt("msh (IAP)"); + } + rt_err_t err = RT_EOK; struct custom_ctx *ctx = RT_NULL; rt_device_t console = rt_console_get_device(); diff --git a/packages/SConscript b/packages/SConscript new file mode 100644 index 0000000..ca95be1 --- /dev/null +++ b/packages/SConscript @@ -0,0 +1,12 @@ +import os +from building import * + +objs = [] +cwd = GetCurrentDir() +list = os.listdir(cwd) + +for item in list: + if os.path.isfile(os.path.join(cwd, item, 'SConscript')): + objs = objs + SConscript(os.path.join(item, 'SConscript')) + +Return('objs') diff --git a/packages/pkgs.json b/packages/pkgs.json new file mode 100644 index 0000000..b1e6172 --- /dev/null +++ b/packages/pkgs.json @@ -0,0 +1,7 @@ +[ + { + "path": "/packages/system/enhanced-kservice/rt_vsnprintf_full", + "ver": "latest", + "name": "RT_VSNPRINTF_FULL" + } +] \ No newline at end of file diff --git a/packages/pkgs_error.json b/packages/pkgs_error.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/packages/pkgs_error.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/packages/rt_vsnprintf_full-latest/README.md b/packages/rt_vsnprintf_full-latest/README.md new file mode 100644 index 0000000..907c598 --- /dev/null +++ b/packages/rt_vsnprintf_full-latest/README.md @@ -0,0 +1,59 @@ +# rt_vsnprintf 完整功能版本 + +在RT-Thread的kservice.c源码中的这些函数的实现是为了满足RT-Thread内核的自持能力,即在不依赖标准C库的情况下,RT-Thread核心代码也可以正常运行,因此rt_kprintf、rt_sprintf、rt_snprintf、rt_vsnprintf这类打印函数(或者称之为rt_kprintf家族函数)仅仅满足内核的使用需求,不会实现完整的、和标准C库一致的功能,以减少ROM占用。但是,很多社区小伙伴希望rt_kprintf家族函数可以支持上更多的功能(例如打印浮点数据等等)。因此,本软件包实现了该功能。 + +本软件包实现了rt_kprintf家族函数的全功能版本,因为rt_kprintf家族函数的核心功能都是调用rt_vsnprintf函数,因此只需要重新实现rt_vsnprintf函数即可。本软件包基于开源项目[printf](https://github.com/eyalroz/printf)重新实现了rt_vsnprintf,在4.1.0以及以上的RT-Thread版本中,只需要安装本软件包即可。若RT-Thread低于4.1.0版本,需要手动将kservice.c内的rt_vsnprintf函数注释掉,再安装本软件包。 + +## 接管标准C库的printf家族函数(仅支持4.1.0及以上版本) +本软件包有三个功能宏开关,是否允许本软件包接管printf、sprintf以及snprintf函数,默认为yes,即接管。 +也就是说,安装本软件包后,即便没有使能libc(RT_USING_LIBC),你可以正常的使用printf、sprintf以及snprintf函数,当你调用这三个函数时,会自动被rt_kprintf、rt_sprintf、rt_snprintf函数接管。你可以正常使用printf家族函数的所有功能。 + +```c +#include + +printf("hello world\n"); +``` + +## ROM占用 +GCC下占用8.6KB, Keil下占用8KB。远小于开启标准C库的ROM占用。 + +## 如何添加该软件包 + +``` +RT-Thread online packages + system packages ---> + enhanced kernel services ---> + [*] rt_vsnprintf_full: fully functional version of rt_vsnprintf ---> + Version (latest) ---> +``` + +- 使用 `RT-Thread Studio` 打开 `RT-Thread Settings`, 点击添加软件包,输入关键字 `printf`, 添加 `rt_vsnprintf_full` 软件包,保存 + + ![1](figures/1.png) + + +- 软件包目录下多出了一个 `rt_vsnprintf_full-latest` 包 + + ![2](figures/2.png) + + +- 打开 rt_vsnprintf.c,发现其中也实现了 rt_vsnprintf + + ```c + rt_int32_t rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args) + { + return __vsnprintf(out_buffer, buf, size, fmt, args); + } + ``` + +- 注释掉 kservice.c 中的 rt_vsnprintf **(只针对4.1.0版本以下)** + +- 重新编译并运行 `rt_kprintf ` 和 `LOG_I`, 浮点数打印正常 + ![3](figures/3.png) + + + +## 维护 + +[Meco Man](https://github.com/mysterywolf) + diff --git a/packages/rt_vsnprintf_full-latest/SConscript b/packages/rt_vsnprintf_full-latest/SConscript new file mode 100644 index 0000000..6dea429 --- /dev/null +++ b/packages/rt_vsnprintf_full-latest/SConscript @@ -0,0 +1,14 @@ +from building import * + +src = ['rt_vsnprintf.c'] +CPPDEFINES = [] + +if GetDepend('RT_VSNPRINTF_FULL_REPLACING_SPRINTF'): + CPPDEFINES += ['sprintf=rt_sprintf'] +if GetDepend('RT_VSNPRINTF_FULL_REPLACING_SNPRINTF'): + CPPDEFINES += ['snprintf=rt_snprintf'] +if GetDepend('RT_VSNPRINTF_FULL_REPLACING_PRINTF'): + CPPDEFINES += ['printf=rt_kprintf'] + +group = DefineGroup('rt_kprintf', src, depend = ['PKG_USING_RT_VSNPRINTF_FULL'], CPPDEFINES = CPPDEFINES) +Return('group') diff --git a/packages/rt_vsnprintf_full-latest/figures/1.png b/packages/rt_vsnprintf_full-latest/figures/1.png new file mode 100644 index 0000000..127f1ba Binary files /dev/null and b/packages/rt_vsnprintf_full-latest/figures/1.png differ diff --git a/packages/rt_vsnprintf_full-latest/figures/2.png b/packages/rt_vsnprintf_full-latest/figures/2.png new file mode 100644 index 0000000..d56d694 Binary files /dev/null and b/packages/rt_vsnprintf_full-latest/figures/2.png differ diff --git a/packages/rt_vsnprintf_full-latest/figures/3.png b/packages/rt_vsnprintf_full-latest/figures/3.png new file mode 100644 index 0000000..4df4e9c Binary files /dev/null and b/packages/rt_vsnprintf_full-latest/figures/3.png differ diff --git a/packages/rt_vsnprintf_full-latest/rt_vsnprintf.c b/packages/rt_vsnprintf_full-latest/rt_vsnprintf.c new file mode 100644 index 0000000..f7bc250 --- /dev/null +++ b/packages/rt_vsnprintf_full-latest/rt_vsnprintf.c @@ -0,0 +1,1101 @@ +/* + * Copyright (c) 2021, Meco Jianting Man + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-27 Meco Man porting for rt_vsnprintf as the fully functional version + */ + +/** + * @author (c) Eyal Rozenberg + * 2021, Haifa, Palestine/Israel + * @author (c) Marco Paland (info@paland.com) + * 2014-2019, PALANDesign Hannover, Germany + * + * @note Others have made smaller contributions to this file: see the + * contributors page at https://github.com/eyalroz/printf/graphs/contributors + * or ask one of the authors. + * + * @brief Small stand-alone implementation of the printf family of functions + * (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems with + * a very limited resources. + * + * @note the implementations are thread-safe; re-entrant; use no functions from + * the standard library; and do not dynamically allocate any memory. + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +#ifndef PRINTF_INTEGER_BUFFER_SIZE +#define PRINTF_INTEGER_BUFFER_SIZE 32 +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32 +#endif + +// Support for the decimal notation floating point conversion specifiers (%f, %F) +#ifndef PRINTF_SUPPORT_DECIMAL_SPECIFIERS +#define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 1 +#endif + +// Support for the exponential notatin floating point conversion specifiers (%e, %g, %E, %G) +#ifndef PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS +#define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 1 +#endif + +// Default precision for the floating point conversion specifiers (the C standard sets this at 6) +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6 +#endif + +// According to the C languages standard, printf() and related functions must be able to print any +// integral number in floating-point notation, regardless of length, when using the %f specifier - +// possibly hundreds of characters, potentially overflowing your buffers. In this implementation, +// all values beyond this threshold are switched to exponential notation. +#ifndef PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL +#define PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9 +#endif + +// Support for the long long integral types (with the ll, z and t length modifiers for specifiers +// %d,%i,%o,%x,%X,%u, and with the %p specifier). Note: 'L' (long double) is not supported. +#ifndef PRINTF_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG 1 +#endif + +#if PRINTF_SUPPORT_LONG_LONG +typedef unsigned long long printf_unsigned_value_t; +typedef long long printf_signed_value_t; +#else +typedef unsigned long printf_unsigned_value_t; +typedef long printf_signed_value_t; +#endif + +#define PRINTF_PREFER_DECIMAL false +#define PRINTF_PREFER_EXPONENTIAL true + +/////////////////////////////////////////////////////////////////////////////// + +// The following will convert the number-of-digits into an exponential-notation literal +#define PRINTF_CONCATENATE(s1, s2) s1##s2 +#define PRINTF_EXPAND_THEN_CONCATENATE(s1, s2) PRINTF_CONCATENATE(s1, s2) +#define PRINTF_FLOAT_NOTATION_THRESHOLD PRINTF_EXPAND_THEN_CONCATENATE(1e,PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL) + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) +#define FLAGS_POINTER (1U << 12U) +// Note: Similar, but not identical, effect as FLAGS_HASH + +#define BASE_BINARY 2 +#define BASE_OCTAL 8 +#define BASE_DECIMAL 10 +#define BASE_HEX 16 + +typedef uint8_t numeric_base_t; + +#if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS) +#include +#if FLT_RADIX != 2 +#error "Non-binary-radix floating-point types are unsupported." +#endif + +#if DBL_MANT_DIG == 24 + +#define DOUBLE_SIZE_IN_BITS 32 +typedef uint32_t double_uint_t; +#define DOUBLE_EXPONENT_MASK 0xFFU +#define DOUBLE_BASE_EXPONENT 127 + +#elif DBL_MANT_DIG == 53 + +#define DOUBLE_SIZE_IN_BITS 64 +typedef uint64_t double_uint_t; +#define DOUBLE_EXPONENT_MASK 0x7FFU +#define DOUBLE_BASE_EXPONENT 1023 + +#else +#error "Unsupported double type configuration" +#endif +#define DOUBLE_STORED_MANTISSA_BITS (DBL_MANT_DIG - 1) + +typedef union { + double_uint_t U; + double F; +} double_with_bit_access; + +// This is unnecessary in C99, since compound initializers can be used, +// but: 1. Some compilers are finicky about this; 2. Some people may want to convert this to C89; +// 3. If you try to use it as C++, only C++20 supports compound literals +static inline double_with_bit_access get_bit_access(double x) +{ + double_with_bit_access dwba; + dwba.F = x; + return dwba; +} + +static inline int get_sign(double x) +{ + // The sign is stored in the highest bit + return get_bit_access(x).U >> (DOUBLE_SIZE_IN_BITS - 1); +} + +static inline int get_exp2(double_with_bit_access x) +{ + // The exponent in an IEEE-754 floating-point number occupies a contiguous + // sequence of bits (e.g. 52..62 for 64-bit doubles), but with a non-trivial representation: An + // unsigned offset from some negative value (with the extremal offset values reserved for + // special use). + return (int)((x.U >> DOUBLE_STORED_MANTISSA_BITS ) & DOUBLE_EXPONENT_MASK) - DOUBLE_BASE_EXPONENT; +} +#define PRINTF_ABS(_x) ( (_x) > 0 ? (_x) : -(_x) ) + +#endif // (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS) + +// Note in particular the behavior here on LONG_MIN or LLONG_MIN; it is valid +// and well-defined, but if you're not careful you can easily trigger undefined +// behavior with -LONG_MIN or -LLONG_MIN +#define ABS_FOR_PRINTING(_x) ((printf_unsigned_value_t) ( (_x) > 0 ? (_x) : -((printf_signed_value_t)_x) )) + +// output function type +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_function_wrapper_type; + + +// internal buffer output +static inline void out_buffer(char character, void* buffer, size_t idx, size_t maxlen) +{ + if (idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + + +// internal null output +static inline void out_discard(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)character; (void)buffer; (void)idx; (void)maxlen; +} + + +// internal secure strlen +// @return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int strnlen_s_(const char* str, size_t maxsize) +{ + const char* s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +// internal test if char is a digit (0-9) +// @return true if char is a digit +static inline bool is_digit_(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + + +// internal ASCII string to unsigned int conversion +static unsigned int atoi_(const char** str) +{ + unsigned int i = 0U; + while (is_digit_(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +// output the specified string in reverse, taking care of any zero-padding +static size_t out_rev_(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) +{ + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +// Invoked by print_integer after the actual number has been printed, performing necessary +// work on the number's prefix (as the number is initially printed in reverse order) +static size_t print_integer_finalization(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, numeric_base_t base, unsigned int precision, unsigned int width, unsigned int flags) +{ + size_t unpadded_len = len; + + // pad with leading zeros + { + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + while ((len < precision) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { + buf[len++] = '0'; + } + + if (base == BASE_OCTAL && (len > unpadded_len)) { + // Since we've written some zeros, we've satisfied the alternative format leading space requirement + flags &= ~FLAGS_HASH; + } + } + + // handle hash + if (flags & (FLAGS_HASH | FLAGS_POINTER)) { + if (!(flags & FLAGS_PRECISION) && len && ((len == precision) || (len == width))) { + // Let's take back some padding digits to fit in what will eventually + // be the format-specific prefix + if (unpadded_len < len) { + len--; + } + if (len && (base == BASE_HEX)) { + if (unpadded_len < len) { + len--; + } + } + } + if ((base == BASE_HEX) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { + buf[len++] = 'x'; + } + else if ((base == BASE_HEX) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { + buf[len++] = 'X'; + } + else if ((base == BASE_BINARY) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_INTEGER_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_INTEGER_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return out_rev_(out, buffer, idx, maxlen, buf, len, width, flags); +} + +// An internal itoa-like function +static size_t print_integer(out_fct_type out, char* buffer, size_t idx, size_t maxlen, printf_unsigned_value_t value, bool negative, numeric_base_t base, unsigned int precision, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_INTEGER_BUFFER_SIZE]; + size_t len = 0U; + + if (!value) { + if ( !(flags & FLAGS_PRECISION) ) { + buf[len++] = '0'; + flags &= ~FLAGS_HASH; + // We drop this flag this since either the alternative and regular modes of the specifier + // don't differ on 0 values, or (in the case of octal) we've already provided the special + // handling for this mode. + } + else if (base == BASE_HEX) { + flags &= ~FLAGS_HASH; + // We drop this flag this since either the alternative and regular modes of the specifier + // don't differ on 0 values + } + } + else { + do { + const char digit = (char)(value % base); + buf[len++] = (char)(digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10); + value /= base; + } while (value && (len < PRINTF_INTEGER_BUFFER_SIZE)); + } + + return print_integer_finalization(out, buffer, idx, maxlen, buf, len, negative, base, precision, width, flags); +} + +#if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS) + +struct double_components { + int_fast64_t integral; + int_fast64_t fractional; + bool is_negative; +}; + +#define NUM_DECIMAL_DIGITS_IN_INT64_T 18 +#define PRINTF_MAX_PRECOMPUTED_POWER_OF_10 NUM_DECIMAL_DIGITS_IN_INT64_T +static const double powers_of_10[NUM_DECIMAL_DIGITS_IN_INT64_T] = { + 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, + 1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17 +}; + +#define PRINTF_MAX_SUPPORTED_PRECISION NUM_DECIMAL_DIGITS_IN_INT64_T - 1 + + +// Break up a double number - which is known to be a finite non-negative number - +// into its base-10 parts: integral - before the decimal point, and fractional - after it. +// Taken the precision into account, but does not change it even internally. +static struct double_components get_components(double number, unsigned int precision) +{ + struct double_components number_; + number_.is_negative = get_sign(number); + double abs_number = (number_.is_negative) ? -number : number; + number_.integral = (int_fast64_t)abs_number; + double remainder = (abs_number - number_.integral) * powers_of_10[precision]; + number_.fractional = (int_fast64_t)remainder; + + remainder -= (double) number_.fractional; + + if (remainder > 0.5) { + ++number_.fractional; + // handle rollover, e.g. case 0.99 with precision 1 is 1.0 + if ((double) number_.fractional >= powers_of_10[precision]) { + number_.fractional = 0; + ++number_.integral; + } + } + else if (remainder == 0.5) { + if ((number_.fractional == 0U) || (number_.fractional & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++number_.fractional; + } + } + + if (precision == 0U) { + remainder = abs_number - (double) number_.integral; + if ((!(remainder < 0.5) || (remainder > 0.5)) && (number_.integral & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++number_.integral; + } + } + return number_; +} + +struct scaling_factor { + double raw_factor; + bool multiply; // if true, need to multiply by raw_factor; otherwise need to divide by it +}; + +double apply_scaling(double num, struct scaling_factor normalization) +{ + return normalization.multiply ? num * normalization.raw_factor : num / normalization.raw_factor; +} + +double unapply_scaling(double normalized, struct scaling_factor normalization) +{ + return normalization.multiply ? normalized / normalization.raw_factor : normalized * normalization.raw_factor; +} + +struct scaling_factor update_normalization(struct scaling_factor sf, double extra_multiplicative_factor) +{ + struct scaling_factor result; + if (sf.multiply) { + result.multiply = true; + result.raw_factor = sf.raw_factor * extra_multiplicative_factor; + } + else { + int factor_exp2 = get_exp2(get_bit_access(sf.raw_factor)); + int extra_factor_exp2 = get_exp2(get_bit_access(extra_multiplicative_factor)); + + // Divide the larger-exponent raw raw_factor by the smaller + if (PRINTF_ABS(factor_exp2) > PRINTF_ABS(extra_factor_exp2)) { + result.multiply = false; + result.raw_factor = sf.raw_factor / extra_multiplicative_factor; + } + else { + result.multiply = true; + result.raw_factor = extra_multiplicative_factor / sf.raw_factor; + } + } + return result; +} + +#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS +static struct double_components get_normalized_components(bool negative, unsigned int precision, double non_normalized, struct scaling_factor normalization) +{ + struct double_components components; + components.is_negative = negative; + components.integral = (int_fast64_t) apply_scaling(non_normalized, normalization); + double remainder = non_normalized - unapply_scaling((double) components.integral, normalization); + double prec_power_of_10 = powers_of_10[precision]; + struct scaling_factor account_for_precision = update_normalization(normalization, prec_power_of_10); + double scaled_remainder = apply_scaling(remainder, account_for_precision); + double rounding_threshold = 0.5; + + if (precision == 0U) { + components.fractional = 0; + components.integral += (scaled_remainder >= rounding_threshold); + if (scaled_remainder == rounding_threshold) { + // banker's rounding: Round towards the even number (making the mean error 0) + components.integral &= ~((int_fast64_t) 0x1); + } + } + else { + components.fractional = (int_fast64_t) scaled_remainder; + scaled_remainder -= components.fractional; + + components.fractional += (scaled_remainder >= rounding_threshold); + if (scaled_remainder == rounding_threshold) { + // banker's rounding: Round towards the even number (making the mean error 0) + components.fractional &= ~((int_fast64_t) 0x1); + } + // handle rollover, e.g. the case of 0.99 with precision 1 becoming (0,100), + // and must then be corrected into (1, 0). + if ((double) components.fractional >= prec_power_of_10) { + components.fractional = 0; + ++components.integral; + } + } + return components; +} +#endif + +static size_t print_broken_up_decimal( + struct double_components number_, out_fct_type out, char *buffer, size_t idx, size_t maxlen, unsigned int precision, + unsigned int width, unsigned int flags, char *buf, size_t len) +{ + if (precision != 0U) { + // do fractional part, as an unsigned number + + unsigned int count = precision; + + if (flags & FLAGS_ADAPT_EXP && !(flags & FLAGS_HASH)) { + // %g/%G mandates we skip the trailing 0 digits... + if (number_.fractional > 0) { + while(true) { + int_fast64_t digit = number_.fractional % 10U; + if (digit != 0) { + break; + } + --count; + number_.fractional /= 10U; + } + + } + // ... and even the decimal point if there are no + // non-zero fractional part digits (see below) + } + + if (number_.fractional > 0 || !(flags & FLAGS_ADAPT_EXP) || (flags & FLAGS_HASH) ) { + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)('0' + number_.fractional % 10U); + if (!(number_.fractional /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = '.'; + } + } + } + else { + if (flags & FLAGS_HASH) { + if (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = '.'; + } + } + } + + // Write the integer part of the number (it comes after the fractional + // since the character order is reversed) + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)('0' + (number_.integral % 10)); + if (!(number_.integral /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (number_.is_negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (number_.is_negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return out_rev_(out, buffer, idx, maxlen, buf, len, width, flags); +} + + // internal ftoa for fixed decimal floating point +static size_t print_decimal_number(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double number, unsigned int precision, unsigned int width, unsigned int flags, char* buf, size_t len) +{ + struct double_components value_ = get_components(number, precision); + return print_broken_up_decimal(value_, out, buffer, idx, maxlen, precision, width, flags, buf, len); +} + +#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t print_exponential_number(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double number, unsigned int precision, unsigned int width, unsigned int flags, char* buf, size_t len) +{ + const bool negative = get_sign(number); + // This number will decrease gradually (by factors of 10) as we "extract" the exponent out of it + double abs_number = negative ? -number : number; + + int exp10; + bool abs_exp10_covered_by_powers_table; + struct scaling_factor normalization; + + + // Determine the decimal exponent + if (abs_number == 0.0) { + // TODO: This is a special-case for 0.0 (and -0.0); but proper handling is required for denormals more generally. + exp10 = 0; // ... and no need to set a normalization factor or check the powers table + } + else { + double_with_bit_access conv = get_bit_access(abs_number); + { + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + int exp2 = get_exp2(conv); + // drop the exponent, so conv.F comes into the range [1,2) + conv.U = (conv.U & (( (double_uint_t)(1) << DOUBLE_STORED_MANTISSA_BITS) - 1U)) | ((double_uint_t) DOUBLE_BASE_EXPONENT << DOUBLE_STORED_MANTISSA_BITS); + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + exp10 = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^exp10 but we want to be sure it won't overflow + exp2 = (int)(exp10 * 3.321928094887362 + 0.5); + const double z = exp10 * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT) << DOUBLE_STORED_MANTISSA_BITS; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (abs_number < conv.F) { + exp10--; + conv.F /= 10; + } + } + abs_exp10_covered_by_powers_table = PRINTF_ABS(exp10) < PRINTF_MAX_PRECOMPUTED_POWER_OF_10; + normalization.raw_factor = abs_exp10_covered_by_powers_table ? powers_of_10[PRINTF_ABS(exp10)] : conv.F; + } + + // We now begin accounting for the widths of the two parts of our printed field: + // the decimal part after decimal exponent extraction, and the base-10 exponent part. + // For both of these, the value of 0 has a special meaning, but not the same one: + // a 0 exponent-part width means "don't print the exponent"; a 0 decimal-part width + // means "use as many characters as necessary". + + bool fall_back_to_decimal_only_mode = false; + if (flags & FLAGS_ADAPT_EXP) { + int required_significant_digits = (precision == 0) ? 1 : (int) precision; + // Should we want to fall-back to "%f" mode, and only print the decimal part? + fall_back_to_decimal_only_mode = (exp10 >= -4 && exp10 < required_significant_digits); + // Now, let's adjust the precision + // This also decided how we adjust the precision value - as in "%g" mode, + // "precision" is the number of _significant digits_, and this is when we "translate" + // the precision value to an actual number of decimal digits. + int precision_ = (fall_back_to_decimal_only_mode) ? + (int) precision - 1 - exp10 : + (int) precision - 1; // the presence of the exponent ensures only one significant digit comes before the decimal point + precision = (precision_ > 0 ? (unsigned) precision_ : 0U); + flags |= FLAGS_PRECISION; // make sure print_broken_up_decimal respects our choice above + } + + normalization.multiply = (exp10 < 0 && abs_exp10_covered_by_powers_table); + bool should_skip_normalization = (fall_back_to_decimal_only_mode || exp10 == 0); + struct double_components decimal_part_components = + should_skip_normalization ? + get_components(negative ? -abs_number : abs_number, precision) : + get_normalized_components(negative, precision, abs_number, normalization); + + // Account for roll-over, e.g. rounding from 9.99 to 100.0 - which effects + // the exponent and may require additional tweaking of the parts + if (fall_back_to_decimal_only_mode) { + if ( (flags & FLAGS_ADAPT_EXP) && exp10 >= -1 && decimal_part_components.integral == powers_of_10[exp10 + 1]) { + exp10++; // Not strictly necessary, since exp10 is no longer really used + precision--; + // ... and it should already be the case that decimal_part_components.fractional == 0 + } + // TODO: What about rollover strictly within the fractional part? + } + else { + if (decimal_part_components.integral >= 10) { + exp10++; + decimal_part_components.integral = 1; + decimal_part_components.fractional = 0; + } + } + + // the exp10 format is "E%+03d" and largest possible exp10 value for a 64-bit double + // is "307" (for 2^1023), so we set aside 4-5 characters overall + unsigned int exp10_part_width = fall_back_to_decimal_only_mode ? 0U : (PRINTF_ABS(exp10) < 100) ? 4U : 5U; + + unsigned int decimal_part_width = + ((flags & FLAGS_LEFT) && exp10_part_width) ? + // We're padding on the right, so the width constraint is the exponent part's + // problem, not the decimal part's, so we'll use as many characters as we need: + 0U : + // We're padding on the left; so the width constraint is the decimal part's + // problem. Well, can both the decimal part and the exponent part fit within our overall width? + ((width > exp10_part_width) ? + // Yes, so we limit our decimal part's width. + // (Note this is trivially valid even if we've fallen back to "%f" mode) + width - exp10_part_width : + // No; we just give up on any restriction on the decimal part and use as many + // characters as we need + 0U); + + const size_t start_idx = idx; + idx = print_broken_up_decimal(decimal_part_components, out, buffer, idx, maxlen, precision, decimal_part_width, flags, buf, len); + + if (! fall_back_to_decimal_only_mode) { + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + idx = print_integer(out, buffer, idx, maxlen, + ABS_FOR_PRINTING(exp10), + exp10 < 0, 10, 0, exp10_part_width - 1, + FLAGS_ZEROPAD | FLAGS_PLUS); + if (flags & FLAGS_LEFT) { + // We need to right-pad with spaces to meet the width requirement + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS + + +static size_t print_floating_point(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int precision, unsigned int width, unsigned int flags, bool prefer_exponential) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + + // test for special values + if (value != value) + return out_rev_(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return out_rev_(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return out_rev_(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + if (!prefer_exponential && ((value > PRINTF_FLOAT_NOTATION_THRESHOLD) || (value < -PRINTF_FLOAT_NOTATION_THRESHOLD))) { + // The required behavior of standard printf is to print _every_ integral-part digit -- which could mean + // printing hundreds of characters, overflowing any fixed internal buffer and necessitating a more complicated + // implementation. +#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS + return print_exponential_number(out, buffer, idx, maxlen, value, precision, width, flags, buf, len); +#else + return 0U; +#endif + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + precision = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // limit precision so that our integer holding the fractional part does not overflow + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (precision > PRINTF_MAX_SUPPORTED_PRECISION)) { + buf[len++] = '0'; // This respects the precision in terms of result length only + precision--; + } + + return +#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS + prefer_exponential ? + print_exponential_number(out, buffer, idx, maxlen, value, precision, width, flags, buf, len) : +#endif + print_decimal_number(out, buffer, idx, maxlen, value, precision, width, flags, buf, len); +} + +#endif // (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS) + +// internal vsnprintf +static int __vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) +{ + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = out_discard; + } + + while (*format) + { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } + else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break; + case '-': flags |= FLAGS_LEFT; format++; n = 1U; break; + case '+': flags |= FLAGS_PLUS; format++; n = 1U; break; + case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break; + case '#': flags |= FLAGS_HASH; format++; n = 1U; break; + default : n = 0U; break; + } + } while (n); + + // evaluate width field + width = 0U; + if (is_digit_(*format)) { + width = atoi_(&format); + } + else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } + else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (is_digit_(*format)) { + precision = atoi_(&format); + } + else if (*format == '*') { + const int precision_ = (int)va_arg(va, int); + precision = precision_ > 0 ? (unsigned int)precision_ : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default: + break; + } + + // evaluate specifier + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + // set the base + numeric_base_t base; + if (*format == 'x' || *format == 'X') { + base = BASE_HEX; + } + else if (*format == 'o') { + base = BASE_OCTAL; + } + else if (*format == 'b') { + base = BASE_BINARY; + } + else { + base = BASE_DECIMAL; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if PRINTF_SUPPORT_LONG_LONG + const long long value = va_arg(va, long long); + idx = print_integer(out, buffer, idx, maxlen, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = print_integer(out, buffer, idx, maxlen, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags); + } + else { + const int value = (flags & FLAGS_CHAR) ? (signed char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = print_integer(out, buffer, idx, maxlen, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags); + } + } + else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if PRINTF_SUPPORT_LONG_LONG + idx = print_integer(out, buffer, idx, maxlen, (printf_unsigned_value_t) va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + idx = print_integer(out, buffer, idx, maxlen, (printf_unsigned_value_t) va_arg(va, unsigned long), false, base, precision, width, flags); + } + else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = print_integer(out, buffer, idx, maxlen, (printf_unsigned_value_t) value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if PRINTF_SUPPORT_DECIMAL_SPECIFIERS + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = print_floating_point(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags, PRINTF_PREFER_DECIMAL); + format++; + break; +#endif +#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = print_floating_point(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags, PRINTF_PREFER_EXPONENTIAL); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS + case 'c' : { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char* p = va_arg(va, char*); + if (p == NULL) { + idx = out_rev_(out, buffer, idx, maxlen, ")llun(", 6, width, flags); + } + else { + unsigned int l = strnlen_s_(p, precision ? precision : (size_t)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void*) * 2U + 2; // 2 hex chars per byte + the "0x" prefix + flags |= FLAGS_ZEROPAD | FLAGS_POINTER; + uintptr_t value = (uintptr_t)va_arg(va, void*); + idx = (value == (uintptr_t) NULL) ? + out_rev_(out, buffer, idx, maxlen, ")lin(", 5, width, flags) : + print_integer(out, buffer, idx, maxlen, (printf_unsigned_value_t) value, false, BASE_HEX, precision, width, flags); + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + +/** + * This function will fill a formatted string to buffer. + * + * @param buf is the buffer to save formatted string. + * + * @param size is the size of buffer. + * + * @param fmt is the format parameters. + * + * @param args is a list of variable parameters. + * + * @return The number of characters actually written to buffer. + */ +#if (RTTHREAD_VERSION >= 40100) || (RTTHREAD_VERSION < 40000 && RTTHREAD_VERSION >= 30106) +int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args) +#else +rt_int32_t rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args) +#endif +{ + return __vsnprintf(out_buffer, buf, size, fmt, args); +} + +#ifdef RT_VSNPRINTF_FULL_REPLACING_VSNPRINTF +int vsnprintf(char * s, size_t n, const char * format, va_list arg) +{ + return rt_vsnprintf(s, n, format, arg); +} +#endif + +#ifdef RT_VSNPRINTF_FULL_REPLACING_VSPRINTF +int vsprintf(char * s, const char * format, va_list arg) +{ + return rt_vsprintf(s, format, arg); +} +#endif diff --git a/project.uvoptx b/project.uvoptx index ad705cd..237fb5e 100644 --- a/project.uvoptx +++ b/project.uvoptx @@ -303,8 +303,8 @@ 0 0 0 - rt-thread\components\libc\cplusplus\cxx_Semaphore.cpp - cxx_Semaphore.cpp + rt-thread\components\libc\cplusplus\cxx_Mutex.cpp + cxx_Mutex.cpp 0 0 @@ -315,20 +315,20 @@ 0 0 0 - rt-thread\components\libc\cplusplus\cxx_Thread.cpp - cxx_Thread.cpp + rt-thread\components\libc\cplusplus\cxx_Semaphore.cpp + cxx_Semaphore.cpp 0 0 2 11 - 1 + 8 0 0 0 - rt-thread\components\libc\cplusplus\cxx_crt_init.c - cxx_crt_init.c + rt-thread\components\libc\cplusplus\cxx_Thread.cpp + cxx_Thread.cpp 0 0 @@ -347,12 +347,12 @@ 2 13 - 8 + 1 0 0 0 - rt-thread\components\libc\cplusplus\cxx_Mutex.cpp - cxx_Mutex.cpp + rt-thread\components\libc\cplusplus\cxx_crt_init.c + cxx_crt_init.c 0 0 @@ -683,8 +683,8 @@ 0 0 0 - rt-thread\components\fal\src\fal.c - fal.c + rt-thread\components\fal\src\fal_partition.c + fal_partition.c 0 0 @@ -695,23 +695,23 @@ 0 0 0 - rt-thread\components\fal\src\fal_flash.c - fal_flash.c - 0 - 0 - - - 6 - 40 - 1 - 0 - 0 - 0 rt-thread\components\fal\src\fal_rtt.c fal_rtt.c 0 0 + + 6 + 40 + 1 + 0 + 0 + 0 + rt-thread\components\fal\src\fal.c + fal.c + 0 + 0 + 6 41 @@ -719,8 +719,8 @@ 0 0 0 - rt-thread\components\fal\src\fal_partition.c - fal_partition.c + rt-thread\components\fal\src\fal_flash.c + fal_flash.c 0 0 @@ -784,7 +784,7 @@ IAP - 1 + 0 0 0 0 @@ -1251,7 +1251,7 @@ - Utilities + rt_kprintf 0 0 0 @@ -1263,14 +1263,34 @@ 0 0 0 + packages\rt_vsnprintf_full-latest\rt_vsnprintf.c + rt_vsnprintf.c + 0 + 0 + + + + + Utilities + 1 + 0 + 0 + 0 + + 12 + 84 + 1 + 0 + 0 + 0 rt-thread\components\utilities\ulog\backend\console_be.c console_be.c 0 0 - 11 - 84 + 12 + 85 1 0 0 @@ -1281,8 +1301,8 @@ 0 - 11 - 85 + 12 + 86 1 0 0 diff --git a/project.uvprojx b/project.uvprojx index 1df6120..792e52b 100644 --- a/project.uvprojx +++ b/project.uvprojx @@ -82,7 +82,7 @@ 1 0 - move_lib.bat + E:\xyfc\413\work\stm32f413\move_lib.bat 0 0 @@ -428,6 +428,11 @@ CPlusPlus + + cxx_Mutex.cpp + 8 + rt-thread\components\libc\cplusplus\cxx_Mutex.cpp + cxx_Semaphore.cpp 8 @@ -438,20 +443,15 @@ 8 rt-thread\components\libc\cplusplus\cxx_Thread.cpp - - cxx_crt_init.c - 1 - rt-thread\components\libc\cplusplus\cxx_crt_init.c - cxx_crt.cpp 8 rt-thread\components\libc\cplusplus\cxx_crt.cpp - cxx_Mutex.cpp - 8 - rt-thread\components\libc\cplusplus\cxx_Mutex.cpp + cxx_crt_init.c + 1 + rt-thread\components\libc\cplusplus\cxx_crt_init.c @@ -593,6 +593,16 @@ Fal + + fal_partition.c + 1 + rt-thread\components\fal\src\fal_partition.c + + + fal_rtt.c + 1 + rt-thread\components\fal\src\fal_rtt.c + fal.c 1 @@ -603,16 +613,6 @@ 1 rt-thread\components\fal\src\fal_flash.c - - fal_rtt.c - 1 - rt-thread\components\fal\src\fal_rtt.c - - - fal_partition.c - 1 - rt-thread\components\fal\src\fal_partition.c - @@ -840,6 +840,16 @@ + + rt_kprintf + + + rt_vsnprintf.c + 1 + packages\rt_vsnprintf_full-latest\rt_vsnprintf.c + + + Utilities diff --git a/rt-thread/src/kservice.c b/rt-thread/src/kservice.c index 2fd38d3..efcc362 100644 --- a/rt-thread/src/kservice.c +++ b/rt-thread/src/kservice.c @@ -645,501 +645,6 @@ void rt_show_version(void) } RTM_EXPORT(rt_show_version); -/* private function */ -#define _ISDIGIT(c) ((unsigned)((c) - '0') < 10) - -/** - * This function will duplicate a string. - * - * @param n is the string to be duplicated. - * - * @param base is support divide instructions value. - * - * @return the duplicated string pointer. - */ -#ifdef RT_KPRINTF_USING_LONGLONG -rt_inline int divide(long long *n, int base) -#else -rt_inline int divide(long *n, int base) -#endif /* RT_KPRINTF_USING_LONGLONG */ -{ - int res; - - /* optimized for processor which does not support divide instructions. */ -#ifdef RT_KPRINTF_USING_LONGLONG - res = (int)(((unsigned long long)*n) % base); - *n = (long long)(((unsigned long long)*n) / base); -#else - res = (int)(((unsigned long)*n) % base); - *n = (long)(((unsigned long)*n) / base); -#endif - - return res; -} - -rt_inline int skip_atoi(const char **s) -{ - int i = 0; - while (_ISDIGIT(**s)) - i = i * 10 + *((*s)++) - '0'; - - return i; -} - -#define ZEROPAD (1 << 0) /* pad with zero */ -#define SIGN (1 << 1) /* unsigned/signed long */ -#define PLUS (1 << 2) /* show plus */ -#define SPACE (1 << 3) /* space if plus */ -#define LEFT (1 << 4) /* left justified */ -#define SPECIAL (1 << 5) /* 0x */ -#define LARGE (1 << 6) /* use 'ABCDEF' instead of 'abcdef' */ - -static char *print_number(char *buf, - char *end, -#ifdef RT_KPRINTF_USING_LONGLONG - long long num, -#else - long num, -#endif /* RT_KPRINTF_USING_LONGLONG */ - int base, - int s, -#ifdef RT_PRINTF_PRECISION - int precision, -#endif /* RT_PRINTF_PRECISION */ - int type) -{ - char c, sign; -#ifdef RT_KPRINTF_USING_LONGLONG - char tmp[64]; -#else - char tmp[32]; -#endif /* RT_KPRINTF_USING_LONGLONG */ - int precision_bak = precision; - const char *digits; - static const char small_digits[] = "0123456789abcdef"; - static const char large_digits[] = "0123456789ABCDEF"; - int i, size; - - size = s; - - digits = (type & LARGE) ? large_digits : small_digits; - if (type & LEFT) - type &= ~ZEROPAD; - - c = (type & ZEROPAD) ? '0' : ' '; - - /* get sign */ - sign = 0; - if (type & SIGN) - { - if (num < 0) - { - sign = '-'; - num = -num; - } - else if (type & PLUS) - sign = '+'; - else if (type & SPACE) - sign = ' '; - } - -#ifdef RT_PRINTF_SPECIAL - if (type & SPECIAL) - { - if (base == 2 || base == 16) - size -= 2; - else if (base == 8) - size--; - } -#endif /* RT_PRINTF_SPECIAL */ - - i = 0; - if (num == 0) - tmp[i++] = '0'; - else - { - while (num != 0) - tmp[i++] = digits[divide(&num, base)]; - } - -#ifdef RT_PRINTF_PRECISION - if (i > precision) - precision = i; - size -= precision; -#else - size -= i; -#endif /* RT_PRINTF_PRECISION */ - - if (!(type & (ZEROPAD | LEFT))) - { - if ((sign) && (size > 0)) - size--; - - while (size-- > 0) - { - if (buf < end) - *buf = ' '; - ++ buf; - } - } - - if (sign) - { - if (buf < end) - { - *buf = sign; - } - -- size; - ++ buf; - } - -#ifdef RT_PRINTF_SPECIAL - if (type & SPECIAL) - { - if (base == 2) - { - if (buf < end) - *buf = '0'; - ++ buf; - if (buf < end) - *buf = 'b'; - ++ buf; - } - else if (base == 8) - { - if (buf < end) - *buf = '0'; - ++ buf; - } - else if (base == 16) - { - if (buf < end) - *buf = '0'; - ++ buf; - if (buf < end) - { - *buf = type & LARGE ? 'X' : 'x'; - } - ++ buf; - } - } -#endif /* RT_PRINTF_SPECIAL */ - - /* no align to the left */ - if (!(type & LEFT)) - { - while (size-- > 0) - { - if (buf < end) - *buf = c; - ++ buf; - } - } - -#ifdef RT_PRINTF_PRECISION - while (i < precision--) - { - if (buf < end) - *buf = '0'; - ++ buf; - } -#endif /* RT_PRINTF_PRECISION */ - - /* put number in the temporary buffer */ - while (i-- > 0 && (precision_bak != 0)) - { - if (buf < end) - *buf = tmp[i]; - ++ buf; - } - - while (size-- > 0) - { - if (buf < end) - *buf = ' '; - ++ buf; - } - - return buf; -} - -/** - * This function will fill a formatted string to buffer. - * - * @param buf is the buffer to save formatted string. - * - * @param size is the size of buffer. - * - * @param fmt is the format parameters. - * - * @param args is a list of variable parameters. - * - * @return The number of characters actually written to buffer. - */ -RT_WEAK int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args) -{ -#ifdef RT_KPRINTF_USING_LONGLONG - unsigned long long num; -#else - rt_uint32_t num; -#endif /* RT_KPRINTF_USING_LONGLONG */ - int i, len; - char *str, *end, c; - const char *s; - - rt_uint8_t base; /* the base of number */ - rt_uint8_t flags; /* flags to print number */ - rt_uint8_t qualifier; /* 'h', 'l', or 'L' for integer fields */ - rt_int32_t field_width; /* width of output field */ - -#ifdef RT_PRINTF_PRECISION - int precision; /* min. # of digits for integers and max for a string */ -#endif /* RT_PRINTF_PRECISION */ - - str = buf; - end = buf + size; - - /* Make sure end is always >= buf */ - if (end < buf) - { - end = ((char *) - 1); - size = end - buf; - } - - for (; *fmt ; ++fmt) - { - if (*fmt != '%') - { - if (str < end) - *str = *fmt; - ++ str; - continue; - } - - /* process flags */ - flags = 0; - - while (1) - { - /* skips the first '%' also */ - ++ fmt; - if (*fmt == '-') flags |= LEFT; - else if (*fmt == '+') flags |= PLUS; - else if (*fmt == ' ') flags |= SPACE; - else if (*fmt == '#') flags |= SPECIAL; - else if (*fmt == '0') flags |= ZEROPAD; - else break; - } - - /* get field width */ - field_width = -1; - if (_ISDIGIT(*fmt)) field_width = skip_atoi(&fmt); - else if (*fmt == '*') - { - ++ fmt; - /* it's the next argument */ - field_width = va_arg(args, int); - if (field_width < 0) - { - field_width = -field_width; - flags |= LEFT; - } - } - -#ifdef RT_PRINTF_PRECISION - /* get the precision */ - precision = -1; - if (*fmt == '.') - { - ++ fmt; - if (_ISDIGIT(*fmt)) precision = skip_atoi(&fmt); - else if (*fmt == '*') - { - ++ fmt; - /* it's the next argument */ - precision = va_arg(args, int); - } - if (precision < 0) precision = 0; - } -#endif /* RT_PRINTF_PRECISION */ - /* get the conversion qualifier */ - qualifier = 0; -#ifdef RT_KPRINTF_USING_LONGLONG - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') -#else - if (*fmt == 'h' || *fmt == 'l') -#endif /* RT_KPRINTF_USING_LONGLONG */ - { - qualifier = *fmt; - ++ fmt; -#ifdef RT_KPRINTF_USING_LONGLONG - if (qualifier == 'l' && *fmt == 'l') - { - qualifier = 'L'; - ++ fmt; - } -#endif /* RT_KPRINTF_USING_LONGLONG */ - } - - /* the default base */ - base = 10; - - switch (*fmt) - { - case 'c': - if (!(flags & LEFT)) - { - while (--field_width > 0) - { - if (str < end) *str = ' '; - ++ str; - } - } - - /* get character */ - c = (rt_uint8_t)va_arg(args, int); - if (str < end) *str = c; - ++ str; - - /* put width */ - while (--field_width > 0) - { - if (str < end) *str = ' '; - ++ str; - } - continue; - - case 's': - s = va_arg(args, char *); - if (!s) s = "(NULL)"; - - for (len = 0; (len != field_width) && (s[len] != '\0'); len++); -#ifdef RT_PRINTF_PRECISION - if (precision > 0 && len > precision) len = precision; -#endif /* RT_PRINTF_PRECISION */ - - if (!(flags & LEFT)) - { - while (len < field_width--) - { - if (str < end) *str = ' '; - ++ str; - } - } - - for (i = 0; i < len; ++i) - { - if (str < end) *str = *s; - ++ str; - ++ s; - } - - while (len < field_width--) - { - if (str < end) *str = ' '; - ++ str; - } - continue; - - case 'p': - if (field_width == -1) - { - field_width = sizeof(void *) << 1; - flags |= ZEROPAD; - } -#ifdef RT_PRINTF_PRECISION - str = print_number(str, end, - (long)va_arg(args, void *), - 16, field_width, precision, flags); -#else - str = print_number(str, end, - (long)va_arg(args, void *), - 16, field_width, flags); -#endif /* RT_PRINTF_PRECISION */ - continue; - - case '%': - if (str < end) *str = '%'; - ++ str; - continue; - - /* integer number formats - set up the flags and "break" */ - case 'b': - base = 2; - break; - case 'o': - base = 8; - break; - - case 'X': - flags |= LARGE; - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - case 'u': - break; - - default: - if (str < end) *str = '%'; - ++ str; - - if (*fmt) - { - if (str < end) *str = *fmt; - ++ str; - } - else - { - -- fmt; - } - continue; - } - -#ifdef RT_KPRINTF_USING_LONGLONG - if (qualifier == 'L') num = va_arg(args, long long); - else if (qualifier == 'l') -#else - if (qualifier == 'l') -#endif /* RT_KPRINTF_USING_LONGLONG */ - { - num = va_arg(args, rt_uint32_t); - if (flags & SIGN) num = (rt_int32_t)num; - } - else if (qualifier == 'h') - { - num = (rt_uint16_t)va_arg(args, int); - if (flags & SIGN) num = (rt_int16_t)num; - } - else - { - num = va_arg(args, rt_uint32_t); - if (flags & SIGN) num = (rt_int32_t)num; - } -#ifdef RT_PRINTF_PRECISION - str = print_number(str, end, num, base, field_width, precision, flags); -#else - str = print_number(str, end, num, base, field_width, flags); -#endif /* RT_PRINTF_PRECISION */ - } - - if (size > 0) - { - if (str < end) *str = '\0'; - else - { - end[-1] = '\0'; - } - } - - /* the trailing null byte doesn't count towards the total - * ++str; - */ - return str - buf; -} RTM_EXPORT(rt_vsnprintf); /** diff --git a/rtconfig.h b/rtconfig.h index bcd4247..a915ab7 100644 --- a/rtconfig.h +++ b/rtconfig.h @@ -124,6 +124,7 @@ /* log format */ +#define ULOG_OUTPUT_FLOAT #define ULOG_USING_COLOR #define ULOG_OUTPUT_TIME #define ULOG_OUTPUT_LEVEL @@ -175,6 +176,8 @@ /* enhanced kernel services */ +#define PKG_USING_RT_VSNPRINTF_FULL +#define PKG_USING_RT_VSNPRINTF_FULL_LATEST_VERSION /* acceleration: Assembly language or algorithmic acceleration packages */ @@ -187,6 +190,11 @@ /* peripheral libraries and drivers */ +/* sensors drivers */ + + +/* touch drivers */ + /* Kendryte SDK */ @@ -194,6 +202,9 @@ /* AI packages */ +/* Signal Processing and Control Algorithm Packages */ + + /* miscellaneous packages */ /* project laboratory */ @@ -207,6 +218,9 @@ /* Arduino libraries */ +/* Projects */ + + /* Sensors */ @@ -216,7 +230,23 @@ /* Timing */ -/* Projects */ +/* Data Processing */ + + +/* Data Storage */ + +/* Communication */ + + +/* Device Control */ + + +/* Other */ + +/* Signal IO */ + + +/* Uncategorized */ #define SOC_FAMILY_STM32 #define SOC_SERIES_STM32F4