新增所有文件
This commit is contained in:
157
middleware/CLI/CLI_console.c
Normal file
157
middleware/CLI/CLI_console.c
Normal 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;
|
||||
}
|
||||
273
middleware/CLI/FreeRTOS_CLI.c
Normal file
273
middleware/CLI/FreeRTOS_CLI.c
Normal 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;
|
||||
}
|
||||
|
||||
67
middleware/CLI/FreeRTOS_CLI.h
Normal file
67
middleware/CLI/FreeRTOS_CLI.h
Normal 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_ */
|
||||
32
middleware/CLI/History.txt
Normal file
32
middleware/CLI/History.txt
Normal 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.
|
||||
|
||||
19
middleware/CLI/LICENSE_INFORMATION.txt
Normal file
19
middleware/CLI/LICENSE_INFORMATION.txt
Normal 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.
|
||||
5
middleware/CLI/ReadMe.url
Normal file
5
middleware/CLI/ReadMe.url
Normal file
@@ -0,0 +1,5 @@
|
||||
[InternetShortcut]
|
||||
URL=http://www.freertos.org/cli
|
||||
IDList=
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,2
|
||||
88
middleware/CLI/include/CLI.h
Normal file
88
middleware/CLI/include/CLI.h
Normal 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_ */
|
||||
4
middleware/CLI/readme.txt
Normal file
4
middleware/CLI/readme.txt
Normal 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
443
middleware/checksum/crc32.c
Normal 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);
|
||||
}
|
||||
37
middleware/checksum/crc32.h
Normal file
37
middleware/checksum/crc32.h
Normal 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
|
||||
437
middleware/checksum/crc32_data.h
Normal file
437
middleware/checksum/crc32_data.h
Normal 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
|
||||
20
middleware/checksum/crc4.c
Normal file
20
middleware/checksum/crc4.c
Normal 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;
|
||||
}
|
||||
11
middleware/checksum/crc4.h
Normal file
11
middleware/checksum/crc4.h
Normal 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
279
middleware/checksum/md5.c
Normal 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
62
middleware/checksum/md5.h
Normal 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
|
||||
33
middleware/checksum/zutil.h
Normal file
33
middleware/checksum/zutil.h
Normal 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
102
middleware/debug/debug.c
Normal 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
555
middleware/disk/disk.c
Normal 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
399
middleware/disk/disk.h
Normal 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
656
middleware/disk/disk_mmc.c
Normal 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;
|
||||
}
|
||||
73
middleware/disk/disk_mmc.h
Normal file
73
middleware/disk/disk_mmc.h
Normal 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_ */
|
||||
450
middleware/disk/disk_norflash.c
Normal file
450
middleware/disk/disk_norflash.c
Normal 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;
|
||||
}
|
||||
55
middleware/disk/disk_norflash.h
Normal file
55
middleware/disk/disk_norflash.h
Normal 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
195
middleware/disk/disk_usb.c
Normal 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;
|
||||
}
|
||||
22
middleware/disk/disk_usb.h
Normal file
22
middleware/disk/disk_usb.h
Normal 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
4590
middleware/dloader/dloader.c
Normal file
File diff suppressed because it is too large
Load Diff
238
middleware/dloader/dloader.h
Normal file
238
middleware/dloader/dloader.h
Normal 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
|
||||
139
middleware/dloader/dloader_disk_io.c
Normal file
139
middleware/dloader/dloader_disk_io.c
Normal 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
|
||||
}
|
||||
70
middleware/dloader/dloader_fuse_bin.c
Normal file
70
middleware/dloader/dloader_fuse_bin.c
Normal 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, "");
|
||||
}
|
||||
4
middleware/dloader/dloader_fuse_bin.h
Normal file
4
middleware/dloader/dloader_fuse_bin.h
Normal 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);
|
||||
566
middleware/dloader/dloader_test.c
Normal file
566
middleware/dloader/dloader_test.c
Normal 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
|
||||
449
middleware/dloader/dloader_usb_fastboot.c
Normal file
449
middleware/dloader/dloader_usb_fastboot.c
Normal 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);
|
||||
}
|
||||
}
|
||||
34
middleware/dloader/dloader_usb_fastboot.h
Normal file
34
middleware/dloader/dloader_usb_fastboot.h
Normal 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
|
||||
331
middleware/fatfs/diskio_sdrv.c
Normal file
331
middleware/fatfs/diskio_sdrv.c
Normal 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
8237
middleware/fatfs/ff.c
Normal file
File diff suppressed because it is too large
Load Diff
187
middleware/fatfs/ff_unittest.c
Normal file
187
middleware/fatfs/ff_unittest.c
Normal 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
187
middleware/fatfs/ffsystem.c
Normal 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
27354
middleware/fatfs/ffunicode.c
Normal file
File diff suppressed because it is too large
Load Diff
82
middleware/fatfs/include/diskio.h
Normal file
82
middleware/fatfs/include/diskio.h
Normal 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
|
||||
444
middleware/fatfs/include/ff.h
Normal file
444
middleware/fatfs/include/ff.h
Normal 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 */
|
||||
291
middleware/fatfs/include/ffconf.h
Normal file
291
middleware/fatfs/include/ffconf.h
Normal 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
1595
middleware/fee/fee.c
Normal file
File diff suppressed because it is too large
Load Diff
161
middleware/fee/fee.h
Normal file
161
middleware/fee/fee.h
Normal 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_ */
|
||||
|
||||
85
middleware/fee/fee_block.c
Normal file
85
middleware/fee/fee_block.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
59
middleware/fee/fee_block.h
Normal file
59
middleware/fee/fee_block.h
Normal 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
241
middleware/fee/fee_eeprom.c
Normal 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;
|
||||
}
|
||||
60
middleware/fee/fee_eeprom.h
Normal file
60
middleware/fee/fee_eeprom.h
Normal 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_ */
|
||||
|
||||
14
middleware/flash/ReadMe.txt
Normal file
14
middleware/flash/ReadMe.txt
Normal 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
460
middleware/flash/fls.c
Normal 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;
|
||||
}
|
||||
105
middleware/flash/include/fls.h
Normal file
105
middleware/flash/include/fls.h
Normal 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
|
||||
119
middleware/flashloader/FlashDev.c
Normal file
119
middleware/flashloader/FlashDev.c
Normal 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.
|
||||
}};
|
||||
1015
middleware/flashloader/FlashPrg.c
Normal file
1015
middleware/flashloader/FlashPrg.c
Normal file
File diff suppressed because it is too large
Load Diff
109
middleware/flashloader/FlashPrg_T32.c
Normal file
109
middleware/flashloader/FlashPrg_T32.c
Normal 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;
|
||||
}
|
||||
456
middleware/flashloader/bpt_update.c
Normal file
456
middleware/flashloader/bpt_update.c
Normal 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;
|
||||
}
|
||||
161
middleware/flashloader/flash_loader.c
Normal file
161
middleware/flashloader/flash_loader.c
Normal 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)
|
||||
;
|
||||
}
|
||||
171
middleware/flashloader/flash_loader_asm.s
Normal file
171
middleware/flashloader/flash_loader_asm.s
Normal 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
|
||||
352
middleware/flashloader/flash_loader_implement.c
Normal file
352
middleware/flashloader/flash_loader_implement.c
Normal 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;
|
||||
}
|
||||
483
middleware/flashloader/flash_wrapper.c
Normal file
483
middleware/flashloader/flash_wrapper.c
Normal 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
|
||||
82
middleware/flashloader/flashloader_fuse_bin.c
Normal file
82
middleware/flashloader/flashloader_fuse_bin.c
Normal 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;
|
||||
}
|
||||
115
middleware/flashloader/include/FlashOS.h
Normal file
115
middleware/flashloader/include/FlashOS.h
Normal 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 ***************************/
|
||||
137
middleware/flashloader/include/bpt_v2.h
Normal file
137
middleware/flashloader/include/bpt_v2.h
Normal 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
|
||||
38
middleware/flashloader/include/flash_config.h
Normal file
38
middleware/flashloader/include/flash_config.h
Normal 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
|
||||
93
middleware/flashloader/include/flash_loader.h
Normal file
93
middleware/flashloader/include/flash_loader.h
Normal 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);
|
||||
46
middleware/flashloader/include/flash_loader_extra.h
Normal file
46
middleware/flashloader/include/flash_loader_extra.h
Normal 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;
|
||||
62
middleware/flashloader/include/flash_wrapper.h
Normal file
62
middleware/flashloader/include/flash_wrapper.h
Normal 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
|
||||
36
middleware/flashloader/include/flashloader.h
Normal file
36
middleware/flashloader/include/flashloader.h
Normal 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);
|
||||
3
middleware/flashloader/include/flashloader_fuse_bin.h
Normal file
3
middleware/flashloader/include/flashloader_fuse_bin.h
Normal 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
806
middleware/fuse/fuse_bin.c
Normal 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;
|
||||
}
|
||||
20
middleware/fuse/fuse_bin.h
Normal file
20
middleware/fuse/fuse_bin.h
Normal 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);
|
||||
110
middleware/gpu_hal/comm/hal_comm_define.h
Normal file
110
middleware/gpu_hal/comm/hal_comm_define.h
Normal 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__
|
||||
41
middleware/gpu_hal/comm/hal_comm_inner.c
Normal file
41
middleware/gpu_hal/comm/hal_comm_inner.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
114
middleware/gpu_hal/comm/hal_comm_inner.h
Normal file
114
middleware/gpu_hal/comm/hal_comm_inner.h
Normal 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__
|
||||
43
middleware/gpu_hal/comm/hal_errno.h
Normal file
43
middleware/gpu_hal/comm/hal_errno.h
Normal 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__
|
||||
37
middleware/gpu_hal/inc/hal_asw.h
Normal file
37
middleware/gpu_hal/inc/hal_asw.h
Normal 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__
|
||||
32
middleware/gpu_hal/inc/hal_asw_define.h
Normal file
32
middleware/gpu_hal/inc/hal_asw_define.h
Normal 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__
|
||||
23
middleware/gpu_hal/inc/hal_disp.h
Normal file
23
middleware/gpu_hal/inc/hal_disp.h
Normal 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__
|
||||
55
middleware/gpu_hal/inc/hal_disp_define.h
Normal file
55
middleware/gpu_hal/inc/hal_disp_define.h
Normal 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__
|
||||
33
middleware/gpu_hal/inc/hal_g2dlite.h
Normal file
33
middleware/gpu_hal/inc/hal_g2dlite.h
Normal 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__
|
||||
126
middleware/gpu_hal/inc/hal_g2dlite_define.h
Normal file
126
middleware/gpu_hal/inc/hal_g2dlite_define.h
Normal 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__
|
||||
22
middleware/gpu_hal/inc/hal_gpu.h
Normal file
22
middleware/gpu_hal/inc/hal_gpu.h
Normal 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__
|
||||
50
middleware/gpu_hal/inc/hal_gpu_define.h
Normal file
50
middleware/gpu_hal/inc/hal_gpu_define.h
Normal 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__
|
||||
25
middleware/gpu_hal/inc/hal_sys.h
Normal file
25
middleware/gpu_hal/inc/hal_sys.h
Normal 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__
|
||||
32
middleware/gpu_hal/inc/hal_sys_define.h
Normal file
32
middleware/gpu_hal/inc/hal_sys_define.h
Normal 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__
|
||||
551
middleware/gpu_hal/src/hal_asw.c
Normal file
551
middleware/gpu_hal/src/hal_asw.c
Normal 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
|
||||
}
|
||||
136
middleware/gpu_hal/src/hal_disp.c
Normal file
136
middleware/gpu_hal/src/hal_disp.c
Normal 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;
|
||||
}
|
||||
|
||||
1005
middleware/gpu_hal/src/hal_g2dlite.c
Normal file
1005
middleware/gpu_hal/src/hal_g2dlite.c
Normal file
File diff suppressed because it is too large
Load Diff
342
middleware/gpu_hal/src/hal_gpu.c
Normal file
342
middleware/gpu_hal/src/hal_gpu.c
Normal 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);
|
||||
}
|
||||
114
middleware/gpu_hal/src/hal_sys.c
Normal file
114
middleware/gpu_hal/src/hal_sys.c
Normal 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();
|
||||
}
|
||||
34
middleware/littlevgl/Kconfig
Normal file
34
middleware/littlevgl/Kconfig
Normal 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
|
||||
|
||||
7
middleware/littlevgl/convert_lk.mk
Normal file
7
middleware/littlevgl/convert_lk.mk
Normal 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 :=
|
||||
7
middleware/littlevgl/lvgl-release-v7/.editorconfig
Normal file
7
middleware/littlevgl/lvgl-release-v7/.editorconfig
Normal 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
|
||||
|
||||
1
middleware/littlevgl/lvgl-release-v7/.github/FUNDING.yml
vendored
Normal file
1
middleware/littlevgl/lvgl-release-v7/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
custom: ["https://paypal.me/littlevgl?locale.x=en_US"]
|
||||
14
middleware/littlevgl/lvgl-release-v7/.github/ISSUE_TEMPLATE/all-other-issues.md
vendored
Normal file
14
middleware/littlevgl/lvgl-release-v7/.github/ISSUE_TEMPLATE/all-other-issues.md
vendored
Normal 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.
|
||||
29
middleware/littlevgl/lvgl-release-v7/.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
29
middleware/littlevgl/lvgl-release-v7/.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal 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.
|
||||
14
middleware/littlevgl/lvgl-release-v7/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
14
middleware/littlevgl/lvgl-release-v7/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal 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
|
||||
12
middleware/littlevgl/lvgl-release-v7/.github/auto-comment.yml
vendored
Normal file
12
middleware/littlevgl/lvgl-release-v7/.github/auto-comment.yml
vendored
Normal 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.
|
||||
17
middleware/littlevgl/lvgl-release-v7/.github/stale.yml
vendored
Normal file
17
middleware/littlevgl/lvgl-release-v7/.github/stale.yml
vendored
Normal 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
|
||||
17
middleware/littlevgl/lvgl-release-v7/.github/workflows/ccpp.yml
vendored
Normal file
17
middleware/littlevgl/lvgl-release-v7/.github/workflows/ccpp.yml
vendored
Normal 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
|
||||
17
middleware/littlevgl/lvgl-release-v7/.github/workflows/merge-to-dev.yml
vendored
Normal file
17
middleware/littlevgl/lvgl-release-v7/.github/workflows/merge-to-dev.yml
vendored
Normal 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}}
|
||||
8
middleware/littlevgl/lvgl-release-v7/.gitignore
vendored
Normal file
8
middleware/littlevgl/lvgl-release-v7/.gitignore
vendored
Normal 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
Reference in New Issue
Block a user