partition names, DCC buffers, etc

This commit is contained in:
wrapper 2025-05-24 00:09:35 +07:00
parent 94140b21c7
commit 60ca45a9e4
20 changed files with 2040 additions and 25 deletions

View file

@ -65,6 +65,7 @@
"C_Cpp_Runner.useLinkTimeOptimization": false,
"C_Cpp_Runner.msvcSecureNoWarnings": false,
"clangd.fallbackFlags": [
"-I${workspaceRoot}"
"-I${workspaceRoot}",
"-DDCC_TESTING=1"
]
}

12
crt.s
View file

@ -290,6 +290,18 @@ DN_Packet_DCC_Send:
bx lr
#endif
/* libc functions */
.global strlen
strlen:
mov r2, r0
strlen.loop:
ldrb r1, [r0], #1
tst r1, r1
bne strlen.loop
sub r0, r0, r2
sub r0, r0, #1
bx lr
/* End */
.weak ExitFunction
.weak UndefHandler, PAbortHandler, DAbortHandler

View file

@ -1,4 +1,5 @@
#include "dn_dcc_proto.h"
#include <stdint.h>
#if HAVE_MINILZO
#include "../minilzo/minilzo.h"
#endif
@ -89,8 +90,6 @@ uint32_t DN_RLE_Matching(uint8_t *src, uint32_t size) {
uint32_t offset = 0;
uint32_t count = 1;
if (size < 2) return count;
while ((offset < (size - 1)) && (count < 0x7fff) && (src[offset] == src[offset + 1])) {
wdog_reset();
count++;
@ -140,7 +139,6 @@ uint32_t DN_Packet_Compress(uint8_t *src, uint32_t size, uint8_t *dest)
dest[outOffset + 2] = src[inOffset];
inOffset += RLE_Count & 0x7fff;
outOffset += 3;
}
}
@ -340,7 +338,205 @@ void DN_Packet_Read(uint8_t *dest, uint32_t size) {
}
}
/* 04 - Utilities */
/* 04 - DCC Buffer */
#if USE_DCC_WBUF
static uint32_t temp_buf;
static uint8_t temp_buf_offset;
static uint32_t checksum;
void DN_Packet_DCC_Send_Buffer_Flush(void) {
if (!temp_buf_offset) return;
checksum = DN_Calculate_CRC32(checksum, (uint8_t *)(&temp_buf), 4);
DN_Packet_DCC_Send(temp_buf);
temp_buf = 0;
temp_buf_offset = 0;
}
void DN_Packet_DCC_Send_Buffer_Reset(void) {
temp_buf = 0;
temp_buf_offset = 0;
checksum = 0xffffffff;
}
static inline void DN_Packet_DCC_Send_Buffer8(uint8_t data) {
temp_buf |= data << (temp_buf_offset << 3);
temp_buf_offset++;
if (temp_buf_offset == 4) DN_Packet_DCC_Send_Buffer_Flush();
}
static inline void DN_Packet_DCC_Send_Buffer8_Multi(uint8_t *data, uint32_t size) {
for (uint32_t i = 0; i < size; i++) {
DN_Packet_DCC_Send_Buffer8(data[i]);
}
}
static inline void DN_Packet_DCC_Send_Buffer16(uint16_t data) {
DN_Packet_DCC_Send_Buffer8(data & 0xff);
DN_Packet_DCC_Send_Buffer8(data >> 8);
}
static inline void DN_Packet_DCC_Send_Buffer32(uint32_t data) {
DN_Packet_DCC_Send_Buffer16(data & 0xffff);
DN_Packet_DCC_Send_Buffer16(data >> 16);
}
void DN_Packet_WriteDirectCompressed(uint8_t *src, uint32_t size) {
uint32_t MAGIC = CMD_WRITE_COMP_RLE;
uint32_t SIZE;
uint32_t inOffset = 0;
uint32_t outOffset = 8;
uint16_t RLE_Count;
uint16_t RAW_Count;
uint32_t rawInOffset;
DN_Packet_DCC_Send_Buffer_Reset();
/* 01 - Compute output size */
while (inOffset < size) {
wdog_reset();
RLE_Count = DN_RLE_Matching(src + inOffset, size - inOffset);
if (RLE_Count == 1) {
RAW_Count = 0;
while (RLE_Count == 1 && inOffset < size) {
wdog_reset();
RAW_Count++;
inOffset++;
if (RAW_Count >= 0x7fff) break;
RLE_Count = DN_RLE_Matching(src + inOffset, size - inOffset);
}
outOffset += 2 + RAW_Count;
}
if (RLE_Count > 1) {
inOffset += RLE_Count;
outOffset += 3;
}
}
SIZE = outOffset - 4;
DN_Packet_DCC_Send(outOffset >> 2);
DN_Packet_DCC_Send_Buffer32(MAGIC);
DN_Packet_DCC_Send_Buffer32(SIZE);
/* 02 - Actually compress */
inOffset = 0;
while (inOffset < size) {
wdog_reset();
RLE_Count = DN_RLE_Matching(src + inOffset, size - inOffset);
if (RLE_Count == 1) {
RAW_Count = 0;
rawInOffset = inOffset;
while (RLE_Count == 1 && inOffset < size) {
wdog_reset();
RAW_Count++;
inOffset++;
if (RAW_Count >= 0x7fff) break;
RLE_Count = DN_RLE_Matching(src + inOffset, size - inOffset);
}
DN_Packet_DCC_Send_Buffer16(RAW_Count);
DN_Packet_DCC_Send_Buffer8_Multi(src + rawInOffset, RAW_Count);
}
if (RLE_Count > 1) {
DN_Packet_DCC_Send_Buffer16(RLE_Count | 0x8000);
DN_Packet_DCC_Send_Buffer8(src[inOffset]);
inOffset += RLE_Count;
}
}
DN_Packet_DCC_Send_Buffer_Flush();
DN_Packet_DCC_Send(checksum);
}
void DN_Packet_WriteDirect(uint8_t *src, uint32_t size) {
uint32_t MAGIC = CMD_WRITE_COMP_NONE;
DN_Packet_DCC_Send_Buffer_Reset();
DN_Packet_DCC_Send((size + 4) >> 2);
DN_Packet_DCC_Send_Buffer32(MAGIC);
DN_Packet_DCC_Send_Buffer8_Multi(src, size);
DN_Packet_DCC_Send_Buffer_Flush();
DN_Packet_DCC_Send(checksum);
}
#endif
static uint32_t temp_read_buf;
static uint8_t temp_read_buf_offset;
void DN_Packet_DCC_Read_Buffer_Reset(void) {
temp_read_buf = 0;
temp_read_buf_offset = 0;
}
static inline uint8_t DN_Packet_DCC_Read_Buffer8(void) {
if (!temp_read_buf_offset) temp_read_buf = DN_Packet_DCC_Read();
uint8_t temp = temp_read_buf & 0xff;
temp_read_buf >>= 8;
temp_read_buf_offset = (temp_read_buf_offset + 1) & 3;
return temp;
}
static inline uint16_t DN_Packet_DCC_Read_Buffer16(void) {
return DN_Packet_DCC_Read_Buffer8() | DN_Packet_DCC_Read_Buffer8() << 8;
}
static inline uint32_t DN_Packet_DCC_Read_Buffer32(void) {
return DN_Packet_DCC_Read_Buffer16() | DN_Packet_DCC_Read_Buffer16() << 16;
}
void DN_Packet_DCC_ReadDirectCompressed(uint8_t *dest, uint32_t size) {
uint32_t inOffset = 0;
uint32_t outOffset = 0;
DN_Packet_DCC_Read_Buffer_Reset();
while (inOffset < size) {
uint16_t flag = DN_Packet_DCC_Read_Buffer16();
uint16_t count = flag & 0x7fff;
if (flag & 0x8000) {
inOffset += 3;
uint8_t data = DN_Packet_DCC_Read_Buffer8();
do {
dest[outOffset++] = data;
} while (count--);
} else {
inOffset += 2 + count;
do {
dest[outOffset++] = DN_Packet_DCC_Read_Buffer8();
} while (count--);
}
}
}
void DN_Packet_DCC_ReadDirect(uint8_t *dest, uint32_t size) {
uint32_t inOffset = 0;
uint32_t outOffset = 0;
while (inOffset < size) {
dest[outOffset++] = DN_Packet_DCC_Read();
inOffset += 4;
}
}
/* 05 - Utilities */
uint32_t DN_Log2(uint32_t value)
{
uint32_t m = 0;

View file

@ -27,6 +27,7 @@ typedef struct {
uint32_t nor_cmd_set;
uint32_t base_offset;
MemTypes type;
char name[255];
} DCCMemory;
typedef struct {
@ -102,14 +103,14 @@ typedef struct {
#define DCC_ERASE_ERROR 0x24 // Erase error
#define DCC_PROGRAM_ERROR 0x25 // Write error
#define DCC_PROBE_ERROR 0x26 // Device probe failed
#define DCC_ASSERT_ERROR 0x27 // Ready flag timeout
#define DCC_R_ASSERT_ERROR 0x27 // Ready flag timeout during read
#define DCC_READ_ERROR 0x28 // Read error
#define DCC_W_ASSERT_ERROR 0x2A // Ready flag timeout during write
#define DCC_E_ASSERT_ERROR 0x2B // Ready flag timeout during erase
#define DCC_ROFS_ERROR 0x2D // Cannot write to read-only memory
#define DCC_E_UNK_ERROR 0x2E // Unknown erase error, Please file a bug report
#define DCC_WUPROT_TIMEOUT 0x2F // Write unprotect timeout
#define DCC_WUPROT_ERROR 0x30 // Write unprotect failed
#define DCC_WUPROT_ERROR 0x30 // Write unprotect failed, Attempted to write unprotect the block but still write protected afterwards.
#define DCC_W_UNK_ERROR 0x31 // Unknown write error, Please file a bug report
#define DCC_UNK_ERROR 0x32 // Unknown error, may happen if the flash is not completely initialized.
#define DCC_FLASH_NOENT 0x37 // Flash with this ID is not probed/not found
@ -132,6 +133,12 @@ void DN_Packet_Send(uint8_t *src, uint32_t size);
void DN_Packet_Send_One(uint32_t data);
void DN_Packet_Read(uint8_t *dest, uint32_t size);
uint32_t DN_Log2(uint32_t value);
#if USE_DCC_WBUF
void DN_Packet_WriteDirectCompressed(uint8_t *src, uint32_t size);
void DN_Packet_WriteDirect(uint8_t *src, uint32_t size);
#endif
void DN_Packet_DCC_ReadDirectCompressed(uint8_t *dest, uint32_t size);
void DN_Packet_DCC_ReadDirect(uint8_t *dest, uint32_t size);
// Watchdog
extern void wdog_reset(void);

1191
dcc/lwprintf.c Normal file

File diff suppressed because it is too large Load diff

313
dcc/lwprintf.h Normal file
View file

@ -0,0 +1,313 @@
/**
* \file lwprintf.h
* \brief Lightweight stdio manager
*/
/*
* Copyright (c) 2024 Tilen MAJERLE
*
* 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.
*
* This file is part of LwPRINTF - Lightweight stdio manager library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.6
*/
#ifndef LWPRINTF_HDR_H
#define LWPRINTF_HDR_H
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include "lwprintf_opt.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* \defgroup LWPRINTF Lightweight stdio manager
* \brief Lightweight stdio manager
* \{
*/
/**
* \brief Unused variable macro
* \param[in] x: Unused variable
*/
#define LWPRINTF_UNUSED(x) ((void)(x))
/**
* \brief Calculate size of statically allocated array
* \param[in] x: Input array
* \return Number of array elements
*/
#define LWPRINTF_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0]))
/**
* \brief Forward declaration for LwPRINTF instance
*/
struct lwprintf;
/**
* \brief Callback function for character output
* \param[in] ch: Character to print
* \param[in] lwobj: LwPRINTF instance
* \return `ch` on success, `0` to terminate further string processing
*/
typedef int (*lwprintf_output_fn)(int ch, struct lwprintf* lwobj);
/**
* \brief LwPRINTF instance
*/
typedef struct lwprintf {
lwprintf_output_fn out_fn; /*!< Output function for direct print operations */
#if LWPRINTF_CFG_OS || __DOXYGEN__
LWPRINTF_CFG_OS_MUTEX_HANDLE mutex; /*!< OS mutex handle */
#endif /* LWPRINTF_CFG_OS || __DOXYGEN__ */
} lwprintf_t;
uint8_t lwprintf_init_ex(lwprintf_t* lwobj, lwprintf_output_fn out_fn);
int lwprintf_vprintf_ex(lwprintf_t* const lwobj, const char* format, va_list arg);
int lwprintf_printf_ex(lwprintf_t* const lwobj, const char* format, ...);
int lwprintf_vsnprintf_ex(lwprintf_t* const lwobj, char* s, size_t n, const char* format, va_list arg);
int lwprintf_snprintf_ex(lwprintf_t* const lwobj, char* s, size_t n, const char* format, ...);
uint8_t lwprintf_protect_ex(lwprintf_t* const lwobj);
uint8_t lwprintf_unprotect_ex(lwprintf_t* const lwobj);
/**
* \brief Write formatted data from variable argument list to sized buffer
* \param[in,out] lwobj: LwPRINTF instance. Set to `NULL` to use default instance
* \param[in] s: Pointer to a buffer where the resulting C-string is stored.
* The buffer should have a size of at least `n` characters
* \param[in] format: C string that contains a format string that follows the same specifications as format in printf
* \param[in] ...: Optional arguments for format string
* \return The number of characters that would have been written,
* not counting the terminating null character.
*/
#define lwprintf_sprintf_ex(lwobj, s, format, ...) lwprintf_snprintf_ex((lwobj), (s), SIZE_MAX, (format), ##__VA_ARGS__)
/**
* \brief Initialize default LwPRINTF instance
* \param[in] out_fn: Output function used for print operation
* \return `1` on success, `0` otherwise
* \sa lwprintf_init_ex
*/
#define lwprintf_init(out_fn) lwprintf_init_ex(NULL, (out_fn))
/**
* \brief Print formatted data from variable argument list to the output with default LwPRINTF instance
* \param[in] format: C string that contains the text to be written to output
* \param[in] arg: A value identifying a variable arguments list initialized with `va_start`.
* `va_list` is a special type defined in `<cstdarg>`.
* \return The number of characters that would have been written if `n` had been sufficiently large,
* not counting the terminating null character.
*/
#define lwprintf_vprintf(format, arg) lwprintf_vprintf_ex(NULL, (format), (arg))
/**
* \brief Print formatted data to the output with default LwPRINTF instance
* \param[in] format: C string that contains the text to be written to output
* \param[in] ...: Optional arguments for format string
* \return The number of characters that would have been written if `n` had been sufficiently large,
* not counting the terminating null character.
*/
#define lwprintf_printf(format, ...) lwprintf_printf_ex(NULL, (format), ##__VA_ARGS__)
/**
* \brief Write formatted data from variable argument list to sized buffer with default LwPRINTF instance
* \param[in] s: Pointer to a buffer where the resulting C-string is stored.
* The buffer should have a size of at least `n` characters
* \param[in] n: 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[in] format: C string that contains a format string that follows the same specifications as format in printf
* \param[in] arg: A value identifying a variable arguments list initialized with `va_start`.
* `va_list` is a special type defined in `<cstdarg>`.
* \return The number of characters that would have been written if `n` had been sufficiently large,
* not counting the terminating null character.
*/
#define lwprintf_vsnprintf(s, n, format, arg) lwprintf_vsnprintf_ex(NULL, (s), (n), (format), (arg))
/**
* \brief Write formatted data from variable argument list to sized buffer with default LwPRINTF instance
* \param[in] s: Pointer to a buffer where the resulting C-string is stored.
* The buffer should have a size of at least `n` characters
* \param[in] n: 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[in] format: C string that contains a format string that follows the same specifications as format in printf
* \param[in] ...: Optional arguments for format string
* \return The number of characters that would have been written if `n` had been sufficiently large,
* not counting the terminating null character.
*/
#define lwprintf_snprintf(s, n, format, ...) lwprintf_snprintf_ex(NULL, (s), (n), (format), ##__VA_ARGS__)
/**
* \brief Write formatted data from variable argument list to sized buffer with default LwPRINTF instance
* \param[in] s: Pointer to a buffer where the resulting C-string is stored.
* The buffer should have a size of at least `n` characters
* \param[in] format: C string that contains a format string that follows the same specifications as format in printf
* \param[in] ...: Optional arguments for format string
* \return The number of characters that would have been written,
* not counting the terminating null character.
*/
#define lwprintf_sprintf(s, format, ...) lwprintf_sprintf_ex(NULL, (s), (format), ##__VA_ARGS__)
/**
* \brief Manually enable mutual exclusion
* \return `1` if protected, `0` otherwise
*/
#define lwprintf_protect() lwprintf_protect_ex(NULL)
/**
* \brief Manually disable mutual exclusion
* \return `1` if protected, `0` otherwise
*/
#define lwprintf_unprotect() lwprintf_unprotect_ex(NULL)
#if LWPRINTF_CFG_ENABLE_SHORTNAMES || __DOXYGEN__
/**
* \copydoc lwprintf_printf
* \note This function is equivalent to \ref lwprintf_printf
* and available only if \ref LWPRINTF_CFG_ENABLE_SHORTNAMES is enabled
*/
#define lwprintf lwprintf_printf
/**
* \copydoc lwprintf_vprintf
* \note This function is equivalent to \ref lwprintf_vprintf
* and available only if \ref LWPRINTF_CFG_ENABLE_SHORTNAMES is enabled
*/
#define lwvprintf lwprintf_vprintf
/**
* \copydoc lwprintf_vsnprintf
* \note This function is equivalent to \ref lwprintf_vsnprintf
* and available only if \ref LWPRINTF_CFG_ENABLE_SHORTNAMES is enabled
*/
#define lwvsnprintf lwprintf_vsnprintf
/**
* \copydoc lwprintf_snprintf
* \note This function is equivalent to \ref lwprintf_snprintf
* and available only if \ref LWPRINTF_CFG_ENABLE_SHORTNAMES is enabled
*/
#define lwsnprintf lwprintf_snprintf
/**
* \copydoc lwprintf_sprintf
* \note This function is equivalent to \ref lwprintf_sprintf
* and available only if \ref LWPRINTF_CFG_ENABLE_SHORTNAMES is enabled
*/
#define lwsprintf lwprintf_sprintf
#endif /* LWPRINTF_CFG_ENABLE_SHORTNAMES || __DOXYGEN__ */
#if LWPRINTF_CFG_ENABLE_STD_NAMES || __DOXYGEN__
/**
* \copydoc lwprintf_printf
* \note This function is equivalent to \ref lwprintf_printf
* and available only if \ref LWPRINTF_CFG_ENABLE_STD_NAMES is enabled
*/
#define printf lwprintf_printf
/**
* \copydoc lwprintf_vprintf
* \note This function is equivalent to \ref lwprintf_vprintf
* and available only if \ref LWPRINTF_CFG_ENABLE_STD_NAMES is enabled
*/
#define vprintf lwprintf_vprintf
/**
* \copydoc lwprintf_vsnprintf
* \note This function is equivalent to \ref lwprintf_vsnprintf
* and available only if \ref LWPRINTF_CFG_ENABLE_STD_NAMES is enabled
*/
#define vsnprintf lwprintf_vsnprintf
/**
* \copydoc lwprintf_snprintf
* \note This function is equivalent to \ref lwprintf_snprintf
* and available only if \ref LWPRINTF_CFG_ENABLE_STD_NAMES is enabled
*/
#define snprintf lwprintf_snprintf
/**
* \copydoc lwprintf_sprintf
* \note This function is equivalent to \ref lwprintf_sprintf
* and available only if \ref LWPRINTF_CFG_ENABLE_STD_NAMES is enabled
*/
#define sprintf lwprintf_sprintf
#endif /* LWPRINTF_CFG_ENABLE_STD_NAMES || __DOXYGEN__ */
/* Debug module */
#if !defined(NDEBUG)
/**
* \brief Debug output function
*
* Its purpose is to have a debug printout to the defined output,
* which will get disabled for the release build (when NDEBUG is defined).
*
* \note It calls \ref lwprintf_printf to execute the print
* \note Defined as empty when \ref NDEBUG is enabled
* \param[in] fmt: Format text
* \param[in] ...: Optional formatting parameters
*/
#define lwprintf_debug(fmt, ...) lwprintf_printf((fmt), ##__VA_ARGS__)
/**
* \brief Conditional debug output
*
* It prints the formatted text only if condition is true
*
* Its purpose is to have a debug printout to the defined output,
* which will get disabled for the release build (when NDEBUG is defined).
*
* \note It calls \ref lwprintf_debug to execute the print
* \note Defined as empty when \ref NDEBUG is enabled
* \param[in] cond: Condition to check before outputing the message
* \param[in] fmt: Format text
* \param[in] ...: Optional formatting parameters
*/
#define lwprintf_debug_cond(cond, fmt, ...) \
do { \
if ((cond)) { \
lwprintf_debug((fmt), ##__VA_ARGS__) \
} \
} while (0)
#else
#define lwprintf_debug(fmt, ...) ((void)0)
#define lwprintf_debug_cond(cond, fmt, ...) ((void)0)
#endif
/**
* \}
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LWPRINTF_HDR_H */

191
dcc/lwprintf_opt.h Normal file
View file

@ -0,0 +1,191 @@
/**
* \file lwprintf_opt.h
* \brief LwPRINTF options
*/
/*
* Copyright (c) 2024 Tilen MAJERLE
*
* 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.
*
* This file is part of LwPRINTF - Lightweight stdio manager library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.6
*/
#ifndef LWPRINTF_OPT_HDR_H
#define LWPRINTF_OPT_HDR_H
/* Uncomment to ignore user options (or set macro in compiler flags) */
/* #define LWPRINTF_IGNORE_USER_OPTS */
/* Include application options */
#ifndef LWPRINTF_IGNORE_USER_OPTS
#include "lwprintf_opts.h"
#endif /* LWPRINTF_IGNORE_USER_OPTS */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* \defgroup LWPRINTF_OPT Configuration
* \brief LwPRINTF options
* \{
*/
/**
* \brief Enables `1` or disables `0` operating system support in the library
*
* \note When `LWPRINTF_CFG_OS` is enabled, user must implement functions in \ref LWPRINTF_SYS group.
*/
#ifndef LWPRINTF_CFG_OS
#define LWPRINTF_CFG_OS 0
#endif
/**
* \brief Mutex handle type
*
* \note This value must be set in case \ref LWPRINTF_CFG_OS is set to `1`.
* If data type is not known to compiler, include header file with
* definition before you define handle type
*/
#ifndef LWPRINTF_CFG_OS_MUTEX_HANDLE
#define LWPRINTF_CFG_OS_MUTEX_HANDLE void*
#endif
/**
* \brief Enables `1` or disables `0` manual mutex lock.
*
* When this feature is enabled, together with \ref LWPRINTF_CFG_OS, behavior is as following:
* - System mutex is kept created during init phase
* - Calls to direct printing functions are not thread-safe by default anymore
* - Calls to sprintf (buffer functions) are kept thread-safe
* - User must manually call \ref lwprintf_protect or \ref lwprintf_protect_ex functions to protect direct printing operation
* - User must manually call \ref lwprintf_unprotect or \ref lwprintf_unprotect_ex functions to exit protected area
*
* \note If you prefer to completely disable locking mechanism with this library,
* turn off \ref LWPRINTF_CFG_OS and fully manually handle mutual exclusion for non-reentrant functions
*/
#ifndef LWPRINTF_CFG_OS_MANUAL_PROTECT
#define LWPRINTF_CFG_OS_MANUAL_PROTECT 0
#endif
/**
* \brief Enables `1` or disables `0` support for `long long int` type, signed or unsigned.
*
*/
#ifndef LWPRINTF_CFG_SUPPORT_LONG_LONG
#define LWPRINTF_CFG_SUPPORT_LONG_LONG 1
#endif
/**
* \brief Enables `1` or disables `0` support for any specifier accepting any kind of integer types.
* This is enabling `%d, %b, %u, %o, %i, %x` specifiers
*
*/
#ifndef LWPRINTF_CFG_SUPPORT_TYPE_INT
#define LWPRINTF_CFG_SUPPORT_TYPE_INT 1
#endif
/**
* \brief Enables `1` or disables `0` support `%p` pointer print type
*
* When enabled, architecture must support `uintptr_t` type, normally available with C11 standard
*/
#ifndef LWPRINTF_CFG_SUPPORT_TYPE_POINTER
#define LWPRINTF_CFG_SUPPORT_TYPE_POINTER 1
#endif
/**
* \brief Enables `1` or disables `0` support `%f` float type
*
*/
#ifndef LWPRINTF_CFG_SUPPORT_TYPE_FLOAT
#define LWPRINTF_CFG_SUPPORT_TYPE_FLOAT 1
#endif
/**
* \brief Enables `1` or disables `0` support for `%e` engineering output type for float numbers
*
* \note \ref LWPRINTF_CFG_SUPPORT_TYPE_FLOAT has to be enabled to use this feature
*
*/
#ifndef LWPRINTF_CFG_SUPPORT_TYPE_ENGINEERING
#define LWPRINTF_CFG_SUPPORT_TYPE_ENGINEERING 1
#endif
/**
* \brief Enables `1` or disables `0` support for `%s` for string output
*
*/
#ifndef LWPRINTF_CFG_SUPPORT_TYPE_STRING
#define LWPRINTF_CFG_SUPPORT_TYPE_STRING 1
#endif
/**
* \brief Enables `1` or disables `0` support for `%k` for hex byte array output
*
*/
#ifndef LWPRINTF_CFG_SUPPORT_TYPE_BYTE_ARRAY
#define LWPRINTF_CFG_SUPPORT_TYPE_BYTE_ARRAY 1
#endif
/**
* \brief Specifies default number of precision for floating number
*
* Represents number of digits to be used after comma if no precision
* is set with specifier itself
*
*/
#ifndef LWPRINTF_CFG_FLOAT_DEFAULT_PRECISION
#define LWPRINTF_CFG_FLOAT_DEFAULT_PRECISION 6
#endif
/**
* \brief Enables `1` or disables `0` optional short names for LwPRINTF API functions.
*
* It adds functions for default instance: `lwprintf`, `lwsnprintf` and others
*/
#ifndef LWPRINTF_CFG_ENABLE_SHORTNAMES
#define LWPRINTF_CFG_ENABLE_SHORTNAMES 1
#endif /* LWPRINTF_CFG_ENABLE_SHORTNAMES */
/**
* \brief Enables `1` or disables `0` C standard API names
*
* Disabled by default not to interfere with compiler implementation.
* Application may need to remove standard C STDIO library from linkage
* to be able to properly compile LwPRINTF with this option enabled
*/
#ifndef LWPRINTF_CFG_ENABLE_STD_NAMES
#define LWPRINTF_CFG_ENABLE_STD_NAMES 0
#endif /* LWPRINTF_CFG_ENABLE_SHORTNAMES */
/**
* \}
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LWPRINTF_OPT_HDR_H */

46
dcc/lwprintf_opts.h Normal file
View file

@ -0,0 +1,46 @@
/**
* \file lwprintf_opts_template.h
* \brief LwPRINTF configuration file
*/
/*
* Copyright (c) 2024 Tilen MAJERLE
*
* 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.
*
* This file is part of LwPRINTF - Lightweight stdio manager library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.6
*/
#ifndef LWPRINTF_OPTS_HDR_H
#define LWPRINTF_OPTS_HDR_H
/* Rename this file to "lwprintf_opts.h" for your application */
/*
* Open "include/lwprintf/lwprintf_opt.h" and
* copy & replace here settings you want to change values
*/
#define LWPRINTF_CFG_SUPPORT_TYPE_FLOAT 0
#define LWPRINTF_CFG_SUPPORT_TYPE_ENGINEERING 0
#endif /* LWPRINTF_OPTS_HDR_H */

View file

@ -1,8 +1,11 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <memory.h>
#ifdef DCC_TESTING
#include <stdio.h>
extern void WRITE_U8(uint32_t reg, uint8_t val);
extern void WRITE_U16(uint32_t reg, uint16_t val);
extern void WRITE_U32(uint32_t reg, uint32_t val);
@ -12,8 +15,10 @@ extern uint16_t READ_U16(uint32_t reg);
extern uint32_t READ_U32(uint32_t reg);
extern void *PLAT_MEMCPY(void *dest, const void *src, size_t n);
#define INT_MEMCPY memcpy
#define PLAT_SNPRINTF snprintf
#else
#include <memory.h>
#include "dcc/lwprintf.h"
#define WRITE_U8(_reg, _val) (*((volatile uint8_t *)(_reg)) = (_val))
#define WRITE_U16(_reg, _val) (*((volatile uint16_t *)(_reg)) = (_val))
@ -24,4 +29,6 @@ extern void *PLAT_MEMCPY(void *dest, const void *src, size_t n);
#define READ_U32(_reg) (*((volatile uint32_t *)(_reg)))
#define PLAT_MEMCPY memcpy
#define INT_MEMCPY memcpy
#define PLAT_SNPRINTF lwprintf_snprintf
#endif

View file

@ -99,6 +99,7 @@ def test_arm():
mu.ctl_set_exits([0])
mu.mem_map(0x00000000, 32 * 1024 * 1024)
mu.mem_map(0x12000000, 32 * 1024 * 1024)
mu.mem_map(0x03000000, 2 * 1024 * 1024)
# map 2MB memory for this emulation
@ -131,14 +132,17 @@ def test_arm():
def on_write(mu, access, address, size, value, data):
if DEBUG:
if address <= 0x14000000:
if address == 0xaaa and value == 0x98:
if (address & 0x1ffff) == 0xaaa and value == 0x98:
mu.mem_write(0x00000000, open("cfi_32mb.bin", "rb").read())
mu.mem_write(0x12000000, open("cfi_32mb.bin", "rb").read())
elif address == 0xaaa and value == 0x90:
elif (address & 0x1ffff) == 0xaaa and value == 0x90:
mu.mem_write(0x00000000, b"\x01\x00\x7e\x22")
mu.mem_write(0x12000000, b"\x01\x00\x7e\x22")
elif address == 0x0 and value == 0xf0:
elif (address & 0x1ffff) == 0x0 and value == 0xf0:
mu.mem_write(0x00000000, open("build/dumpnow.bin", "rb").read())
mu.mem_write(0x12000000, open("build/dumpnow.bin", "rb").read())
# mu.reg_write(0x)
print("Write at", hex(address), size, hex(value))
# if value == 0x98:
@ -211,9 +215,11 @@ if __name__ == '__main__':
print("H:", hex(_dcc_read_host()))
print("RUN")
_dcc_write_host(0x152 | 0x00000000)
_dcc_write_host(0x00120000)
_dcc_write_host(0x00000080)
if False:
_dcc_write_host(0x152 | 0x00000000)
_dcc_write_host(0x00120000)
_dcc_write_host(0x00000080)
while True:
while (_dcc_read_status_host() & 2) == 0: time.sleep(0.1)

12
dcc_parser.py Normal file
View file

@ -0,0 +1,12 @@
import re
import sys
if __name__ == "__main__":
o = open(sys.argv[2], "wb")
for l in open(sys.argv[1], encoding="latin-1"):
m = re.match(r'DCC OCD -> HOST 0x([0-9a-f]*)', l.rstrip())
if m is None: continue
print(m)
s = int(m[1], 16)
print(s)
o.write(s.to_bytes(4, "little"))

View file

@ -8,6 +8,7 @@
static Device devices[] = {
{&nor_cfi_controller, 0x0},
{&nor_cfi_controller, 0x12000000},
// {&nand_controller, 0x0},
{0x0, 0x0}
};

View file

@ -2,6 +2,7 @@
#include "cfi.h"
#include "dcc/dn_dcc_proto.h"
#include "dcc/plat.h"
#define CFI_READ(o, x) READ_U16(o + ((x) * 2))
#define CFI_WRITE(o, x, y) WRITE_U16(o + ((x) * 2), y)
@ -87,7 +88,7 @@ DCC_RETURN CFI_Probe(DCCMemory *mem, uint32_t offset) {
mem->manufacturer = (uint8_t)CFI_READ(offset, 0x00);
mem->device_id = CFI_READ(offset, 0x01);
uint16_t spansion_id2 = CFI_READ(offset, 0x0e);
// uint16_t spansion_id3 = CFI_READ(offset, 0x0f);
uint16_t spansion_id3 = CFI_READ(offset, 0x0f);
mem->bit_width = qry.bit_width;
mem->size = qry.size;
@ -131,6 +132,7 @@ DCC_RETURN CFI_Probe(DCCMemory *mem, uint32_t offset) {
}
} else if (mem->manufacturer == 0x01) { // Spansion
if ((mem->device_id & 0xff) == 0x7e && spansion_id2 == 0x2221 && mem->size == 0x01000000) mem->size = 0x800000;
PLAT_SNPRINTF(mem->name, 255, "0x%04x/0x%04x", spansion_id2, spansion_id3);
}
return DCC_OK;

View file

@ -2,11 +2,17 @@
#include "dcc/dn_dcc_proto.h"
#include "controller/controller.h"
void OneNAND_Ctrl_Wait_Ready(DCCMemory *mem, uint16_t flag) {
int OneNAND_Ctrl_Wait_Ready(DCCMemory *mem, uint16_t flag) {
// Busy assert routines
int timeout = 0x10000;
do {
wdog_reset();
if (timeout == 0) return 0;
timeout--;
} while ((OneNAND_Ctrl_Reg_Read(mem, O1N_REG_INTERRUPT) & flag) != flag);
return 1;
}
uint32_t OneNAND_Probe(DCCMemory *mem, uint32_t offset) {
@ -21,7 +27,7 @@ uint32_t OneNAND_Probe(DCCMemory *mem, uint32_t offset) {
OneNAND_Ctrl_Reg_Write(mem, O1N_REG_INTERRUPT, 0x0);
OneNAND_Ctrl_Reg_Write(mem, O1N_REG_COMMAND, O1N_CMD_HOT_RESET);
OneNAND_Ctrl_Wait_Ready(mem, 0x8000);
if (!OneNAND_Ctrl_Wait_Ready(mem, 0x8000)) return DCC_PROBE_ERROR;
uint16_t mfr_id = OneNAND_Ctrl_Reg_Read(mem, O1N_REG_MANUFACTURER_ID);
uint16_t dev_id = OneNAND_Ctrl_Reg_Read(mem, O1N_REG_DEVICE_ID);
@ -34,7 +40,7 @@ uint32_t OneNAND_Probe(DCCMemory *mem, uint32_t offset) {
uint32_t density = 2 << ((mem->page_size == 4096 ? 4 : 3) + ((dev_id >> 4) & 0xf));
mem->size = density << 20;
mem->block_size = mem->page_size * 0x40;
mem->block_size = mem->page_size << 6;
return DCC_OK;
}
@ -55,7 +61,7 @@ uint32_t OneNAND_Read_Upper(DCCMemory *mem, uint8_t *page_buf, uint8_t *spare_bu
OneNAND_Ctrl_Reg_Write(mem, O1N_REG_START_ADDRESS8, (page & 63) << 2);
OneNAND_Ctrl_Reg_Write(mem, O1N_REG_COMMAND, O1N_CMD_READ);
OneNAND_Ctrl_Wait_Ready(mem, 0x8080);
if (!OneNAND_Ctrl_Wait_Ready(mem, 0x8080)) return DCC_R_ASSERT_ERROR;
OneNAND_Ctrl_Get_Data(mem, page_buf, spare_buf, mem->page_size, mem->page_size >> 5);
return DCC_OK;

BIN
has/msm6050_8mb.has Normal file

Binary file not shown.

26
main.c
View file

@ -1,5 +1,5 @@
#include "dcc/dn_dcc_proto.h"
#include "flash/cfi/cfi.h"
#include "dcc/plat.h"
#include "devices.h"
typedef DCC_RETURN DCC_INIT_PTR(DCCMemory *mem, uint32_t offset);
@ -14,6 +14,8 @@ void *absolute_to_relative(void* ptr) { return ptr; };
extern void *absolute_to_relative(void *ptr);
#endif
size_t strlen(const char *str);
// dcc code
void dcc_main(uint32_t StartAddress, uint32_t PageSize) {
DCCMemory mem[16] = { 0 };
@ -36,12 +38,33 @@ void dcc_main(uint32_t StartAddress, uint32_t PageSize) {
ext_mem = DCC_MEM_EXTENDED(1, mem[i].page_size, mem[i].block_size, mem[i].size >> 20);
mem_has_spare[i] = 0;
WRITE_EXTMEM:
if (strlen(mem[i].name)) ext_mem |= 0x80;
BUF_INIT[dcc_init_offset++] = DCC_MEM_OK | (ext_mem << 16);
BUF_INIT[dcc_init_offset++] = mem[i].manufacturer | (mem[i].device_id << 16);
if (strlen(mem[i].name)) {
int sLen = strlen(mem[i].name);
uint8_t *bufCast = (uint8_t *)BUF_INIT;
// int sPos = 0;
// uint8_t *sData = (uint8_t *)(BUF_INIT + dcc_init_offset);
// BUF_INIT[dcc_init_offset++] = sLen;
// for (int j = 0; j < sLen; j++) {
// BUF_INIT[dcc_init_offset++] = mem[i].name[j];
// }
BUF_INIT[dcc_init_offset] = sLen;
INT_MEMCPY((bufCast + (dcc_init_offset << 2) + 1), mem[i].name, sLen);
dcc_init_offset += ALIGN4(1 + sLen) >> 2;
}
BUF_INIT[dcc_init_offset++] = ext_mem;
break;
case MEMTYPE_NAND:
if (strlen(mem[i].name)) goto NAND_EXTMEM;
BUF_INIT[dcc_init_offset++] = DCC_MEM_OK | (mem[i].page_size << 16);
BUF_INIT[dcc_init_offset++] = mem[i].manufacturer | (mem[i].device_id << 16);
mem_has_spare[i] = 1;
@ -50,6 +73,7 @@ void dcc_main(uint32_t StartAddress, uint32_t PageSize) {
case MEMTYPE_ONENAND:
case MEMTYPE_AND:
case MEMTYPE_AG_AND:
NAND_EXTMEM:
ext_mem = DCC_MEM_EXTENDED(0, mem[i].page_size, mem[i].block_size, mem[i].size >> 20);
mem_has_spare[i] = 1;
goto WRITE_EXTMEM;

View file

@ -1,4 +1,4 @@
@echo off
clang -I . -DDCC_TESTING -DHAVE_MINILZO=1 -DHAVE_LZ4=1 -D_CRT_SECURE_NO_WARNINGS=1 test/test_rle_compress.c dcc/dn_dcc_proto.c minilzo/minilzo.c lz4/lz4_fs.c plat/default.c -o dcc_test_rle.exe
clang -I . -DDCC_TESTING -DHAVE_MINILZO=1 -DHAVE_LZ4=1 -D_CRT_SECURE_NO_WARNINGS=1 test/test_dcc_writing_reading.c dcc/dn_dcc_proto.c minilzo/minilzo.c lz4/lz4_fs.c plat/default.c -o dcc_test_wr.exe
clang -I . -DDCC_TESTING -DHAVE_MINILZO=1 -DHAVE_LZ4=1 -D_CRT_SECURE_NO_WARNINGS=1 test/test_dcc_emulate.c test/test_dcc_platform.c main.c dcc/dn_dcc_proto.c dcc/bitutils.c minilzo/minilzo.c lz4/lz4_fs.c plat/default.c flash/cfi/cfi.c flash/mmap/mmap.c -o dcc_test_emu.exe
clang -I . -DDCC_TESTING -DHAVE_MINILZO=1 -DHAVE_LZ4=1 -D_CRT_SECURE_NO_WARNINGS=1 test/test_dcc_emulate.c test/test_dcc_platform.c main.c dcc/dn_dcc_proto.c dcc/bitutils.c dcc/lwprintf.c minilzo/minilzo.c lz4/lz4_fs.c plat/default.c flash/cfi/cfi.c flash/mmap/mmap.c -o dcc_test_emu.exe

View file

@ -1,4 +1,4 @@
#!/bin/bash
clang -I . -DDCC_TESTING -DHAVE_MINILZO=1 -DHAVE_LZ4=1 -D_CRT_SECURE_NO_WARNINGS=1 test/test_rle_compress.c dcc/dn_dcc_proto.c minilzo/minilzo.c lz4/lz4_fs.c plat/default.c -o dcc_test_rle
clang -I . -DDCC_TESTING -DHAVE_MINILZO=1 -DHAVE_LZ4=1 -D_CRT_SECURE_NO_WARNINGS=1 test/test_dcc_writing_reading.c dcc/dn_dcc_proto.c minilzo/minilzo.c lz4/lz4_fs.c plat/default.c -o dcc_test_wr
clang -I . -DDCC_TESTING -DHAVE_MINILZO=1 -DHAVE_LZ4=1 -D_CRT_SECURE_NO_WARNINGS=1 test/test_dcc_emulate.c test/test_dcc_platform.c main.c dcc/dn_dcc_proto.c dcc/bitutils.c minilzo/minilzo.c lz4/lz4_fs.c plat/default.c flash/cfi/cfi.c flash/mmap/mmap.c -o dcc_test_emu
clang -I . -DDCC_TESTING -DHAVE_MINILZO=1 -DHAVE_LZ4=1 -D_CRT_SECURE_NO_WARNINGS=1 test/test_dcc_emulate.c test/test_dcc_platform.c main.c dcc/dn_dcc_proto.c dcc/bitutils.c dcc/lwprintf.c minilzo/minilzo.c lz4/lz4_fs.c plat/default.c flash/cfi/cfi.c flash/mmap/mmap.c -o dcc_test_emu

View file

@ -117,7 +117,7 @@ DADEFS += -DUSE_BREAKPOINTS=0
DDEFS += -DUSE_BREAKPOINTS=0
endif
SRC = main.c dcc/memory.c dcc/dn_dcc_proto.c dcc/bitutils.c plat/$(PLATFORM).c $(DEVICES) $(CONTROLLERS) $(ADD_DEPS)
SRC = main.c dcc/memory.c dcc/dn_dcc_proto.c dcc/bitutils.c dcc/lwprintf.c plat/$(PLATFORM).c $(DEVICES) $(CONTROLLERS) $(ADD_DEPS)
# List ASM source files here
ASRC = crt.s
@ -149,7 +149,7 @@ MCFLAGS = -mcpu=$(MCU)
ASFLAGS = $(MCFLAGS) -g -gdwarf-2 -Wa,-amhls=$(<:.s=.lst) $(ADEFS) -c
CPFLAGS = $(MCFLAGS) -fPIC -fPIE -I . $(OPT) -gdwarf-2 -mthumb-interwork -fomit-frame-pointer -Wall -Wstrict-prototypes -fverbose-asm -Wa,-ahlms=$(<:.c=.lst) $(DEFS) -c
LDFLAGS = $(MCFLAGS) -fPIC -fPIE -nostartfiles -nostdlib -T$(LDSCRIPT) -Wl,-Map=build/$(PROJECT).map,--cref,--no-warn-mismatch $(LIBDIR)
LDFLAGS = $(MCFLAGS) -fPIC -fPIE -nostartfiles -T$(LDSCRIPT) -Wl,-Map=build/$(PROJECT).map,--cref,--no-warn-mismatch $(LIBDIR)
# Generate dependency information
#CPFLAGS += -MD -MP -MF .dep/$(@F).d

View file

@ -4,7 +4,7 @@
#include <stdio.h>
#define MEMORY_BASE_OFFSET 0x0
#define CFI_TYPE 4
#define CFI_TYPE 2
#if CFI_TYPE == 2 // S71WS256P
#define CFI_MFR_ID 0x01