新增所有文件

This commit is contained in:
2025-10-25 21:11:06 +08:00
parent 8cc4755d15
commit 3134504178
8414 changed files with 2995287 additions and 5 deletions

View File

@@ -0,0 +1,157 @@
/*
* console.c
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: console function.
*
* Revision History:
* -----------------
*/
#include <CLI.h>
#include <debug.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "FreeRTOS_CLI.h"
/* BS and DEL ASCII Number */
#define CLI_ASCII_BS 0x08
#define CLI_ASCII_DEL 0x7F
/* Command Buffer */
#define CLI_INPUT_BUFFER_SIZE 64
#define CLI_OUTPUT_BUFFER_SIZE 1024
static char gcInputBuffer[CLI_INPUT_BUFFER_SIZE];
static char gcOutputBuffer[CLI_OUTPUT_BUFFER_SIZE];
static uint8_t gucInputIndex;
/* a linear array of statically defined command blocks,
defined in the linker script.
*/
extern CLI_Command_Definition_t __commands_start[];
extern CLI_Command_Definition_t __commands_end[];
/* Const messages output by the command console. */
static const char *const gpcWelcomeMessage =
"\r\nFreeRTOS CLI.\r\nType Help to view a list of registered "
"commands.\r\n>";
static const char *const gpcNewLine = "\r\n>";
static const char *const gpcErrMessage = "\r\nInput Command Error\r\n>";
/*
* Register CLI commands.
*/
static void CLIRegisterCommands(void)
{
CLI_Command_Definition_t *cmd;
for (cmd = __commands_start; cmd != __commands_end; cmd++) {
CLIRegisterCommand(cmd);
}
}
/*
* console task entry.
*
* @ arg input param.
*/
void CLICommandHandler(char cRxedChar)
{
int xReturned;
/* Is end of the line? */
if (cRxedChar == '\n' || cRxedChar == '\r') {
/* Start New Line */
CLIWriteData(gpcNewLine, strlen(gpcNewLine));
if (gucInputIndex) {
gcInputBuffer[gucInputIndex] = '\0';
do {
gcOutputBuffer[0] = '\0';
/* Get the next output string from the command interpreter. */
xReturned = CLIProcessCommand(gcInputBuffer, gcOutputBuffer,
CLI_OUTPUT_BUFFER_SIZE);
/* Write the generated string to the UART. */
CLIWriteData(gcOutputBuffer, strlen(gcOutputBuffer));
CLIWriteData(gpcNewLine, strlen(gpcNewLine));
} while (xReturned != CLI_FALSE);
gucInputIndex = 0;
}
} else if ((cRxedChar == CLI_ASCII_BS) || (cRxedChar == CLI_ASCII_DEL)) {
/* Backspace was pressed. Erase the last character in the
string - if any. */
if (gucInputIndex > 0) {
gucInputIndex--;
gcInputBuffer[gucInputIndex] = '\0';
char bs = CLI_ASCII_BS;
char space = ' ';
CLIWriteData(&bs, 1);
CLIWriteData(&space, 1);
CLIWriteData(&bs, 1);
}
} else {
/* echo */
CLIWriteData(&cRxedChar, 1);
if (gucInputIndex < CLI_INPUT_BUFFER_SIZE) {
gcInputBuffer[gucInputIndex] = cRxedChar;
gucInputIndex++;
} else {
CLIWriteData(gpcErrMessage, strlen(gpcErrMessage));
gucInputIndex = 0;
}
}
}
/*
* Tokenize Command.
*
* @ pcCommandString input string.
* @ argv argv array.
*/
int CLITokenizeCommand(const char *pcCommandString, char *argv[])
{
int arg_num = 0;
int arg_len = 0;
char *arg_ptr = (char *)pcCommandString;
/* Index the character pointer past the current word. If this is the start
of the command string then the first word is the command itself. */
while (((*arg_ptr) != 0x00) && ((*arg_ptr) != ' ')) {
arg_ptr++;
}
while ((arg_ptr = (char *)CLIGetParameter(arg_ptr, 1, &arg_len)) != NULL) {
argv[arg_num++] = arg_ptr;
arg_ptr += arg_len;
if (*arg_ptr == ' ') {
*arg_ptr = '\0';
arg_ptr++;
}
if (arg_num >= CLI_MAX_ARGS) {
ssdk_printf(SSDK_WARNING, "CLI command extend max args num\n");
break;
}
}
return arg_num;
}
/*
* CLI Init.
*
* @ pcCommandString input string.
* @ argv argv array.
*/
int CLIInit(void)
{
CLIRegisterCommands();
CLIWriteData(gpcWelcomeMessage, strlen(gpcWelcomeMessage));
return 0;
}

View File

@@ -0,0 +1,273 @@
/*
* FreeRTOS+CLI V1.0.4
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* Standard includes. */
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <debug.h>
/* Utils includes. */
#include <CLI.h>
#include "FreeRTOS_CLI.h"
/*
* The callback function that is executed when "help" is entered. This is the
* only default command that is always present.
*/
static int prvHelpCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/*
* Return the number of parameters that follow the command name.
*/
static int8_t prvGetNumberOfParameters( const char *pcCommandString );
/* The definition of the "help" command. This command is always at the front
of the list of registered commands. */
static CLI_Command_Definition_t xHelpCommand =
{
"help",
"\r\nhelp:\r\n Lists all the registered commands\r\n\r\n",
prvHelpCommand,
NULL,
};
/*-----------------------------------------------------------*/
int CLIRegisterCommand( CLI_Command_Definition_t *pxCommandToRegister )
{
static CLI_Command_Definition_t *pxLastCommandInList = &xHelpCommand;
CLI_Command_Definition_t *pxNewListItem;
/* Check the parameter is not NULL. */
ASSERT( pxCommandToRegister );
pxNewListItem = pxCommandToRegister;
CLI_ENTER_CRITICAL()
{
/* The new list item will get added to the end of the list, so
pxNext has nowhere to point. */
pxNewListItem->pxNext = NULL;
/* Add the newly created list item to the end of the already existing
list. */
pxLastCommandInList->pxNext = pxNewListItem;
/* Set the end of list marker to the new list item. */
pxLastCommandInList = pxNewListItem;
}
CLI_EXIT_CRITICAL()
return CLI_TRUE;
}
/*-----------------------------------------------------------*/
int CLIProcessCommand( const char * const pcCommandInput, char * pcWriteBuffer, size_t xWriteBufferLen )
{
static const CLI_Command_Definition_t *pxCommand = NULL;
int xReturn = CLI_TRUE;
const char *pcRegisteredCommandString;
size_t xCommandStringLength;
/* Note: This function is not re-entrant. It must not be called from more
thank one task. */
if( pxCommand == NULL )
{
/* Search for the command string in the list of registered commands. */
for( pxCommand = &xHelpCommand; pxCommand != NULL; pxCommand = pxCommand->pxNext )
{
pcRegisteredCommandString = pxCommand->pcCommand;
xCommandStringLength = strlen( pcRegisteredCommandString );
/* To ensure the string lengths match exactly, so as not to pick up
a sub-string of a longer command, check the byte after the expected
end of the string is either the end of the string or a space before
a parameter. */
if( ( pcCommandInput[ xCommandStringLength ] == ' ' ) || ( pcCommandInput[ xCommandStringLength ] == 0x00 ) )
{
if( strncmp( pcCommandInput, pcRegisteredCommandString, xCommandStringLength ) == 0 )
{
break;
}
}
}
}
if( ( pxCommand != NULL ) && ( xReturn == CLI_FALSE ) )
{
/* The command was found, but the number of parameters with the command
was incorrect. */
strncpy( pcWriteBuffer, "Incorrect command parameter(s). Enter \"help\" to view a list of available commands.\r\n\r\n", xWriteBufferLen );
pxCommand = NULL;
}
else if( pxCommand != NULL )
{
/* Call the callback function that is registered to this command. */
xReturn = pxCommand->pxCommandInterpreter( pcWriteBuffer, xWriteBufferLen, pcCommandInput );
/* If xReturn is CLI_FALSE, then no further strings will be returned
after this one, and pxCommand can be reset to NULL ready to search
for the next entered command. */
if( xReturn == CLI_FALSE )
{
pxCommand = NULL;
}
}
else
{
/* pxCommand was NULL, the command was not found. */
strncpy( pcWriteBuffer, "Command not recognised. Enter 'help' to view a list of available commands.\r\n\r\n", xWriteBufferLen );
xReturn = CLI_FALSE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
const char *CLIGetParameter( const char *pcCommandString, uint32_t uxWantedParameter, int *pxParameterStringLength )
{
uint32_t uxParametersFound = 0;
const char *pcReturn = NULL;
*pxParameterStringLength = 0;
while( uxParametersFound < uxWantedParameter )
{
/* Find the start of the next string. */
while( ( ( *pcCommandString ) != 0x00 ) && ( ( *pcCommandString ) == ' ' ) )
{
pcCommandString++;
}
/* Was a string found? */
if( *pcCommandString != 0x00 )
{
/* Is this the start of the required parameter? */
uxParametersFound++;
if( uxParametersFound == uxWantedParameter )
{
/* How long is the parameter? */
pcReturn = pcCommandString;
while( ( ( *pcCommandString ) != 0x00 ) && ( ( *pcCommandString ) != ' ' ) )
{
( *pxParameterStringLength )++;
pcCommandString++;
}
if( *pxParameterStringLength == 0 )
{
pcReturn = NULL;
}
break;
}
}
else
{
break;
}
}
return pcReturn;
}
/*-----------------------------------------------------------*/
static int prvHelpCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
static const CLI_Command_Definition_t * pxCommand = NULL;
int xReturn;
( void ) pcCommandString;
if( pxCommand == NULL )
{
/* Reset the pxCommand pointer back to the start of the list. */
pxCommand = &xHelpCommand;
}
/* Return the next command help string, before moving the pointer on to
the next command in the list. */
strncpy( pcWriteBuffer, pxCommand->pcHelpString, xWriteBufferLen );
pxCommand = pxCommand->pxNext;
if( pxCommand == NULL )
{
/* There are no more commands in the list, so there will be no more
strings to return after this one and CLI_FALSE should be returned. */
xReturn = CLI_FALSE;
}
else
{
xReturn = CLI_TRUE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
static int8_t prvGetNumberOfParameters( const char *pcCommandString )
{
int8_t cParameters = 0;
int xLastCharacterWasSpace = CLI_FALSE;
/* Count the number of space delimited words in pcCommandString. */
while( *pcCommandString != 0x00 )
{
if( ( *pcCommandString ) == ' ' )
{
if( xLastCharacterWasSpace != CLI_TRUE )
{
cParameters++;
xLastCharacterWasSpace = CLI_TRUE;
}
}
else
{
xLastCharacterWasSpace = CLI_FALSE;
}
pcCommandString++;
}
/* If the command string ended with spaces, then there will have been too
many parameters counted. */
if( xLastCharacterWasSpace == CLI_TRUE )
{
cParameters--;
}
/* The value returned is one less than the number of space delimited words,
as the first word should be the command itself. */
return cParameters;
}

View File

@@ -0,0 +1,67 @@
/*
* FreeRTOS+CLI V1.0.4
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CLI_H_
#define FREERTOS_CLI_H_
#if CONFIG_OS
#include "portmacro.h"
#define CLI_ENTER_CRITICAL() portENTER_CRITICAL()
#define CLI_EXIT_CRITICAL() portEXIT_CRITICAL()
#else
#define CLI_ENTER_CRITICAL()
#define CLI_EXIT_CRITICAL()
#endif
/*
* Register the command passed in using the pxCommandToRegister parameter.
* Registering a command adds the command to the list of commands that are
* handled by the command interpreter. Once a command has been registered it
* can be executed from the command line.
*/
int CLIRegisterCommand( CLI_Command_Definition_t * pxCommandToRegister );
/*
* Runs the command interpreter for the command string "pcCommandInput". Any
* output generated by running the command will be placed into pcWriteBuffer.
* xWriteBufferLen must indicate the size, in bytes, of the buffer pointed to
* by pcWriteBuffer.
*
* CLIProcessCommand should be called repeatedly until it returns pdFALSE.
*
* pcCmdIntProcessCommand is not reentrant. It must not be called from more
* than one task - or at least - by more than one task at a time.
*/
int CLIProcessCommand( const char * const pcCommandInput, char * pcWriteBuffer, size_t xWriteBufferLen );
/*
* Return a pointer to the xParameterNumber'th word in pcCommandString.
*/
const char *CLIGetParameter( const char *pcCommandString, uint32_t uxWantedParameter, int *pxParameterStringLength );
#endif /* FREERTOS_CLI_H_ */

View File

@@ -0,0 +1,32 @@
Changes between V1.0.3 and V1.0.4 released
+ Update to use stdint and the FreeRTOS specific typedefs that were
introduced in FreeRTOS V8.0.0.
Changes between V1.0.2 and V1.0.3 released
+ Previously, and in line with good software engineering practice, the
FreeRTOS coding standard did not permit the use of char types that were
not explicitly qualified as either signed or unsigned. As a result char
pointers used to reference strings required casts, as did the use of any
standard string handling functions. The casts ensured compiler warnings
were not generated by compilers that defaulted unqualified char types to
be signed or compilers that defaulted unqualified char types to be
unsigned. As it has in later MISRA standards, this rule has now been
relaxed, and unqualified char types are now permitted, but only when:
1) The char is used to point to a human readable text string.
2) The char is used to hold a single ASCII character.
Changes between V1.0.1 and V1.0.2 released 14/10/2013
+ Changed double quotes (") to single quotes (') in the help string to
allow the strings to be used with JSON in FreeRTOS+Nabto.
Changes between V1.0.0 and V1.0.1 released 05/07/2012
+ Change the name of the structure used to map a function that implements
a CLI command to the string used to call the command from
xCommandLineInput to CLI_Command_Definition_t, as it was always intended
to be. A #define was added to map the old name to the new name for
reasons of backward compatibility.

View File

@@ -0,0 +1,19 @@
FreeRTOS+CLI is released under the following MIT license.
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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.

View File

@@ -0,0 +1,5 @@
[InternetShortcut]
URL=http://www.freertos.org/cli
IDList=
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2

View File

@@ -0,0 +1,88 @@
/*
* FreeRTOS+CLI V1.0.4
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef CLI_H_
#define CLI_H_
#include <compiler.h>
#include <types.h>
#define CLI_FALSE ( ( int ) 0 )
#define CLI_TRUE ( ( int ) 1 )
#define CLI_MAX_ARGS 16
/* The prototype to which callback functions used to process command line
commands must comply. pcWriteBuffer is a buffer into which the output from
executing the command can be written, xWriteBufferLen is the length, in bytes of
the pcWriteBuffer buffer, and pcCommandString is the entire string as input by
the user (from which parameters can be extracted).*/
typedef int (*pdCOMMAND_LINE_CALLBACK)( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
/* The structure that defines command line commands. A command line command
should be defined by declaring a const structure of this type. */
typedef struct xCOMMAND_LINE_INPUT
{
const char * const pcCommand; /* The command that causes pxCommandInterpreter to be executed. For example "help". Must be all lower case. */
const char * const pcHelpString; /* String that describes how to use the command. Should start with the command itself, and end with "\r\n". For example "help: Returns a list of all the commands\r\n". */
const pdCOMMAND_LINE_CALLBACK pxCommandInterpreter; /* A pointer to the callback function that will return the output generated by the command. */
struct xCOMMAND_LINE_INPUT *pxNext; /* next command */
} CLI_Command_Definition_t;
/* For backward compatibility. */
#define xCommandLineInput CLI_Command_Definition_t
extern int CLITokenizeCommand(const char *pcCommandString, char *argv[]);
typedef int (*CLI_CMD_CALLBACK)(int argc, char *argv[]);
#define CLI_CMD(name, help, func) \
int _cli_inter_##func (char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) \
{ \
int argc = 0; \
char *argv[CLI_MAX_ARGS]; \
argc = CLITokenizeCommand(pcCommandString, argv); \
return func(argc, argv); \
} \
__USED const CLI_Command_Definition_t _cli_cmd_##func __SECTION(".commands") = \
{ name, help, _cli_inter_##func, NULL}
/*
* Init CLI, register CLI commands.
*/
int CLIInit(void);
/*
* CLI Write Data.
*/
void CLIWriteData(const char *data, size_t len);
/*
* console command handler entry.
*/
void CLICommandHandler(char cRxedChar);
#endif /* CLI_H_ */

View File

@@ -0,0 +1,4 @@
Contains source and header files that implement FreeRTOS+CLI. See
http://www.FreeRTOS.org/cli for documentation and license information.

443
middleware/checksum/crc32.c Normal file
View File

@@ -0,0 +1,443 @@
/**
* @file crc32.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:compute the CRC-32 of a data stream
*
* Revision History:
* -----------------
*/
/*
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
protection on the static variables used to control the first-use generation
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
first call get_crc_table() to initialize the tables before allowing more than
one thread to use crc32().
DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32_data.h.
*/
#ifdef MAKECRCH
#include <stdio.h>
#ifndef DYNAMIC_CRC_TABLE
#define DYNAMIC_CRC_TABLE
#endif /* !DYNAMIC_CRC_TABLE */
#endif /* MAKECRCH */
#include "zutil.h" /* for STDC and FAR definitions */
#define local static
/* Definitions for doing the crc four data bytes at a time. */
#if !defined(NOBYFOUR) && defined(Z_U4)
#error
#define BYFOUR
#endif
#ifdef BYFOUR
local unsigned long crc32_little OF((unsigned long, const unsigned char FAR *,
unsigned));
local unsigned long crc32_big OF((unsigned long, const unsigned char FAR *,
unsigned));
#define TBLS 8
#else
#define TBLS 1
#endif /* BYFOUR */
/* Local functions for crc concatenation */
local unsigned long gf2_matrix_times OF((unsigned long *mat,
unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
#ifdef DYNAMIC_CRC_TABLE
local volatile int crc_table_empty = 1;
local z_crc_t FAR crc_table[TBLS][256];
local void make_crc_table OF((void));
#ifdef MAKECRCH
local void write_table OF((FILE *, const z_crc_t FAR *));
#endif /* MAKECRCH */
/*
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
Polynomials over GF(2) are represented in binary, one bit per coefficient,
with the lowest powers in the most significant bit. Then adding polynomials
is just exclusive-or, and multiplying a polynomial by x is a right shift by
one. If we call the above polynomial p, and represent a byte as the
polynomial q, also with the lowest power in the most significant bit (so the
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
where a mod b means the remainder after dividing a by b.
This calculation is done using the shift-register method of multiplying and
taking the remainder. The register is initialized to zero, and for each
incoming bit, x^32 is added mod p to the register if the bit is a one (where
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
x (which is shifting right by one and adding x^32 mod p if the bit shifted
out is a one). We start with the highest power (least significant bit) of
q and repeat for all eight bits of q.
The first table is simply the CRC of all possible eight bit values. This is
all the information needed to generate CRCs on data a byte at a time for all
combinations of CRC register values and incoming bytes. The remaining tables
allow for word-at-a-time CRC calculation for both big-endian and little-
endian machines, where a word is four bytes.
*/
local void make_crc_table()
{
z_crc_t c;
int n, k;
z_crc_t poly; /* polynomial exclusive-or pattern */
/* terms of polynomial defining this crc (except x^32): */
static volatile int first = 1; /* flag to limit concurrent making */
static const unsigned char p[] = {0, 1, 2, 4, 5, 7, 8,
10, 11, 12, 16, 22, 23, 26};
/* See if another task is already doing this (not thread-safe, but better
than nothing -- significantly reduces duration of vulnerability in
case the advice about DYNAMIC_CRC_TABLE is ignored) */
if (first) {
first = 0;
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
poly = 0;
for (n = 0; n < (int)(sizeof(p) / sizeof(unsigned char)); n++)
poly |= (z_crc_t)1 << (31 - p[n]);
/* generate a crc for every 8-bit value */
for (n = 0; n < 256; n++) {
c = (z_crc_t)n;
for (k = 0; k < 8; k++)
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
crc_table[0][n] = c;
}
#ifdef BYFOUR
/* generate crc for each value followed by one, two, and three zeros,
and then the byte reversal of those as well as the first table */
for (n = 0; n < 256; n++) {
c = crc_table[0][n];
crc_table[4][n] = ZSWAP32(c);
for (k = 1; k < 4; k++) {
c = crc_table[0][c & 0xff] ^ (c >> 8);
crc_table[k][n] = c;
crc_table[k + 4][n] = ZSWAP32(c);
}
}
#endif /* BYFOUR */
crc_table_empty = 0;
} else { /* not first */
/* wait for the other guy to finish (not efficient, but rare) */
while (crc_table_empty)
;
}
#ifdef MAKECRCH
/* write out CRC tables to crc32_data.h */
{
FILE *out;
out = fopen("crc32_data.h", "w");
if (out == NULL)
return;
fprintf(out, "/* crc32_data.h -- tables for rapid CRC calculation\n");
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
fprintf(out, "local const z_crc_t FAR ");
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
write_table(out, crc_table[0]);
#ifdef BYFOUR
fprintf(out, "#ifdef BYFOUR\n");
for (k = 1; k < 8; k++) {
fprintf(out, " },\n {\n");
write_table(out, crc_table[k]);
}
fprintf(out, "#endif\n");
#endif /* BYFOUR */
fprintf(out, " }\n};\n");
fclose(out);
}
#endif /* MAKECRCH */
}
#ifdef MAKECRCH
local void write_table(out, table) FILE *out;
const z_crc_t FAR *table;
{
int n;
for (n = 0; n < 256; n++)
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
(unsigned long)(table[n]),
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
}
#endif /* MAKECRCH */
#else /* !DYNAMIC_CRC_TABLE */
/*
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
*/
#include "crc32_data.h"
#endif /* DYNAMIC_CRC_TABLE */
/*
* This function can be used by asm versions of crc32()
*/
const z_crc_t FAR *ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
return (const z_crc_t FAR *)crc_table;
}
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
#define DO8 \
DO1; \
DO1; \
DO1; \
DO1; \
DO1; \
DO1; \
DO1; \
DO1
unsigned long ZEXPORT crc32(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
uInt len;
{
if (buf == Z_NULL)
return 0UL;
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
#ifdef BYFOUR
if (sizeof(void *) == sizeof(ptrdiff_t)) {
z_crc_t endian;
endian = 1;
if (*((unsigned char *)(&endian)))
return crc32_little(crc, buf, len);
else
return crc32_big(crc, buf, len);
}
#endif /* BYFOUR */
crc = crc ^ 0xffffffffUL;
while (len >= 8) {
DO8;
len -= 8;
}
if (len)
do {
DO1;
} while (--len);
return crc ^ 0xffffffffUL;
}
#ifdef BYFOUR
#define DOLIT4 \
c ^= *buf4++; \
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
#define DOLIT32 \
DOLIT4; \
DOLIT4; \
DOLIT4; \
DOLIT4; \
DOLIT4; \
DOLIT4; \
DOLIT4; \
DOLIT4
local unsigned long crc32_little(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
register z_crc_t c;
register const z_crc_t FAR *buf4;
c = (z_crc_t)crc;
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
len--;
}
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
while (len >= 32) {
DOLIT32;
len -= 32;
}
while (len >= 4) {
DOLIT4;
len -= 4;
}
buf = (const unsigned char FAR *)buf4;
if (len)
do {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
} while (--len);
c = ~c;
return (unsigned long)c;
}
#define DOBIG4 \
c ^= *++buf4; \
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
#define DOBIG32 \
DOBIG4; \
DOBIG4; \
DOBIG4; \
DOBIG4; \
DOBIG4; \
DOBIG4; \
DOBIG4; \
DOBIG4
local unsigned long crc32_big(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
register z_crc_t c;
register const z_crc_t FAR *buf4;
c = ZSWAP32((z_crc_t)crc);
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
len--;
}
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
buf4--;
while (len >= 32) {
DOBIG32;
len -= 32;
}
while (len >= 4) {
DOBIG4;
len -= 4;
}
buf4++;
buf = (const unsigned char FAR *)buf4;
if (len)
do {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
} while (--len);
c = ~c;
return (unsigned long)(ZSWAP32(c));
}
#endif /* BYFOUR */
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
local unsigned long gf2_matrix_times(mat, vec)
unsigned long *mat;
unsigned long vec;
{
unsigned long sum;
sum = 0;
while (vec) {
if (vec & 1)
sum ^= *mat;
vec >>= 1;
mat++;
}
return sum;
}
local void gf2_matrix_square(square, mat) unsigned long *square;
unsigned long *mat;
{
int n;
for (n = 0; n < GF2_DIM; n++)
square[n] = gf2_matrix_times(mat, mat[n]);
}
local uLong crc32_combine_(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off64_t len2;
{
int n;
unsigned long row;
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
/* degenerate case (also disallow negative lengths) */
if (len2 <= 0)
return crc1;
/* put operator for one zero bit in odd */
odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
row = 1;
for (n = 1; n < GF2_DIM; n++) {
odd[n] = row;
row <<= 1;
}
/* put operator for two zero bits in even */
gf2_matrix_square(even, odd);
/* put operator for four zero bits in odd */
gf2_matrix_square(odd, even);
/* apply len2 zeros to crc1 (first square will put the operator for one
zero byte, eight zero bits, in even) */
do {
/* apply zeros operator for this bit of len2 */
gf2_matrix_square(even, odd);
if (len2 & 1)
crc1 = gf2_matrix_times(even, crc1);
len2 >>= 1;
/* if no more bits set, then done */
if (len2 == 0)
break;
/* another iteration of the loop with odd and even swapped */
gf2_matrix_square(odd, even);
if (len2 & 1)
crc1 = gf2_matrix_times(odd, crc1);
len2 >>= 1;
/* if no more bits set, then done */
} while (len2 != 0);
/* return combined crc */
crc1 ^= crc2;
return crc1;
}
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off_t len2;
{
return crc32_combine_(crc1, crc2, len2);
}
uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off64_t len2;
{
return crc32_combine_(crc1, crc2, len2);
}

View File

@@ -0,0 +1,37 @@
/**
* @file crc32.h
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:tables for rapid CRC calculation
* Generated automatically by crc32.c
* Revision History:
* -----------------
*/
#ifndef __CRC32_H
#define __CRC32_H
/*
* Computes the CRC-CCITT, starting with an initialization value.
* buf: the data on which to apply the checksum
* length: the number of bytes of data in 'buf' to be calculated.
*/
unsigned short crc16(const unsigned char *buf, unsigned int length);
/*
* Computes an updated version of the CRC-CCITT from existing CRC.
* crc: the previous values of the CRC
* buf: the data on which to apply the checksum
* length: the number of bytes of data in 'buf' to be calculated.
*/
unsigned short update_crc16(unsigned short crc, const unsigned char *buf,
unsigned int len);
unsigned long crc32(unsigned long crc, const unsigned char *buf,
unsigned int len);
unsigned long adler32(unsigned long adler, const unsigned char *buf,
unsigned int len);
#endif

View File

@@ -0,0 +1,437 @@
/**
* @file crc32.h
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:tables for rapid CRC calculation
* Generated automatically by crc32.c
* Revision History:
* -----------------
*/
#ifndef __CRC32_DATA_H
#define __CRC32_DATA_H
local const z_crc_t FAR crc_table[TBLS][256] = {
{0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
0x2d02ef8dUL
#ifdef BYFOUR
},
{0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
0x9324fd72UL},
{0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
0xbe9834edUL},
{0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
0xde0506f1UL},
{0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
0x8def022dUL},
{0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
0x72fd2493UL},
{0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
0xed3498beUL},
{0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
0xf10605deUL
#endif
}};
#endif

View File

@@ -0,0 +1,20 @@
/********************************************************
* Copyright(c) 2022 Semidrive *
* All rights reserved. *
********************************************************/
#include "crc4.h"
const unsigned char CRC4_Table[16] = {0, 13, 7, 10, 14, 3, 9, 4,
1, 12, 6, 11, 15, 2, 8, 5};
unsigned char crc4_calculate(unsigned char initial_value,
const unsigned char *message, unsigned char len)
{
unsigned char crc_val = initial_value;
int i = 0;
for (; i < len; i++) {
crc_val = CRC4_Table[crc_val] ^ message[i];
}
crc_val = 0 ^ CRC4_Table[crc_val];
return crc_val;
}

View File

@@ -0,0 +1,11 @@
/********************************************************
* Copyright(c) 2022 Semidrive *
* All rights reserved. *
********************************************************/
#ifndef _CRC4_H
#define _CRC4_H
unsigned char crc4_calculate(unsigned char crc, const unsigned char *message,
unsigned char len);
#endif

279
middleware/checksum/md5.c Normal file
View File

@@ -0,0 +1,279 @@
/**
* @file md5.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
* This code implements the MD5 message-digest algorithm.
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*
* Revision History:
* -----------------
*/
#include <md5.h>
#include <string.h>
#include "compiler.h"
static void MD5Transform(__u32 buf[4], __u32 const in[16]);
/**
* @brief byteReverse
*
* @param buf
* @param longs
*/
static void byteReverse(unsigned char *buf, unsigned longs)
{
__u32 t;
do {
t = (__u32)((unsigned)buf[3] << 8 | buf[2]) << 16 |
((unsigned)buf[1] << 8 | buf[0]);
*(__u32 *)buf = t;
buf += 4;
} while (--longs);
}
/**
* @brief Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
* @param ctx
*/
void MD5Init(struct MD5Context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/**
* @brief Update context to reflect the concatenation of another buffer full
* of bytes.
* @param ctx
* @param buf
* @param len
*/
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
{
register __u32 t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((__u32)len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *)ctx->in + t;
t = 64 - t;
if (len < t) {
memmove(p, buf, len);
return;
}
memmove(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (__u32 *)ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memmove(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (__u32 *)ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memmove(ctx->in, buf, len);
}
/**
* @brief Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
* @param digest
* @param ctx
*/
void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
{
unsigned int count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (__u32 *)ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
ctx->in32[14] = ctx->bits[0];
ctx->in32[15] = ctx->bits[1];
MD5Transform(ctx->buf, (__u32 *)ctx->in);
byteReverse((unsigned char *)ctx->buf, 4);
memmove(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
(w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
/**
* @brief * The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*
* @param buf
* @param in
*/
static void MD5Transform(__u32 buf[4], __u32 const in[16])
{
register __u32 a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/**
* @brief * Calculate and store in 'output' the MD5 digest of 'len' bytes at
* 'input'. 'output' must have enough space to hold 16 bytes.
* @param input input buffer
* @param len input buffer length
* @param output md5 output
*/
void md5(const unsigned char *input, const int len, unsigned char output[16])
{
struct MD5Context context;
MD5Init(&context);
MD5Update(&context, input, len);
MD5Final(output, &context);
}

62
middleware/checksum/md5.h Normal file
View File

@@ -0,0 +1,62 @@
/**
* @file chsum.h
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef __MD5_H
#define __MD5_H
#if defined(__cplusplus)
extern "C" {
#endif
#include <compiler.h>
#define MD5_LEN 16
typedef unsigned int __u32;
struct MD5Context {
__u32 buf[4];
__u32 bits[2];
union {
unsigned char in[64];
__u32 in32[16];
};
};
/*
* Calculate and store in 'output' the MD5 digest of 'len' bytes at
* 'input'. 'output' must have enough space to hold 16 bytes.
*/
void md5(const unsigned char *input, const int len, unsigned char output[16]);
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void MD5Init(struct MD5Context *ctx);
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len);
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
#if defined(__cplusplus)
}
#endif
#endif

View File

@@ -0,0 +1,33 @@
/**
* @file zutil.h
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:type define
*
* Revision History:
* -----------------
*/
#ifndef __ZUTIL_H
#define __ZUTIL_H
/* necessary stuff to transplant crc32 and adler32 from zlib */
#include <inttypes.h>
#include <types.h>
typedef unsigned long uLong;
typedef unsigned int uInt;
typedef uint8_t Byte;
typedef Byte Bytef;
typedef int32_t z_off_t;
typedef int64_t z_off64_t;
typedef unsigned long z_crc_t;
#define Z_NULL NULL
#define OF(args) args
#define local static
#define ZEXPORT
#define FAR
#endif

102
middleware/debug/debug.c Normal file
View File

@@ -0,0 +1,102 @@
/*
* debug.c
*
* Copyright (c) 2023 Semidrive Semiconductor.
* All rights reserved.
*
* Description: debug interface.
*
* Revision History:
* -----------------
*/
#include <types.h>
#include <stdio.h>
#include <compiler.h>
#include <param.h>
#include <ctype.h>
#include <debug.h>
#if CONFIG_DEBUG
/**
* @brief hex dump function
*
* @param[in] ptr: dump data address
* @param[in] len: dump data length
*/
void hexdump(const void *ptr, size_t len)
{
addr_t address = (addr_t)ptr;
size_t count;
for (count = 0 ; count < len; count += 16) {
union {
uint32_t buf[4];
uint8_t cbuf[16];
} u;
size_t s = ROUNDUP(MIN(len - count, 16), 4);
size_t i;
ssdk_printf(SSDK_EMERG, "0x%08x: ", address);
for (i = 0; i < s / 4; i++) {
u.buf[i] = ((const uint32_t *)address)[i];
ssdk_printf(SSDK_EMERG, "%08x ", u.buf[i]);
}
for (; i < 4; i++) {
ssdk_printf(SSDK_EMERG, " ");
}
ssdk_printf(SSDK_EMERG, "|");
for (i=0; i < 16; i++) {
unsigned char c = u.cbuf[i];
if (i < s && isprint(c)) {
ssdk_printf(SSDK_EMERG, "%c", c);
} else {
ssdk_printf(SSDK_EMERG, ".");
}
}
ssdk_printf(SSDK_EMERG, "|\r\n");
address += 16;
}
}
/**
* @brief hex dump8 function with display address
*
* @param[in] ptr: ptr dump data address
* @param[in] len: len dump data length
* @param[in] addr: disp_addr display address
*/
void hexdump8_ex(const void *ptr, size_t len, uint64_t addr)
{
addr_t address = (addr_t)ptr;
size_t count;
size_t i;
const char *addr_fmt = ((addr + len) > 0xFFFFFFFF)
? "0x%016llx: "
: "0x%08llx: ";
for (count = 0 ; count < len; count += 16) {
ssdk_printf(SSDK_EMERG, addr_fmt, addr + count);
for (i=0; i < MIN(len - count, 16); i++) {
ssdk_printf(SSDK_EMERG, "%02hhx ", *(const uint8_t *)(address + i));
}
for (; i < 16; i++) {
ssdk_printf(SSDK_EMERG, " ");
}
ssdk_printf(SSDK_EMERG, "|");
for (i=0; i < MIN(len - count, 16); i++) {
unsigned char c = ((const char *)address)[i];
ssdk_printf(SSDK_EMERG, "%c", isprint(c) ? c : '.');
}
ssdk_printf(SSDK_EMERG, "\r\n");
address += 16;
}
}
#endif

555
middleware/disk/disk.c Normal file
View File

@@ -0,0 +1,555 @@
#include <FreeRTOS.h>
#include <armv7-r/atomic.h>
#include <debug.h>
#include <disk.h>
#include <lib/list.h>
#include <param.h>
#include <semphr.h>
struct list_node g_disk_list;
QueueHandle_t g_disk_mutex;
static struct disk_info *disk_get_info(const char *disk_name)
{
struct disk_info *info;
xSemaphoreTake(g_disk_mutex, portMAX_DELAY);
/* matches nodes based on name */
list_for_every_entry (&g_disk_list, info, struct disk_info, node) {
if (!strcmp(disk_name, info->disk_name)) {
xSemaphoreGive(g_disk_mutex);
return info;
}
}
xSemaphoreGive(g_disk_mutex);
return NULL;
}
int disk_open(const char *disk_name, struct disk_dev *dev)
{
struct disk_info *info;
info = disk_get_info(disk_name);
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk devicve node\n");
return -DISK_ERROR_NO_DEVICE;
}
if (NULL != dev->info) {
ssdk_printf(SSDK_ERR, "disk device is open.\n");
return -DISK_ERROR_BUSY;
}
ssdk_printf(SSDK_DEBUG, "disk open:%s\n", info->disk_name);
dev->info = info;
dev->block_size = info->block_align_size;
dev->flags = DISK_FLAGS_REWR;
arch_atomic_add(&info->use_count, 1);
return 0;
}
int disk_close(struct disk_dev *dev)
{
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
ssdk_printf(SSDK_DEBUG, "disk close:%s\n", info->disk_name);
dev->info = NULL;
arch_atomic_add(&info->use_count, -1);
return 0;
}
int disk_read(struct disk_dev *dev, disk_addr_t addr, uint8_t *dst,
disk_size_t size)
{
if (!(dev->flags & DISK_FLAGS_READ)) {
ssdk_printf(SSDK_ERR,
"disk device does not support read operations \n");
return -DISK_ERROR_NO_PERMISSION;
}
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
/* size range judgment */
if (addr + size > info->disk_size) {
ssdk_printf(SSDK_ERR,
"out of disk range, addr:%lld size:%lld disk_size:%lld\n",
addr, size, info->disk_size);
return -DISK_ERROR_OUT_RANGE;
}
ssdk_printf(SSDK_DEBUG, "disk read:%s addr:%lld size:%lld\n",
info->disk_name, addr, size);
#ifdef CONFIG_DISK_CACHE
if ((info->cache) && !(dev->flags & DISK_FLAGS_DIRECT_IO)) {
return disk_cache_read(info->cache, dst, addr, size);
} else
#endif
if (info->disk_ops->disk_read)
return info->disk_ops->disk_read(info, dst, addr, size);
else
return -DISK_ERROR_NO_FUN;
}
int disk_write(struct disk_dev *dev, disk_addr_t addr, const uint8_t *src,
disk_size_t size)
{
if (!(dev->flags & DISK_FLAGS_WRITE)) {
ssdk_printf(SSDK_ERR,
"disk device does not support write operations \n");
return -DISK_ERROR_NO_PERMISSION;
}
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
/* size range judgment */
if (addr + size > info->disk_size) {
ssdk_printf(SSDK_ERR,
"out of disk range, addr:%lld size:%lld disk_size:%lld\n",
addr, size, info->disk_size);
return -DISK_ERROR_OUT_RANGE;
}
ssdk_printf(SSDK_DEBUG, "disk write:%s addr:%lld size:%lld\n",
info->disk_name, addr, size);
#ifdef CONFIG_DISK_CACHE
if (info->cache) {
int ret = 0;
ret |= disk_cache_write(info->cache, src, addr, size);
/* DIRECT_IO situation,TODO */
if (dev->flags & DISK_FLAGS_DIRECT_IO)
ret |= disk_cache_sync_addr(info->cache, addr, size);
return ret;
} else
#endif
if (info->disk_ops->disk_write)
return info->disk_ops->disk_write(info, src, addr, size);
else
return -DISK_ERROR_NO_FUN;
}
int disk_read_block(struct disk_dev *dev, block_t block, uint8_t *dst,
block_count_t count)
{
if (!(dev->flags & DISK_FLAGS_READ)) {
ssdk_printf(SSDK_ERR,
"disk device does not support read operations \n");
return -DISK_ERROR_NO_PERMISSION;
}
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
/* size range judgment */
if (block + count > info->disk_size / dev->block_size) {
ssdk_printf(SSDK_ERR,
"out of disk range, block:%lld count:%d block_size:0x%x "
"addr:%lld size:%lld disk_size:%lld\n",
block, count, dev->block_size,
(disk_addr_t)block * dev->block_size,
(disk_addr_t)count * dev->block_size, info->disk_size);
return -DISK_ERROR_OUT_RANGE;
}
/* mem alignment judgment */
if (!IS_ALIGNED(dst, info->mem_align_size)) {
ssdk_printf(SSDK_ERR, "mem addresses 0x%p not aligned to 0x%x\n", dst,
info->mem_align_size);
return -DISK_ERROR_NO_ALIGNED;
}
ssdk_printf(SSDK_DEBUG,
"disk read block:%s block:%lld count:%d block_size:0x%x "
"addr:%lld size:%lld\n",
info->disk_name, block, count, dev->block_size,
(disk_addr_t)block * dev->block_size,
(disk_addr_t)count * dev->block_size);
#ifdef CONFIG_DISK_CACHE
if ((info->cache) && !(dev->flags & DISK_FLAGS_DIRECT_IO)) {
return disk_cache_read(info->cache, dst, block * dev->block_size,
count * dev->block_size);
} else
#endif
if (info->disk_ops->disk_read_block)
return info->disk_ops->disk_read_block(info, dst, block, count,
dev->block_size);
else
return -DISK_ERROR_NO_FUN;
}
int disk_write_block(struct disk_dev *dev, block_t block, const uint8_t *src,
block_count_t count)
{
if (!(dev->flags & DISK_FLAGS_WRITE)) {
ssdk_printf(SSDK_ERR,
"disk device does not support write operations \n");
return -DISK_ERROR_NO_PERMISSION;
}
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
/* size range judgment */
if (block + count > info->disk_size / dev->block_size) {
ssdk_printf(SSDK_ERR,
"out of disk range, block:%lld count:%d block_size:0x%x "
"addr:%lld size:%lld disk_size:%lld\n",
block, count, dev->block_size,
(disk_addr_t)block * dev->block_size,
(disk_addr_t)count * dev->block_size, info->disk_size);
return -DISK_ERROR_OUT_RANGE;
}
/* mem alignment judgment */
if (!IS_ALIGNED(src, info->mem_align_size)) {
ssdk_printf(SSDK_ERR, "mem addresses %p not aligned to %d\n", src,
info->mem_align_size);
return -DISK_ERROR_NO_ALIGNED;
}
ssdk_printf(SSDK_DEBUG,
"disk write block:%s block:%lld count:%d block_size:0x%x "
"addr:%lld size:%lld\n",
info->disk_name, block, count, dev->block_size,
(disk_addr_t)block * dev->block_size,
(disk_addr_t)count * dev->block_size);
#ifdef CONFIG_DISK_CACHE
if (info->cache) {
int ret = 0;
ret |= disk_cache_write(info->cache, src, block * dev->block_size,
count * dev->block_size);
/* DIRECT_IO situation,TODO */
if (dev->flags & DISK_FLAGS_DIRECT_IO)
ret |= disk_cache_sync_addr(info->cache, block * dev->block_size,
count * dev->block_size);
return ret;
} else
#endif
if (info->disk_ops->disk_write_block)
return info->disk_ops->disk_write_block(info, src, block, count,
dev->block_size);
else
return -DISK_ERROR_NO_FUN;
}
int disk_erase(struct disk_dev *dev, disk_addr_t addr, disk_size_t size,
disk_erase_flags flag)
{
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
/* size range judgment */
if (addr + size > info->disk_size) {
ssdk_printf(SSDK_ERR,
"out of disk range, addr:%lld size:%lld disk_size:%lld\n",
addr, size, info->disk_size);
return -DISK_ERROR_OUT_RANGE;
}
ssdk_printf(SSDK_DEBUG, "disk erase:%s addr:%lld size:%lld flag:%d\n",
info->disk_name, addr, size, flag);
#ifdef CONFIG_DISK_CACHE
if (info->cache) {
int ret = 0;
ret |= disk_cache_erase(info->cache, addr, size, flag);
/* DIRECT_IO situation,TODO */
if (dev->flags & DISK_FLAGS_DIRECT_IO)
ret |= disk_cache_sync_addr(info->cache, addr, size);
return ret;
} else
#endif
if (info->disk_ops->disk_erase)
return info->disk_ops->disk_erase(info, addr, size, flag);
else
return -DISK_ERROR_NO_FUN;
}
int disk_erase_group(struct disk_dev *dev, uint32_t erase_block, uint32_t count,
disk_erase_flags flag)
{
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
/* size range judgment */
if (erase_block + count > info->disk_size / info->erase_size) {
ssdk_printf(SSDK_ERR,
"out of disk range, erase_block:%d count:%d "
"erase_size:0x%x addr:%lld size:%lld disk_size:%lld\n",
erase_block, count, info->erase_size,
(disk_addr_t)erase_block * info->erase_size,
(disk_addr_t)count * info->erase_size, info->disk_size);
return -DISK_ERROR_OUT_RANGE;
}
ssdk_printf(SSDK_DEBUG,
"disk erase group:%s erase_block:%d count:%d erase_size:0x%x "
"addr:%lld size:%lld flag:%d\n",
info->disk_name, erase_block, count, info->erase_size,
(disk_addr_t)erase_block * info->erase_size,
(disk_addr_t)count * info->erase_size, flag);
#ifdef CONFIG_DISK_CACHE
if (info->cache) {
int ret = 0;
ret |= disk_cache_erase(info->cache, erase_block * info->erase_size,
count * info->erase_size, flag);
/* DIRECT_IO situation,TODO */
if (dev->flags & DISK_FLAGS_DIRECT_IO)
ret |= disk_cache_sync_addr(info->cache,
erase_block * info->erase_size,
count * info->erase_size);
return ret;
} else
#endif
if (info->disk_ops->disk_erase_group)
return info->disk_ops->disk_erase_group(info, erase_block, count,
info->erase_size, flag);
else
return -DISK_ERROR_NO_FUN;
}
int disk_sync(struct disk_dev *dev)
{
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
ssdk_printf(SSDK_DEBUG, "disk sync:%s\n", info->disk_name);
#ifdef CONFIG_DISK_CACHE
if (info->cache)
return disk_cache_sync(info->cache);
else
#endif
return -DISK_ERROR_NO_FUN;
}
int disk_sync_addr(struct disk_dev *dev, disk_addr_t addr, disk_size_t size)
{
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
/* size range judgment */
if (addr + size > info->disk_size) {
ssdk_printf(SSDK_ERR,
"out of disk range, addr:%lld size:%lld disk_size:%lld\n",
addr, size, info->disk_size);
return -DISK_ERROR_OUT_RANGE;
}
ssdk_printf(SSDK_DEBUG, "disk sync addr:%s addr:%lld size:%lld\n",
info->disk_name, addr, size);
#ifdef CONFIG_DISK_CACHE
if (info->cache)
return disk_cache_sync_addr(info->cache, addr, size);
else
#endif
return -DISK_ERROR_NO_FUN;
}
disk_addr_t disk_size(struct disk_dev *dev)
{
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
ssdk_printf(SSDK_DEBUG, "disk size:%s size:%lld\n", info->disk_name,
info->disk_size);
return info->disk_size;
}
uint32_t disk_erase_size(struct disk_dev *dev)
{
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
ssdk_printf(SSDK_DEBUG, "disk erase size:%s erase_size:0x%x\n",
info->disk_name, info->erase_size);
return info->erase_size;
}
uint32_t disk_get_block_size(struct disk_dev *dev)
{
ssdk_printf(SSDK_DEBUG, "disk get block size:%s block_size:0x%x\n",
dev->info->disk_name, dev->block_size);
return dev->block_size;
}
int disk_set_block_size(struct disk_dev *dev, uint32_t blk_sz)
{
struct disk_info *info = dev->info;
ssdk_printf(SSDK_DEBUG, "disk set block size:%s block_size:0x%x\n",
dev->info->disk_name, blk_sz);
/* blk_sz alignment judgment */
if (!IS_ALIGNED(blk_sz, info->block_align_size)) {
ssdk_printf(SSDK_ERR, "blk_sz %d not aligned to 0x%x\n", blk_sz,
info->block_align_size);
return -DISK_ERROR_NO_ALIGNED;
}
dev->block_size = blk_sz;
return 0;
}
int disk_set_flags(struct disk_dev *dev, bool mode, uint32_t flags)
{
if (mode)
dev->flags &= flags;
else
dev->flags |= ~flags;
ssdk_printf(SSDK_DEBUG, "disk set flags:%s flags:0x%x\n",
dev->info->disk_name, dev->flags);
return 0;
}
uint32_t disk_get_flags(struct disk_dev *dev)
{
ssdk_printf(SSDK_DEBUG, "disk get flags:%s flags:0x%x\n",
dev->info->disk_name, dev->flags);
return dev->flags;
}
int disk_status(struct disk_dev *dev)
{
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
ssdk_printf(SSDK_DEBUG, "disk status:%s\n", info->disk_name);
if (info->disk_ops->disk_status)
return info->disk_ops->disk_status(info);
else
return -DISK_ERROR_NO_FUN;
}
int disk_ioctl(struct disk_dev *dev, uint32_t cmd, void *buff)
{
struct disk_info *info = dev->info;
if (NULL == info) {
ssdk_printf(SSDK_ERR, "no disk device node\n");
return -DISK_ERROR_NO_DEVICE;
}
ssdk_printf(SSDK_DEBUG, "disk ioctl:%s\n", info->disk_name);
if (info->disk_ops->disk_ioctl)
return info->disk_ops->disk_ioctl(info, cmd, buff);
else
return -DISK_ERROR_NO_FUN;
}
int register_disk(struct disk_info *disk)
{
int ret = 0;
ssdk_printf(SSDK_DEBUG,
"register disk :%s disk_size:%lld erase_size:0x%x\n",
disk->disk_name, disk->disk_size, disk->erase_size);
xSemaphoreTake(g_disk_mutex, portMAX_DELAY);
/* insert node */
list_add_tail(&g_disk_list, &disk->node);
disk->use_count = 0;
xSemaphoreGive(g_disk_mutex);
return ret;
}
int unregister_disk(struct disk_info *disk)
{
int ret = 0;
ssdk_printf(SSDK_DEBUG, "unregiste disk :%s\n", disk->disk_name);
xSemaphoreTake(g_disk_mutex, portMAX_DELAY);
if (disk->use_count) {
xSemaphoreGive(g_disk_mutex);
return -DISK_ERROR_BUSY;
}
/* remove nodes */
if (list_in_list(&disk->node))
list_delete(&disk->node);
xSemaphoreGive(g_disk_mutex);
return ret;
}
int disk_init(void)
{
ssdk_printf(SSDK_DEBUG, "disk init\n");
/* disk list node init */
list_initialize(&g_disk_list);
g_disk_mutex = xSemaphoreCreateMutex();
return 0;
}
int disk_exit(void)
{
ssdk_printf(SSDK_DEBUG, "disk exit\n");
/* disk list node init */
xSemaphoreGive(g_disk_mutex);
return 0;
}

399
middleware/disk/disk.h Normal file
View File

@@ -0,0 +1,399 @@
/**
* @file disk.h
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef DISK_H_
#define DISK_H_
#include <FreeRTOS.h>
#include <lib/list.h>
#include <semphr.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#define DISK_ADDR_64BITS 1
struct disk_info;
struct disk_operations;
struct disk_cache;
/**
* @brief size definition.
*/
#ifdef DISK_ADDR_64BITS
typedef uint64_t disk_addr_t;
#else
typedef uint32_t disk_addr_t;
#endif
#ifdef DISK_ADDR_64BITS
typedef uint64_t disk_size_t;
#else
typedef uint32_t disk_size_t;
#endif
#ifdef DISK_ADDR_64BITS
typedef uint64_t block_t;
#else
typedef uint32_t block_t;
#endif
typedef uint32_t block_count_t;
typedef uint32_t block_size_t;
#define DISK_BIT(n) (0x1 << n)
/**
* @brief disk device name.
*/
#define DISK_MMC_NAME(n) "mmc" #n
#define DISK_MMC_BOOT_NAME(n, m) "mmc" #n "_boot" #m
#define DISK_MMC_RPMB_NAME(n, m) "mmc" #n "_RPMB" #m
#define DISK_MMC_GPP_NAME(n, m) "mmc" #n "_GPP" #m
#define DISK_NOR_FLASH_NAME(n) "norflash" #n
#define DISK_FLASH_NAME(n, p) "flash" #n "_port" #p
#define DISK_RAM_NAME(n) "memdisk" #n
#define DISK_USB_NAME(n) "usb" #n
/**
* @brief disk device flags.
*/
#define DISK_FLAGS_CLR 0
#define DISK_FLAGS_SET 1
#define DISK_FLAGS_READ DISK_BIT(0) /* support read operations */
#define DISK_FLAGS_WRITE DISK_BIT(1) /* support write operations */
#define DISK_FLAGS_REWR (DISK_FLAGS_READ) | (DISK_FLAGS_WRITE)
#define DISK_FLAGS_DIRECT_IO DISK_BIT(2)
/**
* @brief disk error.
*/
typedef enum {
DISK_ERROR_NO_DEVICE = 1,
DISK_ERROR_NO_PERMISSION,
DISK_ERROR_INVALID_PARAMETER,
DISK_ERROR_OUT_RANGE,
DISK_ERROR_NO_FUN,
DISK_ERROR_READ_ACCESS,
DISK_ERROR_WRITE_ACCESS,
DISK_ERROR_ERASE_ACCESS,
DISK_ERROR_NO_ALIGNED,
DISK_ERROR_BUSY,
} disk_error;
/**
* @brief disk device status.
*/
typedef enum {
DISK_STATUS_OK = 1,
DISK_STATUS_ERR,
} disk_status_info;
/**
* @brief disk erase flags.
*/
typedef enum {
DISK_ERASE_DEFAULT = 1, /* erase to the device default value */
DISK_ERASE_ZERO, /* erase to 0x0 */
DISK_ERASE_ONE, /* erase to 0xff */
} disk_erase_flags;
/**
* @brief disk device operations.
*/
struct disk_operations {
/* disk_read operation callback function */
int (*disk_read)(struct disk_info *info, uint8_t *dst, disk_addr_t addr,
disk_size_t size);
/* disk_write operation callback function */
int (*disk_write)(struct disk_info *info, const uint8_t *src,
disk_addr_t addr, disk_size_t size);
/* disk_read_block operation callback function,blk_sz is
* disk_dev->block_size */
int (*disk_read_block)(struct disk_info *info, uint8_t *dst, block_t block,
block_count_t count, block_size_t blk_sz);
/* disk_write_block operation callback function,blk_sz is
* disk_dev->block_size */
int (*disk_write_block)(struct disk_info *info, const uint8_t *src,
block_t block, block_count_t count,
block_size_t blk_sz);
/* disk_erase operation callback function */
int (*disk_erase)(struct disk_info *info, disk_addr_t addr,
disk_size_t size, uint32_t flag);
/* disk_erase_group operation callback function,erase_sz is
* disk_info->erase_size */
int (*disk_erase_group)(struct disk_info *info, uint32_t erase_block,
uint32_t count, uint32_t erase_sz, uint32_t flag);
/* disk_status operation callback function */
int (*disk_status)(struct disk_info *info);
/* disk_ioctloperation callback function */
int (*disk_ioctl)(struct disk_info *info, uint32_t cmd, void *buff);
};
/**
* @brief disk device info.
*/
struct disk_info {
char *disk_name; /* disk device name, registration configuration */
struct list_node node; /* list node */
struct disk_operations *disk_ops; /* disk device operations instance,
registration configuration */
struct disk_cache
*cache; /* disk device cache instance, registration configuration */
/* disk attribute */
uint64_t disk_offset; /* disk device addr offset, registration
configuration, default is 0 */
uint64_t disk_size; /* disk device size, registration configuration */
uint32_t
erase_size; /* disk device erase size, registration configuration */
uint32_t mem_align_size; /* disk device block ops memory alignment size,
registration configuration */
uint32_t block_align_size; /* disk device block ops block_sz alignment size,
registration configuration */
int use_count; /* using the counting */
void *private_data; /* Private data */
};
/**
* @brief disk dev, apply handle & message.
*/
struct disk_dev {
struct disk_info *info; /* disk device info */
/* disk file attribute */
uint32_t block_size; /* disk device block ops block_size */
uint32_t flags; /* disk device flags */
};
extern struct list_node g_disk_list;
extern QueueHandle_t g_disk_mutex;
/* define API */
#define disk_erase_default(dev, addr, size) \
disk_erase(dev, addr, size, DISK_ERASE_DEFAULT)
#define disk_erase_group_default(dev, erase_block, count) \
disk_erase_group(dev, erase_block, count, DISK_ERASE_DEFAULT)
/**
* @brief disk open
*
* @param[in] disk info name
* @param[in] disk apply handle instance,for details,see disk_dev
* @return 0 if OK, or a negative error code.
*/
int disk_open(const char *disk_name, struct disk_dev *dev);
/**
* @brief disk close
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @return 0 if OK, or a negative error code.
*/
int disk_close(struct disk_dev *dev);
/**
* @brief disk read
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @param[in] info addr
* @param[in] dst memory
* @param[in] info size
* @return 0 if OK, or a negative error code.
*/
int disk_read(struct disk_dev *dev, disk_addr_t addr, uint8_t *dst,
disk_size_t size);
/**
* @brief disk write
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @param[in] info addr
* @param[in] src memory
* @param[in] info size
* @return 0 if OK, or a negative error code.
*/
int disk_write(struct disk_dev *dev, disk_addr_t addr, const uint8_t *src,
disk_size_t size);
/**
* @brief disk read block
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @param[in] info block addr
* @param[in] dst memory,must be mem_align_size alignment
* @param[in] info block count
* @return 0 if OK, or a negative error code.
*/
int disk_read_block(struct disk_dev *dev, block_t block, uint8_t *dst,
block_count_t count);
/**
* @brief disk write block
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @param[in] info block addr
* @param[in] src memory,must be mem_align_size alignment
* @param[in] info block count
* @return 0 if OK, or a negative error code.
*/
int disk_write_block(struct disk_dev *dev, block_t block, const uint8_t *src,
block_count_t count);
/**
* @brief disk erase
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @param[in] info addr
* @param[in] info size
* @param[in] erase flag,DISK_ERASE_XXX
* @return 0 if OK, or a negative error code.
*/
int disk_erase(struct disk_dev *dev, disk_addr_t addr, disk_size_t size,
disk_erase_flags flag);
/**
* @brief disk erase group
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @param[in] info erase group addr
* @param[in] info erase group count
* @param[in] erase flag,DISK_ERASE_XXX
* @return 0 if OK, or a negative error code.
*/
int disk_erase_group(struct disk_dev *dev, uint32_t erase_block, uint32_t count,
disk_erase_flags flag);
/**
* @brief disk sync, synchronize all cache data .
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @return 0 if OK, or a negative error code.
*/
int disk_sync(struct disk_dev *dev);
/**
* @brief disk sync addr, synchronize cache data based on the address.
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @param[in] info addr
* @param[in] info size
* @return 0 if OK, or a negative error code.
*/
int disk_sync_addr(struct disk_dev *dev, disk_addr_t addr, disk_size_t size);
/**
* @brief disk get disk size.
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @return disk_addr.
*/
disk_addr_t disk_size(struct disk_dev *dev);
/**
* @brief disk get erase size.
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @return erase_size.
*/
uint32_t disk_erase_size(struct disk_dev *dev);
/**
* @brief disk set block size.
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @param[in] blk_sz,must be block_align_size aligned
* @return 0 if OK, or a negative error code.
*/
int disk_set_block_size(struct disk_dev *dev, uint32_t blk_sz);
/**
* @brief disk get block size.
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @return blk_sz.
*/
uint32_t disk_get_block_size(struct disk_dev *dev);
/**
* @brief disk set flags.
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @param[in] operation mode,DISK_FLAGS_CLR & DISK_FLAGS_SET
* @param[in] disk flags,for details,see DISK_FLAGS_XXX
* @return 0 if OK, or a negative error code.
*/
int disk_set_flags(struct disk_dev *dev, bool mode, uint32_t flags);
/**
* @brief disk get flags.
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @return disk flags.
*/
uint32_t disk_get_flags(struct disk_dev *dev);
/**
* @brief disk status.
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @return disk_status.
*/
int disk_status(struct disk_dev *dev);
/**
* @brief disk ioctl.
*
* @param[in] disk apply handle instance,for details,see disk_dev
* @param[in] command code,for details, see disk_xxx.h
* @param[in] pointer to memory,command content
* @return 0 if OK, or a negative error code.
*/
int disk_ioctl(struct disk_dev *dev, uint32_t cmd, void *buff);
/**
* @brief disk register.
*
* @param[in] disk info instance,for details,see disk_info
* @return 0 if OK, or a negative error code.
*/
int register_disk(struct disk_info *info);
/**
* @brief disk unregister.
*
* @param[in] disk info instance,for details,see disk_info
* @return 0 if OK, or a negative error code.
*/
int unregister_disk(struct disk_info *info);
/**
* @brief disk init.
*
* @return 0 if OK, or a negative error code.
*/
int disk_init(void);
/**
* @brief disk exit.
*
* @return 0 if OK, or a negative error code.
*/
int disk_exit(void);
#endif /* DISK_H_ */

656
middleware/disk/disk_mmc.c Normal file
View File

@@ -0,0 +1,656 @@
/**
* @file disk_mmm.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#include <debug.h>
#include <disk.h>
#include <disk_mmc.h>
#include <param.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
/* Maximum value of a single transmission */
#define MMC_MAX_XFER_SIZE (0x1000000)
/* mmc erase value */
#define MMC_DEFAULT_FLAG(flag) \
((flag == DISK_ERASE_DEFAULT) || (flag == DISK_ERASE_ZERO))
/* MMC physical layer API */
static int mmc_dev_read(struct disk_mmc_info *mmc_info, uint8_t *dst,
block_t sector, block_count_t count)
{
if (mmc_info->config.mmc_read)
return mmc_info->config.mmc_read(mmc_info->config.mmc_dev, dst, sector,
count);
else
return -DISK_ERROR_READ_ACCESS;
}
static int mmc_dev_write(struct disk_mmc_info *mmc_info, const uint8_t *src,
block_t sector, block_count_t count)
{
if (mmc_info->config.mmc_write)
return mmc_info->config.mmc_write(mmc_info->config.mmc_dev, src, sector,
count);
else
return -DISK_ERROR_WRITE_ACCESS;
}
static int mmc_dev_erase(struct disk_mmc_info *mmc_info, block_t block,
block_count_t count)
{
if (mmc_info->config.mmc_erase)
return mmc_info->config.mmc_erase(mmc_info->config.mmc_dev, block,
count);
else
return -DISK_ERROR_ERASE_ACCESS;
}
/* MMC buff reads */
static int mmc_buff_read(struct disk_mmc_info *mmc_info, uint8_t *buff_dst,
block_t sector, block_count_t sector_count,
uint8_t *dst, disk_addr_t addr, disk_size_t size)
{
int ret = 0;
uint32_t sector_size = mmc_info->config.sector_size;
/* Protect the buffer */
xSemaphoreTake(mmc_info->disk_mmc_mutex, portMAX_DELAY);
ret = mmc_dev_read(mmc_info, buff_dst, sector, sector_count);
if (ret)
goto error;
memcpy(dst, buff_dst + addr - ROUNDDOWN(addr, sector_size), size);
xSemaphoreGive(mmc_info->disk_mmc_mutex);
return 0;
error:
xSemaphoreGive(mmc_info->disk_mmc_mutex);
return ret;
}
static int disk_mmc_read(struct disk_info *info, uint8_t *dst, disk_addr_t addr,
disk_size_t size)
{
int ret = 0;
struct disk_mmc_info *mmc_info = info->private_data;
uint8_t *buf = NULL;
disk_size_t remaining = size;
uint32_t sector_size = mmc_info->config.sector_size;
uint32_t buff_size = mmc_info->buff_size;
disk_addr_t sector_addr = 0;
disk_size_t sector_count = 0;
disk_size_t read_len = 0;
disk_size_t max_read_length = 0;
while (remaining) {
/* Process the unaligned portion of the address */
if (!IS_ALIGNED(addr, sector_size)) {
ssdk_printf(SSDK_DEBUG,
"mmc disk read %s address sector unaligned portion\n",
info->disk_name);
buf = mmc_info->buff_sector;
sector_addr = addr / sector_size;
sector_count = 1;
read_len = MIN(ROUNDUP(addr, sector_size) - addr, remaining);
ssdk_printf(SSDK_DEBUG, "mmc disk read addr:%llx read_len:%lld\n",
addr, read_len);
}
/* Address & size aligned portion of sector,Memory CACHE_LINE alignment
*/
else if ((remaining > sector_size) &&
IS_ALIGNED(dst, CONFIG_ARCH_CACHE_LINE)) {
ssdk_printf(SSDK_DEBUG,
"mmc disk read %s address sector aligned & dst "
"CACHE_LINE aligned portion\n",
info->disk_name);
buf = dst;
sector_addr = addr / sector_size;
max_read_length = MIN(mmc_info->mmc_max_xfer_size, remaining);
sector_count = max_read_length / sector_size;
read_len = sector_count * sector_size;
ssdk_printf(SSDK_DEBUG, "mmc disk read addr:%llx read_len:%lld\n",
addr, read_len);
}
/* Address & size aligned portion of sector,Memory CACHE_LINE is not
aligned */
else {
ssdk_printf(SSDK_DEBUG, "mmc disk read %s remaining portion\n",
info->disk_name);
buf = mmc_info->buff_sector;
sector_addr = addr / sector_size;
read_len = MIN(buff_size, remaining);
sector_count = ROUNDUP(read_len, sector_size) / sector_size;
ssdk_printf(SSDK_DEBUG, "mmc disk read addr:%llx read_len:%lld\n",
addr, read_len);
}
if (buf == dst) {
ret = mmc_dev_read(mmc_info, buf, sector_addr, sector_count);
if (ret)
return ret;
}
else {
ret = mmc_buff_read(mmc_info, buf, sector_addr, sector_count, dst,
addr, read_len);
if (ret)
return ret;
}
/* Address & size offset */
dst += read_len;
addr += read_len;
remaining -= read_len;
}
return 0;
}
static int mmc_buff_write(struct disk_mmc_info *mmc_info, uint8_t *buff_src,
block_t sector, block_count_t sector_count,
uint8_t *src, disk_addr_t addr, disk_size_t size)
{
int ret = 0;
uint32_t sector_size = mmc_info->config.sector_size;
/* Protect the buffer */
xSemaphoreTake(mmc_info->disk_mmc_mutex, portMAX_DELAY);
if (IS_ALIGNED(addr, sector_size) && IS_ALIGNED(size, sector_size)) {
memcpy(buff_src, src, size);
}
else {
ret = mmc_dev_read(mmc_info, buff_src, sector, sector_count);
if (ret)
goto error;
memcpy(buff_src + addr - ROUNDDOWN(addr, sector_size), src, size);
}
ret = mmc_dev_write(mmc_info, buff_src, sector, sector_count);
if (ret)
goto error;
xSemaphoreGive(mmc_info->disk_mmc_mutex);
return 0;
error:
xSemaphoreGive(mmc_info->disk_mmc_mutex);
return ret;
}
static int disk_mmc_write(struct disk_info *info, const uint8_t *src,
disk_addr_t addr, disk_size_t size)
{
int ret = 0;
struct disk_mmc_info *mmc_info = info->private_data;
uint8_t *buf = NULL;
disk_size_t remaining = size;
uint32_t sector_size = mmc_info->config.sector_size;
uint32_t buff_size = mmc_info->buff_size;
disk_addr_t sector_addr = 0;
disk_size_t sector_count = 0;
disk_size_t write_len = 0;
disk_size_t max_read_length = 0;
while (remaining) {
/* Process the unaligned portion of the address */
if (!IS_ALIGNED(addr, sector_size)) {
ssdk_printf(SSDK_DEBUG,
"mmc disk write %s address sector unaligned portion\n",
info->disk_name);
buf = mmc_info->buff_sector;
sector_addr = addr / sector_size;
sector_count = 1;
write_len = MIN(ROUNDUP(addr, sector_size) - addr, remaining);
ssdk_printf(SSDK_DEBUG, "mmc disk write addr:%llx write_len:%lld\n",
addr, write_len);
}
/* Address & size aligned portion of sector,Memory CACHE_LINE alignment
*/
else if ((remaining > sector_size) &&
IS_ALIGNED(src, CONFIG_ARCH_CACHE_LINE)) {
ssdk_printf(SSDK_DEBUG,
"mmc disk write %s address sector aligned & dst "
"CACHE_LINE aligned portion\n",
info->disk_name);
buf = (uint8_t *)src;
sector_addr = addr / sector_size;
max_read_length = MIN(mmc_info->mmc_max_xfer_size, remaining);
sector_count = max_read_length / sector_size;
write_len = sector_count * sector_size;
ssdk_printf(SSDK_DEBUG, "mmc disk write addr:%llx write_len:%lld\n",
addr, write_len);
}
else {
ssdk_printf(SSDK_DEBUG, "mmc disk write %s remaining portion\n",
info->disk_name);
buf = mmc_info->buff_sector;
sector_addr = addr / sector_size;
write_len = MIN(buff_size, remaining);
if (!IS_ALIGNED(write_len, sector_size) &&
(write_len > sector_size))
write_len = ROUNDDOWN(write_len, sector_size);
sector_count = ROUNDUP(write_len, sector_size) / sector_size;
ssdk_printf(SSDK_DEBUG, "mmc disk write addr:%llx write_len:%lld\n",
addr, write_len);
}
if (buf == src) {
ret = mmc_dev_write(mmc_info, buf, sector_addr, sector_count);
if (ret)
return ret;
}
else {
ret = mmc_buff_write(mmc_info, buf, sector_addr, sector_count,
(uint8_t *)src, addr, write_len);
if (ret)
return ret;
}
/* Address & size offset */
src += write_len;
addr += write_len;
remaining -= write_len;
}
return 0;
}
static int disk_mmc_read_block(struct disk_info *info, uint8_t *dst,
block_t block, block_count_t count,
block_size_t blk_sz)
{
struct disk_mmc_info *mmc_info = info->private_data;
uint32_t sector_size = mmc_info->config.sector_size;
uint32_t blk_to_sector = blk_sz / sector_size;
return mmc_dev_read(mmc_info, dst, block * blk_to_sector,
count * blk_to_sector);
}
static int disk_mmc_write_block(struct disk_info *info, const uint8_t *src,
block_t block, block_count_t count,
block_size_t blk_sz)
{
struct disk_mmc_info *mmc_info = info->private_data;
uint32_t sector_size = mmc_info->config.sector_size;
uint32_t blk_to_sector = blk_sz / sector_size;
return mmc_dev_write(mmc_info, src, block * blk_to_sector,
count * blk_to_sector);
}
static int mmc_buff_erase(struct disk_mmc_info *mmc_info, uint8_t *buff,
block_t sector, block_count_t sector_count,
disk_addr_t addr, disk_size_t size, char flag)
{
int ret = 0;
uint32_t sector_size = mmc_info->config.sector_size;
/* Protect the buff_sector buffer */
xSemaphoreTake(mmc_info->disk_mmc_mutex, portMAX_DELAY);
if (IS_ALIGNED(addr, sector_size) && IS_ALIGNED(size, sector_size)) {
memset(buff, flag, size);
}
else {
ret = mmc_dev_read(mmc_info, buff, sector, sector_count);
if (ret)
goto error;
memset(buff + addr - ROUNDDOWN(addr, sector_size), flag, size);
}
ret = mmc_dev_write(mmc_info, buff, sector, sector_count);
if (ret)
goto error;
xSemaphoreGive(mmc_info->disk_mmc_mutex);
return 0;
error:
xSemaphoreGive(mmc_info->disk_mmc_mutex);
return ret;
}
static int disk_mmc_erase(struct disk_info *info, disk_addr_t addr,
disk_size_t size, uint32_t flag)
{
int ret = 0;
struct disk_mmc_info *mmc_info = info->private_data;
uint8_t *buf = NULL;
disk_size_t remaining = size;
uint32_t sector_size = mmc_info->config.sector_size;
uint32_t buff_size = mmc_info->buff_size;
uint32_t scr_data_erase = mmc_info->config.scr_data_erase;
uint32_t erase_size = info->erase_size;
disk_addr_t sector_addr = 0;
disk_size_t sector_count = 0;
disk_size_t erase_count = 0;
disk_size_t erase_len = 0;
/* configure c_flag */
char c_flag = 0;
if (MMC_DEFAULT_FLAG(flag))
c_flag = 0x0;
else
c_flag = 0xff;
while (remaining) {
/* Process the sector unaligned portion of the address */
if (!IS_ALIGNED(addr, sector_size)) {
ssdk_printf(SSDK_DEBUG,
"mmc disk erase %s address sector unaligned portion\n",
info->disk_name);
buf = mmc_info->buff_sector;
sector_addr = addr / sector_size;
sector_count = 1;
erase_len = MIN(ROUNDUP(addr, sector_size) - addr, remaining);
ssdk_printf(SSDK_DEBUG, "mmc disk erase addr:%llx erase_len:%lld\n",
addr, erase_len);
}
/* Process the erase_size unaligned portion of the address */
else if (!IS_ALIGNED(addr, erase_size) && (remaining > erase_size)) {
ssdk_printf(
SSDK_DEBUG,
"mmc disk erase %s address erase_size unaligned portion\n",
info->disk_name);
buf = mmc_info->buff_sector;
sector_addr = addr / sector_size;
erase_len = MIN(buff_size, remaining);
erase_len = MIN(ROUNDUP(addr, erase_size) - addr, erase_len);
sector_count = erase_len / sector_size;
erase_len = sector_count * sector_size;
ssdk_printf(SSDK_DEBUG, "mmc disk erase addr:%llx erase_len:%lld\n",
addr, erase_len);
}
/* Address & size aligned portion of sector,Memory CACHE_LINE alignment
*/
else if ((remaining > erase_size) && MMC_DEFAULT_FLAG(flag)
&& !scr_data_erase) {
ssdk_printf(SSDK_DEBUG,
"mmc disk erase %s address erase_size aligned & size "
"erase_size aligned portion\n",
info->disk_name);
buf = NULL;
sector_addr = addr / sector_size;
erase_count = remaining / erase_size;
erase_len = erase_count * erase_size;
ssdk_printf(SSDK_DEBUG, "mmc disk erase addr:%llx erase_len:%lld\n",
addr, erase_len);
}
else if ((remaining > erase_size) && !MMC_DEFAULT_FLAG(flag)
&& scr_data_erase) {
ssdk_printf(SSDK_DEBUG,
"mmc disk erase %s address erase_size aligned & size "
"erase_size aligned portion\n",
info->disk_name);
buf = NULL;
sector_addr = addr / sector_size;
erase_count = remaining / erase_size;
erase_len = erase_count * erase_size;
ssdk_printf(SSDK_DEBUG, "mmc disk erase addr:%llx erase_len:%lld\n",
addr, erase_len);
}
/* Address & size aligned portion of sector,Memory CACHE_LINE is not
aligned */
else {
ssdk_printf(SSDK_DEBUG, "mmc disk erase %s remaining portion\n",
info->disk_name);
buf = mmc_info->buff_sector;
sector_addr = addr / sector_size;
erase_len = MIN(buff_size, remaining);
if (!IS_ALIGNED(erase_len, sector_size) &&
(erase_len > sector_size))
erase_len = ROUNDDOWN(erase_len, sector_size);
sector_count = ROUNDUP(erase_len, sector_size) / sector_size;
ssdk_printf(SSDK_DEBUG, "mmc disk erase addr:%llx erase_len:%lld\n",
addr, erase_len);
}
if (NULL == buf) {
ret = mmc_dev_erase(mmc_info, sector_addr, erase_len / sector_size);
if (ret)
return ret;
}
else {
ret = mmc_buff_erase(mmc_info, buf, sector_addr, sector_count, addr,
erase_len, c_flag);
if (ret)
return ret;
}
/* Address & size offset */
addr += erase_len;
remaining -= erase_len;
}
return 0;
}
static int disk_mmc_erase_group(struct disk_info *info, uint32_t erase_block,
uint32_t count, uint32_t erase_sz,
uint32_t flag)
{
struct disk_mmc_info *mmc_info = info->private_data;
uint32_t sector_size = mmc_info->config.sector_size;
uint32_t scr_data_erase = mmc_info->config.scr_data_erase;
if (erase_sz != info->erase_size) {
ssdk_printf(SSDK_DEBUG,
"mmc disk %s erase group erase_sz error,erase_sz:0x%x "
"erase_size:0x%x \n",
info->disk_name, erase_sz, info->erase_size);
return -DISK_ERROR_INVALID_PARAMETER;
}
if (!IS_ALIGNED(erase_sz, sector_size)) {
ssdk_printf(SSDK_DEBUG,
"mmc disk %s erase group erase_sz error,erase_sz:0x%x "
"sector_size:0x%x \n",
info->disk_name, erase_sz, sector_size);
return -DISK_ERROR_INVALID_PARAMETER;
}
uint32_t sector_addr = erase_block * erase_sz / sector_size;
switch (flag) {
case DISK_ERASE_DEFAULT:
case DISK_ERASE_ZERO:
if (!scr_data_erase) {
return mmc_dev_erase(mmc_info, sector_addr, count * erase_sz / sector_size);
}
else {
return disk_mmc_erase(info, (disk_addr_t)erase_block * erase_sz,
(disk_size_t)count * erase_sz, flag);
}
case DISK_ERASE_ONE:
if (scr_data_erase) {
return mmc_dev_erase(mmc_info, sector_addr, count * erase_sz / sector_size);
}
else {
return disk_mmc_erase(info, (disk_addr_t)erase_block * erase_sz,
(disk_size_t)count * erase_sz, flag);
}
default:
ssdk_printf(SSDK_ERR, "disk mmc erase flag error\n");
return -1;
}
}
static int disk_mmc_status(struct disk_info *info) { return DISK_STATUS_OK; }
static int disk_mmc_ioctl(struct disk_info *info, uint32_t cmd, void *buff)
{
struct disk_mmc_info *mmc_info = info->private_data;
switch (cmd) {
case MMC_IOCTL_PON:
uint32_t pon_type = 0;
memcpy(&pon_type, buff, sizeof(pon_type));
if (mmc_info->config.mmc_pon)
return mmc_info->config.mmc_pon(mmc_info->config.mmc_dev, pon_type);
else
return DISK_ERROR_INVALID_PARAMETER;
break;
default:
ssdk_printf(SSDK_ERR, "disk mmc ioctl cmd error:%d\n", cmd);
return DISK_ERROR_INVALID_PARAMETER;
}
return 0;
}
struct disk_operations disk_mmc_ops = {
.disk_read = disk_mmc_read,
.disk_write = disk_mmc_write,
.disk_read_block = disk_mmc_read_block,
.disk_write_block = disk_mmc_write_block,
.disk_erase = disk_mmc_erase,
.disk_erase_group = disk_mmc_erase_group,
.disk_status = disk_mmc_status,
.disk_ioctl = disk_mmc_ioctl,
};
int register_mmc_disk(struct disk_mmc_info *mmc_info)
{
int ret = 0;
struct disk_info *info = &mmc_info->info;
struct disk_mmc_config *mmc_config = &mmc_info->config;
/* init mmc_info */
mmc_info->buff_size = 4 * 1024;
if (!IS_ALIGNED(mmc_info->buff_size, mmc_config->sector_size)) {
ssdk_printf(
SSDK_ERR,
"mmc disk %s mmc_max_xfer_size not aligned to sector_size\n",
mmc_config->disk_name);
return -1;
}
mmc_info->buff_sector = (uint8_t *)pvPortMallocAligned(
mmc_info->buff_size, CONFIG_ARCH_CACHE_LINE);
if (NULL == mmc_info->buff_sector) {
ssdk_printf(SSDK_ERR, "mmc disk %s buff malloc error\n",
mmc_config->disk_name);
return -1;
}
mmc_info->disk_mmc_mutex = xSemaphoreCreateMutex();
mmc_info->mmc_max_xfer_size = MMC_MAX_XFER_SIZE;
if (!IS_ALIGNED(mmc_info->mmc_max_xfer_size, mmc_config->sector_size)) {
ssdk_printf(
SSDK_ERR,
"mmc disk %s mmc_max_xfer_size not aligned to sector_size\n",
mmc_config->disk_name);
return -1;
}
/* base on config init info */
info->disk_name = mmc_config->disk_name;
info->disk_size = mmc_config->disk_size;
info->disk_offset = 0;
info->erase_size = mmc_config->erase_size;
info->mem_align_size = CONFIG_ARCH_CACHE_LINE;
info->block_align_size = mmc_config->sector_size;
info->private_data = mmc_info;
info->disk_ops = &disk_mmc_ops;
#ifdef CONFIG_DISK_CACHE_NOOP
struct disk_cache_noop *cache_noop = &mmc_info->cache_noop;
/* base on config cache,cache in disk dev layer??? */
cache_noop->cache_align_size = 4u * 1024u;
cache_noop->cache.private_data = cache_noop;
ret = register_disk_cache_noop(cache_noop);
if (ret < 0) {
ssdk_printf(SSDK_ERR, "mmc disk register cache noop:%d\n", ret);
return ret;
}
#endif
ssdk_printf(SSDK_INFO,
"register mmc disk:%s disk_size:%lld erase_size:0x%x "
"sector_size:0x%x\n",
info->disk_name, info->disk_size, info->erase_size,
mmc_config->sector_size);
xSemaphoreTake(g_disk_mutex, portMAX_DELAY);
list_add_tail(&g_disk_list, &info->node);
info->use_count = 0;
xSemaphoreGive(g_disk_mutex);
return ret;
}
int unregister_mmc_disk(struct disk_mmc_info *mmc_info)
{
int ret = 0;
struct disk_info *info = &mmc_info->info;
ssdk_printf(SSDK_INFO, "unregister mmc disk:%s\n", info->disk_name);
#ifdef CONFIG_DISK_CACHE_NOOP
struct disk_cache_noop *cache_noop = &mmc_info->cache_noop;
/* unregister disk cache noop */
ret = unregister_disk_cache_noop(cache_noop);
if (ret < 0) {
ssdk_printf(SSDK_ERR, "mmc disk unregister cache noop:%d\n", ret);
return ret;
}
#endif
vPortFree(mmc_info->buff_sector);
vSemaphoreDelete(mmc_info->disk_mmc_mutex);
xSemaphoreTake(g_disk_mutex, portMAX_DELAY);
if (info->use_count) {
xSemaphoreGive(g_disk_mutex);
ret = -DISK_ERROR_BUSY;
ssdk_printf(SSDK_ERR, "mmc disk unregister:%d\n", ret);
return ret;
}
if (list_in_list(&info->node))
list_delete(&info->node);
xSemaphoreGive(g_disk_mutex);
return ret;
}

View File

@@ -0,0 +1,73 @@
/**
* @file disk_mmc.h
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef DISK_MMC_H_
#define DISK_MMC_H_
#include <disk.h>
#include <lib/list.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
/**
* @brief disk mmc ioctl cmds.
*/
typedef enum {
MMC_IOCTL_PON = 0x1, /* mmc ioctl Power Off Notification */
} disk_mmc_ioctl_cmd;
typedef enum {
MMC_IOCTL_NO_PON = 0x0,
MMC_IOCTL_PON_ON = 0x1,
MMC_IOCTL_PON_OFF_SHORT = 0x2,
MMC_IOCTL_PON_OFF_LONG = 0x3,
MMC_IOCTL_PON_SLEEP = 0x4,
} disk_mmc_ioctl_pon_value;
struct disk_mmc_config {
/* disk device name */
char *disk_name;
/* disk attribute */
disk_size_t disk_size;
uint32_t erase_size;
/* write & read sector size */
uint32_t sector_size;
uint32_t scr_data_erase;
/* mmc device ops API */
/* write & read:addr is block addr,count is block num */
/* erase & read:addr is block addr,size is len */
void *mmc_dev;
int (*mmc_read)(void *mmc_dev, uint8_t *dst, block_t block,
block_count_t count);
int (*mmc_write)(void *mmc_dev, const uint8_t *src, block_t block,
block_count_t count);
int (*mmc_erase)(void *mmc_dev, block_t block, block_count_t count);
int (*mmc_pon)(void *mmc_dev, uint32_t pon_type);
};
struct disk_mmc_info {
uint8_t *buff_sector;
uint32_t buff_size;
QueueHandle_t disk_mmc_mutex;
uint32_t mmc_max_xfer_size;
struct disk_mmc_config config;
struct disk_info info;
// struct disk_cache_noop cache_noop;
};
int register_mmc_disk(struct disk_mmc_info *mmc_info);
int unregister_mmc_disk(struct disk_mmc_info *mmc_info);
#endif /* DISK_MMC_H_ */

View File

@@ -0,0 +1,450 @@
/**
* @file disk_norflash.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#include <debug.h>
#include <disk.h>
#include <disk_norflash.h>
#include <param.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
static inline int norflash_dev_read(struct disk_norflash_info *norflash_info,
disk_addr_t addr, uint8_t *buf,
disk_size_t length)
{
if (norflash_info->config.norflash_read)
return norflash_info->config.norflash_read(
norflash_info->config.norflash_dev, addr, buf, length);
else
return -DISK_ERROR_READ_ACCESS;
}
static inline int norflash_dev_write(struct disk_norflash_info *norflash_info,
disk_addr_t addr, const uint8_t *buf,
disk_size_t length)
{
if (norflash_info->config.norflash_write)
return norflash_info->config.norflash_write(
norflash_info->config.norflash_dev, addr, buf, length);
else
return -DISK_ERROR_WRITE_ACCESS;
}
static inline int norflash_dev_erase(struct disk_norflash_info *norflash_info,
disk_addr_t addr, disk_size_t length)
{
if (norflash_info->config.norflash_erase)
return norflash_info->config.norflash_erase(
norflash_info->config.norflash_dev, addr, length);
else
return -DISK_ERROR_ERASE_ACCESS;
}
static int disk_norflash_read(struct disk_info *info, uint8_t *dst,
disk_addr_t addr, disk_size_t size)
{
int ret = 0;
struct disk_norflash_info *norflash_info = info->private_data;
ssdk_printf(SSDK_DEBUG,
"norflash disk read:%s mem:%p addr:%lld size:%lld\n",
info->disk_name, dst, addr, size);
disk_size_t tmp_len = 0;
while (size) {
tmp_len = size;
if (!IS_ALIGNED(dst, CONFIG_ARCH_CACHE_LINE)) {
tmp_len =
MIN(ROUNDUP((addr_t)dst, CONFIG_ARCH_CACHE_LINE) - (addr_t)dst,
size);
}
tmp_len = tmp_len > CONFIG_ARCH_CACHE_LINE
? (tmp_len - tmp_len % CONFIG_ARCH_CACHE_LINE)
: tmp_len;
if (tmp_len < CONFIG_ARCH_CACHE_LINE) {
xSemaphoreTake(norflash_info->disk_norflash_mutex, portMAX_DELAY);
if (norflash_dev_read(norflash_info, addr,
norflash_info->buff_sector,
ROUNDUP(tmp_len, 4))) {
ret = -1;
goto error;
}
memcpy(dst, norflash_info->buff_sector, tmp_len);
xSemaphoreGive(norflash_info->disk_norflash_mutex);
} else {
if (norflash_dev_read(norflash_info, addr, dst, tmp_len)) {
return -1;
}
}
addr += tmp_len;
size -= tmp_len;
dst += tmp_len;
}
return 0;
error:
xSemaphoreGive(norflash_info->disk_norflash_mutex);
return ret;
}
#if CONFIG_DISK_NOR_FLASH_BYTES_API_SUPPORT
static int disk_norflash_write(struct disk_info *info, const uint8_t *src,
disk_addr_t addr, disk_size_t size)
{
int ret = 0;
struct disk_norflash_info *norflash_info = info->private_data;
ssdk_printf(SSDK_DEBUG,
"norflash disk write:%s mem:%p addr:%lld size:%lld\n",
info->disk_name, src, addr, size);
uint32_t sector_size = norflash_info->config.sector_size;
uint32_t tmp_len;
uint8_t *buf;
while (size) {
buf = norflash_info->buff_sector;
tmp_len = size;
if (!IS_ALIGNED(addr, sector_size)) {
tmp_len = MIN(ROUNDUP(addr, sector_size) - addr, size);
} else if (IS_ALIGNED(src, CONFIG_ARCH_CACHE_LINE) &&
size >= sector_size) {
buf = (uint8_t *)src;
}
tmp_len =
tmp_len > sector_size ? (tmp_len - tmp_len % sector_size) : tmp_len;
if (src == buf) {
if (norflash_dev_erase(norflash_info, addr, tmp_len)) {
return -1;
}
if (norflash_dev_write(norflash_info, addr, buf, tmp_len)) {
return -1;
}
} else {
if (tmp_len < sector_size) {
xSemaphoreTake(norflash_info->disk_norflash_mutex,
portMAX_DELAY);
if (norflash_dev_read(norflash_info,
ROUNDDOWN(addr, sector_size), buf,
sector_size)) {
ret = -1;
goto error;
}
if (norflash_dev_erase(norflash_info,
ROUNDDOWN(addr, sector_size),
sector_size)) {
return -1;
}
} else {
if (norflash_dev_erase(norflash_info, addr, tmp_len)) {
return -1;
}
xSemaphoreTake(norflash_info->disk_norflash_mutex,
portMAX_DELAY);
}
for (disk_size_t size_tmp = 0;
size_tmp < ROUNDUP(tmp_len, sector_size);
size_tmp += sector_size) {
memcpy(buf + ((addr + size_tmp) % sector_size), src,
MIN(sector_size, tmp_len));
if (norflash_dev_write(norflash_info,
ROUNDDOWN(addr + size_tmp, sector_size),
buf, sector_size)) {
ret = -1;
goto error;
}
}
xSemaphoreGive(norflash_info->disk_norflash_mutex);
}
addr += tmp_len;
src += tmp_len;
size -= tmp_len;
}
return 0;
error:
xSemaphoreGive(norflash_info->disk_norflash_mutex);
return ret;
}
#endif
static int disk_norflash_read_block(struct disk_info *info, uint8_t *dst,
block_t block, block_count_t read_count,
block_size_t blk_sz)
{
ssdk_printf(SSDK_DEBUG,
"disk norflash read block:%s mem:%p block:%lld"
"read_count:%d blk_sz:%d addr:%lld size:%d\n",
info->disk_name, dst, block, read_count, blk_sz, block * blk_sz,
read_count * blk_sz);
return disk_norflash_read(info, dst, (disk_addr_t)block * blk_sz,
(disk_size_t)read_count * blk_sz);
}
static int disk_norflash_write_block(struct disk_info *info, const uint8_t *src,
block_t block, block_count_t write_count,
block_size_t blk_sz)
{
disk_size_t write_len;
disk_size_t remain_len = write_count * blk_sz;
disk_addr_t addr = block * blk_sz;
struct disk_norflash_info *norflash_info = info->private_data;
ssdk_printf(SSDK_DEBUG,
"disk norflash write block:%s mem:%p block:%lld"
"write_count:%d blk_sz:%d addr:%lld size:%d\n",
info->disk_name, src, block, write_count, blk_sz, block * blk_sz,
write_count * blk_sz);
while (remain_len) {
write_len = remain_len;
if (!IS_ALIGNED(src, CONFIG_ARCH_CACHE_LINE)) {
write_len =
MIN(ROUNDUP((addr_t)src, CONFIG_ARCH_CACHE_LINE) - (addr_t)src,
write_len);
}
write_len = write_len > CONFIG_ARCH_CACHE_LINE
? ROUNDDOWN(write_len, CONFIG_ARCH_CACHE_LINE)
: write_len;
if (write_len < CONFIG_ARCH_CACHE_LINE) {
xSemaphoreTake(norflash_info->disk_norflash_mutex, portMAX_DELAY);
memcpy(norflash_info->buff_sector, src, write_len);
if (norflash_dev_write(norflash_info, addr,
norflash_info->buff_sector,
ROUNDUP(write_len, 4))) {
xSemaphoreGive(norflash_info->disk_norflash_mutex);
return -1;
}
xSemaphoreGive(norflash_info->disk_norflash_mutex);
} else {
if (norflash_dev_write(norflash_info, addr, src, write_len)) {
return -1;
}
}
addr += write_len;
src += write_len;
remain_len -= write_len;
}
return 0;
}
#if CONFIG_DISK_NOR_FLASH_BYTES_API_SUPPORT
static int disk_norflash_erase(struct disk_info *info, disk_addr_t addr,
disk_size_t size, uint32_t flag)
{
int ret = 0;
struct disk_norflash_info *norflash_info = info->private_data;
ssdk_printf(SSDK_DEBUG,
"norflash disk %s erase,addr:%lld size:%lld:"
"flag:%d\n",
info->disk_name, addr, size, flag);
uint32_t sector_size = norflash_info->config.sector_size;
uint32_t tmp_len;
uint8_t *buf;
while (size) {
buf = norflash_info->buff_sector;
tmp_len = size;
if (!IS_ALIGNED(addr, sector_size)) {
tmp_len = MIN(ROUNDUP(addr, sector_size) - addr, size);
}
tmp_len =
tmp_len > sector_size ? (tmp_len - tmp_len % sector_size) : tmp_len;
if (tmp_len < sector_size) {
xSemaphoreTake(norflash_info->disk_norflash_mutex, portMAX_DELAY);
if (norflash_dev_read(norflash_info, ROUNDDOWN(addr, sector_size),
buf, sector_size)) {
ret = -1;
goto error;
}
if (norflash_dev_erase(norflash_info, ROUNDDOWN(addr, sector_size),
sector_size) < 0) {
ret = -1;
goto error;
}
memset(buf + addr % sector_size, 0xff, tmp_len);
if (norflash_dev_write(norflash_info, ROUNDDOWN(addr, sector_size),
buf, sector_size)) {
ret = -1;
goto error;
}
xSemaphoreGive(norflash_info->disk_norflash_mutex);
} else {
if (norflash_dev_erase(norflash_info, addr, tmp_len)) {
return -1;
}
}
addr += tmp_len;
size -= tmp_len;
}
return 0;
error:
xSemaphoreGive(norflash_info->disk_norflash_mutex);
return ret;
}
#endif
static int disk_norflash_erase_group(struct disk_info *info,
uint32_t erase_block, uint32_t erase_count,
uint32_t erase_sz, uint32_t flag)
{
return norflash_dev_erase(info->private_data,
(disk_addr_t)erase_block * erase_sz,
(disk_size_t)erase_count * erase_sz);
}
static int disk_norflash_status(struct disk_info *info)
{
return DISK_STATUS_OK;
}
static int disk_norflash_ioctl(struct disk_info *info, uint32_t cmd, void *buff)
{
return 0;
}
static struct disk_operations disk_norflash_ops = {
#if CONFIG_DISK_NOR_FLASH_BYTES_API_SUPPORT
.disk_read = disk_norflash_read,
.disk_write = disk_norflash_write,
.disk_erase = disk_norflash_erase,
#else
.disk_read = NULL,
.disk_write = NULL,
.disk_erase = NULL,
#endif
.disk_read_block = disk_norflash_read_block,
.disk_write_block = disk_norflash_write_block,
.disk_erase_group = disk_norflash_erase_group,
.disk_status = disk_norflash_status,
.disk_ioctl = disk_norflash_ioctl,
};
int register_norflash_disk(struct disk_norflash_info *norflash_info)
{
int ret = 0;
struct disk_info *info = &norflash_info->info;
struct disk_norflash_config *norflash_config = &norflash_info->config;
#ifdef CONFIG_DISK_NOR_FLASH_BYTES_API_SUPPORT
norflash_info->buff_size = norflash_config->sector_size;
#else
norflash_info->buff_size = CONFIG_ARCH_CACHE_LINE;
#endif
norflash_info->buff_sector = (uint8_t *)pvPortMallocAligned(
norflash_info->buff_size, CONFIG_ARCH_CACHE_LINE);
if (NULL == norflash_info->buff_sector) {
ssdk_printf(SSDK_ERR, "norflash disk %s buff malloc error\n",
norflash_config->disk_name);
return -1;
}
norflash_info->disk_norflash_mutex = xSemaphoreCreateMutex();
/* base on config init info */
info->disk_name = norflash_config->disk_name;
info->disk_size = norflash_config->disk_size;
info->disk_offset = 0;
info->erase_size = norflash_config->sector_size;
info->mem_align_size = CONFIG_ARCH_CACHE_LINE;
info->block_align_size = 4;
info->private_data = norflash_info;
info->disk_ops = &disk_norflash_ops;
#ifdef CONFIG_DISK_CACHE_NOOP
struct disk_cache_noop *cache_noop = &norflash_info->cache_noop;
/* base on config cache,cache in disk dev layer??? */
cache_noop->cache_align_size = 4u * 1024u;
cache_noop->cache.private_data = cache_noop;
ret = register_disk_cache_noop(cache_noop);
if (ret < 0) {
ssdk_printf(SSDK_ERR, "norflash disk register cache noop:%d\n", ret);
return ret;
}
#endif
ssdk_printf(SSDK_INFO,
"register norflash disk:%s disk_size:%lld"
"erase_size:%d sector_size:%d\n",
info->disk_name, info->disk_size, info->erase_size,
norflash_config->sector_size);
xSemaphoreTake(g_disk_mutex, portMAX_DELAY);
list_add_tail(&g_disk_list, &info->node);
info->use_count = 0;
xSemaphoreGive(g_disk_mutex);
return ret;
}
int unregister_norflash_disk(struct disk_norflash_info *norflash_info)
{
int ret = 0;
struct disk_info *info = &norflash_info->info;
ssdk_printf(SSDK_INFO, "unregister norflash disk:%s\n", info->disk_name);
#ifdef CONFIG_DISK_CACHE_NOOP
struct disk_cache_noop *cache_noop = &norflash_info->cache_noop;
/* unregister disk cache noop */
ret = unregister_disk_cache_noop(cache_noop);
if (ret < 0) {
ssdk_printf(SSDK_ERR, "norflash disk unregister cache noop:%d\n", ret);
return ret;
}
#endif
vPortFree(norflash_info->buff_sector);
vSemaphoreDelete(norflash_info->disk_norflash_mutex);
xSemaphoreTake(g_disk_mutex, portMAX_DELAY);
if (info->use_count) {
xSemaphoreGive(g_disk_mutex);
ret = -DISK_ERROR_BUSY;
ssdk_printf(SSDK_ERR, "norflash disk unregister:%d\n", ret);
return ret;
}
if (list_in_list(&info->node))
list_delete(&info->node);
xSemaphoreGive(g_disk_mutex);
return ret;
}

View File

@@ -0,0 +1,55 @@
/**
* @file disk_mmc.h
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef DISK_NORFLASH_H_
#define DISK_NORFLASH_H_
#include <disk.h>
#include <lib/list.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
//#include <lib/disk/disk_cache_noop.h>
typedef int (*norflash_read_t)(void *, disk_addr_t, uint8_t *, disk_size_t);
typedef int (*norflash_write_t)(void *, disk_addr_t, const uint8_t *,
disk_size_t);
typedef int (*norflash_erase_t)(void *, disk_addr_t, disk_size_t);
struct disk_norflash_config {
/* disk device name */
char *disk_name;
/* disk attribute */
uint64_t disk_size;
/* write & read sector size */
uint32_t sector_size;
void *norflash_dev;
norflash_read_t norflash_read;
norflash_write_t norflash_write;
norflash_erase_t norflash_erase;
};
struct disk_norflash_info {
uint8_t *buff_sector;
uint32_t buff_size;
QueueHandle_t disk_norflash_mutex;
struct disk_norflash_config config;
struct disk_info info;
// struct disk_cache_noop cache_noop;
};
int register_norflash_disk(struct disk_norflash_info *norflash_info);
int unregister_norflash_disk(struct disk_norflash_info *norflash_info);
#endif /* DISK_NORFLASH_H_ */

195
middleware/disk/disk_usb.c Normal file
View File

@@ -0,0 +1,195 @@
/**
* @file disk_usb.c
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#include <Class/MSC/usbh_msc.h>
#include <debug.h>
#include <disk_usb.h>
#include <errno.h>
#include <param.h>
#include <types.h>
/* Maximum blocks of a single transmission */
#define USB_MAX_XFER_BLKS (240u)
#define disk_usb_err(...) ssdk_printf(SSDK_ERR, __VA_ARGS__)
#define disk_usb_warn(...) ssdk_printf(SSDK_WARNING, __VA_ARGS__)
static int disk_usb_read(struct disk_info *info, uint8_t *dst, disk_addr_t addr,
disk_size_t size)
{
USBH_MSC_DEV *p_msc_dev;
USBH_ERR err_usbh;
CPU_INT32U blk_off;
CPU_INT32U blk_cnt;
CPU_INT32U rd_blks;
p_msc_dev = (USBH_MSC_DEV *)info->private_data;
if (!p_msc_dev || !dst || !size) {
return -EINVAL;
}
blk_off = addr / info->block_align_size;
blk_cnt = size / info->block_align_size;
if ((addr != (disk_addr_t)blk_off * info->block_align_size) ||
(size != (disk_size_t)blk_cnt * info->block_align_size)) {
return -EINVAL;
}
if (!IS_ALIGNED(dst, CONFIG_ARCH_CACHE_LINE) ||
!IS_ALIGNED(dst + size, CONFIG_ARCH_CACHE_LINE)) {
disk_usb_warn(
"unaligned rx buffer %p ++ %llx may cause incorrect data\n", dst,
size);
}
while (blk_cnt > 0) {
rd_blks = blk_cnt > USB_MAX_XFER_BLKS ? USB_MAX_XFER_BLKS : blk_cnt;
(void)USBH_MSC_Rd(p_msc_dev, 0u, (CPU_INT32U)blk_off,
(CPU_INT16U)rd_blks,
(CPU_INT32U)info->block_align_size, dst, &err_usbh);
if (err_usbh != USBH_ERR_NONE) {
disk_usb_err("%s: Could not rd MSC dev, USB err: %d.\n", __func__,
err_usbh);
return -EIO;
}
blk_cnt -= rd_blks;
blk_off += rd_blks;
dst += rd_blks * info->block_align_size;
}
return 0;
}
static int disk_usb_write(struct disk_info *info, const uint8_t *src,
disk_addr_t addr, disk_size_t size)
{
USBH_MSC_DEV *p_msc_dev;
USBH_ERR err_usbh;
CPU_INT32U blk_off;
CPU_INT32U blk_cnt;
CPU_INT32U wr_blks;
p_msc_dev = (USBH_MSC_DEV *)info->private_data;
if (!p_msc_dev || !src || !size) {
return -EINVAL;
}
blk_off = addr / info->block_align_size;
blk_cnt = size / info->block_align_size;
if ((addr != (disk_addr_t)blk_off * info->block_align_size) ||
(size != (disk_size_t)blk_cnt * info->block_align_size)) {
return -EINVAL;
}
if (!IS_ALIGNED(src, CONFIG_ARCH_CACHE_LINE) ||
!IS_ALIGNED(src + size, CONFIG_ARCH_CACHE_LINE)) {
disk_usb_warn(
"unaligned tx buffer %p ++ %llx may cause incorrect data\n", src,
size);
}
while (blk_cnt > 0) {
wr_blks = blk_cnt > USB_MAX_XFER_BLKS ? USB_MAX_XFER_BLKS : blk_cnt;
(void)USBH_MSC_Wr(p_msc_dev, 0u, (CPU_INT32U)blk_off,
(CPU_INT16U)wr_blks,
(CPU_INT32U)info->block_align_size, src, &err_usbh);
if (err_usbh != USBH_ERR_NONE) {
printf("%s: Could not wr MSC dev, USB err: %d.\n", __func__,
err_usbh);
return -EIO;
}
blk_cnt -= wr_blks;
blk_off += wr_blks;
src += wr_blks * info->block_align_size;
}
return 0;
}
static int disk_usb_status(struct disk_info *info) { return DISK_STATUS_OK; }
static int disk_usb_ioctl(struct disk_info *info, uint32_t cmd, void *buff)
{
return 0;
}
static struct disk_operations disk_usb_ops = {
.disk_read = disk_usb_read,
.disk_write = disk_usb_write,
.disk_status = disk_usb_status,
.disk_ioctl = disk_usb_ioctl,
};
int register_usb_disk(struct disk_info *info)
{
USBH_MSC_DEV *p_msc_dev;
USBH_ERR err_usbh;
CPU_INT32U blk_nr, blk_sz;
int ret = 0;
if (!info->disk_name || !info->private_data) {
return -1;
}
p_msc_dev = (USBH_MSC_DEV *)info->private_data;
err_usbh = USBH_MSC_Init(p_msc_dev, 0u);
if (err_usbh != USBH_ERR_NONE) {
disk_usb_err("%s: Could not init MSC dev, USB err: %d.\n", __func__,
err_usbh);
return -err_usbh;
}
err_usbh = USBH_MSC_CapacityRd(p_msc_dev, 0u, &blk_nr, &blk_sz);
if (err_usbh != USBH_ERR_NONE) {
disk_usb_err("%s: Could not get MSC dev capacity, USB err: %d.\n",
__func__, err_usbh);
return -err_usbh;
}
info->cache = NULL;
info->disk_size = (uint64_t)blk_nr * blk_sz;
info->disk_offset = 0;
info->erase_size = blk_sz;
info->mem_align_size = CONFIG_ARCH_CACHE_LINE;
info->block_align_size = blk_sz;
info->disk_ops = &disk_usb_ops;
ret = register_disk(info);
if (ret < 0) {
disk_usb_err("usb disk register err:%d\n", ret);
return ret;
}
return 0;
}
int unregister_usb_disk(struct disk_info *info)
{
int ret = 0;
ret = unregister_disk(info);
if (ret < 0) {
disk_usb_err("usb disk unregister err:%d\n", ret);
return ret;
}
return ret;
}

View File

@@ -0,0 +1,22 @@
/**
* @file disk_usb.h
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef DISK_USB_H
#define DISK_USB_H
#include <disk.h>
int register_usb_disk(struct disk_info *info);
int unregister_usb_disk(struct disk_info *info);
#endif /* DISK_MMC_H_ */

4590
middleware/dloader/dloader.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,238 @@
/*
* dloader.h
*
* Copyright (c) 2020 SemiDrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef _DLOADER_H_
#define _DLOADER_H_
#include <debug.h>
#include <disk/disk.h>
#define MAX_DEV_INST_OF_DISK 3
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MD5_LEN
#define MD5_LEN 16
#endif
#ifndef MAX_GPT_NAME_SIZE
#define MAX_GPT_NAME_SIZE 72
#endif
#define DL_DEBUG_ON 1
#if DL_DEBUG_ON
#define ERROR(format, args...) \
ssdk_printf(SSDK_CRIT, "[ERROR]DLOADER:%s %d " format "", __func__, \
__LINE__, ##args);
#define DBG(format, args...) \
ssdk_printf(SSDK_CRIT, "[DEBUG]DLOADER:%s %d " format "", __func__, \
__LINE__, ##args);
#else
#define ERROR(format, args...)
#define DBG(format, args...)
#endif
#define SPARSE_HEADER_MAGIC 0xed26ff3a
#define CHUNK_TYPE_RAW 0xCAC1
#define CHUNK_TYPE_FILL 0xCAC2
#define CHUNK_TYPE_DONT_CARE 0xCAC3
#define CHUNK_TYPE_CRC 0xCAC4
typedef enum dl_err_code {
ERR_NONE = 0,
ERR_UNKNOWN = 0x1,
ERR_FLASH1_INIT_FAIL,
ERR_EMMC1_INIT_FAIL,
ERR_SD1_INIT_FAIL,
ERR_PRI_PTB_NOT_MATCH,
ERR_SUB_PTB_NOT_MATCH,
ERR_PT_NOT_FOUND,
ERR_IMAGE_TOO_LARGE,
ERR_IMAGE_FORMAT_ERR,
ERR_PRI_PTB_NOT_FLASH,
ERR_SUB_PTB_NOT_FLASH,
ERR_PT_READ_FAIL,
ERR_PT_FLASH_FAIL,
ERR_PT_ERASE_FAIL,
ERR_PT_OVERLAP,
ERR_PT_FULL_NAME_FORMAT,
ERR_INVALID_BLOCK_SIZE,
ERR_SPARSE_IMAGE_SIZE_TOO_LOW,
ERR_SPARSE_IMAGE_HEADER,
ERR_SPARSE_IMAGE_BUFFERED,
ERR_SPARSE_IMAGE_CHUNK_HEADER,
ERR_SPARSE_IMAGE_CHUNK_TOO_LARGE,
ERR_SPARSE_IMAGE_CHUNK_NOT_MATCH,
ERR_SPARSE_IMAGE_CHUNK_UNKNOWN,
ERR_SPARSE_IMAGE_MALLOC,
ERR_SPARSE_IMAGE_DO_NOT_SUPPORT,
ERR_HASH_FAIL,
ERR_EFUSE_INDEX,
ERR_EFUSE_BURN,
ERR_EFUSE_READ,
ERR_SWITCH_PART,
ERR_CMD_ERROR,
ERR_PT_BASE_ERROR,
ERR_PT_SIZE_ERROR,
ERR_PTNAME_NOT_EXIST,
ERR_DISK_NOT_EXIST,
ERR_DISK_OPEN_ERROR,
ERR_PARTITION_READ_ERROR,
HYPER_FLASH_FUSE_READ_ERROR,
HYPER_FLASH_FUSE_WRITE_ERROR,
HYPER_FLASH_FUSE_VAL_ERROR,
VERIFY_SIZE_ERROR,
CAN_NOT_FIND_A_DOWNLOAD_FUNCTION,
CAN_NOT_FIND_A_ERASE_FUNCTION,
CAN_NOT_FIND_A_VERIFY_FUNCTION,
ERR_HASH_FAIL_FROM_PC,
ERR_DL_FUSE_SIZE_CHECK_FAIL,
ERR_DL_FUSE_LENGTH_CHECK_FAIL,
ERR_DL_FUSE_ACTION_TYPE_NOT_FIND,
ERR_DL_FUSE_CRC_CHECK_FAIL,
ERR_DL_FUSE_ENC_INIT_FAIL,
ERR_DL_FUSE_ENC_FAIL,
ERR_DL_FUSE_MALLOC_FAIL,
ERR_DL_FUSE_GEN_DATA_FAIL,
ERR_DL_FUSE_READBACK_VERIFY_FAIL,
ERR_GET_SFS_FORM_MSFS_FAIL,
ERR_MAX,
} DL_ERR_CODE_E;
typedef enum partition_type_enum {
TYPE_PT_UNKNOWN = 0,
TYPE_PRI_PTB,
TYPE_PRI_PT,
TYPE_SUB_PTB,
TYPE_SUB_PT,
TYPE_SUB_PT_WHOLE,
TYPE_ALL_PT, /* only for erase all partitions in the gpt */
TYPE_NOT_IN_GPT = 0x100,
TYPE_BOOT_PACK0,
TYPE_BOOT_PACK1,
TYPE_BOOT_PACK2,
TYPE_SAFETY_SFS_PT,
TYPE_SAFETY_RFD_PT,
TYPE_ADD_DIRECT,
} PARTITION_TYPE_E;
typedef enum dev_inst_enum {
FLASH_DEV_INST = 0,
EMMC_USER_SPACE_DEV_INST = 0,
EMMC_BOOT1_DEV_INST = 1,
EMMC_BOOT2_DEV_INST = 2,
EMMC_DEV_INST_MAX,
} DEV_INST_E;
typedef enum disk_type_enum {
MMC,
NORFLASH,
RAMDISK,
USBDISK,
ALLDISK,
STORAGE_TYPE_NM,
} DISK_TYPE_E;
struct ptb_dl_name {
struct list_node node;
char *name;
};
/* record downloaded state */
typedef struct dl_state {
const char download_name[MAX_GPT_NAME_SIZE + 1];
const char disk_name[MAX_GPT_NAME_SIZE + 1];
const char disk_boot1_name[MAX_GPT_NAME_SIZE + 1];
const char disk_boot2_name[MAX_GPT_NAME_SIZE + 1];
DISK_TYPE_E disk_type;
struct disk_dev *disk_inst[MAX_DEV_INST_OF_DISK];
uint32_t block_size;
uint32_t erase_size;
uint64_t capacity;
struct partition_device *ptdev;
uint64_t ptb_offset;
PARTITION_TYPE_E partiton_type;
char ptname[MAX_GPT_NAME_SIZE + 1];
char sub_ptbname[MAX_GPT_NAME_SIZE + 1];
const uint64_t boot_offset;
} DL_STATE_T;
typedef struct command_table {
PARTITION_TYPE_E partiton_type;
DISK_TYPE_E disk_type;
DL_ERR_CODE_E(*flash_callback)
(DL_STATE_T *ds, void *data, unsigned sz, uint8_t sparse_data);
DL_ERR_CODE_E (*erase_cmd_callback)(DL_STATE_T *ds);
DL_ERR_CODE_E (*verify_cmd_callback)(DL_STATE_T *ds);
char *download_cmd_name;
char *erase_cmd_name;
} COMMAND_TABLE_T;
typedef struct download_type_table {
char *ptname;
uint8_t is_sub_pt;
char *type_name;
PARTITION_TYPE_E partiton_type;
} DOWNLOAD_TYPE_TABLE_T;
typedef struct sparse_header {
uint32_t magic; /* 0xed26ff3a */
uint16_t
major_version; /* (0x1) - reject images with higher major versions */
uint16_t minor_version; /* (0x0) - allow images with higer minor versions */
uint16_t file_hdr_sz; /* 28 bytes for first revision of the file format */
uint16_t chunk_hdr_sz; /* 12 bytes for first revision of the file format */
uint32_t blk_sz; /* block size in bytes, must be a multiple of 4 (4096) */
uint32_t total_blks; /* total blocks in the non-sparse output image */
uint32_t total_chunks; /* total chunks in the sparse input image */
uint32_t image_checksum; /* CRC32 checksum of the original data, counting
"don't care" */
/* as 0. Standard 802.3 polynomial, use a Public Domain */
/* table implementation */
} sparse_header_t;
typedef struct chunk_header {
uint16_t
chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
uint16_t reserved1;
uint32_t chunk_sz; /* in blocks in output image */
uint32_t total_sz; /* in bytes of chunk input file including chunk header
and data */
} chunk_header_t;
extern void *dl_scratch_base;
extern uint32_t dl_scratch_sz;
extern void *dl_data_base;
extern uint32_t dl_data_sz;
extern DL_STATE_T *parse_partition_name(const char *full_ptname,
DL_ERR_CODE_E *err);
extern int dloader_init(void);
extern void read_sfs(DL_STATE_T *ds);
extern void read_rfd(DL_STATE_T *ds);
extern uint8_t md5_received[MD5_LEN];
extern DL_ERR_CODE_E dl_cmd_flash(const char *arg, void *data, unsigned sz);
extern DL_ERR_CODE_E dl_cmd_erase(const char *arg, void *data, unsigned sz);
int dl_disk_read(struct disk_dev *dev, disk_addr_t addr, uint8_t *dst,
disk_size_t size);
int dl_disk_write(struct disk_dev *dev, disk_addr_t addr, uint8_t *src,
disk_size_t size);
int dl_disk_erase(struct disk_dev *dev, disk_addr_t addr, disk_size_t size);
char *response_error(enum dl_err_code err, const char *pname);
#endif

View File

@@ -0,0 +1,139 @@
/**
* @file partition_disk_io.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#include <compiler.h>
#include <debug.h>
#include <disk.h>
#include <md5.h>
#include <param.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include "dloader.h"
/**
* @brief dl_disk_read
*
* @param dev disk device
* @param addr read addr
* @param dst data destination
* @param size read size
* @return int 0 success other if failed
*/
int dl_disk_read(struct disk_dev *dev, disk_addr_t addr, uint8_t *dst,
disk_size_t size)
{
#if CONFIG_DLOADER_BLOCK_IO_MODE
if (NULL == dev || NULL == dev->info) {
ERROR("no disk device node\r\n");
return -1;
}
if (!dev->block_size || !IS_ALIGNED(addr, dev->block_size) ||
!IS_ALIGNED(size, dev->block_size)) {
ERROR("addr 0x%llx or size 0x%llx not aligned to block_size = %d\r\n",
addr, size, dev->block_size);
return -1;
}
if (!IS_ALIGNED(dst, dev->info->mem_align_size)) {
ERROR("mem addresses 0x%p not aligned to 0x%x\r\n", dst,
dev->info->mem_align_size);
return -1;
}
return disk_read_block(dev, addr / (dev->block_size), dst,
size / (dev->block_size));
#else
return disk_read(dev, addr, dst, size);
#endif
}
/**
* @brief dl_disk_write
*
* @param dev disk device
* @param addr write addr
* @param src data source
* @param size write size
* @return int 0 success other if failed
*/
int dl_disk_write(struct disk_dev *dev, disk_addr_t addr, uint8_t *src,
disk_size_t size)
{
#if CONFIG_DLOADER_BLOCK_IO_MODE
if (NULL == dev || NULL == dev->info) {
ERROR("no disk device node\r\n");
return -1;
}
if (!dev->block_size || !IS_ALIGNED(addr, dev->block_size) ||
!IS_ALIGNED(size, dev->block_size)) {
ERROR("addr 0x%llx or size 0x%llx not aligned to block_size = %d\r\n",
addr, size, dev->block_size);
return -1;
}
if (!IS_ALIGNED(src, dev->info->mem_align_size)) {
ERROR("mem addresses 0x%p not aligned to 0x%x\r\n", src,
dev->info->mem_align_size);
return -1;
}
return disk_write_block(dev, addr / (dev->block_size), src,
size / (dev->block_size));
#else
return disk_write(dev, addr, src, size);
#endif
}
/**
* @brief dloader disk erase
*
* @param dev disk device
* @param addr erase addr
* @param size erase size
* @return int 0 success
*/
int dl_disk_erase(struct disk_dev *dev, disk_addr_t addr, disk_size_t size)
{
#if CONFIG_DLOADER_BLOCK_IO_MODE
if (NULL == dev || NULL == dev->info) {
ERROR("no disk device node\r\n");
return -1;
}
if (strstr(dev->info->disk_name, "flash")) {
if (!dev->info->erase_size ||
!IS_ALIGNED(addr, dev->info->erase_size) ||
!IS_ALIGNED(size, dev->info->erase_size)) {
ERROR(
"addr 0x%llx or size 0x%llx not aligned to erase_size = %d\r\n",
addr, size, dev->info->erase_size);
return -1;
}
return disk_erase_group(dev, addr / (dev->info->erase_size),
size / (dev->info->erase_size),
DISK_ERASE_DEFAULT);
} else {
return disk_erase(dev, addr, size, DISK_ERASE_DEFAULT);
}
#else
return disk_erase(dev, addr, size, DISK_ERASE_DEFAULT);
#endif
}

View File

@@ -0,0 +1,70 @@
#include <dloader.h>
#include <dloader_usb_fastboot.h>
#include <fuse_bin.h>
static DL_ERR_CODE_E dloader_convert_return_value(FUSE_ERR_CODE_E ret)
{
DL_ERR_CODE_E err = ERR_NONE;
switch (ret) {
case ERR_NONE:
err = ERR_NONE;
break;
case ERR_UNKNOWN:
err = ERR_UNKNOWN;
break;
case ERR_FUSE_BIN_SIZE_CHECK_FAIL:
err = ERR_DL_FUSE_SIZE_CHECK_FAIL;
break;
case ERR_FUSE_BIN_LENGTH_CHECK_FAIL:
err = ERR_DL_FUSE_LENGTH_CHECK_FAIL;
break;
case ERR_FUSE_BIN_ACTION_TYPE_NOT_FIND:
err = ERR_DL_FUSE_ACTION_TYPE_NOT_FIND;
break;
case ERR_FUSE_BIN_CRC_CHECK_FAIL:
err = ERR_DL_FUSE_CRC_CHECK_FAIL;
break;
case ERR_FUSE_BIN_ENC_INIT_FAIL:
err = ERR_DL_FUSE_ENC_INIT_FAIL;
break;
case ERR_FUSE_BIN_ENC_FAIL:
err = ERR_DL_FUSE_ENC_FAIL;
break;
case ERR_FUSE_BIN_MALLOC_FAIL:
err = ERR_DL_FUSE_MALLOC_FAIL;
break;
case ERR_FUSE_BIN_GEN_DATA_FAIL:
err = ERR_DL_FUSE_GEN_DATA_FAIL;
break;
case ERR_FUSE_BIN_READ_FAIL:
err = ERR_EFUSE_READ;
break;
case ERR_FUSE_BIN_WRITE_FAIL:
err = ERR_EFUSE_BURN;
break;
case ERR_FUSE_BIN_READBACK_VERIFY_FAIL:
err = ERR_DL_FUSE_READBACK_VERIFY_FAIL;
break;
default:
break;
}
return err;
}
void fastboot_cmd_fuse_bin(fastboot_t *fb, const char *arg, void *data,
unsigned sz)
{
FUSE_ERR_CODE_E ret;
DL_ERR_CODE_E err;
ret = fuse_bin(data, sz);
err = dloader_convert_return_value(ret);
if (err) {
ERROR("fuse bin error\r\n");
fastboot_common_fail(fb, response_error(err, arg));
} else {
DBG("fuse bin success\r\n");
}
fastboot_common_okay(fb, "");
}

View File

@@ -0,0 +1,4 @@
#include <dloader_usb_fastboot.h>
void fastboot_cmd_fuse_bin(fastboot_t *fb, const char *arg, void *data,
unsigned sz);

View File

@@ -0,0 +1,566 @@
/**
* @file dloader_test.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#include <CLI.h>
#include <armv7-r/cache.h>
#include <board.h>
#include <ctype.h>
#include <debug.h>
#include <md5.h>
#include <param.h>
#include <part.h>
#include <partition_parser.h>
#include <sd_boot_img.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include "checksum/crc32.h"
#include "dloader.h"
#if CONFIG_E3104 == 0
#define DL_TEST_STACK_SIZE 8192
#define DL_TEST_ARGV_NUM 10
#define DL_TEST_ARGV_LEN 50
#if CONFIG_DLOADER_BLOCK_IO_MODE
#define DL_LENGTH_ALIGN 512
#else
#define DL_LENGTH_ALIGN 128
#endif
#define DL_ADDR_ALIGN 512
#define DL_MD5RAM_ALIGN 512
#define DL_MD5DISK_ALIGN 512
typedef struct dl_test_arg {
int argc;
char argv[DL_TEST_ARGV_NUM][DL_TEST_ARGV_LEN];
} dl_test_arg_t;
static dl_test_arg_t dl_test_arg = {0};
static SemaphoreHandle_t new_msg_event;
static TaskHandle_t dloader_process_thread;
extern uint32_t sfs_get_image_base(DL_STATE_T *ds, uint8_t num);
extern int32_t get_bpt_info(struct bpt *bpt, uint8_t *buffer, uint32_t len);
/**
* @brief hexdump an buffer. The addresss could be set
* @param disk_addr
* @param ptr
* @param len
*/
static void dl_hexdump(uint64_t disk_addr, const void *ptr, size_t len)
{
addr_t address = (addr_t)ptr;
size_t count;
for (count = 0; count < len; count += 16) {
union {
uint32_t buf[4];
uint8_t cbuf[16];
} u;
size_t s = ROUNDUP(MIN(len - count, 16), 4);
size_t i;
printf("0x%08x: ", (uint32_t)disk_addr);
for (i = 0; i < s / 4; i++) {
u.buf[i] = ((const uint32_t *)address)[i];
printf("%08x ", u.buf[i]);
}
for (; i < 4; i++) {
printf(" ");
}
printf("|");
for (i = 0; i < 16; i++) {
unsigned char c = u.cbuf[i];
if (i < s && isprint(c)) {
printf("%c", c);
} else {
printf(".");
}
}
printf("|\n");
address += 16;
disk_addr += 16;
}
}
/**
* @brief Get the inst num of disk
* @param partiton_type
* @return uint8_t
*/
static uint8_t get_inst_num(PARTITION_TYPE_E partiton_type)
{
uint8_t inst_num = 0;
if (TYPE_BOOT_PACK0 == partiton_type)
inst_num = 1;
else if (TYPE_BOOT_PACK1 == partiton_type)
inst_num = 2;
DBG("disk_inst= %d\n", inst_num);
return inst_num;
}
static uint8_t read_bpt(DL_STATE_T *ds, uint8_t bpt_num)
{
struct bpt *bpt = NULL;
struct iib *iib = NULL;
uint64_t addr = 0;
uint64_t length = 0;
uint8_t inst_num = 0;
uint32_t crc32_val = 0;
uint32_t i = 0;
if (ds->disk_type == NORFLASH) {
addr = sfs_get_image_base(ds, bpt_num);
inst_num = 0;
} else if (0 == bpt_num) {
addr = 0;
inst_num = 1;
} else if (1 == bpt_num) {
addr = 0;
inst_num = 2;
} else if (2 == bpt_num) {
addr = 0x5000;
inst_num = 0;
}
length = 0x1000;
DBG("read inst %d addr 0x%llx, len %lld for BPT\n", inst_num, addr, length);
memset((uint8_t *)dl_scratch_base, 0, length);
if (dl_disk_read(ds->disk_inst[inst_num], addr, (uint8_t *)dl_scratch_base,
length)) {
ERROR("read storage failed\n");
return 1;
}
crc32_val = sfs_crc32(0, (uint8_t *)dl_scratch_base, 0xFEC);
bpt = (struct bpt *)pvPortMallocAligned(sizeof(struct bpt), ds->block_size);
if (0 != get_bpt_info(bpt, (uint8_t *)dl_scratch_base, length)) {
free(bpt);
return 1;
} else {
DBG("bpt->tag = 0x%08x\n", bpt->tag);
DBG("bpt->size = 0x%x\n", bpt->size);
DBG("bpt->sec_version = 0x%08x\n", bpt->sec_version);
DBG("bpt->hash_alg = 0x%x\n", bpt->hash_alg);
DBG("bpt->crc32 = 0x%08x(crc32_val=0x%08x)\n",
bpt->crc32, crc32_val);
DBG("bpt->pac_serial_num = 0x%08x\n", bpt->pac_serial_num);
DBG("bpt->inver_pac_serial_num = 0x%08x\n", bpt->inver_pac_serial_num);
for (i = 0; i < 8; i++) {
iib = &bpt->iib[i];
if ((iib->tag != IIB_TAG)) {
DBG("iib[%d] is none\n", i);
break;
}
DBG("--------\n");
DBG("iib[%d]->tag = 0x%x\n", i, iib->tag);
DBG("iib[%d]->size = 0x%x\n", i, iib->size);
DBG("iib[%d]->image_type = 0x%x\n", i, iib->image_type);
DBG("iib[%d]->target_core = 0x%x\n", i, iib->target_core);
DBG("iib[%d]->decryp_ctl = 0x%x\n", i, iib->decryp_ctl);
DBG("iib[%d]->dev_logic_page = 0x%08x\n", i, iib->dev_logic_page);
DBG("iib[%d]->image_size = 0x%08x\n", i, iib->image_size);
DBG("iib[%d]->load_base = 0x%08x\n", i, iib->load_base);
DBG("iib[%d]->entry_point = 0x%08x\n", i, iib->entry_point);
}
free(bpt);
return 0;
}
}
/**
* @brief dloader test thread
* @param arg
*/
static void dloader_test_thread(void *arg)
{
uint64_t length_total = 0;
uint32_t total_sec = 0;
uint32_t left_sec = 0;
uint32_t i = 0;
uint8_t inst_num = 0;
char *addrsuffix;
uint32_t crc32_val = 0;
uint8_t md5_calc[MD5_LEN] = {0};
struct MD5Context context;
DL_STATE_T *ds = NULL;
uint64_t addr = 0;
uint64_t length = 0;
DL_ERR_CODE_E err;
while (true) {
if (pdTRUE != xSemaphoreTake(new_msg_event, portMAX_DELAY)) {
break;
}
DBG("dloader thread active\n");
ds = NULL;
inst_num = 0;
crc32_val = 0;
memset(md5_calc, 0, MD5_LEN);
/* disk read test */
if (!strcmp(dl_test_arg.argv[0], "read")) {
if (dl_test_arg.argc < 2) {
ERROR("dl read need at least 2 arg\n");
continue;
}
ds = parse_partition_name((const char *)dl_test_arg.argv[1], &err);
if (!ds) {
ERROR("partition name error\n");
continue;
}
if (ds->disk_type == MMC)
inst_num = get_inst_num(ds->partiton_type);
/* read sfs */
if (!strcmp(ds->ptname, "sfs") && (ds->disk_type == NORFLASH)) {
DBG("read sfs\n");
read_sfs(ds);
continue;
}
if (!strcmp(ds->ptname, "rfd") && (ds->disk_type == NORFLASH)) {
DBG("read rfd\n");
read_rfd(ds);
continue;
}
/* read partition table */
if (!strcmp(ds->ptname, "partition")) {
DBG("read partition\n");
ptdev_read_table(ds->ptdev);
ptdev_dump(ds->ptdev);
continue;
}
/* read a partition address in storage device */
else if (!strcmp(ds->ptname, "bpt0")) {
read_bpt(ds, 0);
continue;
}
/* read a partition address in storage device */
else if (!strcmp(ds->ptname, "bpt1")) {
read_bpt(ds, 1);
continue;
}
/* read a partition address in storage device */
else if (!strcmp(ds->ptname, "bpt2")) {
read_bpt(ds, 2);
continue;
}
/* read a partition address in storage device */
else if (dl_test_arg.argc <= 3 && 0 == inst_num) {
if (!ds->ptdev) {
ERROR("partition is null\n");
continue;
}
addr = ptdev_get_offset(ds->ptdev, ds->ptname);
length = ptdev_get_size(ds->ptdev, ds->ptname);
DBG("read partition cmd addr 0x%llx, len %lld\n", addr, length);
if (dl_test_arg.argc == 3) {
DBG("argv[2] = %s(0x%08x)\n", dl_test_arg.argv[2],
atoi(dl_test_arg.argv[2]));
length = atoi(dl_test_arg.argv[2]);
DBG("length is changed to %lld\n", length);
}
if (!length || addr % DL_ADDR_ALIGN ||
length % DL_LENGTH_ALIGN) {
ERROR("do not align\n");
continue;
}
total_sec = length / DL_LENGTH_ALIGN;
for (i = 0; i < total_sec; i++) {
memset((uint8_t *)dl_scratch_base, 0, DL_LENGTH_ALIGN);
if (dl_disk_read(ds->disk_inst[0], addr,
(uint8_t *)dl_scratch_base,
DL_LENGTH_ALIGN)) {
ERROR("read storage failed\n");
continue;
}
dl_hexdump(addr, (void *)dl_scratch_base, DL_LENGTH_ALIGN);
addr += DL_LENGTH_ALIGN;
}
continue;
}
/* read any address in storage device */
else if (dl_test_arg.argc == 4) {
addr = (addr_t)strtoull(dl_test_arg.argv[2], &addrsuffix, 16);
length = atoi(dl_test_arg.argv[3]);
DBG("read addr cmd addr 0x%llx, len %lld\n", addr, length);
if (addr % DL_ADDR_ALIGN || length % DL_LENGTH_ALIGN ||
!length) {
ERROR("do not align\n");
continue;
}
if (dl_disk_read(ds->disk_inst[inst_num], addr,
(uint8_t *)dl_scratch_base,
MIN(length, dl_scratch_sz))) {
ERROR("read storage failed\n");
continue;
}
dl_hexdump((uint64_t)atoi(dl_test_arg.argv[2]),
(void *)dl_scratch_base, atoi(dl_test_arg.argv[3]));
crc32_val = crc32(0, (uint8_t *)dl_scratch_base,
MIN(length, dl_scratch_sz));
DBG("crc32_val = 0x%08x\n", crc32_val);
}
}
/* md5 calc for disk */
else if (!strcmp(dl_test_arg.argv[0], "md5disk")) {
if (dl_test_arg.argc != 4) {
ERROR("md5disk need 4 arg\n");
continue;
}
ds = parse_partition_name((const char *)dl_test_arg.argv[1], &err);
if (!ds) {
ERROR("partition name error\n");
continue;
}
if (ds->disk_type == MMC)
inst_num = get_inst_num(ds->partiton_type);
addr = (addr_t)strtoull(dl_test_arg.argv[2], &addrsuffix, 16);
length = atoi(dl_test_arg.argv[3]);
printf("disk md5 cmd addr 0x%llx, len %lld\n", addr, length);
MD5Init(&context);
if (addr % DL_ADDR_ALIGN || length % DL_LENGTH_ALIGN) {
ERROR("do not align\n");
continue;
}
total_sec = length / DL_LENGTH_ALIGN;
for (i = 0; i < total_sec; i++) {
memset((uint8_t *)dl_scratch_base, 0, DL_LENGTH_ALIGN);
if (dl_disk_read(ds->disk_inst[inst_num], addr,
(uint8_t *)dl_scratch_base, DL_LENGTH_ALIGN)) {
ERROR("read storage failed\n");
continue;
}
crc32_val = crc32(crc32_val, (uint8_t *)dl_scratch_base,
DL_LENGTH_ALIGN);
MD5Update(&context, (uint8_t *)dl_scratch_base,
DL_LENGTH_ALIGN);
addr += DL_LENGTH_ALIGN;
}
DBG("crc32_val = 0x%08x\n", crc32_val);
MD5Final(md5_calc, &context);
dl_hexdump(0, (void *)md5_calc, MD5_LEN);
continue;
}
/* md5 calc for ram */
else if (!strcmp(dl_test_arg.argv[0], "md5ram")) {
if (dl_test_arg.argc != 3) {
ERROR("md5ram need 3 arg\n");
continue;
}
addr = (addr_t)strtoull(dl_test_arg.argv[1], &addrsuffix, 16);
length = atoi(dl_test_arg.argv[2]);
printf("ram md5 cmd addr 0x%llx, len %lld\n", addr, length);
MD5Init(&context);
if (addr % DL_ADDR_ALIGN || length % DL_LENGTH_ALIGN) {
ERROR("do not align\n");
continue;
}
total_sec = length / DL_MD5RAM_ALIGN;
for (i = 0; i < total_sec; i++) {
memset((uint8_t *)dl_scratch_base, 0, DL_MD5RAM_ALIGN);
memcpy((uint8_t *)dl_scratch_base, (void *)(uint32_t)addr,
DL_MD5RAM_ALIGN);
crc32_val = crc32(crc32_val, (uint8_t *)dl_scratch_base,
DL_MD5RAM_ALIGN);
MD5Update(&context, (uint8_t *)dl_scratch_base,
DL_MD5RAM_ALIGN);
addr += DL_MD5RAM_ALIGN;
}
DBG("crc32_val = 0x%08x\n", crc32_val);
MD5Final(md5_calc, &context);
dl_hexdump(0, (void *)md5_calc, MD5_LEN);
continue;
}
/* flash command test */
else if (!strcmp(dl_test_arg.argv[0], "flash")) {
if (dl_test_arg.argc != 4) {
ERROR("dl flash need at least 4 arg\n");
continue;
}
addr = (addr_t)strtoull(dl_test_arg.argv[2], &addrsuffix, 16);
length_total = (uint32_t)atoi(dl_test_arg.argv[3]);
DBG("flash cmd = %s, addr 0x%llx, len %lld\n",
(const char *)dl_test_arg.argv[1], addr, length_total);
total_sec = ((uint32_t)length_total) / dl_data_sz;
left_sec = ((uint32_t)length_total) % dl_data_sz;
DBG("total_sec = %d, left_sec = %d \n", total_sec, left_sec);
for (i = 0; i <= total_sec; i++) {
if (i == total_sec) {
length = left_sec;
} else {
length = dl_data_sz;
}
if (0 == (uint32_t)length)
break;
DBG("flash data from addr = %d, length = %d \n", (uint32_t)addr,
(uint32_t)length);
md5((const uint8_t *)(uint32_t)addr, length, md5_received);
if (dl_cmd_flash((const char *)dl_test_arg.argv[1],
(void *)(uint32_t)addr, (uint32_t)length)) {
ERROR("dl_cmd_flash error\n");
continue;
}
addr += length;
}
DBG("md5_received :\n");
dl_hexdump(0, (void *)md5_received, MD5_LEN);
DBG("dl_cmd_flash finish\n");
continue;
}
/* erase command test*/
else if (!strcmp(dl_test_arg.argv[0], "erase")) {
if (dl_test_arg.argc != 2) {
ERROR("dl flash need at least 2 arg\n");
continue;
}
DBG("cmd = %s\n", (const char *)dl_test_arg.argv[1]);
dl_cmd_erase((const char *)dl_test_arg.argv[1], dl_data_base, 0);
continue;
}
}
}
/**
* @brief test app for dloader
* @param argc
* @param argv
* @return int
*/
static int dloader_test(int argc, char *argv[])
{
int i = 0;
static bool dl_test_thread_on = 0;
if (0 == dl_test_thread_on) {
if (!strcmp(argv[0], "init")) {
dl_test_thread_on = 1;
/* test thread */
new_msg_event = xSemaphoreCreateCounting(1, 0);
xTaskCreate(dloader_test_thread, "dloader_test", DL_TEST_STACK_SIZE,
NULL, (tskIDLE_PRIORITY + 2), &dloader_process_thread);
if (!dloader_process_thread) {
ERROR("failed to dloader_test process thread\n");
return CLI_FALSE;
}
DBG("download test init success\n");
return CLI_FALSE;
}
}
if (argc == 0) {
ERROR("need in put arg\n");
return CLI_FALSE;
}
if (argc > DL_TEST_ARGV_NUM) {
ERROR("too many arg\n");
return CLI_FALSE;
}
DBG("dloader argc = %d\n", argc);
dl_test_arg.argc = argc;
for (i = 0; i < dl_test_arg.argc; i++) {
memset(dl_test_arg.argv[i], 0, DL_TEST_ARGV_LEN);
strncpy(dl_test_arg.argv[i], argv[i], DL_TEST_ARGV_LEN - 1);
DBG("dl_test_arg.argc[%d] = %s\n", i, dl_test_arg.argv[i]);
}
DBG("event set!\r\n");
xSemaphoreGive(new_msg_event);
return CLI_FALSE;
}
CLI_CMD("dl", "download test", dloader_test);
#endif

View File

@@ -0,0 +1,449 @@
/**
* @file dloader_usb_fastboot.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description: usb fastboot package.
*
* Revision History:
* -----------------
*/
#include <Source/usbd_core.h>
#include <board.h>
#include <part.h>
#include <reg.h>
#include <stdbool.h>
#include <usb_bsp.h>
#include "dloader_usb_fastboot.h"
#include "regs_base.h"
#include "sdrv_fuse.h"
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
#define SD_VENDOR_ID 0x3273
#ifdef CONFIG_E3L
#define SD_PRODUCT_ID 0x0003
#else
#define SD_PRODUCT_ID 0x0002
#endif
#else
#define SD_VENDOR_ID 0x18d1
#define SD_PRODUCT_ID 0x4d00
#endif
#define SD_VERSION_ID 0x0100
#define SD_FB_CFG_MAX_NBR_CMD 20u
#define SD_FB_CFG_MAX_NBR_VAR 20u
#define ANDROID_VENDOR_ID 0x18d1
#define ANDROID_PRODUCT_ID 0x4d00
#define SD_ROM_PATCH0_INDEX 112
#define SD_PID_INDEX 12
#define SD_UID_INDEX 4
#define SD_MINOR_INDEX 6
#define ERROR(format, args...) \
ssdk_printf(SSDK_CRIT, "[ERROR]DLOADER_USB_FB:%s %d " format "", __func__, \
__LINE__, ##args);
#define DBG(format, args...) \
ssdk_printf(SSDK_CRIT, "[DEBUG]DLOADER_USB_FB:%s %d " format "", __func__, \
__LINE__, ##args);
static char usbd_fb_serial[17] = "0000000000000000";
static char usbd_product_str[5] = "0000";
static USBD_DRV_EP_INFO USBD_DrvEP_InfoTbl[] = {
{USBD_EP_INFO_TYPE_CTRL | USBD_EP_INFO_DIR_OUT, 0u, 64u},
{USBD_EP_INFO_TYPE_CTRL | USBD_EP_INFO_DIR_IN, 0u, 64u},
{USBD_EP_INFO_TYPE_ISOC | USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT |
USBD_EP_INFO_DIR_IN,
1u, 512u},
{USBD_EP_INFO_TYPE_ISOC | USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT |
USBD_EP_INFO_DIR_IN,
2u, 512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 3u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 4u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 5u,
512u},
{USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 6u,
64u},
{USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 7u,
64u},
{USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 8u,
64u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 9u,
512u},
{USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 10u,
64u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 11u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 12u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 13u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 14u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 15u,
512u},
{DEF_BIT_NONE, 0u, 0u}};
USBD_DEV_CFG FB_USBD_DevCfg = {
SD_VENDOR_ID, /* Vendor ID. */
SD_PRODUCT_ID, /* Product ID. */
SD_VERSION_ID, /* Device release number. */
"Semidrive", /* Manufacturer string. */
usbd_product_str, /* Product string. */
usbd_fb_serial, /* Serial number string. */
USBD_LANG_ID_ENGLISH_US /* String language ID. */
};
static const USBD_DRV_CFG FB_USBD_DrvCfg = {
DEVICE_BASE(USB0D), /* Base addr of device controller hw registers. */
0u, /* Base addr of device controller dedicated mem. */
0u, /* Size of device controller dedicated mem. */
#if (USBD_CFG_HS_EN == DEF_ENABLED)
USBD_DEV_SPD_HIGH, /* Speed of device controller. */
#else
USBD_DEV_SPD_FULL,
#endif
USBD_DrvEP_InfoTbl /* EP Info tbl of device controller. */
};
/* Donnot care about bus events. */
static USBD_BUS_FNCTS FB_USBD_BusFncts;
static fastboot_dev_t fb_dev = {USBD_CLASS_NBR_NONE, USBD_DEV_NBR_NONE};
static USBD_FB_CMD fb_cmd_tbl[SD_FB_CFG_MAX_NBR_CMD] = {
{"getvar:", USBD_FB_CmdGetVar},
{"download:", USBD_FB_CmdDownload},
};
static CPU_INT16U fb_cmd_len = 2;
static USBD_FB_VAR fb_var_tbl[SD_FB_CFG_MAX_NBR_VAR] = {
{"version", "0.5"},
{"name", "fastboot"},
};
static CPU_INT16U fb_var_len = 2;
static void get_product_no(void)
{
uint32_t product_id = 0;
usbd_product_str[4] = 0;
uint8_t *buf = NULL;
uint32_t ret = 0;
buf = (uint8_t *)&product_id;
ret = sdrv_fuse_sense(SD_MINOR_INDEX, &product_id);
if (ret) {
ERROR("fuse_sense error, use product no = 0000\r\n");
return;
}
snprintf(usbd_product_str, sizeof(usbd_product_str), "%02X%02X", buf[1],
buf[0]);
DBG("usbd_product str = %s\r\n", usbd_product_str);
}
static void get_serialno(void)
{
uint32_t serial_fuse[2] = {0};
uint8_t *buf = NULL;
uint32_t ret = 0;
ret = sdrv_fuse_sense(SD_UID_INDEX, &serial_fuse[0]);
ret |= sdrv_fuse_sense(SD_UID_INDEX + 1, &serial_fuse[1]);
usbd_fb_serial[16] = 0;
if (ret) {
ERROR("fuse_sense error, use serialno = 0000000000000000\r\n");
return;
}
buf = (uint8_t *)serial_fuse;
snprintf(usbd_fb_serial, sizeof(usbd_fb_serial),
"%02X%02X%02X%02X%02X%02X%02X%02X", buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7]);
DBG("patched usbd_fb_serial = %s\r\n", usbd_fb_serial);
}
static void get_vid_pid(uint16_t *vid, uint16_t *pid)
{
uint32_t pid_vid_fuse = 0;
uint32_t use_semidrive_pid_vid = 0;
uint32_t ret = 0;
ret = sdrv_fuse_sense(SD_PID_INDEX, &pid_vid_fuse);
ret |= sdrv_fuse_sense(SD_ROM_PATCH0_INDEX, &use_semidrive_pid_vid);
if (ret) {
*pid = ANDROID_PRODUCT_ID;
*vid = ANDROID_VENDOR_ID;
ERROR("fuse_sense error, use pid = 0x%04x , vid = 0x%04x \r\n", *pid,
*vid);
return;
}
*pid = pid_vid_fuse & 0xFFFFU;
*vid = (pid_vid_fuse >> 16) & 0xFFFFU;
use_semidrive_pid_vid = ((use_semidrive_pid_vid >> 14) & 0x1);
DBG("use semidrive pid vid = %d\r\n", use_semidrive_pid_vid);
DBG("origin fuse vid:0x%0x pid:0x%0x\r\n", *vid, *pid);
if (*pid == 0) {
if (use_semidrive_pid_vid)
*pid = SD_PRODUCT_ID;
else
*pid = ANDROID_PRODUCT_ID;
}
if (*vid == 0) {
if (use_semidrive_pid_vid)
*vid = SD_VENDOR_ID;
else
*vid = ANDROID_VENDOR_ID;
}
DBG("final vid:0x%0x pid:0x%0x\r\n", *vid, *pid);
}
bool App_USBD_FB_Init(fastboot_dev_t *fbd, CPU_INT08U cfg_hs, CPU_INT08U cfg_fs)
{
USBD_ERR err;
CPU_INT08U fb_nbr;
bool valid;
DBG(" Initializing MSC class ... \r\n");
USBD_FB_Init(&err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not initialize MSC class w/err = %d\r\n\r\n",
err);
return 0;
}
fb_nbr = USBD_FB_Add(&err);
if (cfg_hs != USBD_CFG_NBR_NONE) {
valid = USBD_FB_CfgAdd(fb_nbr, fbd->dev_nbr, cfg_hs, &err);
if (!valid) {
ERROR(" ... could not add msc instance #%d to HS "
"configuration w/err = %d\r\n\r\n",
fb_nbr, err);
return 0;
}
}
if (cfg_fs != USBD_CFG_NBR_NONE) {
valid = USBD_FB_CfgAdd(fb_nbr, fbd->dev_nbr, cfg_fs, &err);
if (!valid) {
ERROR(" ... could not add msc instance #%d to FS "
"configuration w/err = %d\r\n\r\n",
fb_nbr, err);
return 0;
}
}
fbd->cls_nbr = fb_nbr;
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
USBD_DevSetMS_VendorCode(fbd->dev_nbr, 1u, &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not set MS vendor code w/err = %d\r\n\r\n",
err);
}
#endif
return 1;
}
static bool fastboot_common_usb_init(fastboot_dev_t *fbd)
{
CPU_INT08U dev_nbr;
CPU_INT08U cfg_hs_nbr;
CPU_INT08U cfg_fs_nbr;
bool ok;
USBD_ERR err;
uint16_t vid;
uint16_t pid;
DBG("Initializing USB Device...\r\n");
get_vid_pid(&vid, &pid);
FB_USBD_DevCfg.VendorID = vid;
FB_USBD_DevCfg.ProductID = pid;
get_serialno();
get_product_no();
if ((vid != SD_VENDOR_ID) && (vid != ANDROID_VENDOR_ID))
FB_USBD_DevCfg.ManufacturerStrPtr = "MANUFACTER";
USBD_Init(&err);
if (err != USBD_ERR_NONE) {
ERROR("... init failed w/err = %d\r\n\r\n", err);
return 0;
}
DBG(" Adding controller driver ... \r\n");
/* Add USB device instance. */
dev_nbr = USBD_DevAdd((USBD_DEV_CFG *)&FB_USBD_DevCfg, &FB_USBD_BusFncts,
&USBD_DrvAPI_RenesasRZ_DMA, &FB_USBD_DrvCfg,
&USBD_DrvBSP_TAISHAN_USB0, &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not add controller driver w/err = %d\r\n\r\n",
err);
return 0;
}
/* Device is not self-powered. */
USBD_DevSelfPwrSet(dev_nbr, DEF_NO, &err);
cfg_hs_nbr = USBD_CFG_NBR_NONE;
cfg_fs_nbr = USBD_CFG_NBR_NONE;
#if (USBD_CFG_HS_EN == DEF_ENABLED)
DBG(" Adding HS configuration ... \r\n");
/* Add HS configuration. */
cfg_hs_nbr = USBD_CfgAdd(dev_nbr, USBD_DEV_ATTRIB_SELF_POWERED, 100u,
USBD_DEV_SPD_HIGH, "HS fastboot config", &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not add HS configuration w/err = %d\r\n\r\n",
err);
/* Continue if dev is not high-speed. */
if (err != USBD_ERR_DEV_INVALID_SPD) {
return 0;
}
}
#endif
DBG(" Adding FS configuration ... \r\n");
/* Add FS configuration. */
cfg_fs_nbr = USBD_CfgAdd(dev_nbr, USBD_DEV_ATTRIB_SELF_POWERED, 100u,
USBD_DEV_SPD_FULL, "FS fastboot config", &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not add FS configuration w/err = %d\r\n\r\n",
err);
return 0;
}
#if (USBD_CFG_HS_EN == DEF_ENABLED)
if ((cfg_fs_nbr != USBD_CFG_NBR_NONE) &&
(cfg_hs_nbr != USBD_CFG_NBR_NONE)) {
/* Associate both config for other spd desc. */
USBD_CfgOtherSpeed(dev_nbr, cfg_hs_nbr, cfg_fs_nbr, &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not associate other speed configuration w/err "
"= %d\r\n\r\n",
err);
return 0;
}
}
#endif
DBG(" Initializing USB classes ... \r\n");
fbd->dev_nbr = dev_nbr;
/* Initialize MSC class. */
ok = App_USBD_FB_Init(fbd, cfg_hs_nbr, cfg_fs_nbr);
if (!ok) {
ERROR(" ... could not initialize MSC class w/err = %d\r\n\r\n",
err);
return 0;
}
return 1;
}
void fastboot_register_cmd(const char *prefix, USBD_FB_CMD_HDL handle)
{
if (!prefix || !*prefix || !handle ||
(fb_cmd_len >= SD_FB_CFG_MAX_NBR_CMD)) {
ERROR("Add command fail cmd len=%d\r\n", fb_cmd_len);
return;
}
fb_cmd_tbl[fb_cmd_len].cmd = prefix;
fb_cmd_tbl[fb_cmd_len].handler = handle;
fb_cmd_len++;
}
void fastboot_register_var(const char *name, const char *value)
{
if (!name || !*name || !value || !*value ||
(fb_var_len >= SD_FB_CFG_MAX_NBR_VAR)) {
ERROR("Add variable fail var len=%d\r\n", fb_var_len);
return;
}
fb_var_tbl[fb_var_len].name = name;
fb_var_tbl[fb_var_len].value = value;
fb_var_len++;
}
fastboot_t *fastboot_common_init(void *dl_addr, uint32_t dl_sz)
{
fastboot_dev_t *fbd;
bool ok;
USBD_ERR err;
fbd = &fb_dev;
ok = fastboot_common_usb_init(fbd);
if (!ok)
return NULL;
USBD_FB_SetDL(fbd->cls_nbr, dl_addr, dl_sz, &err);
USBD_FB_SetCmdTbl(fbd->cls_nbr, fb_cmd_tbl, fb_cmd_len, &err);
USBD_FB_SetVarTbl(fbd->cls_nbr, fb_var_tbl, fb_var_len, &err);
USBD_DevStart(fbd->dev_nbr, &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not start device stack w/err = %d\r\n\r\n", err);
return NULL;
}
DBG(" .... USB classes initialization done.\r\n");
return &fbd->cls_nbr;
}
void fastboot_common_okay(fastboot_t *fb, const char *reason)
{
if (fb) {
USBD_FB_Okay(fb, reason);
}
}
void fastboot_common_fail(fastboot_t *fb, const char *reason)
{
if (fb) {
USBD_FB_Fail(fb, reason);
}
}
void fastboot_common_info(fastboot_t *fb, const char *reason)
{
if (fb) {
USBD_FB_Info(fb, reason);
}
}
void fastboot_common_stop(fastboot_t *fb)
{
USBD_ERR err;
if (fb && (*fb == fb_dev.cls_nbr)) {
USBD_DevStop(fb_dev.dev_nbr, &err);
}
}

View File

@@ -0,0 +1,34 @@
/**
* @file dloader_usb_fastboot.h
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description: fastboot common interface.
*
* Revision History:
* -----------------
*/
#ifndef _DLOADER_USB_FASTBOOT_H
#define _DLOADER_USB_FASTBOOT_H
#include <Class/FastBoot/usbd_fb.h>
typedef unsigned char fastboot_t;
typedef struct fastboot_dev {
fastboot_t cls_nbr;
unsigned char dev_nbr;
} fastboot_dev_t;
void fastboot_register_cmd(const char *prefix, USBD_FB_CMD_HDL handle);
void fastboot_register_var(const char *name, const char *value);
fastboot_t *fastboot_common_init(void *dl_addr, uint32_t dl_sz);
void fastboot_common_okay(fastboot_t *fb, const char *reason);
void fastboot_common_fail(fastboot_t *fb, const char *reason);
void fastboot_common_info(fastboot_t *fb, const char *reason);
void fastboot_common_stop(fastboot_t *fb);
#endif

View File

@@ -0,0 +1,331 @@
#include <assert.h>
#include <debug.h>
#include <disk.h>
#include <stdlib.h>
#include "diskio.h"
#include "ff.h"
#define SECTOR_SIZE 512
struct disk_dev_cfg {
struct disk_dev dev;
uint64_t offset;
};
/*--------------------------------------------------------------------------
Public Functions
---------------------------------------------------------------------------*/
/*
* Global variables
*/
static struct disk_dev_cfg Disk[FF_VOLUMES] = {0};
static DSTATUS Stat[FF_VOLUMES] = {
STA_NOINIT, STA_NOINIT, STA_NOINIT, STA_NOINIT, STA_NOINIT,
STA_NOINIT, STA_NOINIT, STA_NOINIT, STA_NOINIT,
}; /* Disk status */
const char *VolumeStr[FF_VOLUMES] = {
"mmc0", "mmc1", "norflash0", "norflash1",
"memdisk0", DISK_USB_NAME(0), DISK_USB_NAME(1)};
/*-----------------------------------------------------------------------*/
/* Get Disk Status */
/*-----------------------------------------------------------------------*/
/*****************************************************************************/
/**
*
* Gets the status of the disk.
* In case of SD, it checks whether card is present or not.
*
* @param pdrv - Drive number
*
* @return
* 0 Status ok
* STA_NOINIT Drive not initialized
* STA_NODISK No medium in the drive
* STA_PROTECT Write protected
*
* @note In case Card detect signal is not connected,
* this function will not be able to check if card is present.
*
******************************************************************************/
DSTATUS ff_disk_status(BYTE pdrv /* Drive number (0) */
)
{
DSTATUS s = Stat[pdrv];
return s;
}
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
/*****************************************************************************/
/**
*
* Initializes the drive.
* In case of SD, it initializes the host controller and the card.
* This function also selects additional settings such as bus width,
* speed and block size.
*
* @param pdrv - Drive number
*
* @return s - which contains an OR of the following information
* STA_NODISK Disk is not present
* STA_NOINIT Drive not initialized
* STA_PROTECT Drive is write protected
* 0 or only STA_PROTECT both indicate successful initialization.
*
* @note
*
******************************************************************************/
DSTATUS ff_disk_initialize(BYTE pdrv /* Physical drive number (0) */
)
{
DSTATUS s;
s = ff_disk_status(pdrv);
/* If disk is already initialized */
if ((s & STA_NOINIT) == 0U) {
Disk[pdrv].offset = 0;
return s;
}
if (disk_open(VolumeStr[pdrv], &Disk[pdrv].dev) == 0) {
disk_set_block_size(&Disk[pdrv].dev, SECTOR_SIZE);
s &= (~STA_NOINIT);
Stat[pdrv] = s;
} else {
s |= STA_NODISK;
Stat[pdrv] = s;
}
return s;
}
/*-----------------------------------------------------------------------*/
/* Close Disk Drive */
/*-----------------------------------------------------------------------*/
/*****************************************************************************/
/**
*
* Close the drive.
*
* @param pdrv - Drive number
*
* @return s - which contains an OR of the following information
* STA_NODISK Disk is not present
* STA_NOINIT Drive not initialized
* STA_PROTECT Drive is write protected
*
* @note
*
******************************************************************************/
DSTATUS ff_disk_close(BYTE pdrv /* Physical drive number (0) */
)
{
DSTATUS s;
s = ff_disk_status(pdrv);
/* If disk is not initialized */
if (s & STA_NOINIT) {
return s;
}
disk_close(&Disk[pdrv].dev);
s |= STA_NOINIT;
Stat[pdrv] = s;
return s;
}
/*-----------------------------------------------------------------------*/
/* Set global offset */
/*-----------------------------------------------------------------------*/
/*****************************************************************************/
/**
*
* Set global offset of sector number
*
* @param pdrv - Drive number
* @param offset - global offset sector number
* @return
* RES_OK Successful
* RES_ERROR Successful
*
* @note
*
******************************************************************************/
DRESULT disk_set_offset(BYTE pdrv, /* Physical drive number (0) */
LBA_t offset /* Start sector number (LBA) */
)
{
Disk[pdrv].offset = offset;
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
/*****************************************************************************/
/**
*
* Reads the drive
* In case of SD, it reads the SD card using ADMA2 in polled mode.
*
* @param pdrv - Drive number
* @param *buff - Pointer to the data buffer to store read data
* @param sector - Start sector number
* @param count - Sector count
*
* @return
* RES_OK Read successful
* STA_NOINIT Drive not initialized
* RES_ERROR Read not successful
*
* @note
*
******************************************************************************/
DRESULT
ff_disk_read(BYTE pdrv, /* Physical drive number (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
LBA_t sector, /* Start sector number (LBA) */
UINT count /* Sector count (1..128) */
)
{
DSTATUS s;
struct disk_dev *dev = &Disk[pdrv].dev;
LBA_t dst_addr;
ASSERT(dev);
s = ff_disk_status(pdrv);
if ((s & STA_NOINIT) != 0U) {
return RES_NOTRDY;
}
if (count == 0U) {
return RES_PARERR;
}
dst_addr = (sector + Disk[pdrv].offset) * SECTOR_SIZE;
if (disk_read(dev, dst_addr, buff, count * SECTOR_SIZE))
return RES_ERROR;
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT ff_disk_ioctl(BYTE pdrv, /* Physical drive number (0) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res = RES_OK;
struct disk_dev *dev = &Disk[pdrv].dev;
ASSERT(dev);
void *LocBuff = buff;
if ((ff_disk_status(pdrv) & STA_NOINIT) !=
0U) { /* Check if card is in the socket */
return RES_NOTRDY;
}
res = RES_ERROR;
switch (cmd) {
case (BYTE)CTRL_SYNC: /* Make sure that no pending write process */
res = RES_OK;
break;
case (BYTE)GET_SECTOR_COUNT: /* Get number of sectors on the disk (DWORD) */
(*((DWORD *)(void *)LocBuff)) = disk_size(dev) / SECTOR_SIZE;
res = RES_OK;
break;
case (BYTE)
GET_BLOCK_SIZE: /* Get erase block size in unit of sector (DWORD) */
(*((DWORD *)((void *)LocBuff))) = disk_erase_size(dev) / SECTOR_SIZE;
res = RES_OK;
break;
default:
res = RES_PARERR;
break;
}
return res;
}
/******************************************************************************/
/**
*
* This function is User Provided Timer Function for FatFs module
*
* @return DWORD
*
* @note None
*
****************************************************************************/
DWORD get_fattime(void)
{
return ((DWORD)(2010U - 1980U) << 25U) /* Fixed to Jan. 1, 2010 */
| ((DWORD)1 << 21) | ((DWORD)1 << 16) | ((DWORD)0 << 11) |
((DWORD)0 << 5) | ((DWORD)0 >> 1);
}
/*****************************************************************************/
/**
*
* Reads the drive
* In case of SD, it reads the SD card using ADMA2 in polled mode.
*
* @param pdrv - Drive number
* @param *buff - Pointer to the data to be written
* @param sector - Sector address
* @param count - Sector count
*
* @return
* RES_OK Read successful
* STA_NOINIT Drive not initialized
* RES_ERROR Read not successful
*
* @note
*
******************************************************************************/
DRESULT ff_disk_write(BYTE pdrv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
LBA_t sector, /* Sector address (LBA) */
UINT count /* Number of sectors to write (1..128) */
)
{
DSTATUS s;
struct disk_dev *dev = &Disk[pdrv].dev;
LBA_t dst_addr;
ASSERT(dev);
s = ff_disk_status(pdrv);
if ((s & STA_NOINIT) != 0U) {
return RES_NOTRDY;
}
if (count == 0U) {
return RES_PARERR;
}
dst_addr = (sector + Disk[pdrv].offset) * SECTOR_SIZE;
if (disk_write(dev, dst_addr, buff, count * SECTOR_SIZE))
return RES_ERROR;
return RES_OK;
}

8237
middleware/fatfs/ff.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,187 @@
#include <CLI.h>
//#include <cmsis_os2.h>
#include <debug.h>
#include <stdlib.h>
#include <string.h>
#include "ff.h"
static FATFS fatfs;
/*
****************************Partition mounting instructions********************
* VolumeStr[FF_VOLUMES] = "mmc0", "mmc1", "norflash0", "norflash1", "memdisk0",
"usb0";
* f_mount(&fatfs, "mmc0:1:", 1) "mmc0:1:" represents the first FAT partition to
mount mmc0 disk
* f_mount(&fatfs, "flash0:2:", 1) "flash0:2:" represents the second FAT
partition to mount flash1 disk
*/
static int ff_test_mount(int argc, char *argv[])
{
ssdk_printf(SSDK_CRIT, "ff mount test start diskid = %s!\n", argv[0]);
FRESULT rc;
rc = f_mount(&fatfs, argv[0], 1);
if (rc) {
printf("ERROR: f_mount returned %d\r\n", rc);
return -1;
}
printf("f_mount success\r\n");
ssdk_printf(SSDK_CRIT, "ff mount test end!\n");
return 0;
}
/* test read file
* ff_test_read mmc0:1:file_name 0
*/
static int ff_test_read(int argc, char *argv[])
{
ssdk_printf(SSDK_CRIT, "ff read test start!\n");
FIL fil;
FRESULT rc;
UINT br;
uint32_t offset = strtoul(argv[1], NULL, 16);
// uint8_t *buf = osAllocAlign(512, 512 * 16);
uint8_t *buf = pvPortMallocAligned(512 * 16, 512);
rc = f_open(&fil, argv[0], FA_READ);
if (rc) {
printf("ERROR:f_open returned %d\r\n", rc);
return -1;
}
rc = f_lseek(&fil, offset);
if (rc) {
printf("ERROR:f_lseek returned %d\r\n", rc);
return -1;
}
rc = f_read(&fil, (void *)buf, 512 * 16, &br);
if (rc) {
printf("ERROR:f_read returned %d\r\n", rc);
return -1;
}
rc = f_close(&fil);
if (rc) {
printf("ERROR:f_open returned %d\r\n", rc);
return -1;
}
printf("the read string is: %s\n", buf);
// osFree(buf);
vPortFree(buf);
ssdk_printf(SSDK_CRIT, "ff read test end!\n");
return 0;
}
/* test write file
* ff_test_write mmc0:1:file_name 0
*/
static int ff_test_write(int argc, char *argv[])
{
ssdk_printf(SSDK_CRIT, "ff write test start!\n");
FIL fil;
FRESULT rc;
UINT br;
uint32_t offset = strtoul(argv[1], NULL, 16);
const char *buf = "fat: helloworld\n";
rc = f_open(&fil, argv[0], FA_CREATE_ALWAYS);
if (rc) {
printf("ERROR:f_open returned %d\r\n", rc);
return -1;
}
rc = f_close(&fil);
if (rc) {
printf("ERROR:f_close returned %d\r\n", rc);
return -1;
}
rc = f_open(&fil, argv[0], FA_WRITE);
if (rc) {
printf("ERROR:f_open returned %d\r\n", rc);
return -1;
}
rc = f_lseek(&fil, offset);
if (rc) {
printf("ERROR:f_lseek returned %d\r\n", rc);
return -1;
}
rc = f_write(&fil, (void *)buf, strlen(buf) + 1, &br);
if (rc) {
printf("ERROR:f_write returned %d\r\n", rc);
return -1;
}
rc = f_close(&fil);
if (rc) {
printf("ERROR:f_open returned %d\r\n", rc);
return -1;
}
printf("the write string is: %s\n", buf);
ssdk_printf(SSDK_CRIT, "ff write test end!\n");
return 0;
}
static void ff_read_thread(void *arg)
{
char *argv[3] = {NULL};
argv[0] = arg;
argv[1] = "0";
ff_test_read(3, argv);
// osThreadExit();
vTaskDelete(NULL);
}
static void ff_write_thread(void *arg)
{
char *argv[3] = {NULL};
argv[0] = arg;
argv[1] = "0";
ff_test_write(3, argv);
// osThreadExit();
vTaskDelete(NULL);
}
static int ff_test_task(int argc, char *argv[])
{
if (argc == 1) {
// osThreadNew(ff_write_thread, (void *)argv[0], NULL);
xTaskCreate(ff_write_thread, "ff_write_thread", 1024, (void *)argv[0],
configMAX_PRIORITIES - 2, NULL);
// osThreadNew(ff_read_thread, (void *)argv[0], NULL);
xTaskCreate(ff_read_thread, "ff_read_thread", 1024, (void *)argv[0],
configMAX_PRIORITIES - 2, NULL);
} else if (argc == 2) {
// osThreadNew(ff_write_thread, (void *)argv[1], NULL);
xTaskCreate(ff_write_thread, "ff_write_thread", 1024, (void *)argv[1],
configMAX_PRIORITIES - 2, NULL);
// osThreadNew(ff_read_thread, (void *)argv[0], NULL);
xTaskCreate(ff_read_thread, "ff_read_thread", 1024, (void *)argv[0],
configMAX_PRIORITIES - 2, NULL);
}
return 0;
}
CLI_CMD("ff_test_mount", "\r\nff_test_mount:\r\n ff mount unittest case",
ff_test_mount);
CLI_CMD("ff_test_read", "\r\nff_test_read\r\n: ff read file unittest case",
ff_test_read);
CLI_CMD("ff_test_write", "\r\nff_test_write\r\n: ff write file unittest case",
ff_test_write);
CLI_CMD("ff_test_task", "\r\nff_test_task\r\n: ff concurrency unittest case",
ff_test_task);

187
middleware/fatfs/ffsystem.c Normal file
View File

@@ -0,0 +1,187 @@
/*------------------------------------------------------------------------*/
/* Sample Code of OS Dependent Functions for FatFs */
/* (C)ChaN, 2018 */
/*------------------------------------------------------------------------*/
//#include <cmsis_os2.h>
#include <FreeRTOS.h>
#include <portable.h>
#include <semphr.h>
#include <stdint.h>
#include <stdlib.h>
#include <task.h>
#include "ff.h"
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
void *ff_memalloc(/* Returns pointer to the allocated memory block (null if not
enough core) */
UINT msize /* Number of bytes to allocate */
)
{
/* CMSIS2-RTOS */
// return osAllocAlign(512, msize); /* Use osAllocAlign alloc 512 bytes
// aligned buf */
/* FreeRTOS */
return pvPortMallocAligned(
msize, 512); /* Use osAllocAlign alloc 512 bytes aligned buf */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree(void *mblock /* Pointer to the memory block to free (nothing to
do if null) */
)
{
/* CMSIS2-RTOS */
// osFree(mblock); /* Free the memory block with POSIX API */
/* FreeRTOS */
vPortFree(mblock); /* Free the memory block with POSIX API */
}
#endif
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object for the volume, such as semaphore and mutex.
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
*/
// const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
int ff_cre_syncobj(/* 1:Function succeeded, 0:Could not create the sync object
*/
BYTE vol, /* Corresponding volume (logical drive number) */
FF_SYNC_t
*sobj /* Pointer to return the created sync object */
)
{
/* Win32 */
// *sobj = CreateMutex(NULL, FALSE, NULL);
// return (int)(*sobj != INVALID_HANDLE_VALUE);
/* uITRON */
// T_CSEM csem = {TA_TPRI,1,1};
// *sobj = acre_sem(&csem);
// return (int)(*sobj > 0);
/* uC/OS-II */
// OS_ERR err;
// *sobj = OSMutexCreate(0, &err);
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
*sobj = (FF_SYNC_t)xSemaphoreCreateMutex();
return (int)(*sobj != NULL);
/* CMSIS-RTOS */
// *sobj = osMutexCreate(&Mutex[vol]);
// return (int)(*sobj != NULL);
/* CMSIS2-RTOS */
// *sobj = osMutexNew(NULL);
// return (int)(*sobj != NULL);
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj(/* 1:Function succeeded, 0:Could not delete due to an error
*/
FF_SYNC_t sobj /* Sync object tied to the logical drive to be
deleted */
)
{
/* Win32 */
// return (int)CloseHandle(sobj);
/* uITRON */
// return (int)(del_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
vSemaphoreDelete(sobj);
return 1;
/* CMSIS-RTOS */
// return (int)(osMutexDelete(sobj) == osOK);
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant(/* 1:Got a grant to access the volume, 0:Could not get a grant
*/
FF_SYNC_t sobj /* Sync object to wait */
)
{
/* Win32 */
// return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
/* uITRON */
// return (int)(wai_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
/* CMSIS-RTOS */
// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
/* CMSIS2-RTOS */
// return (int)(osMutexAcquire(sobj, FF_FS_TIMEOUT) == osOK);
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant(FF_SYNC_t sobj /* Sync object to be signaled */
)
{
/* Win32 */
// ReleaseMutex(sobj);
/* uITRON */
// sig_sem(sobj);
/* uC/OS-II */
// OSMutexPost(sobj);
/* FreeRTOS */
xSemaphoreGive(sobj);
/* CMSIS-RTOS */
// osMutexRelease(sobj);
}
#endif

27354
middleware/fatfs/ffunicode.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2019 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#include "ff.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS ff_disk_initialize(BYTE pdrv);
DSTATUS ff_disk_close(BYTE pdrv);
DSTATUS ff_disk_status(BYTE pdrv);
DRESULT disk_set_offset(BYTE pdrv, LBA_t offset);
DRESULT ff_disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count);
DRESULT ff_disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count);
DRESULT ff_disk_ioctl(BYTE pdrv, BYTE cmd, void *buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC \
0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE \
2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) \
*/
#define CTRL_TRIM \
4 /* Inform device that the data on the block of sectors is no longer used \
(needed at FF_USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,444 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.14 /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2019, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/
/----------------------------------------------------------------------------*/
#ifndef FF_DEFINED
#define FF_DEFINED 86606 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include <debug.h>
#include <param.h>
#include "ffconf.h" /* FatFs configuration options */
#if FF_DEFINED != FFCONF_DEF
#error Wrong configuration file (ffconf.h).
#endif
/* Integer types used for FatFs API */
#if defined(_WIN32) /* Main development platform */
#define FF_INTDEF 2
#include <windows.h>
typedef unsigned __int64 QWORD;
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
defined(__cplusplus) /* C99 or later */
#define FF_INTDEF 2
#include <stdint.h>
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
typedef unsigned char BYTE; /* char must be 8-bit */
typedef uint16_t WORD; /* 16-bit unsigned integer */
typedef uint32_t DWORD; /* 32-bit unsigned integer */
typedef uint64_t QWORD; /* 64-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#else /* Earlier than C99 */
#define FF_INTDEF 1
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
typedef unsigned char BYTE; /* char must be 8-bit */
typedef unsigned short WORD; /* 16-bit unsigned integer */
typedef unsigned long DWORD; /* 32-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#endif
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char *VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#endif
/* Type of path name strings on FatFs API */
#ifndef _INC_TCHAR
#define _INC_TCHAR
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L##x
#define _TEXT(x) L##x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8##x
#define _TEXT(x) u8##x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U##x
#define _TEXT(x) U##x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size and LBA variables */
#if FF_FS_EXFAT
#if FF_INTDEF != 2
#error exFAT feature wants C99 or later
#endif
typedef QWORD FSIZE_t;
#if FF_LBA64
typedef QWORD LBA_t;
#else
typedef DWORD LBA_t;
#endif
#else
#if FF_LBA64
#error exFAT needs to be enabled when enable 64-bit LBA
#endif
typedef DWORD FSIZE_t;
typedef DWORD LBA_t;
#endif
/* Filesystem object structure (FATFS) */
typedef struct {
BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE pdrv; /* Associated physical drive */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if FF_MAX_SS != FF_MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if FF_USE_LFN
WCHAR *lfnbuf; /* LFN working buffer */
#endif
#if FF_FS_EXFAT
BYTE *dirbuf; /* Directory entry block scratchpad buffer for exFAT */
#endif
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if FF_FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#if FF_FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is
0) */
DWORD
cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is
0) */
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
LBA_t volbase; /* Volume base sector */
LBA_t fatbase; /* FAT base sector */
LBA_t dirbase; /* Root directory base sector/cluster */
LBA_t database; /* Data base sector */
#if FF_FS_EXFAT
LBA_t bitbase; /* Allocation bitmap base sector */
#endif
LBA_t winsect; /* Current sector appearing in the win[] */
BYTE *win;
BYTE real_win[FF_MAX_SS +
CONFIG_ARCH_CACHE_LINE]; /* Disk access window for Directory,
FAT (and file data at tiny cfg) */
#ifdef SEMIDRIVE_MULTI_PARTITION
BYTE read_only;
#endif
} FATFS;
/* Object ID and allocation information (FFOBJID) */
typedef struct {
FATFS *fs; /* Pointer to the hosting volume of this object */
WORD id; /* Hosting volume mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous,
=3:fragmented in this session, b2:sub-directory stretched) */
DWORD
sclust; /* Object data start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if FF_FS_EXFAT
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid
when not zero) */
DWORD
c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status
(valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when file object
and sclust != 0) */
#endif
#if FF_FS_LOCK
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table
Files[]) */
#endif
} FFOBJID;
/* File object structure (FIL) */
typedef struct {
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid
object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */
#if !FF_FS_READONLY
LBA_t dir_sect; /* Sector number containing the directory entry (not used at
exFAT) */
BYTE *dir_ptr; /* Pointer to the directory entry in the win[] (not used at
exFAT) */
#endif
#if FF_USE_FASTSEEK
DWORD *cltbl; /* Pointer to the cluster link map table (nulled on open, set
by application) */
#endif
#if !FF_FS_TINY
BYTE *buf;
BYTE real_buf[FF_MAX_SS + CONFIG_ARCH_CACHE_LINE]; /* File private data
read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
FFOBJID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
LBA_t sect; /* Current sector (0:Read operation has terminated) */
BYTE *dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if FF_USE_LFN
DWORD blk_ofs; /* Offset of current entry block being processed
(0xFFFFFFFF:Invalid) */
#endif
#if FF_USE_FIND
const TCHAR *pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1]; /* Altenative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[12 + 1]; /* File name */
#endif
} FILINFO;
/* Format parameter structure (MKFS_PARM) */
typedef struct {
BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
BYTE n_fat; /* Number of FATs */
UINT align; /* Data area alignment (sector) */
UINT n_root; /* Number of root directory entries */
DWORD au_size; /* Cluster size (byte) */
} MKFS_PARM;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full
*/
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within
defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing
policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
FR_INVALID_PARAMETER, /* (19) Given parameter is invalid */
#ifdef SEMIDRIVE_MULTI_PARTITION
FR_FS_READ_ONLY /* (20) File system read only */
#endif
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open(FIL *fp, const TCHAR *path,
BYTE mode); /* Open or create a file */
FRESULT f_close(FIL *fp); /* Close an open file object */
FRESULT f_read(FIL *fp, void *buff, UINT btr,
UINT *br); /* Read data from the file */
FRESULT f_write(FIL *fp, const void *buff, UINT btw,
UINT *bw); /* Write data to the file */
FRESULT f_lseek(FIL *fp,
FSIZE_t ofs); /* Move file pointer of the file object */
FRESULT f_truncate(FIL *fp); /* Truncate the file */
FRESULT f_sync(FIL *fp); /* Flush cached data of the writing file */
FRESULT f_opendir(DIR *dp, const TCHAR *path); /* Open a directory */
FRESULT f_closedir(DIR *dp); /* Close an open directory */
FRESULT f_readdir(DIR *dp, FILINFO *fno); /* Read a directory item */
FRESULT f_findfirst(DIR *dp, FILINFO *fno, const TCHAR *path,
const TCHAR *pattern); /* Find first file */
FRESULT f_findnext(DIR *dp, FILINFO *fno); /* Find next file */
FRESULT f_mkdir(const TCHAR *path); /* Create a sub directory */
FRESULT f_unlink(const TCHAR *path); /* Delete an existing file or directory */
FRESULT f_rename(const TCHAR *path_old,
const TCHAR *path_new); /* Rename/Move a file or directory */
FRESULT f_stat(const TCHAR *path, FILINFO *fno); /* Get file status */
FRESULT f_chmod(const TCHAR *path, BYTE attr,
BYTE mask); /* Change attribute of a file/dir */
FRESULT f_utime(const TCHAR *path,
const FILINFO *fno); /* Change timestamp of a file/dir */
FRESULT f_chdir(const TCHAR *path); /* Change current directory */
FRESULT f_chdrive(const TCHAR *path); /* Change current drive */
FRESULT f_getcwd(TCHAR *buff, UINT len); /* Get current directory */
FRESULT f_getfree(const TCHAR *path, DWORD *nclst,
FATFS **fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel(const TCHAR *path, TCHAR *label,
DWORD *vsn); /* Get volume label */
FRESULT f_setlabel(const TCHAR *label); /* Set volume label */
FRESULT f_forward(FIL *fp, UINT (*func)(const BYTE *, UINT), UINT btf,
UINT *bf); /* Forward data to the stream */
FRESULT f_expand(FIL *fp, FSIZE_t fsz,
BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount(FATFS *fs, const TCHAR *path,
BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs(const TCHAR *path, const MKFS_PARM *opt, void *work,
UINT len); /* Create a FAT volume */
FRESULT f_fdisk(BYTE pdrv, const LBA_t ptbl[],
void *work); /* Divide a physical drive into some partitions */
FRESULT f_setcp(WORD cp); /* Set current code page */
int f_putc(TCHAR c, FIL *fp); /* Put a character to the file */
int f_puts(const TCHAR *str, FIL *cp); /* Put a string to the file */
int f_printf(FIL *fp, const TCHAR *str,
...); /* Put a formatted string to the file */
TCHAR *f_gets(TCHAR *buff, int len, FIL *fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime(void);
#endif
/* LFN support functions */
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
WCHAR ff_oem2uni(WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
WCHAR ff_uni2oem(DWORD uni, WORD cp); /* Unicode to OEM code conversion */
DWORD ff_wtoupper(DWORD uni); /* Unicode upper-case conversion */
#endif
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void *ff_memalloc(UINT msize); /* Allocate memory block */
void ff_memfree(void *mblock); /* Free memory block */
#endif
/* Sync functions */
#if FF_FS_REENTRANT
int ff_cre_syncobj(BYTE vol, FF_SYNC_t *sobj); /* Create a sync object */
int ff_req_grant(FF_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant(FF_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj(FF_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01
#define FA_WRITE 0x02
#define FA_OPEN_EXISTING 0x00
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA_OPEN_APPEND 0x30
/* Fast seek controls (2nd argument of f_lseek) */
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
/* Format options (2nd argument of f_mkfs) */
#define FM_FAT 0x01
#define FM_FAT32 0x02
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
#define FS_EXFAT 4
/* File attribute bits for directory entry (FILINFO.fattrib) */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#ifdef __cplusplus
}
#endif
#endif /* FF_DEFINED */

View File

@@ -0,0 +1,291 @@
/*---------------------------------------------------------------------------/
/ FatFs Functional Configurations
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 86606 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#ifndef SD_NO_MULTI_PARTITION
#define SEMIDRIVE_MULTI_PARTITION
#endif
#include <FreeRTOS.h>
#include <queue.h>
#define FF_FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define FF_FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: Basic functions are fully enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define FF_USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define FF_USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define FF_USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define FF_USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and
f_utime(). / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to
enable this option. */
#define FF_USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define FF_USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define FF_CODE_PAGE 437
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect code page setting can cause a file open failure.
/
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
/ 0 - Include all code pages above and configured by f_setcp()
*/
#define FF_USE_LFN 3
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/ 0: Disable LFN. FF_MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT
thread-safe. / 2: Enable LFN with dynamic working buffer on the STACK. / 3:
Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN
function / requiers certain internal working buffer occupies (FF_MAX_LFN + 1) *
2 bytes and / additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is
enabled. / The FF_MAX_LFN defines size of the working buffer in UTF-16 code
unit and it can / be in range of 12 to 255. It is recommended to be set it 255
to fully support LFN / specification. / When use stack for the working buffer,
take care on stack overflow. When use heap / memory for the working buffer,
memory management functions, ff_memalloc() and / ff_memfree() exemplified in
ffsystem.c, need to be added to the project. */
#define FF_LFN_UNICODE 0
/* This option switches the character encoding on the API when LFN is enabled.
/
/ 0: ANSI/OEM in current CP (TCHAR = char)
/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
/ 2: Unicode in UTF-8 (TCHAR = char)
/ 3: Unicode in UTF-32 (TCHAR = DWORD)
/
/ Also behavior of string I/O functions will be affected by this option.
/ When LFN is not enabled, this option has no effect. */
#define FF_LFN_BUF 255
#define FF_SFN_BUF 12
/* This set of options defines size of file name members in the FILINFO
structure / which is used to read out directory items. These values should be
suffcient for / the file names to read. The maximum possible length of the read
file name depends / on character encoding. When LFN is not enabled, these
options have no effect. */
#define FF_STRF_ENCODE 3
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
#define FF_FS_RPATH 0
/* This option configures support for relative path.
/
/ 0: Disable relative path and remove related functions.
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define FF_VOLUMES 10
/* Number of volumes (logical drives) to be used. (1-10) */
#ifdef SEMIDRIVE_MULTI_PARTITION
#define MAX_PARTITION_NUM (6)
#define MULTI_PARTITION_VOLUMES (9 * MAX_PARTITION_NUM)
/* A drive has a maximum of five partitions.
* There are currently eight drives defined in diskio.sdrv.c
*/
#endif
#define FF_STR_VOLUME_ID 1
// #define FF_VOLUME_STRS
// "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as
drive / number in the path name. FF_VOLUME_STRS defines the volume ID strings
for each / logical drives. Number of items must not be less than FF_VOLUMES.
Valid / characters for the volume ID strings are A-Z, a-z and 0-9, however,
they are / compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and
FF_VOLUME_STRS is / not defined, a user defined volume string table needs to be
defined as:
/
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
*/
#define FF_MULTI_PARTITION 0
/* This option switches support for multiple volumes on the physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When this function is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also
f_fdisk() / funciton will be available. */
#define FF_MIN_SS 512
#define FF_MAX_SS 512
/* This set of options configures the range of sector size to be supported.
(512, / 1024, 2048 or 4096) Always set both 512 for most systems, generic
memory card and / harddisk. But a larger value may be required for on-board
flash memory and some / type of optical media. When FF_MAX_SS is larger than
FF_MIN_SS, FatFs is configured / for variable sector size mode and
ff_disk_ioctl() function needs to implement / GET_SECTOR_SIZE command. */
#define FF_LBA64 1
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1)
*/
#define FF_MIN_GPT 0x100000000
/* Minimum number of sectors to switch GPT format to create partition in f_mkfs
and / f_fdisk function. 0x100000000 max. This option has no effect when
FF_LBA64 == 0. */
#define FF_USE_TRIM 0
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ ff_disk_ioctl() function. */
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS
bytes. / Instead of private sector buffer eliminated from the file object,
common sector / buffer in the filesystem object (FATFS) is used for the file
data transfer. */
#define FF_FS_EXFAT 1
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
#define FF_FS_NORTC 0
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2019
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not
have / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1
to disable / the timestamp function. Every object modified by FatFs will have a
fixed timestamp / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in
local time. / To enable timestamp function (FF_FS_NORTC = 0), get_fattime()
function need to be / added to the project to read current time form real-time
clock. FF_NORTC_MON, / FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. / These
options have no effect in read-only configuration (FF_FS_READONLY = 1). */
#define FF_FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
#define FF_FS_LOCK 0
/* The option FF_FS_LOCK switches file lock function to control duplicated file
open / and illegal operation to open objects. This option must be 0 when
FF_FS_READONLY / is 1.
/
/ 0: Disable file lock function. To avoid volume corruption, application
program / should avoid illegal open, remove and rename to the open objects.
/ >0: Enable file lock function. The value defines how many
files/sub-directories / can be opened simultaneously under file lock
control. Note that the file / lock control is independent of re-entrancy.
*/
//#include <cmsis_os2.h> // O/S definitions
#define FF_FS_REENTRANT 1
#define FF_FS_TIMEOUT 10000
// #define FF_SYNC_t osMutexId_t
#define FF_SYNC_t QueueHandle_t
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the
FatFs / module itself. Note that regardless of this option, file access to
different / volume is always re-entrant and volume control functions,
f_mount(), f_mkfs() / and f_fdisk() function, are always not re-entrant. Only
file/directory access / to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID,
OS_EVENT*, / SemaphoreHandle_t and etc. A header file for O/S definitions needs
to be / included somewhere in the scope of ff.h. */
/*--- End of configuration options ---*/

1595
middleware/fee/fee.c Normal file

File diff suppressed because it is too large Load Diff

161
middleware/fee/fee.h Normal file
View File

@@ -0,0 +1,161 @@
/**
* @file fee.h
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef DISK_FEE_H_
#define DISK_FEE_H_
#define FEE_PAGE_NUMBER_TWO 2 /* page number, two page schemes are considered to have the highest space utilization */
#define FEE_PAGE_NUMBER FEE_PAGE_NUMBER_TWO
#define FEE_CHAR_BIT 8 /* char indicates the number of bits */
#define FEE_RECORD_BUFF_SIZE 0x1000
#define DIVD_NUM(div, rem, coe) ((div) * (coe) + (rem)) /* compute the dividend */
#define DIV_NUM(num, coe) ((num) / (coe)) /* calculate the divisor */
#define REM_NUM(num, coe) ((num) % (coe)) /* calculate the remainder */
/* page status type */
typedef uint32_t fee_page_status_t;
/* page status definitions */
#define FEE_PAGE_ERASED ((fee_page_status_t)0xFFFFFFFF) /* PAGE is empty */
#define FEE_PAGE_RECEIVE ((fee_page_status_t)0xFFFFFFA5) /* PAGE is marked to receive data */
#define FEE_PAGE_ACTIVE ((fee_page_status_t)0xFFFFA5A5) /* PAGE is marked to store new data */
#define FEE_PAGE_VALID ((fee_page_status_t)0xFFA5A5A5) /* PAGE is full */
#define FEE_PAGE_ERASING ((fee_page_status_t)0xA5A5A5A5) /* PAGE is marked to be erase */
/* page mode type */
typedef uint32_t fee_page_mode_t;
#define FEE_PAGE_BLOCK ((fee_page_mode_t)0xFFFFA5A5) /* PAGE mode is block */
#define FEE_PAGE_EEPROM ((fee_page_mode_t)0xA5A5A5A5) /* PAGE mode is eeprom */
#define FEE_BLOCK_ADDR_BIT_SIZE (0x10000 >> 0x3)
/* page information */
struct fee_page_info {
fee_page_status_t page_status;
};
typedef uint64_t disk_addr_t;
typedef uint64_t disk_size_t;
typedef uint32_t fee_record_status_t;
typedef uint16_t fee_record_number_t; /* block number range is 64K */
typedef uint16_t fee_record_length_t; /* block size range is 64K */
/* block status definitions */
#define FEE_RECORD_ERASED ((fee_record_status_t)0xFFFFFFFF) /* block is empty */
#define FEE_RECORD_INVALID ((fee_record_status_t)0xFFFFA5A5) /* block is marked to invalid */
#define FEE_RECORD_VALID ((fee_record_status_t)0xA5A5A5A5) /* block is marked to valid */
/* record information */
struct fee_record_info {
fee_record_status_t record_status;
fee_record_number_t record_num;
fee_record_length_t record_len;
};
/* page information */
struct fee_page {
disk_addr_t
page_addr; /* page start address in the physical layer device, sector_size aligned */
disk_size_t page_size; /* page size,sector_size aligned */
uint16_t page_sector_num; /* number of sectors in page */
uint16_t page_buff_num; /* number of sectors in page */
fee_page_status_t page_status __ALIGNED(CONFIG_ARCH_CACHE_LINE);
};
/* address mask index */
typedef enum {
FEE_INFO_BUFF = 0,
FEE_DATA_BUFF,
FEE_DATA_OFFSET_BUFF,
FEE_BUFF_MAX,
} fee_buff_index;
/* address mask index */
typedef enum {
FEE_ADDR_MASK_BLOCK = 0,
FEE_ADDR_MASK_RECORD,
FEE_ADDR_MASK_RECORD_CURRENT,
FEE_ADDR_MASK_RECORD_TMP,
FEE_ADDR_MASK_MAX,
} fee_addr_mask_index;
#define FEE_ADDR_MASK_PRT(addr, addr_index, addr_size) ((addr) + ((addr_index) * (addr_size)))
struct disk_dev_info {
/* disk_dev */
void* disk_dev; /* disk device */
disk_addr_t addr; /* disk start address */
disk_size_t size; /* disk size */
uint16_t mem_align_size;
uint16_t access_size;
uint32_t sector_size;
uint16_t pe_cycles; /* flash sector erase the life,Unit ten thousand */
/* disk_ops */
int (*disk_read)(void *disk_dev, uint8_t *dst, disk_addr_t addr, disk_size_t size);
int (*disk_write)(void *disk_dev, const uint8_t *src, disk_addr_t addr, disk_size_t size);
int (*disk_erase)(void *disk_dev, disk_addr_t addr, disk_size_t size);
};
/* fee device */
struct fee_dev {
struct disk_dev_info *disk_dev;
/* page info */
uint16_t page_number; /* PAGE_NUMBER */
struct fee_page page_info[FEE_PAGE_NUMBER];
fee_page_mode_t page_mode;
/* record info */
uint16_t block_number; /* block number range, 1 ~ block_number */
uint16_t block_length; /* single block size range, 1 ~ block_length */
/* record buff */
uint8_t *record_info_buff; /* used for record information cache, the length is sector_size */
uint8_t *record_data_buff; /* used for record data cache, length sector_size */
uint8_t *record_data_offset_buff; /* used for calculate record data offset, length sector_size */
uint16_t record_info_num; /* number of record info in record_info_buff */
uint16_t record_buff_size; /* record buff size */
/* fee dev information at run time */
uint16_t current_page; /* current page page */
disk_size_t record_info_offset; /* current record_info index offset */
disk_size_t record_data_offset; /* current record_data addr offset*/
/* block addr buff */
uint8_t *block_addr_mask; /* used to store address mask information */
uint16_t block_addr_size; /* number of block addr mask size,block_addr_mask size */
/* fee record info */
struct fee_record_info record_info __ALIGNED(CONFIG_ARCH_CACHE_LINE);
};
/* fee APIs */
int fee_init(struct fee_dev *fee_dev);
int fee_exit(struct fee_dev *fee_dev);
/* fee multiple block operations, length block_length aligned */
int fee_write_record_multiple(struct fee_dev *fee_dev, uint16_t block_number,
uint8_t *data_buffer, uint16_t length);
int fee_read_record_multiple(struct fee_dev *fee_dev, uint16_t block_number,
uint8_t *data_buffer, uint16_t length);
/* fee single block operations,length <= block_length */
int fee_write_record_single(struct fee_dev *fee_dev, uint16_t block_number,
uint8_t *data_buffer, uint16_t length);
int fee_read_record_single(struct fee_dev *fee_dev, uint16_t block_number,
uint16_t block_offset, uint8_t *data_buffer, uint16_t length);
#endif /* DISK_MMC_H_ */

View File

@@ -0,0 +1,85 @@
/**
* @file fee_block.c
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#include <debug.h>
#include <stdlib.h>
#include <string.h>
#include <param.h>
#include <types.h>
#include <cmsis_os2.h>
#include <arch/atomic.h>
#include <stdarg.h>
#include <lib/list.h>
#include <lib/fee/fee_block.h>
static struct list_node g_fee_list;
static struct fee_block *fee_get_dev(const char *fee_name)
{
struct fee_block *fee_block;
/* matches nodes based on name */
list_for_every_entry(&g_fee_list, fee_block,
struct fee_block, node) {
if (!strcmp(fee_name, fee_block->fee_name)) {
return fee_block;
}
}
return NULL;
}
int fee_register_block(struct fee_block *fee)
{
int ret = 0;
return ret;
}
int fee_unregister_block(struct fee_block *fee)
{
int ret = 0;
return ret;
}
int fee_read_block(const char *fee_name, uint16_t block_number,
uint16_t block_offset, uint8_t *data_buffer, uint16_t length)
{
int ret = 0;
return ret;
}
int fee_write_block(const char *fee_name, uint16_t block_number,
const uint8_t *data_buffer, uint16_t length)
{
int ret = 0;
return ret;
}
int fee_init_block(void)
{
ssdk_printf(SSDK_INFO, "fee block init\n");
/* disk list node init */
list_initialize(&g_fee_list);
return 0;
}
int fee_exit_block(void)
{
ssdk_printf(SSDK_INFO, "fee block exit\n");
/* disk list node init */
return 0;
}

View File

@@ -0,0 +1,59 @@
/**
* @file fee_block.h
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef DISK_FEE_BLCOK_H_
#define DISK_FEE_BLCOK_H_
#include "fee.h"
#define FEE_BLOCK_NAME(n) "fee_block"#n
struct fee_config_block {
/* nor flash info */
const char *disk_name;
disk_addr_t addr; /* nor flash sector_size aligned */
disk_size_t size; /* sector_size * page_number aligned */
uint16_t mem_align_size; /* nor flash read/write memory alignment size */
uint16_t access_align_size; /* nor flash access alignment size */
uint32_t sector_size; /* erasing is based on sector_size */
uint16_t pe_cycles; /* flash sector erase the life,Unit ten thousand */
/* block info */
const char *fee_name;
uint16_t block_number; /* number of target virtual blocks */
uint16_t block_length; /* maximum size of the target virtual block, align size access_ALIGN_size */
uint32_t block_data_size; /* target virtual block data size */
};
struct fee_block {
const char *fee_name;
struct list_node node; /* list node */
osMutexId_t fee_mutex;
struct fee_dev fee_dev; /* fee device */
struct fee_config_block fee_con; /* fee block config */
};
/* fee block APIs */
int fee_init_block(void);
int fee_init_block(void);
int fee_register_block(struct fee_block *fee);
int fee_unregister_block(struct fee_block *fee);
/* single block can be accessed */
int fee_read_block(const char *fee_name, uint16_t block_number,
uint16_t block_offset, uint8_t *data_buffer, uint16_t length);
int fee_write_block(const char *fee_name, uint16_t block_number,
const uint8_t *data_buffer, uint16_t length);
#endif /* DISK_FEE_BLCOK_H_ */

241
middleware/fee/fee_eeprom.c Normal file
View File

@@ -0,0 +1,241 @@
/**
* @file fee_eeprom.c
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#include <debug.h>
#include <stdlib.h>
#include <string.h>
#include <param.h>
#include <types.h>
#include <stdarg.h>
#include <lib/list.h>
#include <fee/fee_eeprom.h>
static struct list_node g_fee_list;
static struct fee_eeprom *fee_get_dev(const char *fee_name)
{
struct fee_eeprom *fee_eeprom;
/* matches nodes based on name */
list_for_every_entry(&g_fee_list, fee_eeprom,
struct fee_eeprom, node) {
if (!strcmp(fee_name, fee_eeprom->fee_name)) {
return fee_eeprom;
}
}
return NULL;
}
static int fee_eeprom_check(struct fee_config_eeprom *fee_con)
{
struct disk_dev_info *disk_dev = fee_con->disk_dev;
/* check whether the Flash capacity is supported */
uint16_t pe_ratio = ROUNDUP(fee_con->eeprom_pe_cycles,
disk_dev->pe_cycles) / disk_dev->pe_cycles;
uint16_t size_avg = fee_con->eeprom_align_size * FEE_EEPROM_SIZE_AVG;
disk_size_t target_size = fee_con->eeprom_size * pe_ratio +
(fee_con->eeprom_size / size_avg) * pe_ratio * sizeof(struct fee_record_info);
if (target_size > disk_dev->size) {
ssdk_printf(SSDK_CRIT,
"fee eeprom target_size %llx actual size %llx,space size does not meet the requirements\n",
target_size, disk_dev->size);
return -1;
}
ssdk_printf(SSDK_INFO, "fee eeprom target_size %llx actual size %llx\n",
target_size, disk_dev->size);
return 0;
}
int fee_register_eeprom(struct fee_eeprom *fee)
{
int ret = 0;
struct fee_dev *fee_dev = &fee->fee_dev;
struct fee_config_eeprom *fee_con = &fee->fee_con;
fee->fee_name = fee_con->fee_name;
ssdk_printf(SSDK_INFO, "register fee eeprom device %s\n", fee->fee_name);
if (NULL != fee_get_dev(fee->fee_name)) {
ssdk_printf(SSDK_CRIT, "fee devicve %s already registered\n", fee->fee_name);
return -1;
}
/* check the configuration */
ret = fee_eeprom_check(fee_con);
if (ret) {
ssdk_printf(SSDK_CRIT, "register fee eeprom device %s\n error", fee->fee_name);
return -1;
}
/* insert node */
list_add_tail(&g_fee_list, &fee->node);
fee_dev->disk_dev = fee_con->disk_dev;
fee_dev->block_length = fee_con->eeprom_align_size;
fee_dev->block_number = fee_con->eeprom_size / fee_dev->block_length;
fee_dev->page_mode = FEE_PAGE_EEPROM;
fee_dev->block_addr_mask = fee_con->block_addr_mask;
fee_dev->block_addr_size = fee_con->block_addr_size;
ret = fee_init(fee_dev);
if (ret) {
ssdk_printf(SSDK_CRIT, "fee eeprom %s init faild\n", fee->fee_name);
goto error;
}
return ret;
error:
if (list_in_list(&fee->node))
list_delete(&fee->node);
return ret;
}
int fee_unregister_eeprom(struct fee_eeprom *fee)
{
int ret = 0;
struct fee_dev *fee_dev = &fee->fee_dev;
ssdk_printf(SSDK_INFO, "unregiste fee eeprom device %s\n", fee->fee_name);
fee->fee_name = NULL;
/* remove nodes */
if (list_in_list(&fee->node))
list_delete(&fee->node);
fee_exit(fee_dev);
return ret;
}
int fee_read_eeprom(const char *fee_name, uint32_t addr, uint8_t *data_buffer,
uint16_t length)
{
int ret = 0;
struct fee_eeprom *fee = fee_get_dev(fee_name);
if (NULL == fee) {
ssdk_printf(SSDK_CRIT, "no fee devicve %s\n", fee_name);
return -1;
}
ssdk_printf(SSDK_INFO, "read fee eeprom device %s addr:%x length:%x\n", fee->fee_name, addr, length);
struct fee_dev *fee_dev = &fee->fee_dev;
struct fee_config_eeprom *fee_con = &fee->fee_con;
if (!IS_ALIGNED(addr, fee_dev->block_length)) {
ssdk_printf(SSDK_CRIT,
"fee_read eeprom addr %d not aligned to record_length %d\n",
addr, fee_dev->block_length);
return -1;
}
uint16_t block_number = addr / fee_dev->block_length;
if (!IS_ALIGNED(length, fee_dev->block_length)) {
ssdk_printf(SSDK_CRIT,
"fee_read eeprom length %d not aligned to record_length %d\n",
length, fee_dev->block_length);
return -1;
}
if ((addr + length) > fee_con->eeprom_size) {
ssdk_printf(SSDK_CRIT,
"fee_read eeprom addr %d length %d more than eeprom capacity %d\n",
addr, length, fee_con->eeprom_size);
return -1;
}
ret = fee_read_record_multiple(fee_dev, block_number, data_buffer, length);
if (ret) {
ssdk_printf(SSDK_CRIT, "fee_read_record_multiple fee_name %s addr %d error\n",
fee_name, addr);
return -1;
}
return ret;
}
int fee_write_eeprom(const char *fee_name, uint32_t addr,
const uint8_t *data_buffer, uint16_t length)
{
int ret = 0;
struct fee_eeprom *fee = fee_get_dev(fee_name);
if (NULL == fee) {
ssdk_printf(SSDK_CRIT, "no fee devicve %s\n", fee_name);
return -1;
}
struct fee_dev *fee_dev = &fee->fee_dev;
struct fee_config_eeprom *fee_con = &fee->fee_con;
ssdk_printf(SSDK_INFO, "write fee eeprom device %s addr:%x length:%x\n", fee->fee_name, addr, length);
if (!IS_ALIGNED(addr, fee_dev->block_length)) {
ssdk_printf(SSDK_CRIT,
"fee_write eeprom addr %d not aligned to record_length %d\n",
addr, fee_dev->block_length);
return -1;
}
uint16_t block_number = addr / fee_dev->block_length;
if (!IS_ALIGNED(length, fee_dev->block_length)) {
ssdk_printf(SSDK_CRIT,
"fee_write eeprom length %d not aligned to record_length %d\n",
length, fee_dev->block_length);
return -1;
}
if ((addr + length) > fee_con->eeprom_size) {
ssdk_printf(SSDK_CRIT,
"fee_write eeprom addr %d length %d more than eeprom capacity %d\n",
addr, length, fee_con->eeprom_size);
return -1;
}
ret = fee_write_record_multiple(fee_dev, block_number, (uint8_t *)data_buffer,
length);
if (ret) {
ssdk_printf(SSDK_CRIT, "fee_write_record_multiple fee_name %s addr %d error\n",
fee_name, addr);
return -1;
}
return ret;
}
int fee_init_eeprom(void)
{
ssdk_printf(SSDK_INFO, "fee eeprom init\n");
/* disk list node init */
list_initialize(&g_fee_list);
return 0;
}
int fee_exit_eeprom(void)
{
ssdk_printf(SSDK_INFO, "fee eeprom exit\n");
/* disk list node init */
return 0;
}

View File

@@ -0,0 +1,60 @@
/**
* @file fee_eeprom.h
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef DISK_FEE_EEPROM_H_
#define DISK_FEE_EEPROM_H_
#include "fee.h"
#include <lib/list.h>
#define FEE_EEPROM_NAME(n) "fee_eeprom"#n
#define FEE_EEPROM_SIZE_AVG 2 /* average access size,unit is eeprom_align_size */
struct fee_config_eeprom {
/* nor flash info */
struct disk_dev_info *disk_dev;
/* eeprom info */
const char *fee_name;
uint16_t eeprom_size; /* The capacity of the virtual EEPROM */
uint16_t eeprom_align_size;/* virtual EEPROM access alignment size, alignment access_align_size */
uint16_t eeprom_pe_cycles; /* virtual EEPROM lifetime */
/* block addr buff */
uint8_t *block_addr_mask; /* used to store block_addr mask */
uint16_t block_addr_size; /* block_addr buff size */
uint16_t block_addr_num; /* block_addr buff number */
};
struct fee_eeprom {
const char *fee_name;
struct list_node node; /* list node */
struct fee_dev fee_dev; /* fee device */
struct fee_config_eeprom fee_con; /* fee eeprom config */
};
/* fee eeprom APIs */
int fee_init_eeprom(void);
int fee_exit_eeprom(void);
int fee_register_eeprom(struct fee_eeprom *fee);
int fee_unregister_eeprom(struct fee_eeprom *fee);
/* access to multiple blocks, address and length must be aligned eeprom_align_size */
int fee_read_eeprom(const char *fee_name, uint32_t addr, uint8_t *data_buffer,
uint16_t length);
int fee_write_eeprom(const char *fee_name, uint32_t addr,
const uint8_t *data_buffer, uint16_t length);
#endif /* DISK_FEE_EEPROM_H_ */

View File

@@ -0,0 +1,14 @@
1. The path to the required header file:
\middleware\flash\include
2. Dependent source:
\drivers\source\dma\sdrv_dma.c
drivers\source\vic\irq.c
\devices\$PART_ID$\reset_ip.c
\drivers\source\reset\sdrv_rstgen.c
\drivers\source\reset\sdrv_rstgen_hw.h
\drivers\source\clk\sdrv_ckgen.c
\drivers\source\spi_nor\sdrv_hyperbus.c
\drivers\source\spi_nor\sdrv_spi_nor.c
\drivers\source\spi_nor\sdrv_xspi.c
3. -DCONFIG_IRQ for irq mode
4. -DCONFIG_XSPI_ENABLE_DMA & -DCONFIG_IRQ & -DXSPI_USE_DIRECT_MODE=0 for dma mode

460
middleware/flash/fls.c Normal file
View File

@@ -0,0 +1,460 @@
/**
* @file fls.c
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#include <armv7-r/barriers.h>
#include <armv7-r/cache.h>
#include <clock_cfg.h>
#include <clock_ip.h>
#include <debug.h>
#include <irq.h>
#include <irq_num.h>
#include <param.h>
#include <pinmux_cfg.h>
#include <regs_base.h>
#include <reset_cfg.h>
#include <scr_hw.h>
#include <sdrv_ckgen.h>
#include <sdrv_rstgen.h>
#include <sdrv_scr.h>
#include <sdrv_spi_nor.h>
#include <sdrv_xspi.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include <udelay/udelay.h>
#include <reset_ip.h>
#if CONFIG_XSPI_ENABLE_DMA
#include "sdrv_dma.h"
#endif
#include "fls.h"
extern sdrv_scr_t g_scr_ctrl;
#define XSPI_SWITCH_DEVICE_MAX_NUM (2u)
typedef struct {
Fls_Controller_ID_t id;
struct spi_nor_host spi_nor_host;
struct xspi_pdata xspi;
struct spi_nor flash[XSPI_SWITCH_DEVICE_MAX_NUM];
uint8_t flash_num;
#if CONFIG_XSPI_ENABLE_DMA
sdrv_dma_t g_dma_instance;
sdrv_dma_channel_t g_channel;
volatile uint8_t dma_xspi_done_flag;
uint8_t dma_xspi_init_dmac_flag;
#endif
bool is_locksetp_mode;
bool is_parallel_mode;
bool is_xip_mode;
uint8_t flag;
} Fls_Context_t;
#if defined(APB_XSPI2PORTA_BASE) && defined(APB_XSPI2PORTB_BASE)
#define XSPI_RESOURE_NUM (2u)
#else
#define XSPI_RESOURE_NUM (1u)
#endif
#define XSPI_PORT_MAX_NUM (XSPI_RESOURE_NUM * 2)
static Fls_Context_t fls_context[XSPI_PORT_MAX_NUM];
static sdrv_ckgen_node_t *clk_node_tab[FLS_CONTROLLER_ID_MAX] = {
[FLS_XSPI1_PORTA] = CLK_NODE(g_ckgen_ip_xspi1a),
[FLS_XSPI1_PORTB] = CLK_NODE(g_ckgen_ip_xspi1b),
#if (XSPI_RESOURE_NUM >= 2)
[FLS_XSPI2_PORTA] = CLK_NODE(g_ckgen_ip_xspi2a),
[FLS_XSPI2_PORTB] = CLK_NODE(g_ckgen_ip_xspi2b),
#endif
};
static struct xspi_config host_config[FLS_CONTROLLER_ID_MAX] = {
[FLS_XSPI1_PORTA] = {
.id = FLS_XSPI1_PORTA,
.irq = XSPI1_IRQ0_INTR_NUM,
.apb_base = APB_XSPI1PORTA_BASE,
.direct_base = XSPI1_XSPI1PORTA_BASE,
},
[FLS_XSPI1_PORTB] = {
.id = FLS_XSPI1_PORTB,
.irq = XSPI1_IRQ1_INTR_NUM,
.apb_base = APB_XSPI1PORTB_BASE,
.direct_base = XSPI1_XSPI1PORTB_BASE,
},
#if (XSPI_RESOURE_NUM >= 2)
[FLS_XSPI2_PORTA] = {
.id = FLS_XSPI2_PORTA,
.irq = XSPI2_IRQ0_INTR_NUM,
.apb_base = APB_XSPI2PORTA_BASE,
.direct_base = XSPI2_XSPI2PORTA_BASE,
},
[FLS_XSPI2_PORTB] = {
.id = FLS_XSPI2_PORTB,
.irq = XSPI2_IRQ1_INTR_NUM,
.apb_base = APB_XSPI2PORTB_BASE,
.direct_base = XSPI2_XSPI2PORTB_BASE,
},
#endif
};
#ifndef SCR_SF_XSPI1_SRC_CFG_LOCKSTEP_MODE_N
#define SCR_SF_XSPI1_SRC_CFG_LOCKSTEP_MODE_N SCR_SF_XSPI1_LOCKSTEP_DISABLE
#endif
static void sdrv_xspi_lockstep_enable(bool flag, uint8_t id)
{
scr_signal_t signal;
sdrv_rstgen_sig_t *xspi_porta, *xspi_portb;
switch (id) {
case FLS_XSPI1_PORTA:
signal = (scr_signal_t)SCR_SF_XSPI1_SRC_CFG_LOCKSTEP_MODE_N;
xspi_porta = &rstsig_xspi1a;
xspi_portb = &rstsig_xspi1b;
break;
#if (XSPI_RESOURE_NUM >= 2)
case FLS_XSPI2_PORTA:
signal = (scr_signal_t)SCR_SF_XSPI2_SRC_CFG_LOCKSTEP_MODE_N;
xspi_porta = &rstsig_xspi2a;
xspi_portb = &rstsig_xspi2b;
break;
#endif
default:
ssdk_printf(SSDK_ERR, "xspi %d unsupport lockstep mode", id);
return;
}
sdrv_rstgen_assert(xspi_portb);
sdrv_rstgen_assert(xspi_porta);
DSB;
udelay(10);
scr_set(&g_scr_ctrl, &signal, !flag);
udelay(10);
DSB;
sdrv_rstgen_deassert(xspi_porta);
sdrv_rstgen_deassert(xspi_portb);
}
static void sdrv_xspi_parallel_enable(bool flag, uint8_t id)
{
scr_signal_t signal;
sdrv_rstgen_sig_t *xspi_porta, * xspi_portb;
switch (id) {
case FLS_XSPI1_PORTA:
signal = (scr_signal_t)SCR_SF_XSPI1_SRC_CFG_PARALLEL_MODE;
xspi_porta = &rstsig_xspi1a;
xspi_portb = &rstsig_xspi1b;
break;
#if (XSPI_RESOURE_NUM >= 2)
case FLS_XSPI2_PORTA:
signal = (scr_signal_t)SCR_SF_XSPI2_SRC_CFG_PARALLEL_MODE;
xspi_porta = &rstsig_xspi2a;
xspi_portb = &rstsig_xspi2b;
break;
#endif
default:
ssdk_printf(SSDK_ERR, "xspi %d unsupport parallel mode", id);
return;
}
sdrv_rstgen_assert(xspi_portb);
sdrv_rstgen_assert(xspi_porta);
DSB;
udelay(10);
scr_set(&g_scr_ctrl, &signal, flag);
udelay(10);
DSB;
sdrv_rstgen_deassert(xspi_porta);
sdrv_rstgen_deassert(xspi_portb);
}
#if CONFIG_XSPI_ENABLE_DMA
static void sdrv_dma_transfer_every_mad_done(uint32_t status, uint32_t param,
void *context) {
Fls_Context_t *pCtx = context;
ssdk_printf(SSDK_INFO, " xspi set dma transfer done\r\n");
if (status == SDRV_DMA_COMPLETED) {
pCtx->dma_xspi_done_flag = 1;
}
}
static void sdrv_xspi_dma_config(struct spi_nor *nor, flash_addr_t addr, uint8_t *buf,
uint32_t len, bool is_read_flag, uint32_t burst_len) {
uint32_t burst_width;
struct xspi_pdata *xspi = nor->host->priv_data;
sdrv_dma_channel_config_t xspi_dma_cfg;
Fls_Context_t *pCtx = &fls_context[nor->id];
burst_width = SDRV_DMA_BUSWIDTH_4_BYTES;
ssdk_printf(SSDK_INFO, "burst lens is %d\n", burst_len);
if (pCtx->dma_xspi_init_dmac_flag == 0) {
ssdk_printf(SSDK_INFO, "dma init controller\r\n");
/* 1.init dma controller (only one time) */
sdrv_dma_init_dmac(APB_DMA_SF0_BASE);
/* 2.create dma instance */
sdrv_dma_create_instance(&pCtx->g_dma_instance, APB_DMA_SF0_BASE);
pCtx->dma_xspi_init_dmac_flag = 1;
}
/* 3.get default config */
sdrv_dma_init_channel_config(&xspi_dma_cfg, &pCtx->g_dma_instance);
/* 4.modify config param */
xspi_dma_cfg.channel_id = SDRV_DMA_CHANNEL_1; /* select channel */
xspi_dma_cfg.xfer_mode =
SDRV_DMA_TRANSFER_MODE_SINGLE; /* single or continuous or linklist */
xspi_dma_cfg.buffer_mode = SDRV_DMA_SINGLE_BUFFER; /* buffer mode */
xspi_dma_cfg.loop_mode =
SDRV_DMA_LOOP_MODE_2; /* mem2mem(MODE_0) mem2dev/dev2mem(MODE_1,MODE_2) */
xspi_dma_cfg.interrupt_type = SDRV_DMA_LAST_MAD_DONE; /* set interrupt type */
xspi_dma_cfg.trig_mode = SDRV_DMA_TRIGGER_BY_HARDWARE; /* by hardware trig */
if (is_read_flag) {
ssdk_printf(SSDK_INFO, "dev2mem\r\n");
xspi_dma_cfg.xfer_type = SDRV_DMA_DIR_DEV2MEM;
xspi_dma_cfg.src_addr = (addr_t)xspi->apb_base + XSPI_INDIRECT_RDATA;
xspi_dma_cfg.dst_addr = (addr_t)buf;
xspi_dma_cfg.src_inc =
SDRV_DMA_ADDR_NO_INC; /* source address increase or not */
xspi_dma_cfg.dst_inc =
SDRV_DMA_ADDR_INC; /* destination address increase or not */
xspi_dma_cfg.src_port_sel =
SDRV_DMA_PORT_AHB32; /* periph -> SDRV_DMA_PORT_AHB32 */
}
else {
ssdk_printf(SSDK_INFO, "mem2dev\r\n");
xspi_dma_cfg.xfer_type = SDRV_DMA_DIR_MEM2DEV;
xspi_dma_cfg.dst_addr = (addr_t)xspi->apb_base + XSPI_INDIRECT_WDATA;
xspi_dma_cfg.src_addr = (addr_t)buf;
xspi_dma_cfg.src_inc = SDRV_DMA_ADDR_INC; /* source address increase or not */
xspi_dma_cfg.dst_inc =
SDRV_DMA_ADDR_NO_INC; /* destination address increase or not */
xspi_dma_cfg.dst_port_sel =
SDRV_DMA_PORT_AHB32; /* periph -> SDRV_DMA_PORT_AHB32 */
}
xspi_dma_cfg.xfer_bytes = len;
xspi_dma_cfg.src_width = (sdrv_dma_bus_width_e)burst_width;
xspi_dma_cfg.dst_width = (sdrv_dma_bus_width_e)burst_width;
xspi_dma_cfg.src_burst_len = burst_len;
xspi_dma_cfg.dst_burst_len = burst_len;
/* 5.init channel config */
sdrv_dma_init_channel(&pCtx->g_channel, &xspi_dma_cfg);
/* 6.set interrupt callback */
pCtx->g_channel.irq_callback = sdrv_dma_transfer_every_mad_done;
pCtx->g_channel.irq_context = (void *)pCtx;
/* 7.start channel transfer */
pCtx->dma_xspi_done_flag = 0;
sdrv_dma_start_channel_xfer(&pCtx->g_channel);
}
static void sdrv_xspi_dma_stop(struct spi_nor *nor) {
Fls_Context_t *pCtx = &fls_context[nor->id];
sdrv_dma_stop_channel_xfer(&pCtx->g_channel);
return;
}
static void spi_nor_register_dma_handler(struct spi_nor *flash_handle) {
flash_handle->dma_xfer_config = sdrv_xspi_dma_config;
flash_handle->dma_stop = sdrv_xspi_dma_stop;
return;
}
#endif
struct spi_nor_host* sdrv_norflash_init(struct spi_nor_config *config,
uint8_t num, bool xip_en)
{
bool locksetp_mode = false;
bool parallel_mode = false;
Fls_Context_t *pCtx = NULL;
if (config->id >= XSPI_PORT_MAX_NUM) {
ssdk_printf(SSDK_CRIT, "config id(%d) Cross the line(%d)!\r\n",
config->id, XSPI_PORT_MAX_NUM);
return NULL;
}
pCtx = &fls_context[config->id];
/* config dev spi nor dev single mode */
switch (config->dev_mode) {
case SPI_NOR_DEV_LOCKSTEP_MODE:
locksetp_mode = true;
break;
case SPI_NOR_DEV_PARALLEL_MODE:
parallel_mode = true;
break;
default:
break;
}
if (pCtx->flag) { // host has been initialized
if ((locksetp_mode != pCtx->is_locksetp_mode) ||
(parallel_mode != pCtx->is_parallel_mode) ||
(xip_en != pCtx->is_xip_mode)) {
ssdk_printf(SSDK_CRIT, "This controller(%d) has been initialized to (lockstep:%d parallel%d xip:%d) mode!\r\n",
config->id, pCtx->is_locksetp_mode, pCtx->is_parallel_mode, pCtx->is_xip_mode);
return NULL;
} else if ((pCtx->flash_num + num) > XSPI_SWITCH_DEVICE_MAX_NUM) {
ssdk_printf(SSDK_CRIT, "This controller(%d) unsupport %d devices be connected at the same time!\r\n",
config->id, pCtx->flash_num + num);
return NULL;
}
} else {
sdrv_ckgen_node_t *clk = clk_node_tab[config->id];
struct xspi_config host_cfg;
memcpy(&host_cfg, &host_config[config->id], sizeof(struct xspi_config));
if (!xip_en) {
/* close locksetp/parallel mode */
sdrv_xspi_lockstep_enable(locksetp_mode, config->id);
sdrv_xspi_parallel_enable(parallel_mode, config->id);
}
/* initializes xspi host */
host_cfg.ref_clk = sdrv_ckgen_get_rate(clk);
host_cfg.xip_mode = xip_en;
if (config->xfer_mode == SPI_NOR_XFER_POLLING_MODE) {
host_cfg.irq = 0;
}
sdrv_xspi_host_init(&(pCtx->spi_nor_host), &(pCtx->xspi), &host_cfg);
pCtx->spi_nor_host.clk = clk;
sdrv_ckgen_set_rate(clk, config->baudrate);
pCtx->is_locksetp_mode = locksetp_mode;
pCtx->is_parallel_mode = parallel_mode;
pCtx->is_xip_mode = xip_en;
pCtx->flag = 1;
pCtx->id = (Fls_Controller_ID_t)config->id;
ssdk_printf(SSDK_CRIT, "xspi(%d) init (lockstep:%d parallel%d) sucessfully! clock rate is %u!\r\n",
pCtx->id, pCtx->is_locksetp_mode, pCtx->is_parallel_mode, sdrv_ckgen_get_rate(clk));
}
for (uint8_t i = 0; i < num; i++) {
config->cs = pCtx->flash_num;
/* initializes spi nor device */
if (sdrv_spi_nor_init(&(pCtx->flash[pCtx->flash_num]), &(pCtx->spi_nor_host), config)) {
ssdk_printf(SSDK_CRIT, "spinor(id:%d cs:%d) init failed!\r\n", pCtx->id, pCtx->flash_num);
return NULL;
}
#if CONFIG_XSPI_ENABLE_DMA
spi_nor_register_dma_handler(&(pCtx->flash[pCtx->flash_num]));
#endif
ssdk_printf(SSDK_CRIT, "spinor(id:%d cs:%d) size = 0x%llx, sector_size = 0x%x \r\n",
pCtx->id, pCtx->flash_num,
pCtx->flash[pCtx->flash_num].info.size,
pCtx->flash[pCtx->flash_num].info.sector_size);
pCtx->flash_num++;
}
return &pCtx->spi_nor_host;
}
void sdrv_norflash_deinit(struct spi_nor_host* host) {
uint32_t j;
Fls_Context_t *pCtx = &fls_context[host->id];
if (!pCtx->flag) {
return;
}
for (j = 0; j < pCtx->flash_num; j++) {
struct spi_nor *flash = &pCtx->flash[j];
/* soft reset flash */
sdrv_spi_nor_deinit(flash);
/* soft reset xspi host */
sdrv_spi_nor_drv_deinit(flash);
}
memset(pCtx, 0, sizeof(Fls_Context_t));
}
void sdrv_norflash_deinit_all(void)
{
uint32_t i;
for (i = 0; i < FLS_CONTROLLER_ID_MAX; i++) {
sdrv_norflash_deinit(&(fls_context[i].spi_nor_host));
}
return;
}
struct spi_nor* get_flashhandler_by_id(Fls_Controller_ID_t port_id, uint8_t cs_id) {
if (port_id >= FLS_CONTROLLER_ID_MAX) {
ssdk_printf(SSDK_CRIT, "xspi port id %s cross!\r\n", port_id);
return NULL;
} else if (!fls_context[port_id].flag) {
ssdk_printf(SSDK_CRIT, "xspi host %d uninitialized id\r\n", port_id);
return NULL;
} else if (cs_id >= fls_context[port_id].flash_num) {
ssdk_printf(SSDK_CRIT, "xspi host %d cs %d uninitialized id\r\n",
port_id, cs_id);
return NULL;
}
return &(fls_context[port_id].flash[cs_id]);
}
int sdrv_norflash_enable_rfd(struct spi_nor_host* host, uint8_t mask) {
if (!host || !host->nor_tab[0]) {
return -1;
}
return sdrv_spi_nor_enable_rfd(host->nor_tab[0], mask);
}
int get_norflash_direct_base(struct spi_nor_host* host, addr_t *direct_base) {
if (!host || !direct_base) {
return -1;
}
*direct_base = ((struct xspi_pdata*)(host->priv_data))->direct_base;
return 0;
}
int sdrv_norflash_swap_cs(struct spi_nor_host* host, bool is_reverse) {
uint32_t reg;
uint8_t cs_order = (is_reverse) ? 0x89 : 0x98;
if (!host) {
return -1;
}
reg = readl(((struct xspi_pdata*)(host->priv_data))->apb_base + 0x44);
reg = (reg & (~0xffu)) | (cs_order);
writel(reg, ((struct xspi_pdata*)(host->priv_data))->apb_base + 0x44);
return 0;
}
int sdrv_norflash_get_flash_info(struct spi_nor_host* host, uint8_t cs_id,
Fls_Flash_Info_t* info) {
if (!host || !info) {
return -1;
} else if (!host->nor_tab[cs_id]) {
return -2;
}
info->octal_dtr_en = host->nor_tab[cs_id]->octal_dtr_en;
info->cinst_type = (host->nor_tab[cs_id]->info.read_proto >> 8) & 0xf;
return 0;
}

View File

@@ -0,0 +1,105 @@
/**
* @file fls.h
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef FLASH_FLS_H_
#define FLASH_FLS_H_
#include <sdrv_spi_nor.h>
#include <sdrv_xspi.h>
typedef enum {
FLS_XSPI1_PORTA = 0,
FLS_XSPI1_PORTB,
FLS_XSPI2_PORTA,
FLS_XSPI2_PORTB,
FLS_CONTROLLER_ID_MAX,
} Fls_Controller_ID_t;
typedef struct {
bool octal_dtr_en;
uint8_t cinst_type; /* 0:Single | 1:Dual | 2:Quad | 3:Octal */
} Fls_Flash_Info_t;
/******************************************************************************
** Service name : sdrv_norflash_init **
** Parameters (in) : ConfigPtr Pointer to flash driver configuration set **
** Parameters (in) : Number of flash bound to the controller **
** Parameters (in) : Enable or disable xip mode **
** Return value : struct spi_nor_host*, failed is NULL **
** Description : Initializes the Flash Driver **
******************************************************************************/
struct spi_nor_host* sdrv_norflash_init(struct spi_nor_config *config,
uint8_t cs_num, bool xip_en);
/******************************************************************************
** Service name : sdrv_norflash_deinit **
** Parameters (in) : ConfigPtr Pointer to xspi host **
** Return value : NONE **
** Description : DeInitializes the Host and the Flash attached **
******************************************************************************/
void sdrv_norflash_deinit(struct spi_nor_host* host);
/******************************************************************************
** Service name : sdrv_norflash_deinit_all **
** Return value : NONE **
** Description : DeInitializes all Host and the Flash **
******************************************************************************/
void sdrv_norflash_deinit_all(void);
/******************************************************************************
** Service name : get_flashhandler_by_id **
** Parameters (in) : The index of host(Fls_Controller_ID_t) **
** Parameters (in) : The index of flash bound to the controller **
** Return value : struct spi_nor*, failed is NULL **
** Description : Get the Flash handler **
******************************************************************************/
struct spi_nor* get_flashhandler_by_id(Fls_Controller_ID_t port_id, uint8_t cs_id);
/******************************************************************************
** Service name : get_flashhandler_by_id **
** Parameters (in) : The index of host(Fls_Controller_ID_t) **
** Parameters (in) : The mask of rfd region **
** Return value : 0, failed is !0 **
** Description : Get the Flash handler **
******************************************************************************/
int sdrv_norflash_enable_rfd(struct spi_nor_host* host, uint8_t mask);
/******************************************************************************
** Service name : get_norflash_direct_base **
** Parameters (in) : The index of host(Fls_Controller_ID_t) **
** Parameters (out) : The direct base of flash **
** Return value : 0, failed is !0 **
** Description : Get the Flash handler **
******************************************************************************/
int get_norflash_direct_base(struct spi_nor_host* host, addr_t *direct_base);
/******************************************************************************
** Service name : sdrv_norflash_swap_cs **
** Parameters (in) : The index of host(Fls_Controller_ID_t) **
** Parameters (in) : The order of cs (Positive:0, Reverse:1) **
** Return value : 0, failed is !0 **
** Description : Swap Flash cs sequence **
******************************************************************************/
int sdrv_norflash_swap_cs(struct spi_nor_host* host, bool is_reverse);
/******************************************************************************
** Service name : sdrv_norflash_swap_cs **
** Parameters (in) : The index of host(Fls_Controller_ID_t) **
** Parameters (in) : The index of cs **
** Parameters (out) : The infomation of flash **
** Return value : 0, failed is !0 **
** Description : Swap Flash cs sequence **
******************************************************************************/
int sdrv_norflash_get_flash_info(struct spi_nor_host* host, uint8_t cs_id,
Fls_Flash_Info_t* info);
#endif

View File

@@ -0,0 +1,119 @@
/***********************************************************************
* SEGGER Microcontroller GmbH *
* The Embedded Experts *
************************************************************************
* *
* (c) SEGGER Microcontroller GmbH *
* All rights reserved *
* www.segger.com *
* *
************************************************************************
* *
************************************************************************
* *
* *
* Licensing terms *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* *
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "AS IS" AND ANY *
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR *
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE *
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, *
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY *
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH. *
* DAMAGE. *
* *
************************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : FlashDev.c
Purpose : Flash device description Template
*/
#include <compiler.h>
#include "FlashOS.h"
struct SECTOR_INFO {
U32 SectorSize; // Sector Size in bytes
U32 SectorStartAddr; // Start address of the sector area (relative to the
// "BaseAddr" of the flash)
};
struct FlashDevice {
U16 AlgoVer; // Algo version number
U8 Name[128]; // Flash device name. NEVER change the size of this array!
U16 Type; // Flash device type
U32 BaseAddr; // Flash base address
U32 TotalSize; // Total flash device size in Bytes (256 KB)
U32 PageSize; // Page Size (number of bytes that will be passed to
// ProgramPage(). MinAlig is 8 byte
U32 Reserved; // Reserved, should be 0
U8 ErasedVal; // Flash erased value
U32 TimeoutProg; // Program page timeout in ms
U32 TimeoutErase; // Erase sector timeout in ms
struct SECTOR_INFO SectorInfo[4]; // Flash sector layout definition. May be
// adapted up to 512 entries
};
__USED __SECTION(".DEVDSCR") const struct FlashDevice FlashDevice = {
0x0101, // Algo version. Must be == 0x0101
{"ospi flash"}, // Flash device name
1, // Flash device type. Must be == 1
0x00000000, // Flash base address
0x04000000, // Total flash device size in Bytes
#if CONFIG_HYPERBUS_MODE
1 << 14, // Page Size (Will be passed as <NumBytes> to ProgramPage(). A
// multiple of this is passed as <NumBytes> to
// SEGGER_OPEN_Program() to program moer than 1 page in 1 RAMCode
// call, speeding up programming).
#else
1 << 12, // Page Size (Will be passed as <NumBytes> to ProgramPage(). A
// multiple of this is passed as <NumBytes> to
// SEGGER_OPEN_Program() to program moer than 1 page in 1 RAMCode
// call, speeding up programming).
#endif
0, // Reserved, should be 0
0xFF, // Flash erased value
10000, // Program page timeout in ms
5000, // Erase sector timeout in ms
//
// Flash sector layout definition
// Keil / CMSIS does not do a great job in explaining these...
// The logic is as follows:
// For flashes with uniform sectors, you need exactly 1 entry here:
// <SectorSize>, <SectorStartOff> (rel. to <FlashBaseAddr>) For a flash with
// 512 sectors, the entry would be: 0x200, 0x0
//
// When having a flash with 3 different sector sizes, like: 4 * 16 KB, 1 *
// 64 KB, 1 * 128 KB you will have 3 entries here: 0x4000, 0x0 4
// * 16 KB = 64 KB 0x10000, 0x10000 1 * 64 KB = 64 KB 0x20000,
// 0x20000 1 * 128 KB = 128 KB
//
{
#if CONFIG_HYPERBUS_MODE
{0x40000, 0x0}, // 256 * 256 KB = 64M
#else
{0x1000, 0x0}, // 256 * 4 KB = 64M
#endif
{0xFFFFFFFF, 0xFFFFFFFF} // Indicates the end of the flash sector
// layout. Must be present.
}};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,109 @@
#include <FlashOS.h>
#include <compiler.h>
#include <debug.h>
#include <part.h>
#include <stdint.h>
#if CONFIG_E3L == 1
#define CMD_ARGS_ADDRESS 0x4FDFE0
#else
#define CMD_ARGS_ADDRESS 0x3FDFE0
#endif
#define CMD_BUF_ADDRESS (CMD_ARGS_ADDRESS + 0x20)
#define CMD_PROGRAM (1)
#define CMD_BLOCK_ERASE (2)
#define CMD_CHIP_ERASE (5)
#define NO_ERROR (0x0)
#define PROGRAM_ERROR (0x100)
#define SECTOR_REASE_ERROR (0x101)
#define BULK_ERASE_ERROR (0x102)
#define LOCK_ERROR (0x103)
#define UNLOCK_ERROR (0x104)
#define NOT_IMPLEMENTED_ERROR (0x141)
#define FLASH_INIT_ERROR (0x142)
typedef struct trace32_cmd_args {
uint32_t flash_base_address;
uint32_t reserved;
uint32_t data_bus_width;
uint32_t offset;
uint32_t address;
uint32_t size;
uint32_t timing;
uint32_t command;
} __PACKED trace32_cmd_args_t;
typedef struct trace32_return_args {
uint32_t not_valid_1;
uint32_t reserved_1;
uint32_t not_valid_2;
uint32_t reserved_2;
uint32_t address;
uint32_t not_valid_3;
uint32_t reserved_3;
uint32_t status;
} __PACKED trace32_return_args_t;
void t32_flashloader_end(void);
void t32_flashloader_begin(void);
__ARM __USED __SECTION(".T32CODEBEGIN") void t32_flashloader_begin(void)
{
t32_flashloader_end();
}
__USED __SECTION(".T32CODEEND") void t32_flashloader_end(void)
{
struct trace32_cmd_args *pCmdArgs =
(struct trace32_cmd_args *)CMD_ARGS_ADDRESS;
struct trace32_return_args *pRetArgs =
(struct trace32_return_args *)CMD_ARGS_ADDRESS;
int ret;
ret = Init(NULL, NULL, NULL);
if (ret != 0) {
pRetArgs->status = FLASH_INIT_ERROR;
return;
}
if (pCmdArgs->command == CMD_PROGRAM) {
ret = SEGGER_OPEN_Program(pCmdArgs->address, pCmdArgs->size,
(unsigned char *)CMD_BUF_ADDRESS);
if (ret != 0) {
pRetArgs->status = PROGRAM_ERROR;
return;
}
} else if (pCmdArgs->command == CMD_BLOCK_ERASE) {
if (pCmdArgs->address % jflash_wrapper->sector_size != 0) {
ssdk_printf(SSDK_NOTICE,
"Erase address must be aligned to the sector size\r\n");
pRetArgs->status = SECTOR_REASE_ERROR;
return;
} else if (pCmdArgs->size != jflash_wrapper->sector_size) {
ssdk_printf(SSDK_NOTICE,
"Erase size must be aligned to the sector size\r\n");
pRetArgs->status = SECTOR_REASE_ERROR;
return;
} else {
ret = SEGGER_OPEN_Erase(pCmdArgs->address, NULL, 1);
if (ret != 0) {
pRetArgs->status = SECTOR_REASE_ERROR;
return;
}
}
} else if (pCmdArgs->command == CMD_CHIP_ERASE) {
ret = EraseChip();
if (ret != 0) {
pRetArgs->status = BULK_ERASE_ERROR;
return;
}
} else {
pRetArgs->status = NOT_IMPLEMENTED_ERROR;
ssdk_printf(SSDK_NOTICE, "Not implemented command\r\n");
return;
}
pRetArgs->status = NO_ERROR;
return;
}

View File

@@ -0,0 +1,456 @@
/**
* @file bpt_update.c
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#include <board.h>
#include <bpt_v2.h>
#include <config.h>
#include <ctype.h>
#include <debug.h>
#include <flash_wrapper.h>
#include <param.h>
#include <sd_boot_img/sd_boot_img.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
sfs_t *sfs = NULL;
static uint8_t sfs_buffer[FL_SFS_SIZE] __ALIGNED(CONFIG_ARCH_CACHE_LINE);
uint8_t bpt_buffer[FL_BPT_HEDAER_LEN] __ALIGNED(CONFIG_ARCH_CACHE_LINE);
bpt_iib_t iib_info_temp __ALIGNED(CONFIG_ARCH_CACHE_LINE) = {0};
/* dump data */
void hexdump(const void *ptr, size_t len)
{
addr_t address = (addr_t)ptr;
size_t count;
for (count = 0; count < len; count += 16) {
union {
uint32_t buf[4];
uint8_t cbuf[16];
} u;
size_t s = ROUNDUP(MIN(len - count, 16), 4);
size_t i;
printf("0x%08x: ", address);
for (i = 0; i < s / 4; i++) {
u.buf[i] = ((const uint32_t *)address)[i];
printf("%08x ", u.buf[i]);
}
for (; i < 4; i++) {
printf(" ");
}
printf("|");
for (i = 0; i < 16; i++) {
unsigned char c = u.cbuf[i];
if (i < s && isprint(c)) {
printf("%c", c);
} else {
printf(".");
}
}
printf("|\r\n");
address += 16;
}
}
/* dump data */
static void BptInit(bpt_v2_t *bpt)
{
bpt->tag = FL_BPT_TAG_VAL;
bpt->reserved1 = 0;
bpt->size = FL_BPT_HEDAER_LEN;
bpt->sec_ver = 0;
bpt->digest_alg = 3;
memset(bpt->reserved2, 0, 19);
bpt->rcp.tag = FL_BPT_RCP_TAG;
bpt->rcp.size = FL_BPT_RCP_SIZE;
memset(&bpt->rcp.rot_id, 0, 1040);
memset(bpt->signature, 0, 512);
memset(bpt->key_wraps, 0, 512);
memset(bpt->reserved3, 0, 984);
bpt->sn = FL_BPT_PAGE_SN;
bpt->sn_inversion = ~(FL_BPT_PAGE_SN);
memset(bpt->reserved4, 0, 8);
}
/* add iib data */
static int BptAddIIB(bpt_iib_t *iib_info, uint32_t img_base, uint32_t bpt_base,
uint32_t link_base, uint32_t img_size, uint8_t core)
{
uint32_t img_offset;
img_offset = FLASH_ADDR_MASK((uint32_t)img_base);
if (img_offset >= (bpt_base + FL_BPT_HEDAER_LEN)) {
img_offset -= bpt_base;
} else {
ssdk_printf(SSDK_ALERT, "img_base 0x%x < bpt base 0x%x\r\n", img_base,
bpt_base);
return -1;
}
iib_info->tag = FL_BPT_IIB_TAG_VAL;
iib_info->size = FL_BPT_IIB_SIZE;
iib_info->reserved1 = 0;
memset(iib_info->dbg_ctrl, 0, 8);
memset(iib_info->did, 0, 8);
iib_info->img_type = 0;
iib_info->target_core = core;
iib_info->dec_ctrl = 0;
iib_info->reserved2 = 0;
memset(iib_info->iv, 0, 8);
iib_info->img_page = img_offset / FL_BPT_PAGE_SIZE;
iib_info->img_size = img_size;
if (link_base == 0) {
iib_info->load_addr = (uint32_t)img_base;
} else {
iib_info->load_addr = link_base;
}
iib_info->reserved3 = 0;
iib_info->entry = iib_info->load_addr;
iib_info->reserved4 = 0;
memset(iib_info->hash, 0x00, 64);
return 0;
}
/* get the iib image base */
uint32_t BptGetIIBImgbase(bpt_v2_t *bpt, uint8_t core)
{
bpt_iib_t *iib_info;
uint8_t idx;
for (idx = 0; idx < FL_BPT_IIB_NUM; idx++) {
iib_info = (bpt_iib_t *)(bpt->iib[idx]);
if (iib_info->tag == FL_BPT_IIB_TAG_VAL &&
iib_info->target_core == core) {
return (iib_info->img_page) * FL_BPT_PAGE_SIZE;
}
}
return 0;
}
/* mask an iib */
static void BptMaskIIB(bpt_v2_t *bpt, uint8_t core)
{
bpt_iib_t *iib_info;
uint8_t idx;
for (idx = 0; idx < FL_BPT_IIB_NUM; idx++) {
iib_info = (bpt_iib_t *)(bpt->iib[idx]);
if (iib_info->tag == FL_BPT_IIB_TAG_VAL &&
iib_info->target_core == core) {
memset(iib_info, 0, FL_BPT_IIB_SIZE);
break;
}
}
}
/* remove an empty iib*/
static void BptRemoveEmptyIIB(bpt_v2_t *bpt, uint8_t index)
{
bpt_iib_t *iib_info;
bpt_iib_t *iib_info_next;
uint8_t idx = index;
for (idx = index; idx < FL_BPT_IIB_NUM - 1; idx++) {
iib_info = (bpt_iib_t *)(bpt->iib[idx]);
iib_info_next = (bpt_iib_t *)(bpt->iib[idx + 1]);
if (iib_info->tag != FL_BPT_IIB_TAG_VAL) {
memcpy(iib_info, iib_info_next, FL_BPT_IIB_SIZE);
}
}
if (idx == (FL_BPT_IIB_NUM - 1)) {
iib_info = (bpt_iib_t *)(bpt->iib[idx]);
if (iib_info->tag != FL_BPT_IIB_TAG_VAL) {
memset(iib_info, 0, FL_BPT_IIB_SIZE);
}
}
}
/* exchange two iib's position */
static void BptExchangeIIB(bpt_v2_t *bpt, uint8_t index_des, uint8_t index_src)
{
bpt_iib_t *iib_info_des;
bpt_iib_t *iib_info_src;
iib_info_des = (bpt_iib_t *)(bpt->iib[index_des]);
iib_info_src = (bpt_iib_t *)(bpt->iib[index_src]);
memcpy(&iib_info_temp, iib_info_des, FL_BPT_IIB_SIZE);
memcpy(iib_info_des, iib_info_src, FL_BPT_IIB_SIZE);
memcpy(iib_info_src, &iib_info_temp, FL_BPT_IIB_SIZE);
}
/* search iib for one core */
static bpt_iib_t *BptSearchIIB(bpt_v2_t *bpt, uint8_t core)
{
bpt_iib_t *iib_info;
uint8_t idx;
uint8_t core_temp = core;
uint8_t core_remove = 0;
if (core == FL_BPT_CORE_CR5_SX) {
core = FL_BPT_CORE_CR5_SX0;
core_remove = FL_BPT_CORE_CR5_SX1;
}
if (core == FL_BPT_CORE_CR5_SP) {
core = FL_BPT_CORE_CR5_SP0;
core_remove = FL_BPT_CORE_CR5_SP1;
}
iib_info = (bpt_iib_t *)(bpt->iib[0]);
if ((iib_info->tag != FL_BPT_IIB_TAG_VAL) || (iib_info->target_core != 0)) {
ssdk_printf(SSDK_ALERT, "sf core not in bpt, download sf first\r\n");
return NULL;
}
for (idx = 1; idx < FL_BPT_IIB_NUM; idx++) {
iib_info = (bpt_iib_t *)(bpt->iib[idx]);
/* find same core */
if (iib_info->tag == FL_BPT_IIB_TAG_VAL &&
((iib_info->target_core == core) ||
(iib_info->target_core == core_temp))) {
/* if the core is lockstep, remove the split core sp1 or sx1*/
if (core_temp != core) {
BptMaskIIB(bpt, core_remove);
}
iib_info->target_core = core_temp;
return iib_info;
}
}
for (idx = 1; idx < FL_BPT_IIB_NUM; idx++) {
iib_info = (bpt_iib_t *)(bpt->iib[idx]);
/* find the first invalid tag core */
if (iib_info->tag != FL_BPT_IIB_TAG_VAL) {
return iib_info;
}
}
return NULL;
}
/* sort iib */
static void BptSortIIB(bpt_v2_t *bpt)
{
bpt_iib_t *iib_info;
bpt_iib_t *iib_info_next;
uint8_t idx;
uint8_t idy;
uint8_t min_idy;
for (idx = 1; idx < FL_BPT_IIB_NUM; idx++) {
BptRemoveEmptyIIB(bpt, idx);
}
for (idx = 1; idx < FL_BPT_IIB_NUM - 1; idx++) {
iib_info = (bpt_iib_t *)(bpt->iib[idx]);
if (iib_info->tag != FL_BPT_IIB_TAG_VAL)
break;
min_idy = idx;
for (idy = idx + 1; idy < FL_BPT_IIB_NUM; idy++) {
iib_info_next = (bpt_iib_t *)(bpt->iib[idy]);
if (iib_info_next->tag != FL_BPT_IIB_TAG_VAL)
break;
if (iib_info_next->target_core < iib_info->target_core) {
min_idy = idy;
} else if (iib_info_next->target_core == iib_info->target_core) {
memset(iib_info_next, 0, FL_BPT_IIB_SIZE);
BptRemoveEmptyIIB(bpt, idy);
}
}
if (min_idy != idx)
BptExchangeIIB(bpt, idx, min_idy);
}
return;
}
/* dump bpt information */
static int32_t dump_bpt_info(bpt_v2_t *bpt)
{
int i = 0;
bpt_iib_t *iib;
ssdk_printf(SSDK_ALERT,
"================= FL_BPT 0 ================= \r\n");
ssdk_printf(SSDK_ALERT, "bpt->tag = 0x%08x\r\n", bpt->tag);
ssdk_printf(SSDK_ALERT, "bpt->size = 0x%x\r\n", bpt->size);
ssdk_printf(SSDK_ALERT, "bpt->sec_version = 0x%08x\r\n",
bpt->sec_ver);
ssdk_printf(SSDK_ALERT, "bpt->hash_alg = 0x%x\r\n",
bpt->digest_alg);
ssdk_printf(SSDK_ALERT, "bpt->crc32 = 0x%08x\r\n", bpt->crc);
ssdk_printf(SSDK_ALERT, "bpt->pac_serial_num = 0x%08x\r\n", bpt->sn);
ssdk_printf(SSDK_ALERT, "bpt->inver_pac_serial_num = 0x%08x\r\n",
bpt->sn_inversion);
for (i = 0; i < FL_BPT_IIB_NUM; i++) {
iib = (bpt_iib_t *)(bpt->iib[i]);
if ((iib->tag != FL_BPT_IIB_TAG_VAL)) {
ssdk_printf(SSDK_ALERT, "iib[%d] is none\r\n", i);
break;
}
ssdk_printf(SSDK_ALERT, "--------\r\n");
ssdk_printf(SSDK_ALERT, "iib[%d]->tag = 0x%x\r\n", i,
iib->tag);
ssdk_printf(SSDK_ALERT, "iib[%d]->size = 0x%x\r\n", i,
iib->size);
ssdk_printf(SSDK_ALERT, "iib[%d]->image_type = 0x%x\r\n", i,
iib->img_type);
ssdk_printf(SSDK_ALERT, "iib[%d]->target_core = 0x%x\r\n", i,
iib->target_core);
ssdk_printf(SSDK_ALERT, "iib[%d]->decryp_ctl = 0x%x\r\n", i,
iib->dec_ctrl);
ssdk_printf(SSDK_ALERT, "iib[%d]->dev_logic_page = 0x%08x\r\n", i,
iib->img_page);
ssdk_printf(SSDK_ALERT, "iib[%d]->image_size = 0x%08x\r\n", i,
iib->img_size);
ssdk_printf(SSDK_ALERT, "iib[%d]->load_base = 0x%08x\r\n", i,
iib->load_addr);
ssdk_printf(SSDK_ALERT, "iib[%d]->entry_point = 0x%08x\r\n", i,
iib->entry);
}
return 0;
}
/* update bpt */
int BptUpdate(flash_wrapper_t *flash_wrapper, void *img_base,
uint32_t link_base, uint32_t img_size, uint8_t core)
{
bpt_v2_t *bpt;
bpt_iib_t *iib_info;
uint32_t bpt_base0, bpt_base1, bpt_base2;
int crc;
// read sfs
if (sfs == NULL) {
ssdk_printf(SSDK_ALERT, "read sfs error\r\n");
return -1;
}
bpt_base0 = sfs->normal_img_base;
bpt_base1 = sfs->backup_img_base;
bpt_base2 = sfs->third_img_base;
ssdk_printf(SSDK_ALERT, "bpt0: 0x%x, bpt1: 0x%x, bpt2: 0x%x\r\n", bpt_base0,
bpt_base1, bpt_base2);
flash_wrapper_read(flash_wrapper, (flash_addr_t)bpt_base0, bpt_buffer,
FL_BPT_HEDAER_LEN);
bpt = (bpt_v2_t *)bpt_buffer;
if (core == 0) {
BptInit(bpt);
iib_info = (bpt_iib_t *)(bpt->iib[0]);
} else {
iib_info = BptSearchIIB(bpt, core);
}
if (iib_info == NULL) {
ssdk_printf(SSDK_ALERT, "Find IIB error\r\n");
return -1;
}
if (BptAddIIB(iib_info, (uint32_t)img_base, bpt_base0, link_base, img_size,
core) < 0) {
return -1;
}
BptSortIIB(bpt);
crc = sfs_crc32(0, (uint8_t *)bpt, FL_BPT_CRC_CHECKSUM_OFFSET);
memcpy(&bpt->crc, &crc, 4);
if (flash_wrapper_erase(flash_wrapper, (flash_addr_t)bpt_base0,
FL_BPT_HEDAER_LEN)) {
ssdk_printf(SSDK_ALERT, " erase 0x%08x, length 0x%08x error",
(uint32_t)bpt_base0, FL_BPT_HEDAER_LEN);
return -1;
}
if (flash_wrapper_write(flash_wrapper, (flash_addr_t)bpt_base0, bpt_buffer,
FL_BPT_HEDAER_LEN)) {
ssdk_printf(SSDK_ALERT, " write 0x%08x, length 0x%08x error",
(uint32_t)bpt_base0, FL_BPT_HEDAER_LEN);
return -1;
}
if (flash_wrapper_read(flash_wrapper, (flash_addr_t)bpt_base0, bpt_buffer,
FL_BPT_HEDAER_LEN)) {
ssdk_printf(SSDK_ALERT, " read 0x%08x, length 0x%08x error",
(uint32_t)bpt_base0, FL_BPT_HEDAER_LEN);
return -1;
}
bpt = (bpt_v2_t *)bpt_buffer;
dump_bpt_info(bpt);
return 0;
}
/* read sfs in flash */
int read_sfs(flash_wrapper_t *flash_wrapper)
{
uint32_t crc_val = 0;
uint32_t crc_orig = 0;
flash_wrapper_read(flash_wrapper, FL_SFS_BASE, sfs_buffer, FL_SFS_SIZE);
ssdk_printf(SSDK_ALERT, "sfs dump\r\n");
hexdump(sfs_buffer, FL_SFS_SIZE);
sfs = (sfs_t *)sfs_buffer;
crc_orig = sfs->crc32;
crc_val = sfs_crc32(0, sfs_buffer, FL_SFS_SIZE - 4);
if (crc_val != crc_orig) {
ssdk_printf(SSDK_ALERT, "sfs crc_orig:0x%0x crc_val:0x%0x!\r\n",
crc_orig, crc_val);
sfs = NULL;
return -1;
}
ssdk_printf(SSDK_ALERT, "sfs tag = 0x%08x\r\n", sfs->tag);
ssdk_printf(SSDK_ALERT, "sfs freq = 0x%02x\r\n", sfs->freq);
ssdk_printf(SSDK_ALERT, "sfs sw_reset_info = 0x%02x\r\n",
sfs->sw_reset_info);
ssdk_printf(SSDK_ALERT, "sfs normal_img_base = 0x%08x\r\n",
sfs->normal_img_base);
ssdk_printf(SSDK_ALERT, "sfs backup_img_base = 0x%08x\r\n",
sfs->backup_img_base);
ssdk_printf(SSDK_ALERT, "sfs third_img_base = 0x%08x\r\n",
sfs->third_img_base);
ssdk_printf(SSDK_ALERT, "sfs crc32 = 0x%08x\r\n", sfs->crc32);
return 0;
}

View File

@@ -0,0 +1,161 @@
//------------------------------------------------------------------------------
//
// Copyright (c) 2008-2015 IAR Systems
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision: 39363 $
//
//------------------------------------------------------------------------------
// Wrapper for target-specific flash loader code
#include <config.h>
#include "flash_loader.h"
#include "flash_loader_extra.h"
#ifndef MAX_ARGS
#define MAX_ARGS 7
#endif
// Maximum combined size of arguments, including a trailing null for each
// argument.
#ifndef MAX_ARG_SIZE
#define MAX_ARG_SIZE 64
#endif
// Functions in this file, called from the assembly wrapper
void Fl2FlashInitEntry(void);
void Fl2FlashWriteEntry(void);
void Fl2FlashEraseWriteEntry(void);
void Fl2FlashChecksumEntry(void);
void Fl2FlashSignoffEntry(void);
void FlashBreak(void);
#if CODE_ADDR_AS_VOID_PTR
extern uint32_t FlashChecksum(void const *begin, uint32_t count);
#else
extern uint32_t FlashChecksum(uint32_t begin, uint32_t count);
#endif
extern uint32_t FlashSignoff();
uint16_t Crc16_helper(uint8_t const *p, uint32_t len, uint16_t sum);
// Flashloader framework version
__root const uint16_t frameworkVersion = 200;
__root __no_init FlashParamsHolder theFlashParams;
__no_init int __argc;
__no_init char __argvbuf[MAX_ARG_SIZE];
#pragma required = __argvbuf
__no_init const char *__argv[MAX_ARGS];
#if CODE_ADDR_AS_VOID_PTR
#define CODE_REF void *
#else
#define CODE_REF uint32_t
#endif
void Fl2FlashInitEntry()
{
#if USE_ARGC_ARGV
theFlashParams.count =
FlashInit((CODE_REF)theFlashParams.base_ptr,
theFlashParams.block_size, // Image size
theFlashParams.offset_into_block, // link adr
theFlashParams.count, // flags
__argc, __argv);
#else
theFlashParams.count =
FlashInit((CODE_REF)theFlashParams.base_ptr,
theFlashParams.block_size, // Image size
theFlashParams.offset_into_block, // link adr
theFlashParams.count); // flags
#endif
}
// The normal flash write function
// ----------------------------------------------
void Fl2FlashWriteEntry()
{
theFlashParams.count = FlashWrite(
(CODE_REF)theFlashParams.base_ptr, theFlashParams.offset_into_block,
theFlashParams.count, theFlashParams.buffer);
}
// The erase-first flash write function
// -----------------------------------------
void Fl2FlashEraseWriteEntry()
{
uint32_t tmp = theFlashParams.block_size;
if (tmp == 0) {
FlashEraseData *p = (FlashEraseData *)theFlashParams.buffer;
for (uint32_t i = 0; i < theFlashParams.count; ++i) {
tmp = FlashErase((CODE_REF)p->start, p->length);
if (tmp != 0)
break;
++p;
}
} else {
tmp = FlashErase((CODE_REF)theFlashParams.base_ptr,
theFlashParams.block_size);
if (tmp == 0) {
tmp = FlashWrite((CODE_REF)theFlashParams.base_ptr,
theFlashParams.offset_into_block,
theFlashParams.count, theFlashParams.buffer);
}
}
theFlashParams.count = tmp;
}
void Fl2FlashChecksumEntry()
{
theFlashParams.count =
FlashChecksum((CODE_REF)theFlashParams.base_ptr, theFlashParams.count);
}
void Fl2FlashSignoffEntry() { theFlashParams.count = FlashSignoff(); }
uint16_t Crc16(uint8_t const *p, uint32_t len)
{
uint8_t zero[2] = {0, 0};
uint16_t sum = Crc16_helper(p, len, 0);
return Crc16_helper(zero, 2, sum);
}
uint16_t Crc16_helper(uint8_t const *p, uint32_t len, uint16_t sum)
{
while (len--) {
int i;
uint8_t byte = *p++;
for (i = 0; i < 8; ++i) {
uint32_t osum = sum;
sum <<= 1;
if (byte & 0x80)
sum |= 1;
if (osum & 0x8000)
sum ^= 0x1021;
byte <<= 1;
}
}
return sum;
}
#pragma optimize = no_inline
__root void FlashBreak()
{
while (1)
;
}

View File

@@ -0,0 +1,171 @@
;---------------------------------
;
; Copyright (c) 2008 IAR Systems
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; $Revision: 117855 $
;
; Functions accessed by the debugger to perform a flash download.
; All public symbols and the function FlashBreak() are looked up and called by the debugger.
;
;---------------------------------
#define _CORTEX_ ((__CORE__ == __ARM6M__) || (__CORE__ == __ARM6SM__) || (__CORE__ == __ARM7M__) \
|| (__CORE__ == __ARM7EM__) || (__CORE__ == __ARM8M__) || (__CORE__ == __ARM8M_BASELINE__) \
|| (__CORE__ == __ARM8M_MAINLINE__) || (__CORE__ == __ARM8EM_MAINLINE__))
PUBLIC FlashInitEntry
PUBLIC FlashWriteEntry
PUBLIC FlashEraseWriteEntry
PUBLIC FlashChecksumEntry
PUBLIC FlashSignoffEntry
PUBLIC FlashBufferStart
PUBLIC FlashBufferEnd
EXTERN FlashBreak
EXTERN Fl2FlashInitEntry
EXTERN Fl2FlashWriteEntry
EXTERN Fl2FlashEraseWriteEntry
EXTERN Fl2FlashChecksumEntry
EXTERN Fl2FlashSignoffEntry
SECTION CSTACK:DATA:NOROOT(3)
;---------------------------------
;
; FlashInitEntry()
; Debugger interface function
;
;---------------------------------
SECTION .text:CODE:ROOT(2)
#if !_CORTEX_
ARM
#else
THUMB
#endif
FlashInitEntry:
#if !_CORTEX_
;; Set up the normal stack pointer.
LDR sp, =SFE(CSTACK) ; End of CSTACK
#endif
BL Fl2FlashInitEntry
BL FlashBreak
;---------------------------------
;
; FlashWriteEntry()
; Debugger interface function
;
;---------------------------------
SECTION .text:CODE:ROOT(2)
#if !_CORTEX_
ARM
#else
THUMB
#endif
FlashWriteEntry:
BL Fl2FlashWriteEntry
BL FlashBreak
;---------------------------------
;
; FlashEraseWriteEntry
; Debugger interface function
;
;---------------------------------
SECTION .text:CODE:ROOT(2)
#if !_CORTEX_
ARM
#else
THUMB
#endif
FlashEraseWriteEntry:
BL Fl2FlashEraseWriteEntry
BL FlashBreak
;---------------------------------
;
; FlashChecksumEntry
; Debugger interface function
;
;---------------------------------
SECTION .text:CODE:NOROOT(2)
#if !_CORTEX_
ARM
#else
THUMB
#endif
FlashChecksumEntry:
BL Fl2FlashChecksumEntry
BL FlashBreak
;---------------------------------
;
; FlashSignoffEntry
; Debugger interface function
;
;---------------------------------
SECTION .text:CODE:NOROOT(2)
#if !_CORTEX_
ARM
#else
THUMB
#endif
FlashSignoffEntry:
BL Fl2FlashSignoffEntry
BL FlashBreak
;---------------------------------
;
; Flash buffer and Cortex stack
;
;---------------------------------
SECTION LOWEND:DATA(8)
DATA
FlashBufferStart:
SECTION HIGHSTART:DATA
DATA
FlashBufferEnd:
#if _CORTEX_
PUBLIC __vector_table
SECTION .intvec:CODE:ROOT(2)
DATA
__vector_table:
DC32 SFE(CSTACK)
DC32 FlashInitEntry
; The following dummy entries are needed for NXP devices that requires a checksum for the range __vector_table-__vector_table+0x1B
DC32 0
DC32 0
DC32 0
DC32 0
DC32 0
DC32 0
#endif
END

View File

@@ -0,0 +1,352 @@
/**
* @file flash_loader_implement.c
* @brief The flash loader framework API.
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#include <armv7-r/cache.h>
#include <debug.h>
#include <flash_loader.h>
#include <flash_loader_extra.h>
#include <flash_wrapper.h>
#include <param.h>
#include <regs_base.h>
#include <sd_boot_img/sd_boot_img.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef CONFIG_BPT_UPDATE
#include <bpt_v2.h>
#endif
/** external data **/
extern void __iar_data_init3(void);
extern void device_init(void);
static flash_wrapper_t *flash_wrapper;
static flash_addr_t written_size = 0;
static flash_addr_t erase_size = 0;
static struct spi_nor *flash_loader;
static uint32_t img_size;
static void *img_flash_base;
static uint32_t img_link_base;
static uint8_t core;
static uint8_t flash_init_flag = 0;
static bool img_flash_base_fg;
static bool use_flash_base_in_bpt = 0;
static bpt_v2_t *p_bpt = NULL;
static int32_t base_offset = 0;
static volatile int program_hyperflash_fuse_flag = 0;
#ifdef CONFIG_BPT_UPDATE
static bool bpt_update_fg;
#endif
#if CONFIG_CHECK_FLASH_LOAD
static uint8_t check_buffer[CONFIG_FLASHLOADER_BUFFER_SIZE];
#endif
/** public functions **/
#if USE_ARGC_ARGV
uint32_t FlashInit(void *base_of_flash, uint32_t image_size,
uint32_t link_address, uint32_t flags, int argc,
char const *argv[])
{
__iar_data_init3();
device_init();
board_init();
ssdk_printf(SSDK_NOTICE,
"\r\n------ CMD FlashInit ------\r\nADDR:0x%x "
"\r\nLINK_ADDR:0x%x \r\nSIZE:0x%x \r\nFLAGS:0x%x\r\n",
(uint32_t)base_of_flash, link_address, image_size, flags);
img_size = image_size;
img_link_base = link_address;
flash_init_flag = flags;
use_flash_base_in_bpt = 0;
uint32_t image_base = 0;
#ifdef CONFIG_BPT_UPDATE
if (argc > 1) {
core = atoi(argv[0]);
bpt_update_fg = atoi(argv[1]);
ssdk_printf(SSDK_NOTICE,
"ARGV0: core = %d \r\nARGV1: bpt_update_fg = 0x%x \r\n",
core, bpt_update_fg);
}
if (argc > 2) {
img_link_base = strtoul(argv[2], NULL, 16);
ssdk_printf(SSDK_NOTICE, "ARGV2: img_link_base = 0x%x \r\n",
img_link_base);
}
if (argc > 3) {
use_flash_base_in_bpt = atoi(argv[0]);
;
ssdk_printf(SSDK_NOTICE, "ARGV3: use_flash_base_in_bpt = 0x%x \r\n",
use_flash_base_in_bpt);
}
#endif
board_norflash_init();
flashloader_init(&flash_loader);
read_back_buffer_flag = 1;
flash_wrapper = flash_wrapper_init(flash_loader);
if (flash_wrapper == NULL) {
ssdk_printf(SSDK_ERR, "Flash wrapper init fail\r\n");
return RESULT_ERROR;
}
if (read_sfs(flash_wrapper)) {
ssdk_printf(SSDK_NOTICE, "read sfs error\r\n");
}
if (use_flash_base_in_bpt && sfs && sfs->normal_img_base) {
flash_wrapper_read(flash_wrapper, (flash_addr_t)sfs->normal_img_base,
bpt_buffer, FL_BPT_HEDAER_LEN);
p_bpt = (bpt_v2_t *)bpt_buffer;
if (p_bpt->crc ==
sfs_crc32(0, (uint8_t *)p_bpt, FL_BPT_CRC_CHECKSUM_OFFSET)) {
image_base = BptGetIIBImgbase(p_bpt, core);
if (image_base && !img_flash_base_fg) {
img_flash_base =
(void *)(image_base + XSPI1_BASE + sfs->normal_img_base);
img_flash_base_fg = true;
base_offset =
(uint32_t)img_flash_base - (uint32_t)base_of_flash;
ssdk_printf(SSDK_NOTICE,
"***base_of_flash change from 0x%x to "
"img_flash_base 0x%x***\r\n",
base_of_flash, img_flash_base);
} else
ssdk_printf(SSDK_NOTICE,
"can not get core %d image_base(0x%x), "
"img_flash_base_fg = %d\r\n",
core, image_base, img_flash_base_fg);
} else {
ssdk_printf(SSDK_ERR, "can not read bpt from flash addr 0x%x\r\n",
(flash_addr_t)sfs->normal_img_base);
return RESULT_ERROR;
}
}
if (use_flash_base_in_bpt && img_flash_base_fg) {
ssdk_printf(SSDK_NOTICE,
"FlashInit start, base:0x%x, link base:0x%x, size:0x%x, "
"flags:0x%x\r\n\r\n",
base_of_flash, img_link_base, img_size, flags);
} else {
ssdk_printf(SSDK_NOTICE,
"FlashInit start, base:0x%x, link base:0x%x, size:0x%x, "
"flags:0x%x\r\n\r\n",
(uint32_t)img_flash_base, img_link_base, img_size, flags);
}
ssdk_printf(SSDK_NOTICE, "FlashInit Success\r\n");
return RESULT_OK;
}
#else
uint32_t FlashInit(void *base_of_flash, uint32_t image_size,
uint32_t link_address, uint32_t flags)
{
return RESULT_ERROR;
}
#endif
uint32_t FlashWrite(void *block_start, uint32_t offset_into_block,
uint32_t count, char const *buffer)
{
int ret;
uint32_t block_start_addr = (uint32_t)block_start;
uint32_t block_end_addr;
int32_t written_size_by_addr;
ssdk_printf(SSDK_NOTICE,
"------ CMD FlashWrite ------\r\nADDR:0x%x \r\nOFFSET:0x%x "
"\r\nSIZE:0x%x\r\n",
(uint32_t)block_start, offset_into_block, count);
if (!use_flash_base_in_bpt)
block_start_addr = (uint32_t)block_start;
else if (img_flash_base_fg)
block_start_addr = (uint32_t)block_start + (uint32_t)base_offset;
block_end_addr = block_start_addr + offset_into_block + count;
if (!img_flash_base_fg) {
img_flash_base = (void *)block_start_addr;
img_flash_base_fg = true;
}
flash_addr_t rx_addr =
FLASH_ADDR_MASK((uint32_t)block_start_addr) + offset_into_block;
arch_invalidate_cache_range((addr_t)buffer, count);
ssdk_printf(
SSDK_NOTICE,
"FlashWrite addr:0x%x, offset:0x%x, count:0x%x, buffer:0x%x\r\n",
(uint32_t)block_start_addr, offset_into_block, count, buffer);
if((0 == rx_addr) && is_msfs_data(buffer)) {
if(0 != get_matched_sfs(&(flash_loader->info.flash_id[0]), (void **)&buffer, &count)) {
ssdk_printf(SSDK_ERR, "FlashWrite msfs error\r\n");
return RESULT_ERROR;
}
}
ret = flash_wrapper_write(flash_wrapper, rx_addr, (const uint8_t *)buffer,
(flash_size_t)count);
if (ret < 0) {
ssdk_printf(SSDK_ERR, "FlashWrite fail\r\n");
return RESULT_ERROR;
}
written_size += (flash_size_t)count;
#if CONFIG_CHECK_FLASH_LOAD
uint32_t check_count;
uint8_t *buffer_ptr = (uint8_t *)buffer;
while (count > 0) {
check_count = MIN(count, CONFIG_FLASHLOADER_BUFFER_SIZE);
flash_wrapper_read(flash_wrapper, rx_addr, (uint8_t *)check_buffer,
(flash_size_t)check_count);
for (uint32_t i = 0; i < check_count; i++) {
if (buffer_ptr[i] != check_buffer[i]) {
ssdk_printf(SSDK_NOTICE,
"Error@0x%x: write 0x%x, read 0x%x\r\n",
(unsigned int)(rx_addr + i), buffer_ptr[i],
check_buffer[i]);
}
}
rx_addr += check_count;
buffer_ptr += check_count;
count -= check_count;
}
#endif
written_size_by_addr = (block_end_addr - (uint32_t)img_flash_base);
ssdk_printf(SSDK_NOTICE,
"written_size = 0x%x, written_size_by_addr = 0x%x\r\n",
(uint32_t)written_size, (uint32_t)written_size_by_addr);
// if the whole image has been written, add the footer or update bpt
if (((written_size >= img_size) ||
(written_size_by_addr >= (int)img_size)) &&
ret == 0) {
ssdk_printf(
SSDK_DEBUG,
"Last copy done, total written size: 0x%x, image size: 0x%x\r\n",
(unsigned int)written_size, img_size);
#ifdef CONFIG_BPT_UPDATE
if (bpt_update_fg) {
ret = BptUpdate(flash_wrapper, img_flash_base, img_link_base,
img_size, core);
if (ret < 0) {
ssdk_printf(SSDK_ERR, "BptUpdate fail\r\n");
return RESULT_ERROR;
}
}
#endif
#if (CONFIG_HYPERBUS_MODE == 1) && (CONFIG_IAR_HYPERFLASH_FUSE == 1)
if (program_hyperflash_fuse_flag == 0) {
ret = program_hyperflash_fuse();
if (ret < 0) {
ssdk_printf(SSDK_ERR, "Fuse hyperflash fail\r\n");
return RESULT_ERROR;
}
program_hyperflash_fuse_flag = 1;
}
#endif
ssdk_printf(SSDK_NOTICE, "Flashload finished, ret:%d (0 is OK)\r\n",
ret);
}
if (ret < 0) {
ssdk_printf(SSDK_ERR, "FlashWrite fail\r\n");
return RESULT_ERROR;
}
return RESULT_OK;
}
uint32_t FlashErase(void *block_start, uint32_t block_size)
{
int ret;
uint32_t block_start_addr = (uint32_t)block_start;
ssdk_printf(SSDK_NOTICE,
"------ CMD FlashErase ------ \r\nADDR:0x%x \r\nSIZE:0x%x\r\n",
(uint32_t)block_start, block_size);
if (!use_flash_base_in_bpt)
block_start_addr = (uint32_t)block_start;
else if (img_flash_base_fg)
block_start_addr = (uint32_t)block_start + (uint32_t)base_offset;
if (!img_flash_base_fg) {
img_flash_base = (void *)block_start_addr;
img_flash_base_fg = true;
}
if (((erase_size + block_size) > img_size) && img_size) {
block_size = img_size - erase_size;
}
block_size = ALIGN(block_size, flash_wrapper->page_size);
erase_size += block_size;
if ((core == 255) && (flash_init_flag & FLAG_ERASE_ONLY) && (sfs != NULL)) {
if (sfs->normal_img_base) {
flash_wrapper_erase(flash_wrapper, sfs->normal_img_base,
flash_wrapper->sector_size);
ssdk_printf(SSDK_NOTICE, "FlashErase bpt addr:0x%x, count:0x%x\r\n",
(uint32_t)sfs->normal_img_base,
flash_wrapper->sector_size);
}
if (sfs->backup_img_base) {
flash_wrapper_erase(flash_wrapper, sfs->backup_img_base,
flash_wrapper->sector_size);
ssdk_printf(SSDK_NOTICE, "FlashErase bpt addr:0x%x, count:0x%x\r\n",
(uint32_t)sfs->backup_img_base,
flash_wrapper->sector_size);
}
if (sfs->third_img_base)
flash_wrapper_erase(flash_wrapper, sfs->third_img_base,
flash_wrapper->sector_size);
ssdk_printf(SSDK_NOTICE, "FlashErase bpt addr:0x%x, count:0x%x\r\n",
(uint32_t)sfs->third_img_base, flash_wrapper->sector_size);
}
ssdk_printf(SSDK_NOTICE, "FlashErase addr:0x%x, count:0x%x\r\n",
(uint32_t)block_start_addr, block_size);
ret = flash_wrapper_erase(flash_wrapper,
FLASH_ADDR_MASK((uint32_t)block_start_addr),
(flash_size_t)block_size);
if (ret < 0) {
ssdk_printf(SSDK_ERR, "FlashErase fail\r\n");
return RESULT_ERROR;
}
return RESULT_OK;
}

View File

@@ -0,0 +1,483 @@
/**
* @file flash_wrapper.c
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#include <armv7-r/arm.h>
#include <armv7-r/cache.h>
#include <armv7-r/pmu.h>
#include <armv7-r/register.h>
#include <clock_cfg.h>
#include <clock_ip.h>
#include <config.h>
#include <debug.h>
#include <flash_wrapper.h>
#include <param.h>
#include <part.h>
#include <pinmux_cfg.h>
#include <regs_base.h>
#include <reset_cfg.h>
#include <reset_ip.h>
#include <scr_cfg.h>
#include <scr_hw.h>
#include <sdrv_fuse.h>
#include <sdrv_pinctrl.h>
#include <sdrv_rstgen.h>
#include <sdrv_scr.h>
#include <sdrv_spi_nor.h>
#include <sdrv_xspi.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include <udelay/udelay.h>
#include "board.h"
#if CONFIG_HYPERBUS_MODE
#define FLASH_TYPE "hyperflash"
#else
#define FLASH_TYPE "norflash"
#endif
#define VERSION_NUMBER "V00.03.00"
#if (defined PART_ID) && (defined FLASH_TYPE) && (defined VERSION_NUMBER)
__USED char version_info[] =
"flashloader_version:" PART_ID " " FLASH_TYPE " " VERSION_NUMBER;
#endif
#define HYPER_FLASH_MODE_FUSE_INDEX (181)
#define HYPER_FLASH_MODE_FUSE_VAL (0x00100000)
static struct spi_nor_host spi_nor_host = {0};
static struct xspi_pdata xspi = {0};
static struct spi_nor flash = {0};
static struct flash_info *flash_info;
static flash_wrapper_t flash_wrapper_entry;
static uint8_t *g_rb_buffer = (uint8_t *)IRAM1_BASE;
volatile uint8_t read_back_buffer_flag = 0;
static struct xspi_config host_config = {
.id = 0,
.apb_base = APB_XSPI1PORTA_BASE,
.direct_base = XSPI1_XSPI1PORTA_BASE,
};
static struct spi_nor_config config = {
.id = 0,
.cs = 0,
.baudrate = 20000000,
.xfer_mode = SPI_NOR_XFER_POLLING_MODE,
.dev_mode = SPI_NOR_DEV_SINGLE_MODE,
.sw_rst = false, /* config soft reset spi norflash */
.async_mode = false,
#ifdef CONFIG_HYPERBUS_MODE
.hyperbus_mode = CONFIG_HYPERBUS_MODE,
#else
.hyperbus_mode = false,
#endif
};
static void print_flashloader_info(void)
{
static uint8_t print_info_flag = 0;
if (print_info_flag == 0) {
ssdk_printf(SSDK_CRIT, "flashloader version %s\r\n", VERSION_NUMBER);
uint32_t support_flash_num = 0;
#if (CONFIG_HYPERBUS_MODE == 1)
const struct flash_info *support_flash_info =
sdrv_spi_nor_get_flash_table(1, &support_flash_num);
#else
const struct flash_info *support_flash_info =
sdrv_spi_nor_get_flash_table(0, &support_flash_num);
#endif
if (support_flash_info != NULL) {
ssdk_printf(SSDK_CRIT, "support flash table:\r\n");
for (uint32_t i = 0; i < support_flash_num; i++) {
ssdk_printf(SSDK_CRIT, "%s", support_flash_info[i].name);
ssdk_printf(SSDK_CRIT, " ");
}
ssdk_printf(SSDK_CRIT, "\r\n");
} else {
ssdk_printf(SSDK_ERR, "get support flash table fail\r\n");
}
print_info_flag = 1;
}
}
void xspi_lockstep_enable(bool flag)
{
#if (CONFIG_E3 || CONFIG_D3)
scr_signal_t signal = SCR_SF_XSPI1_SRC_CFG_LOCKSTEP_MODE_N;
#else
scr_signal_t signal = SCR_SF_XSPI1_LOCKSTEP_DISABLE;
#endif
sdrv_rstgen_assert(&rstsig_xspi1b);
sdrv_rstgen_assert(&rstsig_xspi1a);
udelay(10u);
scr_set(&g_scr_ctrl, &signal, !flag);
udelay(10u);
sdrv_rstgen_deassert(&rstsig_xspi1a);
sdrv_rstgen_deassert(&rstsig_xspi1b);
}
void xspi_parallel_enable(bool flag)
{
scr_signal_t signal = SCR_SF_XSPI1_SRC_CFG_PARALLEL_MODE;
sdrv_rstgen_assert(&rstsig_xspi1b);
sdrv_rstgen_assert(&rstsig_xspi1a);
udelay(10u);
scr_set(&g_scr_ctrl, &signal, flag);
udelay(10u);
sdrv_rstgen_deassert(&rstsig_xspi1a);
sdrv_rstgen_deassert(&rstsig_xspi1b);
}
static void arch_disabled_alignment_fault_checking(void)
{
uint32_t sctlr;
sctlr = arm_read_sctlr();
sctlr &= ~(SCTLR_A);
arm_write_sctlr(sctlr);
}
void board_init(void)
{
/* disable i&d cache */
arch_disable_cache(UCACHE);
/* disable alignment_fault_checking */
arch_disabled_alignment_fault_checking();
/* Stop and clear the cycle counter, failure to do so may result in slower
* downloads */
pmu_stop_clear_cycle_cntr();
/* reset module */
board_reset_init();
/* initializes clock source */
sdrv_ckgen_init(&g_clock_config);
/* config spinor pinmux */
sdrv_pinctrl_init(NUM_OF_CONFIGURED_PINS, g_pin_init_config);
/* board debug console uart init */
board_debug_console_init();
/* print flashloader info */
print_flashloader_info();
}
void board_norflash_init(void)
{
bool locksetp_mode = false;
bool parallel_mode = false;
/* get xspi1a clk node */
sdrv_ckgen_node_t *clk = CLK_NODE(g_ckgen_ip_xspi1a);
/* config dev spi nor dev single mode */
switch (config.dev_mode) {
case SPI_NOR_DEV_LOCKSTEP_MODE:
locksetp_mode = true;
break;
case SPI_NOR_DEV_PARALLEL_MODE:
parallel_mode = true;
break;
default:
break;
}
/* close locksetp/parallel mode */
xspi_lockstep_enable(locksetp_mode);
xspi_parallel_enable(parallel_mode);
/* initializes xspi host */
host_config.ref_clk = sdrv_ckgen_get_rate(clk);
sdrv_xspi_host_init(&spi_nor_host, &xspi, &host_config);
spi_nor_host.clk = clk;
sdrv_ckgen_set_rate(clk, config.baudrate);
ssdk_printf(SSDK_DEBUG, "xspi clock rate is %u!\r\n",
sdrv_ckgen_get_rate(clk));
/* initializes spi nor device */
if (sdrv_spi_nor_init(&flash, &spi_nor_host, &config)) {
ssdk_printf(SSDK_ERR, "spinor init failed!\r\n");
return;
}
/* get flash info data information */
flash_info = sdrv_spi_nor_get_info(&flash);
ssdk_printf(SSDK_DEBUG,
"spinor flash size = 0x%llx, sector_size = 0x%x \r\n",
flash_info->size, flash_info->sector_size);
return;
}
void flashloader_init(struct spi_nor **flashloader) { *flashloader = &flash; }
flash_wrapper_t *flash_wrapper_init(struct spi_nor *device)
{
struct flash_info *flash_info;
flash_info = sdrv_spi_nor_get_info(device);
if (flash_info == NULL) {
ssdk_printf(SSDK_ERR, "Get flash info fail\r\n");
return NULL;
}
flash_wrapper_entry.device = device;
flash_wrapper_entry.sector_size = flash_info->sector_size;
flash_wrapper_entry.page_size = flash_info->page_size;
flash_wrapper_entry.flash_size = flash_info->size;
return &flash_wrapper_entry;
}
int flash_wrapper_read(flash_wrapper_t *flash_wrapper, flash_addr_t addr,
uint8_t *buf, flash_size_t size)
{
if (!IS_ALIGNED(size, 4)) {
ssdk_printf(SSDK_ERR, "Read address unaligned:0x%x\r\n", addr);
return FL_DL_READ_LENGTH_UNALIGNED_ERROR;
}
if (sdrv_spi_nor_read(flash_wrapper->device, addr, buf, size) == 0)
return 0;
else
return FL_DL_READ_ERROR;
}
int flash_wrapper_write(flash_wrapper_t *flash_wrapper, flash_addr_t addr,
const uint8_t *buf, flash_size_t size)
{
if (!IS_ALIGNED(addr, 2)) {
ssdk_printf(SSDK_ERR, "Write address unaligned:0x%x\r\n", addr);
return FL_DL_PROGRAM_ADDRESS_UNALIGNED_ERROR;
}
if (sdrv_spi_nor_write(flash_wrapper->device, addr, buf, size) == 0)
return 0;
else
return FL_DL_PROGRAM_ERROR;
}
int flash_wrapper_erase(flash_wrapper_t *flash_wrapper, flash_addr_t addr,
flash_size_t size)
{
uint32_t sector_size = flash_wrapper->sector_size;
uint32_t erase_addr;
uint32_t erase_len;
if (read_back_buffer_flag == 1) {
if (CONFIG_READ_BACK_BUFFER_SIZE < sector_size) {
ssdk_printf(SSDK_ERR, "Config read back buffer < sector size.\r\n");
return -1;
}
while (size) {
if (!IS_ALIGNED(addr, sector_size)) {
erase_addr = ROUNDDOWN(addr, sector_size);
erase_len = MIN(ROUNDUP(addr, sector_size) - addr, size);
} else {
erase_addr = addr;
erase_len =
size > sector_size ? (size - size % sector_size) : size;
}
if (erase_len < sector_size) {
if (sdrv_spi_nor_read(flash_wrapper->device, erase_addr,
g_rb_buffer, sector_size)) {
ssdk_printf(SSDK_ERR,
"sdrv_spi_nor_read error, addr = 0x%08x length "
"= 0x%08x \r\n",
erase_addr, erase_len);
return -1;
}
if (sdrv_spi_nor_erase(flash_wrapper->device, erase_addr,
sector_size)) {
ssdk_printf(SSDK_ERR,
"sdrv_spi_nor_erase error, addr = 0x%08x "
"length = 0x%08x \r\n",
erase_addr, sector_size);
return -1;
}
memset(g_rb_buffer + addr % sector_size, 0xff, erase_len);
if (sdrv_spi_nor_write(flash_wrapper->device, erase_addr,
g_rb_buffer, sector_size)) {
ssdk_printf(SSDK_ERR,
"sdrv_spi_nor_erase error, addr = 0x%08x "
"length = 0x%08x \r\n",
erase_addr, sector_size);
return -1;
}
} else {
if (sdrv_spi_nor_erase(flash_wrapper->device, erase_addr,
erase_len)) {
return -1;
}
}
addr += erase_len;
size -= erase_len;
}
return 0;
} else {
if (!IS_ALIGNED(addr, sector_size) || !IS_ALIGNED(size, sector_size)) {
ssdk_printf(SSDK_ERR, "Erase address unaligned:0x%x\r\n", addr);
return FL_DL_ERASE_ADDRESS_UNALIGNED_ERROR;
} else {
if (sdrv_spi_nor_erase(flash_wrapper->device, addr, size) == 0)
return 0;
else
return FL_DL_ERASE_ERROR;
}
}
}
int32_t fuse_write(uint32_t index, uint32_t value)
{
int32_t err = 0;
uint32_t read_value = 0;
if (0 != sdrv_fuse_sense(index, &read_value)) {
ssdk_printf(SSDK_ERR, "Failed to read fuse %d\n", index);
err = FL_FUSE_READ_ERROR;
goto end;
}
if ((read_value & value) != value) {
read_value |= value;
ssdk_printf(SSDK_ERR, "write fuse %d val 0x%08x\n", index, read_value);
if (0 != sdrv_fuse_program(index, read_value)) {
ssdk_printf(SSDK_ERR, "Failed to write fuse %d val 0x%08x\n", index,
read_value);
err = FL_FUSE_WRITE_ERROR;
goto end;
}
read_value = 0;
if (0 != sdrv_fuse_sense(index, &read_value)) {
ssdk_printf(SSDK_ERR, "Failed to read fuse %d\n", index);
err = FL_FUSE_READ_ERROR;
goto end;
}
ssdk_printf(SSDK_DEBUG, "read back fuse %d val 0x%08x\n", index,
read_value);
if ((read_value & value) != value) {
ssdk_printf(SSDK_ERR, "read back error, fuse %d val 0x%08x\n",
index, read_value);
err = FL_FUSE_READBACK_VERIFY_ERROR;
goto end;
}
} else {
ssdk_printf(SSDK_DEBUG, "no need to fuse\n");
}
end:
return err;
}
int32_t fuse_read(uint32_t index, uint32_t *value)
{
int32_t ret = 0;
ret = sdrv_fuse_sense(index, value);
if (ret != 0) {
ssdk_printf(SSDK_ERR, "Failed to read fuse %d\n", index);
return FL_FUSE_READ_ERROR;
}
return 0;
}
static uint32_t crc32_table[256] = {
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
0x2d02ef8dUL};
uint32_t flashloader_crc32(uint8_t *buf, int32_t len, uint32_t crc)
{
while (len--) {
crc = crc32_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
}
return crc;
}
#if (CONFIG_HYPERBUS_MODE == 1) && \
((CONFIG_IAR_HYPERFLASH_FUSE == 1) || \
(CONFIG_SDFACTORYTOOL_HYPERFLASH_FUSE == 1))
int32_t program_hyperflash_fuse(void)
{
return fuse_write(HYPER_FLASH_MODE_FUSE_INDEX, HYPER_FLASH_MODE_FUSE_VAL);
}
#endif

View File

@@ -0,0 +1,82 @@
#include <compiler.h>
#include <debug.h>
#include <flashloader.h>
#include <fuse_bin.h>
static FL_ERR_CODE_E flashloader_convert_return_value(FUSE_ERR_CODE_E ret)
{
FL_ERR_CODE_E err = ERR_NONE;
switch (ret) {
case ERR_NONE:
err = ERR_NONE;
break;
case ERR_UNKNOWN:
err = ERR_UNKNOWN;
break;
case ERR_FUSE_BIN_SIZE_CHECK_FAIL:
err = ERR_FL_FUSE_SIZE_CHECK_FAIL;
break;
case ERR_FUSE_BIN_LENGTH_CHECK_FAIL:
err = ERR_FL_FUSE_LENGTH_CHECK_FAIL;
break;
case ERR_FUSE_BIN_ACTION_TYPE_NOT_FIND:
err = ERR_FL_FUSE_ACTION_TYPE_NOT_FIND;
break;
case ERR_FUSE_BIN_CRC_CHECK_FAIL:
err = ERR_FL_FUSE_CRC_CHECK_FAIL;
break;
case ERR_FUSE_BIN_ENC_INIT_FAIL:
err = ERR_FL_FUSE_ENC_INIT_FAIL;
break;
case ERR_FUSE_BIN_ENC_FAIL:
err = ERR_FL_FUSE_ENC_FAIL;
break;
case ERR_FUSE_BIN_MALLOC_FAIL:
err = ERR_FL_FUSE_MALLOC_FAIL;
break;
case ERR_FUSE_BIN_GEN_DATA_FAIL:
err = ERR_FL_FUSE_GEN_DATA_FAIL;
break;
case ERR_FUSE_BIN_READ_FAIL:
err = ERR_FUSE_READ_FAIL;
break;
case ERR_FUSE_BIN_WRITE_FAIL:
err = ERR_FUSE_WRITE_FAIL;
break;
case ERR_FUSE_BIN_READBACK_VERIFY_FAIL:
err = ERR_FUSE_READBACK_VERIFY_FAIL;
break;
default:
break;
}
return err;
}
void tcm_enable_axi_slave_port(void)
{
uint32_t val;
__ASM volatile("mov %0, #0\n"
"mcr p15, 0, %0, c11, c0, 0\n"
: "+r"(val)
:
:);
}
__USED int32_t jflash_program_fuse_bin(uint32_t nNumBytes,
const uint8_t *pSrcBuff)
{
jflash_board_init_once();
tcm_enable_axi_slave_port();
FUSE_ERR_CODE_E ret;
FL_ERR_CODE_E err;
ret = fuse_bin((void *)pSrcBuff, nNumBytes);
err = flashloader_convert_return_value(ret);
if (err) {
ssdk_printf(SSDK_NOTICE, "fuse bin error\r\n");
report_error(err);
} else {
ssdk_printf(SSDK_NOTICE, "fuse bin success\r\n");
}
return err;
}

View File

@@ -0,0 +1,115 @@
/***********************************************************************
* SEGGER Microcontroller GmbH *
* The Embedded Experts *
************************************************************************
* *
* (c) SEGGER Microcontroller GmbH *
* All rights reserved *
* www.segger.com *
* *
************************************************************************
* *
************************************************************************
* *
* *
* Licensing terms *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* *
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "AS IS" AND ANY *
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR *
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE *
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, *
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY *
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH. *
* DAMAGE. *
* *
************************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : FlashOS.h
Purpose : Contains all defines and prototypes of public functions.
*/
#include <flash_wrapper.h>
#define U8 unsigned char
#define U16 unsigned short
#define U32 unsigned long
#define I8 signed char
#define I16 signed short
#define I32 signed long
struct SEGGER_OPEN_CMD_INFO; // Forward declaration of OFL lib private struct
extern flash_wrapper_t *jflash_wrapper;
typedef struct {
//
// Optional functions may be be NULL
//
void (*pfFeedWatchdog)(void); // Optional
int (*pfInit)(U32 Addr, U32 Freq, U32 Func); // Mandatory
int (*pfUnInit)(U32 Func); // Mandatory
int (*pfEraseSector)(U32 Addr); // Mandatory
int (*pfProgramPage)(U32 Addr, U32 NumBytes, U8 *pSrcBuff); // Mandatory
int (*pfBlankCheck)(U32 Addr, U32 NumBytes, U8 BlankData); // Optional
int (*pfEraseChip)(void); // Optional
U32 (*pfVerify)(U32 Addr, U32 NumBytes, U8 *pSrcBuff); // Optional
U32(*pfSEGGERCalcCRC)
(U32 CRC, U32 Addr, U32 NumBytes, U32 Polynom); // Optional
int (*pfSEGGERRead)(U32 Addr, U32 NumBytes, U8 *pDestBuff); // Optional
int (*pfSEGGERProgram)(U32 DestAddr, U32 NumBytes,
U8 *pSrcBuff); // Optional
int (*pfSEGGERErase)(U32 SectorAddr, U32 SectorIndex,
U32 NumSectors); // Optional
void (*pfSEGGERStart)(
volatile struct SEGGER_OPEN_CMD_INFO *pInfo); // Optional
} SEGGER_OFL_API;
//
// Keil / CMSIS API
//
int Init(U32 Addr, U32 Freq, U32 Func); // Mandatory
int UnInit(U32 Func); // Mandatory
int EraseSector(U32 Addr); // Mandatory
int ProgramPage(U32 Addr, U32 NumBytes, U8 *pSrcBuff); // Mandatory
int BlankCheck(U32 Addr, U32 NumBytes, U8 BlankData); // Optional
int EraseChip(void); // Optional
U32 Verify(U32 Addr, U32 NumBytes, U8 *pSrcBuff); // Optional
//
// SEGGER extensions
//
U32 SEGGER_OPEN_CalcCRC(U32 CRC, U32 Addr, U32 NumBytes,
U32 Polynom); // Optional
int SEGGER_OPEN_Read(U32 Addr, U32 NumBytes, U8 *pDestBuff); // Optional
int SEGGER_OPEN_Program(U32 DestAddr, U32 NumBytes, U8 *pSrcBuff); // Optional
int SEGGER_OPEN_Erase(U32 SectorAddr, U32 SectorIndex,
U32 NumSectors); // Optional
void SEGGER_OPEN_Start(volatile struct SEGGER_OPEN_CMD_INFO *pInfo); // Optional
//
// SEGGER OFL lib helper functions that may be called by specific algo part
//
U32 SEGGER_OFL_Lib_CalcCRC(const SEGGER_OFL_API *pAPI, U32 CRC, U32 Addr,
U32 NumBytes, U32 Polynom);
void SEGGER_OFL_Lib_StartTurbo(const SEGGER_OFL_API *pAPI,
volatile struct SEGGER_OPEN_CMD_INFO *pInfo);
/**************************** End of file ***************************/

View File

@@ -0,0 +1,137 @@
/**
* @file bpt_v2.h
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#ifndef FL_BPT_V2_H_
#define FL_BPT_V2_H_
#include <flash_wrapper.h>
#define FL_SFS_NORMAL_IMG_ADDR 0x70
#define FL_SFS_BAKEUP_IMG_ADDR 0x74
#define FL_SFS_THIRD_IMG_ADDR 0x78
#define FL_SFS_BASE 0x0
#define FL_SFS_SIZE 0x80
#define FL_SFS_TAG (0x53465301)
#define FL_SFS_TAG_OFFSET (0x0)
#define FL_SFS_INIT_ACT_OFFSET (0x4)
#define FL_SFS_XFER_CONFIG_OFFSET (0x40)
#define FL_SFS_IP_SETTINGS_OFFSET (0x50)
#define FL_SFS_FREQ_OFFSET (0x60)
#define FL_SFS_SW_RESET (0x67)
#define FL_SFS_TP_OFFSET (0x68)
#define FL_SFS_NIA_OFFSET (0x70)
#define FL_SFS_BIA_OFFSET (0x74)
#define FL_SFS_TIA_OFFSET (0x78)
#define FL_SFS_CRC32_OFFSET (0x7C)
#define FL_SFS_INIT_ACT_SIZE 0x3C
#define FL_SFS_XFER_CONFIG_SIZE 0x10
#define FL_SFS_IP_SETTINGS_SIZE 0x10
#define FL_SFS_TP_SIZE 0x8
#define FL_BPT_TAG_OFFSET 0x0
#define FL_BPT_IIB_OFFSET 0x20
#define FL_BPT_CRC_CHECKSUM_OFFSET 0xFEC
#define FL_BPT_IIB_TARGET_OFFSET 0x19
#define FL_BPT_IIB_IMG_SIZE_OFFSET 0x28
#define FL_BPT_IIB_LOAD_ADDR_OFFSET 0x2C
#define FL_BPT_IIB_SIZE 124
#define FL_BPT_IIB_NUM 8
#define FL_BPT_TAG_VAL 0x42505402
#define FL_BPT_IIB_TAG_VAL 0xEAE2
#define FL_BPT_HEDAER_LEN 0x1000
#define FL_BPT_PAGE_SIZE 512
#define FL_BPT_RCP_TAG 0xEAF0
#define FL_BPT_RCP_SIZE 0x414
#define FL_BPT_CORE_CR5_SF 0
#define FL_BPT_CORE_CR5_SP0 2
#define FL_BPT_CORE_CR5_SP1 3
#define FL_BPT_CORE_CR5_SX0 4
#define FL_BPT_CORE_CR5_SX1 5
#define FL_BPT_CORE_CR5_SX 6
#define FL_BPT_CORE_CR5_SP 7
#define FL_BPT_PAGE_SN 0x0100
typedef __packed struct bpt_rcp {
uint16_t tag;
uint16_t size;
uint8_t rot_id;
uint8_t key_type;
uint8_t reserved[10];
uint8_t key[1028];
} bpt_rcp_t;
typedef __packed struct bpt_v2 {
uint32_t tag;
uint16_t reserved1;
uint16_t size;
uint32_t sec_ver;
uint8_t digest_alg;
uint8_t reserved2[19];
uint8_t iib[FL_BPT_IIB_NUM][FL_BPT_IIB_SIZE];
bpt_rcp_t rcp;
uint8_t signature[512];
uint8_t key_wraps[512];
uint8_t reserved3[984];
uint32_t crc;
uint32_t sn;
uint32_t sn_inversion;
uint8_t reserved4[8];
} bpt_v2_t;
typedef __packed struct bpt_iib {
uint16_t tag;
uint16_t size;
uint32_t reserved1;
uint8_t dbg_ctrl[8];
uint8_t did[8];
uint8_t img_type;
uint8_t target_core;
uint8_t dec_ctrl;
uint8_t reserved2;
uint8_t iv[8];
uint32_t img_page;
uint32_t img_size;
uint32_t load_addr;
uint32_t reserved3;
uint32_t entry;
uint32_t reserved4;
uint8_t hash[64];
} bpt_iib_t;
typedef __packed struct {
uint32_t tag;
uint8_t init_act[FL_SFS_INIT_ACT_SIZE];
uint8_t xfer_config[FL_SFS_XFER_CONFIG_SIZE];
uint8_t ospi_settings[FL_SFS_IP_SETTINGS_SIZE];
uint8_t freq;
uint8_t reserved[6];
uint8_t sw_reset_info;
uint8_t training_pattern[FL_SFS_TP_SIZE];
uint32_t normal_img_base;
uint32_t backup_img_base;
uint32_t third_img_base;
uint32_t crc32;
} sfs_t;
extern sfs_t *sfs;
extern int read_sfs(flash_wrapper_t *flash_wrapper);
extern int BptUpdate(flash_wrapper_t *flash_wrapper, void *img_base,
uint32_t link_base, uint32_t img_size, uint8_t core);
extern uint32_t BptGetIIBImgbase(bpt_v2_t *bpt, uint8_t core);
extern uint8_t bpt_buffer[FL_BPT_HEDAER_LEN];
#endif

View File

@@ -0,0 +1,38 @@
//------------------------------------------------------------------------------
//
// Copyright (c) 2008-2015 IAR Systems
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision: 38952 $
//
//------------------------------------------------------------------------------
// when this macro is non-zero, your FlashInit function should accept
// extra 'argc' and 'argv' arguments as specified by the function
// prototype in 'flash_loader.h'
#define USE_ARGC_ARGV 1
// You can customize the memory reserved for passing arguments to FlashInit
// through argc and argv.
#if USE_ARGC_ARGV
// This specifies the maximum allowed number of arguments in argv
#define MAX_ARGS 5
// This specifies the maximum combined size of the arguments, including
// a trailing null for each argument
#define MAX_ARG_SIZE 64
#endif
// If this is true (non-zero), the parameter designating the code destination
// in flash operations will be a 'void *', otherwise it will be a uint32_t.
// Targets where void * is smaller than a code pointer should set this to 0.
#define CODE_ADDR_AS_VOID_PTR 1

View File

@@ -0,0 +1,93 @@
//------------------------------------------------------------------------------
//
// Copyright (c) 2008-2015 IAR Systems
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision: 54713 $
//
//------------------------------------------------------------------------------
#include <stdint.h>
#include "flash_config.h"
#define RESULT_OK 0
#define RESULT_ERROR 1
#define RESULT_OVERRIDE_DEVICE 2
#define RESULT_ERASE_DONE 3
#define RESULT_ERROR_WITH_MSG 4
#define RESULT_CUSTOM_FIRST 100
#define RESULT_CUSTOM_LAST 200
#define FLAG_ERASE_ONLY 0x1
#define FLAG_MASS_ERASE 0x2
#ifndef CODE_ADDR_AS_VOID_PTR
#define CODE_ADDR_AS_VOID_PTR 1
#endif
// These are functions you MUST implement -------------------------------
#if CODE_ADDR_AS_VOID_PTR
#if USE_ARGC_ARGV
uint32_t FlashInit(void *base_of_flash, uint32_t image_size,
uint32_t link_address, uint32_t flags, int argc,
char const *argv[]);
#else
uint32_t FlashInit(void *base_of_flash, uint32_t image_size,
uint32_t link_address, uint32_t flags);
#endif
uint32_t FlashWrite(void *block_start, uint32_t offset_into_block,
uint32_t count, char const *buffer);
uint32_t FlashErase(void *block_start, uint32_t block_size);
#else // !CODE_ADDR_AS_VOID_PTR
#if USE_ARGC_ARGV
uint32_t FlashInit(uint32_t base_of_flash, uint32_t image_size,
uint32_t link_address, uint32_t flags, int argc,
char const *argv[]);
#else
uint32_t FlashInit(uint32_t base_of_flash, uint32_t image_size,
uint32_t link_address, uint32_t flags);
#endif
uint32_t FlashWrite(uint32_t block_start, uint32_t offset_into_block,
uint32_t count, char const *buffer);
uint32_t FlashErase(uint32_t block_start, uint32_t block_size);
#endif // CODE_ADDR_AS_VOID_PTR
// These are functions you MAY implement --------------------------------
#if CODE_ADDR_AS_VOID_PTR
uint32_t FlashChecksum(void const *begin, uint32_t count);
#else
uint32_t FlashChecksum(uint32_t begin, uint32_t count);
#endif
uint32_t FlashSignoff(void);
#define OPTIONAL_CHECKSUM _Pragma("required=FlashChecksumEntry") __root
#define OPTIONAL_SIGNOFF _Pragma("required=FlashSignoffEntry") __root
void FlashChecksumEntry();
void FlashSignoffEntry();
// These are functions you may call -------------------------------------
// If your code cannot be accessed using data pointers, you will have to
// write your own Crc16 function.
uint16_t Crc16(uint8_t const *p, uint32_t len);

View File

@@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
//
// Copyright (c) 2008-2015 IAR Systems
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// $Revision: 54622 $
//
//------------------------------------------------------------------------------
#define OVERRIDE_LAYOUT 0x010000
#define OVERRIDE_BUFSIZE 0x020000
#define OVERRIDE_PAGESIZE 0x040000
#define ERROR_MESSAGE_BUFFER ((char *)theFlashParams.buffer)
#define LAYOUT_OVERRIDE_BUFFER ((char *)theFlashParams.buffer)
#define SET_BUFSIZE_OVERRIDE(new_size) theFlashParams.block_size = (new_size)
#define SET_PAGESIZE_OVERRIDE(new_size) \
theFlashParams.offset_into_block = (new_size)
// parameter passing structure
typedef struct {
uint32_t base_ptr;
uint32_t count;
uint32_t offset_into_block;
void *buffer;
uint32_t block_size;
} FlashParamsHolder;
typedef struct {
uint32_t start;
uint32_t length;
} FlashEraseData;
extern FlashParamsHolder theFlashParams;
extern char FlashBufferStart;
extern char FlashBufferEnd;

View File

@@ -0,0 +1,62 @@
/**
* @file flash_wrapper.h
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#ifndef _FLASH_WRAPPER_H_
#define _FLASH_WRAPPER_H_
#include <sdrv_spi_nor.h>
#define FLASH_ADDR_MASK(base) ((base)&0xFFFFFFF)
enum FL_STATUS {
FL_OK = 0,
FL_DL_INIT_ERROR = -1,
FL_DL_ERASE_ADDRESS_UNALIGNED_ERROR = -2,
FL_DL_ERASE_ERROR = -3,
FL_DL_PROGRAM_ADDRESS_UNALIGNED_ERROR = -4,
FL_DL_PROGRAM_ERROR = -5,
FL_DL_READ_LENGTH_UNALIGNED_ERROR = -6,
FL_DL_READ_ERROR = -7,
FL_DL_VERIFY_ERROR = -8,
FL_FUSE_CMD_ERROR = -9,
FL_FUSE_READ_ERROR = -10,
FL_FUSE_WRITE_ERROR = -11,
FL_FUSE_READBACK_VERIFY_ERROR = -12
};
typedef struct flash_wrapper {
struct spi_nor *device;
uint32_t sector_size;
uint32_t page_size;
flash_size_t flash_size;
} flash_wrapper_t;
extern volatile uint8_t read_back_buffer_flag;
void flashloader_init(struct spi_nor **flashloader);
uint32_t flashloader_crc32(uint8_t *buf, int32_t len, uint32_t crc);
flash_wrapper_t *flash_wrapper_init(struct spi_nor *device);
int flash_wrapper_read(flash_wrapper_t *flash_wrapper, flash_addr_t addr,
uint8_t *buf, flash_size_t size);
int flash_wrapper_write(flash_wrapper_t *flash_wrapper, flash_addr_t addr,
const uint8_t *buf, flash_size_t size);
int flash_wrapper_erase(flash_wrapper_t *flash_wrapper, flash_addr_t addr,
flash_size_t size);
int32_t fuse_write(uint32_t index, uint32_t value);
int32_t fuse_read(uint32_t index, uint32_t *value);
void board_init(void);
void board_norflash_init(void);
#if (CONFIG_HYPERBUS_MODE == 1) && \
((CONFIG_IAR_HYPERFLASH_FUSE == 1) || \
(CONFIG_SDFACTORYTOOL_HYPERFLASH_FUSE == 1))
int32_t program_hyperflash_fuse(void);
#endif
#endif

View File

@@ -0,0 +1,36 @@
typedef enum fl_err_code {
ERR_NONE = 0,
ERR_UNKNOWN,
ERR_FUSE_READ_FAIL,
ERR_FUSE_WRITE_CMD_VERIFY_FAIL,
ERR_FUSE_WRITE_FAIL,
ERR_FUSE_READBACK_VERIFY_FAIL,
ERR_INIT_FAIL,
ERR_BLANKCHECK_FAIL,
ERR_ERASE_ADDRESS_UNALIGNED,
ERR_ERASE_FAIL,
ERR_ERASECHIP_FAIL,
ERR_PROGRAM_ADDRESS_UNALIGNED,
ERR_PROGRAM_FAIL,
ERR_PROGRAM_HYPERFLASH_FUSE_FAIL,
ERR_READ_LENGTH_UNALIGNED,
ERR_READ_FAIL,
ERR_VERIFY_FAIL,
ERR_FL_FUSE_SIZE_CHECK_FAIL,
ERR_FL_FUSE_LENGTH_CHECK_FAIL,
ERR_FL_FUSE_ACTION_TYPE_NOT_FIND,
ERR_FL_FUSE_CRC_CHECK_FAIL,
ERR_FL_FUSE_ENC_INIT_FAIL,
ERR_FL_FUSE_ENC_FAIL,
ERR_FL_FUSE_MALLOC_FAIL,
ERR_FL_FUSE_GEN_DATA_FAIL,
ERR_FL_FLASH_MSFS_FAIL,
ERR_FL_MSFS_VERIFY_FAIL,
ERR_MAX,
} FL_ERR_CODE_E;
void report_error(enum fl_err_code err);
void jflash_board_init_once(void);

View File

@@ -0,0 +1,3 @@
#include <stdint.h>
int32_t jflash_program_fuse_bin(uint32_t nNumBytes, const uint8_t *pSrcBuff);

806
middleware/fuse/fuse_bin.c Normal file
View File

@@ -0,0 +1,806 @@
#include <armv7-r/cache.h>
#include <board.h>
#include <common.h>
#include <debug.h>
#include <fuse_bin.h>
#include <mailbox/sdrv_crypto_mailbox_common.h>
#include <mailbox/sdrv_crypto_mailbox_ske_basic.h>
#include <param.h>
#include <reg.h>
#include <regs_base.h>
#include <sd_boot_img/sd_boot_img.h>
#include <sdrv_crypto_init.h>
#include <sdrv_fuse.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef enum {
E_ACTION_FUSE_DIRECT_PROGRAM = 1,
E_ACTION_FUSE_GEN_AND_PROGRAM = 2,
E_ACTION_FUSE_OR_OPR_PROGRAM = 3,
E_ACTION_FUSE_LOCK = 4,
E_ACTION_FUSE_SSRK_PROGRAM = 9,
E_ACTION_FUSE_TSRK_PROGRAM = 10,
E_ACTION_FUSE_KCRC_PROGRAM = 11,
} ACTION_TYPE;
#define ACTION_SEQ_TAG (0xE101)
#define ACTION_ITEM_TAG (0xF001)
#define ACTION_SEQ_VER (0x0001)
#define ACTION_ITEM_VER (0x0001)
#define EFUSE_FSRK_INDEX (48)
#define EFUSE_EHSM_CFG_INDEX (192)
#define EFUSE_NVM_ALG_MASK (0xC00)
#define EFUSE_NVM_ALG_OFFSET (10)
#define EFUSE_NVM_ALG_AES_128_ECB (0x1)
#define EFUSE_FSRK_KEY_ID (1)
#define EFUSE_SSRK_KEY_ID (3)
#define IS_NEED_TRANS(ADDR) \
(((uint32_t)(ADDR) >= IRAM1_BASE - 0x20000 && \
(uint32_t)(ADDR) < IRAM1_BASE) \
? 1 \
: 0)
#define OFFSET_BASE(ADDR) ((uint32_t)(ADDR) + 0x20000 - IRAM1_BASE)
#define TRANS_ADDR(ADDR) \
((OFFSET_BASE(ADDR) > 0x10000) \
? (R5_SF_TCM_R5_SF_TCMB_BASE - 0x10000 + OFFSET_BASE(ADDR)) \
: (R5_SF_TCM_R5_SF_TCMB_BASE + 0x10000 + OFFSET_BASE(ADDR)))
#define TRANS_TO_SEIP_ACCESS_ADDR(ADDR) \
((IS_NEED_TRANS(ADDR)) ? TRANS_ADDR(ADDR) : (uint32_t)(ADDR))
#define REAL_FUSE_NOT_SHADOW_REGISTER 1
#define NVM_ALG_AES_128_ECB_TEST 0
typedef struct {
uint16_t nTag;
uint16_t nVer;
uint16_t nCount; // action count
uint8_t bReserved[18];
uint32_t nSize; // total fuse bin size
uint32_t nCrc32;
} ACTION_SEQ_T;
typedef struct {
uint16_t nTag;
uint16_t nVer;
uint16_t nActionType;
uint16_t nLen; // 1 action and 1 item
uint8_t bReserved[8];
} ACTION_ITEM_T;
typedef struct {
uint32_t nFuseType;
uint16_t nFuseIndex;
uint16_t nFuseLen; // fuse data len
uint8_t *lpData;
} FUSE_BURN_ITEM_T;
typedef struct {
uint32_t nFuseType;
uint16_t nFuseIndex;
uint16_t nFuseLen;
uint16_t nKeyIndex;
uint16_t nKeyLen;
} FUSE_KCRC_ITEM_T;
typedef struct {
uint16_t nBankID;
uint16_t nLockType;
uint32_t nDomainType;
} FUSE_LOCK_ITEM_T;
#define htonl(A) \
((((uint32_t)(A)&0xFF000000) >> 24) | (((uint32_t)(A)&0x00FF0000) >> 8) | \
(((uint32_t)(A)&0x0000FF00) << 8) | (((uint32_t)(A)&0x000000FF) << 24))
#define ONE_KEY_INDEX_LENGTH (4)
#define ONE_FUSE_INDEX_BYTE_LENGTH (4)
static FUSE_ERR_CODE_E fuse_program_with_readback_verify(uint32_t index,
uint32_t value)
{
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
uint32_t read_value = 0;
if (0 != sdrv_fuse_sense(index, &read_value)) {
ssdk_printf(SSDK_ERR, "Failed to read fuse %d\n", index);
err = ERR_FUSE_BIN_READ_FAIL;
goto end;
}
if ((read_value & value) != value) {
read_value |= value;
ssdk_printf(SSDK_ERR, "write fuse %d val 0x%08x\n", index, read_value);
if (0 != sdrv_fuse_program(index, read_value)) {
ssdk_printf(SSDK_ERR, "Failed to write fuse %d val 0x%08x\n", index,
read_value);
err = ERR_FUSE_BIN_WRITE_FAIL;
goto end;
}
read_value = 0;
if (0 != sdrv_fuse_sense(index, &read_value)) {
ssdk_printf(SSDK_ERR, "Failed to read fuse %d\n", index);
err = ERR_FUSE_BIN_READ_FAIL;
goto end;
}
ssdk_printf(SSDK_DEBUG, "read back fuse %d val 0x%08x\n", index,
read_value);
if ((read_value & value) != value) {
ssdk_printf(SSDK_ERR, "read back error, fuse %d val 0x%08x\n",
index, read_value);
err = ERR_FUSE_BIN_READBACK_VERIFY_FAIL;
goto end;
}
} else {
ssdk_printf(SSDK_DEBUG, "no need to fuse\n");
}
end:
return err;
}
static FUSE_ERR_CODE_E fuse_seip(uint32_t index, uint32_t length,
uint32_t *value)
{
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
for (uint32_t i = 0; i < length / ONE_KEY_INDEX_LENGTH; i++) {
index += ONE_KEY_INDEX_LENGTH * i;
value = (value + ONE_KEY_INDEX_LENGTH * i);
for (uint32_t j = 0; j < ONE_KEY_INDEX_LENGTH; j++) {
ssdk_printf(SSDK_CRIT, "write cipher index:0x%08x val:0x%08x\r\n",
index + j,
htonl(*(value + ONE_KEY_INDEX_LENGTH - 1 - j)));
#if REAL_FUSE_NOT_SHADOW_REGISTER
err = fuse_program_with_readback_verify(
index + j, htonl(*(value + ONE_KEY_INDEX_LENGTH - 1 - j)));
if (err != ERR_FUSE_BIN_NONE) {
return err;
}
#else
writel(htonl(*(value + ONE_KEY_INDEX_LENGTH - 1 - j)),
APB_EFUSEC_BASE + FUSE0_OFFSET +
ONE_FUSE_INDEX_BYTE_LENGTH * (index + j));
#endif
}
}
return ERR_FUSE_BIN_NONE;
}
uint32_t get_fuse_bin_size(ACTION_SEQ_T *p_action_seq)
{
uint32_t offset = 3 * sizeof(uint16_t) + 18 * sizeof(uint8_t);
return *(uint32_t *)((uint8_t *)p_action_seq + offset);
}
uint32_t get_fuse_bin_crc(ACTION_SEQ_T *p_action_seq)
{
uint32_t offset =
3 * sizeof(uint16_t) + 18 * sizeof(uint8_t) + sizeof(uint32_t);
return *(uint32_t *)((uint8_t *)p_action_seq + offset);
}
FUSE_ERR_CODE_E verify_fuse_bin_crc(void *data)
{
uint32_t crc_calc =
sfs_crc32(0, (uint8_t *)data, sizeof(ACTION_SEQ_T) - sizeof(uint32_t));
uint32_t size = get_fuse_bin_size((ACTION_SEQ_T *)data);
crc_calc = sfs_crc32(crc_calc, (uint8_t *)data + sizeof(ACTION_SEQ_T),
size - sizeof(ACTION_SEQ_T));
uint32_t crc_recieved = get_fuse_bin_crc((ACTION_SEQ_T *)data);
if (crc_calc == crc_recieved) {
return ERR_FUSE_BIN_NONE;
} else {
return ERR_FUSE_BIN_CRC_CHECK_FAIL;
}
}
uint16_t get_action_count(ACTION_SEQ_T *p_action_seq)
{
uint32_t offset = 2 * sizeof(uint16_t);
return *(uint16_t *)((uint8_t *)p_action_seq + offset);
}
uint16_t get_action_type(ACTION_ITEM_T *p_action_item)
{
uint32_t offset = 2 * sizeof(uint16_t);
return *(uint16_t *)((uint8_t *)p_action_item + offset);
}
uint16_t get_action_length(ACTION_ITEM_T *p_action_item)
{
uint32_t offset = 3 * sizeof(uint16_t);
return *(uint16_t *)((uint8_t *)p_action_item + offset);
}
uint32_t get_fuse_type(FUSE_BURN_ITEM_T *p_fuse_item)
{
return *(uint32_t *)(p_fuse_item);
}
uint16_t get_fuse_index(FUSE_BURN_ITEM_T *p_fuse_item)
{
uint32_t offset = sizeof(uint32_t);
return *(uint16_t *)((uint8_t *)p_fuse_item + offset);
}
uint16_t get_fuse_length(FUSE_BURN_ITEM_T *p_fuse_item)
{
uint32_t offset = sizeof(uint32_t) + sizeof(uint16_t);
return *(uint16_t *)((uint8_t *)p_fuse_item + offset);
}
uint32_t *get_fuse_value(FUSE_BURN_ITEM_T *p_fuse_item)
{
uint32_t offset = sizeof(uint32_t) + 2 * sizeof(uint16_t);
return (uint32_t *)((uint8_t *)p_fuse_item + offset);
}
FUSE_ERR_CODE_E fuse_gen_and_program(FUSE_BURN_ITEM_T *p_fuse_item)
{
ssdk_printf(SSDK_CRIT, "fuse_gen_and_program\r\n");
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
int32_t ret;
uint16_t index, length;
uint8_t *value, *value_align, *value_align_seip;
length = get_fuse_length(p_fuse_item);
if (length % ONE_FUSE_INDEX_BYTE_LENGTH != 0)
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
index = get_fuse_index(p_fuse_item);
value = (uint8_t *)malloc(CONFIG_ARCH_CACHE_LINE +
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
if (!value) {
err = ERR_FUSE_BIN_MALLOC_FAIL;
goto end;
}
value_align = (uint8_t *)ROUNDUP((uint32_t)value, CONFIG_ARCH_CACHE_LINE);
board_mpu_init();
if (sdrv_crypto_init()) {
err = ERR_FUSE_BIN_ENC_INIT_FAIL;
goto end;
}
arch_invalidate_cache_range((addr_t)value_align,
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
value_align_seip = (uint8_t *)TRANS_TO_SEIP_ACCESS_ADDR(value_align);
ssdk_printf(SSDK_CRIT, "value_align:0x%08x value_align_seip:0x%08x\r\n",
value_align, value_align_seip);
ret = cmd_trng_get_rand((uint8_t *)value_align_seip, length);
if (ret != 0) {
err = ERR_FUSE_BIN_GEN_DATA_FAIL;
goto end;
}
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
ssdk_printf(
SSDK_CRIT, "write index:0x%08x val:0x%08x\r\n", index + i,
*(uint32_t *)(value_align + ONE_FUSE_INDEX_BYTE_LENGTH * i));
#if REAL_FUSE_NOT_SHADOW_REGISTER
err = fuse_program_with_readback_verify(index + i, *(value_align + i));
if (err != ERR_FUSE_BIN_NONE) {
goto end;
}
#else
writel(*(value_align + i),
APB_EFUSEC_BASE + FUSE0_OFFSET +
ONE_FUSE_INDEX_BYTE_LENGTH * (index + i));
#endif
}
end:
if (value)
free(value);
return err;
}
FUSE_ERR_CODE_E fuse_oropr_program(FUSE_BURN_ITEM_T *p_fuse_item)
{
ssdk_printf(SSDK_CRIT, "fuse_oropr_program\r\n");
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
int32_t ret;
uint16_t index, length;
uint32_t *p_value;
length = get_fuse_length(p_fuse_item);
if (length % ONE_FUSE_INDEX_BYTE_LENGTH != 0)
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
index = get_fuse_index(p_fuse_item);
p_value = get_fuse_value(p_fuse_item);
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
uint32_t read_value = 0;
ret = sdrv_fuse_sense(index + i, &read_value);
if (ret != 0)
return ERR_FUSE_BIN_READ_FAIL;
ssdk_printf(SSDK_CRIT, "read index:0x%08x val:0x%08x\r\n", index + i,
read_value);
ssdk_printf(SSDK_CRIT, "write index:0x%08x val:0x%08x\r\n", index + i,
((*(p_value + i)) | read_value));
#if REAL_FUSE_NOT_SHADOW_REGISTER
err = fuse_program_with_readback_verify(
index + i, ((*(p_value + i)) | read_value));
if (err != ERR_FUSE_BIN_NONE) {
return err;
}
#else
writel(((*(p_value + i)) | read_value),
APB_EFUSEC_BASE + FUSE0_OFFSET +
ONE_FUSE_INDEX_BYTE_LENGTH * (index + i));
#endif
}
return ERR_FUSE_BIN_NONE;
}
FUSE_ERR_CODE_E fuse_direct_program(FUSE_BURN_ITEM_T *p_fuse_item)
{
ssdk_printf(SSDK_CRIT, "fuse_direct_program\r\n");
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
uint16_t index, length;
uint32_t *p_value;
length = get_fuse_length(p_fuse_item);
if (length % ONE_FUSE_INDEX_BYTE_LENGTH != 0)
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
index = get_fuse_index(p_fuse_item);
p_value = get_fuse_value(p_fuse_item);
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
ssdk_printf(SSDK_CRIT, "write index:0x%08x val:0x%08x\r\n", index + i,
*(p_value + i));
#if REAL_FUSE_NOT_SHADOW_REGISTER
err = fuse_program_with_readback_verify(index + i, *(p_value + i));
if (err != ERR_FUSE_BIN_NONE) {
return err;
}
#else
writel(*(p_value + i), APB_EFUSEC_BASE + FUSE0_OFFSET +
ONE_FUSE_INDEX_BYTE_LENGTH * (index + i));
#endif
}
return ERR_FUSE_BIN_NONE;
}
FUSE_ERR_CODE_E fuse_ssrk_program(FUSE_BURN_ITEM_T *p_fuse_item)
{
ssdk_printf(SSDK_CRIT, "fuse_ssrk_program\r\n");
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
int32_t ret;
uint16_t index, length;
uint32_t *p_value;
uint32_t ehsm_cfg;
uint8_t *ssrk_plain, *ssrk_cipher;
uint8_t *ssrk_plain_align, *ssrk_cipher_align;
uint8_t *ssrk_plain_align_seip, *ssrk_cipher_align_seip;
length = get_fuse_length(p_fuse_item);
if (length != 16 && length != 32)
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
index = get_fuse_index(p_fuse_item);
p_value = get_fuse_value(p_fuse_item);
ssrk_plain = (uint8_t *)malloc(CONFIG_ARCH_CACHE_LINE +
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
if (!ssrk_plain) {
err = ERR_FUSE_BIN_MALLOC_FAIL;
goto end;
}
ssrk_cipher = (uint8_t *)malloc(CONFIG_ARCH_CACHE_LINE +
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
if (!ssrk_cipher) {
err = ERR_FUSE_BIN_MALLOC_FAIL;
goto end;
}
ssrk_plain_align =
(uint8_t *)ROUNDUP((uint32_t)ssrk_plain, CONFIG_ARCH_CACHE_LINE);
ssrk_cipher_align =
(uint8_t *)ROUNDUP((uint32_t)ssrk_cipher, CONFIG_ARCH_CACHE_LINE);
memcpy((uint8_t *)ssrk_plain_align, (uint8_t *)p_value, length);
#if NVM_ALG_AES_128_ECB_TEST && !REAL_FUSE_NOT_SHADOW_REGISTER
writel(EFUSE_NVM_ALG_AES_128_ECB << EFUSE_NVM_ALG_OFFSET,
APB_EFUSEC_BASE + FUSE0_OFFSET +
ONE_FUSE_INDEX_BYTE_LENGTH * EFUSE_EHSM_CFG_INDEX);
#endif
// get ehsm cfg
#if REAL_FUSE_NOT_SHADOW_REGISTER
ret = sdrv_fuse_sense(EFUSE_EHSM_CFG_INDEX, &ehsm_cfg);
if (ret != 0) {
err = ERR_FUSE_BIN_READ_FAIL;
goto end;
}
#else
ehsm_cfg = readl(APB_EFUSEC_BASE + FUSE0_OFFSET +
ONE_FUSE_INDEX_BYTE_LENGTH * EFUSE_EHSM_CFG_INDEX);
#endif
// enc ssrk
board_mpu_init();
if (sdrv_crypto_init()) {
err = ERR_FUSE_BIN_ENC_INIT_FAIL;
goto end;
}
arch_clean_cache_range((addr_t)ssrk_plain_align,
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
arch_invalidate_cache_range((addr_t)ssrk_cipher_align,
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
ssrk_plain_align_seip =
(uint8_t *)TRANS_TO_SEIP_ACCESS_ADDR((uint32_t)ssrk_plain_align);
ssrk_cipher_align_seip =
(uint8_t *)TRANS_TO_SEIP_ACCESS_ADDR((uint32_t)ssrk_cipher_align);
ssdk_printf(SSDK_CRIT,
"ssrk_plain_align:0x%08x ssrk_plain_align_seip:0x%08x\r\n",
ssrk_plain_align, ssrk_plain_align_seip);
ssdk_printf(SSDK_CRIT,
"ssrk_cipher_align:0x%08x ssrk_cipher_align_seip:0x%08x\r\n",
ssrk_cipher_align, ssrk_cipher_align_seip);
if ((ehsm_cfg & EFUSE_NVM_ALG_MASK) >> EFUSE_NVM_ALG_OFFSET !=
EFUSE_NVM_ALG_AES_128_ECB) {
ssdk_printf(SSDK_CRIT, "ssrk enc by sm4 ecb\r\n");
ret =
cmd_ske_basic_enc(SKE_ALG_SM4_ECB, (uint8_t *)ssrk_plain_align_seip,
length, CMD_KEY_INTERNAL, NULL, EFUSE_FSRK_KEY_ID,
NULL, (uint8_t *)ssrk_cipher_align_seip, NULL);
} else {
ssdk_printf(SSDK_CRIT, "ssrk enc by aes 128 ecb\r\n");
ret = cmd_ske_basic_enc(
SKE_ALG_AES_128_ECB, (uint8_t *)ssrk_plain_align_seip, length,
CMD_KEY_INTERNAL, NULL, EFUSE_FSRK_KEY_ID, (uint8_t *)NULL,
(uint8_t *)ssrk_cipher_align_seip, NULL);
}
if (ret != 0) {
err = ERR_FUSE_BIN_ENC_FAIL;
goto end;
}
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
ssdk_printf(
SSDK_CRIT, "plain index:0x%08x val:0x%08x\r\n", index + i,
*(uint32_t *)(ssrk_plain_align + ONE_FUSE_INDEX_BYTE_LENGTH * i));
}
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
ssdk_printf(
SSDK_CRIT, "cipher index:0x%08x val:0x%08x\r\n", index + i,
*(uint32_t *)(ssrk_cipher_align + ONE_FUSE_INDEX_BYTE_LENGTH * i));
}
// program
err = fuse_seip(index, length / ONE_FUSE_INDEX_BYTE_LENGTH,
(uint32_t *)ssrk_cipher_align);
end:
if (ssrk_plain)
free(ssrk_plain);
if (ssrk_cipher)
free(ssrk_cipher);
return err;
}
FUSE_ERR_CODE_E fuse_tsrk_program(FUSE_BURN_ITEM_T *p_fuse_item)
{
ssdk_printf(SSDK_CRIT, "fuse_tsrk_program\r\n");
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
int32_t ret;
uint16_t index, length;
uint32_t *p_value;
uint32_t ehsm_cfg;
uint8_t *tsrk_plain, *tsrk_cipher;
uint8_t *tsrk_plain_align, *tsrk_cipher_align;
uint8_t *tsrk_plain_align_seip, *tsrk_cipher_align_seip;
length = get_fuse_length(p_fuse_item);
if (length != 16 && length != 32)
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
index = get_fuse_index(p_fuse_item);
p_value = get_fuse_value(p_fuse_item);
tsrk_plain = (uint8_t *)malloc(CONFIG_ARCH_CACHE_LINE +
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
if (!tsrk_plain) {
err = ERR_FUSE_BIN_MALLOC_FAIL;
goto end;
}
tsrk_cipher = (uint8_t *)malloc(CONFIG_ARCH_CACHE_LINE +
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
if (!tsrk_cipher) {
err = ERR_FUSE_BIN_MALLOC_FAIL;
goto end;
}
tsrk_plain_align =
(uint8_t *)ROUNDUP((uint32_t)tsrk_plain, CONFIG_ARCH_CACHE_LINE);
tsrk_cipher_align =
(uint8_t *)ROUNDUP((uint32_t)tsrk_cipher, CONFIG_ARCH_CACHE_LINE);
memcpy((uint8_t *)tsrk_plain_align, (uint8_t *)p_value, length);
// get enc type
#if REAL_FUSE_NOT_SHADOW_REGISTER
ret = sdrv_fuse_sense(EFUSE_EHSM_CFG_INDEX, &ehsm_cfg);
if (ret != 0) {
err = ERR_FUSE_BIN_READ_FAIL;
goto end;
}
#else
ehsm_cfg = readl(APB_EFUSEC_BASE + FUSE0_OFFSET +
ONE_FUSE_INDEX_BYTE_LENGTH * EFUSE_EHSM_CFG_INDEX);
#endif
// enc tsrk
board_mpu_init();
if (sdrv_crypto_init()) {
err = ERR_FUSE_BIN_ENC_INIT_FAIL;
goto end;
}
arch_clean_cache_range((addr_t)tsrk_plain_align,
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
arch_invalidate_cache_range((addr_t)tsrk_cipher_align,
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
tsrk_plain_align_seip =
(uint8_t *)TRANS_TO_SEIP_ACCESS_ADDR((uint32_t)tsrk_plain_align);
tsrk_cipher_align_seip =
(uint8_t *)TRANS_TO_SEIP_ACCESS_ADDR((uint32_t)tsrk_cipher_align);
ssdk_printf(SSDK_CRIT,
"tsrk_plain_align:0x%08x tsrk_plain_align_seip:0x%08x\r\n",
tsrk_plain_align, tsrk_plain_align_seip);
ssdk_printf(SSDK_CRIT,
"tsrk_cipher_align:0x%08x tsrk_cipher_align_seip:0x%08x\r\n",
tsrk_cipher_align, tsrk_cipher_align_seip);
if ((ehsm_cfg & EFUSE_NVM_ALG_MASK) >> EFUSE_NVM_ALG_OFFSET !=
EFUSE_NVM_ALG_AES_128_ECB) {
ssdk_printf(SSDK_CRIT, "tsrk enc by sm4 ecb\r\n");
ret =
cmd_ske_basic_enc(SKE_ALG_SM4_ECB, (uint8_t *)tsrk_plain_align_seip,
length, CMD_KEY_INTERNAL, NULL, EFUSE_SSRK_KEY_ID,
NULL, (uint8_t *)tsrk_cipher_align_seip, NULL);
} else {
ssdk_printf(SSDK_CRIT, "tsrk enc by aes 128 ecb\r\n");
ret = cmd_ske_basic_enc(
SKE_ALG_AES_128_ECB, (uint8_t *)tsrk_plain_align_seip, length,
CMD_KEY_INTERNAL, NULL, EFUSE_SSRK_KEY_ID, (uint8_t *)NULL,
(uint8_t *)tsrk_cipher_align_seip, NULL);
}
if (ret != 0) {
err = ERR_FUSE_BIN_ENC_FAIL;
goto end;
}
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
ssdk_printf(
SSDK_CRIT, "plain index:0x%08x val:0x%08x\r\n", index + i,
*(uint32_t *)(tsrk_plain_align + ONE_FUSE_INDEX_BYTE_LENGTH * i));
}
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
ssdk_printf(
SSDK_CRIT, "cipher index:0x%08x val:0x%08x\r\n", index + i,
*(uint32_t *)(tsrk_cipher_align + ONE_FUSE_INDEX_BYTE_LENGTH * i));
}
// program
err = fuse_seip(index, length / ONE_FUSE_INDEX_BYTE_LENGTH,
(uint32_t *)tsrk_cipher_align);
end:
if (tsrk_plain)
free(tsrk_plain);
if (tsrk_cipher)
free(tsrk_cipher);
return err;
}
uint32_t get_crc_fuse_type(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
{
return *(uint32_t *)(p_crc_fuse_item);
}
uint16_t get_crc_fuse_index(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
{
uint32_t offset = sizeof(uint32_t);
return *(uint16_t *)((uint8_t *)p_crc_fuse_item + offset);
}
uint16_t get_crc_fuse_length(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
{
uint32_t offset = sizeof(uint32_t) + sizeof(uint16_t);
return *(uint16_t *)((uint8_t *)p_crc_fuse_item + offset);
}
uint16_t get_crc_key_index(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
{
uint32_t offset = sizeof(uint32_t) + 2 * sizeof(uint16_t);
return *(uint16_t *)((uint8_t *)p_crc_fuse_item + offset);
}
uint16_t get_crc_key_length(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
{
uint32_t offset = sizeof(uint32_t) + 3 * sizeof(uint16_t);
return *(uint16_t *)((uint8_t *)p_crc_fuse_item + offset);
}
static uint32_t reverse(uint32_t x)
{
uint32_t result = 0;
for (int32_t i = 0; i < 32; i++) {
result <<= 1;
result |= (x & 1);
x >>= 1;
}
return result;
}
FUSE_ERR_CODE_E fuse_kcrc_program(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
{
ssdk_printf(SSDK_CRIT, "fuse_kcrc_program\r\n");
uint16_t key_index, key_length, fuse_index, fuse_length;
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
int32_t ret;
uint32_t key_value;
uint32_t crc_calc = 0;
key_length = get_crc_key_length(p_crc_fuse_item);
fuse_length = get_crc_fuse_length(p_crc_fuse_item);
if ((key_length != 16 && key_length != 32) || fuse_length != 4) {
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
}
key_index = get_crc_key_index(p_crc_fuse_item);
for (uint32_t i = 0; i < key_length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
// read
#if REAL_FUSE_NOT_SHADOW_REGISTER
ret = sdrv_fuse_sense(key_index + i, &key_value);
if (ret != 0) {
return ERR_FUSE_BIN_READ_FAIL;
}
#else
key_value = readl(APB_EFUSEC_BASE + FUSE0_OFFSET +
ONE_FUSE_INDEX_BYTE_LENGTH * (key_index + i));
#endif
ssdk_printf(SSDK_CRIT, "read index:0x%08x val:0x%08x\r\n",
key_index + i, key_value);
// calc crc
crc_calc = sfs_crc32(crc_calc, (uint8_t *)&key_value,
ONE_FUSE_INDEX_BYTE_LENGTH);
}
// ssrk tsrk need add 16 bytes 0 to calc;
if (key_length == 16) {
for (uint32_t i = 0; i < 16 / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
key_value = 0;
crc_calc = sfs_crc32(crc_calc, (uint8_t *)&key_value,
ONE_FUSE_INDEX_BYTE_LENGTH);
}
}
crc_calc = reverse(crc_calc);
// program
fuse_index = get_crc_fuse_index(p_crc_fuse_item);
ssdk_printf(SSDK_CRIT, "write index:0x%08x val:0x%08x\r\n", fuse_index,
crc_calc);
#if REAL_FUSE_NOT_SHADOW_REGISTER
err = fuse_program_with_readback_verify(fuse_index, crc_calc);
if (err != ERR_FUSE_BIN_NONE) {
return err;
}
#else
writel(crc_calc, APB_EFUSEC_BASE + FUSE0_OFFSET +
ONE_FUSE_INDEX_BYTE_LENGTH * fuse_index);
#endif
return ERR_FUSE_BIN_NONE;
}
uint16_t get_lock_bank_id(FUSE_LOCK_ITEM_T *p_lock_item)
{
return *(uint16_t *)(p_lock_item);
}
uint16_t get_lock_type(FUSE_LOCK_ITEM_T *p_lock_item)
{
uint32_t offset = sizeof(uint16_t);
return *(uint16_t *)((uint8_t *)p_lock_item + offset);
}
FUSE_ERR_CODE_E fuse_lock_program(FUSE_LOCK_ITEM_T *p_lock_item)
{
ssdk_printf(SSDK_CRIT, "fuse_lock_program\r\n");
int32_t ret;
uint16_t bank_id = get_lock_bank_id(p_lock_item);
uint16_t lock_type = get_lock_type(p_lock_item);
ssdk_printf(SSDK_CRIT, "write bank_id:0x%08x lock_type:0x%08x\r\n",
bank_id, lock_type);
#if REAL_FUSE_NOT_SHADOW_REGISTER
ret = sdrv_fuse_lock_bank((fuse_lock_bank_e)bank_id,
(fuse_lock_bits_e)lock_type);
if (ret != 0) {
return ERR_FUSE_BIN_WRITE_FAIL;
}
#endif
return ERR_FUSE_BIN_NONE;
}
FUSE_ERR_CODE_E fuse_bin(void *data, uint32_t sz)
{
uint16_t action_count;
uint16_t action_type, action_length;
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
// verify fuse bin size
uint32_t bin_size = get_fuse_bin_size((ACTION_SEQ_T *)data);
if (bin_size != sz) {
ssdk_printf(SSDK_CRIT,
"bin size check fail, size in bin:0x%x, recieved "
"size:0x%x\r\n",
bin_size, sz);
return ERR_FUSE_BIN_SIZE_CHECK_FAIL;
}
// verify fuse bin crc
err = verify_fuse_bin_crc((ACTION_SEQ_T *)data);
if (err != ERR_FUSE_BIN_NONE) {
return err;
}
// get action count
action_count = get_action_count((ACTION_SEQ_T *)data);
ACTION_ITEM_T *p_action_item =
(ACTION_ITEM_T *)((uint8_t *)data + sizeof(ACTION_SEQ_T));
for (uint16_t i = 0; i < action_count; i++) {
// get action type
action_type = get_action_type(p_action_item);
void *p_item = (uint8_t *)p_action_item + sizeof(ACTION_ITEM_T);
switch (action_type) {
case E_ACTION_FUSE_DIRECT_PROGRAM:
err = fuse_direct_program((FUSE_BURN_ITEM_T *)p_item);
break;
case E_ACTION_FUSE_GEN_AND_PROGRAM:
err = fuse_gen_and_program((FUSE_BURN_ITEM_T *)p_item);
break;
case E_ACTION_FUSE_OR_OPR_PROGRAM:
err = fuse_oropr_program((FUSE_BURN_ITEM_T *)p_item);
break;
case E_ACTION_FUSE_LOCK:
err = fuse_lock_program((FUSE_LOCK_ITEM_T *)p_item);
break;
case E_ACTION_FUSE_SSRK_PROGRAM:
err = fuse_ssrk_program((FUSE_BURN_ITEM_T *)p_item);
break;
case E_ACTION_FUSE_TSRK_PROGRAM:
err = fuse_tsrk_program((FUSE_BURN_ITEM_T *)p_item);
break;
case E_ACTION_FUSE_KCRC_PROGRAM:
err = fuse_kcrc_program((FUSE_KCRC_ITEM_T *)p_item);
break;
default:
err = ERR_FUSE_BIN_ACTION_TYPE_NOT_FIND;
break;
}
if (err != ERR_FUSE_BIN_NONE) {
break;
}
// get next action
action_length = get_action_length(p_action_item);
p_action_item =
(ACTION_ITEM_T *)((uint8_t *)p_action_item + action_length);
}
return err;
}

View File

@@ -0,0 +1,20 @@
#include <stdint.h>
typedef enum fuse_err_code {
ERR_FUSE_BIN_NONE = 0,
ERR_FUSE_BIN_UNKNOWN,
ERR_FUSE_BIN_SIZE_CHECK_FAIL,
ERR_FUSE_BIN_LENGTH_CHECK_FAIL,
ERR_FUSE_BIN_ACTION_TYPE_NOT_FIND,
ERR_FUSE_BIN_CRC_CHECK_FAIL,
ERR_FUSE_BIN_ENC_INIT_FAIL,
ERR_FUSE_BIN_ENC_FAIL,
ERR_FUSE_BIN_MALLOC_FAIL,
ERR_FUSE_BIN_GEN_DATA_FAIL,
ERR_FUSE_BIN_READ_FAIL,
ERR_FUSE_BIN_WRITE_FAIL,
ERR_FUSE_BIN_READBACK_VERIFY_FAIL,
ERR_FUSE_BIN_MAX,
} FUSE_ERR_CODE_E;
FUSE_ERR_CODE_E fuse_bin(void *data, uint32_t sz);

View File

@@ -0,0 +1,110 @@
/*
* hal_comm_define.h
*@brief hal common header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/06 create this file
*/
#ifndef __HAL_COMM_DEFINE_H__
#define __HAL_COMM_DEFINE_H__
#include <stdint.h>
#define CONFIG_ASW 1
#define HAL_GUI_MAX_WIDTH 8192
#define HAL_GUI_MAX_HEIGHT 8192
typedef void* HAL_HANDLE;
/* Whether or not parameter checking is performed */
#define HAL_DEBUG_MODE 1
/* module id */
typedef enum {
HAL_MOD_COMMON = 0, /* common module */
HAL_MOD_SYS, /* system module */
HAL_MOD_G2DLITE, /* g2dlite module */
HAL_MOD_ASW, /* asw module */
HAL_MOD_DISP, /* disp module */
HAL_MOD_SW, /* Software implementation module */
HAL_MOD_GPU, /* gpu module */
HAL_MOD_BUTT
} HAL_ModId;
/* fmt */
typedef enum {
HAL_FMT_A8 = 0, /* alpha 8bit */
HAL_FMT_RGB565, /* rgb565 */
HAL_FMT_ARGB4444, /* argb4444 */
HAL_FMT_ARGB1555, /* argb1555 */
HAL_FMT_RGB888, /* rgb888 */
HAL_FMT_ARGB8888, /* argb8888 */
HAL_FMT_BUTT
} HAL_Format;
typedef struct {
uint32_t x; /* The abscissa of a rectangle */
uint32_t y; /* The ordinate of the rectangle */
uint32_t w; /* the width of the rectangle */
uint32_t h; /* the height of the rectangle */
} HAL_Rect;
typedef struct {
uint32_t x; /* The abscissa of a rectangle */
uint32_t y; /* The ordinate of the rectangle */
} HAL_Point;
typedef struct {
uint32_t color; /* full color */
HAL_Format fmt; /* buf fmt */
uint8_t *buf; /* buf addr */
uint32_t stride; /* buf stride */
HAL_Rect dstRect; /* full rect */
} HAL_FillRectInfo;
/* Triangles are cut from rectangles */
typedef enum {
HAL_TRIANGLE_TOP_LEFT = 0, /* shows the triangle in the top left corner */
HAL_TRIANGLE_BOTTOM_LEFT, /* shows the triangle in the bottom left corner */
HAL_TRIANGLE_TOP_RIGHT, /* shows the triangle in the top right corner */
HAL_TRIANGLE_BOTTOM_RIGHT, /* shows the triangle in the bottom right corner */
HAL_TRIANGLE_BUTT
} HAL_TRIANLE_Type;
typedef struct {
HAL_TRIANLE_Type type; /* The area type of a triangle */
HAL_Format fmt; /* The format type of a triangle */
uint32_t color; /* The color of a triangle */
HAL_Rect dstRect; /* The color of a triangle */
uint8_t *buf; /* The buf of a triangle */
uint32_t stride; /* The stride of buf */
} HAL_FillRatriaInfo;
typedef struct {
HAL_Rect srcRect; /* the rect for rotate */
uint8_t *srcBuf; /* the rect buf for rotation */
HAL_Format srcFmt; /* the rect format for rotation */
uint32_t srcStride; /* the rect buf stride */
uint8_t *dstBuf; /* output rect buf */
HAL_Format dstFmt; /* output rect format*/
uint32_t dstWidth; /* output rect widtht*/
uint32_t dstHeight; /* output rect height*/
uint32_t dstStride; /* output rect buf strde*/
double angle; /* rotate angle */
/* ARGB888, A:bit[31:24], R:bit[23:16], G:bit[15:8], B:bit[7:0]
Pixels outside the rotated region fill the background color */
uint32_t bgColor;
} HAL_RotateInfo;
#endif //__HAL_COMM_DEFINE_H__

View File

@@ -0,0 +1,41 @@
/*
* hal_comm_inner.c
*@brief hal common inner file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/19 create this file
*/
#include <string.h>
#include "FreeRTOS.h"
#include <dispss/disp.h>
#include <dispss/disp_data_type.h>
#include "hal_comm_inner.h"
#include "hal_disp.h"
extern struct dc_dev g_dc_dev;
int COMM_getFmtBpp(HAL_Format fmt)
{
switch (fmt) {
case HAL_FMT_A8:
return 1;
case HAL_FMT_RGB565:
case HAL_FMT_ARGB1555:
case HAL_FMT_ARGB4444:
return 2;
case HAL_FMT_RGB888:
return 3;
case HAL_FMT_ARGB8888:
return 4;
default:
HAL_LOG_E(HAL_MOD_COMMON, "can't support this fmt:%d!\n", fmt);
return -1;
}
}

View File

@@ -0,0 +1,114 @@
/*
* hal_comm_inner.h
*@brief hal common inner header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/06 create this file
*/
#ifndef __HAL_COMM_INNER_H__
#define __HAL_COMM_INNER_H__
#include "stdio.h"
#include "hal_comm_define.h"
#include "hal_errno.h"
#include <debug.h>
#define MOD_NAME_LEN 16
static char g_modName[HAL_MOD_BUTT + 1][MOD_NAME_LEN] = {
"common",
"sys",
"g2dlite",
"asw",
"disp",
"sw",
"gpu",
"unkown"
};
#if HAL_DEBUG_LEVEL <= HAL_LOG_INFO
#define HAL_LOG_I(mod_, info, ...) \
printf("info [%s][%s][%d]: "info"!\r\n", g_modName[mod_], __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define HAL_LOG_I(mod_, info, ...)
#endif
#if HAL_DEBUG_LEVEL <= HAL_LOG_DUBUG
#define HAL_LOG_D(mod_, info, ...) \
printf("debug [%s][%s][%d]: "info"!\r\n", g_modName[mod_], __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define HAL_LOG_D(mod_, info, ...)
#endif
#if HAL_DEBUG_LEVEL <= HAL_LOG_WARNING
#define HAL_LOG_W(mod_, info, ...) \
printf("warning [%s][%s][%d]: "info"!\r\n", g_modName[mod_], __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define HAL_LOG_W(mod_, info, ...)
#endif
#if HAL_DEBUG_LEVEL <= HAL_LOG_ERROR
#define HAL_LOG_E(mod_, info, ...) \
printf("error [%s][%s][%d]: "info"!\r\n", g_modName[mod_], __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define HAL_LOG_E(mod_, info, ...)
#endif
#if HAL_DEBUG_LEVEL <= HAL_LOG_FAIL
#define HAL_LOG_F(mod_, info, ...) \
printf("fail [%s][%s][%d]: "info"!\r\n", g_modName[mod_], __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define HAL_LOG_F(mod_, info, ...)
#endif
#define CHECK_NULLPTR_RETURN(mod_, ptr_, errno_) \
do { \
if ((ptr_) == NULL) { \
HAL_LOG_E(mod_, "%s is null!", #ptr_); \
return errno_; \
} \
} while (0);
#define CHECK_RETURN(mod_, ret_, str_) \
do { \
if ((ret_) != HAL_SUCCESS) { \
HAL_LOG_E(mod_, "%s fail,ret:%#x!", str_, ret_); \
return ret_; \
} \
} while (0);
#define CHECK_VALUE_RETURN(mod_, param_, min_, max_, errno_) \
do { \
if (((param_) < (min_)) || ((param_) > (max_))) { \
HAL_LOG_E(mod_, "%s[%d] is invaild!", #param_, param_); \
return errno_; \
} \
} while (0);
#define CHECK_GOTO(mod_, ret_, str_, goto_) \
do { \
if ((ret_) != HAL_SUCCESS) { \
HAL_LOG_E(mod_, "%s fail,ret:%#x!", str_, ret_); \
goto goto_; \
} \
} while (0);
typedef struct {
uint8_t * buf; /* tmp buf for rotation */
int bufLen; /* tmp buf len for rotation */
} COMM_RotateBuf;
typedef struct {
HAL_RotateInfo rotateInfo; /* rotate info */
int maxRotateAngle; /* max rotate angle */
} COMM_RotateContext;
int COMM_getFmtBpp(HAL_Format fmt);
#endif //__G2D_HAL_H__

View File

@@ -0,0 +1,43 @@
/*
* hal_errno.h
*@brief hal errno header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/06 create this file
*/
#ifndef __HAL_ERRNO_H__
#define __HAL_ERRNO_H__
enum {
HAL_ERRNO_NOT_INIT = 0, /* The module is not initialized. */
HAL_ERRNO_NULL_PTR, /* Null pointer exception */
HAL_ERRNO_ERR_PARAM, /* Parameters of the abnormal */
HAL_ERRNO_NOT_SUPPORT, /* This operation is not supported */
HAL_ERRNO_NO_MEM, /* System memory is insufficient */
};
enum {
HAL_FAILURE = -1,
HAL_SUCCESS = 0
};
/* module: bit[31:16],errno: bit[15:0] */
#define HAL_GENERATE_ERRNO(mod_, errno_) ((mod_) << 16) + (errno_)
/* log level enum */
#define HAL_LOG_INFO 0
#define HAL_LOG_DUBUG 1
#define HAL_LOG_WARNING 2
#define HAL_LOG_ERROR 3
#define HAL_LOG_FAIL 4
/* define log level */
#define HAL_DEBUG_LEVEL HAL_LOG_ERROR
#endif //__G2D_HAL_H__

View File

@@ -0,0 +1,37 @@
/*
* hal_asw.h
*@brief hal asw header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/19 create this file
*/
#ifndef __HAL_ASW_H__
#define __HAL_ASW_H__
#include "hal_asw_define.h"
#include "hal_comm_define.h"
/* full buf stride, must align 8 bit */
int HAL_ASW_FillTriangle(const HAL_FillRatriaInfo *info);
/* full buf stride, must align 8 bit */
int HAL_ASW_FillRect(const HAL_FillRectInfo *info);
/* cpu copy, Multi-threading is not supported */
int HAL_ASW_Rotate(const HAL_RotateInfo *info);
int HAL_ASW_RotateEx(const HAL_RotateInfo *info);
/****************************************************
inner function
*****************************************************/
int ASW_Rotate(const ASW_RotateInfo *info);
#endif //__HAL_ASW_H__

View File

@@ -0,0 +1,32 @@
/*
* hal_asw_define.h
*@brief hal asw define header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/06/01 create this file
*/
#ifndef __HAL_ASW_DEFINE_H__
#define __HAL_ASW_DEFINE_H__
#include "hal_errno.h"
#include "hal_comm_define.h"
#define HAL_ASW_NOT_INIT HAL_GENERATE_ERRNO(HAL_MOD_ASW, HAL_ERRNO_NOT_INIT)
#define HAL_ASW_NULL_PTR HAL_GENERATE_ERRNO(HAL_MOD_ASW, HAL_ERRNO_NULL_PTR)
#define HAL_ASW_ERR_PARAM HAL_GENERATE_ERRNO(HAL_MOD_ASW, HAL_ERRNO_ERR_PARAM)
#define HAL_ASW_NOT_SUPPORT HAL_GENERATE_ERRNO(HAL_MOD_ASW, HAL_ERRNO_NOT_SUPPORT)
#define HAL_ASW_NO_MEM HAL_GENERATE_ERRNO(HAL_MOD_ASW, HAL_ERRNO_NO_MEM)
typedef struct {
HAL_RotateInfo rotate;
uint8_t *tmpBuf; /* tmp rect buf */
uint32_t tmpStride; /* tmp rect buf strde*/
} ASW_RotateInfo;
#endif // __HAL_ASW_DEFINE_H__

View File

@@ -0,0 +1,23 @@
/*
* hal_disp.h
*@brief hal disp header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/19 create this file
*/
#ifndef __HAL_DISP_H__
#define __HAL_DISP_H__
#include "hal_disp_define.h"
#include "hal_comm_define.h"
HAL_HANDLE HAL_DISP_GetHandle(HAL_DISP_ScreenType type);
int HAL_DISP_Post(HAL_HANDLE handle, const HAL_DISP_Info *info);
#endif // __HAL_DISP_H__

View File

@@ -0,0 +1,55 @@
/*
* hal_disp_define.h
*@brief hal disp define header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/19 create this file
*/
#ifndef __HAL_DISP_DEFINE_H__
#define __HAL_DISP_DEFINE_H__
#include "hal_errno.h"
#include "hal_comm_define.h"
#define HAL_DISP_NOT_INIT HAL_GENERATE_ERRNO(HAL_MOD_DISP, HAL_ERRNO_NOT_INIT)
#define HAL_DISP_NULL_PTR HAL_GENERATE_ERRNO(HAL_MOD_DISP, HAL_ERRNO_NULL_PTR)
#define HAL_DISP_ERR_PARAM HAL_GENERATE_ERRNO(HAL_MOD_DISP, HAL_ERRNO_ERR_PARAM)
#define HAL_DISP_NOT_SUPPORT HAL_GENERATE_ERRNO(HAL_MOD_DISP, HAL_ERRNO_NOT_SUPPORT)
#define HAL_DISP_WIN_MAX_CNT 2
#define HAL_DISP_YUVA_ADDR_CNT 4
typedef enum {
HAL_SCREEN_TYPE_CLUSTER = 0,
HAL_SCREEN_TYPE_BUTT
} HAL_DISP_ScreenType;
typedef struct {
uint32_t id;
int dirty;
int en;
HAL_Format fmt;
HAL_Rect src;
uint8_t *addr[HAL_DISP_YUVA_ADDR_CNT];//YUVA
uint32_t srcStride[HAL_DISP_YUVA_ADDR_CNT];
HAL_Rect dst;
int enCkey;
int ckey;
int enAlpha;
char alpha;
int zOrder;
int security;
} HAL_DISP_WindowInfo;
typedef struct {
uint32_t winCnt;
HAL_DISP_WindowInfo winInfo[HAL_DISP_WIN_MAX_CNT];
} HAL_DISP_Info;
#endif // __HAL_DISP_DEFINE_H__

View File

@@ -0,0 +1,33 @@
/*
* hal_g2dlite.h
*@brief hal g2dlite header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/06/01 create this file
*/
#ifndef __HAL_G2DLITE_H__
#define __HAL_G2DLITE_H__
#include "hal_g2dlite_define.h"
int HAL_G2DLITE_Init(void);
int HAL_G2DLITE_Deinit(void);
int HAL_G2DLITE_ClearRect(HAL_G2DLITE_OutputInfo *info);
int HAL_G2DLITE_BlendImg(const HAL_G2DLITE_BlendImgInfo *info);
int HAL_G2DLITE_BlendImgWithPd(const HAL_G2DLITE_BlendImgInfo *info, HAL_G2DLITE_PorterDuffInfo *pdInfo);
int HAL_G2DLITE_BlendRleImg(const HAL_G2DLITE_BlendImgInfo *info, HAL_G2DLITE_RleInfo *rleInfo);
int HAL_G2DLITE_BlendRleImgWithPd(const HAL_G2DLITE_BlendImgInfo *info, HAL_G2DLITE_RleInfo *rleInfo, HAL_G2DLITE_PorterDuffInfo *pdInfo);
int HAL_G2DLITE_BlendMask(const HAL_G2DLITE_BlendMaskInfo *info);
int HAL_G2DLITE_FillMask(const HAL_G2DLITE_FillMaskInfo *info);
int HAL_G2DLITE_FillTriangle(const HAL_FillRatriaInfo *triangle_info);
int HAL_G2DLITE_FillRect(const HAL_FillRectInfo *rect);
int HAL_G2DLITE_FastCopy(const HAL_G2DLITE_FastCopyInfo *src,
const HAL_G2DLITE_FastCopyInfo *dst);
#endif //__HAL_G2DLITE_H__

View File

@@ -0,0 +1,126 @@
/*
* hal_g2dlite_define.h
*@brief hal g2dlite define header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/23 create this file
*/
#ifndef __HAL_G2DLITE_DEFINE_H__
#define __HAL_G2DLITE_DEFINE_H__
#include "hal_errno.h"
#include "hal_comm_define.h"
#define HAL_G2DLITE_NOT_INIT HAL_GENERATE_ERRNO(HAL_MOD_G2DLITE, HAL_ERRNO_NOT_INIT)
#define HAL_G2DLITE_NULL_PTR HAL_GENERATE_ERRNO(HAL_MOD_G2DLITE, HAL_ERRNO_NULL_PTR)
#define HAL_G2DLITE_ERR_PARAM HAL_GENERATE_ERRNO(HAL_MOD_G2DLITE, HAL_ERRNO_ERR_PARAM)
#define HAL_G2DLITE_NOT_SUPPORT HAL_GENERATE_ERRNO(HAL_MOD_G2DLITE, HAL_ERRNO_NOT_SUPPORT)
typedef enum {
HAL_G2DLITE_RLE_IN_BG_SURFACE = 0, /* run-length encoding in the background surface */
HAL_G2DLITE_RLE_IN_FG_SURFACE, /* run-length encoding in the foreground surface */
HAL_G2DLITE_RLE_BUTT
} HAL_G2DLITE_RleSurfaceType;
typedef struct {
HAL_G2DLITE_RleSurfaceType rleType; /* run-length encoding type */
} HAL_G2DLITE_RleInfo;
/* porter duff blend mode */
typedef enum {
HAL_G2DLITE_PD_MODE_CLEAR = 0,
HAL_G2DLITE_PD_MODE_SRC,
HAL_G2DLITE_PD_MODE_DST,
HAL_G2DLITE_PD_MODE_SRC_OVER,
HAL_G2DLITE_PD_MODE_DST_OVER,
HAL_G2DLITE_PD_MODE_SRC_IN,
HAL_G2DLITE_PD_MODE_DST_IN,
HAL_G2DLITE_PD_MODE_SRC_OUT,
HAL_G2DLITE_PD_MODE_DST_OUT,
HAL_G2DLITE_PD_MODE_SRC_ATOP,
HAL_G2DLITE_PD_MODE_DST_ATOP,
HAL_G2DLITE_PD_MODE_XOR,
HAL_G2DLITE_PD_MODE_DARKEN,
HAL_G2DLITE_PD_MODE_LIGHTEN,
HAL_G2DLITE_PD_MODE_MULTIPLY,
HAL_G2DLITE_PD_MODE_SCREEN,
HAL_G2DLITE_PD_MODE_ADD,
HAL_G2DLITE_PD_MODE_OVERLAY,
HAL_G2DLITE_PD_MODE_SRC_SUB,
HAL_G2DLITE_PD_MODE_DES_SUB,
HAL_G2DLITE_PD_MODE_BUTT
} HAL_G2DLITE_PdMode;
typedef enum {
HAL_G2DLITE_PD_TYPE_SRC_IN_BG = 0, /* porter duff src in background surface */
HAL_G2DLITE_PD_TYPE_SRC_IN_FG, /* porter duff src in in the foreground surface */
HAL_G2DLITE_PD_TYPE_BUTT
} HAL_G2DLITE_PdSurfaceType;
typedef struct {
HAL_G2DLITE_PdMode pdMode; /* porter duff blend mode */
HAL_G2DLITE_PdSurfaceType pdType; /* porter duff type */
} HAL_G2DLITE_PorterDuffInfo;
typedef enum {
HAL_G2DLITE_BLEND_PIXEL_NONE = 0, /* Use of global alpha */
HAL_G2DLITE_BLEND_PIXEL_PREMULTI, /* Premultiply, alpha is already premultiplied into data. */
HAL_G2DLITE_BLEND_PIXEL_COVERAGE, /* Use of iamge alpha */
HAL_G2DLITE_BLEND_PIXEL_BUTT
} HAL_G2DLITE_BlendMode;
typedef struct {
uint8_t *buf; // surface buf addr
uint8_t alpha; // surface alpha
uint32_t stride; // surface buf stride
HAL_Format fmt; // surface format type
HAL_Rect srcRect; // surface source rect
HAL_Rect dstRect; // surface destination rect
HAL_G2DLITE_BlendMode blendMode; // surface blend mode
} HAL_G2DLITE_SurfaceInfo;
typedef struct {
uint8_t *buf; // output buf addr
uint32_t stride; // output rect buf stride
HAL_Format fmt; // output rect buf format
HAL_Rect dstRect; // Output to the area of the output rectangle
} HAL_G2DLITE_OutputInfo;
typedef struct {
HAL_G2DLITE_SurfaceInfo fgSurface; // need to synthetic the upper surface
HAL_G2DLITE_SurfaceInfo bgSurface; // need to synthesize the lower surface
HAL_G2DLITE_OutputInfo output; // outout rect info
} HAL_G2DLITE_BlendImgInfo;
typedef struct {
uint8_t *buf; // mask area buf
uint32_t color; // mask area color, ARGB888, A:bit[31:24], R:bit[23:16], G:bit[15:8], B:bit[7:0]
uint32_t stride; // mask area buf stride
HAL_Rect rect; // mask area
} HAL_G2DLITE_MaskInfo;
typedef struct {
HAL_G2DLITE_SurfaceInfo surfaceInfo; // need to synthetic the surface
HAL_G2DLITE_OutputInfo output; // outout area info
HAL_G2DLITE_MaskInfo maskInfo; // need to synthetic the mask area info
} HAL_G2DLITE_BlendMaskInfo;
typedef struct {
HAL_G2DLITE_OutputInfo output; // outout area info
HAL_G2DLITE_MaskInfo maskInfo; // need to synthetic the mask area info
} HAL_G2DLITE_FillMaskInfo;
typedef struct {
uint8_t *buf; // copy area buf addr
HAL_Format fmt; // copy area format
HAL_Rect rect; // copy region location
uint32_t stride; // copy area buf stride
} HAL_G2DLITE_FastCopyInfo;
#endif // __HAL_G2DLITE_DEFINE_H__

View File

@@ -0,0 +1,22 @@
/*
* hal_gpu.h
*@brief hal gpu header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/06/01 create this file
*/
#ifndef __HAL_GPU_H__
#define __HAL_GPU_H__
#include "hal_gpu_define.h"
int HAL_GPU_Rotate(const HAL_RotateInfo *info);
int HAL_GPU_RotateEx(const HAL_RotateInfo *info);
#endif //__HAL_GPU_H__

View File

@@ -0,0 +1,50 @@
/*hal_gpu_define.h
*@brief hal gpu define header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/19 create this file
*/
#ifndef __HAL_GPU_DEFINE_H__
#define __HAL_GPU_DEFINE_H__
#include "hal_errno.h"
#include "hal_comm_define.h"
#define HAL_GPU_NOT_INIT HAL_GENERATE_ERRNO(HAL_MOD_GPU, HAL_ERRNO_NOT_INIT)
#define HAL_GPU_NULL_PTR HAL_GENERATE_ERRNO(HAL_MOD_GPU, HAL_ERRNO_NULL_PTR)
#define HAL_GPU_ERR_PARAM HAL_GENERATE_ERRNO(HAL_MOD_GPU, HAL_ERRNO_ERR_PARAM)
#define HAL_GPU_NOT_SUPPORT HAL_GENERATE_ERRNO(HAL_MOD_GPU, HAL_ERRNO_NOT_SUPPORT)
#define HAL_GPU_NO_MEM HAL_GENERATE_ERRNO(HAL_MOD_GPU, HAL_ERRNO_NO_MEM)
/************old define*************/
typedef struct {
uint8_t * buf; /* tmp buf for rotation */
int buf_len; /* tmp buf len for rotation */
} aswlite_rotate_buf;
typedef struct {
int src_x;
int src_y;
int src_w;
int src_h;
uint8_t *src_buf;
int src_fmt;
int src_stride;
uint8_t *dst_buf;
int dst_fmt;
int dst_w;
int dst_h;
int dst_stride;
double angle;
int bg_color;
} hal_asw_rotate_info;
#endif // __HAL_GPU_DEFINE_H__

View File

@@ -0,0 +1,25 @@
/*
* hal_sys.h
*@brief hal sys header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/19 create this file
*/
#ifndef __HAL_SYS_H__
#define __HAL_SYS_H__
#include "hal_sys_define.h"
#include "hal_comm_define.h"
int HAL_SYS_CleanCacheRange(const HAL_SYS_CacheInfo *info);
int HAL_SYS_InvalidateCacheRange(const HAL_SYS_CacheInfo *info);
int HAL_SYS_CleanInvalidateCacheRange(const HAL_SYS_CacheInfo *info);
void HAL_SYS_CleanInvalidateCacheAll(void);
#endif //__HAL_SYS_H__

View File

@@ -0,0 +1,32 @@
/*
* hal_sys_define.h
*@brief hal sys define header file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/19 create this file
*/
#ifndef __HAL_SYS_DEFINE_H__
#define __HAL_SYS_DEFINE_H__
#include "hal_errno.h"
#include "hal_comm_define.h"
#define HAL_SYS_NOT_INIT HAL_GENERATE_ERRNO(HAL_MOD_SYS, HAL_ERRNO_NOT_INIT)
#define HAL_SYS_NULL_PTR HAL_GENERATE_ERRNO(HAL_MOD_SYS, HAL_ERRNO_NULL_PTR)
#define HAL_SYS_ERR_PARAM HAL_GENERATE_ERRNO(HAL_MOD_SYS, HAL_ERRNO_ERR_PARAM)
#define HAL_SYS_NOT_SUPPORT HAL_GENERATE_ERRNO(HAL_MOD_SYS, HAL_ERRNO_NOT_SUPPORT)
typedef struct {
uint8_t *buf; /* cache buf addr */
HAL_Rect rect; /* clean cache rect */
HAL_Format fmt; /* cache format */
uint32_t stride; /* cache buf format */
} HAL_SYS_CacheInfo;
#endif // __HAL_SYS_DEFINE_H__

View File

@@ -0,0 +1,551 @@
/*
* hal_asw.c
*@brief hal asw function file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/19 create this file
*/
#include <stdlib.h>
#include <math.h>
#include "types.h"
#include "hal_comm_define.h"
#include "hal_comm_inner.h"
#include "hal_errno.h"
#if CONFIG_ASW
#include "asw/asw.h"
#endif
#include "hal_asw.h"
#define ASW_MAX_ANGLE 180 /* 180 ~360 filp */
#define ASW_ROTATE_MAX_ANGLE 5
#define ASW_ROTATE_IMG_CNT (ASW_MAX_ANGLE / (ASW_ROTATE_MAX_ANGLE * 2) ) /* 10: 0~20 */
static COMM_RotateContext g_aswContext = {0};
static bool g_ratateChanged = true;
static COMM_RotateBuf g_rotateBuf[ASW_ROTATE_IMG_CNT + 1] = { NULL, NULL }; /* add tmp buf */
static int ASW_TransformFmtType(HAL_Format fmtType, int *fmt)
{
#if CONFIG_ASW
switch (fmtType) {
case HAL_FMT_A8:
*fmt = FMT_MONOTONIC_8BIT;
break;
case HAL_FMT_RGB565:
*fmt = FMT_RGB565;
break;
case HAL_FMT_ARGB1555:
*fmt = FMT_RGBA5551;
break;
case HAL_FMT_ARGB8888:
*fmt = FMT_ARGB8888;
break;
default:
HAL_LOG_E(HAL_MOD_ASW, "can't support this fmt:%d!\n", fmtType);
return HAL_ASW_ERR_PARAM;
}
return HAL_SUCCESS;
#else
HAL_LOG_E(HAL_MOD_ASW, "CONFIG_ASW not open, don't support asw!\n");
return HAL_ASW_NOT_SUPPORT;
#endif
}
/* The color order of asw and dc is different and needs to be converted
@ dc color : A:bit[31:24], R:bit[23:16], G:bit[15:8], B:bit[7:0] ARGB
@ asw input bg color : A:bit[31:24], B:bit[23:16], G:bit[15:8], R:bit[7:0] ABGR
@ color : input color, A:bit[31:24], R:bit[23:16], G:bit[15:8], B:bit[7:0]
@ halFmt : HAL output format
@ fmt: ASW putput format
*/
static uint32_t ASW_TransformBgColor(HAL_Format halFmt, uint32_t color)
{
#if CONFIG_ASW
uint32_t out_color = color;
switch (halFmt) {
case HAL_FMT_RGB565:
/* ASW output BGR: B:bit[23:16], G:bit[15:8], R:bit[7:0]
The alpha value is ignored andConsistent position does not need to be moved,
and the RGB is in its original order */
return color;
case HAL_FMT_ARGB1555:
/* ASW input ABGR, output ABGR: A:bit[31:24], B:bit[23:16], G:bit[15:8], R:bit[7:0]
To get ARGB data, A:bit[31:24], B:bit[23:16], G:bit[15:8], B:bit[7:0]
Consistent position does not need to be moved.
*/
return color;
case HAL_FMT_ARGB8888:
/* asw bg color RGBA, DC color ARGB
@ input in bg color : A:bit[31:24], R:bit[23:16], G:bit[15:8], B:bit[7:0] ARGB
@ asw input bg color : A:bit[31:24], B:bit[23:16], G:bit[15:8], R:bit[7:0] ABGR
@ asw out bg color : B:bit[31:24], G:bit[23:16], R:bit[15:8], A:bit[7:0] BGRA
@ dc out color : A:bit[31:24], R:bit[23:16], G:bit[15:8], B:bit[7:0] ARGB
input color -> asw input color: A->A R->B G->G B->R
asw input color -> asw out bg color: B->B G->G R->R A->A
input color -> asw out bg color: R->B G->G B->R A->A
asw out bg color -> dc out color: B->A G->R R->G A->B
input color -> dc out color: R->A G->R B->G A->B
You need to convert ARGB to BARG */
uint32_t out_color = (((color >> 24) & 0xff) << 16) | (((color >> 16) & 0xff) << 8) |
((color >> 8) & 0xff) | ((color & 0xff) << 24);
return out_color;
default :
return color;
}
#else
HAL_LOG_E(HAL_MOD_ASW, "CONFIG_ASW not open, don't support asw!\n");
return HAL_ASW_NOT_SUPPORT;
#endif
}
/* The color order of asw and dc is different and needs to be converted
ASW in ARGB: B:bit[31:24], G:bit[23:16], R:bit[15:8], A:bit[7:0]
DC ARGB : A:bit[31:24], R:bit[23:16], G:bit[15:8], B:bit[7:0]
@ color : input color, A:bit[31:24], R:bit[23:16], G:bit[15:8], B:bit[7:0]
@ halFmt : HAL output format
@ fmt: ASW putput format
*/
static uint32_t ASW_TransformColor(HAL_Format halFmt, uint32_t color)
{
#if CONFIG_ASW
uint32_t outColor = color;
switch (halFmt) {
case HAL_FMT_RGB565:
/* ASW output RGB: B:bit[23:16], G:bit[15:8], R:bit[7:0]
The alpha value is ignored and needs to be moved to [7:0], and the RGB is in its original order */
uint32_t outColor = ((color >> 24) & 0xff) | (((color >> 16) & 0xff) << 24) |
(((color >> 8) & 0xff) << 16) | ((color & 0xff) << 8);
return outColor;
case HAL_FMT_ARGB1555:
/* ASW output RGBA: A:bit[31:24], B:bit[23:16], G:bit[15:8], R:bit[7:0]
To get ARGB data, A:bit[31:24], B:bit[23:16], G:bit[15:8], B:bit[7:0]
press RGBA input can be. R:bit[31:24], G:bit[23:16], B:bit[15:8], A:bit[7:0]
*/
outColor = ((color >> 24) & 0xff) | (((color >> 16) & 0xff) << 24) |
(((color >> 8) & 0xff) << 16) | ((color & 0xff) << 8);
return outColor;
case HAL_FMT_ARGB8888:
/* There is no format conversion within ASWs, and no conversion is required from ASWs to DC */
return color;
default:
return color;
}
#else
HAL_LOG_E(HAL_MOD_ASW, "CONFIG_ASW not open, don't support asw!\n");
return HAL_ASW_NOT_SUPPORT;
#endif
}
static void ASW_DeleteRotateBuf(uint32_t rotateImgCnt)
{
for (int i = 0; i < rotateImgCnt; i++) {
if (g_rotateBuf[i].buf != NULL) {
free((void *)g_rotateBuf[i].buf);
g_rotateBuf[i].bufLen = 0;
g_rotateBuf[i].buf = NULL;
}
}
/* free tmp buf */
if (g_rotateBuf[ASW_ROTATE_IMG_CNT].buf != NULL) {
free((void *)g_rotateBuf[ASW_ROTATE_IMG_CNT].buf);
g_rotateBuf[ASW_ROTATE_IMG_CNT].bufLen = 0;
g_rotateBuf[ASW_ROTATE_IMG_CNT].buf = NULL;
}
}
static int ASW_MallocRotateBuf(const HAL_RotateInfo *info, uint32_t rotateImgCnt, uint32_t sideLen, int srcBpp, int dstBpp)
{
/* malloc tmp buf */
if ((g_rotateBuf[ASW_ROTATE_IMG_CNT].buf == NULL) || (sideLen * sideLen * dstBpp > g_rotateBuf[ASW_ROTATE_IMG_CNT].bufLen)) {
if (g_rotateBuf[ASW_ROTATE_IMG_CNT].buf != NULL) {
free((void *)g_rotateBuf[ASW_ROTATE_IMG_CNT].buf);
}
g_rotateBuf[ASW_ROTATE_IMG_CNT].bufLen = sideLen * sideLen * dstBpp;
g_rotateBuf[ASW_ROTATE_IMG_CNT].buf = (uint8_t*)pvPortMallocAligned(g_rotateBuf[ASW_ROTATE_IMG_CNT].bufLen, 0x1000);
if (g_rotateBuf[ASW_ROTATE_IMG_CNT].buf == NULL) {
HAL_LOG_E(HAL_MOD_ASW, "pvPortMallocAligned rotate buf, len:%d error!\n",g_rotateBuf[ASW_ROTATE_IMG_CNT].bufLen);
g_rotateBuf[ASW_ROTATE_IMG_CNT].bufLen = 0;
g_rotateBuf[ASW_ROTATE_IMG_CNT].buf = NULL;
ASW_DeleteRotateBuf(rotateImgCnt);
return HAL_ASW_NO_MEM;
}
}
/* Save the image rotated degrees */
for (int i = 0; i < rotateImgCnt; i++) {
int bpp = dstBpp;
if (i == 0) {
bpp = srcBpp;
}
if ((g_rotateBuf[i].buf == NULL) || (sideLen * sideLen * bpp > g_rotateBuf[i].bufLen)) {
if (g_rotateBuf[i].buf != NULL) {
free((void *)g_rotateBuf[i].buf);
}
g_rotateBuf[i].bufLen = sideLen * sideLen * bpp;
g_rotateBuf[i].buf = (uint8_t*)pvPortMallocAligned(g_rotateBuf[i].bufLen, 0x1000);
if (g_rotateBuf[i].buf == NULL) {
HAL_LOG_E(HAL_MOD_ASW, "pvPortMallocAligned rotate buf, len:%d error!\n",g_rotateBuf[i].bufLen);
g_rotateBuf[i].bufLen = 0;
g_rotateBuf[i].buf = NULL;
ASW_DeleteRotateBuf(rotateImgCnt);
return HAL_ASW_NO_MEM;
}
g_ratateChanged = true;
}
}
return HAL_SUCCESS;
}
static int ASW_SaveRotateImg(const HAL_RotateInfo *info, uint32_t maxRotateAngle, uint32_t sideLen, int srcBpp, int dstBpp)
{
/* need to re-save the rotated image */
if (!g_ratateChanged && (info->srcBuf == g_aswContext.rotateInfo.srcBuf) && (info->srcRect.x == g_aswContext.rotateInfo.srcRect.x) && (info->srcRect.y == g_aswContext.rotateInfo.srcRect.y) &&
(info->srcRect.w == g_aswContext.rotateInfo.srcRect.w) && (info->srcRect.h == g_aswContext.rotateInfo.srcRect.h) &&
(info->srcFmt == g_aswContext.rotateInfo.srcFmt) && (info->dstFmt == g_aswContext.rotateInfo.dstFmt) && (info->bgColor == g_aswContext.rotateInfo.bgColor)) {
HAL_LOG_I(HAL_MOD_ASW, "the rotate img is not change!");
return HAL_SUCCESS;
}
uint32_t rotateImgCnt = ASW_MAX_ANGLE / (maxRotateAngle * 2);
int srcFmt = 0;
int ret = ASW_TransformFmtType(info->srcFmt, &srcFmt);
CHECK_RETURN(HAL_MOD_ASW, ret, "transform fmt type");
int dstFmt = 0;
ret = ASW_TransformFmtType(info->dstFmt, &dstFmt);
CHECK_RETURN(HAL_MOD_ASW, ret, "transform fmt type");
/* clean buf, save the image rotated degrees */
sdrv_asw_fill_rect(srcFmt, 0, sideLen, sideLen, 0, 0, (int)g_rotateBuf[0].buf, sideLen * srcBpp);
sdrv_asw_fill_rect(dstFmt, 0, sideLen, sideLen, 0, 0, (int)g_rotateBuf[ASW_ROTATE_IMG_CNT].buf, sideLen * dstBpp);
for (int i = 1; i < rotateImgCnt; i++) {
sdrv_asw_fill_rect(dstFmt, 0, sideLen, sideLen, 0, 0, (int)g_rotateBuf[i].buf, sideLen * dstBpp);
}
int copy_x = (sideLen - info->srcRect.w) / 2;
int copy_y = (sideLen - info->srcRect.h) / 2;
for (int i = 0; i < info->srcRect.h; i++) {
uint8_t *dstBuf = (g_rotateBuf[0].buf + copy_y * sideLen * srcBpp + copy_x * srcBpp) + i * sideLen * srcBpp;
uint8_t *srcBuf = (info->srcBuf + info->srcRect.y * info->srcStride + info->srcRect.x * srcBpp) + i * info->srcStride;
memcpy(dstBuf, srcBuf, info->srcRect.w * srcBpp);
}
arch_clean_cache_range(g_rotateBuf[0].buf, sideLen * srcBpp * sideLen);
ASW_RotateInfo rotateInfo = {0};
rotateInfo.rotate.srcRect.x = 0;
rotateInfo.rotate.srcRect.y = 0;
rotateInfo.rotate.srcRect.w = sideLen;
rotateInfo.rotate.srcRect.h = sideLen;
rotateInfo.rotate.srcFmt = info->srcFmt;
rotateInfo.rotate.srcStride = sideLen * srcBpp;
rotateInfo.rotate.srcBuf = g_rotateBuf[0].buf;
rotateInfo.rotate.dstWidth = sideLen;
rotateInfo.rotate.dstHeight = sideLen;
rotateInfo.rotate.dstFmt = info->dstFmt;
rotateInfo.rotate.dstStride = sideLen * dstBpp;
rotateInfo.rotate.bgColor = info->bgColor;
rotateInfo.tmpBuf = g_rotateBuf[ASW_ROTATE_IMG_CNT].buf;
rotateInfo.tmpStride = sideLen * dstBpp;
/* save the image rotated degrees */
for (int i = 1; i < rotateImgCnt; i++) {
rotateInfo.rotate.angle = (maxRotateAngle * 2) * i;
rotateInfo.rotate.dstBuf = g_rotateBuf[i].buf;
ret = ASW_Rotate(&rotateInfo);
CHECK_RETURN(HAL_MOD_ASW, ret, "ASW_Rotate");
}
g_ratateChanged = false;
g_aswContext.rotateInfo = *info;
return HAL_SUCCESS;
}
static int ASW_RotateAndCache(const HAL_RotateInfo *info, uint32_t maxRotateAngle)
{
#if CONFIG_ASW
int ret = HAL_SUCCESS;
HAL_LOG_D(HAL_MOD_ASW, "src:rect[%u, %u, %u, %u] buf[%#x] stride[%u] format[%d]",
info->srcRect.x, info->srcRect.y, info->srcRect.w, info->srcRect.h,
info->srcBuf, info->srcStride, info->srcFmt);
HAL_LOG_D(HAL_MOD_ASW, "dst:width[%u] height[%u] buf[%#x] stride[%u] format[%d] angle[%lf] bgColor[%#x]",
info->dstWidth, info->dstHeight, info->dstBuf, info->dstStride, info->dstFmt, info->angle, info->bgColor);
/* Apply buf with the diagonal of the picture as the side length */
uint32_t rotateWidth = (uint32_t)sqrt(info->srcRect.w * info->srcRect.w + info->srcRect.h * info->srcRect.h) + 1;
/* align 8 */
rotateWidth = rotateWidth % 8 ? ((rotateWidth / 8 + 1) * 8) : rotateWidth;
/* The target area should not be smaller than the diagonal of the picture */
if (rotateWidth > info->dstWidth || rotateWidth > info->dstHeight) {
HAL_LOG_E(HAL_MOD_ASW, "dst: width[%u] and height[%u] Must be greater than %u!\n",info->dstWidth, info->dstHeight, rotateWidth);
return HAL_ASW_ERR_PARAM;
}
int srcBpp = COMM_getFmtBpp(info->srcFmt);
if (srcBpp < 0){
return HAL_ASW_ERR_PARAM;
}
int dstBpp = COMM_getFmtBpp(info->dstFmt);
if (dstBpp < 0){
return HAL_ASW_ERR_PARAM;
}
HAL_LOG_I(HAL_MOD_ASW, "rotate:width[%u] height[%u] srcBpp[%d] dstBpp[%d]", rotateWidth, rotateWidth, srcBpp, dstBpp);
if ((maxRotateAngle < ASW_ROTATE_MAX_ANGLE) || (ASW_MAX_ANGLE % maxRotateAngle != 0)) {
HAL_LOG_E(HAL_MOD_ASW, "maxRotateAngle[%d] Must be greater than %u and It has to be divisible by 180!\n",maxRotateAngle, ASW_ROTATE_MAX_ANGLE);
return HAL_ASW_ERR_PARAM;
}
uint32_t rotateImgCnt = ASW_MAX_ANGLE / (maxRotateAngle * 2);
/* Save the image rotated degrees */
ret = ASW_MallocRotateBuf(info, rotateImgCnt, rotateWidth, srcBpp, dstBpp);
CHECK_RETURN(HAL_MOD_ASW, ret, "transform fmt type");
if (!g_ratateChanged && g_aswContext.maxRotateAngle != maxRotateAngle) {
g_ratateChanged = true;
g_aswContext.maxRotateAngle = maxRotateAngle;
}
/* clean buf, save the image rotated degrees */
ret = ASW_SaveRotateImg(info, maxRotateAngle, rotateWidth, srcBpp, dstBpp);
CHECK_GOTO(HAL_MOD_ASW, ret, "ASW_SaveRotateImg", GOTO);
int posX = 0;
int posY = 0;
if ((rotateWidth != info->dstWidth) || (rotateWidth != info->dstHeight)) {
posX = (info->dstWidth - rotateWidth) / 2;
posY = (info->dstHeight - rotateWidth) / 2;
}
HAL_LOG_I(HAL_MOD_ASW, "out rotate rect:posX[%d] posY[%d]", posX, posY);
ASW_RotateInfo rotateInfo = {0};
rotateInfo.rotate.srcRect.x = 0;
rotateInfo.rotate.srcRect.y = 0;
rotateInfo.rotate.srcRect.w = rotateWidth;
rotateInfo.rotate.srcRect.h = rotateWidth;
rotateInfo.rotate.srcFmt = info->srcFmt;
rotateInfo.rotate.srcStride = rotateWidth * srcBpp;
rotateInfo.rotate.dstWidth = rotateWidth;
rotateInfo.rotate.dstHeight = rotateWidth;
rotateInfo.rotate.dstFmt = info->dstFmt;
rotateInfo.rotate.dstBuf = (info->dstBuf + posY * info->dstStride + posX * dstBpp);
rotateInfo.rotate.dstStride = info->dstStride;
rotateInfo.rotate.bgColor = info->bgColor;
rotateInfo.tmpBuf = g_rotateBuf[ASW_ROTATE_IMG_CNT].buf;
rotateInfo.tmpStride = rotateWidth * dstBpp;
rotateInfo.rotate.angle = info->angle;
while (rotateInfo.rotate.angle < 0) {
rotateInfo.rotate.angle += 360;
}
while (rotateInfo.rotate.angle > 360) {
rotateInfo.rotate.angle -= 360;
}
if ((rotateInfo.rotate.angle <= maxRotateAngle || rotateInfo.rotate.angle >= 360 - maxRotateAngle) ||
((ASW_MAX_ANGLE - maxRotateAngle <= rotateInfo.rotate.angle) && (rotateInfo.rotate.angle <= ASW_MAX_ANGLE + maxRotateAngle))) {
rotateInfo.rotate.srcBuf = g_rotateBuf[0].buf;
ret = ASW_Rotate(&rotateInfo);
CHECK_GOTO(HAL_MOD_ASW, ret, "ASW_Rotate", GOTO);
return HAL_SUCCESS;
}
for (int i = 1; i < rotateImgCnt; i++) {
if (((maxRotateAngle + (maxRotateAngle * 2 * (i - 1)) <= rotateInfo.rotate.angle) &&
(rotateInfo.rotate.angle <= maxRotateAngle + (maxRotateAngle * 2 * i))) ||
((rotateInfo.rotate.angle >= ASW_MAX_ANGLE + (maxRotateAngle + maxRotateAngle * 2 * (i - 1))) &&
(rotateInfo.rotate.angle <= ASW_MAX_ANGLE + (maxRotateAngle + maxRotateAngle * 2 * i)))) {
rotateInfo.rotate.srcStride = rotateWidth * dstBpp;
rotateInfo.rotate.srcBuf = g_rotateBuf[i].buf;
rotateInfo.rotate.srcFmt = info->dstFmt;
rotateInfo.rotate.angle -= (maxRotateAngle * 2 * i);
ret = ASW_Rotate(&rotateInfo);
CHECK_GOTO(HAL_MOD_ASW, ret, "ASW_Rotate", GOTO);
break;
}
}
return HAL_SUCCESS;
GOTO:
ASW_DeleteRotateBuf(rotateImgCnt);
return ret;
#else
HAL_LOG_E(HAL_MOD_ASW, "CONFIG_ASW not open, don't support asw!\n");
return HAL_ASW_NOT_SUPPORT;
#endif
}
int HAL_ASW_FillTriangle(const HAL_FillRatriaInfo *info)
{
#if CONFIG_ASW
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info, HAL_ASW_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info->buf, HAL_ASW_NULL_PTR);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->dstRect.w, 1, HAL_GUI_MAX_WIDTH, HAL_ASW_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->dstRect.h, 1, HAL_GUI_MAX_HEIGHT, HAL_ASW_ERR_PARAM);
if ((info->stride == 0) || (info->stride % 8 != 0)) {
HAL_LOG_E(HAL_MOD_ASW, "ratria stride[%d] is invalid,It has to be a multiple of 8!\n", info->stride);
return HAL_ASW_ERR_PARAM;
}
if (info->type >= HAL_TRIANGLE_BUTT) {
HAL_LOG_E(HAL_MOD_ASW, "triangle_info->type:%d is invaild!\n", info->type);
return HAL_ASW_ERR_PARAM;
}
#endif
int fmt = 0;
int ret = ASW_TransformFmtType(info->fmt, &fmt);
CHECK_RETURN(HAL_MOD_ASW, ret, "transform fmt type");
HAL_LOG_D(HAL_MOD_ASW, "buf[%#x] type[%#x] stride[%d] format[%d], color[0x%x] rect(%d, %d, %d, %d)",
info->buf, info->type, info->stride, info->fmt, info->color,
info->dstRect.x, info->dstRect.y, info->dstRect.w, info->dstRect.h);
struct asw_ratria ratria_info;
ratria_info.type = info->type;
ratria_info.fmt = fmt;
ratria_info.color = ASW_TransformColor(info->fmt, info->color);
ratria_info.hsize = info->dstRect.w;
ratria_info.vsize = info->dstRect.h;
ratria_info.pos_x = info->dstRect.x;
ratria_info.pos_y = info->dstRect.y;
ratria_info.addr = (int)info->buf;
ratria_info.stride = info->stride;
sdrv_asw_ra_triangle(&ratria_info);
return HAL_SUCCESS;
#else
HAL_LOG_E(HAL_MOD_ASW, "CONFIG_ASW not open, don't support asw!\n");
return HAL_ASW_NOT_SUPPORT;
#endif
}
int HAL_ASW_FillRect(const HAL_FillRectInfo *info)
{
#if CONFIG_ASW
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info, HAL_ASW_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info->buf, HAL_ASW_NULL_PTR);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->dstRect.w, 1, HAL_GUI_MAX_WIDTH, HAL_ASW_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->dstRect.h, 1, HAL_GUI_MAX_HEIGHT, HAL_ASW_ERR_PARAM);
if (info->dstRect.w == 0 || info->dstRect.h == 0) {
HAL_LOG_E(HAL_MOD_ASW, "rect w[%d] or h[%d] is invalid!\n",
info->dstRect.w, info->dstRect.h);
return HAL_ASW_ERR_PARAM;
}
if ((info->stride == 0) || (info->stride % 8 != 0)) {
HAL_LOG_E(HAL_MOD_ASW, "rect stride[%d] is invalid,It has to be a multiple of 8!\n", info->stride);
return HAL_ASW_ERR_PARAM;
}
#endif
int fmt = 0;
int ret = ASW_TransformFmtType(info->fmt, &fmt);
CHECK_RETURN(HAL_MOD_ASW, ret, "transform fmt type");
HAL_LOG_D(HAL_MOD_ASW, "out :buf[%#x] stride[%d] format[%d], color [0x%x] rect(%d, %d, %d, %d)",
info->buf, info->stride, info->fmt, info->color,
info->dstRect.x, info->dstRect.y, info->dstRect.w, info->dstRect.h);
uint32_t color = ASW_TransformColor(info->fmt, info->color);
sdrv_asw_fill_rect(fmt, color, info->dstRect.w, info->dstRect.h,
info->dstRect.x, info->dstRect.y, (int)info->buf, info->stride);
return HAL_SUCCESS;
#else
HAL_LOG_E(HAL_MOD_ASW, "CONFIG_ASW not open, don't support asw!\n");
return HAL_ASW_NOT_SUPPORT;
#endif
}
int HAL_ASW_Rotate(const HAL_RotateInfo *info)
{
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info, HAL_ASW_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info->srcBuf, HAL_ASW_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info->dstBuf, HAL_ASW_NULL_PTR);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->srcRect.w, 1, HAL_GUI_MAX_WIDTH, HAL_ASW_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->srcRect.h, 1, HAL_GUI_MAX_HEIGHT, HAL_ASW_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->dstWidth, 1, HAL_GUI_MAX_WIDTH, HAL_ASW_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->dstHeight, 1, HAL_GUI_MAX_HEIGHT, HAL_ASW_ERR_PARAM);
if ((info->dstStride == 0) || (info->dstStride % 8 != 0)) {
HAL_LOG_E(HAL_MOD_ASW, "dst stride[%d] is invalid,It has to be a multiple of 8!\n", info->dstStride);
return HAL_ASW_ERR_PARAM;
}
#endif
return ASW_RotateAndCache(info, ASW_MAX_ANGLE / 2);
}
int HAL_ASW_RotateEx(const HAL_RotateInfo *info)
{
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info, HAL_ASW_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info->srcBuf, HAL_ASW_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info->dstBuf, HAL_ASW_NULL_PTR);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->srcRect.w, 1, HAL_GUI_MAX_WIDTH, HAL_ASW_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->srcRect.h, 1, HAL_GUI_MAX_HEIGHT, HAL_ASW_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->dstWidth, 1, HAL_GUI_MAX_WIDTH, HAL_ASW_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_ASW, info->dstHeight, 1, HAL_GUI_MAX_HEIGHT, HAL_ASW_ERR_PARAM);
if ((info->dstStride == 0) || (info->dstStride % 8 != 0)) {
HAL_LOG_E(HAL_MOD_ASW, "dst stride[%d] is invalid,It has to be a multiple of 8!\n", info->dstStride);
return HAL_ASW_ERR_PARAM;
}
#endif
return ASW_RotateAndCache(info, ASW_ROTATE_MAX_ANGLE);
}
int ASW_Rotate(const ASW_RotateInfo *info)
{
#if CONFIG_ASW
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_ASW, info, HAL_ASW_NULL_PTR);
#endif
HAL_LOG_D(HAL_MOD_ASW, "src:rect[%u, %u, %u, %u] buf[%#x] stride[%u] format[%d]",
info->rotate.srcRect.x, info->rotate.srcRect.y, info->rotate.srcRect.w, info->rotate.srcRect.h,
info->rotate.srcBuf, info->rotate.srcStride, info->rotate.srcFmt);
HAL_LOG_D(HAL_MOD_ASW, "dst:width[%u] height[%u] buf[%#x] stride[%u] format[%d] angle[%lf] bgColor[%#x]",
info->rotate.dstWidth, info->rotate.dstHeight, info->rotate.dstBuf, info->rotate.dstStride,
info->rotate.dstFmt, info->rotate.angle, info->rotate.bgColor);
struct asw_rot rot = {0};
rot.hsize = info->rotate.srcRect.w;
rot.vsize = info->rotate.srcRect.h;
rot.angle = info->rotate.angle;
int ret = ASW_TransformFmtType(info->rotate.dstFmt, &rot.dst_fmt);
CHECK_RETURN(HAL_MOD_ASW, ret, "transform fmt type");
rot.dst_ba = (int)(info->rotate.dstBuf);
rot.dst_stride = info->rotate.dstStride;
ret = ASW_TransformFmtType(info->rotate.srcFmt, &rot.src_fmt);
CHECK_RETURN(HAL_MOD_ASW, ret, "transform fmt type");
rot.bg_color = ASW_TransformBgColor(info->rotate.dstFmt, info->rotate.bgColor);
rot.src_stride[0] = info->rotate.srcStride;
rot.src_ba[0] = (int)info->rotate.srcBuf;
rot.t_buf = (int)info->tmpBuf;
rot.t_stride = (int)info->tmpStride;
sdrv_asw_bilinear_rotation(&rot);
return HAL_SUCCESS;
#else
HAL_LOG_E(HAL_MOD_ASW, "CONFIG_ASW not open, don't support asw!\n");
return HAL_ASW_NOT_SUPPORT;
#endif
}

View File

@@ -0,0 +1,136 @@
/*
* hal_disp.c
*@brief hal disp function file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/19 create this file
*/
#include <string.h>
#include "FreeRTOS.h"
#include <dispss/disp.h>
#include <dispss/disp_data_type.h>
#include "hal_comm_inner.h"
#include "hal_disp.h"
extern struct dc_dev g_dc_dev;
static int DISP_TransformFmtType(HAL_Format fmtType, int *fmt)
{
switch (fmtType) {
case HAL_FMT_RGB565:
*fmt = COLOR_RGB565;
break;
case HAL_FMT_ARGB1555:
*fmt = COLOR_ARGB1555;
break;
case HAL_FMT_ARGB4444:
*fmt = COLOR_ARGB4444;
break;
case HAL_FMT_RGB888:
*fmt = COLOR_RGB888;
break;
case HAL_FMT_ARGB8888:
*fmt = COLOR_ARGB8888;
break;
default:
HAL_LOG_E(HAL_MOD_DISP, "can't support this fmt:%d!\n", fmtType);
return HAL_DISP_ERR_PARAM;
}
return HAL_SUCCESS;
}
HAL_HANDLE HAL_DISP_GetHandle(HAL_DISP_ScreenType type)
{
if (type != HAL_SCREEN_TYPE_CLUSTER) {
HAL_LOG_E(HAL_MOD_DISP, "can't support this type:%d!\n", type);
return NULL;
}
return (HAL_HANDLE)&g_dc_dev;
}
int HAL_DISP_Post(HAL_HANDLE handle, const HAL_DISP_Info *info)
{
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_DISP, handle, HAL_DISP_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_DISP, info, HAL_DISP_NULL_PTR);
if ((info->winCnt == 0) || (info->winCnt > HAL_DISP_WIN_MAX_CNT)) {
HAL_LOG_E(HAL_MOD_DISP, "info->winCnt[%d] can not be more than %d and has to be greater than 0 !",
info->winCnt, HAL_DISP_WIN_MAX_CNT);
return HAL_DISP_ERR_PARAM;
}
for (uint32_t i = 0; i < info->winCnt; i++) {
if (info->winInfo[i].en) {
if (info->winInfo[i].addr[0] == NULL) {
HAL_LOG_E(HAL_MOD_DISP, "info->winInfo[%d].addr[0] is null!\n", i);
return HAL_DISP_NULL_PTR;
}
if (info->winInfo[i].srcStride[0] == 0) {
HAL_LOG_E(HAL_MOD_DISP, "info->winInfo[%d].srcStride[0] %d is invaild!\n", i, info->winInfo[i].srcStride[0]);
return HAL_DISP_ERR_PARAM;
}
CHECK_VALUE_RETURN(HAL_MOD_DISP, info->winInfo[i].src.w, 1, HAL_GUI_MAX_WIDTH, HAL_DISP_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_DISP, info->winInfo[i].src.h, 1, HAL_GUI_MAX_HEIGHT, HAL_DISP_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_DISP, info->winInfo[i].dst.w, 1, HAL_GUI_MAX_WIDTH, HAL_DISP_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_DISP, info->winInfo[i].dst.w, 1, HAL_GUI_MAX_HEIGHT, HAL_DISP_ERR_PARAM);
}
}
#endif
struct post_cfg post;
memset(&post, 0, sizeof(struct post_cfg));
HAL_LOG_D(HAL_MOD_DISP, "winCnt[%d]!\n", info->winCnt);
struct surface layer[HAL_DISP_WIN_MAX_CNT];
memset(layer, 0, sizeof(struct surface) * HAL_DISP_WIN_MAX_CNT);
post.num_layers = info->winCnt;
post.layers = layer;
for (uint32_t i = 0; i < info->winCnt; i++) {
const HAL_DISP_WindowInfo *winInfo = &info->winInfo[i];
HAL_LOG_D(HAL_MOD_DISP, "winInfo->src.w[%d] winInfo->src.h %d!\n", winInfo ->src.w, winInfo ->src.h);
HAL_LOG_D(HAL_MOD_DISP, "winInfo->dst.w[%d] winInfo->dst.h %d!\n", winInfo->dst.w, winInfo->dst.h);
HAL_LOG_D(HAL_MOD_DISP, "winInfo->src.x[%d] winInfo->src.y %d!\n", winInfo->src.x, winInfo->src.y);
HAL_LOG_D(HAL_MOD_DISP, "winInfo->dst.x[%d] winInfo->dst.y %d!\n", winInfo->dst.x, winInfo->dst.y);
layer[i].id = winInfo->id;
layer[i].dirty = winInfo->dirty;
layer[i].en = winInfo->en;
int ret = DISP_TransformFmtType(winInfo->fmt, &layer[i].fmt);
CHECK_RETURN(HAL_MOD_DISP, ret, "transform fmt type");
layer[i].src.x = winInfo->src.x;
layer[i].src.y = winInfo->src.y;
layer[i].src.w = winInfo->src.w;
layer[i].src.h = winInfo->src.h;
layer[i].start.x = winInfo->src.x;
layer[i].start.y = winInfo->src.y;
layer[i].start.w = winInfo->src.w;
layer[i].start.h = winInfo->src.h;
for (int j = 0; j < HAL_DISP_YUVA_ADDR_CNT; j++) {
layer[i].addr[j] = (unsigned long)winInfo->addr[j];
layer[i].src_stride[j] = winInfo->srcStride[j];
HAL_LOG_D(HAL_MOD_DISP, "winInfo->src_stride[%d] %d!\n", j, winInfo->srcStride[j]);
HAL_LOG_D(HAL_MOD_DISP, "layer[%d].addr[%d]:%#x!\n", i, j, layer[i].addr[j]);
}
layer[i].dst.x = winInfo->dst.x;
layer[i].dst.y = winInfo->dst.y;
layer[i].dst.w = winInfo->dst.w;
layer[i].dst.h = winInfo->dst.h;
layer[i].z_order = winInfo->zOrder;
layer[i].alpha_en = winInfo->enAlpha;
layer[i].alpha = winInfo->alpha;
layer[i].ckey_en = winInfo->enCkey;
layer[i].security = winInfo->security;
}
sdrv_display_post((struct dc_dev *)handle, &post);
return HAL_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,342 @@
/*
* hal_gpu.c
*@brief hal gpu function file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/06/01 create this file
*/
#include <dispss/disp.h>
#include <dispss/disp_data_type.h>
#include <g2dlite/g2dlite.h>
#include "hal_gpu.h"
#include "hal_g2dlite.h"
#include "hal_asw.h"
#include "hal_comm_inner.h"
#include <asw/asw.h>
#define GPU_MAX_ANGLE 180 /* 180 ~360 filp */
#define GPU_ROTATE_MAX_ANGLE 5 /* 10: 0~20 */
#define GPU_ROTATE_IMG_CNT (GPU_MAX_ANGLE / (GPU_ROTATE_MAX_ANGLE * 2))
static COMM_RotateContext g_gpuContext = {0};
/* The first rotation or rotation of the picture sends a change */
static bool g_ratateChanged = true;
/* rotate buf */
static COMM_RotateBuf g_rotateBuf[GPU_ROTATE_IMG_CNT + 1] = { NULL, NULL }; /* add tmp buf */
extern struct g2dlite_device g2dlite_dev;
static void GPU_DeleteRotateBuf(uint32_t rotateImgCnt)
{
for (int i = 0; i < rotateImgCnt; i++) {
if (g_rotateBuf[i].buf != NULL) {
free((void *)g_rotateBuf[i].buf);
g_rotateBuf[i].bufLen = 0;
g_rotateBuf[i].buf = NULL;
}
}
/* free tmp buf */
if (g_rotateBuf[GPU_ROTATE_IMG_CNT].buf != NULL) {
free((void *)g_rotateBuf[GPU_ROTATE_IMG_CNT].buf);
g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen = 0;
g_rotateBuf[GPU_ROTATE_IMG_CNT].buf = NULL;
}
}
static int GPU_MallocRotateBuf(const HAL_RotateInfo *info, uint32_t rotateImgCnt, uint32_t sideLen, uint32_t rotateSrcStride, uint32_t rotateDstStride)
{
/* malloc tmp buf */
if ((g_rotateBuf[GPU_ROTATE_IMG_CNT].buf == NULL) || (sideLen * rotateDstStride > g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen)) {
if (g_rotateBuf[GPU_ROTATE_IMG_CNT].buf != NULL) {
free((void *)g_rotateBuf[GPU_ROTATE_IMG_CNT].buf);
}
g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen = sideLen * rotateDstStride;
g_rotateBuf[GPU_ROTATE_IMG_CNT].buf = (uint8_t*)pvPortMallocAligned(g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen, 0x1000);
if (g_rotateBuf[GPU_ROTATE_IMG_CNT].buf == NULL) {
HAL_LOG_E(HAL_MOD_GPU, "pvPortMallocAligned rotate buf, len:%d error!\n",g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen);
g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen = 0;
g_rotateBuf[GPU_ROTATE_IMG_CNT].buf = NULL;
GPU_DeleteRotateBuf(rotateImgCnt);
return HAL_GPU_NO_MEM;
}
}
/* Save the image rotated degrees */
for (int i = 0; i < rotateImgCnt; i++) {
uint32_t stride = rotateDstStride;
if (i == 0) {
stride = rotateSrcStride;
}
/* Reapply for buf when the buf is too small or the picture is sent differently */
if ((g_rotateBuf[i].buf == NULL) || (sideLen * stride > g_rotateBuf[i].bufLen)) {
if (g_rotateBuf[i].buf != NULL) {
free((void *)g_rotateBuf[i].buf);
}
g_rotateBuf[i].bufLen = sideLen * stride;
g_rotateBuf[i].buf = (uint8_t*)pvPortMallocAligned(g_rotateBuf[i].bufLen, 0x1000);
if (g_rotateBuf[i].buf == NULL) {
HAL_LOG_E(HAL_MOD_GPU, "pvPortMallocAligned rotate buf, len:%d error!\n",g_rotateBuf[i].bufLen);
g_rotateBuf[i].bufLen = 0;
g_rotateBuf[i].buf = NULL;
GPU_DeleteRotateBuf(rotateImgCnt);
return HAL_GPU_NO_MEM;
}
g_ratateChanged = true;
}
}
return HAL_SUCCESS;
}
static int GPU_SaveRotateImg(const HAL_RotateInfo *info, uint32_t maxRotateAngle, uint32_t sideLen, uint32_t rotateSrcStride, uint32_t rotateDstStride)
{
/* need to re-save the rotated image */
if (!g_ratateChanged && (info->srcBuf == g_gpuContext.rotateInfo.srcBuf) && (info->srcRect.x == g_gpuContext.rotateInfo.srcRect.x) && (info->srcRect.y == g_gpuContext.rotateInfo.srcRect.y) &&
(info->srcRect.w == g_gpuContext.rotateInfo.srcRect.w) && (info->srcRect.h == g_gpuContext.rotateInfo.srcRect.h) &&
(info->srcFmt == g_gpuContext.rotateInfo.srcFmt) && (info->dstFmt == g_gpuContext.rotateInfo.dstFmt) && (info->bgColor == g_gpuContext.rotateInfo.bgColor)) {
HAL_LOG_I(HAL_MOD_GPU, "the rotate img is not change!");
return HAL_SUCCESS;
}
uint32_t rotateImgCnt = GPU_MAX_ANGLE / (maxRotateAngle * 2);
/* clean buf, save the image rotated degrees */
HAL_FillRectInfo rectInfo = {0};
rectInfo.buf = g_rotateBuf[0].buf;
rectInfo.color = 0;
rectInfo.fmt = info->srcFmt;
rectInfo.stride = rotateSrcStride;
rectInfo.dstRect.x = 0;
rectInfo.dstRect.y = 0;
rectInfo.dstRect.w = sideLen;
rectInfo.dstRect.h = sideLen;
for (int i = 0; i < rotateImgCnt; i++) {
if (i != 0) {
rectInfo.fmt = info->dstFmt;
rectInfo.stride = rotateDstStride;
}
rectInfo.buf = g_rotateBuf[i].buf;
int ret = HAL_ASW_FillRect(&rectInfo);
CHECK_RETURN(HAL_MOD_GPU, ret, "HAL_ASW_FillRect");
}
rectInfo.fmt = info->dstFmt;
rectInfo.stride = rotateDstStride;
rectInfo.buf = g_rotateBuf[GPU_ROTATE_IMG_CNT].buf;
int ret = HAL_ASW_FillRect(&rectInfo);
CHECK_RETURN(HAL_MOD_GPU, ret, "HAL_ASW_FillRect");
int copy_x = (sideLen - info->srcRect.w) / 2;
int copy_y = (sideLen - info->srcRect.h) / 2;
HAL_G2DLITE_FastCopyInfo src, dst;
src.buf = info->srcBuf;
src.rect.x = info->srcRect.x;
src.rect.y = info->srcRect.y;
src.rect.w = info->srcRect.w;
src.rect.h = info->srcRect.h;
src.fmt = info->srcFmt;
src.stride = info->srcStride;
dst.buf = g_rotateBuf[0].buf;
dst.rect.x = copy_x;
dst.rect.y = copy_y;
dst.rect.w = info->srcRect.w;
dst.rect.h = info->srcRect.h;
dst.fmt = info->srcFmt;
dst.stride = rotateSrcStride;
ret = HAL_G2DLITE_FastCopy(&src, &dst);
CHECK_RETURN(HAL_MOD_GPU, ret, "HAL_G2DLITE_FastCopy");
ASW_RotateInfo rotateInfo = {0};
rotateInfo.rotate.srcRect.x = 0;
rotateInfo.rotate.srcRect.y = 0;
rotateInfo.rotate.srcRect.w = sideLen;
rotateInfo.rotate.srcRect.h = sideLen;
rotateInfo.rotate.srcFmt = info->srcFmt;
rotateInfo.rotate.srcStride = rotateSrcStride;
rotateInfo.rotate.srcBuf = g_rotateBuf[0].buf;
rotateInfo.rotate.dstWidth = sideLen;
rotateInfo.rotate.dstHeight = sideLen;
rotateInfo.rotate.dstFmt = info->dstFmt;
rotateInfo.rotate.bgColor = info->bgColor;
rotateInfo.tmpBuf = g_rotateBuf[GPU_ROTATE_IMG_CNT].buf;
rotateInfo.tmpStride = rotateDstStride;
/* save the image rotated maxRotateAngle degrees */
rotateInfo.rotate.dstStride = rotateDstStride;
for (int i = 1; i < rotateImgCnt; i++) {
rotateInfo.rotate.angle = (maxRotateAngle * 2) * i;
rotateInfo.rotate.dstBuf = g_rotateBuf[i].buf;
int ret = ASW_Rotate(&rotateInfo);
CHECK_RETURN(HAL_MOD_GPU, ret, "ASW_Rotate");
}
g_gpuContext.rotateInfo = *info;
g_ratateChanged = false;
return HAL_SUCCESS;
}
static int GPU_Rotate(const HAL_RotateInfo *info, uint32_t maxRotateAngle)
{
int ret = HAL_SUCCESS;
HAL_LOG_D(HAL_MOD_GPU, "src:rect[%u, %u, %u, %u] buf[%#x] stride[%u] format[%d]",
info->srcRect.x, info->srcRect.y, info->srcRect.w, info->srcRect.h,
info->srcBuf, info->srcStride, info->srcFmt);
HAL_LOG_D(HAL_MOD_GPU, "dst:width[%u] height[%u] buf[%#x] stride[%u] format[%d] angle[%lf] bgColor[%#x]",
info->dstWidth, info->dstHeight, info->dstBuf, info->dstStride, info->dstFmt, info->angle, info->bgColor);
if ((maxRotateAngle < GPU_ROTATE_MAX_ANGLE) || (GPU_MAX_ANGLE % maxRotateAngle != 0)) {
HAL_LOG_E(HAL_MOD_GPU, "maxRotateAngle[%d] Must be greater than %u and It has to be divisible by 180!\n",maxRotateAngle, GPU_ROTATE_MAX_ANGLE);
return HAL_GPU_ERR_PARAM;
}
int srcBpp = COMM_getFmtBpp(info->srcFmt);
if (srcBpp < 0){
return HAL_GPU_ERR_PARAM;
}
int dstBpp = COMM_getFmtBpp(info->dstFmt);
if (dstBpp < 0){
return HAL_GPU_ERR_PARAM;
}
uint32_t rotateImgCnt = GPU_MAX_ANGLE / (maxRotateAngle * 2);
/* Apply buf with the diagonal of the picture as the side length */
uint32_t rotateWidth = (uint32_t)sqrt(info->srcRect.w * info->srcRect.w + info->srcRect.h * info->srcRect.h) + 1;
/* align 8 */
rotateWidth = rotateWidth % 8 ? ((rotateWidth / 8 + 1) * 8) : rotateWidth;
/* The target area should not be smaller than the diagonal of the picture */
if (rotateWidth > info->dstWidth || rotateWidth > info->dstHeight) {
HAL_LOG_E(HAL_MOD_GPU, "dst: width[%u] and height[%u] Must be greater than %u!\n",info->dstWidth, info->dstHeight, rotateWidth);
return HAL_GPU_ERR_PARAM;
}
uint32_t rotateSrcStride = rotateWidth * srcBpp;
uint32_t rotateDstStride = rotateWidth * dstBpp;
HAL_LOG_I(HAL_MOD_GPU, "rotate:width[%u] height[%u] srcBpp[%d] dstBpp[%d]", rotateWidth, rotateWidth, srcBpp, dstBpp);
/* Save the image rotated degrees */
ret = GPU_MallocRotateBuf(info, rotateImgCnt, rotateWidth, rotateSrcStride, rotateDstStride);
CHECK_RETURN(HAL_MOD_GPU, ret, "GPU_MallocRotateBuf");
if (!g_ratateChanged && g_gpuContext.maxRotateAngle != maxRotateAngle) {
g_ratateChanged = true;
g_gpuContext.maxRotateAngle = maxRotateAngle;
}
/* clean buf, save the image rotated degrees */
ret = GPU_SaveRotateImg(info, maxRotateAngle, rotateWidth, rotateSrcStride, rotateDstStride);
CHECK_GOTO(HAL_MOD_GPU, ret, "GPU_SaveRotateImg", GOTO);
int posX = 0;
int posY = 0;
if ((rotateWidth != info->dstWidth) || (rotateWidth != info->dstHeight)) {
posX = (info->dstWidth - rotateWidth) / 2;
posY = (info->dstHeight - rotateWidth) / 2;
}
HAL_LOG_I(HAL_MOD_GPU, "out rotate rect:posX[%d] posY[%d]", posX, posY);
ASW_RotateInfo rotateInfo = {0};
rotateInfo.rotate.srcRect.x = 0;
rotateInfo.rotate.srcRect.y = 0;
rotateInfo.rotate.srcRect.w = rotateWidth;
rotateInfo.rotate.srcRect.h = rotateWidth;
rotateInfo.rotate.srcFmt = info->srcFmt;
rotateInfo.rotate.srcStride = rotateSrcStride;
rotateInfo.rotate.dstWidth = rotateWidth;
rotateInfo.rotate.dstHeight = rotateWidth;
rotateInfo.rotate.dstFmt = info->dstFmt;
rotateInfo.rotate.dstBuf = (info->dstBuf + posY * info->dstStride + posX * dstBpp);
rotateInfo.rotate.dstStride = info->dstStride;
rotateInfo.rotate.bgColor = info->bgColor;
rotateInfo.tmpBuf = g_rotateBuf[GPU_ROTATE_IMG_CNT].buf;
rotateInfo.tmpStride = rotateDstStride;
rotateInfo.rotate.angle = info->angle;
while (rotateInfo.rotate.angle < 0) {
rotateInfo.rotate.angle += 360;
}
while (rotateInfo.rotate.angle > 360) {
rotateInfo.rotate.angle -= 360;
}
if ((rotateInfo.rotate.angle <= maxRotateAngle || rotateInfo.rotate.angle >= 360 - maxRotateAngle) ||
((GPU_MAX_ANGLE - maxRotateAngle <= rotateInfo.rotate.angle) && (rotateInfo.rotate.angle <= GPU_MAX_ANGLE + maxRotateAngle))) {
rotateInfo.rotate.srcBuf = g_rotateBuf[0].buf;
ret = ASW_Rotate(&rotateInfo);
CHECK_GOTO(HAL_MOD_GPU, ret, "ASW_Rotate", GOTO);
return HAL_SUCCESS;
}
for (int i = 1; i < rotateImgCnt; i++) {
if ((maxRotateAngle + (maxRotateAngle * 2 * (i - 1)) <= rotateInfo.rotate.angle) &&
(rotateInfo.rotate.angle <= maxRotateAngle + (maxRotateAngle * 2 * i)) ||
((rotateInfo.rotate.angle >= GPU_MAX_ANGLE + (maxRotateAngle + maxRotateAngle * 2 * (i - 1))) &&
(rotateInfo.rotate.angle <= GPU_MAX_ANGLE + (maxRotateAngle + maxRotateAngle * 2 * i)))) {
rotateInfo.rotate.srcStride = rotateDstStride;
rotateInfo.rotate.srcFmt = info->dstFmt;
rotateInfo.rotate.srcBuf = g_rotateBuf[i].buf;
rotateInfo.rotate.angle -= (maxRotateAngle * 2 * i);
ret = ASW_Rotate(&rotateInfo);
CHECK_GOTO(HAL_MOD_GPU, ret, "ASW_Rotate", GOTO);
break;
}
}
return HAL_SUCCESS;
GOTO:
GPU_DeleteRotateBuf(rotateImgCnt);
return ret;
}
int HAL_GPU_Rotate(const HAL_RotateInfo *info)
{
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info, HAL_GPU_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info->dstBuf, HAL_GPU_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info->srcBuf, HAL_GPU_NULL_PTR);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->srcRect.w, 1, HAL_GUI_MAX_WIDTH, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->srcRect.h, 1, HAL_GUI_MAX_HEIGHT, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->dstWidth, 1, HAL_GUI_MAX_WIDTH, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->dstHeight, 1, HAL_GUI_MAX_HEIGHT, HAL_GPU_ERR_PARAM);
if ((info->dstStride == 0) || (info->dstStride % 8 != 0)) {
HAL_LOG_E(HAL_MOD_ASW, "dst stride[%d] is invalid,It has to be a multiple of 8!\n", info->dstStride);
return HAL_GPU_ERR_PARAM;
}
#endif
return GPU_Rotate(info, GPU_MAX_ANGLE / 2);
}
int HAL_GPU_RotateEx(const HAL_RotateInfo *info)
{
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info, HAL_GPU_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info->dstBuf, HAL_GPU_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info->srcBuf, HAL_GPU_NULL_PTR);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->srcRect.w, 1, HAL_GUI_MAX_WIDTH, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->srcRect.h, 1, HAL_GUI_MAX_HEIGHT, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->dstWidth, 1, HAL_GUI_MAX_WIDTH, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->dstHeight, 1, HAL_GUI_MAX_HEIGHT, HAL_GPU_ERR_PARAM);
if ((info->dstStride == 0) || (info->dstStride % 8 != 0)) {
HAL_LOG_E(HAL_MOD_GPU, "dst stride[%d] is invalid,It has to be a multiple of 8!\n", info->dstStride);
return HAL_GPU_ERR_PARAM;
}
#endif
return GPU_Rotate(info, GPU_ROTATE_MAX_ANGLE);
}

View File

@@ -0,0 +1,114 @@
/*
* hal_sys.c
*@brief hal sys function file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/09/19 create this file
*/
#include "types.h"
#include "armv7-r/cache.h"
#include "hal_comm_inner.h"
#include "hal_sys.h"
int HAL_SYS_CleanCacheRange(const HAL_SYS_CacheInfo *info)
{
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_SYS, info, HAL_SYS_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_SYS, info->buf, HAL_SYS_NULL_PTR);
if (info->rect.w == 0 || info->rect.h == 0 || info->stride == 0) {
HAL_LOG_E(HAL_MOD_SYS, "rect w[%u] or h[%u] stride[%u] is invalid!\n",
info->rect.w, info->rect.h, info->buf, info->stride);
return HAL_SYS_ERR_PARAM;
}
#endif
int bpp = COMM_getFmtBpp(info->fmt);
if (bpp < 0) {
return HAL_SYS_ERR_PARAM;
}
HAL_LOG_D(HAL_MOD_SYS, "cache :buf[%#x] stride[%u] format[%d], rect[%u, %u, %u, %u] ",
info->buf, info->stride, info->fmt, info->rect.x, info->rect.y, info->rect.w, info->rect.h);
// This function should be called when the CPU is accessing the drawing device.
for(int i = 0; i < info->rect.h; i++) {
addr_t buf = (addr_t)(info->buf + info->rect.y * info->stride + info->rect.x * bpp + i * info->stride);
uint32_t len = info->rect.w * bpp;
arch_clean_cache_range(buf, len);
}
return HAL_SUCCESS;
}
int HAL_SYS_InvalidateCacheRange(const HAL_SYS_CacheInfo *info)
{
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_SYS, info, HAL_SYS_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_SYS, info->buf, HAL_SYS_NULL_PTR);
if (info->rect.w == 0 || info->rect.h == 0 || info->stride == 0) {
HAL_LOG_E(HAL_MOD_SYS, "rect w[%u] or h[%u] or stride[%u] is invalid!\n",
info->rect.w, info->rect.h, info->buf, info->stride);
return HAL_SYS_ERR_PARAM;
}
#endif
int bpp = COMM_getFmtBpp(info->fmt);
if (bpp < 0) {
return HAL_SYS_ERR_PARAM;
}
HAL_LOG_D(HAL_MOD_SYS, "cache :buf[%#x] stride[%u] format[%d], rect[%u, %u, %u, %u] ",
info->buf, info->stride, info->fmt, info->rect.x, info->rect.y, info->rect.w, info->rect.h);
// This function should be called when the CPU is accessing the drawing device.
for(int i = 0; i < info->rect.h; i++) {
addr_t buf = (addr_t)(info->buf + info->rect.y * info->stride + info->rect.x * bpp + i * info->stride);
uint32_t len = info->rect.w * bpp;
arch_invalidate_cache_range(buf, len);
}
return HAL_SUCCESS;
}
int HAL_SYS_CleanInvalidateCacheRange(const HAL_SYS_CacheInfo *info)
{
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_SYS, info, HAL_SYS_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_SYS, info->buf, HAL_SYS_NULL_PTR);
if (info->rect.w == 0 || info->rect.h == 0 || info->stride == 0) {
HAL_LOG_E(HAL_MOD_SYS, "rect w[%u] or h[%u] or stride[%u] is invalid!\n",
info->rect.w, info->rect.h, info->buf, info->stride);
return HAL_SYS_ERR_PARAM;
}
HAL_LOG_D(HAL_MOD_SYS, "cache :buf[%#x] stride[%u] format[%d], rect[%u, %u, %u, %u] ",
info->buf, info->stride, info->fmt, info->rect.x, info->rect.y, info->rect.w, info->rect.h);
#endif
int bpp = COMM_getFmtBpp(info->fmt);
if (bpp < 0) {
return HAL_SYS_ERR_PARAM;
}
// This function should be called when the CPU is accessing the drawing device.
for(int i = 0; i < info->rect.h; i++) {
addr_t buf = (addr_t)(info->buf + info->rect.y * info->stride + info->rect.x * bpp + i * info->stride);
uint32_t len = info->rect.w * bpp;
arch_clean_invalidate_cache_range(buf, len);
}
return HAL_SUCCESS;
}
void HAL_SYS_CleanInvalidateCacheAll(void)
{
arch_clean_invalidate_dcache_all();
}

View File

@@ -0,0 +1,34 @@
comment "LVGL gui engine"
config LVGL_SDRV_DISPLAY
bool "SDRV LVGL support display"
select DISPSS
default n
config LVGL_SDRV_DECODER_PNG
bool "SDRV LVGL support png decoder"
select DECODER_LODEPNG
default n
config LVGL_SDRV_DECODER_JPG
bool "SDRV LVGL support jpg decoder"
select TJPGDEC
default n
config LVGL_SDRV_FAT_FS
bool "SDRV LVGL support fat fs"
default n
config LVGL_SDRV_GPU
bool "SDRV LVGL support GPU"
select G2DLITE
default n
config LVGL_SDRV_INPUT
bool "SDRV LVGL support touch"
default n
config LVGL_EXAMPLE_DEMO
bool "SDRV LVGL examples demo"
default n

View File

@@ -0,0 +1,7 @@
VPATH := $(patsubst :%, %, $(VPATH))
MODULE_SRCS += $(patsubst %.c,$(join $(VPATH)/, %.c), $(CSRCS))
MODULE_CFLAGS += $(CFLAGS)
GLOBAL_INCLUDES += $(VPATH)
CFLAGS :=
VPATH :=
CSRCS :=

View File

@@ -0,0 +1,7 @@
[*.{c,h}]
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

View File

@@ -0,0 +1 @@
custom: ["https://paypal.me/littlevgl?locale.x=en_US"]

View File

@@ -0,0 +1,14 @@
---
name: All other issues
about: Questions and enhancement requests should go to the forum.
title: ''
labels: not-template
assignees: ''
---
# All enhancement requests or questions should be directed to the Forum.
We use GitHub issues for development related discussions.
Please use the [forum](https://forum.littlevgl.com/) to ask questions.

View File

@@ -0,0 +1,29 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
> # Important: issues that don't use this template will be ignored/closed.
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Please provide a small, independent code sample that can be used to reproduce the issue. Ideally this should work in the PC simulator unless the problem is specific to one platform.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,14 @@
blank_issues_enabled: false
contact_links:
- name: Documentation
url: https://docs.lvgl.io
about: Be sure to read to documentation first
- name: Forum
url: https://forum.lvgl.io
about: For how-to questions use the forum
- name: CONTIBUTING.md
url: https://github.com/lvgl/lvgl/blob/master/docs/CONTRIBUTING.md#faq-about-contributing
about: The basic rules of contributing
- name: CODING_STYLE.md
url: https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md
about: Quick summary of LVGL's code style

View File

@@ -0,0 +1,12 @@
# Comment to a new issue.
pullRequestOpened: |
Thank you for raising your pull request.
To ensure that all licensing criteria is met all repositories of the LVGL project apply a process called DCO (Developer's Certificate of Origin).
The text of DCO can be read here: https://developercertificate.org/
For a more detailed description see the [Documentation](https://docs.lvgl.io/latest/en/html/contributing/index.html#developer-certification-of-origin-dco) site.
By contributing to any repositories of the LVGL project you state that your contribution corresponds with the DCO.
No further action is required if your contribution fulfills the DCO. If you are not sure about it feel free to ask us in a comment.

View File

@@ -0,0 +1,17 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 21
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- architecture
- pinned
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue or pull request has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@@ -0,0 +1,17 @@
name: C/C++ CI
on:
push:
branches: [ master, dev ]
pull_request:
branches: [master, dev ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: sudo apt-get install libpng-dev; cd tests; python ./build.py

View File

@@ -0,0 +1,17 @@
name: Merge master branch to dev
on:
push:
branches:
- 'master'
jobs:
merge-branch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Merge to dev branch
uses: devmasx/merge-branch@v1.1.0
with:
type: now
target_branch: 'dev'
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

View File

@@ -0,0 +1,8 @@
**/*.o
**/*bin
**/*.swp
**/*.swo
tags
docs/api_doc
scripts/cppcheck_res.txt
scripts/built_in_font/lv_font_*

Some files were not shown because too many files have changed in this diff Show More