mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Finish the Zynq demo.
This commit is contained in:
parent
2fc4e89b98
commit
c83414ccc4
|
@ -32,8 +32,9 @@
|
|||
</option>
|
||||
<option id="xilinx.gnu.compiler.dircategory.includes.1516519458" name="Include Paths" superClass="xilinx.gnu.compiler.dircategory.includes" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/FreeRTOS_Source/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/FreeRTOS-Plus-CLI}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Standard_Demo_Tasks/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Full_Demo}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Full_Demo/FreeRTOS-Plus-CLI}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Full_Demo/Standard_Demo_Tasks/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/FreeRTOS_Source/portable/GCC/ARM_CA9}""/>
|
||||
</option>
|
||||
|
|
|
@ -24,56 +24,38 @@
|
|||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>src/FreeRTOS-Plus-CLI</name>
|
||||
<type>2</type>
|
||||
<locationURI>FREERTOS_ROOT/FreeRTOS-Plus/Source/FreeRTOS-Plus-CLI</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src/FreeRTOS_Source</name>
|
||||
<type>2</type>
|
||||
<locationURI>FREERTOS_ROOT/FreeRTOS/Source</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src/Sample-CLI-commands.c</name>
|
||||
<name>src/Full_Demo/FreeRTOS-Plus-CLI</name>
|
||||
<type>2</type>
|
||||
<locationURI>FREERTOS_ROOT/FreeRTOS-Plus/Source/FreeRTOS-Plus-CLI</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src/Full_Demo/Sample-CLI-commands.c</name>
|
||||
<type>1</type>
|
||||
<locationURI>FREERTOS_ROOT/FreeRTOS-Plus/Demo/Common/FreeRTOS_Plus_CLI_Demos/Sample-CLI-commands.c</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src/Standard_Demo_Tasks</name>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks</name>
|
||||
<type>2</type>
|
||||
<locationURI>FREERTOS_ROOT/FreeRTOS/Demo/Common</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src/UARTCommandConsole.c</name>
|
||||
<name>src/Full_Demo/UARTCommandConsole.c</name>
|
||||
<type>1</type>
|
||||
<locationURI>FREERTOS_ROOT/FreeRTOS-Plus/Demo/Common/FreeRTOS_Plus_CLI_Demos/UARTCommandConsole.c</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src/Standard_Demo_Tasks/IntQueue.c</name>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks/IntQueue.c</name>
|
||||
<type>1</type>
|
||||
<locationURI>FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/IntQueue.c</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
<filteredResources>
|
||||
<filter>
|
||||
<id>1390227891704</id>
|
||||
<name>src/Standard_Demo_Tasks</name>
|
||||
<type>9</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-minimal</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1390227891720</id>
|
||||
<name>src/Standard_Demo_Tasks</name>
|
||||
<type>9</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-include</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1390074074500</id>
|
||||
<name>src/FreeRTOS_Source/portable</name>
|
||||
|
@ -93,57 +75,21 @@
|
|||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1390228639904</id>
|
||||
<name>src/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<id>0</id>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks</name>
|
||||
<type>9</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-alt*.*</arguments>
|
||||
<arguments>1.0-name-matches-false-false-minimal</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1390228639904</id>
|
||||
<name>src/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<id>0</id>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks</name>
|
||||
<type>9</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-cr*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1390228639904</id>
|
||||
<name>src/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-sp*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1390228639904</id>
|
||||
<name>src/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-intqueue*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1390228639904</id>
|
||||
<name>src/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-*strings*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1390227918703</id>
|
||||
<name>src/Standard_Demo_Tasks/include</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-alt*.*</arguments>
|
||||
<arguments>1.0-name-matches-false-false-include</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
|
@ -164,6 +110,69 @@
|
|||
<arguments>1.0-name-matches-false-false-heap_4.c</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>0</id>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-alt*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>0</id>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-cr*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>0</id>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-sp*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>0</id>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-intqueue*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>0</id>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-*strings*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>0</id>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks/Minimal</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-copy*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>0</id>
|
||||
<name>src/Full_Demo/Standard_Demo_Tasks/include</name>
|
||||
<type>6</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-alt*.*</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
</filteredResources>
|
||||
<variableList>
|
||||
<variable>
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_TICK_HOOK 1
|
||||
#define configMAX_PRIORITIES ( 5 )
|
||||
#define configMAX_PRIORITIES ( 7 )
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 160 )
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 51200 ) )
|
||||
#define configMAX_TASK_NAME_LEN ( 10 )
|
||||
|
|
|
@ -150,11 +150,12 @@ const XScuGic_VectorTableEntry *pxVectorEntry;
|
|||
/* The ID of the interrupt is obtained by bitwise anding the ICCIAR value
|
||||
with 0x3FF. */
|
||||
ulInterruptID = ulICCIAR & 0x3FFUL;
|
||||
configASSERT( ulInterruptID < XSCUGIC_MAX_NUM_INTR_INPUTS );
|
||||
|
||||
if( ulInterruptID < XSCUGIC_MAX_NUM_INTR_INPUTS )
|
||||
{
|
||||
/* Call the function installed in the array of installed handler functions. */
|
||||
pxVectorEntry = &( pxVectorTable[ ulInterruptID ] );
|
||||
pxVectorEntry->Handler( pxVectorEntry->CallBackRef );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -139,7 +139,8 @@ static const UBaseType_t uxInterruptPriorities[ tmrTIMERS_USED ] =
|
|||
configMAX_API_CALL_INTERRUPT_PRIORITY + 1,
|
||||
configMAX_API_CALL_INTERRUPT_PRIORITY,
|
||||
configMAX_API_CALL_INTERRUPT_PRIORITY - 1
|
||||
}
|
||||
};
|
||||
|
||||
static XTtcPs xTimerInstances[ tmrTIMERS_USED ];
|
||||
|
||||
/* Used to provide a means of ensuring the intended interrupt nesting depth is
|
|
@ -74,6 +74,13 @@
|
|||
* full demo. Generic functions, such FreeRTOS hook functions, and functions
|
||||
* required to configure the hardware, are defined in main.c.
|
||||
*
|
||||
* NOTE 3: The full demo includes a test that checks the floating point context
|
||||
* is maintained correctly across task switches. The standard GCC libraries can
|
||||
* use floating point registers and made this test fail (unless the tasks that
|
||||
* use the library are given a floating point context as described on the
|
||||
* documentation page for this demo). printf-stdarg.c is included in this
|
||||
* project to prevent the standard GCC libraries being linked into the project.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* main_full() creates all the demo application tasks and software timers, then
|
||||
|
@ -84,22 +91,13 @@
|
|||
* In addition to the standard demo tasks, the following tasks and tests are
|
||||
* defined and/or created within this file:
|
||||
*
|
||||
* FreeRTOS+CLI command console. The command console is access through UART2
|
||||
* using 115200 baud if mainINCLUDE_FAT_SL_DEMO is set to 1. For reasons of
|
||||
* robustness testing the UART driver is deliberately written to be inefficient
|
||||
* and should not be used as a template for a production driver. Type "help" to
|
||||
* see a list of registered commands. The FreeRTOS+CLI license is different to
|
||||
* the FreeRTOS license, see http://www.FreeRTOS.org/cli for license and usage
|
||||
* details.
|
||||
*
|
||||
* FreeRTOS+FAT SL. FreeRTOS+FAT SL is demonstrated using a RAM disk if
|
||||
* mainINCLUDE_FAT_SL_DEMO is set to 1. [At the time of writing] The
|
||||
* functionality of the file system demo is identical to the functionality of
|
||||
* the FreeRTOS Win32 simulator file system demo, with the command console being
|
||||
* accessed via the UART (as described above) instead of a network terminal.
|
||||
* The FreeRTOS+FAT SL license is different to the FreeRTOS license, see
|
||||
* http://www.FreeRTOS.org/fat_sl for license and usage details, and a
|
||||
* description of the file system demo functionality.
|
||||
* FreeRTOS+CLI command console. The command console is access through the
|
||||
* UART to USB connector on the ZC702 Zynq development board (marked J2). For
|
||||
* reasons of robustness testing the UART driver is deliberately written to be
|
||||
* inefficient and should not be used as a template for a production driver.
|
||||
* Type "help" to see a list of registered commands. The FreeRTOS+CLI license
|
||||
* is different to the FreeRTOS license, see http://www.FreeRTOS.org/cli for
|
||||
* license and usage details. The default baud rate is 115200.
|
||||
*
|
||||
* "Reg test" tasks - These fill both the core and floating point registers with
|
||||
* known values, then check that each register maintains its expected value for
|
||||
|
@ -146,9 +144,6 @@
|
|||
#include "QueueOverwrite.h"
|
||||
#include "IntQueue.h"
|
||||
|
||||
/* FreeRTOS+CLI and FreeRTOS+FAT SL includes. */
|
||||
//#include "UARTCommandConsole.h"
|
||||
|
||||
/* Priorities for the demo application tasks. */
|
||||
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1UL )
|
||||
#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2UL )
|
||||
|
@ -168,20 +163,15 @@
|
|||
/* A block time of zero simply means "don't block". */
|
||||
#define mainDONT_BLOCK ( 0UL )
|
||||
|
||||
/* In this example the baud rate is hard coded and there is no LED for use by
|
||||
the COM test tasks, so just set both to invalid values. */
|
||||
#define mainCOM_TEST_LED ( 100 )
|
||||
#define mainBAUD_RATE ( 0 )
|
||||
|
||||
/* The period after which the check timer will expire, in ms, provided no errors
|
||||
have been reported by any of the standard demo tasks. ms are converted to the
|
||||
equivalent in ticks using the portTICK_RATE_MS constant. */
|
||||
#define mainNO_ERROR_CHECK_TASK_PERIOD ( 3000UL / portTICK_RATE_MS )
|
||||
equivalent in ticks using the portTICK_PERIOD_MS constant. */
|
||||
#define mainNO_ERROR_CHECK_TASK_PERIOD ( 3000UL / portTICK_PERIOD_MS )
|
||||
|
||||
/* The period at which the check timer will expire, in ms, if an error has been
|
||||
reported in one of the standard demo tasks. ms are converted to the equivalent
|
||||
in ticks using the portTICK_RATE_MS constant. */
|
||||
#define mainERROR_CHECK_TASK_PERIOD ( 200UL / portTICK_RATE_MS )
|
||||
in ticks using the portTICK_PERIOD_MS constant. */
|
||||
#define mainERROR_CHECK_TASK_PERIOD ( 200UL / portTICK_PERIOD_MS )
|
||||
|
||||
/* Parameters that are passed into the register check tasks solely for the
|
||||
purpose of ensuring parameters are passed into tasks correctly. */
|
||||
|
@ -191,12 +181,6 @@ purpose of ensuring parameters are passed into tasks correctly. */
|
|||
/* The base period used by the timer test tasks. */
|
||||
#define mainTIMER_TEST_PERIOD ( 50 )
|
||||
|
||||
/* The length of queues used to pass characters into and out of the UART
|
||||
interrupt. Note the comments above about the UART driver being implemented in
|
||||
this way to test the kernel robustness rather than to provide a template for an
|
||||
efficient production driver. */
|
||||
#define mainUART_QUEUE_LENGTHS 10
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
@ -236,16 +220,16 @@ extern void vUARTCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriori
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The following two variables are used to communicate the status of the
|
||||
register check tasks to the check software timer. If the variables keep
|
||||
incrementing, then the register check tasks has not discovered any errors. If
|
||||
a variable stops incrementing, then an error has been found. */
|
||||
register check tasks to the check task. If the variables keep incrementing,
|
||||
then the register check tasks has not discovered any errors. If a variable
|
||||
stops incrementing, then an error has been found. */
|
||||
volatile unsigned long ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void main_full( void )
|
||||
{
|
||||
/* Start all the other standard demo/test tasks. The have not particular
|
||||
/* Start all the other standard demo/test tasks. They have not particular
|
||||
functionality, but do demonstrate how to use the FreeRTOS API and test the
|
||||
kernel port. */
|
||||
vStartInterruptQueueTasks();
|
||||
|
@ -267,9 +251,7 @@ void main_full( void )
|
|||
/* Register the standard CLI commands. */
|
||||
vRegisterSampleCLICommands();
|
||||
|
||||
|
||||
/* Create the register check tasks, as described at the top of this
|
||||
file */
|
||||
/* Create the register check tasks, as described at the top of this file */
|
||||
xTaskCreate( prvRegTestTaskEntry1, "Reg1", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_1_PARAMETER, tskIDLE_PRIORITY, NULL );
|
||||
xTaskCreate( prvRegTestTaskEntry2, "Reg2", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL );
|
||||
|
|
@ -74,6 +74,13 @@
|
|||
* This file implements the code that is not demo specific, including the
|
||||
* hardware setup and FreeRTOS hook functions.
|
||||
*
|
||||
* NOTE: The full demo includes a test that checks the floating point context
|
||||
* is maintained correctly across task switches. The standard GCC libraries can
|
||||
* use floating point registers and made this test fail (unless the tasks that
|
||||
* use the library are given a floating point context as described on the
|
||||
* documentation page for this demo). printf-stdarg.c is included in this
|
||||
* project to prevent the standard GCC libraries being linked into the project.
|
||||
*
|
||||
* ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON
|
||||
* THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO
|
||||
* APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT!
|
||||
|
@ -128,6 +135,10 @@ void vApplicationIdleHook( void );
|
|||
void vApplicationStackOverflowHook( xTaskHandle pxTask, char *pcTaskName );
|
||||
void vApplicationTickHook( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The interrupt controller is initialised in this file, and made available to
|
||||
other modules. */
|
||||
XScuGic xInterruptController;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -149,6 +160,7 @@ int main( void )
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Don't expect to reach here. */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
293
FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/printf-stdarg.c
Normal file
293
FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/printf-stdarg.c
Normal file
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
Copyright 2001, 2002 Georges Menie (www.menie.org)
|
||||
stdarg version contributed by Christian Ettinger
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
putchar is the only external dependency for this file,
|
||||
if you have a working putchar, leave it commented out.
|
||||
If not, uncomment the define below and
|
||||
replace outbyte(c) by your own function call.
|
||||
|
||||
*/
|
||||
|
||||
#define putchar(c) c
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static void printchar(char **str, int c)
|
||||
{
|
||||
//extern int putchar(int c);
|
||||
|
||||
if (str) {
|
||||
**str = (char)c;
|
||||
++(*str);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)putchar(c);
|
||||
}
|
||||
}
|
||||
|
||||
#define PAD_RIGHT 1
|
||||
#define PAD_ZERO 2
|
||||
|
||||
static int prints(char **out, const char *string, int width, int pad)
|
||||
{
|
||||
register int pc = 0, padchar = ' ';
|
||||
|
||||
if (width > 0) {
|
||||
register int len = 0;
|
||||
register const char *ptr;
|
||||
for (ptr = string; *ptr; ++ptr) ++len;
|
||||
if (len >= width) width = 0;
|
||||
else width -= len;
|
||||
if (pad & PAD_ZERO) padchar = '0';
|
||||
}
|
||||
if (!(pad & PAD_RIGHT)) {
|
||||
for ( ; width > 0; --width) {
|
||||
printchar (out, padchar);
|
||||
++pc;
|
||||
}
|
||||
}
|
||||
for ( ; *string ; ++string) {
|
||||
printchar (out, *string);
|
||||
++pc;
|
||||
}
|
||||
for ( ; width > 0; --width) {
|
||||
printchar (out, padchar);
|
||||
++pc;
|
||||
}
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
/* the following should be enough for 32 bit int */
|
||||
#define PRINT_BUF_LEN 12
|
||||
|
||||
static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
|
||||
{
|
||||
char print_buf[PRINT_BUF_LEN];
|
||||
register char *s;
|
||||
register int t, neg = 0, pc = 0;
|
||||
register unsigned int u = (unsigned int)i;
|
||||
|
||||
if (i == 0) {
|
||||
print_buf[0] = '0';
|
||||
print_buf[1] = '\0';
|
||||
return prints (out, print_buf, width, pad);
|
||||
}
|
||||
|
||||
if (sg && b == 10 && i < 0) {
|
||||
neg = 1;
|
||||
u = (unsigned int)-i;
|
||||
}
|
||||
|
||||
s = print_buf + PRINT_BUF_LEN-1;
|
||||
*s = '\0';
|
||||
|
||||
while (u) {
|
||||
t = (unsigned int)u % b;
|
||||
if( t >= 10 )
|
||||
t += letbase - '0' - 10;
|
||||
*--s = (char)(t + '0');
|
||||
u /= b;
|
||||
}
|
||||
|
||||
if (neg) {
|
||||
if( width && (pad & PAD_ZERO) ) {
|
||||
printchar (out, '-');
|
||||
++pc;
|
||||
--width;
|
||||
}
|
||||
else {
|
||||
*--s = '-';
|
||||
}
|
||||
}
|
||||
|
||||
return pc + prints (out, s, width, pad);
|
||||
}
|
||||
|
||||
static int print( char **out, const char *format, va_list args )
|
||||
{
|
||||
register int width, pad;
|
||||
register int pc = 0;
|
||||
char scr[2];
|
||||
|
||||
for (; *format != 0; ++format) {
|
||||
if (*format == '%') {
|
||||
++format;
|
||||
width = pad = 0;
|
||||
if (*format == '\0') break;
|
||||
if (*format == '%') goto out;
|
||||
if (*format == '-') {
|
||||
++format;
|
||||
pad = PAD_RIGHT;
|
||||
}
|
||||
while (*format == '0') {
|
||||
++format;
|
||||
pad |= PAD_ZERO;
|
||||
}
|
||||
for ( ; *format >= '0' && *format <= '9'; ++format) {
|
||||
width *= 10;
|
||||
width += *format - '0';
|
||||
}
|
||||
if( *format == 's' ) {
|
||||
register char *s = (char *)va_arg( args, int );
|
||||
pc += prints (out, s?s:"(null)", width, pad);
|
||||
continue;
|
||||
}
|
||||
if( *format == 'd' ) {
|
||||
pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a');
|
||||
continue;
|
||||
}
|
||||
if( *format == 'x' ) {
|
||||
pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a');
|
||||
continue;
|
||||
}
|
||||
if( *format == 'X' ) {
|
||||
pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A');
|
||||
continue;
|
||||
}
|
||||
if( *format == 'u' ) {
|
||||
pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a');
|
||||
continue;
|
||||
}
|
||||
if( *format == 'c' ) {
|
||||
/* char are converted to int then pushed on the stack */
|
||||
scr[0] = (char)va_arg( args, int );
|
||||
scr[1] = '\0';
|
||||
pc += prints (out, scr, width, pad);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
out:
|
||||
printchar (out, *format);
|
||||
++pc;
|
||||
}
|
||||
}
|
||||
if (out) **out = '\0';
|
||||
va_end( args );
|
||||
return pc;
|
||||
}
|
||||
|
||||
int printf(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start( args, format );
|
||||
return print( 0, format, args );
|
||||
}
|
||||
|
||||
int sprintf(char *out, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start( args, format );
|
||||
return print( &out, format, args );
|
||||
}
|
||||
|
||||
|
||||
int snprintf( char *buf, unsigned int count, const char *format, ... )
|
||||
{
|
||||
va_list args;
|
||||
|
||||
( void ) count;
|
||||
|
||||
va_start( args, format );
|
||||
return print( &buf, format, args );
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST_PRINTF
|
||||
int main(void)
|
||||
{
|
||||
char *ptr = "Hello world!";
|
||||
char *np = 0;
|
||||
int i = 5;
|
||||
unsigned int bs = sizeof(int)*8;
|
||||
int mi;
|
||||
char buf[80];
|
||||
|
||||
mi = (1 << (bs-1)) + 1;
|
||||
printf("%s\n", ptr);
|
||||
printf("printf test\n");
|
||||
printf("%s is null pointer\n", np);
|
||||
printf("%d = 5\n", i);
|
||||
printf("%d = - max int\n", mi);
|
||||
printf("char %c = 'a'\n", 'a');
|
||||
printf("hex %x = ff\n", 0xff);
|
||||
printf("hex %02x = 00\n", 0);
|
||||
printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3);
|
||||
printf("%d %s(s)%", 0, "message");
|
||||
printf("\n");
|
||||
printf("%d %s(s) with %%\n", 0, "message");
|
||||
sprintf(buf, "justif: \"%-10s\"\n", "left"); printf("%s", buf);
|
||||
sprintf(buf, "justif: \"%10s\"\n", "right"); printf("%s", buf);
|
||||
sprintf(buf, " 3: %04d zero padded\n", 3); printf("%s", buf);
|
||||
sprintf(buf, " 3: %-4d left justif.\n", 3); printf("%s", buf);
|
||||
sprintf(buf, " 3: %4d right justif.\n", 3); printf("%s", buf);
|
||||
sprintf(buf, "-3: %04d zero padded\n", -3); printf("%s", buf);
|
||||
sprintf(buf, "-3: %-4d left justif.\n", -3); printf("%s", buf);
|
||||
sprintf(buf, "-3: %4d right justif.\n", -3); printf("%s", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* if you compile this file with
|
||||
* gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c
|
||||
* you will get a normal warning:
|
||||
* printf.c:214: warning: spurious trailing `%' in format
|
||||
* this line is testing an invalid % at the end of the format string.
|
||||
*
|
||||
* this should display (on 32bit int machine) :
|
||||
*
|
||||
* Hello world!
|
||||
* printf test
|
||||
* (null) is null pointer
|
||||
* 5 = 5
|
||||
* -2147483647 = - max int
|
||||
* char a = 'a'
|
||||
* hex ff = ff
|
||||
* hex 00 = 00
|
||||
* signed -3 = unsigned 4294967293 = hex fffffffd
|
||||
* 0 message(s)
|
||||
* 0 message(s) with %
|
||||
* justif: "left "
|
||||
* justif: " right"
|
||||
* 3: 0003 zero padded
|
||||
* 3: 3 left justif.
|
||||
* 3: 3 right justif.
|
||||
* -3: -003 zero padded
|
||||
* -3: -3 left justif.
|
||||
* -3: -3 right justif.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* To keep linker happy. */
|
||||
int write( int i, char* c, int n)
|
||||
{
|
||||
(void)i;
|
||||
(void)n;
|
||||
(void)c;
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in a new issue