├── .gitignore
├── LICENSE
├── README.md
├── SConstruct
├── coremark
├── README.md
├── SConscript
├── core_list_join.c
├── core_main.c
├── core_matrix.c
├── core_portme.c
├── core_portme.h
├── core_state.c
├── core_util.c
├── coremark.h
└── main.c
├── cxx
├── SConscript
├── crt
│ ├── SConscript
│ ├── crt.cpp
│ └── crt.h
├── cxx.cpp
├── cxx.h
└── main.c
├── devicetest
├── SConscript
├── device_test.c
└── main.c
├── hello
├── SConscript
└── main.c
├── lib
├── SConscript
└── lib.c
├── md5
├── SConscript
├── main.c
├── md5.c
└── md5.h
├── memperf
├── LICENSE
├── README.md
├── SConscript
├── main.c
├── mem_perf.c
├── portme.c
└── portme.h
├── tools
├── __init__.py
├── host
│ ├── building.py
│ └── rtthread
│ │ ├── SConscript
│ │ ├── finsh.h
│ │ ├── rthw.h
│ │ ├── rtthread.c
│ │ └── rtthread.h
├── ua.def
└── ua.py
└── ymodem
├── SConscript
├── tofile.c
├── ymodem.c
└── ymodem.h
/.gitignore:
--------------------------------------------------------------------------------
1 | # Object files
2 | *.o
3 | *.ko
4 | *.obj
5 | *.elf
6 | *.mo
7 | *.pyc
8 |
9 | # Precompiled Headers
10 | *.gch
11 | *.pch
12 |
13 | # Libraries
14 | *.lib
15 | *.a
16 | *.la
17 | *.lo
18 |
19 | # Shared objects (inc. Windows DLLs)
20 | *.dll
21 | *.so
22 | *.so.*
23 | *.dylib
24 |
25 | # Executables
26 | *.exe
27 | *.out
28 | *.app
29 | *.i*86
30 | *.x86_64
31 | *.hex
32 |
33 | .sconsign.dblite
34 |
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # The Applications of RT-Thread RTOS #
2 |
3 | ## Introduction ##
4 |
5 | The user application is the application layer of RT-Thread RTOS. The developer can
6 | develop his/her application out of RT-Thread RTOS firmware environment.
7 |
8 | There are two mode for RT-Thread Applications,
9 |
10 | * Standalone Application
11 | * Shared Library
12 |
13 | The standalone application has a main() function as the program entry. It more like
14 | a program in the PC/Linux.
15 |
16 | The shared library is compose of functions, and provide these APIs to other programs.
17 |
18 | ## Build Application ##
19 |
20 | First of all, these programs must base on RT-Thread RTOS environment, and run inside.
21 | In the RT-Thread RTOS, the module option must be enable in rtconfig.h File:
22 |
23 | #define RT_USING_MODULE
24 |
25 | And provide the flags for Application building in rtconfig.py file (since RT-Thread 2.1.x,
26 | these flags will be gradually added to each BSP):
27 |
28 | * M_CFLAGS - User Application C/C++ compiler flags
29 | * M_LFLAGS - User Application link flags
30 |
31 | And Provide the ENV variable `BSP_ROOT` which points to your board support package
32 | directory.
33 |
34 | Windows:
35 |
36 | set BSP_ROOT=your_bsp_directory
37 |
38 | Linux:
39 |
40 | export BSP_ROOT=your_bsp_directory
41 |
42 | And to run the command under your BSP directory:
43 |
44 | scons --target=ua -s
45 |
46 | To generate the information for User Application, such as the header file search path,
47 | the macro defined in the RT-Thread RTOS etc.
48 |
49 | Finally, you can build the user application in `rtthread-apps` directory, for example:
50 |
51 | scons --app=hello
52 |
53 | To build `hello` program.
54 |
55 | scons --lib=libtar
56 |
57 | To build a shared library.
58 |
59 | ## A Simple Application ##
60 |
61 | This is a simple application of `Hello World`:
62 |
63 | #include
64 |
65 | int main(int argc, char **argv)
66 | {
67 | printf("Hello World!\n");
68 | return 0;
69 | }
70 |
71 | It's just like the `Hello World` program in the PC/Linux. Beside that, the user
72 | application can use the most of APIs of RT-Thread, for example:
73 |
74 | #include
75 |
76 | void my_thread_entry(void* parameter)
77 | {
78 | int index;
79 |
80 | while (1)
81 | {
82 | rt_kprintf("index => %d\n", index ++);
83 | rt_thread_delay(RT_TICK_PER_SECOND);
84 | }
85 | }
86 |
87 | int my_thread_init(void)
88 | {
89 | rt_thread_t tid;
90 |
91 | tid = rt_thread_create("tMyTask', my_thread_entry, RT_NULL,
92 | 2048, 20, 20);
93 | if (tid != RT_NULL) rt_thread_startup(tid);
94 |
95 | return 0;
96 | }
97 |
98 | This example will create a sub-thread, which named as 'tMyTask'.
99 |
100 | ## Build the POSIX application in the host ##
101 |
102 | If you didn't set RTT_ROOT/BSP_ROOT, The command ```scons --app=hello``` will
103 | build the program in host environment, for example, build it as a Linux program.
104 |
105 | Therefore, only POSIX application can be built like that.
106 |
107 | ## License ##
108 |
109 | All of user application are standalone program, if there is no special explanation,
110 | the license of these program is [GPLv2](LICENSE). While the license of RT-Thread RTOS is GPLv2+.
111 |
--------------------------------------------------------------------------------
/SConstruct:
--------------------------------------------------------------------------------
1 | # File : SConstruct.py
2 | # Building Script for User Applications
3 | # This file is part of RT-Thread RTOS
4 | # COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team
5 | #
6 | # This program is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 2 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License along
17 | # with this program; if not, write to the Free Software Foundation, Inc.,
18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 | #
20 | # Change Logs:
21 | # Date Author Notes
22 | # 2015-02-07 Bernard The firstly version
23 | # 2018-04-15 Bernard Add the build option for library
24 | #
25 |
26 | import os
27 |
28 | from tools.ua import BuildApplication
29 | from tools.ua import BuildLibrary
30 |
31 | AddOption('--app',
32 | dest='app',
33 | nargs=1, type='string',
34 | action='store',
35 | metavar='DIR',
36 | help='application to be built')
37 |
38 | AddOption('--lib',
39 | dest='lib',
40 | nargs=1, type='string',
41 | action='store',
42 | metavar='DIR',
43 | help='library to be built')
44 |
45 | app = GetOption('app')
46 | lib = GetOption('lib')
47 |
48 | if app == None and lib == None:
49 | print("none application or library, please use ")
50 | print(" scons --app=your_app")
51 | print(" scons --lib=your_lib")
52 | exit(0)
53 |
54 | else:
55 | if app:
56 | BuildApplication(app + '/' + app + '.mo', app +'/SConscript')
57 |
58 | if lib:
59 | BuildLibrary(lib + '/' + lib + '.so', lib +'/SConscript')
60 |
--------------------------------------------------------------------------------
/coremark/README.md:
--------------------------------------------------------------------------------
1 | # Coremark
2 |
3 | RT-Thread 上的 MCU/CPU 性能测试小工具,在 menuconfig 里选中软件包后,在 msh 中输入:
4 |
5 | ```
6 | msh> core_mark
7 | ```
8 |
9 | 就可以看到跑分结果了,例如:
10 |
11 | ### STM32F103RC (72MHZ) ARMCC -O3 -Otime 跑分 135:
12 |
13 | ```
14 | \ | /
15 | - RT - Thread Operating System
16 | / | \ 4.0.2 build Oct 13 2019
17 | 2006 - 2019 Copyright by rt-thread team
18 | msh >
19 | msh >core_mark
20 | Benchmark started, please make sure it runs for at least 10s.
21 |
22 | 2K performance run parameters for coremark.
23 | CoreMark Size : 666
24 | Total ticks : 17776
25 | Total time (secs): 17.776000
26 | Iterations/Sec : 135.013501
27 | Iterations : 2400
28 | Compiler version : Please put compiler version here (e.g. gcc 4.1)
29 | Compiler flags :
30 | Memory location : STACK
31 | seedcrc : 0xe9f5
32 | [0]crclist : 0xe714
33 | [0]crcmatrix : 0x1fd7
34 | [0]crcstate : 0x8e3a
35 | [0]crcfinal : 0x382f
36 | Correct operation validated. See README.md for run and reporting rules.
37 | CoreMark 1.0 : 135.013501 / Please put compiler version here (e.g. gcc 4.1) / STACK
38 | ```
39 |
40 | ### GD32VF103 (108MHz) GCC -Os 跑分 327:
41 |
42 | ```
43 | \ | /
44 | - RT - Thread Operating System
45 | / | \ 4.0.2 build Oct 13 2019
46 | 2006 - 2019 Copyright by rt-thread team
47 | msh >
48 | msh >core_mark
49 | Benchmark started, please make sure it runs for at least 10s.
50 |
51 | 2K performance run parameters for coremark.
52 | CoreMark Size : 666
53 | Total ticks : 1178
54 | Total time (secs): 11
55 | Iterations/Sec : 327
56 | Iterations : 3600
57 | Compiler version : GCC8.2.0
58 | Compiler flags :
59 | Memory location : STACK
60 | seedcrc : 0xe9f5
61 | [0]crclist : 0xe714
62 | [0]crcmatrix : 0x1fd7
63 | [0]crcstate : 0x8e3a
64 | [0]crcfinal : 0x4bfc
65 | Correct operation validated. See README.md for run and reporting rules.
66 | CoreMark 1.0 : 327 / GCC8.2.0 / STACK
67 | ```
68 |
69 | 更多测试结果可以在这里看到:
70 |
71 | **https://www.eembc.org/coremark/scores.php**
72 |
73 | ## 注意事项
74 |
75 | - 如果结果希望以小数形式打印,默认会选择 libc 依赖
76 | - 测试程序需要运行至少 10s,如果 MCU 性能太强劲一下就结束了,可以适当增加迭代次数
77 |
78 | ---------------------------
79 |
80 | # Introduction
81 |
82 | CoreMark's primary goals are simplicity and providing a method for testing only a processor's core features. For more information about EEMBC's comprehensive embedded benchmark suites, please see www.eembc.org.
83 |
84 | For a more compute-intensive version of CoreMark that uses larger datasets and execution loops taken from common applications, please check out EEMBC's [CoreMark-PRO](https://www.github.com/eembc/coremark-pro) benchmark, also on GitHub.
85 |
86 | # Building and Running
87 |
88 | To build and run the benchmark, type
89 |
90 | `> make`
91 |
92 | Full results are available in the files `run1.log` and `run2.log`. CoreMark result can be found in `run1.log`.
93 |
94 | ## Cross Compiling
95 |
96 | For cross compile platforms please adjust `core_portme.mak`, `core_portme.h` (and possibly `core_portme.c`) according to the specific platform used. When porting to a new platform, it is recommended to copy one of the default port folders (e.g. `mkdir && cp linux/* `), adjust the porting files, and run:
97 | ~~~
98 | % make PORT_DIR=
99 | ~~~
100 |
101 | ## Make Targets
102 | `run` - Default target, creates `run1.log` and `run2.log`.
103 | `run1.log` - Run the benchmark with performance parameters, and output to `run1.log`
104 | `run2.log` - Run the benchmark with validation parameters, and output to `run2.log`
105 | `run3.log` - Run the benchmark with profile generation parameters, and output to `run3.log`
106 | `compile` - compile the benchmark executable
107 | `link` - link the benchmark executable
108 | `check` - test MD5 of sources that may not be modified
109 | `clean` - clean temporary files
110 |
111 | ### Make flag: `ITERATIONS`
112 | By default, the benchmark will run between 10-100 seconds. To override, use `ITERATIONS=N`
113 | ~~~
114 | % make ITERATIONS=10
115 | ~~~
116 | Will run the benchmark for 10 iterations. It is recommended to set a specific number of iterations in certain situations e.g.:
117 |
118 | * Running with a simulator
119 | * Measuring power/energy
120 | * Timing cannot be restarted
121 |
122 | Minimum required run time: **Results are only valid for reporting if the benchmark ran for at least 10 secs!**
123 |
124 | ### Make flag: `XCFLAGS`
125 | To add compiler flags from the command line, use `XCFLAGS` e.g.:
126 |
127 | ~~~
128 | % make XCFLAGS="-g -DMULTITHREAD=4 -DUSE_FORK=1"
129 | ~~~
130 |
131 | ### Make flag: `CORE_DEBUG`
132 |
133 | Define to compile for a debug run if you get incorrect CRC.
134 |
135 | ~~~
136 | % make XCFLAGS="-DCORE_DEBUG=1"
137 | ~~~
138 |
139 | ### Make flag: `REBUILD`
140 |
141 | Force a rebuild of the executable.
142 |
143 | ## Systems Without `make`
144 | The following files need to be compiled:
145 | * `core_list_join.c`
146 | * `core_main.c`
147 | * `core_matrix.c`
148 | * `core_state.c`
149 | * `core_util.c`
150 | * `PORT_DIR/core_portme.c`
151 |
152 | For example:
153 | ~~~
154 | % gcc -O2 -o coremark.exe core_list_join.c core_main.c core_matrix.c core_state.c core_util.c simple/core_portme.c -DPERFORMANCE_RUN=1 -DITERATIONS=1000
155 | % ./coremark.exe > run1.log
156 | ~~~
157 | The above will compile the benchmark for a performance run and 1000 iterations. Output is redirected to `run1.log`.
158 |
159 | # Parallel Execution
160 | Use `XCFLAGS=-DMULTITHREAD=N` where N is number of threads to run in parallel. Several implementations are available to execute in multiple contexts, or you can implement your own in `core_portme.c`.
161 |
162 | ~~~
163 | % make XCFLAGS="-DMULTITHREAD=4 -DUSE_PTHREAD"
164 | ~~~
165 |
166 | Above will compile the benchmark for execution on 4 cores, using POSIX Threads API.
167 |
168 | # Run Parameters for the Benchmark Executable
169 | CoreMark's executable takes several parameters as follows (but only if `main()` accepts arguments):
170 | 1st - A seed value used for initialization of data.
171 | 2nd - A seed value used for initialization of data.
172 | 3rd - A seed value used for initialization of data.
173 | 4th - Number of iterations (0 for auto : default value)
174 | 5th - Reserved for internal use.
175 | 6th - Reserved for internal use.
176 | 7th - For malloc users only, ovreride the size of the input data buffer.
177 |
178 | The run target from make will run coremark with 2 different data initialization seeds.
179 |
180 | ## Alternative parameters:
181 | If not using `malloc` or command line arguments are not supported, the buffer size
182 | for the algorithms must be defined via the compiler define `TOTAL_DATA_SIZE`.
183 | `TOTAL_DATA_SIZE` must be set to 2000 bytes (default) for standard runs.
184 | The default for such a target when testing different configurations could be:
185 |
186 | ~~~
187 | % make XCFLAGS="-DTOTAL_DATA_SIZE=6000 -DMAIN_HAS_NOARGC=1"
188 | ~~~
189 |
190 | # Submitting Results
191 |
192 | CoreMark results can be submitted on the web. Open a web browser and go to the [submission page](https://www.eembc.org/coremark/submit.php). After registering an account you may enter a score.
193 |
194 | # Run Rules
195 | What is and is not allowed.
196 |
197 | ## Required
198 | 1. The benchmark needs to run for at least 10 seconds.
199 | 2. All validation must succeed for seeds `0,0,0x66` and `0x3415,0x3415,0x66`, buffer size of 2000 bytes total.
200 | * If not using command line arguments to main:
201 | ~~~
202 | % make XCFLAGS="-DPERFORMANCE_RUN=1" REBUILD=1 run1.log
203 | % make XCFLAGS="-DVALIDATION_RUN=1" REBUILD=1 run2.log
204 | ~~~
205 | 3. If using profile guided optimization, profile must be generated using seeds of `8,8,8`, and buffer size of 1200 bytes total.
206 | ~~~
207 | % make XCFLAGS="-DTOTAL_DATA_SIZE=1200 -DPROFILE_RUN=1" REBUILD=1 run3.log
208 | ~~~
209 | 4. All source files must be compiled with the same flags.
210 | 5. All data type sizes must match size in bits such that:
211 | * `ee_u8` is an unsigned 8-bit datatype.
212 | * `ee_s16` is a signed 16-bit datatype.
213 | * `ee_u16` is an unsigned 16-bit datatype.
214 | * `ee_s32` is a signed 32-bit datatype.
215 | * `ee_u32` is an unsigned 32-bit datatype.
216 |
217 | ## Allowed
218 |
219 | 1. Changing number of iterations
220 | 2. Changing toolchain and build/load/run options
221 | 3. Changing method of acquiring a data memory block
222 | 5. Changing the method of acquiring seed values
223 | 6. Changing implementation `in core_portme.c`
224 | 7. Changing configuration values in `core_portme.h`
225 | 8. Changing `core_portme.mak`
226 |
227 | ## NOT ALLOWED
228 | 1. Changing of source file other then `core_portme*` (use `make check` to validate)
229 |
230 | # Reporting rules
231 | Use the following syntax to report results on a data sheet:
232 |
233 | CoreMark 1.0 : N / C [/ P] [/ M]
234 |
235 | N - Number of iterations per second with seeds 0,0,0x66,size=2000)
236 |
237 | C - Compiler version and flags
238 |
239 | P - Parameters such as data and code allocation specifics
240 |
241 | * This parameter *may* be omitted if all data was allocated on the heap in RAM.
242 | * This parameter *may not* be omitted when reporting CoreMark/MHz
243 |
244 | M - Type of parallel execution (if used) and number of contexts
245 | * This parameter may be omitted if parallel execution was not used.
246 |
247 | e.g.:
248 |
249 | ~~~
250 | CoreMark 1.0 : 128 / GCC 4.1.2 -O2 -fprofile-use / Heap in TCRAM / FORK:2
251 | ~~~
252 | or
253 | ~~~
254 | CoreMark 1.0 : 1400 / GCC 3.4 -O4
255 | ~~~
256 |
257 | If reporting scaling results, the results must be reported as follows:
258 |
259 | CoreMark/MHz 1.0 : N / C / P [/ M]
260 |
261 | P - When reporting scaling results, memory parameter must also indicate memory frequency:core frequency ratio.
262 | 1. If the core has cache and cache frequency to core frequency ratio is configurable, that must also be included.
263 |
264 | e.g.:
265 |
266 | ~~~
267 | CoreMark/MHz 1.0 : 1.47 / GCC 4.1.2 -O2 / DDR3(Heap) 30:1 Memory 1:1 Cache
268 | ~~~
269 |
270 | # Log File Format
271 | The log files have the following format
272 |
273 | ~~~
274 | 2K performance run parameters for coremark. (Run type)
275 | CoreMark Size : 666 (Buffer size)
276 | Total ticks : 25875 (platform dependent value)
277 | Total time (secs) : 25.875000 (actual time in seconds)
278 | Iterations/Sec : 3864.734300 (Performance value to report)
279 | Iterations : 100000 (number of iterations used)
280 | Compiler version : GCC3.4.4 (Compiler and version)
281 | Compiler flags : -O2 (Compiler and linker flags)
282 | Memory location : Code in flash, data in on chip RAM
283 | seedcrc : 0xe9f5 (identifier for the input seeds)
284 | [0]crclist : 0xe714 (validation for list part)
285 | [0]crcmatrix : 0x1fd7 (validation for matrix part)
286 | [0]crcstate : 0x8e3a (validation for state part)
287 | [0]crcfinal : 0x33ff (iteration dependent output)
288 | Correct operation validated. See README.md for run and reporting rules. (*Only when run is successful*)
289 | CoreMark 1.0 : 6508.490622 / GCC3.4.4 -O2 / Heap (*Only on a successful performance run*)
290 | ~~~
291 |
292 | # Theory of Operation
293 |
294 | This section describes the initial goals of CoreMark and their implementation.
295 |
296 | ## Small and easy to understand
297 |
298 | * X number of source code lines for timed portion of the benchmark.
299 | * Meaningful names for variables and functions.
300 | * Comments for each block of code more than 10 lines long.
301 |
302 | ## Portability
303 |
304 | A thin abstraction layer will be provided for I/O and timing in a separate file. All I/O and timing of the benchmark will be done through this layer.
305 |
306 | ### Code / data size
307 |
308 | * Compile with gcc on x86 and make sure all sizes are according to requirements.
309 | * If dynamic memory allocation is used, take total memory allocated into account as well.
310 | * Avoid recursive functions and keep track of stack usage.
311 | * Use the same memory block as data site for all algorithms, and initialize the data before each algorithm – while this means that initialization with data happens during the timed portion, it will only happen once during the timed portion and so have negligible effect on the results.
312 |
313 | ## Controlled output
314 |
315 | This may be the most difficult goal. Compilers are constantly improving and getting better at analyzing code. To create work that cannot be computed at compile time and must be computed at run time, we will rely on two assumptions:
316 |
317 | * Some system functions (e.g. time, scanf) and parameters cannot be computed at compile time. In most cases, marking a variable volatile means the compiler is force to read this variable every time it is read. This will be used to introduce a factor into the input that cannot be precomputed at compile time. Since the results are input dependent, that will make sure that computation has to happen at run time.
318 |
319 | * Either a system function or I/O (e.g. scanf) or command line parameters or volatile variables will be used before the timed portion to generate data which is not available at compile time. Specific method used is not relevant as long as it can be controlled, and that it cannot be computed or eliminated by the compiler at compile time. E.g. if the clock() functions is a compiler stub, it may not be used. The derived values will be reported on the output so that verification can be done on a different machine.
320 |
321 | * We cannot rely on command line parameters since some embedded systems do not have the capability to provide command line parameters. All 3 methods above will be implemented (time based, scanf and command line parameters) and all 3 are valid if the compiler cannot determine the value at compile time.
322 |
323 | * It is important to note that The actual values that are to be supplied at run time will be standardized. The methodology is not intended to provide random data, but simply to provide controlled data that cannot be precomputed at compile time.
324 |
325 | * Printed results must be valid at run time. This will be used to make sure the computation has been executed.
326 |
327 | * Some embedded systems do not provide “printf” or other I/O functionality. All I/O will be done through a thin abstraction interface to allow execution on such systems (e.g. allow output via JTAG).
328 |
329 | ## Key Algorithms
330 |
331 | ### Linked List
332 |
333 | The following linked list structure will be used:
334 |
335 | ~~~
336 | typedef struct list_data_s {
337 | ee_s16 data16;
338 | ee_s16 idx;
339 | } list_data;
340 |
341 | typedef struct list_head_s {
342 | struct list_head_s *next;
343 | struct list_data_s *info;
344 | } list_head;
345 | ~~~
346 |
347 | While adding a level of indirection accessing the data, this structure is realistic and used in many embedded applications for small to medium lists.
348 |
349 | The list itself will be initialized on a block of memory that will be passed in to the initialization function. While in general linked lists use malloc for new nodes, embedded applications sometime control the memory for small data structures such as arrays and lists directly to avoid the overhead of system calls, so this approach is realistic.
350 |
351 | The linked list will be initialized such that 1/4 of the list pointers point to sequential areas in memory, and 3/4 of the list pointers are distributed in a non sequential manner. This is done to emulate a linked list that had add/remove happen for a while disrupting the neat order, and then a series of adds that are likely to come from sequential memory locations.
352 |
353 | For the benchmark itself:
354 | - Multiple find operations are going to be performed. These find operations may result in the whole list being traversed. The result of each find will become part of the output chain.
355 | - The list will be sorted using merge sort based on the data16 value, and then derive CRC of the data16 item in order for part of the list. The CRC will become part of the output chain.
356 | - The list will be sorted again using merge sort based on the idx value. This sort will guarantee that the list is returned to the primary state before leaving the function, so that multiple iterations of the function will have the same result. CRC of the data16 for part of the list will again be calculated and become part of the output chain.
357 |
358 | The actual `data16` in each cell will be pseudo random based on a single 16b input that cannot be determined at compile time. In addition, the part of the list which is used for CRC will also be passed to the function, and determined based on an input that cannot be determined at run time.
359 |
360 | ### Matrix Multiply
361 |
362 | This very simple algorithm forms the basis of many more complex algorithms. The tight inner loop is the focus of many optimizations (compiler as well as hardware based) and is thus relevant for embedded processing.
363 |
364 | The total available data space will be divided to 3 parts:
365 | 1. NxN matrix A.
366 | 2. NxN matrix B.
367 | 3. NxN matrix C.
368 |
369 | E.g. for 2K we will have 3 12x12 matrices (assuming data type of 32b 12(len)*12(wid)*4(size)*3(num) =1728 bytes).
370 |
371 | Matrix A will be initialized with small values (upper 3/4 of the bits all zero).
372 | Matrix B will be initialized with medium values (upper half of the bits all zero).
373 | Matrix C will be used for the result.
374 |
375 | For the benchmark itself:
376 | - Multiple A by a constant into C, add the upper bits of each of the values in the result matrix. The result will become part of the output chain.
377 | - Multiple A by column X of B into C, add the upper bits of each of the values in the result matrix. The result will become part of the output chain.
378 | - Multiple A by B into C, add the upper bits of each of the values in the result matrix. The result will become part of the output chain.
379 |
380 | The actual values for A and B must be derived based on input that is not available at compile time.
381 |
382 | ### State Machine
383 |
384 | This part of the code needs to exercise switch and if statements. As such, we will use a small Moore state machine. In particular, this will be a state machine that identifies string input as numbers and divides them according to format.
385 |
386 | The state machine will parse the input string until either a “,” separator or end of input is encountered. An invalid number will cause the state machine to return invalid state and a valid number will cause the state machine to return with type of number format (int/float/scientific).
387 |
388 | This code will perform a realistic task, be small enough to easily understand, and exercise the required functionality. The other option used in embedded systems is a mealy based state machine, which is driven by a table. The table then determines the number of states and complexity of transitions. This approach, however, tests mainly the load/store and function call mechanisms and less the handling of branches. If analysis of the final results shows that the load/store functionality of the processor is not exercised thoroughly, it may be a good addition to the benchmark (codesize allowing).
389 |
390 | For input, the memory block will be initialized with comma separated values of mixed formats, as well as invalid inputs.
391 |
392 | For the benchmark itself:
393 | - Invoke the state machine on all of the input and count final states and state transitions. CRC of all final states and transitions will become part of the output chain.
394 | - Modify the input at intervals (inject errors) and repeat the state machine operation.
395 | - Modify the input back to original form.
396 |
397 | The actual input must be initialized based on data that cannot be determined at compile time. In addition the intervals for modification of the input and the actual modification must be based on input that cannot be determined at compile time.
398 |
399 | # Validation
400 |
401 | This release was tested on the following platforms:
402 | * x86 cygwin and gcc 3.4 (Quad, dual and single core systems)
403 | * x86 linux (Ubuntu/Fedora) and gcc (4.2/4.1) (Quad and single core systems)
404 | * MIPS64 BE linux and gcc 3.4 16 cores system
405 | * MIPS32 BE linux with CodeSourcery compiler 4.2-177 on Malta/Linux with a 1004K 3-core system
406 | * PPC simulator with gcc 4.2.2 (No OS)
407 | * PPC 64b BE linux (yellowdog) with gcc 3.4 and 4.1 (Dual core system)
408 | * BF533 with VDSP50
409 | * Renesas R8C/H8 MCU with HEW 4.05
410 | * NXP LPC1700 armcc v4.0.0.524
411 | * NEC 78K with IAR v4.61
412 | * ARM simulator with armcc v4
413 |
414 | # Memory Analysis
415 |
416 | Valgrind 3.4.0 used and no errors reported.
417 |
418 | # Balance Analysis
419 |
420 | Number of instructions executed for each function tested with cachegrind and found balanced with gcc and -O0.
421 |
422 | # Statistics
423 |
424 | Lines:
425 | ~~~
426 | Lines Blank Cmnts Source AESL
427 | ===== ===== ===== ===== ========== =======================================
428 | 469 66 170 251 627.5 core_list_join.c (C)
429 | 330 18 54 268 670.0 core_main.c (C)
430 | 256 32 80 146 365.0 core_matrix.c (C)
431 | 240 16 51 186 465.0 core_state.c (C)
432 | 165 11 20 134 335.0 core_util.c (C)
433 | 150 23 36 98 245.0 coremark.h (C)
434 | 1610 166 411 1083 2707.5 ----- Benchmark ----- (6 files)
435 | 293 15 74 212 530.0 linux/core_portme.c (C)
436 | 235 30 104 104 260.0 linux/core_portme.h (C)
437 | 528 45 178 316 790.0 ----- Porting ----- (2 files)
438 |
439 | * For comparison, here are the stats for Dhrystone
440 | Lines Blank Cmnts Source AESL
441 | ===== ===== ===== ===== ========== =======================================
442 | 311 15 242 54 135.0 dhry.h (C)
443 | 789 132 119 553 1382.5 dhry_1.c (C)
444 | 186 26 68 107 267.5 dhry_2.c (C)
445 | 1286 173 429 714 1785.0 ----- C ----- (3 files)
446 | ~~~
447 |
448 | # Credits
449 | Many thanks to all of the individuals who helped with the development or testing of CoreMark including (Sorted by company name; note that company names may no longer be accurate as this was written in 2009).
450 | * Alan Anderson, ADI
451 | * Adhikary Rajiv, ADI
452 | * Elena Stohr, ARM
453 | * Ian Rickards, ARM
454 | * Andrew Pickard, ARM
455 | * Trent Parker, CAVIUM
456 | * Shay Gal-On, EEMBC
457 | * Markus Levy, EEMBC
458 | * Peter Torelli, EEMBC
459 | * Ron Olson, IBM
460 | * Eyal Barzilay, MIPS
461 | * Jens Eltze, NEC
462 | * Hirohiko Ono, NEC
463 | * Ulrich Drees, NEC
464 | * Frank Roscheda, NEC
465 | * Rob Cosaro, NXP
466 | * Shumpei Kawasaki, RENESAS
467 |
468 | # Legal
469 | Please refer to LICENSE.md in this reposity for a description of your rights to use this code.
470 |
471 | # Copyright
472 | Copyright © 2009 EEMBC All rights reserved.
473 | CoreMark is a trademark of EEMBC and EEMBC is a registered trademark of the Embedded Microprocessor Benchmark Consortium.
474 |
475 |
--------------------------------------------------------------------------------
/coremark/SConscript:
--------------------------------------------------------------------------------
1 | from building import *
2 | import rtconfig
3 |
4 | # get current directory
5 | cwd = GetCurrentDir()
6 | # The set of source files associated with this SConscript file.
7 | src = Glob('*.c')
8 |
9 | path = [cwd + '/']
10 |
11 | LOCAL_CCFLAGS = ''
12 |
13 | group = DefineGroup('coremark', src, depend = [''], CPPPATH = path, LOCAL_CCFLAGS = LOCAL_CCFLAGS)
14 |
15 | Return('group')
16 |
--------------------------------------------------------------------------------
/coremark/core_list_join.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | Original Author: Shay Gal-on
17 | */
18 |
19 | #include "coremark.h"
20 | /*
21 | Topic: Description
22 | Benchmark using a linked list.
23 |
24 | Linked list is a common data structure used in many applications.
25 |
26 | For our purposes, this will excercise the memory units of the processor.
27 | In particular, usage of the list pointers to find and alter data.
28 |
29 | We are not using Malloc since some platforms do not support this library.
30 |
31 | Instead, the memory block being passed in is used to create a list,
32 | and the benchmark takes care not to add more items then can be
33 | accomodated by the memory block. The porting layer will make sure
34 | that we have a valid memory block.
35 |
36 | All operations are done in place, without using any extra memory.
37 |
38 | The list itself contains list pointers and pointers to data items.
39 | Data items contain the following:
40 |
41 | idx - An index that captures the initial order of the list.
42 | data - Variable data initialized based on the input parameters. The 16b are divided as follows:
43 | o Upper 8b are backup of original data.
44 | o Bit 7 indicates if the lower 7 bits are to be used as is or calculated.
45 | o Bits 0-2 indicate type of operation to perform to get a 7b value.
46 | o Bits 3-6 provide input for the operation.
47 |
48 | */
49 |
50 | /* local functions */
51 |
52 | list_head *core_list_find(list_head *list,list_data *info);
53 | list_head *core_list_reverse(list_head *list);
54 | list_head *core_list_remove(list_head *item);
55 | list_head *core_list_undo_remove(list_head *item_removed, list_head *item_modified);
56 | list_head *core_list_insert_new(list_head *insert_point
57 | , list_data *info, list_head **memblock, list_data **datablock
58 | , list_head *memblock_end, list_data *datablock_end);
59 | typedef ee_s32(*list_cmp)(list_data *a, list_data *b, core_results *res);
60 | list_head *core_list_mergesort(list_head *list, list_cmp cmp, core_results *res);
61 |
62 | ee_s16 calc_func(ee_s16 *pdata, core_results *res) {
63 | ee_s16 data=*pdata;
64 | ee_s16 retval;
65 | ee_u8 optype=(data>>7) & 1; /* bit 7 indicates if the function result has been cached */
66 | if (optype) /* if cached, use cache */
67 | return (data & 0x007f);
68 | else { /* otherwise calculate and cache the result */
69 | ee_s16 flag=data & 0x7; /* bits 0-2 is type of function to perform */
70 | ee_s16 dtype=((data>>3) & 0xf); /* bits 3-6 is specific data for the operation */
71 | dtype |= dtype << 4; /* replicate the lower 4 bits to get an 8b value */
72 | switch (flag) {
73 | case 0:
74 | if (dtype<0x22) /* set min period for bit corruption */
75 | dtype=0x22;
76 | retval=core_bench_state(res->size,res->memblock[3],res->seed1,res->seed2,dtype,res->crc);
77 | if (res->crcstate==0)
78 | res->crcstate=retval;
79 | break;
80 | case 1:
81 | retval=core_bench_matrix(&(res->mat),dtype,res->crc);
82 | if (res->crcmatrix==0)
83 | res->crcmatrix=retval;
84 | break;
85 | default:
86 | retval=data;
87 | break;
88 | }
89 | res->crc=crcu16(retval,res->crc);
90 | retval &= 0x007f;
91 | *pdata = (data & 0xff00) | 0x0080 | retval; /* cache the result */
92 | return retval;
93 | }
94 | }
95 | /* Function: cmp_complex
96 | Compare the data item in a list cell.
97 |
98 | Can be used by mergesort.
99 | */
100 | ee_s32 cmp_complex(list_data *a, list_data *b, core_results *res) {
101 | ee_s16 val1=calc_func(&(a->data16),res);
102 | ee_s16 val2=calc_func(&(b->data16),res);
103 | return val1 - val2;
104 | }
105 |
106 | /* Function: cmp_idx
107 | Compare the idx item in a list cell, and regen the data.
108 |
109 | Can be used by mergesort.
110 | */
111 | ee_s32 cmp_idx(list_data *a, list_data *b, core_results *res) {
112 | if (res==NULL) {
113 | a->data16 = (a->data16 & 0xff00) | (0x00ff & (a->data16>>8));
114 | b->data16 = (b->data16 & 0xff00) | (0x00ff & (b->data16>>8));
115 | }
116 | return a->idx - b->idx;
117 | }
118 |
119 | void copy_info(list_data *to,list_data *from) {
120 | to->data16=from->data16;
121 | to->idx=from->idx;
122 | }
123 |
124 | /* Benchmark for linked list:
125 | - Try to find multiple data items.
126 | - List sort
127 | - Operate on data from list (crc)
128 | - Single remove/reinsert
129 | * At the end of this function, the list is back to original state
130 | */
131 | ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx) {
132 | ee_u16 retval=0;
133 | ee_u16 found=0,missed=0;
134 | list_head *list=res->list;
135 | ee_s16 find_num=res->seed3;
136 | list_head *this_find;
137 | list_head *finder, *remover;
138 | list_data info;
139 | ee_s16 i;
140 |
141 | info.idx=finder_idx;
142 | /* find values in the list, and change the list each time (reverse and cache if value found) */
143 | for (i=0; inext->info->data16 >> 8) & 1;
150 | }
151 | else {
152 | found++;
153 | if (this_find->info->data16 & 0x1) /* use found value */
154 | retval+=(this_find->info->data16 >> 9) & 1;
155 | /* and cache next item at the head of the list (if any) */
156 | if (this_find->next != NULL) {
157 | finder = this_find->next;
158 | this_find->next = finder->next;
159 | finder->next=list->next;
160 | list->next=finder;
161 | }
162 | }
163 | if (info.idx>=0)
164 | info.idx++;
165 | #if CORE_DEBUG
166 | ee_printf("List find %d: [%d,%d,%d]\n",i,retval,missed,found);
167 | #endif
168 | }
169 | retval+=found*4-missed;
170 | /* sort the list by data content and remove one item*/
171 | if (finder_idx>0)
172 | list=core_list_mergesort(list,cmp_complex,res);
173 | remover=core_list_remove(list->next);
174 | /* CRC data content of list from location of index N forward, and then undo remove */
175 | finder=core_list_find(list,&info);
176 | if (!finder)
177 | finder=list->next;
178 | while (finder) {
179 | retval=crc16(list->info->data16,retval);
180 | finder=finder->next;
181 | }
182 | #if CORE_DEBUG
183 | ee_printf("List sort 1: %04x\n",retval);
184 | #endif
185 | remover=core_list_undo_remove(remover,list->next);
186 | /* sort the list by index, in effect returning the list to original state */
187 | list=core_list_mergesort(list,cmp_idx,NULL);
188 | /* CRC data content of list */
189 | finder=list->next;
190 | while (finder) {
191 | retval=crc16(list->info->data16,retval);
192 | finder=finder->next;
193 | }
194 | #if CORE_DEBUG
195 | ee_printf("List sort 2: %04x\n",retval);
196 | #endif
197 | return retval;
198 | }
199 | /* Function: core_list_init
200 | Initialize list with data.
201 |
202 | Parameters:
203 | blksize - Size of memory to be initialized.
204 | memblock - Pointer to memory block.
205 | seed - Actual values chosen depend on the seed parameter.
206 | The seed parameter MUST be supplied from a source that cannot be determined at compile time
207 |
208 | Returns:
209 | Pointer to the head of the list.
210 |
211 | */
212 | list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed) {
213 | /* calculated pointers for the list */
214 | ee_u32 per_item=16+sizeof(struct list_data_s);
215 | ee_u32 size=(blksize/per_item)-2; /* to accomodate systems with 64b pointers, and make sure same code is executed, set max list elements */
216 | list_head *memblock_end=memblock+size;
217 | list_data *datablock=(list_data *)(memblock_end);
218 | list_data *datablock_end=datablock+size;
219 | /* some useful variables */
220 | ee_u32 i;
221 | list_head *finder,*list=memblock;
222 | list_data info;
223 |
224 | /* create a fake items for the list head and tail */
225 | list->next=NULL;
226 | list->info=datablock;
227 | list->info->idx=0x0000;
228 | list->info->data16=(ee_s16)0x8080;
229 | memblock++;
230 | datablock++;
231 | info.idx=0x7fff;
232 | info.data16=(ee_s16)0xffff;
233 | core_list_insert_new(list,&info,&memblock,&datablock,memblock_end,datablock_end);
234 |
235 | /* then insert size items */
236 | for (i=0; inext;
244 | i=1;
245 | while (finder->next!=NULL) {
246 | if (iinfo->idx=i++;
248 | else {
249 | ee_u16 pat=(ee_u16)(i++ ^ seed); /* get a pseudo random number */
250 | finder->info->idx=0x3fff & (((i & 0x07) << 8) | pat); /* make sure the mixed items end up after the ones in sequence */
251 | }
252 | finder=finder->next;
253 | }
254 | list = core_list_mergesort(list,cmp_idx,NULL);
255 | #if CORE_DEBUG
256 | ee_printf("Initialized list:\n");
257 | finder=list;
258 | while (finder) {
259 | ee_printf("[%04x,%04x]",finder->info->idx,(ee_u16)finder->info->data16);
260 | finder=finder->next;
261 | }
262 | ee_printf("\n");
263 | #endif
264 | return list;
265 | }
266 |
267 | /* Function: core_list_insert
268 | Insert an item to the list
269 |
270 | Parameters:
271 | insert_point - where to insert the item.
272 | info - data for the cell.
273 | memblock - pointer for the list header
274 | datablock - pointer for the list data
275 | memblock_end - end of region for list headers
276 | datablock_end - end of region for list data
277 |
278 | Returns:
279 | Pointer to new item.
280 | */
281 | list_head *core_list_insert_new(list_head *insert_point, list_data *info, list_head **memblock, list_data **datablock
282 | , list_head *memblock_end, list_data *datablock_end) {
283 | list_head *newitem;
284 |
285 | if ((*memblock+1) >= memblock_end)
286 | return NULL;
287 | if ((*datablock+1) >= datablock_end)
288 | return NULL;
289 |
290 | newitem=*memblock;
291 | (*memblock)++;
292 | newitem->next=insert_point->next;
293 | insert_point->next=newitem;
294 |
295 | newitem->info=*datablock;
296 | (*datablock)++;
297 | copy_info(newitem->info,info);
298 |
299 | return newitem;
300 | }
301 |
302 | /* Function: core_list_remove
303 | Remove an item from the list.
304 |
305 | Operation:
306 | For a singly linked list, remove by copying the data from the next item
307 | over to the current cell, and unlinking the next item.
308 |
309 | Note:
310 | since there is always a fake item at the end of the list, no need to check for NULL.
311 |
312 | Returns:
313 | Removed item.
314 | */
315 | list_head *core_list_remove(list_head *item) {
316 | list_data *tmp;
317 | list_head *ret=item->next;
318 | /* swap data pointers */
319 | tmp=item->info;
320 | item->info=ret->info;
321 | ret->info=tmp;
322 | /* and eliminate item */
323 | item->next=item->next->next;
324 | ret->next=NULL;
325 | return ret;
326 | }
327 |
328 | /* Function: core_list_undo_remove
329 | Undo a remove operation.
330 |
331 | Operation:
332 | Since we want each iteration of the benchmark to be exactly the same,
333 | we need to be able to undo a remove.
334 | Link the removed item back into the list, and switch the info items.
335 |
336 | Parameters:
337 | item_removed - Return value from the
338 | item_modified - List item that was modified during
339 |
340 | Returns:
341 | The item that was linked back to the list.
342 |
343 | */
344 | list_head *core_list_undo_remove(list_head *item_removed, list_head *item_modified) {
345 | list_data *tmp;
346 | /* swap data pointers */
347 | tmp=item_removed->info;
348 | item_removed->info=item_modified->info;
349 | item_modified->info=tmp;
350 | /* and insert item */
351 | item_removed->next=item_modified->next;
352 | item_modified->next=item_removed;
353 | return item_removed;
354 | }
355 |
356 | /* Function: core_list_find
357 | Find an item in the list
358 |
359 | Operation:
360 | Find an item by idx (if not 0) or specific data value
361 |
362 | Parameters:
363 | list - list head
364 | info - idx or data to find
365 |
366 | Returns:
367 | Found item, or NULL if not found.
368 | */
369 | list_head *core_list_find(list_head *list,list_data *info) {
370 | if (info->idx>=0) {
371 | while (list && (list->info->idx != info->idx))
372 | list=list->next;
373 | return list;
374 | } else {
375 | while (list && ((list->info->data16 & 0xff) != info->data16))
376 | list=list->next;
377 | return list;
378 | }
379 | }
380 | /* Function: core_list_reverse
381 | Reverse a list
382 |
383 | Operation:
384 | Rearrange the pointers so the list is reversed.
385 |
386 | Parameters:
387 | list - list head
388 | info - idx or data to find
389 |
390 | Returns:
391 | Found item, or NULL if not found.
392 | */
393 |
394 | list_head *core_list_reverse(list_head *list) {
395 | list_head *next=NULL, *tmp;
396 | while (list) {
397 | tmp=list->next;
398 | list->next=next;
399 | next=list;
400 | list=tmp;
401 | }
402 | return next;
403 | }
404 | /* Function: core_list_mergesort
405 | Sort the list in place without recursion.
406 |
407 | Description:
408 | Use mergesort, as for linked list this is a realistic solution.
409 | Also, since this is aimed at embedded, care was taken to use iterative rather then recursive algorithm.
410 | The sort can either return the list to original order (by idx) ,
411 | or use the data item to invoke other other algorithms and change the order of the list.
412 |
413 | Parameters:
414 | list - list to be sorted.
415 | cmp - cmp function to use
416 |
417 | Returns:
418 | New head of the list.
419 |
420 | Note:
421 | We have a special header for the list that will always be first,
422 | but the algorithm could theoretically modify where the list starts.
423 |
424 | */
425 | list_head *core_list_mergesort(list_head *list, list_cmp cmp, core_results *res) {
426 | list_head *p, *q, *e, *tail;
427 | ee_s32 insize, nmerges, psize, qsize, i;
428 |
429 | insize = 1;
430 |
431 | while (1) {
432 | p = list;
433 | list = NULL;
434 | tail = NULL;
435 |
436 | nmerges = 0; /* count number of merges we do in this pass */
437 |
438 | while (p) {
439 | nmerges++; /* there exists a merge to be done */
440 | /* step `insize' places along from p */
441 | q = p;
442 | psize = 0;
443 | for (i = 0; i < insize; i++) {
444 | psize++;
445 | q = q->next;
446 | if (!q) break;
447 | }
448 |
449 | /* if q hasn't fallen off end, we have two lists to merge */
450 | qsize = insize;
451 |
452 | /* now we have two lists; merge them */
453 | while (psize > 0 || (qsize > 0 && q)) {
454 |
455 | /* decide whether next element of merge comes from p or q */
456 | if (psize == 0) {
457 | /* p is empty; e must come from q. */
458 | e = q; q = q->next; qsize--;
459 | } else if (qsize == 0 || !q) {
460 | /* q is empty; e must come from p. */
461 | e = p; p = p->next; psize--;
462 | } else if (cmp(p->info,q->info,res) <= 0) {
463 | /* First element of p is lower (or same); e must come from p. */
464 | e = p; p = p->next; psize--;
465 | } else {
466 | /* First element of q is lower; e must come from q. */
467 | e = q; q = q->next; qsize--;
468 | }
469 |
470 | /* add the next element to the merged list */
471 | if (tail) {
472 | tail->next = e;
473 | } else {
474 | list = e;
475 | }
476 | tail = e;
477 | }
478 |
479 | /* now p has stepped `insize' places along, and q has too */
480 | p = q;
481 | }
482 |
483 | tail->next = NULL;
484 |
485 | /* If we have done only one merge, we're finished. */
486 | if (nmerges <= 1) /* allow for nmerges==0, the empty list case */
487 | return list;
488 |
489 | /* Otherwise repeat, merging lists twice the size */
490 | insize *= 2;
491 | }
492 | #if COMPILER_REQUIRES_SORT_RETURN
493 | return list;
494 | #endif
495 | }
496 |
--------------------------------------------------------------------------------
/coremark/core_main.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | Original Author: Shay Gal-on
17 | */
18 |
19 | /* File: core_main.c
20 | This file contains the framework to acquire a block of memory, seed initial parameters, tun t he benchmark and report the results.
21 | */
22 | #include "coremark.h"
23 | #include
24 | /* Function: iterate
25 | Run the benchmark for a specified number of iterations.
26 |
27 | Operation:
28 | For each type of benchmarked algorithm:
29 | a - Initialize the data block for the algorithm.
30 | b - Execute the algorithm N times.
31 |
32 | Returns:
33 | NULL.
34 | */
35 | static ee_u16 list_known_crc[] = {(ee_u16)0xd4b0,(ee_u16)0x3340,(ee_u16)0x6a79,(ee_u16)0xe714,(ee_u16)0xe3c1};
36 | static ee_u16 matrix_known_crc[] = {(ee_u16)0xbe52,(ee_u16)0x1199,(ee_u16)0x5608,(ee_u16)0x1fd7,(ee_u16)0x0747};
37 | static ee_u16 state_known_crc[] = {(ee_u16)0x5e47,(ee_u16)0x39bf,(ee_u16)0xe5a4,(ee_u16)0x8e3a,(ee_u16)0x8d84};
38 | void *iterate(void *pres) {
39 | ee_u32 i;
40 | ee_u16 crc;
41 | core_results *res=(core_results *)pres;
42 | ee_u32 iterations=res->iterations;
43 | res->crc=0;
44 | res->crclist=0;
45 | res->crcmatrix=0;
46 | res->crcstate=0;
47 |
48 | for (i=0; icrc=crcu16(crc,res->crc);
51 | crc=core_bench_list(res,-1);
52 | res->crc=crcu16(crc,res->crc);
53 | if (i==0) res->crclist=res->crc;
54 | }
55 | return NULL;
56 | }
57 |
58 | #if (SEED_METHOD==SEED_ARG)
59 | ee_s32 get_seed_args(int i, int argc, char *argv[]);
60 | #define get_seed(x) (ee_s16)get_seed_args(x,argc,argv)
61 | #define get_seed_32(x) get_seed_args(x,argc,argv)
62 | #else /* via function or volatile */
63 | ee_s32 get_seed_32(int i);
64 | #define get_seed(x) (ee_s16)get_seed_32(x)
65 | #endif
66 |
67 | #if (MEM_METHOD==MEM_STATIC)
68 | ee_u8 static_memblk[TOTAL_DATA_SIZE];
69 | #endif
70 | char *mem_name[3] = {"Static","Heap","Stack"};
71 | /* Function: main
72 | Main entry routine for the benchmark.
73 | This function is responsible for the following steps:
74 |
75 | 1 - Initialize input seeds from a source that cannot be determined at compile time.
76 | 2 - Initialize memory block for use.
77 | 3 - Run and time the benchmark.
78 | 4 - Report results, testing the validity of the output if the seeds are known.
79 |
80 | Arguments:
81 | 1 - first seed : Any value
82 | 2 - second seed : Must be identical to first for iterations to be identical
83 | 3 - third seed : Any value, should be at least an order of magnitude less then the input size, but bigger then 32.
84 | 4 - Iterations : Special, if set to 0, iterations will be automatically determined such that the benchmark will run between 10 to 100 secs
85 |
86 | */
87 |
88 | #if MAIN_HAS_NOARGC
89 | MAIN_RETURN_TYPE core_mark(void) {
90 | int argc=0;
91 | char *argv[1];
92 | #else
93 | MAIN_RETURN_TYPE core_mark(int argc, char *argv[]) {
94 | #endif
95 | ee_u16 i,j=0,num_algorithms=0;
96 | ee_s16 known_id=-1,total_errors=0;
97 | ee_u16 seedcrc=0;
98 | CORE_TICKS total_time;
99 | core_results results[MULTITHREAD];
100 | #if (MEM_METHOD==MEM_STACK)
101 | ee_u8 stack_memblock[TOTAL_DATA_SIZE*MULTITHREAD];
102 | #endif
103 | /* first call any initializations needed */
104 | portable_init(&(results[0].port), &argc, argv);
105 | /* First some checks to make sure benchmark will run ok */
106 | if (sizeof(struct list_head_s)>128) {
107 | ee_printf("list_head structure too big for comparable data!\n");
108 | return MAIN_RETURN_VAL;
109 | }
110 | results[0].seed1=get_seed(1);
111 | results[0].seed2=get_seed(2);
112 | results[0].seed3=get_seed(3);
113 | results[0].iterations=get_seed_32(4);
114 | #if CORE_DEBUG
115 | results[0].iterations=1;
116 | #endif
117 | results[0].execs=get_seed_32(5);
118 | if (results[0].execs==0) { /* if not supplied, execute all algorithms */
119 | results[0].execs=ALL_ALGORITHMS_MASK;
120 | }
121 | /* put in some default values based on one seed only for easy testing */
122 | if ((results[0].seed1==0) && (results[0].seed2==0) && (results[0].seed3==0)) { /* validation run */
123 | results[0].seed1=0;
124 | results[0].seed2=0;
125 | results[0].seed3=0x66;
126 | }
127 | if ((results[0].seed1==1) && (results[0].seed2==0) && (results[0].seed3==0)) { /* perfromance run */
128 | results[0].seed1=0x3415;
129 | results[0].seed2=0x3415;
130 | results[0].seed3=0x66;
131 | }
132 | #if (MEM_METHOD==MEM_STATIC)
133 | results[0].memblock[0]=(void *)static_memblk;
134 | results[0].size=TOTAL_DATA_SIZE;
135 | results[0].err=0;
136 | #if (MULTITHREAD>1)
137 | #error "Cannot use a static data area with multiple contexts!"
138 | #endif
139 | #elif (MEM_METHOD==MEM_MALLOC)
140 | for (i=0 ; i1)
217 | if (default_num_contexts>MULTITHREAD) {
218 | default_num_contexts=MULTITHREAD;
219 | }
220 | for (i=0 ; i=0) {
265 | for (i=0 ; i 0)
292 | ee_printf("Iterations/Sec : %f\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
293 | #else
294 | ee_printf("Total time (secs): %d\n",time_in_secs(total_time));
295 | if (time_in_secs(total_time) > 0)
296 | ee_printf("Iterations/Sec : %d\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
297 | #endif
298 | if (time_in_secs(total_time) < 10) {
299 | ee_printf("ERROR! Must execute for at least 10 secs for a valid result!\n");
300 | total_errors++;
301 | }
302 |
303 | ee_printf("Iterations : %lu\n", (long unsigned) default_num_contexts*results[0].iterations);
304 | ee_printf("Compiler version : %s\n",COMPILER_VERSION);
305 | ee_printf("Compiler flags : %s\n",COMPILER_FLAGS);
306 | #if (MULTITHREAD>1)
307 | ee_printf("Parallel %s : %d\n",PARALLEL_METHOD,default_num_contexts);
308 | #endif
309 | ee_printf("Memory location : %s\n",MEM_LOCATION);
310 | /* output for verification */
311 | ee_printf("seedcrc : 0x%04x\n",seedcrc);
312 | if (results[0].execs & ID_LIST)
313 | for (i=0 ; i1)
335 | ee_printf(" / %d:%s",default_num_contexts,PARALLEL_METHOD);
336 | #endif
337 | ee_printf("\n");
338 | }
339 | #else
340 | if (known_id==3) {
341 | ee_printf("CoreMark 1.0 : %d / %s %s",default_num_contexts*results[0].iterations/time_in_secs(total_time),COMPILER_VERSION,COMPILER_FLAGS);
342 | #if defined(MEM_LOCATION) && !defined(MEM_LOCATION_UNSPEC)
343 | ee_printf(" / %s",MEM_LOCATION);
344 | #else
345 | ee_printf(" / %s",mem_name[MEM_METHOD]);
346 | #endif
347 |
348 | #if (MULTITHREAD>1)
349 | ee_printf(" / %d:%s",default_num_contexts,PARALLEL_METHOD);
350 | #endif
351 | ee_printf("\n");
352 | }
353 | #endif
354 | }
355 | if (total_errors>0)
356 | ee_printf("Errors detected\n");
357 | if (total_errors<0)
358 | ee_printf("Cannot validate operation for these seed values, please compare with results on a known platform.\n");
359 |
360 | #if (MEM_METHOD==MEM_MALLOC)
361 | for (i=0 ; i>(from)) & (~(0xffffffff << (to))))
48 |
49 | #if CORE_DEBUG
50 | void printmat(MATDAT *A, ee_u32 N, char *name) {
51 | ee_u32 i,j;
52 | ee_printf("Matrix %s [%dx%d]:\n",name,N,N);
53 | for (i=0; i N times,
79 | changing the matrix values slightly by a constant amount each time.
80 | */
81 | ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc) {
82 | ee_u32 N=p->N;
83 | MATRES *C=p->C;
84 | MATDAT *A=p->A;
85 | MATDAT *B=p->B;
86 | MATDAT val=(MATDAT)seed;
87 |
88 | crc=crc16(matrix_test(N,C,A,B,val),crc);
89 |
90 | return crc;
91 | }
92 |
93 | /* Function: matrix_test
94 | Perform matrix manipulation.
95 |
96 | Parameters:
97 | N - Dimensions of the matrix.
98 | C - memory for result matrix.
99 | A - input matrix
100 | B - operator matrix (not changed during operations)
101 |
102 | Returns:
103 | A CRC value that captures all results calculated in the function.
104 | In particular, crc of the value calculated on the result matrix
105 | after each step by .
106 |
107 | Operation:
108 |
109 | 1 - Add a constant value to all elements of a matrix.
110 | 2 - Multiply a matrix by a constant.
111 | 3 - Multiply a matrix by a vector.
112 | 4 - Multiply a matrix by a matrix.
113 | 5 - Add a constant value to all elements of a matrix.
114 |
115 | After the last step, matrix A is back to original contents.
116 | */
117 | ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val) {
118 | ee_u16 crc=0;
119 | MATDAT clipval=matrix_big(val);
120 |
121 | matrix_add_const(N,A,val); /* make sure data changes */
122 | #if CORE_DEBUG
123 | printmat(A,N,"matrix_add_const");
124 | #endif
125 | matrix_mul_const(N,C,A,val);
126 | crc=crc16(matrix_sum(N,C,clipval),crc);
127 | #if CORE_DEBUG
128 | printmatC(C,N,"matrix_mul_const");
129 | #endif
130 | matrix_mul_vect(N,C,A,B);
131 | crc=crc16(matrix_sum(N,C,clipval),crc);
132 | #if CORE_DEBUG
133 | printmatC(C,N,"matrix_mul_vect");
134 | #endif
135 | matrix_mul_matrix(N,C,A,B);
136 | crc=crc16(matrix_sum(N,C,clipval),crc);
137 | #if CORE_DEBUG
138 | printmatC(C,N,"matrix_mul_matrix");
139 | #endif
140 | matrix_mul_matrix_bitextract(N,C,A,B);
141 | crc=crc16(matrix_sum(N,C,clipval),crc);
142 | #if CORE_DEBUG
143 | printmatC(C,N,"matrix_mul_matrix_bitextract");
144 | #endif
145 |
146 | matrix_add_const(N,A,-val); /* return matrix to initial value */
147 | return crc;
148 | }
149 |
150 | /* Function : matrix_init
151 | Initialize the memory block for matrix benchmarking.
152 |
153 | Parameters:
154 | blksize - Size of memory to be initialized.
155 | memblk - Pointer to memory block.
156 | seed - Actual values chosen depend on the seed parameter.
157 | p - pointers to containing initialized matrixes.
158 |
159 | Returns:
160 | Matrix dimensions.
161 |
162 | Note:
163 | The seed parameter MUST be supplied from a source that cannot be determined at compile time
164 | */
165 | ee_u32 core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p) {
166 | ee_u32 N=0;
167 | MATDAT *A;
168 | MATDAT *B;
169 | ee_s32 order=1;
170 | MATDAT val;
171 | ee_u32 i=0,j=0;
172 | if (seed==0)
173 | seed=1;
174 | while (jA=A;
196 | p->B=B;
197 | p->C=(MATRES *)align_mem(B+N*N);
198 | p->N=N;
199 | #if CORE_DEBUG
200 | printmat(A,N,"A");
201 | printmat(B,N,"B");
202 | #endif
203 | return N;
204 | }
205 |
206 | /* Function: matrix_sum
207 | Calculate a function that depends on the values of elements in the matrix.
208 |
209 | For each element, accumulate into a temporary variable.
210 |
211 | As long as this value is under the parameter clipval,
212 | add 1 to the result if the element is bigger then the previous.
213 |
214 | Otherwise, reset the accumulator and add 10 to the result.
215 | */
216 | ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval) {
217 | MATRES tmp=0,prev=0,cur=0;
218 | ee_s16 ret=0;
219 | ee_u32 i,j;
220 | for (i=0; iclipval) {
225 | ret+=10;
226 | tmp=0;
227 | } else {
228 | ret += (cur>prev) ? 1 : 0;
229 | }
230 | prev=cur;
231 | }
232 | }
233 | return ret;
234 | }
235 |
236 | /* Function: matrix_mul_const
237 | Multiply a matrix by a constant.
238 | This could be used as a scaler for instance.
239 | */
240 | void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val) {
241 | ee_u32 i,j;
242 | for (i=0; i
20 | #include
21 | #include
22 | #include "coremark.h"
23 |
24 | #if VALIDATION_RUN
25 | volatile ee_s32 seed1_volatile=0x3415;
26 | volatile ee_s32 seed2_volatile=0x3415;
27 | volatile ee_s32 seed3_volatile=0x66;
28 | #endif
29 | #if PERFORMANCE_RUN
30 | volatile ee_s32 seed1_volatile=0x0;
31 | volatile ee_s32 seed2_volatile=0x0;
32 | volatile ee_s32 seed3_volatile=0x66;
33 | #endif
34 | #if PROFILE_RUN
35 | volatile ee_s32 seed1_volatile=0x8;
36 | volatile ee_s32 seed2_volatile=0x8;
37 | volatile ee_s32 seed3_volatile=0x8;
38 | #endif
39 | volatile ee_s32 seed4_volatile=ITERATIONS;
40 | volatile ee_s32 seed5_volatile=0;
41 | /* Porting : Timing functions
42 | How to capture time and convert to seconds must be ported to whatever is supported by the platform.
43 | e.g. Read value from on board RTC, read value from cpu clock cycles performance counter etc.
44 | Sample implementation for standard time.h and windows.h definitions included.
45 | */
46 | /* Define : TIMER_RES_DIVIDER
47 | Divider to trade off timer resolution and total time that can be measured.
48 |
49 | Use lower values to increase resolution, but make sure that overflow does not occur.
50 | If there are issues with the return value overflowing, increase this value.
51 | */
52 | #define NSECS_PER_SEC RT_TICK_PER_SECOND
53 | #define CORETIMETYPE rt_tick_t
54 | #define GETMYTIME(_t) (*_t=rt_tick_get())
55 | #define MYTIMEDIFF(fin,ini) ((fin)-(ini))
56 | #define TIMER_RES_DIVIDER 1
57 | #define SAMPLE_TIME_IMPLEMENTATION 1
58 | #define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER)
59 |
60 | /** Define Host specific (POSIX), or target specific global time variables. */
61 | static CORETIMETYPE start_time_val, stop_time_val;
62 |
63 | /* Function : start_time
64 | This function will be called right before starting the timed portion of the benchmark.
65 |
66 | Implementation may be capturing a system timer (as implemented in the example code)
67 | or zeroing some system parameters - e.g. setting the cpu clocks cycles to 0.
68 | */
69 | void start_time(void) {
70 | GETMYTIME(&start_time_val );
71 | }
72 | /* Function : stop_time
73 | This function will be called right after ending the timed portion of the benchmark.
74 |
75 | Implementation may be capturing a system timer (as implemented in the example code)
76 | or other system parameters - e.g. reading the current value of cpu cycles counter.
77 | */
78 | void stop_time(void) {
79 | GETMYTIME(&stop_time_val );
80 | }
81 | /* Function : get_time
82 | Return an abstract "ticks" number that signifies time on the system.
83 |
84 | Actual value returned may be cpu cycles, milliseconds or any other value,
85 | as long as it can be converted to seconds by .
86 | This methodology is taken to accomodate any hardware or simulated platform.
87 | The sample implementation returns millisecs by default,
88 | and the resolution is controlled by
89 | */
90 | CORE_TICKS get_time(void) {
91 | CORE_TICKS elapsed=(CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
92 | return elapsed;
93 | }
94 | /* Function : time_in_secs
95 | Convert the value returned by get_time to seconds.
96 |
97 | The type is used to accomodate systems with no support for floating point.
98 | Default implementation implemented by the EE_TICKS_PER_SEC macro above.
99 | */
100 | secs_ret time_in_secs(CORE_TICKS ticks) {
101 | secs_ret retval=((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
102 | return retval;
103 | }
104 |
105 | ee_u32 default_num_contexts=MULTITHREAD;
106 |
107 | /* Function : portable_init
108 | Target specific initialization code
109 | Test for some common mistakes.
110 | */
111 | void portable_init(core_portable *p, int *argc, char *argv[])
112 | {
113 | ee_printf("Benchmark started, please make sure it runs for at least 10s.\n\n");
114 | if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) {
115 | ee_printf("ERROR! Please define ee_ptr_int to a type that holds a pointer!\n");
116 | }
117 | if (sizeof(ee_u32) != 4) {
118 | ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
119 | }
120 | p->portable_id=1;
121 | }
122 | /* Function : portable_fini
123 | Target specific final code
124 | */
125 | void portable_fini(core_portable *p)
126 | {
127 | p->portable_id=0;
128 | }
129 |
130 | #if USE_PTHREAD
131 | ee_u8
132 | core_start_parallel(core_results *res)
133 | {
134 | return (ee_u8)pthread_create(
135 | &(res->port.thread), NULL, iterate, (void *)res);
136 | }
137 | ee_u8
138 | core_stop_parallel(core_results *res)
139 | {
140 | void *retval;
141 | return (ee_u8)pthread_join(res->port.thread, &retval);
142 | }
143 | #endif
144 |
--------------------------------------------------------------------------------
/coremark/core_portme.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | Original Author: Shay Gal-on
17 | */
18 |
19 | /* Topic : Description
20 | This file contains configuration constants required to execute on different platforms
21 | */
22 | #ifndef CORE_PORTME_H
23 | #define CORE_PORTME_H
24 |
25 | #include
26 |
27 | #define COREMARK_ITERATIONS 36000
28 | #define ITERATIONS COREMARK_ITERATIONS
29 |
30 | /************************/
31 | /* Data types and settings */
32 | /************************/
33 | /* Configuration : HAS_FLOAT
34 | Define to 1 if the platform supports floating point.
35 | */
36 | #ifndef HAS_FLOAT
37 | #define HAS_FLOAT CORE_MARK_HAS_FLOAT
38 | #endif
39 | /* Configuration : HAS_TIME_H
40 | Define to 1 if platform has the time.h header file,
41 | and implementation of functions thereof.
42 | */
43 | #ifndef HAS_TIME_H
44 | #define HAS_TIME_H 1
45 | #endif
46 | /* Configuration : USE_CLOCK
47 | Define to 1 if platform has the time.h header file,
48 | and implementation of functions thereof.
49 | */
50 | #ifndef USE_CLOCK
51 | #define USE_CLOCK 1
52 | #endif
53 | /* Configuration : HAS_STDIO
54 | Define to 1 if the platform has stdio.h.
55 | */
56 | #ifndef HAS_STDIO
57 | #define HAS_STDIO 1
58 | #endif
59 | /* Configuration : HAS_PRINTF
60 | Define to 1 if the platform has stdio.h and implements the printf function.
61 | */
62 | #ifndef HAS_PRINTF
63 | #define HAS_PRINTF 1
64 | #endif
65 |
66 | /* Configuration : CORE_TICKS
67 | Define type of return from the timing functions.
68 | */
69 | #include
70 | typedef clock_t CORE_TICKS;
71 |
72 | /* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION
73 | Initialize these strings per platform
74 | */
75 | #ifndef COMPILER_VERSION
76 | #ifdef __GNUC__
77 | #define COMPILER_VERSION "GCC"__VERSION__
78 | #else
79 | #define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)"
80 | #endif
81 | #endif
82 | #ifndef COMPILER_FLAGS
83 | #define COMPILER_FLAGS "" /* "Please put compiler flags here (e.g. -o3)" */
84 | #endif
85 | #ifndef MEM_LOCATION
86 | #define MEM_LOCATION "STACK"
87 | #endif
88 |
89 | /* Data Types :
90 | To avoid compiler issues, define the data types that need ot be used for 8b, 16b and 32b in .
91 |
92 | *Imprtant* :
93 | ee_ptr_int needs to be the data type used to hold pointers, otherwise coremark may fail!!!
94 | */
95 | typedef signed short ee_s16;
96 | typedef unsigned short ee_u16;
97 | typedef signed int ee_s32;
98 | typedef double ee_f32;
99 | typedef unsigned char ee_u8;
100 | typedef unsigned int ee_u32;
101 | typedef ee_u32 ee_ptr_int;
102 | typedef size_t ee_size_t;
103 | /* align_mem :
104 | This macro is used to align an offset to point to a 32b value. It is used in the Matrix algorithm to initialize the input memory blocks.
105 | */
106 | #define align_mem(x) (void *)(4 + (((ee_ptr_int)(x) - 1) & ~3))
107 |
108 | /* Configuration : SEED_METHOD
109 | Defines method to get seed values that cannot be computed at compile time.
110 |
111 | Valid values :
112 | SEED_ARG - from command line.
113 | SEED_FUNC - from a system function.
114 | SEED_VOLATILE - from volatile variables.
115 | */
116 | #ifndef SEED_METHOD
117 | #define SEED_METHOD SEED_VOLATILE
118 | #endif
119 |
120 | /* Configuration : MEM_METHOD
121 | Defines method to get a block of memry.
122 |
123 | Valid values :
124 | MEM_MALLOC - for platforms that implement malloc and have malloc.h.
125 | MEM_STATIC - to use a static memory array.
126 | MEM_STACK - to allocate the data block on the stack (NYI).
127 | */
128 | #ifndef MEM_METHOD
129 | #define MEM_METHOD MEM_STACK
130 | #endif
131 |
132 | /* Configuration : MULTITHREAD
133 | Define for parallel execution
134 |
135 | Valid values :
136 | 1 - only one context (default).
137 | N>1 - will execute N copies in parallel.
138 |
139 | Note :
140 | If this flag is defined to more then 1, an implementation for launching parallel contexts must be defined.
141 |
142 | Two sample implementations are provided. Use or to enable them.
143 |
144 | It is valid to have a different implementation of and in ,
145 | to fit a particular architecture.
146 | */
147 | #ifndef MULTITHREAD
148 | #define MULTITHREAD 1
149 | #define USE_PTHREAD 0
150 | #define USE_FORK 0
151 | #define USE_SOCKET 0
152 | #endif
153 |
154 | /* Configuration : MAIN_HAS_NOARGC
155 | Needed if platform does not support getting arguments to main.
156 |
157 | Valid values :
158 | 0 - argc/argv to main is supported
159 | 1 - argc/argv to main is not supported
160 |
161 | Note :
162 | This flag only matters if MULTITHREAD has been defined to a value greater then 1.
163 | */
164 | #ifndef MAIN_HAS_NOARGC
165 | #define MAIN_HAS_NOARGC 1
166 | #endif
167 |
168 | /* Configuration : MAIN_HAS_NORETURN
169 | Needed if platform does not support returning a value from main.
170 |
171 | Valid values :
172 | 0 - main returns an int, and return value will be 0.
173 | 1 - platform does not support returning a value from main
174 | */
175 | #ifndef MAIN_HAS_NORETURN
176 | #define MAIN_HAS_NORETURN 0
177 | #endif
178 |
179 | /* Variable : default_num_contexts
180 | Not used for this simple port, must cintain the value 1.
181 | */
182 | extern ee_u32 default_num_contexts;
183 |
184 | #if (MULTITHREAD > 1)
185 | #if USE_PTHREAD
186 | #include
187 | #define PARALLEL_METHOD "PThreads"
188 | #endif /* USE_PTHREAD */
189 | #endif /* MULTITHREAD > 1 */
190 |
191 | typedef struct CORE_PORTABLE_S {
192 | #if (MULTITHREAD > 1)
193 | #if USE_PTHREAD
194 | pthread_t thread;
195 | #endif /* Method for multithreading */
196 | #endif /* MULTITHREAD>1 */
197 | ee_u8 portable_id;
198 | } core_portable;
199 |
200 | /* target specific init/fini */
201 | void portable_init(core_portable *p, int *argc, char *argv[]);
202 | void portable_fini(core_portable *p);
203 |
204 | #if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) && !defined(VALIDATION_RUN)
205 | #if (TOTAL_DATA_SIZE==1200)
206 | #define PROFILE_RUN 1
207 | #elif (TOTAL_DATA_SIZE==2000)
208 | #define PERFORMANCE_RUN 1
209 | #else
210 | #define VALIDATION_RUN 1
211 | #endif
212 | #endif
213 |
214 | #if (MULTITHREAD > 1)
215 | #if USE_PTHREAD
216 | #include
217 | #define PARALLEL_METHOD "PThreads"
218 | #endif /* Method for multithreading */
219 | #endif /* MULTITHREAD > 1 */
220 |
221 | #endif /* CORE_PORTME_H */
222 |
--------------------------------------------------------------------------------
/coremark/core_state.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | Original Author: Shay Gal-on
17 | */
18 |
19 | #include "coremark.h"
20 | /* local functions */
21 | enum CORE_STATE core_state_transition( ee_u8 **instr , ee_u32 *transition_count);
22 |
23 | /*
24 | Topic: Description
25 | Simple state machines like this one are used in many embedded products.
26 |
27 | For more complex state machines, sometimes a state transition table implementation is used instead,
28 | trading speed of direct coding for ease of maintenance.
29 |
30 | Since the main goal of using a state machine in CoreMark is to excercise the switch/if behaviour,
31 | we are using a small moore machine.
32 |
33 | In particular, this machine tests type of string input,
34 | trying to determine whether the input is a number or something else.
35 | (see core_state.png).
36 | */
37 |
38 | /* Function: core_bench_state
39 | Benchmark function
40 |
41 | Go over the input twice, once direct, and once after introducing some corruption.
42 | */
43 | ee_u16 core_bench_state(ee_u32 blksize, ee_u8 *memblock,
44 | ee_s16 seed1, ee_s16 seed2, ee_s16 step, ee_u16 crc)
45 | {
46 | ee_u32 final_counts[NUM_CORE_STATES];
47 | ee_u32 track_counts[NUM_CORE_STATES];
48 | ee_u8 *p=memblock;
49 | ee_u32 i;
50 |
51 |
52 | #if CORE_DEBUG
53 | ee_printf("State Bench: %d,%d,%d,%04x\n",seed1,seed2,step,crc);
54 | #endif
55 | for (i=0; i0) {
127 | for(i=0;i>3) & 0x3];
138 | next=4;
139 | break;
140 | case 3: /* float */
141 | case 4: /* float */
142 | buf=floatpat[(seed>>3) & 0x3];
143 | next=8;
144 | break;
145 | case 5: /* scientific */
146 | case 6: /* scientific */
147 | buf=scipat[(seed>>3) & 0x3];
148 | next=8;
149 | break;
150 | case 7: /* invalid */
151 | buf=errpat[(seed>>3) & 0x3];
152 | next=8;
153 | break;
154 | default: /* Never happen, just to make some compilers happy */
155 | break;
156 | }
157 | }
158 | size++;
159 | while (total='0') & (c<='9')) ? 1 : 0;
171 | return retval;
172 | }
173 |
174 | /* Function: core_state_transition
175 | Actual state machine.
176 |
177 | The state machine will continue scanning until either:
178 | 1 - an invalid input is detcted.
179 | 2 - a valid number has been detected.
180 |
181 | The input pointer is updated to point to the end of the token, and the end state is returned (either specific format determined or invalid).
182 | */
183 |
184 | enum CORE_STATE core_state_transition( ee_u8 **instr , ee_u32 *transition_count) {
185 | ee_u8 *str=*instr;
186 | ee_u8 NEXT_SYMBOL;
187 | enum CORE_STATE state=CORE_START;
188 | for( ; *str && state != CORE_INVALID; str++ ) {
189 | NEXT_SYMBOL = *str;
190 | if (NEXT_SYMBOL==',') /* end of this input */ {
191 | str++;
192 | break;
193 | }
194 | switch(state) {
195 | case CORE_START:
196 | if(ee_isdigit(NEXT_SYMBOL)) {
197 | state = CORE_INT;
198 | }
199 | else if( NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-' ) {
200 | state = CORE_S1;
201 | }
202 | else if( NEXT_SYMBOL == '.' ) {
203 | state = CORE_FLOAT;
204 | }
205 | else {
206 | state = CORE_INVALID;
207 | transition_count[CORE_INVALID]++;
208 | }
209 | transition_count[CORE_START]++;
210 | break;
211 | case CORE_S1:
212 | if(ee_isdigit(NEXT_SYMBOL)) {
213 | state = CORE_INT;
214 | transition_count[CORE_S1]++;
215 | }
216 | else if( NEXT_SYMBOL == '.' ) {
217 | state = CORE_FLOAT;
218 | transition_count[CORE_S1]++;
219 | }
220 | else {
221 | state = CORE_INVALID;
222 | transition_count[CORE_S1]++;
223 | }
224 | break;
225 | case CORE_INT:
226 | if( NEXT_SYMBOL == '.' ) {
227 | state = CORE_FLOAT;
228 | transition_count[CORE_INT]++;
229 | }
230 | else if(!ee_isdigit(NEXT_SYMBOL)) {
231 | state = CORE_INVALID;
232 | transition_count[CORE_INT]++;
233 | }
234 | break;
235 | case CORE_FLOAT:
236 | if( NEXT_SYMBOL == 'E' || NEXT_SYMBOL == 'e' ) {
237 | state = CORE_S2;
238 | transition_count[CORE_FLOAT]++;
239 | }
240 | else if(!ee_isdigit(NEXT_SYMBOL)) {
241 | state = CORE_INVALID;
242 | transition_count[CORE_FLOAT]++;
243 | }
244 | break;
245 | case CORE_S2:
246 | if( NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-' ) {
247 | state = CORE_EXPONENT;
248 | transition_count[CORE_S2]++;
249 | }
250 | else {
251 | state = CORE_INVALID;
252 | transition_count[CORE_S2]++;
253 | }
254 | break;
255 | case CORE_EXPONENT:
256 | if(ee_isdigit(NEXT_SYMBOL)) {
257 | state = CORE_SCIENTIFIC;
258 | transition_count[CORE_EXPONENT]++;
259 | }
260 | else {
261 | state = CORE_INVALID;
262 | transition_count[CORE_EXPONENT]++;
263 | }
264 | break;
265 | case CORE_SCIENTIFIC:
266 | if(!ee_isdigit(NEXT_SYMBOL)) {
267 | state = CORE_INVALID;
268 | transition_count[CORE_INVALID]++;
269 | }
270 | break;
271 | default:
272 | break;
273 | }
274 | }
275 | *instr=str;
276 | return state;
277 | }
278 |
--------------------------------------------------------------------------------
/coremark/core_util.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | Original Author: Shay Gal-on
17 | */
18 |
19 | #include "coremark.h"
20 | /* Function: get_seed
21 | Get a values that cannot be determined at compile time.
22 |
23 | Since different embedded systems and compilers are used, 3 different methods are provided:
24 | 1 - Using a volatile variable. This method is only valid if the compiler is forced to generate code that
25 | reads the value of a volatile variable from memory at run time.
26 | Please note, if using this method, you would need to modify core_portme.c to generate training profile.
27 | 2 - Command line arguments. This is the preferred method if command line arguments are supported.
28 | 3 - System function. If none of the first 2 methods is available on the platform,
29 | a system function which is not a stub can be used.
30 |
31 | e.g. read the value on GPIO pins connected to switches, or invoke special simulator functions.
32 | */
33 | #if (SEED_METHOD==SEED_VOLATILE)
34 | extern volatile ee_s32 seed1_volatile;
35 | extern volatile ee_s32 seed2_volatile;
36 | extern volatile ee_s32 seed3_volatile;
37 | extern volatile ee_s32 seed4_volatile;
38 | extern volatile ee_s32 seed5_volatile;
39 | ee_s32 get_seed_32(int i) {
40 | ee_s32 retval;
41 | switch (i) {
42 | case 1:
43 | retval=seed1_volatile;
44 | break;
45 | case 2:
46 | retval=seed2_volatile;
47 | break;
48 | case 3:
49 | retval=seed3_volatile;
50 | break;
51 | case 4:
52 | retval=seed4_volatile;
53 | break;
54 | case 5:
55 | retval=seed5_volatile;
56 | break;
57 | default:
58 | retval=0;
59 | break;
60 | }
61 | return retval;
62 | }
63 | #elif (SEED_METHOD==SEED_ARG)
64 | ee_s32 parseval(char *valstring) {
65 | ee_s32 retval=0;
66 | ee_s32 neg=1;
67 | int hexmode=0;
68 | if (*valstring == '-') {
69 | neg=-1;
70 | valstring++;
71 | }
72 | if ((valstring[0] == '0') && (valstring[1] == 'x')) {
73 | hexmode=1;
74 | valstring+=2;
75 | }
76 | /* first look for digits */
77 | if (hexmode) {
78 | while (((*valstring >= '0') && (*valstring <= '9')) || ((*valstring >= 'a') && (*valstring <= 'f'))) {
79 | ee_s32 digit=*valstring-'0';
80 | if (digit>9)
81 | digit=10+*valstring-'a';
82 | retval*=16;
83 | retval+=digit;
84 | valstring++;
85 | }
86 | } else {
87 | while ((*valstring >= '0') && (*valstring <= '9')) {
88 | ee_s32 digit=*valstring-'0';
89 | retval*=10;
90 | retval+=digit;
91 | valstring++;
92 | }
93 | }
94 | /* now add qualifiers */
95 | if (*valstring=='K')
96 | retval*=1024;
97 | if (*valstring=='M')
98 | retval*=1024*1024;
99 |
100 | retval*=neg;
101 | return retval;
102 | }
103 |
104 | ee_s32 get_seed_args(int i, int argc, char *argv[]) {
105 | if (argc>i)
106 | return parseval(argv[i]);
107 | return 0;
108 | }
109 |
110 | #elif (SEED_METHOD==SEED_FUNC)
111 | /* If using OS based function, you must define and implement the functions below in core_portme.h and core_portme.c ! */
112 | ee_s32 get_seed_32(int i) {
113 | ee_s32 retval;
114 | switch (i) {
115 | case 1:
116 | retval=portme_sys1();
117 | break;
118 | case 2:
119 | retval=portme_sys2();
120 | break;
121 | case 3:
122 | retval=portme_sys3();
123 | break;
124 | case 4:
125 | retval=portme_sys4();
126 | break;
127 | case 5:
128 | retval=portme_sys5();
129 | break;
130 | default:
131 | retval=0;
132 | break;
133 | }
134 | return retval;
135 | }
136 | #endif
137 |
138 | /* Function: crc*
139 | Service functions to calculate 16b CRC code.
140 |
141 | */
142 | ee_u16 crcu8(ee_u8 data, ee_u16 crc )
143 | {
144 | ee_u8 i=0,x16=0,carry=0;
145 |
146 | for (i = 0; i < 8; i++)
147 | {
148 | x16 = (ee_u8)((data & 1) ^ ((ee_u8)crc & 1));
149 | data >>= 1;
150 |
151 | if (x16 == 1)
152 | {
153 | crc ^= 0x4002;
154 | carry = 1;
155 | }
156 | else
157 | carry = 0;
158 | crc >>= 1;
159 | if (carry)
160 | crc |= 0x8000;
161 | else
162 | crc &= 0x7fff;
163 | }
164 | return crc;
165 | }
166 | ee_u16 crcu16(ee_u16 newval, ee_u16 crc) {
167 | crc=crcu8( (ee_u8) (newval) ,crc);
168 | crc=crcu8( (ee_u8) ((newval)>>8) ,crc);
169 | return crc;
170 | }
171 | ee_u16 crcu32(ee_u32 newval, ee_u16 crc) {
172 | crc=crc16((ee_s16) newval ,crc);
173 | crc=crc16((ee_s16) (newval>>16) ,crc);
174 | return crc;
175 | }
176 | ee_u16 crc16(ee_s16 newval, ee_u16 crc) {
177 | return crcu16((ee_u16)newval, crc);
178 | }
179 |
180 | ee_u8 check_data_types() {
181 | ee_u8 retval=0;
182 | if (sizeof(ee_u8) != 1) {
183 | ee_printf("ERROR: ee_u8 is not an 8b datatype!\n");
184 | retval++;
185 | }
186 | if (sizeof(ee_u16) != 2) {
187 | ee_printf("ERROR: ee_u16 is not a 16b datatype!\n");
188 | retval++;
189 | }
190 | if (sizeof(ee_s16) != 2) {
191 | ee_printf("ERROR: ee_s16 is not a 16b datatype!\n");
192 | retval++;
193 | }
194 | if (sizeof(ee_s32) != 4) {
195 | ee_printf("ERROR: ee_s32 is not a 32b datatype!\n");
196 | retval++;
197 | }
198 | if (sizeof(ee_u32) != 4) {
199 | ee_printf("ERROR: ee_u32 is not a 32b datatype!\n");
200 | retval++;
201 | }
202 | if (sizeof(ee_ptr_int) != sizeof(int *)) {
203 | ee_printf("ERROR: ee_ptr_int is not a datatype that holds an int pointer!\n");
204 | retval++;
205 | }
206 | if (retval>0) {
207 | ee_printf("ERROR: Please modify the datatypes in core_portme.h!\n");
208 | }
209 | return retval;
210 | }
211 |
--------------------------------------------------------------------------------
/coremark/coremark.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | Original Author: Shay Gal-on
17 | */
18 |
19 | /* Topic: Description
20 | This file contains declarations of the various benchmark functions.
21 | */
22 |
23 | /* Configuration: TOTAL_DATA_SIZE
24 | Define total size for data algorithms will operate on
25 | */
26 | #ifndef TOTAL_DATA_SIZE
27 | #define TOTAL_DATA_SIZE 2*1000
28 | #endif
29 |
30 | #define SEED_ARG 0
31 | #define SEED_FUNC 1
32 | #define SEED_VOLATILE 2
33 |
34 | #define MEM_STATIC 0
35 | #define MEM_MALLOC 1
36 | #define MEM_STACK 2
37 |
38 | #include "core_portme.h"
39 |
40 | #if HAS_STDIO
41 | #include
42 | #endif
43 | #if HAS_PRINTF
44 | #if(HAS_FLOAT)
45 | #define ee_printf printf
46 | #else
47 | #define ee_printf rt_kprintf
48 | #endif
49 | #endif
50 |
51 | /* Actual benchmark execution in iterate */
52 | void *iterate(void *pres);
53 |
54 | /* Typedef: secs_ret
55 | For machines that have floating point support, get number of seconds as a double.
56 | Otherwise an unsigned int.
57 | */
58 | #if HAS_FLOAT
59 | typedef double secs_ret;
60 | #else
61 | typedef ee_u32 secs_ret;
62 | #endif
63 |
64 | #if MAIN_HAS_NORETURN
65 | #define MAIN_RETURN_VAL
66 | #define MAIN_RETURN_TYPE void
67 | #else
68 | #define MAIN_RETURN_VAL 0
69 | #define MAIN_RETURN_TYPE int
70 | #endif
71 |
72 | void start_time(void);
73 | void stop_time(void);
74 | CORE_TICKS get_time(void);
75 | secs_ret time_in_secs(CORE_TICKS ticks);
76 |
77 | /* Misc useful functions */
78 | ee_u16 crcu8(ee_u8 data, ee_u16 crc);
79 | ee_u16 crc16(ee_s16 newval, ee_u16 crc);
80 | ee_u16 crcu16(ee_u16 newval, ee_u16 crc);
81 | ee_u16 crcu32(ee_u32 newval, ee_u16 crc);
82 | ee_u8 check_data_types(void);
83 | void *portable_malloc(ee_size_t size);
84 | void portable_free(void *p);
85 | ee_s32 parseval(char *valstring);
86 |
87 | /* Algorithm IDS */
88 | #define ID_LIST (1<<0)
89 | #define ID_MATRIX (1<<1)
90 | #define ID_STATE (1<<2)
91 | #define ALL_ALGORITHMS_MASK (ID_LIST|ID_MATRIX|ID_STATE)
92 | #define NUM_ALGORITHMS 3
93 |
94 | /* list data structures */
95 | typedef struct list_data_s {
96 | ee_s16 data16;
97 | ee_s16 idx;
98 | } list_data;
99 |
100 | typedef struct list_head_s {
101 | struct list_head_s *next;
102 | struct list_data_s *info;
103 | } list_head;
104 |
105 |
106 | /*matrix benchmark related stuff */
107 | #define MATDAT_INT 1
108 | #if MATDAT_INT
109 | typedef ee_s16 MATDAT;
110 | typedef ee_s32 MATRES;
111 | #else
112 | typedef ee_f16 MATDAT;
113 | typedef ee_f32 MATRES;
114 | #endif
115 |
116 | typedef struct MAT_PARAMS_S {
117 | int N;
118 | MATDAT *A;
119 | MATDAT *B;
120 | MATRES *C;
121 | } mat_params;
122 |
123 | /* state machine related stuff */
124 | /* List of all the possible states for the FSM */
125 | typedef enum CORE_STATE {
126 | CORE_START=0,
127 | CORE_INVALID,
128 | CORE_S1,
129 | CORE_S2,
130 | CORE_INT,
131 | CORE_FLOAT,
132 | CORE_EXPONENT,
133 | CORE_SCIENTIFIC,
134 | NUM_CORE_STATES
135 | } core_state_e ;
136 |
137 |
138 | /* Helper structure to hold results */
139 | typedef struct RESULTS_S {
140 | /* inputs */
141 | ee_s16 seed1; /* Initializing seed */
142 | ee_s16 seed2; /* Initializing seed */
143 | ee_s16 seed3; /* Initializing seed */
144 | void *memblock[4]; /* Pointer to safe memory location */
145 | ee_u32 size; /* Size of the data */
146 | ee_u32 iterations; /* Number of iterations to execute */
147 | ee_u32 execs; /* Bitmask of operations to execute */
148 | struct list_head_s *list;
149 | mat_params mat;
150 | /* outputs */
151 | ee_u16 crc;
152 | ee_u16 crclist;
153 | ee_u16 crcmatrix;
154 | ee_u16 crcstate;
155 | ee_s16 err;
156 | /* ultithread specific */
157 | core_portable port;
158 | } core_results;
159 |
160 | /* Multicore execution handling */
161 | #if (MULTITHREAD>1)
162 | ee_u8 core_start_parallel(core_results *res);
163 | ee_u8 core_stop_parallel(core_results *res);
164 | #endif
165 |
166 | /* list benchmark functions */
167 | list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed);
168 | ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx);
169 |
170 | /* state benchmark functions */
171 | void core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p);
172 | ee_u16 core_bench_state(ee_u32 blksize, ee_u8 *memblock,
173 | ee_s16 seed1, ee_s16 seed2, ee_s16 step, ee_u16 crc);
174 |
175 | /* matrix benchmark functions */
176 | ee_u32 core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p);
177 | ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc);
178 |
179 |
--------------------------------------------------------------------------------
/coremark/main.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main(int argc, char *argv[])
4 | {
5 | rt_kprintf("Hello, world\n");
6 |
7 | extern int core_mark(void);
8 | core_mark();
9 |
10 | return 0;
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/cxx/SConscript:
--------------------------------------------------------------------------------
1 | from building import *
2 |
3 | src = Glob('*.c') + Glob('*.cpp')
4 | cwd = GetCurrentDir()
5 |
6 | CPPPATH = [cwd]
7 | group = DefineGroup('', src, depend = [''], CPPPATH=CPPPATH)
8 |
9 | # add C++ runtime wrapper
10 | group = group + SConscript('runtime/SConscript')
11 |
12 | Return('group')
13 |
--------------------------------------------------------------------------------
/cxx/crt/SConscript:
--------------------------------------------------------------------------------
1 | import rtconfig
2 | from building import *
3 |
4 | src = Glob('*.c') + Glob('*.cpp')
5 | cwd = GetCurrentDir()
6 | CPPPATH = [cwd]
7 |
8 | if rtconfig.CPU == 'win32':
9 | group = []
10 | else:
11 | group = DefineGroup('C++ Run time', src, depend = [''], CPPPATH=CPPPATH)
12 |
13 | Return('group')
14 |
--------------------------------------------------------------------------------
/cxx/crt/crt.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "crt.h"
3 |
4 | void *operator new(size_t size)
5 | {
6 | return rt_malloc(size);
7 | }
8 |
9 | void *operator new[](size_t size)
10 | {
11 | return rt_malloc(size);
12 | }
13 |
14 | void operator delete(void *ptr)
15 | {
16 | rt_free(ptr);
17 | }
18 |
19 | void operator delete[] (void *ptr)
20 | {
21 | return rt_free(ptr);
22 | }
23 |
24 | void __cxa_pure_virtual(void)
25 | {
26 | RT_ASSERT(!"Illegal to call a pure virtual function.");
27 | }
28 |
29 | #ifdef __GNUC__
30 | namespace std {
31 |
32 | void __throw_bad_cast()
33 | {
34 | RT_ASSERT(!"Bad cast.");
35 | }
36 |
37 | void __throw_bad_alloc()
38 | {
39 | RT_ASSERT(!"Bad alloc.");
40 | }
41 |
42 | void __throw_bad_typeid()
43 | {
44 | RT_ASSERT(!"Bad typeid.");
45 | }
46 |
47 | void __throw_ios_failure(char const* p)
48 | {
49 | RT_ASSERT(!"iOS failure.");
50 | }
51 |
52 | void __throw_logic_error(char const* p)
53 | {
54 | RT_ASSERT(!"Logic error.");
55 | }
56 |
57 | void __throw_range_error(char const* p)
58 | {
59 | RT_ASSERT(!"Range error.");
60 | }
61 |
62 | void __throw_domain_error(char const* p)
63 | {
64 | RT_ASSERT(!"Domain error.");
65 | }
66 |
67 | void __throw_future_error(int p)
68 | {
69 | RT_ASSERT(!"Future error.");
70 | }
71 |
72 | void __throw_length_error(char const* p)
73 | {
74 | RT_ASSERT(!"Length error.");
75 | }
76 |
77 | void __throw_out_of_range(char const* p)
78 | {
79 | RT_ASSERT(!"Out of range error.");
80 | }
81 |
82 | void __throw_system_error(int p)
83 | {
84 | RT_ASSERT(!"System error.");
85 | }
86 |
87 | void __throw_bad_exception()
88 | {
89 | RT_ASSERT(!"Bad exception.");
90 | }
91 |
92 | void __throw_runtime_error(char const* p)
93 | {
94 | RT_ASSERT(!"Runtime error.");
95 | }
96 |
97 | void __throw_overflow_error(char const* p)
98 | {
99 | RT_ASSERT(!"Overflow error.");
100 | }
101 |
102 | void __throw_underflow_error(char const* p)
103 | {
104 | RT_ASSERT(!"Underflow error.");
105 | }
106 |
107 | void __throw_invalid_argument(char const* p)
108 | {
109 | RT_ASSERT(!"Invalid argument.");
110 | }
111 |
112 | void __throw_out_of_range_fmt(char const* p, ...)
113 | {
114 | RT_ASSERT(!"Out of range fmt.");
115 | }
116 |
117 | }
118 | #endif
119 |
--------------------------------------------------------------------------------
/cxx/crt/crt.h:
--------------------------------------------------------------------------------
1 | #ifndef CRT_H_
2 | #define CRT_H_
3 |
4 | #include
5 | #include
6 |
7 | void *operator new(size_t size);
8 | void *operator new[](size_t size);
9 |
10 | void operator delete(void * ptr);
11 | void operator delete[] (void *ptr);
12 |
13 | extern "C" void __cxa_pure_virtual(void);
14 | extern "C" int cplusplus_system_init(void);
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/cxx/cxx.cpp:
--------------------------------------------------------------------------------
1 | #include "cxx.h"
2 |
3 | #include
4 |
5 | A::A()
6 | : a(0)
7 | {
8 | }
9 |
10 | void A::setA(int value)
11 | {
12 | a = value;
13 | }
14 |
15 | int A::getA(void)
16 | {
17 | return a;
18 | }
19 |
20 | void A::toString()
21 | {
22 | rt_kprintf("A::a = %d\n", a);
23 | }
24 |
25 | extern "C" {
26 |
27 | int Atest(void)
28 | {
29 | A a;
30 |
31 | a.setA(100);
32 | a.toString();
33 |
34 | return 0;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/cxx/cxx.h:
--------------------------------------------------------------------------------
1 | #ifndef CXX_H__
2 | #define CXX_H__
3 |
4 | class A
5 | {
6 | public:
7 | A();
8 |
9 | void setA(int value);
10 | int getA(void);
11 |
12 | void toString();
13 |
14 | private:
15 | int a;
16 | };
17 |
18 | #endif
19 |
--------------------------------------------------------------------------------
/cxx/main.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | extern int Atest(void);
4 |
5 | int main(int argc, char** argv)
6 | {
7 | Atest();
8 |
9 | return 0;
10 | }
11 |
--------------------------------------------------------------------------------
/devicetest/SConscript:
--------------------------------------------------------------------------------
1 | from building import *
2 |
3 | src = Glob('*.c') + Glob('*.cpp')
4 | cwd = GetCurrentDir()
5 |
6 | CPPPATH = [cwd]
7 | group = DefineGroup('', src, depend = [''], CPPPATH=CPPPATH)
8 |
9 | Return('group')
10 |
--------------------------------------------------------------------------------
/devicetest/device_test.c:
--------------------------------------------------------------------------------
1 | /*
2 | * File : device_test.c
3 | * This file is part of RT-Thread RTOS
4 | * COPYRIGHT (C) 2011, RT-Thread Development Team
5 | *
6 | * The license and distribution terms for this file may be
7 | * found in the file LICENSE in this distribution or at
8 | * http://openlab.rt-thread.com/license/LICENSE.
9 | *
10 | * Change Logs:
11 | * Date Author Notes
12 | * 2011-01-01 aozima the first version.
13 | * 2012-02-11 aozima add multiple sector speed test.
14 | * 2012-05-27 aozima use rt_deice API.
15 | */
16 |
17 | #include
18 |
19 | /* calculate speed */
20 | static void calculate_speed_print(rt_uint32_t speed)
21 | {
22 | rt_uint32_t k,m;
23 |
24 | k = speed/1024UL;
25 | if( k )
26 | {
27 | m = k/1024UL;
28 | if( m )
29 | {
30 | rt_kprintf("%d.%dMbyte/s",m,k%1024UL*100/1024UL);
31 | }
32 | else
33 | {
34 | rt_kprintf("%d.%dKbyte/s",k,speed%1024UL*100/1024UL);
35 | }
36 | }
37 | else
38 | {
39 | rt_kprintf("%dbyte/s",speed);
40 | }
41 | }
42 |
43 | static rt_err_t _block_device_test(rt_device_t device)
44 | {
45 | rt_err_t result;
46 | struct rt_device_blk_geometry geometry;
47 | rt_uint8_t * read_buffer = RT_NULL;
48 | rt_uint8_t * write_buffer = RT_NULL;
49 |
50 | rt_kprintf("\r\n");
51 |
52 | while (1)
53 | {
54 | if(rt_device_find("sd0") != RT_NULL)
55 | {
56 | if (dfs_unmount("/") == RT_EOK)
57 | {
58 | rt_kprintf("emmc dfs_unmount to '/' successful.");
59 | break;
60 | }
61 | else
62 | {
63 | rt_kprintf("emmc dfs_unmount to '/' failed!");
64 | }
65 | }
66 | rt_thread_mdelay(5000);
67 | }
68 |
69 | if( (device->flag & RT_DEVICE_FLAG_RDWR) == RT_DEVICE_FLAG_RDWR )
70 | {
71 | // device can read and write.
72 | // step 1: open device
73 | result = rt_device_open(device,RT_DEVICE_FLAG_RDWR);
74 | if( result != RT_EOK )
75 | {
76 | return result;
77 | }
78 |
79 | // step 2: get device info
80 | rt_memset(&geometry, 0, sizeof(geometry));
81 | result = rt_device_control(device,
82 | RT_DEVICE_CTRL_BLK_GETGEOME,
83 | &geometry);
84 | if( result != RT_EOK )
85 | {
86 | rt_kprintf("device : %s cmd RT_DEVICE_CTRL_BLK_GETGEOME failed.\r\n");
87 | return result;
88 | }
89 | rt_kprintf("device info:\r\n");
90 | rt_kprintf("sector size : %d byte\r\n", geometry.bytes_per_sector);
91 | rt_kprintf("sector count : %d \r\n", geometry.sector_count);
92 | rt_kprintf("block size : %d byte\r\n", geometry.block_size);
93 |
94 | rt_kprintf("\r\n");
95 | read_buffer = rt_malloc(geometry.bytes_per_sector);
96 | if( read_buffer == RT_NULL )
97 | {
98 | rt_kprintf("no memory for read_buffer!\r\n");
99 | goto __return;
100 | }
101 | write_buffer = rt_malloc(geometry.bytes_per_sector);
102 | if( write_buffer == RT_NULL )
103 | {
104 | rt_kprintf("no memory for write_buffer!\r\n");
105 | goto __return;
106 | }
107 |
108 | /* step 3: R/W test */
109 | {
110 | rt_uint32_t i, err_count, sector_no;
111 | rt_uint8_t * data_point;
112 |
113 | i = rt_device_read(device, 0, read_buffer, 1);
114 | if(i != 1)
115 | {
116 | rt_kprintf("read device :%s ", device->parent.name);
117 | rt_kprintf("the first sector failed.\r\n");
118 | goto __return;
119 | }
120 |
121 | data_point = write_buffer;
122 | for(i=0; iparent.name);
136 | rt_kprintf("the first sector failed.\r\n");
137 | rt_kprintf("maybe readonly!\r\n");
138 | goto __return;
139 | }
140 |
141 | /* write the second sector */
142 | sector_no = 1;
143 | data_point = write_buffer;
144 | *data_point++ = (rt_uint8_t)sector_no;
145 | i = rt_device_write(device,sector_no,write_buffer,1);
146 | if( i != 1 )
147 | {
148 | rt_kprintf("write device :%s ",device->parent.name);
149 | rt_kprintf("the second sector failed.\r\n");
150 | goto __return;
151 | }
152 |
153 | /* write the end sector */
154 | sector_no = geometry.sector_count-1;
155 | data_point = write_buffer;
156 | *data_point++ = (rt_uint8_t)sector_no;
157 | i = rt_device_write(device,sector_no,write_buffer,1);
158 | if( i != 1 )
159 | {
160 | rt_kprintf("write device :%s ",device->parent.name);
161 | rt_kprintf("the end sector failed.\r\n");
162 | goto __return;
163 | }
164 |
165 | /* verify first sector */
166 | sector_no = 0;
167 | i = rt_device_read(device,sector_no,read_buffer,1);
168 | if( i != 1 )
169 | {
170 | rt_kprintf("read device :%s ",device->parent.name);
171 | rt_kprintf("the first sector failed.\r\n");
172 | goto __return;
173 | }
174 | err_count = 0;
175 | data_point = read_buffer;
176 | if( (*data_point++) != (rt_uint8_t)sector_no)
177 | {
178 | err_count++;
179 | }
180 | for(i=1; i 0 )
188 | {
189 | rt_kprintf("verify device :%s ",device->parent.name);
190 | rt_kprintf("the first sector failed.\r\n");
191 | goto __return;
192 | }
193 |
194 | /* verify sector sector */
195 | sector_no = 1;
196 | i = rt_device_read(device,sector_no,read_buffer,1);
197 | if( i != 1 )
198 | {
199 | rt_kprintf("read device :%s ",device->parent.name);
200 | rt_kprintf("the second sector failed.\r\n");
201 | goto __return;
202 | }
203 | err_count = 0;
204 | data_point = read_buffer;
205 | if( (*data_point++) != (rt_uint8_t)sector_no)
206 | {
207 | err_count++;
208 | }
209 | for(i=1; i 0 )
217 | {
218 | rt_kprintf("verify device :%s ",device->parent.name);
219 | rt_kprintf("the second sector failed.\r\n");
220 | goto __return;
221 | }
222 |
223 | /* verify the end sector */
224 | sector_no = geometry.sector_count-1;
225 | i = rt_device_read(device,sector_no,read_buffer,1);
226 | if( i != 1 )
227 | {
228 | rt_kprintf("read device :%s ",device->parent.name);
229 | rt_kprintf("the end sector failed.\r\n");
230 | goto __return;
231 | }
232 | err_count = 0;
233 | data_point = read_buffer;
234 | if( (*data_point++) != (rt_uint8_t)sector_no)
235 | {
236 | err_count++;
237 | }
238 | for(i=1; i 0 )
246 | {
247 | rt_kprintf("verify device :%s ",device->parent.name);
248 | rt_kprintf("the end sector failed.\r\n");
249 | goto __return;
250 | }
251 | rt_kprintf("device R/W test pass!\r\n");
252 |
253 | } /* step 3: I/O R/W test */
254 |
255 | rt_kprintf("\r\nRT_TICK_PER_SECOND:%d\r\n", RT_TICK_PER_SECOND);
256 |
257 | // step 4: continuous single sector speed test
258 | {
259 | rt_uint32_t tick_start,tick_end;
260 | rt_uint32_t i;
261 |
262 | rt_kprintf("\r\ncontinuous single sector speed test:\r\n");
263 |
264 | if( geometry.sector_count < 10 )
265 | {
266 | rt_kprintf("device sector_count < 10, speed test abort!\r\n");
267 | }
268 | else
269 | {
270 | unsigned int sector;
271 |
272 | // sign sector write
273 | rt_kprintf("write: ");
274 | sector = 0;
275 | tick_start = rt_tick_get();
276 | for(i=0; i<200; i++)
277 | {
278 | sector += rt_device_write(device, i, read_buffer, 1);
279 | if((i != 0) && ((i%4) == 0) )
280 | {
281 | if(sector < 4)
282 | {
283 | rt_kprintf("#");
284 | }
285 | else
286 | {
287 | rt_kprintf("<");
288 | }
289 | sector = 0;
290 | }
291 | }
292 | tick_end = rt_tick_get();
293 | rt_kprintf("\r\nwrite 200 sector from %d to %d, ",tick_start,tick_end);
294 | calculate_speed_print( (geometry.bytes_per_sector*200UL*RT_TICK_PER_SECOND)/(tick_end-tick_start) );
295 | rt_kprintf("\r\n");
296 |
297 | // sign sector read
298 | rt_kprintf("read : ");
299 | sector = 0;
300 | tick_start = rt_tick_get();
301 | for(i=0; i<200; i++)
302 | {
303 | sector += rt_device_read(device, i, read_buffer, 1);
304 | if((i != 0) && ((i%4) == 0) )
305 | {
306 | if(sector < 4)
307 | {
308 | rt_kprintf("#");
309 | }
310 | else
311 | {
312 | rt_kprintf(">");
313 | }
314 | sector = 0;
315 | }
316 | }
317 | tick_end = rt_tick_get();
318 | rt_kprintf("\r\nread 200 sector from %d to %d, ",tick_start,tick_end);
319 | calculate_speed_print( (geometry.bytes_per_sector*200UL*RT_TICK_PER_SECOND)/(tick_end-tick_start) );
320 | rt_kprintf("\r\n");
321 | }
322 | }// step 4: speed test
323 |
324 | // step 5: random single sector speed test
325 | {
326 | rt_uint32_t tick_start,tick_end;
327 | rt_uint32_t i;
328 |
329 | rt_kprintf("\r\nrandom single sector speed test:\r\n");
330 |
331 | if( geometry.sector_count < 10 )
332 | {
333 | rt_kprintf("device sector_count < 10, speed test abort!\r\n");
334 | }
335 | else
336 | {
337 | unsigned int sector;
338 |
339 | // sign sector write
340 | rt_kprintf("write: ");
341 | sector = 0;
342 | tick_start = rt_tick_get();
343 | for(i=0; i<200; i++)
344 | {
345 | sector += rt_device_write(device, (geometry.sector_count / 10) * (i%10) + (i%10), read_buffer, 1);
346 | if((i != 0) && ((i%4) == 0) )
347 | {
348 | if(sector < 4)
349 | {
350 | rt_kprintf("#");
351 | }
352 | else
353 | {
354 | rt_kprintf("<");
355 | }
356 | sector = 0;
357 | }
358 | }
359 | tick_end = rt_tick_get();
360 | rt_kprintf("\r\nwrite 200 sector from %d to %d, ",tick_start,tick_end);
361 | calculate_speed_print( (geometry.bytes_per_sector*200UL*RT_TICK_PER_SECOND)/(tick_end-tick_start) );
362 | rt_kprintf("\r\n");
363 |
364 | // sign sector read
365 | rt_kprintf("read : ");
366 | sector = 0;
367 | tick_start = rt_tick_get();
368 | for(i=0; i<200; i++)
369 | {
370 | sector += rt_device_read(device, (geometry.sector_count / 10) * (i%10) + (i%10), read_buffer, 1);
371 | if((i != 0) && ((i%4) == 0) )
372 | {
373 | if(sector < 4)
374 | {
375 | rt_kprintf("#");
376 | }
377 | else
378 | {
379 | rt_kprintf(">");
380 | }
381 | sector = 0;
382 | }
383 | }
384 | tick_end = rt_tick_get();
385 | rt_kprintf("\r\nread 200 sector from %d to %d, ",tick_start,tick_end);
386 | calculate_speed_print( (geometry.bytes_per_sector*200UL*RT_TICK_PER_SECOND)/(tick_end-tick_start) );
387 | rt_kprintf("\r\n");
388 | }
389 | }// step 4: speed test
390 |
391 | /* step 6: multiple sector speed test */
392 | {
393 | rt_uint8_t * multiple_buffer;
394 | rt_uint8_t * ptr;
395 | rt_uint32_t tick_start,tick_end;
396 | rt_uint32_t sector,i;
397 |
398 | rt_kprintf("\r\nmultiple sector speed test\r\n");
399 |
400 | for(sector=2; sector<256; sector=sector*2)
401 | {
402 | multiple_buffer = rt_malloc(geometry.bytes_per_sector * sector);
403 |
404 | if(multiple_buffer == RT_NULL)
405 | {
406 | rt_kprintf("no memory for %d sector! multiple sector speed test abort!\r\n", sector);
407 | break;
408 | }
409 |
410 | rt_memset(multiple_buffer, sector, geometry.bytes_per_sector * sector);
411 | rt_kprintf("write: ");
412 | tick_start = rt_tick_get();
413 | for(i=0; i<10; i++)
414 | {
415 | rt_size_t n;
416 | n = rt_device_write(device, 50, multiple_buffer, sector);
417 | if(n == sector)
418 | {
419 | rt_kprintf("<");
420 | }
421 | else
422 | {
423 | rt_kprintf("#");
424 | }
425 | }
426 | tick_end = rt_tick_get();
427 | rt_kprintf("\r\n");
428 | rt_kprintf("multiple write %d sector speed : ", sector);
429 | calculate_speed_print( (geometry.bytes_per_sector * sector * 10 * RT_TICK_PER_SECOND)/(tick_end-tick_start) );
430 | rt_kprintf("\r\n");
431 |
432 | rt_memset(multiple_buffer, ~sector, geometry.bytes_per_sector * sector);
433 | rt_kprintf("read : ");
434 | tick_start = rt_tick_get();
435 | for(i=0; i<10; i++)
436 | {
437 | rt_size_t n;
438 | n = rt_device_read(device, 50, multiple_buffer, sector);
439 | if(n == sector)
440 | {
441 | rt_kprintf(">");
442 | }
443 | else
444 | {
445 | rt_kprintf("#");
446 | }
447 | }
448 | tick_end = rt_tick_get();
449 | rt_kprintf("\r\n");
450 | rt_kprintf("multiple read %d sector speed : ", sector);
451 | calculate_speed_print( (geometry.bytes_per_sector * sector * 10 * RT_TICK_PER_SECOND)/(tick_end-tick_start) );
452 |
453 | ptr = multiple_buffer;
454 | for(i=0; iflag & RT_DEVICE_FLAG_ACTIVATED))
510 | {
511 | rt_err_t result;
512 | result = rt_device_init(device);
513 | if (result != RT_EOK)
514 | {
515 | rt_kprintf("To initialize device:%s failed. The error code is %d\r\n",
516 | device->parent.name, result);
517 | return result;
518 | }
519 | else
520 | {
521 | device->flag |= RT_DEVICE_FLAG_ACTIVATED;
522 | }
523 | }
524 |
525 | // step 3: device test
526 | switch( device->type )
527 | {
528 | case RT_Device_Class_Block :
529 | rt_kprintf("block device!\r\n");
530 | return _block_device_test(device);
531 | default:
532 | rt_kprintf("unkown device type : %02X",device->type);
533 | return RT_ERROR;
534 | }
535 | }
536 | MSH_CMD_EXPORT(device_test, run device_test sd0);
537 |
--------------------------------------------------------------------------------
/devicetest/main.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main(int argc, char *argv[])
4 | {
5 | rt_kprintf("device testing\n");
6 |
7 | extern int device_test(void);
8 | device_test();
9 |
10 | return 0;
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/hello/SConscript:
--------------------------------------------------------------------------------
1 | from building import *
2 |
3 | src = Glob('*.c') + Glob('*.cpp')
4 | cwd = GetCurrentDir()
5 |
6 | CPPPATH = [cwd]
7 | group = DefineGroup('', src, depend = [''], CPPPATH=CPPPATH)
8 |
9 | Return('group')
10 |
--------------------------------------------------------------------------------
/hello/main.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main(int argc, char *argv[])
4 | {
5 | printf("Hello, world\n");
6 |
7 | return 0;
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/lib/SConscript:
--------------------------------------------------------------------------------
1 | from building import *
2 |
3 | src = Glob('*.c') + Glob('*.cpp')
4 | cwd = GetCurrentDir()
5 |
6 | CPPPATH = [cwd]
7 | group = DefineGroup('', src, depend = [''], CPPPATH=CPPPATH)
8 |
9 | Return('group')
10 |
--------------------------------------------------------------------------------
/lib/lib.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int lib_func(void)
4 | {
5 | printf("hello world from RTT::dynamic library!\n");
6 |
7 | return 0;
8 | }
9 |
10 | int add_func(int a, int b)
11 | {
12 | return (a + b);
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/md5/SConscript:
--------------------------------------------------------------------------------
1 | from building import *
2 |
3 | src = Glob('*.c') + Glob('*.cpp')
4 | cwd = GetCurrentDir()
5 |
6 | CPPPATH = [cwd]
7 | group = DefineGroup('', src, depend = [''], CPPPATH=CPPPATH)
8 |
9 | Return('group')
10 |
--------------------------------------------------------------------------------
/md5/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "md5.h"
6 |
7 | #define BUF_SZ 2048
8 |
9 | void usage(void)
10 | {
11 | printf("The md5 value generation/comparision tool.\n");
12 | printf("md5 -g filename : to generate md5 file.\n");
13 | printf("md5 -c filename : to compare md5 value.\n");
14 |
15 | return;
16 | }
17 |
18 | static MD5_CTX md5_ctx;
19 | static unsigned char md5[16];
20 |
21 | int main(int argc, char** argv)
22 | {
23 | FILE* fp;
24 | char* fn;
25 | int generate = -1;
26 |
27 | MD5Init(&md5_ctx);
28 |
29 | if (argc != 3)
30 | {
31 | usage();
32 | return -1;
33 | }
34 |
35 | /* parse argument */
36 | if (strcmp(argv[1], "-g") == 0) generate = 1;
37 | if (strcmp(argv[1], "-c") == 0) generate = 0;
38 |
39 | if (generate == -1)
40 | {
41 | usage();
42 | return -1;
43 | }
44 |
45 | fp = fopen(argv[2], "rb");
46 | if (fp)
47 | {
48 | uint8_t *buf_ptr;
49 |
50 | buf_ptr = (uint8_t*)malloc(BUF_SZ);
51 | if (buf_ptr)
52 | {
53 | int length;
54 |
55 | while (!feof(fp))
56 | {
57 | length = fread(buf_ptr, 1, BUF_SZ, fp);
58 | MD5Update(&md5_ctx, buf_ptr, length);
59 | }
60 |
61 | MD5Final(md5, &md5_ctx);
62 | free(buf_ptr);
63 | }
64 |
65 | fclose(fp);
66 |
67 | /* get the md5 file name */
68 | fn = (char*) malloc(strlen(argv[2] + 16));
69 | if (!fn)
70 | {
71 | printf("no memory!\n");
72 | return -1;
73 | }
74 |
75 | {
76 | char *ptr;
77 |
78 | strcpy(fn, argv[2]);
79 | ptr = strchr(fn, '.');
80 | if (ptr)
81 | {
82 | ptr ++;
83 | }
84 | else
85 | {
86 | /* no ext name */
87 | ptr = &fn[strlen(fn)];
88 | *ptr++ = '.';
89 | }
90 |
91 | /* with .md5 ext name */
92 | *ptr++ = 'm';
93 | *ptr++ = 'd';
94 | *ptr++ = '5';
95 | *ptr = '\0';
96 | }
97 |
98 | if (generate == 1)
99 | {
100 | /* generate md5 file */
101 | fp = fopen(fn, "wb+");
102 | free(fn); /* release filename memory */
103 |
104 | if (fp)
105 | {
106 | fwrite(md5, 1, sizeof(md5), fp);
107 | fclose(fp);
108 |
109 | return 0;
110 | }
111 | }
112 | else if (generate == 0)
113 | {
114 | unsigned char md5_temp[16];
115 |
116 | /* compare md5 file */
117 | fp = fopen(fn, "rb");
118 | free(fn); /* release filename memory */
119 |
120 | if (fp)
121 | {
122 | fread(md5_temp, 1, sizeof(md5_temp), fp);
123 | fclose(fp);
124 | }
125 |
126 | if (memcmp(md5, md5_temp, sizeof(md5)) == 0)
127 | {
128 | printf("md5 value is the same!\n");
129 | return 0;
130 | }
131 | else
132 | {
133 | printf("md5 value is different!\n");
134 | return -1;
135 | }
136 | }
137 | }
138 | else
139 | {
140 | printf("%s open failed!\n", argv[2]);
141 | }
142 |
143 | return -1;
144 | }
145 |
--------------------------------------------------------------------------------
/md5/md5.c:
--------------------------------------------------------------------------------
1 | /*
2 | ***********************************************************************
3 | ** md5.c -- the source code for MD5 routines **
4 | ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
5 | ** Created: 2/17/90 RLR **
6 | ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
7 | ***********************************************************************
8 | */
9 |
10 | /*
11 | ***********************************************************************
12 | ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
13 | ** **
14 | ** License to copy and use this software is granted provided that **
15 | ** it is identified as the "RSA Data Security, Inc. MD5 Message- **
16 | ** Digest Algorithm" in all material mentioning or referencing this **
17 | ** software or this function. **
18 | ** **
19 | ** License is also granted to make and use derivative works **
20 | ** provided that such works are identified as "derived from the RSA **
21 | ** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
22 | ** material mentioning or referencing the derived work. **
23 | ** **
24 | ** RSA Data Security, Inc. makes no representations concerning **
25 | ** either the merchantability of this software or the suitability **
26 | ** of this software for any particular purpose. It is provided "as **
27 | ** is" without express or implied warranty of any kind. **
28 | ** **
29 | ** These notices must be retained in any copies of any part of this **
30 | ** documentation and/or software. **
31 | ***********************************************************************
32 | */
33 |
34 | #include "md5.h"
35 | #include
36 |
37 | /*
38 | ***********************************************************************
39 | ** Message-digest routines: **
40 | ** To form the message digest for a message M **
41 | ** (1) Initialize a context buffer mdContext using MD5Init **
42 | ** (2) Call MD5Update on mdContext and M **
43 | ** (3) Call MD5Final on mdContext **
44 | ** The message digest is now in mdContext->digest[0...15] **
45 | ***********************************************************************
46 | */
47 |
48 | /* forward declaration */
49 | static void Transform (uint32_t *buf, uint32_t *in);
50 |
51 | static unsigned char PADDING[64] = {
52 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
60 | };
61 |
62 | /* F, G, H and I are basic MD5 functions */
63 | #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
64 | #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
65 | #define H(x, y, z) ((x) ^ (y) ^ (z))
66 | #define I(x, y, z) ((y) ^ ((x) | (~z)))
67 |
68 | /* ROTATE_LEFT rotates x left n bits */
69 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
70 |
71 | /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
72 | /* Rotation is separate from addition to prevent recomputation */
73 | #define FF(a, b, c, d, x, s, ac) \
74 | {(a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
75 | (a) = ROTATE_LEFT ((a), (s)); \
76 | (a) += (b); \
77 | }
78 | #define GG(a, b, c, d, x, s, ac) \
79 | {(a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
80 | (a) = ROTATE_LEFT ((a), (s)); \
81 | (a) += (b); \
82 | }
83 | #define HH(a, b, c, d, x, s, ac) \
84 | {(a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
85 | (a) = ROTATE_LEFT ((a), (s)); \
86 | (a) += (b); \
87 | }
88 | #define II(a, b, c, d, x, s, ac) \
89 | {(a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
90 | (a) = ROTATE_LEFT ((a), (s)); \
91 | (a) += (b); \
92 | }
93 |
94 | #ifdef __STDC__
95 | #define UL(x) x##UL
96 | #else
97 | #ifdef WIN32
98 | #define UL(x) x##UL
99 | #else
100 | #define UL(x) x
101 | #endif
102 | #endif
103 |
104 | /* The routine MD5Init initializes the message-digest context
105 | mdContext. All fields are set to zero.
106 | */
107 | void
108 | MD5Init (MD5_CTX *mdContext)
109 | {
110 | mdContext->i[0] = mdContext->i[1] = (uint32_t)0;
111 |
112 | /* Load magic initialization constants. */
113 | mdContext->buf[0] = (uint32_t)0x67452301UL;
114 | mdContext->buf[1] = (uint32_t)0xefcdab89UL;
115 | mdContext->buf[2] = (uint32_t)0x98badcfeUL;
116 | mdContext->buf[3] = (uint32_t)0x10325476UL;
117 | }
118 |
119 | /* The routine MD5Update updates the message-digest context to
120 | account for the presence of each of the characters inBuf[0..inLen-1]
121 | in the message whose digest is being computed.
122 | */
123 | void
124 | MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen)
125 | {
126 | uint32_t in[16];
127 | int mdi;
128 | unsigned int i, ii;
129 |
130 | /* compute number of bytes mod 64 */
131 | mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
132 |
133 | /* update number of bits */
134 | if ((mdContext->i[0] + ((uint32_t)inLen << 3)) < mdContext->i[0]) {
135 | mdContext->i[1]++;
136 | }
137 | mdContext->i[0] += ((uint32_t)inLen << 3);
138 | mdContext->i[1] += ((uint32_t)inLen >> 29);
139 |
140 | while (inLen--) {
141 | /* add new character to buffer, increment mdi */
142 | mdContext->in[mdi++] = *inBuf++;
143 |
144 | /* transform if necessary */
145 | if (mdi == 0x40) {
146 | for (i = 0, ii = 0; i < 16; i++, ii += 4) {
147 | in[i] = (((uint32_t)mdContext->in[ii+3]) << 24) |
148 | (((uint32_t)mdContext->in[ii+2]) << 16) |
149 | (((uint32_t)mdContext->in[ii+1]) << 8) |
150 | ((uint32_t)mdContext->in[ii]);
151 | }
152 | Transform (mdContext->buf, in);
153 | mdi = 0;
154 | }
155 | }
156 | }
157 |
158 | /* The routine MD5Final terminates the message-digest computation and
159 | ends with the desired message digest in mdContext->digest[0...15].
160 | */
161 | void
162 | MD5Final (unsigned char hash[], MD5_CTX *mdContext)
163 | {
164 | uint32_t in[16];
165 | int mdi;
166 | unsigned int i, ii;
167 | unsigned int padLen;
168 |
169 | /* save number of bits */
170 | in[14] = mdContext->i[0];
171 | in[15] = mdContext->i[1];
172 |
173 | /* compute number of bytes mod 64 */
174 | mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
175 |
176 | /* pad out to 56 mod 64 */
177 | padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
178 | MD5Update (mdContext, PADDING, padLen);
179 |
180 | /* append length in bits and transform */
181 | for (i = 0, ii = 0; i < 14; i++, ii += 4) {
182 | in[i] = (((uint32_t)mdContext->in[ii+3]) << 24) |
183 | (((uint32_t)mdContext->in[ii+2]) << 16) |
184 | (((uint32_t)mdContext->in[ii+1]) << 8) |
185 | ((uint32_t)mdContext->in[ii]);
186 | }
187 | Transform (mdContext->buf, in);
188 |
189 | /* store buffer in digest */
190 | for (i = 0, ii = 0; i < 4; i++, ii += 4) {
191 | mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
192 | mdContext->digest[ii+1] =
193 | (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
194 | mdContext->digest[ii+2] =
195 | (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
196 | mdContext->digest[ii+3] =
197 | (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
198 | }
199 | memcpy(hash, mdContext->digest, 16);
200 | }
201 |
202 | /* Basic MD5 step. Transforms buf based on in.
203 | */
204 | static void
205 | Transform (uint32_t *buf, uint32_t *in)
206 | {
207 | uint32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3];
208 |
209 | /* Round 1 */
210 | #define S11 7
211 | #define S12 12
212 | #define S13 17
213 | #define S14 22
214 | FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
215 | FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
216 | FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
217 | FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
218 | FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
219 | FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
220 | FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
221 | FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
222 | FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
223 | FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
224 | FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
225 | FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
226 | FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
227 | FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
228 | FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
229 | FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
230 |
231 | /* Round 2 */
232 | #define S21 5
233 | #define S22 9
234 | #define S23 14
235 | #define S24 20
236 | GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
237 | GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
238 | GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
239 | GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
240 | GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
241 | GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
242 | GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
243 | GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
244 | GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
245 | GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
246 | GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
247 | GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
248 | GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
249 | GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
250 | GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
251 | GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
252 |
253 | /* Round 3 */
254 | #define S31 4
255 | #define S32 11
256 | #define S33 16
257 | #define S34 23
258 | HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
259 | HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
260 | HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
261 | HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
262 | HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
263 | HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
264 | HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
265 | HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
266 | HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
267 | HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
268 | HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
269 | HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
270 | HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
271 | HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
272 | HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
273 | HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
274 |
275 | /* Round 4 */
276 | #define S41 6
277 | #define S42 10
278 | #define S43 15
279 | #define S44 21
280 | II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
281 | II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
282 | II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
283 | II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
284 | II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
285 | II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
286 | II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
287 | II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
288 | II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
289 | II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
290 | II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
291 | II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
292 | II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
293 | II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
294 | II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
295 | II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
296 |
297 | buf[0] += a;
298 | buf[1] += b;
299 | buf[2] += c;
300 | buf[3] += d;
301 | }
302 |
--------------------------------------------------------------------------------
/md5/md5.h:
--------------------------------------------------------------------------------
1 | /*
2 | ***********************************************************************
3 | ** md5.h -- header file for implementation of MD5 **
4 | ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
5 | ** Created: 2/17/90 RLR **
6 | ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
7 | ** Revised (for MD5): RLR 4/27/91 **
8 | ** -- G modified to have y&~z instead of y&z **
9 | ** -- FF, GG, HH modified to add in last register done **
10 | ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
11 | ** -- distinct additive constant for each step **
12 | ** -- round 4 added, working mod 7 **
13 | ***********************************************************************
14 | */
15 |
16 | /*
17 | ***********************************************************************
18 | ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
19 | ** **
20 | ** License to copy and use this software is granted provided that **
21 | ** it is identified as the "RSA Data Security, Inc. MD5 Message- **
22 | ** Digest Algorithm" in all material mentioning or referencing this **
23 | ** software or this function. **
24 | ** **
25 | ** License is also granted to make and use derivative works **
26 | ** provided that such works are identified as "derived from the RSA **
27 | ** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
28 | ** material mentioning or referencing the derived work. **
29 | ** **
30 | ** RSA Data Security, Inc. makes no representations concerning **
31 | ** either the merchantability of this software or the suitability **
32 | ** of this software for any particular purpose. It is provided "as **
33 | ** is" without express or implied warranty of any kind. **
34 | ** **
35 | ** These notices must be retained in any copies of any part of this **
36 | ** documentation and/or software. **
37 | ***********************************************************************
38 | */
39 |
40 | #ifndef MD5_H
41 | #define MD5_H
42 |
43 | #include
44 |
45 | /* Data structure for MD5 (Message-Digest) computation */
46 | typedef struct {
47 | uint32_t i[2]; /* number of _bits_ handled mod 2^64 */
48 | uint32_t buf[4]; /* scratch buffer */
49 | unsigned char in[64]; /* input buffer */
50 | unsigned char digest[16]; /* actual digest after MD5Final call */
51 | } MD5_CTX;
52 |
53 | void MD5Init ( MD5_CTX *mdContext);
54 | void MD5Update( MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen);
55 | void MD5Final ( unsigned char hash[], MD5_CTX *mdContext);
56 |
57 | #endif /* MD5_H */
58 |
--------------------------------------------------------------------------------
/memperf/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 SummerGift (summergift2019@gmail.com)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/memperf/README.md:
--------------------------------------------------------------------------------
1 | # Memory Performance Testing
2 |
3 | ## 1. 介绍
4 |
5 | 这是一个运行在 RT-Thread 上的内存性能测试软件包,用于对 ARM CPU 的 内存性能评估,可适用于如下场景:
6 |
7 | - 评估不同类型内存的读写性能
8 | - 对于带有 cache 的 CPU,可用于评估 cache 性能
9 |
10 | 非常欢迎小伙伴们在运行完测试程序后,将相关测试结果 PR 到 [测试示例](#测试示例) 中以供他人参考。
11 |
12 | ### 1.1 目录结构
13 |
14 | | 名称 | 说明 |
15 | | ---- | ---- |
16 | | inc | 头文件目录 |
17 | | src | 源代码目录 |
18 |
19 | ### 1.2 许可证
20 |
21 | `MemoryPerf` 软件包遵循 MIT 许可,详见 `LICENSE` 文件。
22 |
23 | ### 1.3 依赖
24 |
25 | 具有良好的移植性,无操作系统依赖。
26 |
27 | ## 2. 下载方式
28 |
29 | 使用 `MemoryPerf package` 需要在 RT-Thread 的包管理器中选择它,具体路径如下:
30 |
31 | ```
32 | RT-Thread online packages
33 | tools packages --->
34 | [*] MemoryPerf: Memory Performance Testing for ARM CPU.
35 | ```
36 |
37 | 然后让 RT-Thread 的包管理器自动更新,或者使用 `pkgs --update` 命令更新包到 BSP 中。
38 |
39 | ## 3. 使用方法
40 |
41 | - 在 `msh` 中运行 `` 命令
42 |
43 | ## 4. 注意事项
44 |
45 | - 检查内存测试地址与长度是否设置正确
46 | - 测试内存性能时推荐对比打开 cache 与 关闭 cache 的测试结果
47 |
48 | ## 5. 联系方式
49 |
50 | * 维护:我夏了夏天 (SummerGift)
51 | * 主页:https://github.com/SummerLife
52 |
53 | ## 测试示例
54 |
55 | ### 6.1 示例一
56 |
57 | 测试环境 `zynq7045 Cortex-A9 800M SDRAM uncached GCC -O3` :
58 |
59 | ```shell
60 | msh />memory_perf 0x10100000 0x100000
61 | Memory performance testing start...
62 | address: 0x10100000, length: 0x100000
63 | Data length : 209 MB.
64 | --------------------------------------
65 | 8-bit write speed test begin.
66 | Spend time : 7.480000 s.
67 | 8-bit write speed: 28.036793 M/s.
68 | 8-bit read speed test begin.
69 | Spend time : 5.380000 s.
70 | 8-bit Read speed: 38.980518 M/s.
71 | --------------------------------------
72 | 16-bit write speed test begin.
73 | Spend time : 3.740000 s.
74 | 16-bit write speed: 56.073586 M/s.
75 | 16-bit read speed test begin.
76 | Spend time : 2.690000 s.
77 | 16-bit Read speed: 77.961037 M/s.
78 | --------------------------------------
79 | 32-bit write speed test begin.
80 | Spend time : 1.870000 s.
81 | 32-bit Write speed: 112.147171 M/s.
82 | 32-bit read speed test begin.
83 | Spend time : 1.350000 s.
84 | 32-bit Read speed: 155.344589 M/s.
85 | Memory performance completed.
86 | ```
87 |
88 | ### 6.2 示例二
89 |
90 | 测试环境 `zynq7045 Cortex-A9 800M SDRAM cached GCC -O3` :
91 |
92 | ```shell
93 | msh />memory_perf 0x10100000 0x100000 # Testing with cache
94 | Memory performance testing start...
95 | address: 0x10100000, length: 0x100000
96 | Data length : 209 MB.
97 | --------------------------------------
98 | 8-bit write speed test begin.
99 | Spend time : 0.290000 s.
100 | 8-bit write speed: 723.155884 M/s. # Achieve the best write performance
101 | 8-bit read speed test begin.
102 | Spend time : 0.490000 s.
103 | 8-bit Read speed: 427.990204 M/s.
104 | --------------------------------------
105 | 16-bit write speed test begin.
106 | Spend time : 0.290000 s.
107 | 16-bit write speed: 723.155884 M/s. # Achieve the best write performance
108 | 16-bit read speed test begin.
109 | Spend time : 0.410000 s.
110 | 16-bit Read speed: 511.500488 M/s.
111 | --------------------------------------
112 | 32-bit write speed test begin.
113 | Spend time : 0.290000 s.
114 | 32-bit Write speed: 723.155884 M/s. # Achieve the best write performance
115 | 32-bit read speed test begin.
116 | Spend time : 0.370000 s.
117 | 32-bit Read speed: 566.797852 M/s.
118 | Memory performance completed.
119 | ```
120 |
121 | ### 6.3 示例三
122 |
123 | 测试环境 `stm32f407-atk-explorer Cortex-M4 168M SRAM uncached GCC -O3` :
124 |
125 | ```shell
126 | msh >memory_perf 0x20010000 0x10000
127 | Memory performance testing start...
128 | address: 0x20010000, length: 0x10000, iterations: 200
129 | Data length : 13 MB.
130 | --------------------------------------
131 | 8-bit write speed test begin.
132 | Spend time : 0.139000 s.
133 | 8-bit write speed: 94.296402 M/s.
134 | 8-bit read speed test begin.
135 | Spend time : 0.361000 s.
136 | 8-bit Read speed: 36.308033 M/s.
137 | --------------------------------------
138 | 16-bit write speed test begin.
139 | Spend time : 0.070000 s.
140 | 16-bit write speed: 187.245712 M/s.
141 | 16-bit read speed test begin.
142 | Spend time : 0.180000 s.
143 | 16-bit Read speed: 72.817780 M/s.
144 | --------------------------------------
145 | 32-bit write speed test begin.
146 | Spend time : 0.035000 s.
147 | 32-bit Write speed: 374.491425 M/s.
148 | 32-bit read speed test begin.
149 | Spend time : 0.090000 s.
150 | 32-bit Read speed: 145.635559 M/s.
151 | Memory performance completed.
152 | ```
153 |
154 | ### 6.4 示例四
155 |
156 | 测试环境 `stm32f407-atk-explorer Cortex-M4 168M SRAM uncached ARM(AC6) -O3` :
157 |
158 | ```shell
159 | msh >memory_perf 0x20010000 0x10000
160 | Memory performance testing start...
161 | address: 20010000, length: 0x10000, iterations: 200
162 | Data length : 13 MB.
163 | --------------------------------------
164 | 8-bit write speed test begin.
165 | Spend time : 0.094000 s.
166 | 8-bit write speed: 139.438309 M/s.
167 | 8-bit read speed test begin.
168 | Spend time : 0.268000 s.
169 | 8-bit Read speed: 48.907459 M/s.
170 | --------------------------------------
171 | 16-bit write speed test begin.
172 | Spend time : 0.047000 s.
173 | 16-bit write speed: 278.876617 M/s.
174 | 16-bit read speed test begin.
175 | Spend time : 0.134000 s.
176 | 16-bit Read speed: 97.814919 M/s.
177 | --------------------------------------
178 | 32-bit write speed test begin.
179 | Spend time : 0.023000 s.
180 | 32-bit Write speed: 569.878296 M/s.
181 | 32-bit read speed test begin.
182 | Spend time : 0.068000 s.
183 | 32-bit Read speed: 192.752930 M/s.
184 | Memory performance completed.
185 | ```
186 |
187 | ### 6.5 示例五
188 |
189 | 测试环境 `stm32l475-atk-Pandora Cortex-M4 80M SRAM uncached GCC -O3` :
190 |
191 | ```shell
192 | msh >memory_perf 0x20008000 0xa000
193 | Memory performance testing start...
194 | address: 0x20008000, length: 0xa000, iterations: 200
195 | Data length : 8 MB.
196 | --------------------------------------
197 | 8-bit write speed test begin.
198 | Spend time : 0.180000 s.
199 | 8-bit write speed: 45.511108 M/s.
200 | 8-bit read speed test begin.
201 | Spend time : 0.449000 s.
202 | 8-bit Read speed: 18.244987 M/s.
203 | --------------------------------------
204 | 16-bit write speed test begin.
205 | Spend time : 0.090000 s.
206 | 16-bit write speed: 91.022217 M/s.
207 | 16-bit read speed test begin.
208 | Spend time : 0.225000 s.
209 | 16-bit Read speed: 36.408890 M/s.
210 | --------------------------------------
211 | 32-bit write speed test begin.
212 | Spend time : 0.045000 s.
213 | 32-bit Write speed: 182.044434 M/s.
214 | 32-bit read speed test begin.
215 | Spend time : 0.113000 s.
216 | 32-bit Read speed: 72.495575 M/s.
217 | Memory performance completed.
218 | ```
219 |
220 |
--------------------------------------------------------------------------------
/memperf/SConscript:
--------------------------------------------------------------------------------
1 | from building import *
2 |
3 | src = Glob('*.c') + Glob('*.cpp')
4 | cwd = GetCurrentDir()
5 |
6 | CPPPATH = [cwd]
7 | group = DefineGroup('', src, depend = [''], CPPPATH=CPPPATH)
8 |
9 | Return('group')
10 |
--------------------------------------------------------------------------------
/memperf/main.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main(int argc, char *argv[])
4 | {
5 | extern int memory_perf(void);
6 | memory_perf();
7 |
8 | return 0;
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/memperf/mem_perf.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 SummerGift (summergift2019@gmail.com)
3 | *
4 | * MIT License
5 | *
6 | * Change Logs:
7 | * Date Author Notes
8 | * 2020-11-27 SummerGift first version
9 | * 2020-11-28 SummerGift optimize cmd
10 | */
11 |
12 | #include
13 | #include "portme.h"
14 |
15 | #define __version__ "1.0.0"
16 |
17 | #define ITERATIONS 200
18 |
19 | static mp_u32 data_len;
20 |
21 | static void memory_perf_8bit(void *addr, mp_u32 len)
22 | {
23 | volatile mp_u8 *read_addr;
24 | mp_f32 seconds, speed;
25 |
26 |
27 | printf("--------------------------------------\n");
28 | printf("8-bit write speed test begin.\n");
29 |
30 | start_time_mp();
31 | for(int i = 0; i < ITERATIONS; i++)
32 | {
33 | for(int i = 0; i < len; i+=8)
34 | {
35 | read_addr = (mp_u8 *) (addr + i);
36 | *read_addr++ = 0x55;
37 | *read_addr++ = 0x55;
38 | *read_addr++ = 0x55;
39 | *read_addr++ = 0x55;
40 | *read_addr++ = 0x55;
41 | *read_addr++ = 0x55;
42 | *read_addr++ = 0x55;
43 | *read_addr++ = 0x55;
44 | }
45 | }
46 | stop_time_mp();
47 |
48 | seconds = (unsigned int) get_time_mp() / (NSECS_PER_SEC * 1.0);
49 | speed = data_len / seconds;
50 |
51 | printf("Spend time : %f s.\n", seconds);
52 | printf("8-bit write speed: %f M/s.\n", speed / 1000000);
53 |
54 | printf("8-bit read speed test begin.\n");
55 |
56 | start_time_mp();
57 | for(int i = 0; i < ITERATIONS; i++)
58 | {
59 | for(int i = 0; i < len; i+=8)
60 | {
61 | read_addr = (mp_u8 *) (addr + i);
62 | __asm volatile ("ldrb r0, [%0]\n"
63 | ::"r"(read_addr++): "r0");
64 | __asm volatile ("ldrb r0, [%0]\n"
65 | ::"r"(read_addr++): "r0");
66 | __asm volatile ("ldrb r0, [%0]\n"
67 | ::"r"(read_addr++): "r0");
68 | __asm volatile ("ldrb r0, [%0]\n"
69 | ::"r"(read_addr++): "r0");
70 | __asm volatile ("ldrb r0, [%0]\n"
71 | ::"r"(read_addr++): "r0");
72 | __asm volatile ("ldrb r0, [%0]\n"
73 | ::"r"(read_addr++): "r0");
74 | __asm volatile ("ldrb r0, [%0]\n"
75 | ::"r"(read_addr++): "r0");
76 | __asm volatile ("ldrb r0, [%0]\n"
77 | ::"r"(read_addr): "r0");
78 | }
79 | }
80 | stop_time_mp();
81 |
82 | seconds = (unsigned int) get_time_mp() / (NSECS_PER_SEC * 1.0);
83 | speed = data_len / seconds;
84 |
85 | printf("Spend time : %f s.\n", seconds);
86 | printf("8-bit Read speed: %f M/s.\n", speed / 1000000);
87 | }
88 |
89 | static void memory_perf_16bit(void *addr, mp_u32 len)
90 | {
91 | volatile mp_u16 *read_addr;
92 | mp_f32 seconds, speed;
93 |
94 | printf("--------------------------------------\n");
95 | printf("16-bit write speed test begin.\n");
96 |
97 | start_time_mp();
98 | for(int i = 0; i < ITERATIONS; i++)
99 | {
100 | for(int i = 0; i < len; i += 16)
101 | {
102 | read_addr = (mp_u16 *) (addr + i);
103 | *read_addr++ = 0x55;
104 | *read_addr++ = 0x55;
105 | *read_addr++ = 0x55;
106 | *read_addr++ = 0x55;
107 | *read_addr++ = 0x55;
108 | *read_addr++ = 0x55;
109 | *read_addr++ = 0x55;
110 | *read_addr++ = 0x55;
111 | }
112 | }
113 | stop_time_mp();
114 |
115 | seconds = (unsigned int) get_time_mp() / (NSECS_PER_SEC * 1.0);
116 | speed = data_len / seconds;
117 |
118 | printf("Spend time : %f s.\n", seconds);
119 | printf("16-bit write speed: %f M/s.\n", speed / 1000000);
120 |
121 | printf("16-bit read speed test begin.\n");
122 |
123 | start_time_mp();
124 | for(int i = 0; i < ITERATIONS; i++)
125 | {
126 | for(int i = 0; i < len; i += 16)
127 | {
128 | read_addr = (mp_u16 *) (addr + i);
129 | __asm volatile ("ldrh r0, [%0]\n"
130 | ::"r"(read_addr++): "r0");
131 | __asm volatile ("ldrh r0, [%0]\n"
132 | ::"r"(read_addr++): "r0");
133 | __asm volatile ("ldrh r0, [%0]\n"
134 | ::"r"(read_addr++): "r0");
135 | __asm volatile ("ldrh r0, [%0]\n"
136 | ::"r"(read_addr++): "r0");
137 | __asm volatile ("ldrh r0, [%0]\n"
138 | ::"r"(read_addr++): "r0");
139 | __asm volatile ("ldrh r0, [%0]\n"
140 | ::"r"(read_addr++): "r0");
141 | __asm volatile ("ldrh r0, [%0]\n"
142 | ::"r"(read_addr++): "r0");
143 | __asm volatile ("ldrh r0, [%0]\n"
144 | ::"r"(read_addr): "r0");
145 | }
146 | }
147 | stop_time_mp();
148 |
149 | seconds = (unsigned int) get_time_mp() / (NSECS_PER_SEC * 1.0);
150 | speed = data_len / seconds;
151 |
152 | printf("Spend time : %f s.\n", seconds);
153 | printf("16-bit Read speed: %f M/s.\n", speed / 1000000);
154 | }
155 |
156 | static void memory_perf_32bit(void *addr, mp_u32 len)
157 | {
158 | volatile mp_u32 *read_addr;
159 | mp_f32 seconds, speed;
160 |
161 | printf("--------------------------------------\n");
162 | printf("32-bit write speed test begin.\n");
163 |
164 | start_time_mp();
165 | for(int i = 0; i < ITERATIONS; i++)
166 | {
167 | for(int i = 0; i < len; i += 32)
168 | {
169 | read_addr = (mp_u32 *) (addr + i);
170 | *read_addr++ = 0x55;
171 | *read_addr++ = 0x55;
172 | *read_addr++ = 0x55;
173 | *read_addr++ = 0x55;
174 | *read_addr++ = 0x55;
175 | *read_addr++ = 0x55;
176 | *read_addr++ = 0x55;
177 | *read_addr++ = 0x55;
178 | }
179 | }
180 | stop_time_mp();
181 |
182 | seconds = (unsigned int) get_time_mp() / (NSECS_PER_SEC * 1.0);
183 | speed = data_len / seconds;
184 |
185 | printf("Spend time : %f s.\n", seconds);
186 | printf("32-bit Write speed: %f M/s.\n", speed / 1000000);
187 |
188 | printf("32-bit read speed test begin.\n");
189 |
190 | start_time_mp();
191 | for(int i = 0; i < ITERATIONS; i++)
192 | {
193 | for(int i = 0; i < len; i += 32)
194 | {
195 | read_addr = (mp_u32 *) (addr + i);
196 | __asm volatile ("ldr r0, [%0]\n"
197 | ::"r"(read_addr++): "r0");
198 | __asm volatile ("ldr r0, [%0]\n"
199 | ::"r"(read_addr++): "r0");
200 | __asm volatile ("ldr r0, [%0]\n"
201 | ::"r"(read_addr++): "r0");
202 | __asm volatile ("ldr r0, [%0]\n"
203 | ::"r"(read_addr++): "r0");
204 | __asm volatile ("ldr r0, [%0]\n"
205 | ::"r"(read_addr++): "r0");
206 | __asm volatile ("ldr r0, [%0]\n"
207 | ::"r"(read_addr++): "r0");
208 | __asm volatile ("ldr r0, [%0]\n"
209 | ::"r"(read_addr++): "r0");
210 | __asm volatile ("ldr r0, [%0]\n"
211 | ::"r"(read_addr): "r0");
212 | }
213 | }
214 | stop_time_mp();
215 |
216 | seconds = (mp_u32) get_time_mp() / (NSECS_PER_SEC * 1.0);
217 | speed = data_len / seconds;
218 |
219 | printf("Spend time : %f s.\n", seconds);
220 | printf("32-bit Read speed: %f M/s.\n", speed / 1000000);
221 | }
222 |
223 | static void memory_perf(int argc, char** argv)
224 | {
225 | printf("\nMemoryPerf version " __version__ " \n");
226 | printf("Copyright (c) 2020 SummerGift (summergift2019@gmail.com)\n");
227 | printf("Licensed under the MIT License version.\n\n");
228 |
229 | if (argc != 3)
230 | {
231 | printf("Please set test address and length correctly.\n");
232 | printf("Example: \n");
233 | return;
234 | }
235 |
236 | void *address = (void *)strtol(argv[1] + 2, NULL, 16);
237 | mp_u32 len = (mp_u32)strtol(argv[2] + 2, NULL, 16);
238 | data_len = ITERATIONS * len;
239 |
240 | printf("Memory performance testing start...\n");
241 | printf("address: %p, length: 0x%x, iterations: %d\n", address, len, ITERATIONS);
242 | printf("Data length : %u MB.\n", data_len / 1000000);
243 |
244 | memory_perf_8bit(address, len);
245 | memory_perf_16bit(address, len);
246 | memory_perf_32bit(address, len);
247 |
248 | printf("Memory performance completed.\n");
249 | }
250 | MSH_CMD_EXPORT(memory_perf, run memory performance test);
251 |
--------------------------------------------------------------------------------
/memperf/portme.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 SummerGift (summergift2019@gmail.com)
3 | *
4 | * MIT License
5 | *
6 | * Change Logs:
7 | * Date Author Notes
8 | * 2020-11-27 SummerGift first version
9 | */
10 |
11 | #include "portme.h"
12 |
13 | static CORETIMETYPE start_time_val, stop_time_val;
14 |
15 | void start_time_mp(void)
16 | {
17 | GETMYTIME(&start_time_val);
18 | }
19 |
20 | void stop_time_mp(void)
21 | {
22 | GETMYTIME(&stop_time_val);
23 | }
24 |
25 | CORETIMETYPE get_time_mp(void)
26 | {
27 | CORETIMETYPE elapsed = (CORETIMETYPE) (MYTIMEDIFF(stop_time_val, start_time_val));
28 | return elapsed;
29 | }
30 |
--------------------------------------------------------------------------------
/memperf/portme.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 SummerGift (summergift2019@gmail.com)
3 | *
4 | * MIT License
5 | *
6 | * Change Logs:
7 | * Date Author Notes
8 | * 2020-11-27 SummerGift first version
9 | */
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | typedef unsigned char mp_u8;
16 | typedef unsigned short mp_u16;
17 | typedef unsigned int mp_u32;
18 | typedef float mp_f32;
19 |
20 | #define NSECS_PER_SEC RT_TICK_PER_SECOND
21 | #define CORETIMETYPE rt_tick_t
22 | #define MYTIMEDIFF(fin,ini) ((fin)-(ini))
23 | #define GETMYTIME(_t) (*_t=rt_tick_get())
24 |
25 | void start_time_mp(void);
26 | void stop_time_mp(void);
27 | CORETIMETYPE get_time_mp(void);
28 |
--------------------------------------------------------------------------------
/tools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RT-Thread/rtthread-apps/55e31c7262e65f22cccecb83369682d1553a6230/tools/__init__.py
--------------------------------------------------------------------------------
/tools/host/building.py:
--------------------------------------------------------------------------------
1 | #
2 | # File : building.py
3 | # This file is part of RT-Thread RTOS
4 | # COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team
5 | #
6 | # This program is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 2 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License along
17 | # with this program; if not, write to the Free Software Foundation, Inc.,
18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 | #
20 | # Change Logs:
21 | # Date Author Notes
22 | # 2015-01-20 Bernard Add copyright information
23 | #
24 |
25 | import os
26 | import sys
27 | import string
28 |
29 | from SCons.Script import *
30 |
31 | BuildOptions = {}
32 | Projects = []
33 | Env = None
34 |
35 | def GetCurrentDir():
36 | conscript = File('SConscript')
37 | fn = conscript.rfile()
38 | name = fn.name
39 | path = os.path.dirname(fn.abspath)
40 | return path
41 |
42 | def PrepareHostModuleBuilding(env):
43 | global Env
44 | Env = env;
45 |
46 | def GetDepend(depend):
47 | # always true
48 | return True
49 |
50 | def MergeGroup(src_group, group):
51 | src_group['src'] = src_group['src'] + group['src']
52 | if group.has_key('CCFLAGS'):
53 | if src_group.has_key('CCFLAGS'):
54 | src_group['CCFLAGS'] = src_group['CCFLAGS'] + group['CCFLAGS']
55 | else:
56 | src_group['CCFLAGS'] = group['CCFLAGS']
57 | if group.has_key('CPPPATH'):
58 | if src_group.has_key('CPPPATH'):
59 | src_group['CPPPATH'] = src_group['CPPPATH'] + group['CPPPATH']
60 | else:
61 | src_group['CPPPATH'] = group['CPPPATH']
62 | if group.has_key('CPPDEFINES'):
63 | if src_group.has_key('CPPDEFINES'):
64 | src_group['CPPDEFINES'] = src_group['CPPDEFINES'] + group['CPPDEFINES']
65 | else:
66 | src_group['CPPDEFINES'] = group['CPPDEFINES']
67 |
68 | # for local CCFLAGS/CPPPATH/CPPDEFINES
69 | if group.has_key('LOCAL_CCFLAGS'):
70 | if src_group.has_key('LOCAL_CCFLAGS'):
71 | src_group['LOCAL_CCFLAGS'] = src_group['LOCAL_CCFLAGS'] + group['LOCAL_CCFLAGS']
72 | else:
73 | src_group['LOCAL_CCFLAGS'] = group['LOCAL_CCFLAGS']
74 | if group.has_key('LOCAL_CPPPATH'):
75 | if src_group.has_key('LOCAL_CPPPATH'):
76 | src_group['LOCAL_CPPPATH'] = src_group['LOCAL_CPPPATH'] + group['LOCAL_CPPPATH']
77 | else:
78 | src_group['LOCAL_CPPPATH'] = group['LOCAL_CPPPATH']
79 | if group.has_key('LOCAL_CPPDEFINES'):
80 | if src_group.has_key('LOCAL_CPPDEFINES'):
81 | src_group['LOCAL_CPPDEFINES'] = src_group['LOCAL_CPPDEFINES'] + group['LOCAL_CPPDEFINES']
82 | else:
83 | src_group['LOCAL_CPPDEFINES'] = group['LOCAL_CPPDEFINES']
84 |
85 | if group.has_key('LINKFLAGS'):
86 | if src_group.has_key('LINKFLAGS'):
87 | src_group['LINKFLAGS'] = src_group['LINKFLAGS'] + group['LINKFLAGS']
88 | else:
89 | src_group['LINKFLAGS'] = group['LINKFLAGS']
90 | if group.has_key('LIBS'):
91 | if src_group.has_key('LIBS'):
92 | src_group['LIBS'] = src_group['LIBS'] + group['LIBS']
93 | else:
94 | src_group['LIBS'] = group['LIBS']
95 | if group.has_key('LIBPATH'):
96 | if src_group.has_key('LIBPATH'):
97 | src_group['LIBPATH'] = src_group['LIBPATH'] + group['LIBPATH']
98 | else:
99 | src_group['LIBPATH'] = group['LIBPATH']
100 |
101 | def DefineGroup(name, src, depend, **parameters):
102 | global Env
103 | if not GetDepend(depend):
104 | return []
105 |
106 | # find exist group and get path of group
107 | group_path = ''
108 | for g in Projects:
109 | if g['name'] == name:
110 | group_path = g['path']
111 | if group_path == '':
112 | group_path = GetCurrentDir()
113 |
114 | group = parameters
115 | group['name'] = name
116 | group['path'] = group_path
117 | if type(src) == type(['src1']):
118 | group['src'] = File(src)
119 | else:
120 | group['src'] = src
121 |
122 | if group.has_key('CCFLAGS'):
123 | Env.Append(CCFLAGS = group['CCFLAGS'])
124 | if group.has_key('CPPPATH'):
125 | Env.Append(CPPPATH = group['CPPPATH'])
126 | if group.has_key('CPPDEFINES'):
127 | Env.Append(CPPDEFINES = group['CPPDEFINES'])
128 | if group.has_key('LINKFLAGS'):
129 | Env.Append(LINKFLAGS = group['LINKFLAGS'])
130 |
131 | if group.has_key('LIBS'):
132 | Env.Append(LIBS = group['LIBS'])
133 | if group.has_key('LIBPATH'):
134 | Env.Append(LIBPATH = group['LIBPATH'])
135 |
136 | if group.has_key('LIBRARY'):
137 | objs = Env.Library(name, group['src'])
138 | else:
139 | objs = group['src']
140 |
141 | # merge group
142 | for g in Projects:
143 | if g['name'] == name:
144 | # merge to this group
145 | MergeGroup(g, group)
146 | return objs
147 |
148 | # add a new group
149 | Projects.append(group)
150 |
151 | return objs
152 |
--------------------------------------------------------------------------------
/tools/host/rtthread/SConscript:
--------------------------------------------------------------------------------
1 | from building import *
2 |
3 | src = Glob('*.c') + Glob('*.cpp')
4 | cwd = GetCurrentDir()
5 |
6 | CPPPATH = [cwd]
7 | CPPDEFINES = ['HOST_BUILD']
8 |
9 | group = DefineGroup('RT-Thread', src, depend = [''], CPPPATH=CPPPATH, CPPDEFINES = CPPDEFINES)
10 |
11 | Return('group')
12 |
--------------------------------------------------------------------------------
/tools/host/rtthread/finsh.h:
--------------------------------------------------------------------------------
1 | #ifndef FINSH_H__
2 | #define FINSH_H__
3 |
4 | #define MSH_CMD_EXPORT(command, desc)
5 | #define MSH_CMD_EXPORT_ALIAS(command, alias, desc)
6 |
7 | #define FINSH_FUNCTION_EXPORT(name, desc)
8 | #define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc)
9 |
10 | #endif
11 |
--------------------------------------------------------------------------------
/tools/host/rtthread/rthw.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RT-Thread/rtthread-apps/55e31c7262e65f22cccecb83369682d1553a6230/tools/host/rtthread/rthw.h
--------------------------------------------------------------------------------
/tools/host/rtthread/rtthread.c:
--------------------------------------------------------------------------------
1 | #include "rtthread.h"
2 |
3 | #include
4 |
5 | void rt_kprintf(const char *fmt, ...)
6 | {
7 | va_list argptr;
8 |
9 | va_start(argptr,fmt);
10 | vprintf(fmt,argptr);
11 | va_end(argptr);
12 |
13 | return ;
14 | }
15 |
16 | rt_tick_t rt_tick_get(void)
17 | {
18 | return 0;
19 | }
20 |
21 | void *rt_malloc(rt_size_t nbytes)
22 | {
23 | void* ret = malloc(nbytes);
24 |
25 | return ret;
26 | }
27 |
28 | void rt_free(void *ptr)
29 | {
30 | free(ptr);
31 | }
32 |
33 | int rt_hw_interrupt_disable(void)
34 | {
35 | return 0;
36 | }
37 |
38 | void rt_hw_interrupt_enable(int level)
39 | {
40 | return ;
41 | }
42 |
--------------------------------------------------------------------------------
/tools/host/rtthread/rtthread.h:
--------------------------------------------------------------------------------
1 | #ifndef RTTHREAD_H__
2 | #define RTTHREAD_H__
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #ifdef __cplusplus
11 | extern "C" {
12 | #endif
13 |
14 | #define RT_USING_DFS
15 | #define RT_USING_DEVICE
16 | #define RT_TICK_PER_SECOND 100
17 | #define RT_CONSOLEBUF_SIZE 256
18 |
19 | #define RT_NULL NULL
20 | #define RT_ASSERT(EX) \
21 | if (!(EX)) \
22 | { \
23 | printf(#EX); \
24 | exit(-1); \
25 | }
26 |
27 | #define rt_vsnprintf vsnprintf
28 |
29 | typedef size_t rt_size_t;
30 | typedef uint32_t rt_tick_t;
31 |
32 | void rt_kprintf(const char *fmt, ...);
33 | rt_tick_t rt_tick_get(void);
34 |
35 | void *rt_malloc(rt_size_t nbytes);
36 | void rt_free(void *ptr);
37 |
38 | int rt_hw_interrupt_disable(void);
39 | void rt_hw_interrupt_enable(int level);
40 |
41 | #ifdef __cplusplus
42 | }
43 | #endif
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/tools/ua.def:
--------------------------------------------------------------------------------
1 | EXPORTS
2 | main
3 |
--------------------------------------------------------------------------------
/tools/ua.py:
--------------------------------------------------------------------------------
1 | # File : ua.py
2 | # Tool Script for building User Applications
3 | # This file is part of RT-Thread RTOS
4 | # COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team
5 | #
6 | # This program is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 2 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License along
17 | # with this program; if not, write to the Free Software Foundation, Inc.,
18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 | #
20 | # Change Logs:
21 | # Date Author Notes
22 | # 2015-02-07 Bernard The firstly version
23 | #
24 |
25 | import os
26 | import sys
27 | from SCons.Script import *
28 |
29 | Rtt_Root = ''
30 | BSP_Root = ''
31 | Env = None
32 |
33 | def BuildEnv(BSP_ROOT, RTT_ROOT):
34 | if BSP_ROOT == None:
35 | if os.getenv('BSP_ROOT'):
36 | BSP_ROOT = os.getenv('BSP_ROOT')
37 | else:
38 | print 'Please set BSP(board support package) directory!'
39 | exit(-1)
40 |
41 | if not os.path.exists(BSP_ROOT):
42 | print 'No BSP(board support package) directory found!'
43 | exit(-1)
44 |
45 | if RTT_ROOT == None:
46 | # get RTT_ROOT from BSP_ROOT
47 | sys.path = sys.path + [BSP_ROOT]
48 | try:
49 | import rtconfig
50 | RTT_ROOT = rtconfig.RTT_ROOT
51 | except Exception as e:
52 | print 'Import rtconfig.py in BSP(board support package) failed.'
53 | print e
54 | exit(-1)
55 |
56 | global Rtt_Root
57 | global BSP_Root
58 |
59 | Rtt_Root = RTT_ROOT
60 | BSP_Root = BSP_ROOT
61 |
62 | def BuildHostApplication(TARGET, SConscriptFile):
63 | import platform
64 |
65 | platform_type = platform.system()
66 | if platform_type == 'Windows' or platform_type.find('MINGW') != -1:
67 | TARGET = TARGET.replace('.mo', '.exe')
68 |
69 | sys.path = sys.path + [os.path.join(os.getcwd(), 'tools', 'host')]
70 |
71 | from building import PrepareHostModuleBuilding
72 |
73 | HostRtt = os.path.join(os.getcwd(), 'tools', 'host', 'rtthread')
74 | Env = Environment()
75 |
76 | if not GetOption('verbose'):
77 | # override the default verbose command string
78 | Env.Replace(
79 | ARCOMSTR = 'AR $TARGET',
80 | ASCOMSTR = 'AS $TARGET',
81 | ASPPCOMSTR = 'AS $TARGET',
82 | CCCOMSTR = 'CC $TARGET',
83 | CXXCOMSTR = 'CXX $TARGET',
84 | LINKCOMSTR = 'LINK $TARGET'
85 | )
86 |
87 | PrepareHostModuleBuilding(Env)
88 |
89 | objs = SConscript(SConscriptFile)
90 | objs += SConscript(HostRtt + '/SConscript')
91 |
92 | target = Env.Program(TARGET, objs)
93 | return
94 |
95 | def BuildHostLibrary(TARGET, SConscriptFile):
96 | import platform
97 |
98 | platform_type = platform.system()
99 | if platform_type == 'Windows' or platform_type.find('MINGW') != -1:
100 | TARGET = TARGET.replace('.mo', '.exe')
101 |
102 | sys.path = sys.path + [os.path.join(os.getcwd(), 'tools', 'host')]
103 |
104 | from building import PrepareHostModuleBuilding
105 |
106 | HostRtt = os.path.join(os.getcwd(), 'tools', 'host', 'rtthread')
107 | Env = Environment()
108 |
109 | if not GetOption('verbose'):
110 | # override the default verbose command string
111 | Env.Replace(
112 | ARCOMSTR = 'AR $TARGET',
113 | ASCOMSTR = 'AS $TARGET',
114 | ASPPCOMSTR = 'AS $TARGET',
115 | CCCOMSTR = 'CC $TARGET',
116 | CXXCOMSTR = 'CXX $TARGET',
117 | LINKCOMSTR = 'LINK $TARGET'
118 | )
119 |
120 | PrepareHostModuleBuilding(Env)
121 |
122 | objs = SConscript(SConscriptFile)
123 | objs += SConscript(HostRtt + '/SConscript')
124 |
125 | target = Env.Program(TARGET, objs)
126 | return
127 |
128 |
129 | def BuildApplication(TARGET, SConscriptFile, BSP_ROOT = None, RTT_ROOT = None):
130 | global Env
131 | global Rtt_Root
132 | global BSP_Root
133 |
134 | # add comstr option
135 | AddOption('--verbose',
136 | dest='verbose',
137 | action='store_true',
138 | default=False,
139 | help='print verbose information during build')
140 |
141 | # build application in host
142 | if BSP_ROOT == None and RTT_ROOT == None and not os.getenv('BSP_ROOT'):
143 | BuildHostApplication(TARGET, SConscriptFile)
144 | return
145 |
146 | if RTT_ROOT == None and os.getenv('RTT_ROOT'):
147 | RTT_ROOT = os.getenv('RTT_ROOT')
148 |
149 | # handle BSP_ROOT and RTT_ROOT
150 | BuildEnv(BSP_ROOT, RTT_ROOT)
151 |
152 | sys.path = sys.path + [os.path.join(Rtt_Root, 'tools'), BSP_Root]
153 |
154 | # get configuration from BSP
155 | import rtconfig
156 | from rtua import GetCPPPATH
157 | from rtua import GetCPPDEFINES
158 | from building import PrepareModuleBuilding
159 |
160 | linkflags = rtconfig.M_LFLAGS + ' -e main'
161 | CPPPATH = GetCPPPATH(BSP_Root, Rtt_Root)
162 |
163 | if rtconfig.PLATFORM == 'cl':
164 | Env = Environment(TARGET_ARCH='x86')
165 | Env.Append(CCFLAGS=rtconfig.M_CFLAGS)
166 | Env.Append(LINKFLAGS=rtconfig.M_LFLAGS)
167 | Env.Append(CPPPATH=CPPPATH)
168 | Env.Append(LIBS='rtthread', LIBPATH=BSP_Root)
169 | Env.Append(CPPDEFINES=GetCPPDEFINES() + ['RTT_IN_MODULE'])
170 | Env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
171 | else:
172 | Env = Environment(tools = ['mingw'],
173 | AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
174 | CC = rtconfig.CC, CCFLAGS = rtconfig.M_CFLAGS,
175 | CPPDEFINES = GetCPPDEFINES(),
176 | CXX = rtconfig.CXX, AR = rtconfig.AR, ARFLAGS = '-rc',
177 | LINK = rtconfig.LINK, LINKFLAGS = linkflags,
178 | CPPPATH = CPPPATH)
179 |
180 | if not GetOption('verbose'):
181 | # override the default verbose command string
182 | Env.Replace(
183 | ARCOMSTR = 'AR $TARGET',
184 | ASCOMSTR = 'AS $TARGET',
185 | ASPPCOMSTR = 'AS $TARGET',
186 | CCCOMSTR = 'CC $TARGET',
187 | CXXCOMSTR = 'CXX $TARGET',
188 | LINKCOMSTR = 'LINK $TARGET'
189 | )
190 |
191 | PrepareModuleBuilding(Env, Rtt_Root, BSP_Root)
192 |
193 | objs = SConscript(SConscriptFile)
194 |
195 | # build program
196 | if rtconfig.PLATFORM == 'cl':
197 | dll_target = TARGET.replace('.mo', '.dll')
198 | target = Env.SharedLibrary(dll_target, objs)
199 |
200 | target = Command("$TARGET", dll_target, [Move(TARGET, dll_target)])
201 | # target = dll_target
202 | else:
203 | target = Env.Program(TARGET, objs)
204 |
205 | if hasattr(rtconfig, 'M_POST_ACTION'):
206 | Env.AddPostAction(target, rtconfig.M_POST_ACTION)
207 |
208 | if hasattr(rtconfig, 'M_BIN_PATH'):
209 | Env.AddPostAction(target, [Copy(rtconfig.M_BIN_PATH, TARGET)])
210 |
211 | def BuildLibrary(TARGET, SConscriptFile, BSP_ROOT = None, RTT_ROOT = None):
212 | global Env
213 | global Rtt_Root
214 | global BSP_Root
215 |
216 | # add comstr option
217 | AddOption('--verbose',
218 | dest='verbose',
219 | action='store_true',
220 | default=False,
221 | help='print verbose information during build')
222 |
223 | # build application in host
224 | if BSP_ROOT == None and RTT_ROOT == None and not os.getenv('BSP_ROOT'):
225 | BuildHostLibrary(TARGET, SConscriptFile)
226 | return
227 |
228 | if RTT_ROOT == None and os.getenv('RTT_ROOT'):
229 | RTT_ROOT = os.getenv('RTT_ROOT')
230 |
231 | # handle BSP_ROOT and RTT_ROOT
232 | BuildEnv(BSP_ROOT, RTT_ROOT)
233 |
234 | sys.path = sys.path + [os.path.join(Rtt_Root, 'tools'), BSP_Root]
235 |
236 | # get configuration from BSP
237 | import rtconfig
238 | from rtua import GetCPPPATH
239 | from rtua import GetCPPDEFINES
240 | from building import PrepareModuleBuilding
241 |
242 | linkflags = rtconfig.M_LFLAGS + ' -e 0'
243 | CPPPATH = GetCPPPATH(BSP_Root, Rtt_Root)
244 |
245 | if rtconfig.PLATFORM == 'cl':
246 | Env = Environment(TARGET_ARCH='x86')
247 | Env.Append(CCFLAGS=rtconfig.M_CFLAGS)
248 | Env.Append(LINKFLAGS=rtconfig.M_LFLAGS)
249 | Env.Append(CPPPATH=CPPPATH)
250 | Env.Append(LIBS='rtthread', LIBPATH=BSP_Root)
251 | Env.Append(CPPDEFINES=GetCPPDEFINES() + ['RTT_IN_MODULE'])
252 | Env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
253 | else:
254 | Env = Environment(tools = ['mingw'],
255 | AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
256 | CC = rtconfig.CC, CCFLAGS = rtconfig.M_CFLAGS,
257 | CPPDEFINES = GetCPPDEFINES(),
258 | CXX = rtconfig.CXX, AR = rtconfig.AR, ARFLAGS = '-rc',
259 | LINK = rtconfig.LINK, LINKFLAGS = linkflags,
260 | CPPPATH = CPPPATH)
261 |
262 | if not GetOption('verbose'):
263 | # override the default verbose command string
264 | Env.Replace(
265 | ARCOMSTR = 'AR $TARGET',
266 | ASCOMSTR = 'AS $TARGET',
267 | ASPPCOMSTR = 'AS $TARGET',
268 | CCCOMSTR = 'CC $TARGET',
269 | CXXCOMSTR = 'CXX $TARGET',
270 | LINKCOMSTR = 'LINK $TARGET'
271 | )
272 |
273 | PrepareModuleBuilding(Env, Rtt_Root, BSP_Root)
274 |
275 | objs = SConscript(SConscriptFile)
276 |
277 | # build program
278 | if rtconfig.PLATFORM == 'cl':
279 | dll_target = TARGET.replace('.so', '.dll')
280 | target = Env.SharedLibrary(dll_target, objs)
281 |
282 | target = Command("$TARGET", dll_target, [Move(TARGET, dll_target)])
283 | # target = dll_target
284 | else:
285 | target = Env.Program(TARGET, objs)
286 |
287 | if hasattr(rtconfig, 'M_POST_ACTION'):
288 | Env.AddPostAction(target, rtconfig.M_POST_ACTION)
289 |
--------------------------------------------------------------------------------
/ymodem/SConscript:
--------------------------------------------------------------------------------
1 | from building import *
2 |
3 | src = Glob('*.c') + Glob('*.cpp')
4 | cwd = GetCurrentDir()
5 |
6 | CPPPATH = [cwd]
7 | group = DefineGroup('', src, depend = [''], CPPPATH=CPPPATH)
8 |
9 | Return('group')
10 |
--------------------------------------------------------------------------------
/ymodem/tofile.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "ymodem.h"
6 |
7 | struct custom_ctx
8 | {
9 | struct rym_ctx parent;
10 | int fd;
11 | int flen;
12 | char fpath[256];
13 | };
14 |
15 | static enum rym_code _rym_bg(
16 | struct rym_ctx *ctx,
17 | rt_uint8_t *pbuf,
18 | rt_size_t len)
19 | {
20 | char *buf = (char*)pbuf;
21 | struct custom_ctx *cctx = (struct custom_ctx *)ctx;
22 | cctx->fpath[0] = '\0';
23 |
24 | /* use current working directory */
25 | getcwd(cctx->fpath, sizeof(cctx->fpath));
26 | strcat(cctx->fpath, "/");
27 | strcat(cctx->fpath, (char*)buf);
28 |
29 | cctx->fd = open(cctx->fpath, O_CREAT | O_WRONLY | O_TRUNC, 0);
30 | if (cctx->fd < 0)
31 | {
32 | rt_err_t err = rt_get_errno();
33 | rt_kprintf("error creating file: %d\n", err);
34 | rt_kprintf("abort transmission\n");
35 | return RYM_CODE_CAN;
36 | }
37 |
38 | cctx->flen = atoi(buf + strlen(buf) + 1);
39 | if (cctx->flen == 0)
40 | cctx->flen = -1;
41 | return RYM_CODE_ACK;
42 | }
43 |
44 | static enum rym_code _rym_tof(
45 | struct rym_ctx *ctx,
46 | rt_uint8_t *buf,
47 | rt_size_t len)
48 | {
49 | struct custom_ctx *cctx = (struct custom_ctx *)ctx;
50 | RT_ASSERT(cctx->fd >= 0);
51 | if (cctx->flen == -1)
52 | {
53 | write(cctx->fd, buf, len);
54 | }
55 | else
56 | {
57 | int wlen = len > cctx->flen ? cctx->flen : len;
58 | write(cctx->fd, buf, wlen);
59 | cctx->flen -= wlen;
60 | }
61 | return RYM_CODE_ACK;
62 | }
63 |
64 | static enum rym_code _rym_end(
65 | struct rym_ctx *ctx,
66 | rt_uint8_t *buf,
67 | rt_size_t len)
68 | {
69 | struct custom_ctx *cctx = (struct custom_ctx *)ctx;
70 |
71 | RT_ASSERT(cctx->fd >= 0);
72 | close(cctx->fd);
73 | cctx->fd = -1;
74 |
75 | return RYM_CODE_ACK;
76 | }
77 |
78 | rt_err_t rym_write_to_file(rt_device_t idev)
79 | {
80 | rt_err_t res;
81 | struct custom_ctx *ctx = rt_malloc(sizeof(*ctx));
82 |
83 | RT_ASSERT(idev);
84 |
85 | rt_kprintf("entering RYM mode\n");
86 |
87 | res = rym_recv_on_device(&ctx->parent, idev,
88 | _rym_bg, _rym_tof, _rym_end, 1000);
89 |
90 | /* there is no Ymodem traffic on the line so print out info. */
91 | rt_kprintf("leaving RYM mode with code %d\n", res);
92 | rt_kprintf("file %s has been created.\n", ctx->fpath);
93 |
94 | rt_free(ctx);
95 |
96 | return res;
97 | }
98 |
99 | int main(int argc, char **argv)
100 | {
101 | rt_err_t res;
102 |
103 | if (argc != 2)
104 | {
105 | rt_kprintf("Usage: ymodem device\n");
106 | return 0;
107 | }
108 |
109 | rt_device_t dev = rt_device_find(argv[1]);
110 | if (!dev)
111 | {
112 | rt_kprintf("could not find device:%s\n", argv[1]);
113 | return -RT_ERROR;
114 | }
115 |
116 | res = rym_write_to_file(dev);
117 |
118 | return res;
119 | }
120 |
--------------------------------------------------------------------------------
/ymodem/ymodem.c:
--------------------------------------------------------------------------------
1 | /*
2 | * File : ymodem.c
3 | * COPYRIGHT (C) 2012, Shanghai Real-Thread Technology Co., Ltd
4 | *
5 | * Change Logs:
6 | * Date Author Notes
7 | * 2013-04-14 Grissiom initial implementation
8 | */
9 |
10 | #include
11 | #include "ymodem.h"
12 |
13 | static const rt_uint16_t ccitt_table[256] =
14 | {
15 | 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
16 | 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
17 | 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
18 | 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
19 | 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
20 | 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
21 | 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
22 | 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
23 | 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
24 | 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
25 | 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
26 | 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
27 | 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
28 | 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
29 | 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
30 | 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
31 | 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
32 | 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
33 | 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
34 | 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
35 | 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
36 | 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
37 | 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
38 | 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
39 | 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
40 | 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
41 | 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
42 | 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
43 | 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
44 | 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
45 | 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
46 | 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
47 | };
48 | rt_uint16_t CRC16(unsigned char *q, int len)
49 | {
50 | rt_uint16_t crc = 0;
51 |
52 | while (len-- > 0)
53 | crc = (crc << 8) ^ ccitt_table[((crc >> 8) ^ *q++) & 0xff];
54 | return crc;
55 | }
56 |
57 | // we could only use global varible because we could not use
58 | // rt_device_t->user_data(it is used by the serial driver)...
59 | static struct rym_ctx *_rym_the_ctx;
60 |
61 | static rt_err_t _rym_rx_ind(rt_device_t dev, rt_size_t size)
62 | {
63 | return rt_sem_release(&_rym_the_ctx->sem);
64 | }
65 |
66 | /* SOH/STX + seq + payload + crc */
67 | #define _RYM_SOH_PKG_SZ (1+2+128+2)
68 | #define _RYM_STX_PKG_SZ (1+2+1024+2)
69 |
70 | static enum rym_code _rym_read_code(
71 | struct rym_ctx *ctx,
72 | rt_tick_t timeout)
73 | {
74 | /* consume the available sem and read the data in buffer if possible */
75 | while (rt_sem_trytake(&ctx->sem) == RT_EOK)
76 | ;
77 | if (rt_device_read(ctx->dev, 0, ctx->buf, 1) == 1)
78 | return *ctx->buf;
79 | /* no data yet, wait for one */
80 | if (rt_sem_take(&ctx->sem, timeout) != RT_EOK)
81 | return RYM_CODE_NONE;
82 | /* read one */
83 | if (rt_device_read(ctx->dev, 0, ctx->buf, 1) == 1)
84 | return *ctx->buf;
85 | return RYM_CODE_NONE;
86 | }
87 |
88 | /* the caller should at least alloc _RYM_STX_PKG_SZ buffer */
89 | static rt_size_t _rym_read_data(
90 | struct rym_ctx *ctx,
91 | rt_size_t len)
92 | {
93 | /* we should already have had the code */
94 | rt_uint8_t *buf = ctx->buf + 1;
95 | rt_size_t readlen = 0;
96 |
97 | do
98 | {
99 | readlen += rt_device_read(ctx->dev,
100 | 0, buf + readlen, len - readlen);
101 | if (readlen >= len)
102 | return readlen;
103 | }
104 | while (rt_sem_take(&ctx->sem, RYM_WAIT_CHR_TICK) == RT_EOK);
105 |
106 | return readlen;
107 | }
108 |
109 | static rt_size_t _rym_putchar(struct rym_ctx *ctx, rt_uint8_t code)
110 | {
111 | rt_device_write(ctx->dev, 0, &code, sizeof(code));
112 | return 1;
113 | }
114 |
115 | static rt_err_t _rym_do_handshake(
116 | struct rym_ctx *ctx,
117 | int tm_sec)
118 | {
119 | enum rym_code code;
120 | rt_size_t i;
121 | rt_uint16_t recv_crc, cal_crc;
122 |
123 | ctx->stage = RYM_STAGE_ESTABLISHING;
124 | /* send C every second, so the sender could know we are waiting for it. */
125 | for (i = 0; i < tm_sec; i++)
126 | {
127 | _rym_putchar(ctx, RYM_CODE_C);
128 | code = _rym_read_code(ctx,
129 | RYM_CHD_INTV_TICK);
130 | if (code == RYM_CODE_SOH)
131 | break;
132 | }
133 | if (i == tm_sec)
134 | return -RYM_ERR_TMO;
135 |
136 | i = _rym_read_data(ctx, _RYM_SOH_PKG_SZ - 1);
137 | if (i != (_RYM_SOH_PKG_SZ - 1))
138 | return -RYM_ERR_DSZ;
139 |
140 | /* sanity check */
141 | if (ctx->buf[1] != 0 || ctx->buf[2] != 0xFF)
142 | return -RYM_ERR_SEQ;
143 |
144 | recv_crc = (rt_uint16_t)(*(ctx->buf + _RYM_SOH_PKG_SZ - 2) << 8) | *(ctx->buf + _RYM_SOH_PKG_SZ - 1);
145 | cal_crc = CRC16(ctx->buf + 3, _RYM_SOH_PKG_SZ - 5);
146 | if (recv_crc != cal_crc)
147 | return -RYM_ERR_CRC;
148 |
149 | /* congratulations, check passed. */
150 | if (ctx->on_begin && ctx->on_begin(ctx, ctx->buf + 3, 128) != RYM_CODE_ACK)
151 | return -RYM_ERR_CAN;
152 |
153 | return RT_EOK;
154 | }
155 |
156 | static rt_err_t _rym_trans_data(
157 | struct rym_ctx *ctx,
158 | rt_size_t data_sz,
159 | enum rym_code *code)
160 | {
161 | const rt_size_t tsz = 2 + data_sz + 2;
162 | rt_uint16_t recv_crc;
163 |
164 | /* seq + data + crc */
165 | rt_size_t i = _rym_read_data(ctx, tsz);
166 | if (i != tsz)
167 | return -RYM_ERR_DSZ;
168 |
169 | if ((ctx->buf[1] + ctx->buf[2]) != 0xFF)
170 | {
171 | return -RYM_ERR_SEQ;
172 | }
173 |
174 | /* sanity check */
175 | recv_crc = (rt_uint16_t)(*(ctx->buf + tsz - 1) << 8) | *(ctx->buf + tsz);
176 | if (recv_crc != CRC16(ctx->buf + 3, data_sz))
177 | return -RYM_ERR_CRC;
178 |
179 | /* congratulations, check passed. */
180 | if (ctx->on_data)
181 | *code = ctx->on_data(ctx, ctx->buf + 3, data_sz);
182 | else
183 | *code = RYM_CODE_ACK;
184 | return RT_EOK;
185 | }
186 |
187 | static rt_err_t _rym_do_trans(struct rym_ctx *ctx)
188 | {
189 | _rym_putchar(ctx, RYM_CODE_ACK);
190 | _rym_putchar(ctx, RYM_CODE_C);
191 | ctx->stage = RYM_STAGE_ESTABLISHED;
192 |
193 | while (1)
194 | {
195 | rt_err_t err;
196 | enum rym_code code;
197 | rt_size_t data_sz;
198 |
199 | code = _rym_read_code(ctx,
200 | RYM_WAIT_PKG_TICK);
201 | switch (code)
202 | {
203 | case RYM_CODE_SOH:
204 | data_sz = 128;
205 | break;
206 | case RYM_CODE_STX:
207 | data_sz = 1024;
208 | break;
209 | case RYM_CODE_EOT:
210 | return RT_EOK;
211 | default:
212 | return -RYM_ERR_CODE;
213 | };
214 | ctx->stage = RYM_STAGE_TRANSMITTING;
215 |
216 | err = _rym_trans_data(ctx, data_sz, &code);
217 | if (err != RT_EOK)
218 | return err;
219 | switch (code)
220 | {
221 | case RYM_CODE_CAN:
222 | /* the spec require multiple CAN */
223 | _rym_putchar(ctx, RYM_CODE_CAN);
224 | _rym_putchar(ctx, RYM_CODE_CAN);
225 | _rym_putchar(ctx, RYM_CODE_CAN);
226 | _rym_putchar(ctx, RYM_CODE_CAN);
227 | _rym_putchar(ctx, RYM_CODE_CAN);
228 | _rym_putchar(ctx, RYM_CODE_CAN);
229 | _rym_putchar(ctx, RYM_CODE_CAN);
230 | _rym_putchar(ctx, RYM_CODE_CAN);
231 | _rym_putchar(ctx, RYM_CODE_CAN);
232 | return -RYM_ERR_CAN;
233 | case RYM_CODE_ACK:
234 | _rym_putchar(ctx, RYM_CODE_ACK);
235 | break;
236 | default:
237 | // wrong code
238 | break;
239 | };
240 | }
241 | }
242 |
243 | static rt_err_t _rym_do_fin(struct rym_ctx *ctx)
244 | {
245 | enum rym_code code;
246 | rt_uint16_t recv_crc;
247 | rt_size_t i;
248 |
249 | ctx->stage = RYM_STAGE_FINISHING;
250 | /* we already got one EOT in the caller. invoke the callback if there is
251 | * one. */
252 | if (ctx->on_end)
253 | ctx->on_end(ctx, ctx->buf + 3, 128);
254 |
255 | _rym_putchar(ctx, RYM_CODE_NAK);
256 | code = _rym_read_code(ctx, RYM_WAIT_PKG_TICK);
257 | if (code != RYM_CODE_EOT)
258 | return -RYM_ERR_CODE;
259 |
260 | _rym_putchar(ctx, RYM_CODE_ACK);
261 | _rym_putchar(ctx, RYM_CODE_C);
262 |
263 | code = _rym_read_code(ctx, RYM_WAIT_PKG_TICK);
264 | if (code != RYM_CODE_SOH)
265 | return -RYM_ERR_CODE;
266 |
267 | i = _rym_read_data(ctx, _RYM_SOH_PKG_SZ - 1);
268 | if (i != (_RYM_SOH_PKG_SZ - 1))
269 | return -RYM_ERR_DSZ;
270 |
271 | /* sanity check
272 | *
273 | * TODO: multiple files transmission
274 | */
275 | if (ctx->buf[1] != 0 || ctx->buf[2] != 0xFF)
276 | return -RYM_ERR_SEQ;
277 |
278 | recv_crc = (rt_uint16_t)(*(ctx->buf + _RYM_SOH_PKG_SZ - 2) << 8) | *(ctx->buf + _RYM_SOH_PKG_SZ - 1);
279 | if (recv_crc != CRC16(ctx->buf + 3, _RYM_SOH_PKG_SZ - 5))
280 | return -RYM_ERR_CRC;
281 |
282 | /* congratulations, check passed. */
283 | ctx->stage = RYM_STAGE_FINISHED;
284 |
285 | /* put the last ACK */
286 | _rym_putchar(ctx, RYM_CODE_ACK);
287 |
288 | return RT_EOK;
289 | }
290 |
291 | static rt_err_t _rym_do_recv(
292 | struct rym_ctx *ctx,
293 | int handshake_timeout)
294 | {
295 | rt_err_t err;
296 |
297 | ctx->stage = RYM_STAGE_NONE;
298 |
299 | ctx->buf = rt_malloc(_RYM_STX_PKG_SZ);
300 | if (ctx->buf == RT_NULL)
301 | return -RT_ENOMEM;
302 |
303 | err = _rym_do_handshake(ctx, handshake_timeout);
304 | if (err != RT_EOK)
305 | return err;
306 |
307 | err = _rym_do_trans(ctx);
308 | if (err != RT_EOK)
309 | {
310 | if (ctx->on_end)
311 | ctx->on_end(ctx, RT_NULL, 0);
312 | return err;
313 | }
314 |
315 | return _rym_do_fin(ctx);
316 | }
317 |
318 | rt_err_t rym_recv_on_device(
319 | struct rym_ctx *ctx,
320 | rt_device_t dev,
321 | rym_callback on_begin,
322 | rym_callback on_data,
323 | rym_callback on_end,
324 | int handshake_timeout)
325 | {
326 | rt_err_t res;
327 | rt_err_t (*odev_rx_ind)(rt_device_t dev, rt_size_t size);
328 | rt_uint16_t odev_flag;
329 | int int_lvl;
330 |
331 | RT_ASSERT(_rym_the_ctx == 0);
332 | _rym_the_ctx = ctx;
333 |
334 | ctx->on_begin = on_begin;
335 | ctx->on_data = on_data;
336 | ctx->on_end = on_end;
337 | ctx->dev = dev;
338 | rt_sem_init(&ctx->sem, "rymsem", 0, RT_IPC_FLAG_FIFO);
339 |
340 | odev_rx_ind = dev->rx_indicate;
341 | /* no data should be received before the device has been fully setted up.
342 | */
343 | int_lvl = rt_hw_interrupt_disable();
344 | rt_device_set_rx_indicate(dev, _rym_rx_ind);
345 |
346 | odev_flag = dev->flag;
347 | /* make sure the device don't change the content. */
348 | dev->flag &= ~RT_DEVICE_FLAG_STREAM;
349 | rt_hw_interrupt_enable(int_lvl);
350 |
351 | res = rt_device_open(dev, 0);
352 | if (res != RT_EOK)
353 | goto __exit;
354 |
355 | res = _rym_do_recv(ctx, handshake_timeout);
356 |
357 | rt_device_close(dev);
358 |
359 | __exit:
360 | /* no rx_ind should be called before the callback has been fully detached.
361 | */
362 | int_lvl = rt_hw_interrupt_disable();
363 | rt_sem_detach(&ctx->sem);
364 |
365 | dev->flag = odev_flag;
366 | rt_device_set_rx_indicate(dev, odev_rx_ind);
367 | rt_hw_interrupt_enable(int_lvl);
368 |
369 | rt_free(ctx->buf);
370 | _rym_the_ctx = RT_NULL;
371 |
372 | return res;
373 | }
374 |
375 |
--------------------------------------------------------------------------------
/ymodem/ymodem.h:
--------------------------------------------------------------------------------
1 | #ifndef __YMODEM_H__
2 | #define __YMODEM_H__
3 | /*
4 | * File : ymodem.h
5 | * COPYRIGHT (C) 2012, Shanghai Real-Thread Technology Co., Ltd
6 | *
7 | * Change Logs:
8 | * Date Author Notes
9 | * 2013-04-14 Grissiom initial implementation
10 | */
11 |
12 | #include "rtthread.h"
13 |
14 | /* The word "RYM" is stand for "Real-YModem". */
15 |
16 | enum rym_code
17 | {
18 | RYM_CODE_NONE = 0x00,
19 | RYM_CODE_SOH = 0x01,
20 | RYM_CODE_STX = 0x02,
21 | RYM_CODE_EOT = 0x04,
22 | RYM_CODE_ACK = 0x06,
23 | RYM_CODE_NAK = 0x15,
24 | RYM_CODE_CAN = 0x18,
25 | RYM_CODE_C = 0x43,
26 | };
27 |
28 | /* RYM error code
29 | *
30 | * We use the rt_err_t to return error values. We take use of current error
31 | * codes available in RTT and append ourselves.
32 | */
33 | /* timeout on handshake */
34 | #define RYM_ERR_TMO 0x70
35 | /* wrong code, wrong SOH, STX etc. */
36 | #define RYM_ERR_CODE 0x71
37 | /* wrong sequence number */
38 | #define RYM_ERR_SEQ 0x72
39 | /* wrong CRC checksum */
40 | #define RYM_ERR_CRC 0x73
41 | /* not enough data received */
42 | #define RYM_ERR_DSZ 0x74
43 | /* the transmission is aborted by user */
44 | #define RYM_ERR_CAN 0x75
45 |
46 | /* how many ticks wait for chars between packet. */
47 | #ifndef RYM_WAIT_CHR_TICK
48 | #define RYM_WAIT_CHR_TICK (RT_TICK_PER_SECOND * 3)
49 | #endif
50 | /* how many ticks wait for between packet. */
51 | #ifndef RYM_WAIT_PKG_TICK
52 | #define RYM_WAIT_PKG_TICK (RT_TICK_PER_SECOND * 3)
53 | #endif
54 | /* how many ticks between two handshake code. */
55 | #ifndef RYM_CHD_INTV_TICK
56 | #define RYM_CHD_INTV_TICK (RT_TICK_PER_SECOND / 4)
57 | #endif
58 |
59 | enum rym_stage
60 | {
61 | RYM_STAGE_NONE,
62 | /* set when C is send */
63 | RYM_STAGE_ESTABLISHING,
64 | /* set when we've got the packet 0 and sent ACK and second C */
65 | RYM_STAGE_ESTABLISHED,
66 | /* set when the sender respond to our second C */
67 | RYM_STAGE_TRANSMITTING,
68 | /* set when the sender send a EOT */
69 | RYM_STAGE_FINISHING,
70 | /* set when transmission is really finished, i.e., after the NAK, C, final
71 | * NULL packet stuff. */
72 | RYM_STAGE_FINISHED,
73 | };
74 |
75 | struct rym_ctx;
76 | /* when receiving files, the buf will be the data received from ymodem protocol
77 | * and the len is the data size.
78 | *
79 | * TODO:
80 | * When sending files, the len is the buf size in RYM. The callback need to
81 | * fill the buf with data to send. Returning RYM_CODE_EOT will terminate the
82 | * transfer and the buf will be discarded. Any other return values will cause
83 | * the transfer continue.
84 | */
85 | typedef enum rym_code(*rym_callback)(struct rym_ctx *ctx, rt_uint8_t *buf, rt_size_t len);
86 |
87 | /* Currently RYM only support one transfer session(ctx) for simplicity.
88 | *
89 | * In case we could support multiple sessions in The future, the first argument
90 | * of APIs are (struct rym_ctx*).
91 | */
92 | struct rym_ctx
93 | {
94 | rym_callback on_data;
95 | rym_callback on_begin;
96 | rym_callback on_end;
97 | /* When error happened, user need to check this to get when the error has
98 | * happened. */
99 | enum rym_stage stage;
100 | /* user could get the error content through this */
101 | rt_uint8_t *buf;
102 |
103 | struct rt_semaphore sem;
104 |
105 | rt_device_t dev;
106 | };
107 |
108 | /** recv a file on device dev with ymodem session ctx.
109 | *
110 | * If an error happens, you can get where it is failed from ctx->stage.
111 | *
112 | * @param on_begin The callback will be invoked when the first packet arrived.
113 | * This packet often contain file names and the size of the file, if the sender
114 | * support it. So if you want to save the data to a file, you may need to
115 | * create the file on need. It is the on_begin's responsibility to parse the
116 | * data content. The on_begin can be NULL, in which case the transmission will
117 | * continue without any side-effects.
118 | *
119 | * @param on_data The callback will be invoked on the packets received. The
120 | * callback should save the data to the destination. The return value will be
121 | * sent to the sender and in turn, only RYM_{ACK,CAN} is valid. When on_data is
122 | * NULL, RYM will barely send ACK on every packet and have no side-effects.
123 | *
124 | * @param on_end The callback will be invoked when one transmission is
125 | * finished. The data should be 128 bytes of NULL. You can do some cleaning job
126 | * in this callback such as closing the file. The return value of this callback
127 | * is ignored. As above, this parameter can be NULL if you don't need such
128 | * function.
129 | *
130 | * @param handshake_timeout the timeout when hand shaking. The unit is in
131 | * second.
132 | */
133 | rt_err_t rym_recv_on_device(struct rym_ctx *ctx, rt_device_t dev,
134 | rym_callback on_begin, rym_callback on_data, rym_callback on_end,
135 | int handshake_timeout);
136 |
137 | #endif
138 |
--------------------------------------------------------------------------------