From 3c6f0dd50f95dc771f5c191d1405ddaa3a451bd5 Mon Sep 17 00:00:00 2001 From: Frank Voorburg Date: Thu, 10 Nov 2011 17:55:56 +0000 Subject: [PATCH] git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@1 5dc33758-31d5-4daf-9ae8-b24bf3d40d73 --- Doc/license.html | 733 +++++++++ Host/MicroBoot.exe | Bin 0 -> 366592 bytes Host/Pcan_usb.dll | Bin 0 -> 90112 bytes Host/Source/MainUnit.dfm | Bin 0 -> 6720 bytes Host/Source/MainUnit.pas | 767 ++++++++++ Host/Source/MicroBoot.cfg | 35 + Host/Source/MicroBoot.dof | 86 ++ Host/Source/MicroBoot.dpr | 55 + Host/Source/MicroBoot.ico | Bin 0 -> 2238 bytes Host/Source/SettingsUnit.dfm | Bin 0 -> 996 bytes Host/Source/SettingsUnit.pas | 229 +++ Host/Source/StopWatch.pas | 143 ++ Host/Source/interfaces/SRecReader.pas | 649 ++++++++ Host/Source/interfaces/XcpDataFile.pas | 219 +++ Host/Source/interfaces/XcpIcon.bmp | Bin 0 -> 2446 bytes Host/Source/interfaces/XcpLoader.pas | 1241 +++++++++++++++ Host/Source/interfaces/XcpProtection.pas | 172 +++ Host/Source/interfaces/can/peak/CANIcon.bmp | Bin 0 -> 2446 bytes Host/Source/interfaces/can/peak/PCANdrvD.pas | 547 +++++++ Host/Source/interfaces/can/peak/Pcan_usb.pas | 296 ++++ .../interfaces/can/peak/XcpSettings.dfm | Bin 0 -> 13359 bytes .../interfaces/can/peak/XcpSettings.pas | 289 ++++ .../interfaces/can/peak/XcpTransport.pas | 362 +++++ .../interfaces/can/peak/openblt_can_peak.cfg | 35 + .../interfaces/can/peak/openblt_can_peak.dof | 87 ++ .../interfaces/can/peak/openblt_can_peak.dpr | 605 ++++++++ Host/Source/interfaces/can/vector/CANIcon.bmp | Bin 0 -> 2446 bytes Host/Source/interfaces/can/vector/CANdrvD.pas | 740 +++++++++ Host/Source/interfaces/can/vector/CANlibD.pas | 959 ++++++++++++ .../interfaces/can/vector/XcpSettings.dfm | Bin 0 -> 13512 bytes .../interfaces/can/vector/XcpSettings.pas | 289 ++++ .../interfaces/can/vector/XcpTransport.pas | 398 +++++ .../can/vector/openblt_can_vector.cfg | 35 + .../can/vector/openblt_can_vector.dof | 86 ++ .../can/vector/openblt_can_vector.dpr | 605 ++++++++ Host/Source/interfaces/uart/CPDrv.ico | Bin 0 -> 766 bytes Host/Source/interfaces/uart/CPDrv.pas | 1158 ++++++++++++++ Host/Source/interfaces/uart/XcpSettings.dfm | Bin 0 -> 11217 bytes Host/Source/interfaces/uart/XcpSettings.pas | 270 ++++ Host/Source/interfaces/uart/XcpTransport.pas | 267 ++++ Host/Source/interfaces/uart/openblt_uart.cfg | 35 + Host/Source/interfaces/uart/openblt_uart.dof | 86 ++ Host/Source/interfaces/uart/openblt_uart.dpr | 605 ++++++++ Host/Source/uBootInterface.pas | 422 ++++++ Host/openblt_can_peak.dll | Bin 0 -> 396288 bytes Host/openblt_can_peak.ini | 14 + Host/openblt_can_vector.dll | Bin 0 -> 397824 bytes Host/openblt_can_vector.ini | 14 + Host/openblt_uart.dll | Bin 0 -> 391680 bytes Host/openblt_uart.ini | 10 + Host/vcand32.dll | Bin 0 -> 101888 bytes .../bin/openbtl_olimex_lpc_l2294_20mhz.elf | Bin 0 -> 64969 bytes .../bin/openbtl_olimex_lpc_l2294_20mhz.hex | 361 +++++ .../bin/openbtl_olimex_lpc_l2294_20mhz.map | 176 +++ .../Boot/cmd/build.bat | 2 + .../Boot/cmd/clean.bat | 2 + .../Boot/cmd/debug.bat | 5 + .../Boot/cmd/debug.cfg | 67 + .../Boot/cmd/flash.bat | 3 + .../Boot/cmd/flash.cfg | 79 + .../Boot/config.h | 128 ++ .../Boot/hooks.c | 187 +++ .../Boot/ide/DemoBoot.project | 126 ++ .../Boot/ide/DemoBoot.workspace | 12 + .../Boot/ide/readme.txt | 4 + .../Boot/lpc2294.h | 409 +++++ .../Boot/main.c | 158 ++ .../Boot/makefile | 163 ++ .../bin/demoprog_olimex_lpc_l2294_20mhz.elf | Bin 0 -> 19463 bytes .../bin/demoprog_olimex_lpc_l2294_20mhz.map | 122 ++ .../bin/demoprog_olimex_lpc_l2294_20mhz.sx | 145 ++ .../Prog/boot.c | 353 +++++ .../Prog/boot.h | 42 + .../Prog/cmd/build.bat | 2 + .../Prog/cmd/clean.bat | 2 + .../Prog/cstart.s | 136 ++ .../Prog/header.h | 46 + .../Prog/ide/DemoProg.project | 97 ++ .../Prog/ide/DemoProg.workspace | 12 + .../Prog/ide/readme.txt | 4 + .../Prog/irq.c | 140 ++ .../Prog/irq.h | 43 + .../Prog/led.c | 100 ++ .../Prog/led.h | 42 + .../Prog/lpc2294.h | 409 +++++ .../Prog/main.c | 151 ++ .../Prog/makefile | 144 ++ .../Prog/memory.x | 51 + .../Prog/timer.c | 119 ++ .../Prog/timer.h | 44 + .../Prog/vectors.c | 107 ++ Target/Source/ARM7_LPC2000/GCC/cstart.s | 237 +++ Target/Source/ARM7_LPC2000/GCC/flash.c | 705 +++++++++ Target/Source/ARM7_LPC2000/GCC/flash.h | 46 + Target/Source/ARM7_LPC2000/GCC/memory.x | 54 + Target/Source/ARM7_LPC2000/GCC/vectors.c | 88 ++ Target/Source/ARM7_LPC2000/can.c | 253 ++++ Target/Source/ARM7_LPC2000/can.h | 45 + Target/Source/ARM7_LPC2000/cpu.c | 138 ++ Target/Source/ARM7_LPC2000/cpu.h | 44 + Target/Source/ARM7_LPC2000/nvm.c | 201 +++ Target/Source/ARM7_LPC2000/nvm.h | 60 + Target/Source/ARM7_LPC2000/timer.c | 152 ++ Target/Source/ARM7_LPC2000/timer.h | 45 + Target/Source/ARM7_LPC2000/types.h | 58 + Target/Source/ARM7_LPC2000/uart.c | 251 ++++ Target/Source/ARM7_LPC2000/uart.h | 45 + Target/Source/assert.c | 70 + Target/Source/assert.h | 63 + Target/Source/backdoor.c | 135 ++ Target/Source/backdoor.h | 41 + Target/Source/boot.c | 76 + Target/Source/boot.h | 58 + Target/Source/com.c | 191 +++ Target/Source/com.h | 63 + Target/Source/cop.c | 77 + Target/Source/cop.h | 42 + Target/Source/plausibility.h | 212 +++ Target/Source/xcp.c | 1326 +++++++++++++++++ Target/Source/xcp.h | 226 +++ 120 files changed, 21738 insertions(+) create mode 100644 Doc/license.html create mode 100644 Host/MicroBoot.exe create mode 100644 Host/Pcan_usb.dll create mode 100644 Host/Source/MainUnit.dfm create mode 100644 Host/Source/MainUnit.pas create mode 100644 Host/Source/MicroBoot.cfg create mode 100644 Host/Source/MicroBoot.dof create mode 100644 Host/Source/MicroBoot.dpr create mode 100644 Host/Source/MicroBoot.ico create mode 100644 Host/Source/SettingsUnit.dfm create mode 100644 Host/Source/SettingsUnit.pas create mode 100644 Host/Source/StopWatch.pas create mode 100644 Host/Source/interfaces/SRecReader.pas create mode 100644 Host/Source/interfaces/XcpDataFile.pas create mode 100644 Host/Source/interfaces/XcpIcon.bmp create mode 100644 Host/Source/interfaces/XcpLoader.pas create mode 100644 Host/Source/interfaces/XcpProtection.pas create mode 100644 Host/Source/interfaces/can/peak/CANIcon.bmp create mode 100644 Host/Source/interfaces/can/peak/PCANdrvD.pas create mode 100644 Host/Source/interfaces/can/peak/Pcan_usb.pas create mode 100644 Host/Source/interfaces/can/peak/XcpSettings.dfm create mode 100644 Host/Source/interfaces/can/peak/XcpSettings.pas create mode 100644 Host/Source/interfaces/can/peak/XcpTransport.pas create mode 100644 Host/Source/interfaces/can/peak/openblt_can_peak.cfg create mode 100644 Host/Source/interfaces/can/peak/openblt_can_peak.dof create mode 100644 Host/Source/interfaces/can/peak/openblt_can_peak.dpr create mode 100644 Host/Source/interfaces/can/vector/CANIcon.bmp create mode 100644 Host/Source/interfaces/can/vector/CANdrvD.pas create mode 100644 Host/Source/interfaces/can/vector/CANlibD.pas create mode 100644 Host/Source/interfaces/can/vector/XcpSettings.dfm create mode 100644 Host/Source/interfaces/can/vector/XcpSettings.pas create mode 100644 Host/Source/interfaces/can/vector/XcpTransport.pas create mode 100644 Host/Source/interfaces/can/vector/openblt_can_vector.cfg create mode 100644 Host/Source/interfaces/can/vector/openblt_can_vector.dof create mode 100644 Host/Source/interfaces/can/vector/openblt_can_vector.dpr create mode 100644 Host/Source/interfaces/uart/CPDrv.ico create mode 100644 Host/Source/interfaces/uart/CPDrv.pas create mode 100644 Host/Source/interfaces/uart/XcpSettings.dfm create mode 100644 Host/Source/interfaces/uart/XcpSettings.pas create mode 100644 Host/Source/interfaces/uart/XcpTransport.pas create mode 100644 Host/Source/interfaces/uart/openblt_uart.cfg create mode 100644 Host/Source/interfaces/uart/openblt_uart.dof create mode 100644 Host/Source/interfaces/uart/openblt_uart.dpr create mode 100644 Host/Source/uBootInterface.pas create mode 100644 Host/openblt_can_peak.dll create mode 100644 Host/openblt_can_peak.ini create mode 100644 Host/openblt_can_vector.dll create mode 100644 Host/openblt_can_vector.ini create mode 100644 Host/openblt_uart.dll create mode 100644 Host/openblt_uart.ini create mode 100644 Host/vcand32.dll create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/bin/openbtl_olimex_lpc_l2294_20mhz.elf create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/bin/openbtl_olimex_lpc_l2294_20mhz.hex create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/bin/openbtl_olimex_lpc_l2294_20mhz.map create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/build.bat create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/clean.bat create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/debug.bat create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/debug.cfg create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/flash.bat create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/flash.cfg create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/config.h create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/hooks.c create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/DemoBoot.project create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/DemoBoot.workspace create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/readme.txt create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/lpc2294.h create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/main.c create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/makefile create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.elf create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.map create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.sx create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/boot.c create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/boot.h create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cmd/build.bat create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cmd/clean.bat create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cstart.s create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/header.h create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/DemoProg.project create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/DemoProg.workspace create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/readme.txt create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/irq.c create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/irq.h create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/led.c create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/led.h create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/lpc2294.h create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/main.c create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/makefile create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/memory.x create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/timer.c create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/timer.h create mode 100644 Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/vectors.c create mode 100644 Target/Source/ARM7_LPC2000/GCC/cstart.s create mode 100644 Target/Source/ARM7_LPC2000/GCC/flash.c create mode 100644 Target/Source/ARM7_LPC2000/GCC/flash.h create mode 100644 Target/Source/ARM7_LPC2000/GCC/memory.x create mode 100644 Target/Source/ARM7_LPC2000/GCC/vectors.c create mode 100644 Target/Source/ARM7_LPC2000/can.c create mode 100644 Target/Source/ARM7_LPC2000/can.h create mode 100644 Target/Source/ARM7_LPC2000/cpu.c create mode 100644 Target/Source/ARM7_LPC2000/cpu.h create mode 100644 Target/Source/ARM7_LPC2000/nvm.c create mode 100644 Target/Source/ARM7_LPC2000/nvm.h create mode 100644 Target/Source/ARM7_LPC2000/timer.c create mode 100644 Target/Source/ARM7_LPC2000/timer.h create mode 100644 Target/Source/ARM7_LPC2000/types.h create mode 100644 Target/Source/ARM7_LPC2000/uart.c create mode 100644 Target/Source/ARM7_LPC2000/uart.h create mode 100644 Target/Source/assert.c create mode 100644 Target/Source/assert.h create mode 100644 Target/Source/backdoor.c create mode 100644 Target/Source/backdoor.h create mode 100644 Target/Source/boot.c create mode 100644 Target/Source/boot.h create mode 100644 Target/Source/com.c create mode 100644 Target/Source/com.h create mode 100644 Target/Source/cop.c create mode 100644 Target/Source/cop.h create mode 100644 Target/Source/plausibility.h create mode 100644 Target/Source/xcp.c create mode 100644 Target/Source/xcp.h diff --git a/Doc/license.html b/Doc/license.html new file mode 100644 index 00000000..18e02da2 --- /dev/null +++ b/Doc/license.html @@ -0,0 +1,733 @@ + + + + + + + + + + +The GNU General Public License v3.0 - GNU Project - Free Software Foundation (FSF) + + + + + + + + + + + + + + + + +
+

Introduction

+

The OpenBLT source code is licensed by the modified GNU General +Public License (GPL) text provided below.  The OpenBLT download +also includes demo application source code, some of which is provided +by third parties AND IS LICENSED SEPARATELY FROM OPENBLT. For the +avoidance of any doubt refer to the comment included at the top of each +source and header file for license and copyright information.
+
+This is a list of files for which Feaser is not the copyright owner and are NOT COVERED BY THE GPL.
+

+
    +
  1. Various header files provided by silicon manufacturers and tool +vendors that define processor specific memory addresses and utility +macros. Permission has been granted by the various copyright holders +for these files to be included in the OpenBLT download. Users must +ensure license conditions are adhered to for any use other than +compilation of the OpenBLT demo applications.
  2. +
  3. Various peripheral driver source files and binaries provided by silicon +manufacturers and tool vendors. Permission has been granted by the +various copyright holders for these files to be included in the OpenBLT +download. Users must ensure license conditions are adhered to for any +use other than compilation of the OpenBLT demo applications.
  4. +
+

Errors and omissions should be reported to Feaser, contact details can be obtained from http://www.feaser.com.
+
+The GPL license text follows. A special exception to the GPL is +included to allow you to distribute a combined work that includes +OpenBLT without being obliged to provide the source code for any +proprietary components. The exception text is included at the bottom of +this file.
+

+
+ +

GNU GENERAL PUBLIC LICENSE

+

Version 3, 29 June 2007

+ +

Copyright © 2007 Free Software Foundation, Inc. + <http://fsf.org/>

+ Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed.

+ +

Preamble

+ +

The GNU General Public License is a free, copyleft license for +software and other kinds of works.

+ +

The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too.

+ +

When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things.

+ +

To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others.

+ +

For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights.

+ +

Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it.

+ +

For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions.

+ +

Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users.

+ +

Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free.

+ +

The precise terms and conditions for copying, distribution and +modification follow.

+ +

TERMS AND CONDITIONS

+ +

0. Definitions.

+ +

“This License” refers to version 3 of the GNU General Public License.

+ +

“Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks.

+ +

“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations.

+ +

To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a “modified version” of the +earlier work or a work “based on” the earlier work.

+ +

A “covered work” means either the unmodified Program or a work based +on the Program.

+ +

To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well.

+ +

To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying.

+ +

An interactive user interface displays “Appropriate Legal Notices” +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion.

+ +

1. Source Code.

+ +

The “source code” for a work means the preferred form of the work +for making modifications to it. “Object code” means any non-source +form of a work.

+ +

A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language.

+ +

The “System Libraries” of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it.

+ +

The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work.

+ +

The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source.

+ +

The Corresponding Source for a work in source code form is that +same work.

+ +

2. Basic Permissions.

+ +

All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law.

+ +

You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you.

+ +

Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary.

+ +

3. Protecting Users' Legal Rights From Anti-Circumvention Law.

+ +

No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures.

+ +

When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures.

+ +

4. Conveying Verbatim Copies.

+ +

You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program.

+ +

You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee.

+ +

5. Conveying Modified Source Versions.

+ +

You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions:

+ +
    +
  • a) The work must carry prominent notices stating that you modified + it, and giving a relevant date.
  • + +
  • b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + “keep intact all notices”.
  • + +
  • c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it.
  • + +
  • d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so.
  • +
+ +

A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate.

+ +

6. Conveying Non-Source Forms.

+ +

You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways:

+ +
    +
  • a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange.
  • + +
  • b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge.
  • + +
  • c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b.
  • + +
  • d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements.
  • + +
  • e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d.
  • +
+ +

A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work.

+ +

A “User Product” is either (1) a “consumer product”, which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, “normally used” refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product.

+ +

“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made.

+ +

If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM).

+ +

The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network.

+ +

Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying.

+ +

7. Additional Terms.

+ +

“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions.

+ +

When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission.

+ +

Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms:

+ +
    +
  • a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or
  • + +
  • b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or
  • + +
  • c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or
  • + +
  • d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or
  • + +
  • e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or
  • + +
  • f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors.
  • +
+ +

All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying.

+ +

If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms.

+ +

Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way.

+ +

8. Termination.

+ +

You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11).

+ +

However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation.

+ +

Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice.

+ +

Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10.

+ +

9. Acceptance Not Required for Having Copies.

+ +

You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so.

+ +

10. Automatic Licensing of Downstream Recipients.

+ +

Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License.

+ +

An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts.

+ +

You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it.

+ +

11. Patents.

+ +

A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”.

+ +

A contributor's “essential patent claims” are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License.

+ +

Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version.

+ +

In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party.

+ +

If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid.

+ +

If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it.

+ +

A patent license is “discriminatory” if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007.

+ +

Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law.

+ +

12. No Surrender of Others' Freedom.

+ +

If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program.

+ +

13. Use with the GNU Affero General Public License.

+ +

Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such.

+ +

14. Revised Versions of this License.

+ +

The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns.

+ +

Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation.

+ +

If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program.

+ +

Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version.

+ +

15. Disclaimer of Warranty.

+ +

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

+ +

16. Limitation of Liability.

+ +

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES.

+ +

17. Interpretation of Sections 15 and 16.

+ +

If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee.

+
+

OpenBLT GPL Exception Text
+

+ +

Any OpenBLT source code, whether modified or in it's original +release form, or whether in whole or in part, can only be distributed +by you under the terms
+of the GNU General Public License plus this exception. An independent +module is a module which is not derived from or based on OpenBLT.
+

+

Clause 1

+

Linking OpenBLT statically or dynamically with other modules is +making a combined work based on OpenBLT. Thus, the terms and conditions +of the GNU General Public License cover the whole combination.
+
+As a special exception, the copyright holder of OpenBLT gives you +permission to link OpenBLT with independent modules that communicate +with OpenBLT solely through the OpenBLT API interface, regardless of +the license terms of these independent modules, and to copy and +distribute the resulting combined work under terms of your choice, +provided that
+
+

+
    +
  • Every copy of the combined work is accompanied by a written +statement that details to the recipient the version of OpenBLT used and +an offer by yourself to provide the OpenBLT source code (including any +modifications you may have made) should the recipient request it.
  • +
  • The combined work is not itself a bootloader or related product.
  • +
  • The independent modules add significant and primary functionality +to OpenBLT and do not merely extend the existing functionality already +present in OpenBLT.
  • +
+

Clause 2

+

OpenBLT may not be used for any competitive or comparative purpose, +including the publication of any form of run time or compile time +metric, without the express permission of Feaser (this is the norm +within the industry andis intended to ensure information accuracy).
+

+


+

+ + +
\ No newline at end of file diff --git a/Host/MicroBoot.exe b/Host/MicroBoot.exe new file mode 100644 index 0000000000000000000000000000000000000000..e56187e9d2a5bf8c8cdb82289a30cc0f6f374092 GIT binary patch literal 366592 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 D@H0GuxP_O z;9RS-P}`w3libIj`KQ)Q72+Rv3%SthJ86REgy;`-0jIM;^3mm9sO z3x+gpFe8tivI`^yD`U10RP>#QbjG?iBu)075njNj$e^c;b%)f$s1Khb4gPSPxBn6o zKL+z41p&t^(84O}F_ewh{IZD!5l-}@&pKWcwLo)+QU5$kOiPra-NRf;5e>QdqEEye z&%xHH+YRosq_isCXFZkfFe)L!aJZs(=;31#q@!AIj@l-|HW*rhp`ZRm;U=nZ zg@Xc-LY5aU^dGyUuuE;>Gi1p=o)=VdW=zVRH6hzQcjEHmr3;oVoSU&|>58JobF*`& zDw8~U(-xFGFmu6D?;<2YIeh$29rc%?4M87-gU^Ct;bSx}p(4)}$R{ch#VsGG(zjN1)TJ zte^hbnEmR2IjoC6Xk{hN@^fk|dpJ=WHQFESKiLaM?{TB<{(2{7lhA!G=`Qecah&7r zMvEVx0tTyC{s5?w zR#wNb^hB^P*3zckuJ@_L7$+wQI@u56C}qqxYas2vLs9K4&cl?5$NI8KPe?ti$I^6V z>fsKVIf@t{R(t{_C3HL3hNd8hY|yYHXQmcp={1OG2(zK%$Zkm+;Z4HQP}&Ns*NMp< zO!atetk|Bm!mjr82f&3RSGcuZC>#WKGG$DYY7-^yJ%bJdwFoS>eLUi_>Z|Dsitf#Ig8y*-}n+$CnX zo*>s|xccjC`N3SF1Y61OO<`xv4@T+5dm<&)(EBKXD{;hmazZ=EhGeJ_3tbaTzA+)y z?i-_f?T)ts6DH`GyNxkzLwcih`ctRzT?EQ9V*7|Q4lUo8O#UV2%6O(r)V4L$(GyDEor#Z`YQbSgE2e+s*&TN*(hw@ zHUu7MmPujVwJL!VY@tt($Qn39^LEb9)vz-1qYiB6U!nG}UN)H%Gu$XA-UMR|=}Lm| zV)+QdoX4=#JUgcH=keNh77M{j*SADUdOk;ojuwND3si)&z+4qqT+5q0$(In-X3CS~cAy|PZ`Mo{Ztjvetbmi~WQSh)z>sgy9MRyi zz6=_CG$p|(uLR8~zlnDLJ=U*e`E+FyZG0e7#Ft@?VPpVHQVW@LHtV5vzY-nN$-lVa z+k|ZVV~nK>*us=yBLi40vgOa?G*uBf7R1nLs<9@B^e@!Rk>*-Ewa;2&N@yH9CR7K| zez80oGmn29J9O3!Q|FF(xV$@p)%q+*wY5kUURj4*JqSa}pdR%je zV$Mn=<_v`L92o%r&~sbJ62LmmhQh2ygj$hJi+L9FCEz3YD~#|mW(OKm1s;Pe-hUyY z+Qyi?|HHbHXfMHI)U3BRA{4vRhB}qW?zXcPSWV9>+Ikyx6KKJ){P5ZycWH3Q_|OVJ z=15cd;dP%!TYEh*G!3cd)yM+>3q+BBjt7Jh<35A_rWZgT0qm$%AZK3JNk$ca7>8l;Fq32!DSEpIbIEr(6BFd^486O|g^!hmX)oT6692Jje z!U(V1xYhfa=wljOA5cR{9{viRkyZU8tCHF6TWA*X%yW0o9~t#6U7*J^U{CVwRa$ zg1aQMK3{*tv%FYcynI`m}gP7HGo=Fq5}rv9jQfc1pWs~S+f zq|dJ8(?%X|fJb!Br+W{JxZv+P(3-HWFFGp|+j%}hV2F{;GTV7OycXo^7KHsZMcq?G zdWF;xnopxX#$L=Cg2vkK_4yL{#C+P?{vLlIo-@2+bY7r&+8bP9YE$d2P6bm`#uyqI z(B9R;d^a+!UCjt^C~Du9&N7V0(BOqSI52{u$27p5hs$%Sd~+y_sq+6~WG3S-kx_-oC^zX;hJ z3ei-Q5w;>>Vu<$KV0_@oqS=|#|Mr^CH|LwS<=-9JL=J*}44cx9aMb6aa5+d~5-VuO zpsD+qL#1Zz&<309asHK#en7CE7T8$;Rl>qt?Lm0GgXTXS>uXUHzuI{kYe0lbia!QxX3;L_oMRBtpOs?!tQG4i$GGlD59|BwDXyG&DSns9At^i2=k%vOA%^2 zL&+3uXJ|69HfLtGN82|tz@|Roq^VWQg!U=k(|j?!crb>}csfx#jXWkm?oE5R88q+m zh6?hLR7+$^n7@aXzF_{G{K}LkBCUdFNFnCG#xyzBKZfFlh!!CQ53ot?Y*zbs%!TE5 zo(sF{yXV5LrFk<^OR0O4&#B#GKX*m=U{9M4u!inu0kXFr4L+oLoPpwBMNb*9;u8ue`DJsxgPwbvIGh(#FSuh~9nVUj1Y3kgf|W zH`>!VwN|0;Nm{gb`C1f-&`~2GiPKAO9J6Q5_2rSZ*ADq|%)4vN+Pgz8m`+z(#~O2~ zJyGo0?L#i|sbDk}Et26v!Hgs+K^d?a?Xw_$Q&#t@h@CW~d2J$u-l^?^WAmBk@1C#P zk&;sdBLlh(3Z_5{4-o@El6!bTdPYV-ER$J4_B#LSu*o~X&oOft@6lR$cMjo#s?sdl ziuQWz2t^;PHStvBNNW%woZ3Y&Y0Q_XHDB^w@D2Txiv~WbpD^`51hzqJd?mSy&Ek9a z;k8Qeznh`UJ=y$CSc~5d?Or%%I3&C(oKV;H;98&iyiC#17lXUhyNVj zXw;+`^8THAk=E4pIZ`hUE+X|P=B=eRJGb{6I&lnGt`8-hCw=S}KBPYE2iH!zum*0O zbs^R9L`3Mx%I3S_Mu|HGol_9GMKklAu#x)Ff}Dh=P_ofRs4>tp&D@YzC(Wo=$*|Q? zeP!$?Nj(hZeFLU+_9G;gvEumKFrbm?X)F=39hOEcoyGA{pTfO??c=LJfCLCU9NCyt zF~vjzP^l&)u+oHB^r5gxv4!>E8<8#4&>8Dak!NaCg`8;bin;EYrjd=laDqD67w)27 z=L_4()K$IB7w(4n+pt4*_`==Qgld|&2o1+HqehcqGuDN5x7J0w%c|XF)9$kSgU%W2 zzR+*U)81pbHzjB-mbo{X+0>h25&t8|#*B4*o}LI-!$mvIi9a*ewaGq$XkSrY9P2S!p}LokMX=c)LmV%d zw3c-Vd@;rep)$B>J9!z*`f9@^j`xFR)tA8fMlvkWT99M@e4L`pSa(Lx{;q5l9;0v;vCn|WLVuGo%)Re%M zx1$A^5zb;WtV6b~?V{D1+Dz~BL}Up2YFHoEqawj~f%tKui#pzS!LCmBUFfRj`7U%* zSNJY~A3kK&cLDq$##EcBFhY}0Ab4V|sfE9YWmvK1rmrz9vY`zPi=~yq2d(thI1yH# zgSp=+CTtQj;}^@OLI~pxKMUZTucrxj*qgJoX2W3^a+R-NYmnY$2PITrMenXP8&<2) z3lUb>T7;#RX^wKLeY25MY|pZo+W1hURLW13H`=>wX-Z;+qa)ktlq#FLUFlEGqIdrOI}ih7-S2jAq*G7QaNkPq9J_1YK~J(5 zd{C%73>k6^_dmkDllBzt6E^WxqK#WO?P-RfsKPPavVONVg ztl=b!yB#B5eGu)oVDIvqkt02+gF+6U84W(fXem3=k(GlbbK1#$1cA70ejkM&89;Zp zH#+>yTy=oxEsaLcEE_7Rps>M=QkrN(MZ8TYND;JeWQ9Gl!WLO!jf@brLOaIiz!?b? z{ZTnK%vGyfB^8I|i+>WE-b?lcM2ymqW*xovE8 zd1PJR^2nOFYAZi|ghaQU9pH6T{Fw+#64-{(M;E_t#W=;?222f9Ofs43u~4MBIh#aN z=~gyEH>aLs4d)-^n)?KEpZLT1NSd3gMD|Z0>vx~P##{`i(@fr5wRx>+YueTfz!2^# z+WUnqyp9+1xTTg&Ya5C)5qvzNuXMMvyc66^X`0un&yREgRUU*IfvBT?xlg67Ikm>3 ztvLlUH?q7_L_$zYZRB-FDJQ2qv_RRzh++>vh|SPGo`hmq*-ZXLvuMikf6-7!(Z)?lVdBt5{V#+Cqa=RleQHIi&a))=utX-(=9Zq3yTaaXo@{MrBt6WZL)-=V znjy>nx)V$K)A;$+PLG5h0I$~Y?zhrPqKo+49N^8m@$I~(pRNTw5kbd z6Ky!jGtus~vWdw(?JpOQW)t7}CTFnDse8=G;;kK>&N5BhdYo4P-z6tpoBb<9-j&OB{7xmGoB?DJ`yh; z-jfKN^Sw#=QylAGL`r;X&M4jl-Mc=L$Len@8=MdBzSOO%xADe9jgA&oI zn>2IO-)9F=JQ$xr<_?j6+Gl3$`-apB!q~HdI;p5*NMHuehzbnDh6U`S&VjBn&KcQDvLyaSTv>>QmNH%uglQ>*G=|H{RaBKI>7v)+ z3j4Ge3h1?y7ex@!2W}Eo33J=bnU>d%el6)E95jq&3Z(pGFf```a#$F9{$%__?G?Olc1A;u5ON%UxFE=5L)o;>+>GW z9Pwa*8~Q`ck6@olRyNsLXN$QKW`eVr6NtsKKdggQVykjowVCfbAoK&uAcxJfv1v}0 zXGd3K{|90VDIIx;sWH10-<)|^Y7k`wrHBn09{vy#D%vFqI}?F%Zo3zsZ`mePh$S@;N>NLB#8wV6;M|AtQ}Ngp6AE^NxDVpkgBbFTdsuq|21u3MVwM6NCcyy`v!?XjYOz%AXTI7O~k3_vh z{IM=Mr<<4jk8glG(yXS5^a|GXL9hj|hR%2T!)9+>!=z;50}jCl;dC3E8YYQys9B7J z=pp&WpMZ;gxN-xfNXtw_nTnN4MAzW5`QR00tYtbITuGTAr)BonGLyB;luB17v`WAK z{t`3um{ecisCMr##a({K%QH6&rgQOS7b)dlTg1~JRk2&J?4n5S`I`GdI&{~5$Yy6x z$=~7Wdh&#Iy%zF$QUvejzi3`{l|i!$3r2EM5YCLr_={*=_4DJWwq_`5n}`E*wV3BZ zZ~c8}%CeIriE4uXqGi=p{O=JEuGi*UBQul4*y0U@MrE!kMB4a^MC!|}6rcXqR?3C` z+E$Vcy_yC|WvfM*cyD5>6D_OhIK)toJ*|0NZyoofe`2wQPFPJR}sjrEG;iD@l(=6Y zEWZYNUT%fR@5ji}4Ol%pW@M!Ya`GVp zi{AEJI9&GVOLs_yX$7H=Ju>yTy~JUlkAGV$@l!}5}6x|9za zxA7P?g=`(F-LRiI%doe?!s+3T}i zJD$6$YRhxWpUZQNbtIp?;jvwN@?GoWp9rrWb4S@+*T-G9+;%YTu}ycoj!wVd`cC8N z#(Q1AySB{jDqY^b$n}5!T`}~9e{KKsV%K}mzZ;o6aCPlI*E5NK+TQ!0FMlz9LhBPI`PpDFZ}tEzV;tk z>5tsJWbRe%*YABjedY1pr-$6UzU=ypy$Mx^l^dS@OI1dne}w<-Jifi|V#e&Jt3z>5 zSDaqx-hbx2{?U|QJo&Es-oHK>cckTKHDe|<{HELU|K51j@n53;qAZfnD>Ei z*`I!&Tw%_>r*4q9ZT5T1?(Kf-zjr>I?ZNoKc|IitT?`Bq&M!={TXtYpOc#|p!+vTvD-(~MZ3FqHG-{OB?@xN>8(ulW1=MVc2 zDgN^&782S7Aydyaw>Ix>KG1wH?W^K0tE_2fierYJ>GzfE*r#*O2hlWOPqUbn z>in71z51D%4Cg$rQ*l84a>U!6wRJg77kwx`oHMMSpBbDVffN1s98~7(0tiPb{YE-( zMmmSewESRFz83X&W_cb+&Hh%F<7Ae9QhrI}d~co~N2X8zGZ;Hqytmg-W6IZrG2t)vqLjeI_r8r+C*1jFY=f^+ z$n;k-wP8Y#KLt}qzkNI?21AE17SY4TUL%TU@Z4xT{^1ml$>Dzkf`db3v}FcBJ6ZrP zKz+<4Jk9kncN&lhuoO1LP+T;17DLgS$UrGdP#R*AfL6uqYlxv~)U$5%2V-ce@{};q z5?ci3h*cDHN7DV{n~)7R zjIIRIl(1F=z>Hi@Ssa)~D-wn{uAu|?v3iA@rBOWYx`PGUgf8xm_Iz9O+&;%132NPJe} zMu|^Ld`jXI600OWB5{Mn^%8v&OC_$Bs7hQRajC>2i3=s(BXO?8e2KXdJrbu%%#@fR z(Is)5#L*H*NgN?@n8d*nQzRx!>@P7%VxmN+M0@o8tRW9}i8hH=iHgMbGlsvg#Iq9H zB%YGUC7zJjD)ETK7K!^MHc8wqafie@i2;dkNUV|gio|M(nDshFxr4oxIE|hqW#JLjlCFV->NSrD$Q(}fhm&9=rM@t+f zafHNS5(i66k(ey8zr-Yoi4vU>?GkMgtr8W9E6y3^zf@w8#Cs&pm6$Jap~PH?9*I*W zW=hPE=#n^2;%JGZB#w|cOyXdPDH4+<_LrC>F;SvZqFtg*qE(_IvHgEi&Ly6e*e3Cm zL@x1!#8!z%B(_N0FR@ADZizc2)=3OVd_!W5#8)I%OWZ8+1&Pl}+$iyBiBCy<&SBrcU$Bypj{dnC@4m@hF`qDSIXiJ20kbTj0;OX4_*qa}`# zI6~quiGwAkNKBU4Ut*HPM2Sv`c8NBLR*8zlcB%Km63Br%mr5*>xKQFf66Z?HmzXQjBXO$4Oo`ji? zM?wgff#hh^j~0{unz?8+y}p81Ew;!*<`>8uM;qXiuz;6H)3&rVh3^nS?3x+Z z%DL@y*Bx!nzv2fQq4~4Ij}3m}F~{DZSdeGqfFzB86=m9j`xh<6!P(?#IkPg|?y0a+ zrY-lDEW%yM((3N)8B?cD%efQpnRg3MIe8w>jO^UI$&&oTJ|~@g-92^kbazhF9{Hv| zZzb|z?6-)-oao%=eF6@_&@Xpg>GP7aiPj7$-1bi4c;|4tMYt)Q!jZEnNd54(h@udF zDe<(#GZN2A{GY^g63H9|OycJfzmV7@v036?iTfn(m-wE<0}>BPY>{|K;`JSs6Daht?ii9v~V61PjNm)Ib2hr~vSJ0!|W zk@#PUuS$GPVvWQt61PfxUE&)O-<0^4#J44G1WNfWf8dJTpMofKjP)LYLoiga=WX1CoNvOX!?Q&7gcS>d$)w#oJ9+Y?<>k)bYDIuv1lIaDcI8(GjXX4Pvft% zIcj%3+{s_(d!xVap6qTS5K(`^Y22hFsu z);-}~9Jr}!`VpGsPBR5RL{ojtxZ}HH}9&vnMdZV=M z?ipTnM&YzY4=yi$2y3AmeuOr;|5&=CcawKi$wWt{1Lk3{!{7Ni4QYY;uiO%%U4yp zl=dH?P3}LH#|iFf3)CW!+% zO~r=tTfA_Q_2)mFUUL7bbmQGo2D8B2AE8U`Kb3BRJC8nkLM2!A%8$?`ccS}K^pFEG zA^7WAzL+lfcNYIJFUZ{v+CQW}qxG8PP0&tXP@+QKmi`EBa{sBcySmetFM}vY>-CNw zp-t{ir2D7nBd2@9efKRYDVe!=`O*c{P$BJuOMaLy+(gLu1A`teU1{fc)@*!5LQj~{xDz2{ioB0t}djC zW9ZZueuOr;Q(69$dfCM-KAj{8V=*B@y|Wbj>OiA=kK76Osf$-G$}K8hv|!tk z+nymRn}|q*(h9a2aUgxhUCwK1<7A6C!*(Yw@xk`}+c8S-Rbd`Cp*VJ2!78&gc|+{P zNq1pcNjK7u&DC^w-%i|eam>;jY7U+Gn>UUQM0!mwT+N4jsdC5zE+M32y*L12!5K?! z+nDB+X03Tlk@6s<;(ZyjE>mt4gy+`Q%i{#Ol)E399LC32HhcwM0 zn#5Nly?cTpz4ct9EvQXM_%41eHrV0rh4>sCp5|YM3`Wx(2H0VUU6_AD5D#z`LU_P= zY*!L^C%w~$FRb8c1vX6LUJMig#dU~c%bArkGwS?+;Y=JL_cq+mP|qiV5Z34Js))6| zJ*;nW!Y~}>w_YCBw`2?)2f+~pONYANrp-MSxj&2eYMXo~6N-EJYA^Us_ATz}J84yI zzS_%pDT%!^(|ee1E2Ai?u=#U|f_WQjJ+|u`9}}qE>U_wh@PFV`67CKHMXD!6dC)@a zY0bj!s{Q;uEIf)Un$0YTE189?;ksA3-*z*+)j9qdtB5VLGvvAxi3(U*P6jH_wN#)y38|qyd80f$ z2F7#3+36i5?rtmJL4NrOP@%iuD&3dyJL}=QU?I|pU9^-=ce~g?O!Yg+ABBy}@nisb zq^qr4^rXu4B%B;i^zfHuIDQ%i{SMq%a$UO9+nQUMKFq_{!Y-#W-AqTIaG>aZyt4Gs zxMCdMa8#x;-CmiKvBe6N#9zebMfy~W*i%e$7e2q&f9z^4$0?#}5PM%e9J^|uEVPnD z?DD`S+aP~{5{o^hxZW$sZ$qi*aYj7QD8y*ALByhHa;*ptNsWhR+60DudShXO680qe zFGlDJioM5(ze2Vl21Q7gxausivh-@>cHW=&!(G5;Z_Etrq{k^OiiG3~*9{r9>{beb z8&!E5HkUGvGuMMF=Kd^#JN)|LsO)xr4d(8Ugl@Q6wVtOK#A0XQY{5EcA8~Y$(k$wE z3qCtzFNLuGS>$pS+aq?Dg7$vUrkG(bWPdKMM70++rW zu8ke2d4$3dUnt9KlYGeXP2TRajPP_b@jOt#EM)`V|HhU0X)f|6B!Koaw?n#!4@Fd{ zq7oq9Pr(rnH-WKo^YSmy2H@UOctI9Omi=`+2lJY=buu-8Q(W1Vd1vtpRP8# zh06^ZC|i*cxWAzWiH;1}p&i6`mpa>5-Wee~==lS<8eu2yXzi{JHE!$_7gEX_S|d1K z8Nq#hU!8f@|GCBgg$4Ik(zTv+KkKZS)C6?IbiP?T4`MsDaAz{}@BTi2oqZuS@Cey} zS`iJ;t`Pxj;f}#keA9#>y9D8j+94yzA#sE3KeVPfMi{gK(0?e4--Gp}DstWi!U7rONVc{w<8@0sT-CPgY{MTRsXA{L;u z!IQRYWFQ_F_@4eZ5_ZV&r>4NCFHEglm|8cUj9|Wt^nQ`vPbLp(Qd?wtXL&l6&-v!N zH#DJ`AZLo#qJ=YwUpZ)3Gtj8IaQyh-h=53z*tMzNr0vm;cDxVya^(Q+XyyEfc3?AD z)m_^$OFM*13$$(C&%jdMJTh>FN1_I!8}j$pqdZ}BA{tys`x_?jld!oRpTeN4lJO9_ z1$`Lw2#ha$!JC+;Z^LJmIGW-J&XMlpZ+<0dq0%Q%SSODKF`;ApbuHp+QDOh3fh%KP zABYUHeNzy6L?0*_lhF_jqXGp}1uK1ypv}pBDDKa{gs)-l+|4-4`D2je-69o4F5p@P)^E z6L5zlY<6tck81NyfSf|&3xblYDw&pB$P-mn4;{8FsU^ep}2~C6vM8Y?!*ZRUE zipTlFV^-b%z~KZRAK`d4U;$%pg+qSAl1Sdr1*?px!tHSyRRipym zj%*I59Nn-@T#<(JC28|)tLBnNuf1~Ahb-3dDzOW6bb82F6erS!tD z9KS{Qk$v=cJ>Dnd_ZR%m$}q!WJ_bJ{1KfpP43rt0c4SC1{}3f!Ij;%bUtAAw)pD%9 z3mGc*+U2P?`Yz;qo3_yKL%;4keP#@|-uF7+&!1ye&d;&(I9OBD+y(arcPkCt1P?+^aN{+TZhlSC>R(2*cdB>1Z1P=j ztD|2w`z}mUd%SG%U6`&SX51iPM(CHVH9Zg-%pOy_a?n=l&ce;x&+%%nFcuZ?$qaYv zRts$X;T|hvY8)`(w!TXDW7=uQtMBrD&>Y&fO7CMq^yb?5ZU3bsgS-u?fI<*$o?Wb8 zQWrrC%b;Q|&|>N=w7MQT?!Fa%*YS@ok(#j>ON(?a2W>Nj`4Ynb8bNHQFj%C-&j`j2 za{8uOr!d%8i*-^q&GwsLH;Y4j(Q`oZqH=%TS)3unS1{;y+1JgGVzldA!6rtw@5)zd z*sh^F)3&WiA-5B+ib%soq|@4=AuG$zVW%Iz1ySpC{)z|Shg2Ng(rQc7^$`{tm)!IU zZ0n(ey-)k4!q$ud}^WC5#j?)?Z(6)WxwzYIk zhTiSCJv@HzL*3=3ULDRn$6OYhJvULk7rrz)}lc zeb^mtxi$G$F0jz{LDHW<(p2G&%*XLIS`_x}dUmRa4-6M~`kpn)o)%>_1Tq$L3#lmS zY$ko23@umz1Oeai=!G8Grm7>@Gnv;&ygSRgL!3I+zN!$Os^0FG(2|9Ig+7Gd_JKPL zX`>F7kQ-6ZQru{$5%D@BP@M?$8U&t>&Q7~rxb>cs{AuucCfntB&5ieQ3V($7PV)6G ztlA5=atnV5R+6?|L1)nzPy8CXtPmU0dwU9LuX!PEQ|wLei980G_@IBvpFY6H8tRg$ ze~$BUuw(Dj(9MLdDK1{j#<3}S9f9FTI~1R8%EZk!-70de5#PycickAac2z&a#bx*a zLL;&X3J7TQR}E@tXurgCh(WND=+pLv3m^qLJ=l)Pl~0ODgIq&+tlU$Rd<%?GE{SnN zmeB)PViw)ynX`C}K_I5Wnu6;}g9XSqt)7Zj9d z%V3ByRk!qvO#Tq^H=E_1MZLNa!|SM*{HT}FnS5r{O9PLCmvnyvU0LG4)YbcMBZAcw z!4r5?rpIidcIpr3am{o%Z%M3(Zi7J!t+GEblG~!x>iL#xiqP=%Y$s1Qayp|cQq{np zfTxZqZQiFlgmpZ!OL8|59rC7j|2_Kuz-X)Xcft#SoD9q)GyX=MQ}4 zhsL;mi8Y762>+g<4CI!d#i6YwmK^@Hu=0`BN3iN(i3d~>2e-dSEUCx&Grf(jmH^Ae z{NzaF1^J_IJctP=O5IhDL{lgDgi+w0e;cz1{8mco2)J*huhDSvt;J|c7h?;)kxIue z$Ad?On_dC83egi*yZQrXU@#ZcSyFsH3*WA|RllwxTK0IEZN%)Bvf+x3PqxKWZZ!_Bds69 zL>Ye%nAYNWv^R>Xqdb!-Hk9W$XyRb#9L5(y#8INgSf6B*%JlyGjd$uw+>e)s@CPHQ zsR(6g5&r0%Y{`xiPc~#G8sx}d{G&06!k>qMxomV27xjVvK5GA{u(wKkjC*2+(`-5P zFl4H%?gcd4Qkl`DT>r}QCQLeEms9;-sM$AL@j~9c{pCFabUmzxmG37{{IAV|lY=_D zZK^{<#c&Lu9FC}Hv}Yg9qaHu>&lCtFk;-x+^3q(ss|%#1X<}vh87K~8>S=RZB=Y*` zM_src6%X_mdeN*tZ$u@AKwg70!F&*kON^lEz7Sc*P{9(pNsW1X96}iSzx;Db-X`aV zNQukpkxAlzd5aP~4J}pWlaz0CH>UmtFXi;2mA`;M_2rxKv>Hj$%BzLdD|p625o+Z% z;{6RgW3)d9#7iAHYH#ikFT3dl^Z=eE*2+ps2i=1VY53VW7=hi8YD3{c-H5-N@GPqf zAPvT0^QkEroO-#N?)d=Mx8f^RebGX?Hq~LaoVVfv2R@%3v44PEjb7psE!8F;&Bu4j z>ML(jR_{fFQshjADx@h;JThq)-9p%w)wvM6823g$mv9I?MjMJtpek`W*a6-Q-OL&= zRp#Km{~C#0`G7)no-L}Aq6D7mAV3;w`eRWIMHQY-t53tX*7yUsNdt8VQScRrprg{{ z!8=u&I9LWl+n%LLBV#AJ--ul_roPqqtZ@wg_|FKj9>KfC=ZbY5Z0kXfOKj_jZoKJe zcj-zM(d^z@6-{31VSe)WNK_j>+2g+yyDmO$)CU2yYu+#Etq-$*P=`0HtBiXPlDG>6 zgGtw+nm1hUZby>o`y13hE2ZN3@7r*lb~ftyec@Rvv3F#19HOP>FBw`s7<&I1kxhID zlP-wJgd6rI85=>qBNI6&o2Dshmno`aivMJM7^7L(Y&YX-ECd8HD~MHVPx!t2VJMU)=f{4?-$@3Lo_fW11pRC z9aQ>IGLq53j4Z^6n`U^=7ev#=y8wfs?GQGdcT^F1?*s}>mfY(d=_D&E1@w=irSKG$ z!p$OLDurh$V*1V@{~M@wL|iK(KFj||b3dV6im;7J0QXQR(HqNWM{g|8F>Wl+Gj1#& zm#Jpzc^x;Fr>eK>cSdh4zty<0e6YB&ytjU{abx))y0LtKeoeI{SZxhf#{{cmgVk}t zYFn^6K3Lr)SZxnhcMVo|3s(2We%yz_VbNYPqcEd-`Y9A9ed9?JD+tg`c&7_8P}7tr zq6LSZI_@j=Kb)v|9aLy8C_sJ#LrEv<&| zFF09{Q7aGNSzlgXVeHO?5>3;_F14 z-lMep3)&q*69+aMnH5t4yzDtcYV&}>kYgjb+)AIcB|$RuOgR&4haFYU$4ayNDYLg0EqYt1tH?;~cnUBNXCcHSwixZ{Spu8Xg z3J-HpyF0S>FQk#$l^3CSf}zF#M_EHpOeoHJm)#@`jJ{@qW2KZ*p-Y7eC5sZYe4?79F1e3v>Cuc8G4v?R0wknHpMEN8|j= z8-~I5Ou#VMpQ(ePW(OW<{S&wNi2c1GYGrjqhRTIT1N5z0d|hiCdI|U73mJ(O%GWyE zQ(rRS1MBCf>!#`D=Sq82*hd&2HFG@El{(|aA@=UjJ!K!EY<&;KO!hZko`A3JSYI;h zJu9rEzedT7Yhr4#h=O>HIqg(@OQi<7`6AM}c(HHnVq$#asT_UY*&BchBR<$5|;+u%Lp=1ue3q-WgTIGpmisK60$lBrX zHIG7u*Ig^t?TEWHOM>;hcqD@swRz^JLSsD{WI?fvCum?r0jq>TejIG1b>+iATv55b zfNugz#nNI7yEOExJHNK}mq(-gXl@=vuvUl?f;F)B_}>wq7=WeerE@SKdJ+_AjI<#) zDe|q6Pmgr?DCy)wPhxQu8UK&9bAgYlxE}u|*(6J{kbprWB1VmhJQM{LP1J-u0C@$I z@K8`9BnAx-lU)TR5Dio|mnijB`}0vzYFkPxKB|cPG_V*z(IQ$!z=Dc8>!JopAxLEZ z-!u2#-3?ap|M~wHZsy*3oH;Xd=FH5QGiTC6vQb~_CU63Q^>}3DWd-Y2BczaR$%pq? zR!pS~vgP}=?DQ`_l(Oh5TRCoLD*$W0$7R!O3sRj&-c(JPBjhBQFmCeszilz|4UA zMElEKoBg+C{c!tgR1W<1-I#h`>wR^))MYF4#vXcSwKa!%L>K&6z;Sgi4N5um2ADMW zQ(p**m=e#FOHc8TGaCb9YI=HNgE7O0LlT?Rd@Bw&Nk!fJt={iarbATxC-9{r#}6XRN*U3xaAr(>n)R1nwJ!I zxuu`F!TR(sxxqyta>OL)JsV*Hhl1xc=3kP~IOUSWemiPT&RgQlL@H!f)6C}=mi1Yk_wJB!cK?0vXBwiP+?PhxI6|cjcAf0N4+!==C7Dyr? zfBwR?nh5;rFOuwtPPV`3Rkt9CbX*X~)5-R;zpOGSs+6dMcfU$M5287o^dbKFMgvprB0e)NJ}1fN)=tUKHk0Rt zlmBbCPJVTyjpCV!QAHWyC@+{%$f0fR3;{XM%AtL&M?P=iGvsX#c{?f>@g4HEtx2UI z=8ftHpb;x@nH8884*Y;X8s2Rp^~2ZHU>kwq;qw4QN^`7@CxW{FaT!C;VMGiD^)x3U zix@;W*@O~sXI(hsLR)4bfM@Z`m@yzDTD~E&jIvo~8hNj_-es0i$s@4DzmgAmm;5tw z#}tjR!sJ^%Gpuisp9qkd?xIbQNUQa@CXJe)m>0ZOERn=W4cJ zTd*bB#Ezd|T_2F9CBC(|Xhk8bsZ=fR%OJ0|i!5@CVumvX%{_G(fkm)4>6U*Wp)cvs z{dVXRg!(4A)%lM^tv(7s0BecnEHdjcsnho!4%eyHZ<1|nl|#AZqR8UaF~;dnZD)lS zk5N72G`Url2nV&U%WFCyl?_EUC$;H5HDn1K9I<9l#?H!ZkyG8uS%>nf!53dJqpFIkbqp`}7x%KypVf+^$r;O%hmy8Gx~g_xLglPUUHA^vd}-|N&wVQ+*Yg?;t*q0v(`AJwg^ zKz5_kXwia(zX2#}sV}32$mP`&RtA8-1#FD>>p#O>ow}H;jKbbUYBJDuo^yFwv}-{k zfs;vNr5B@e4GRW1JpCB23j3;ID@nJF^?ug->|ym<^eMCNWKM4Dv)@bIyLe#e0iCWTV96z8PJk9 zBqo%Xp<#taWHijpU}d>mw&V=KBs3X(1ysr^tn6``dJ5CXhj3+1zZ6%N z--~c7ap&W1!{38Df_PQ9J9g$fX5cR6dkStdZV7HC?r7Y;xcRu-NS}=>OP(RP>8ub3 z;I<7v<$aJ9e+cg% zSn&t(-fYDm!24zkeqY`lR@x-e&)|{0(bV$XSx}EgYLWmRV54{@$XSRM4^J zBqG!wad7irftyKZ9X2fSVPAbgyxxQNvAw+}1vvF}sj)R!^_K0?eX0cZZ`5_LCAn{4 zXrUyCtxauuDJS!p9Mdl3!4<)?o4jA8ygW6v{%DMcKh8V4q`XnEFRQ@4AofK^DD8=j z#5FecN4N5Z8)cu=?FiyCW<`#p*?P|XBWK}~n!R!8S@`SgzI1rvRu5e1R|n|!DQ}F~ zH+Xy2827?68jk!pzgO~>g}qk~S}C*foTp@-wDR!Bs|Oui8SJf@-7w&IPF?v~ySP0Y z_v$DWf0eJqmBDt2iDfQ!r?7q3pUZ>DLEq2Rc#goT_$%skBULrNfOx4tlGKJH&YIZ4 zTUHk|PW>w7jnaMBtW4VFc>0Vl&d&5CX7}?X ztqi(VSNxG{js@fEC+B^(8>69@$ZQzJ(|Ghn4z9StpV==bC#PQ~e=;+8?U%u8-^_mJ z=M0pP%z^T!-$4BOW#T6h`wf&onfMKq*aIaUF9QXD{2@udfdusB`~1FyoUaKv$0THy zh#%{%s`{g{9!^Xi?)3EH){XUnGlD%*UK#F6)?SGzuZ(l852UE26u~oEHRCYRSZh*v z8>4W4R4BJ;(ie@AW)^^Ns|xxAngPw2iLd8MfGa}_(LFlq@Mct8*~77*S3R0nUOB;@ zf+jVBAxZMP4(1bQ*4O#DUC!J>>m@nv%<{G(F(1jh`i?&q={p^4x_*B8s_gSTnb~J~ zGN8)T>@4qhpMBGqz`K+8WMb%#*z7ESy+jV&$0N%Vvhp=?v3WWe)_U{@&#+1#K~_fPXaj2s)@b zQ5=cTLhZkP0lKR`jF|K8uhZ}QuBQ*9qsF;@ML#(SZqSU8^o1}LMGtE3UyAYc-M-Qt zC?dgInx+zcgTv#>^19#v16N9E&Lg+8Da}Dj^Btw>Luq`H()a`J1PMhymvI-21+2K7D>>4US4R?1|!M+7Og1L=xc~npGDDAU%!9}YF zHPr2Pc$34tCfH|Xy%=kT)$VSoahN@oTu+ysnp>gZx5xWs z(_L|ECHu!3^Lu{LxVKq3>-VKp#19%&@z-m-!Hb($8g=b)b*_1`Z+%Zzott5z&fO5| zQHum4EAEn-b6WDV;vD1Vc0GnGUYFnTP4JA0O?hz_ImjWH_J*)KE7GYFVUXuQg)xC` zj`oW6U#C>~;+7Q0`k|R`jRdU48k>{fN?G(0X|O10n?FSNqt2Bag499{A?N%v-jLSJ z9mrt#r@ME)`10Pawcn3~pYgR_zR>FQmA37f)oOgSMq>8g;7Qy$WU-T)FiZRx#u`t1 zRf^r1-_57%oOh#Bfa~Bmp86=4qDkc91n?rGt&FDv8ieFNpbzxwD+U5Fm~6~kL}r8@s}=G#$O#1bbiA18-mHKA09Kw z&M#x7Gdsg`cr07lgSW35aD_9eHf3j58P=Fe>@4UQ7W~=_YwT8kL{L5=C^shPnB59* z-JTS;?d~7iVjPZ|uO%$@@J^w4SrZ;vWv>ZC@$IaCQx>00H1#B!0_r_hgKOHEN9Yb-UOiMMq?x6m^vU zaH2g6#Z&ZiqCGDXPf-YZRTkA2^xoo`ew=5bc*+`Iy}Fb)5e2B{ckw2?id3#CTX7U!64LJTLHWyC5m!SrOhI*e)>T(v|raD{0 zK&i`^+T1lGo}wnQ8v&EOoVT&OEw5)PDZAS#x^~vqlT1wozIq(lt@`JF{%l}0QI|8{ z3g_w3c|QFcGtY>eV9;FN&zY<3S6OZPd>D^Vyc1D=7{(e6;|2?c*aehe)7HuIkZEJ& zY0G`aa#vXHA1(J;%l(t({@HT>V!10V_pg?_%5wi^xqr9Z=PY-b<^I-kAF$j9E%zbI zeb{mzvE1KT?xU9bd&~VF%YDppAGh2mEcZ#v{e$J!TkhSKdynNdSneXrU2M6(vD|wt zcZuctEVt2e4a;3>xlNXPpXJ_fxz(0?o8{J6Zms2dEZ1wfw_ENVmOIyS=UMKZmV1}w z&bQn;%Uxi(3oUn=<(66QO_n>|a%Wg>x#d<^?#-54X}L2k_ZG{&)pDyWcb4VOw%j?E zTV%Q8E%#c>EwEp`&T*v{=l(&Y`)MiP=c|$$xr6=g=JN><+$=KgI`IFS3dPO zT-R{{4_6Ns#Wdxo#%lS`M2yPI1#u%{jC@zJ;ozmo<4Q5+yAru4ty|VL9o~}~rzC|g z?%nN>e~&kQr1wCuTVuDJCQrAR%i9-x(y&=nZp{5BuF2#;MRMac9gY3i4BJCqyBa3} zFFm&LhNP5N=J!cvJ0czBv#u4!q+a!3?YaDIPoGyD;;%Kbu6}q@8z1N{P_jtb=jV*DmQ1{^Jq4$EPf=(#ph*{qlQ-3tJCaJ=}Wtpd)+B5L0Wg+WG zdA-@w;~d(-apUz&7E$Orhg9;>guDv9)Q^nIj7!P(D#>wC+%!&Sd9`PdyPH7tq`#SIFb3<4j50Gm7@(7J>}u!4XO7X*ARDULpSWlV?$v%poq z05IKal2YCX#SIOe!Ukao!|eXMVc`JU#DvM=dsnwy<7ijxs-c@}VwY@Qxn#YzdT-); zx2X+ms={wHIG_cZY9c~RW2@GJUIZ*6K^lUF$OHB1K2hKu2ou+S6#K*fJKWm2tMLUO zNAGEBrQjyx{}W95iK(-xizY+kl$Y!-BkDCDsc*@O-Ev(@M46FcZaNWV*ZNHcN`K(R zg>)q$DK@U9&Wv8hX^p4V2je-kz@M(i-u9#hPg0^6!6C{6rn3NeT35Mv!bQ6bZd+`e z3?ZBvyZ-aoU9;r2xcWP3y0ZSyd_rEnFGCL=z!g8COvu8d%OdDGdY@m_vh4!gF8>VbK#A?I!E^zi=V~5Y&T9Q-VMX@ zp0Q>XMNr-brY$RYi=Nf3pyk37iY}z|2f9+@+Lm?0KuI3sPsckhsU){*=FPKbmCyDF zZ*$1ZFpU82n;czU;km|J>zP?GubZdrTDd0O`gD29@<_mW|0x2aOUbaA`7_7NnNhAm z$X>@J0ddm|0Z}qXC*@1KC3D0xt<%@oIU0%dPM%_EVCL+b$IY&qXEbjFUW~hBM0r)U z7`rH+>yZ3F~=FOQkt8DfR=fpWRGaSzRGEZ3|1|P5pQWN9KE32v! zBoc?snNw9>HrsYr0q2)~5-#NVYivNcu@!=Whgn)#kpARa^UJU$TwqTlj}zJK=~_^j z2W*dN!N_QyaRS&9{%c_;7Zi@GE}yN@UUvex68?Vy7YiXZ8gAOFzg!m*E^w=Xf1Tk;m~*@} z7)r`t_sjJn;lCE|?zYV+dU=gDzGO77_yzc@2z!Y~a6ggFnW69HIQDMOVUG`94)CYAFIFWHd`2iP2tyL>sal z2VOU3t&WNU}ww zv43s6r@ayR7XJjkrH(4e^5Zc<}+4ob{Z_N5}ew*XiPddAP)_p~@ z^E{-?`q@T07ioU3eijk;DV`GYN&}W%ROuU14rnUE2&JH@y08)Akn$f_-srlJ_m>F& zHT1p;8d(Mob{mVEDA_X)a;?uf9&D%Ybi!TuOd_ves$&1XI1L zax*8R*>i%t7Fl_%J3(GU4*WE)WNqfv%xU)t^4U+g@XcRSCaJd>C4^eE49;CTBon{ zPG7w{eRa++vr|}K{S{CMjm@_NB<$u}DsNl2-tLDB@-*^%LXCXQ)6SE?cN))GJcD?y z;u+0z9Zw}s3^nKGkzcd^>nMB#e`!Ja8O_-n8Ef$QxnCvWy8gRI+IvzF`&<{oUwDe> zE5f%Iotx`e$CG(pu45^Wvv01WlBeqYT*q9VMLf%R9_Q)ZFW1q{>a*79vTP&y{L*h5 z;h97@(RjGzKb?6)g6>N-%QD}Lz#kFyZs&O&elz%(OFq9u*SmknabzFOaa8lDA9Ebj zI%pZ5v|hQ6j#G0T**tR-DW3)`^)G|KG~7g}v5Xa^(OgMhN!?1qlRGi!JRd*C-2C!d z7TM)B=2}#bxryqwSD*d-z3wZYcQlWCe$KiGTWyajN8gql$DeuZ-xa(+!jp-IjJZ{3 z=Q_60UjNPZa%%5fJ*MpFldIWDGsws{i zLmeTGnuLA`9SOCE4u=kf{u62o9b`W8eds`F8mTLJs(2RhEa6$k^AOKdJoCwE8BcF= zSju-b&lH|~zLO%A)nt}4G0IEoK}O}+@H8gYVPO@5c8^(gQjg2yl#v%yxje#mPehMtnba-M2%g7zs(GH`*-EMYj4N~4X}GB+ z!^&!BP8Yk4b7qg8Ir~;{*l`>V*_(61_+;?jmq&b7QT|_Q-*$n&6L`O}eP1H}?sI4% zo_wCsJR^9jcw(@kUxe$9#ur=#x5Q4Kg8d38Fw!c*Z)Om$Tep&tGnkQ%!7w-WNVRQB zyQerQk2b4?d~|#T>i-qK66=BmIg7*{3NCF*#y5&>Z8v9s5W~5E8yyz6nb5dWx3Aa= z&Dm_)ON{Mwo~Z*P0UV@2oLRbs&L0{y!cmJk6exX-^3b2n;sT;l-ff=^8>YVwVm2TSDliogRAtR zh;z|=80Fn0U>BQt@R}7bEYJHOT14tV<+NMpvY^+h zu@Iv&noLgKYPXG9UzN#Vj7Dy0<+pF!A%VLoM$^OEWSw8VTqfAdhX}#bH1-{;<428p zjvQWF+(ux_;&%QfH|Y;K1gG;|o+(7wpIrl^NooU%6KRzi!v>UksuFKGc=BAl!;y8m zl-F}As=W2&h|-IM6eKzvIVp?gPyyk_{tt+n$ftn3KX4{sg5QRNPp5=UizPEPe3psy z)wuq^k(-J4MdVB%V(+&WZ<(8D^j36n|EiND0x z(O7WQWF^=M5FW1YyV2+KQT}%sr)xV4r`?i7Z|?!IVzS{i^hPo7O4o`>1V=6h7a)MLCF^;9BMc)xxZ@9WfMu?{&)uTvG9sj772Hn8U}zrfT=@7N zm3-8XEE$Y?3B+Uu*S&ue{=QDV$C#>ihdmnRx*Xoq)!ShYwRI}sU*j82w@hHLH>!EL zFf7h!bLO|hjp3;f` zK^QcNoLKzVUBuqOAIwD-xSB?EOj4i06_enzR{K3cmclgOfJ6BM^Pqh>${Wq6u?58l z4mB)K6+-XzPvLW1z51Swt2%{ph*y`eSE-OhZ?IA)393s94y$W*BrDfcVye0L_yY-& z<-ssM7ZPG-^y9k{{1u~3@Y}|M!@}KUj2y3;Z$uuMmWc{lO9hhzm2(5?VcD4ueTw5j z0RPleOBwrs&#u4*sM(r^)T|BzU|^H)37=F+H9;#8nY-RHse{ed4DQi83z<6u{yzzJ>3=}mgD`j$#8@_B4a%B-vz zy>xFKw3do|W*wFi4v~Dalzf?JV}e3nq|6)&f`@VROs0S4dF)8p-us2J_3TtO3SsnK z9d4=}7W#`|-TuH;8hs%hdj2w_$ldTm&Vp_-e9en%SRc3kNNlis!w;?niKeANQ-3w? zE$)(^1XhAyG0N;QxpGxJRtcP0X@>WEK2QPN5;E4CZKC<2n4)MGYg$(0w7h>@<1C7ii~B40=}oa5Cb6e>Ag=lBuy9lf`2+F@T$ zu10GEc9pwm<$x>c4XT~2Gh(RuKz5S zGfnE8Yhi~`rb#}s@LD`WYT{~*mu~#y@|=p8-<}&V~HP`3fQ*oDIavGE+=qF=}{P?FgrgzOE^WJ z5AD+8i-jHaE)W|_kIDfwqOImD+_L8oS3H9g$d=7Krr} z^}pBAxrN5adpvestW3vRnHtAs$_eV{I(-y?w zuX273G%7&@I*iO`!g=nbU8JDj{WQ-xP+hoihpaqALgNo)MCGB&c^>*YnxCr!lcO4C zzEp*ET5r*W@Y%foC5|4qHEl`u_pr%httBDer-Tt#&IORRC9y=f;`mn>8}>2=g;Da6 zMu_BnSd~A}M3A=aU~JCX##w^5usEP?2aFfSl2z+WS=0zNix1T$GC(v??54sDtPH}= zn$K9@9&fa-|4O)fLvtrzwf>9PtnWPISp7LO(F{A8`PSO8P!&h)otfx;f27{0CvgP- zTy5q4Wafo$Do_`j2aIZYF7?bfKK>2v!n>e-A)tNtC%YMr?Jiq1e1l=TuGU^U$xoq0J27Pd8} zC=c_aExsmsi{ki)*@3fJisy7|8kC@(D~_H9b(NWeK2_~TD5GwNRnwJxi}wSoMK8XR zt(0-fD=8Ptd@OpUh*>X*ET?%N77UhG3&V=J9Y7i*=B4J{8UKLNZl{ZeDeV{tHZ7Jk zs^UgKLv%Ob`UC02vKM$#Pg303GpigAs3gAp%ff48b8e{D`Pyux(ERh1!=ia}<(r_^ zK}uFBHmTE~Yimw40RD*H;b80YbUtD76|Wr&sqVaMAK!2MFOp ztRYA+UvYzAegj=l4?Hpv(`_u1i3@n-E>L4L_C9i)p`vt)N0}T7DwX;0f-%&*Ou*Bm z7?-klXchzeuYPTpR{fcBNSsNohPzyjg({51l|;4@r(^#Snlf3H=IiPolqJm2t5`_d zykkDB$fB~liKBUkJs*^LAdA>m(`c%Z9x5)0+&93S@dzEpFVdYM(Qz`vaWwzeHaQW( zSaV}3*Yw?XxjF{=e zG<1Cq3dx9~<%_bc!33&N-5YVkK&}ko6XSgvDYuE#dE)n>j@Pd0$;a4He=sJPYWnD! zWbyh3EViH{X!RSJAF`Sf`5gkq$|;{qW%1(v67iYl;ggNcYajhY*C8!`k`}!ITlyk$ z90xmCXqwbILL;0FbHP24MF9mL6oxM*M@`||nEmFmNE&(MzwM@PDL8D?D{>NPO(C|d z9o{VCpfvj+-R!Mqm72}oTGTXVzuEHIqjdiywT?dLbRy|kkY&t zDGl>+O|`uxo4w3m)Z2f6+eDVmJ9I7`Y7v}~^^ZmY`wN=(bv-JJR+KNAR$kc~RgD@C zPIn=E_O_aG=uOy_;MX*U%Q4!*l~$nCqqKKJb8Os>P(j;R?;fG8w;3@5GJl%dZk%R8 z$SDj%*xw1lel-CI+ImhmX@UL5Kh@CTj6r)^;=1Ow#3kivz?;K${5qJ14Nq)<_4)&o z7%0Ql2oL@_UUJVb-DpIzLS`jmK2qL=o`|ol_3Cxm_zBo8%`o0t-gkYDm_7Up zGgOPhnr#e;_Hb{x<+G?7P^~|hy=6?q zmwP-A27$C+UBFBKR+g2lApl61FzS2UuBaCtr#j|@ZvRwW{$m2TtmYZU%vZZnj4EP?3~HT1@bz2bCHDt-p_fb8}=A zcA#I$?HzenhZybk5InrsgT*M6C3fMI)9a#C=JSckY|9ltUqQ%>PWt!rtij@|YqdnXh?7<|Wm}g-?vxYAg~+?Vki? z;6uf^nSz=8A{wWxFYH!fqDjJUs2jmVH*bX6hY?L?qP;XGAFwF0R`*hO()XmXBVDf} z3{@(|dzd!fURt?F`^q+%-NqR5$q8O=_%ZC#coMSzBrZ1N80gn=-tV}>U^7Cb2b4jU zkq$VdKC3Gx&g!$0^k0W}L%6oS1iWOof$aQ&K^n(!U>x%gA@RwuPv~CEB?!T z@*Wb|<88b8ehAcI5~pmyz)R2g2`@D%b_X%xqx*ycH}W3F!l$ul)9X*xzhkV9Caje8 z+RSSxsR&1!vAg3d%n&!zhp`)LIo{Mpcws85id18Q+t|E($QwDVTi#-Lm8hv=%tu-yHXvVfnW*Ed$1*HjN-yVsSouU zqcPQyC)J^;xUU(jTA!_nru}=BT>+*{Idwk8vt-IoAQ6@Vak+=O=n(JWoSK}iR!$dD z@geffON~gIPv#3b?t-9hRzQB zJc>Uc^|evF?>~&*Aq3-hMHga+6+*eE6k`qC(?>Z;jcp~@K_72;8qcfd81Sv{iJBWazE_Gbi zvH3%qdSCWl5M>6#xdS^z$>1x>M)+0=Wheg%X>0keRJ#9y9Yu8hSbRjnH+(z2>>I)cZxK%QNASEA)r$6vL zyxcB1^ZA@Kzmb!Ayxe~2FJwA3D$@f8$rKWu(u&0cYdn6?%5Dps$RB9X*;%4{qj`e9 zP)~&SY&Ik9YKdEa%og6io=UTEBM;ro5%)bERXV)B+fqx-bXV@C$K=mwaRf}klg(3k zGLxY{ce+dw?f`E%j^=(7wChrUd32vB5xI*GIWrZhyZq^t$?7!=BE9BjGluRpN53bw zNokqj8ZLPg;H9Gf3HS2{d?O+iE%amV@!Et+&&o^liu5nQWX9}h>9k%`$@eZ}l)K4& zpnuEyy>Y))-)HG6mcA+MQ*MnA88V{2bz~FDOSK3c&huaQ1{(MOOqm}>oNbr+d`k3F zPEl*d&}B}PGI!z>AE_)5IKG?xmh7Ys-i9Ok1B+P#*u-Y7h3twD9uV`5joVK%KZJ`3q<6c3B-xheY`aBetLNqBoinoTY_qNyYM1<959co`4&HXA zP-Gcb+Wy|x#yC3Cd+Kpv>@j)9aNV^_+tj8;>Du$Z!HTW+M3JRUy`Vi8ev@@@ephNs zRDJ%$BEXZhT?6n^ZMThNbhYsqOQZhUw-_jeMK>ou2)VFSP2+96QbV z>H5#&xD`|VIF#hIX*6|{o+B}&UU5UZryBGR8^@(?)7|9@37$Rrc46kHfptG2ewLV3+42siU_k2XLKPJ3ME~ki1#M?*S38 zj%i0Ix>?j`w*P?@b6G(Yk8=S>hT{_WI{Hrp>5<2ttD0-5;1Yy`@qsKjUuuF}fgVKii^)2?1U z)0&)H{Pc6e#sAYQrD%gScxD>r8b)@39``XL#^5HVh2Z5*wI=F2<&`bs^&Vc#!w@hq zsWF>PED2sPhq9dd_vpD)SUzK`vW(54>JKa_MLL058R<2y19qEL+zmNEg@FB z?=I)!P~B}luUG@uHwDRk1g*P>?6o`RgJpC7OO0zTGs^M433`7ItDE07>C%)kw5g>;_)&~*}*MU zdZL)h{1fE?zse3#NZIsBz0Tqx6E%am%dH32Hwk9zGwX0&*Kn_vjx2*qn12u6Qd*hF zd4L(Ai)Q%FY`DU)Ak|2^dwu8(t`7Osu@?wQMzz!UHx>s*q-GuQOd|?LyINGSho;&U zEW)n$Nz3Qbpee67j2;GUyC3+T)I4$a_H6U9JV) znPaj;{1NrE4u*@cYrY@o*hdauZK!jhKQp`NqCHo&x zR518c*%up@WI)XgibV4`T{sozrr7gEA-4O~GQp_Q{>sQ$q2t4vxEO6lCLW9f6!s%YE!#xe0y zBQJswhP!-sFuZ9)v5ScDlZHf3j&j{*CT_(@8Eab?Yg=^|$*q#)5lTrqz{LJVzuSH% zA2QExoJdby^bwIa@)HrhoLP_wwYX`xNhL)!bE*qx&h=Kq?{pb$(!Et^m8pbptkWn+ z^I=e}Ak|msZYoUWsvK1c7i}s`gUZx3yjs?A?WB z4&Ach$}}{}94U+ZF%C=VYu%rv`AaL`ZMUgqd0){wo3RJjx}QB44ry5Ea-`fhlC*Fe zt-WzEtlW~BEel7p1AFQ~4I?KUIQUTD0V-bi`+b5xd?z*3Q}9BMS}v)@{4U%D{gzivYH;U8Puv44+%0!^Gf$LB(N}89pb|0YC>kB0+DrfpWUNb$zs=5ylr2=an ztZTB)^udqG)UW=03ACN8!ycBf!mK-7DND=gpyAFi9LO@qs3WRB@K5McOEWB`$G!-I z07z#!U5e4pGP9>B5USTHHgXha{mmH*kqYe!!~30v*P#Y#cndYWaNx@Xnl(T6-;&)l z363Z*|4V|kI^e`VNpP+XhFJ(}0%>ixXWYcG1=mu!(3_syO*Hq*8m^QUrPY5!n3>0K zKCxT(-XnIq+e*s$da6D`s)=gu5LsiPE32TxdrpIxCrrVLi`2@f1-i;pb?mEl5Sy`# z;Xtb$uM3y!KH!^q-cFv#Kdz8+370eFn&7H+chSZ%(e&JEM*kdoHVH80hvQK^UuXJ9 z$rLW)6y!`iUj9hq@%CT~kB`E5oD2{X@V5Z=2OMEMki|iSqKT`g(Z)kC#a@J3Yh~#i zHDL^dl{#hEttura8oxQ3V&)M~*yrb0Nfu9BE)-+(&Rdv>lvb|o1ZRfG)iNzObEDy` zx8OXc;gs5Niq!)zlj{!A4v$wikV34Fi;m_*)f=kQgT;i@{u9zXb##3NxU}ipV}Y37f11 z9ib5rSciJ@G#%2CGbKjVfC&xc*dYB&h8lAUFsQ?(4E7FQby}c&aC*IgARGJLWiC*J z(z)#Hso4@#&>=9jj9KswlgMR26UuHP1Akx-gSGDO4b9V356Y$I#i@E;488c(lc&n2 zM9M?W$OL6>+2YKkP;)0ZJY7qO@Rmq7C!y-V9TZF}X`{P0%4rCuL+HqI)f;kq(~?rx zs~JnUV%11g6Chk$JD)Qc=*tY#HF58 z*1yPShX?|S)6|pMqS_+WDYB?^4KZC7`~zi=hvP5aQ`YVUsBr6Z@3i?cng=4uffqAv zJp2;0ThKl(>e|tlbczl&1+@Huo1o^X?dA6fl${&{uICRF=s=45-*}(&WxoS5rPU~Ns+JA%DhjgCzoq|?_kis(cc{;r(p#x;G$yMz8$oICdC3vYZHm(2I z)H{-Vt?FXIZ*1D-A7i`g;|b@#4Tp^@OpO_v>TB`6wLTEraqy46_ZmKp!&GvYUEY@K zO&eJBDJ{?5A-v>*P`FKtMK~rkDh$j?(?h#J@4C#of3pt+m05?)HiQv+0o8By%uyi| z^CogWy7`#zpw!dG z7WS(UpIRm<;dRhLV8&@wHeoBz7P{C zqVv0a!`Q+hMr-|ujIdrz@a(`VgNUrxa;}EvR=tJ>JI19SE{48FQgZr?y>5_v-|Unx zITrOb0av_sB&7Ba)Zm&%DDf;Z^K27=87gchiIVBC&Y5na9nDM^OQs+2M`vo!<#lm6O_iq{T?RFUAO>%}*$Zxl8!!5yNi;PNmwhZ#Xsp^c5X zXS!FapIy`azA;MA%k(XmfjAqvrZM~I1~5&*Aw%vtf#FT);Xqada&2l9uM(Qm7qi(? zpPRx-8MN#v@yUm{*4)#jRFB=0gRDm51S^>?r!4xjuzXV97nM>st0a<@>o_~Ew})L! z^&DjhEERrLAaP^$$l5B@#eBTAep<$lq~?k$6E|bbKBKg?;mux z9Xu;A56Ui8U(v6Gq+LK#C-D!?eGm_@4K{eqSI~-nbdTs!MfNT z>QC)a2vrhE0$(^HxvhZ)m?r4xG6AvH%GQ1E-^&hblDSNHmS9QuI=iQo`D=Oq(43Fx zM%6keIhm}2M2GZfNPSF&XxyMV_u9I zQwhP7WmnX%9%d5a%g^Ly5T5MJ$94_iK6x1rNzWKTj9VpricYU5Yku_!HEX9YHPdsW zN~ZH;?xX+MnK_x66XOrHsnhqD^r<>Mj9K!3Lelp(^Y3Y0KCxwI>Bw-J@ZRkHTdOu_=p&^$ECq!lX=~AivQ2Ze;x=00ty_y0KAyCC~5y zPS5z@RH_Cv1hrTpnk|iP^jKlgFToI*JNIN(X>2pS{b~=*61>o8S-S&dRe_8aXY!@w z>oWN|iLZ9~I$yrx)h!3j!&avLB;xX4wAC6%xac~E>pzGjWB|8BfNloQrNMmWolYC! z@nDnkx@^F*i+CX+38q0szq(99-pJ2PkdU4f(Q3Uj1pj#T!S@u(Y^-IX-vyGQS-xCc zxSqMk_tZ;Rk60ozgLe*vLYb}EtzJ3TI|-CBQPdSq&J z%h1MMooZhu(~$6q=3!Jfy}`G5HyO4p-pk+Qd+Y(>?_mqR=>TDp$mUyXplWLtz0QlquZiD8` zEFOtuQEO#^z~i3`V3N-i$UfN5#NS+D>T!?>msujvpF2(DCB$uq_-!s5JUuYEuX!cB zm?FHN`YBas!gP@ou?u>M3=J}?)6=X68M)MF{IQc) z9wvco_m#uD{ed$G(!0#EO0w34q8}Sp(rYRBj&XnrFwaxhzAcrdq@9gqyPdgu!&)R= zY%Y?}ioIYHwY7uhG3X6hc~0+1h}S_aRP16{O8_j_1F(R4FO1j&z%w(cArsC&QOe-A z^>yEg^Z?~#t!}A4dluh#b?>)&5+_*e^$z!@XdM~7J*tI?i`+JPQrbJ1oXN`ceHBl+ zjrZ3)POzG(2@X~FbBV*sdE{D)D{qDY5WT2rLd>f)`$AaGKk%|RM^1VXM9M=NIUVp% zy60*n(dyHH6j}se-X3<`0p!``O^}vj_gZNB&n;2SVSooYnY#)9VKU?o80Qh&)`>QG zxS(}`$>*%QC(X+zAMIur(#%f%j-D&J(2ag>UrM=mG6_SOi+7R9d0lfI1BpHXcP39A z&oZ7*c*OrC>ydYP#NSS{g7-B%TY1`ftjsur@5t`z-C7&az>C(rnWy8SQ+tq2fvTS?~#b# z5&ZVl;df8O?;-|RNgKRP&z6Oet1?-hmF^e3Cy0o2f}TC=pl5ZElAyaJNLE#nNK6eZrAuqBGsVUo0pzP&6Xkct4a zU2TV!!{q-5>YO>M`n~4j`_-HDdBNg*ukjkv{vSJ7bW?R%P~0{;Wjff!HMF}^?mb`z`xm?i{uW5abz)~`in2*pzqSi_sw5y)a zKp{0&$Tnaw<*~z#JWbdHAt+hdbf~`wOkVx!G%14}ZM#If&;l{}Eh$PXg1S-ob1^rv*T01eoO* zBXLdI>`<#D3)6r7axmQ{(eI#efh9mIwTiP7R3nHCMNlv~c&o(x*EdvUSFeaTRT-dO zT?6%4@ID3KV1WhUQ40bSmm)o_XGMsvCIcA)IgWQAmfz1kL2`)2#O4`E&8YT@WEQ5o zM5spSt`v5Q{`1+yX^qgC><7sf9=jNRCF72@Ipje<7d@&q!lTbBEcVsO4r;Q`D_3pO zVy$|%xW)r)l~YSe z2wjWP)s@#!p=)H3;_#fLF67I!wV~H@gMvNm_2+?J0)QpkASv36aM1*k+4ebu)QZ=M zq}yIc%{1Rd9ut0x4ToDRbDj`aUV`zO06L&3EmASODr{HW(vODy$ORbctNI^$d{7bM84+BB_@)@$Zzw-+5Z&w#k z$>H3RNiVsL*SRI@+^lmR<~laKTrCD{WVtF=R#3>Sv;Qs6&P__0OePWVL0P0T+|(S$u^8R4`x0o6RFb5{F7~hV4Xxt zS<>mnA$lg3RD2XsWQo)r?&%M_P1BmEVfCIEHrpEf9l=D*3>}be6sJC;?wJIC%j?lr zdk^2dKZ86M?^0w6*to0P+Rq;~Wzv32+pu7fqMu&1+;41`iqx`Og z>uvr$UNANj%UWDLObou6wRR{UfbFwKVpmRZyb6p;iDOB<<5Z3yOoBD!hyI=<(FN(t zH*rsm6y#zGf={C9^9rvSX3@-bBAPuBc0N4au2Df`zSQU5g$?c9Qttg5*)U%94#} zeQBFosJ|{LT_e&eb({V=&+5-dkv#@`m8$2oFWZEiIb=yD!{|ow3X{NCvXw5>4JPFe zY(7m$K&sbTdt0>hTVjQ^ZJ?#c0god(q+v*pYDgVwBmBT0SfC+A%M0}hDp6=ItsH>4 zO%ojYDE&AGCbD6Dwk|{V-da>P@Xfc2r66LuZk7;Ki@E{st7))B-NEE0D5rs2)T3r# zt{J!=pX&$=qc)iQWQXm1joRmMX4$upMVKi|Z`i2i0nAMIi>_+;!jxbbPpXLXM0b;3 z_+wtW>chMm@u%)kW7)_Y%W7{TeW^%Jtg(?<6e=FA1259UubyTwEfzCzOuzTbIwSE? zphc$N1H3TPh2R!O`+JS{epPdZOsU(|Ex7(brl2oVOIv=)wrrsTy_vUIx3ViZB2=7j z?VF2o8ll_@+jRoM)VB#9o)emwEu2J84nz_qdw3tRhqsA6ym9XS<75x7-Q2?)=Qj87 z&VPHNG29h5JT+!qs&CVAdw4fS?cvG(r0mzF%I4%9A4pl)oYcC>t{1wf0EFs)0Xdbp zmcAmp!S(Yq_`7gnuNPt=s*MCj*z66oEMn5T*)y&Wh322di`@9Q@YEOLi2JA+mnnKIbI^an<}m??`%y=3$-`sF z`%pXJ#mGR08DN25O8`=E&FBBlyUFLri%}^vv3gW|=~E3?4iIG(Pmkr|7OBmJQbo_m zhsY9b?W}jw0H_rUpK@d6b;oA zkYGnRjUC|&En!D5YezUu<-QyWJs$(P_C-?wp+_WlUI+UDYrAMpwH1c}mA0Q*AGnFwvM<*~#% z7iAIGS)#QO<2_AgEH6vud1+Ry^-i(rN#}5mmBZ;46{f1!US$3PG%;6W5#pDVO)_G> zsO=7F(_FAyqp&wfCg^oyM{(s|I!AG(>-1digw0E@KvOE^;q_}rV1Ag%n`so>OM7V}nDzOWiM^Wf=z;6`v8-K9 zdkLIf6pM3SmkgS>VrAJJG%*7-lBQ)$Uola-jVDVtv;o3={8W*Czf7Qie<6*cb@6jv z%R$d*HqF|d{t5-8deTG%-_vaZiWJZ@x)!qJ439%KI)JPlrNY}_JW*90YomjIhMoiti#H>V6e@Mp@owE$x1E&g4 zl>Rk{Y8R6vY7{=HJ_S?)yf-{VomP*0zmJ7XbirEtIJYM(>wO`QZbX{G={mj z%~r2T%rgPHi-joAPu|yMFfMwbVB{OjMSj$jD810Tu5g#)R@KJ%s-_-Yng6R(&5N*3r^t} z?|!XoPcN|U<`Y%yJDjv>Uo6&6beVc(|9}`d>(HW#x@v-PlaJFkG{`OVzSRG6U!U+v zI@wSrk7BMuf8?x=0oTFJ{E>B;9%KGnyzEZ#8s_$vL%cb?rI&ELR}FJp`jomq(2l~! z>rxG`Th=Fc^>!c?GtUmLNYb-cRAYkO*TiCjKA1Fdf|1v|h^q}`1dz+=NNmpo-UM*e z0fVQz@X3%uIl5bOfTP4XehvT+GV5P`A?X=Uj6x1SFm`{a{wY*zDcIKn&QeQXMMR;& zVrGj84o@;nhm$FJF3d$(JS)dt@mgz0ot-R2wa4Q;cUG(CGz}U(Z$M+vPtR1SL~Vyr zV6Kjd@J|lAhyW(v#Lq6~zX2*}(yv<7e-7zwL#=@Qyo*t}Fx%2UPw8A%^v`81QVz3_ z%(`Vp0xcbe(nZVjwZ8*)8$LVfp~fBA4GS;@^_4L^Tls*iOTJ0HK;A;IrtKENOXEg8 zTmVC)9+*)N3Kb7n9V3LI>4Y%U7Ok+MC@e<8thQ(W2!ojeJXaWb+17B^o8d0xb<3U} z3^rS}tO7ZzLZ)3`5gjc&Z5e$KJO=MUnix!5!Q^-Rsd3*h&JAU&nSX`3PzR-)aA~Jt zR$k|d@o~Q1SJTKPOL@C9q2Z*m_PUKUK_{kwKGD5Quk)fv?pi1`isUX#qy_G9Hx{^- zz^cu8=e2$Is4$1#5836g47tcDGS}|4APT%A)831p6;=PFwtE`Y---Bvr;#; zAm@yd&lAQc=ZqF__olqo#SvF;^R(baLO^3urQeA2>HA>Tbv4bNLs+2$nU|)k4 zIRgV{(88ziIR*MU_jZJ*URv8;-;- zNCCa5LLrxT3z@m4SXe?Z3exFP$;SHM8)MS7RsBxo>n-_8t*8w``667Kx*<*5Xr>*l zOviAEhdEgY0~e;jdD4L`q0sNMN>jaYSp{xS;%o83g*w;ZS{TD?m=CE}(;_*zMK_qX zGS6BVQ`4E2$VsPn&XX1{t($kH;8iUG(PQH+tQDl2IUYMX0Kk zdhBi1qpfS#J@6qcU=!NdQp!6?6^3~uFqquFTM@uoi3 z#6ki>|MD*FI+aMrz3X;y%UQ}pQaLgG?5d))S)1~ldi^@wt$w?awh`-$#csWDmOm&6 zvfhzDz2y(HGGAWirn~_{;WpC2lt2RId0m%g6)5YIhccL$ZALp$6?$Y`6GMCJxhyz> zm$`FYBHXB5aPx(6lM@q|1?g#?1lgq0{>=PnTpT0xC~rhyy^Q!K3=c5;f!{zo!Ea5U zvxqFziO%qg>?pxw$x|{J(ci9sP<%RTU+=u-+MKvU8N@Ti<1r!*nZ$&^H0%ChEN^m8 zg4)X4;O&E()xmf0(mT_yidXY9`hEFD6h+(CR!`%te62Rb2hCV=&ScF~pslVsJF4Bs zfs;S5iE5NvRH?Uyfr460?Tu#SAJ5X`(mpSf=eyY&dPd+dcU-p)5A_#3UMYmDkE=aSK$nW@ z{PK!2Z%~9PprVot1PRjEtg3L z%Qc>5u7TlviaqnH%5{h=;+zB|RMZZeQ#Hd?Q9II8RyA{aaz$;aTohY1b9OoJVyExc z@^M}d_!dcYF7qM}4W~9n0C4}0!0*DnbYoLxI}MtNZkMKhW=3w)Qr4_~#L0{D#@{H$SBWz%m> zte!QolDkLat7na!Q?37c5~^qA&8eQ(MZCC{pn6`{YOV&Wxw#xb__+BhtG(6yu!Hc& z!wND#0IgFcX*l{7$dc5AEN^5uX-~~35GpDweaPiXb z+}n3y=RPql>N}tJ(L8ecQFNky=}xHQ?_iAKCZz0Px!gZyb&y)~4q<_xc)X_|VO}Zd zvSTyHY+i~t_d!9Mvu`e^VrN#&wC-R$^X!+;_)|W2Fg|GB!5Ec{dUOwplqsF}?5OX4 zykE?dL7DbbtG`sH(FNw6L2|F;GTu>=<0m~~37B!}iT58v9zx_s{1L|MCyJK?@sB;z!!Ll`a^P(Dt1Py*y)f8 zTrn!wv5F_Eg2>RUKp)DS2J}x-U5eLy3&1pk&9jJ0RlDU0$Iv0KAbBD2W*gQ|Uqsz7BGiu827(3?<`$F^{G1ta(Gv0Jh zY}}aIn-fesw?^{^%NX}G^MX0=oP zA@e9dcZ_<6TSv5 z?ZDm3lYf^0G}1qDUbBSm;MNyJsatV zLmsCM{+#RZJVyQEegKRiq}%Z{^=6er@P)^kg_6Sjqy~-VoXb0xF}l3+o=>>+q7&8O zUT{eLi`-T@a{8RvCha|b9BkJWo%8A-T>AKl>Tf=9ZQ5JKdtV-*J@-np{_=6Fd2Bv5 zmv`Y~`&OB>H{fr%jzK)peC(;eqUVa=3Z7P;c#XHwEI2ZklR^mkKdCV!0Nt|U2eIPx zBowIx5pOJ8bX>Wl-lBgJE`9h!JVFsKHGFUHn6lZh2w5Na-t%p^sJUW&bNt1z!$x`! zY1wM{{**8Ob4-g1D|}-!^wlYoGevZvEv%e%=vcInQG~s~L&n&h0Fg231TI$amIyll zFfGSzkb6%Kvsy>qpx={$YRVq8-3a^Yk(5`8GT615%v1vjIh$#I-b5>{Jxin$wq@5G zrzlM$>f%HIZ(2$2Ouj0zs@-guv*q~8hzvFq2x?AM2eUw^+4G*(0~9;>>_TTqKtfOp zzXS|>H`h9S?CfG$$~ehaIV z3J%xT9d@wMA_|b0o@mEjiIiNcW;zk8Z!l7`O544MMGdA0g|K&<9s#1{&`1vcK>cAs zOM^nix0QPvpgyQ>8SMo;mHIUWG|xa-wmd9*y8l6}Q_A%wNz0u{EICJ)lNIAOd^roK{ zPg(hirXlS^+LH3Q9y7g(n;F;iHT_K(7FJe(lviXD)2mFJhs~)$2xrEZv3h!yjk6tM zhFNKxwW{uY`RsyW?hXyj!-4Cgs3_R`{|q|U$ZTSd1e>teb%Qm$^ue^O95+y4g%1-PsT(PAlGmgeUhmaz zXr%0d!Wmaj$)D`T2)vXr*_%DXJIf8$b(Qd}8Cls=BF%Hdv$Lia92qWcn^BmbKPBrL zHzUbka9uDt>nL3JC)}HrU*IjAG2Q2Nlel=D?w#famYufczCF;vfm)jm>~HZUYGkWf z!N!M0w3-?E>bXQnW{Y&q=a0=0$ZfAz`K9k3zv{7zwh+a{gI&v4>SfQvMi7(9bU?$!Xd#y4_!*~4+B=a*0}ql|gpR9Gp4z*$ zm>-ALQak*jNH{KVFaXjGx)K8i?JurV?FN5jggxAZoK*j5B)yCs4>ps@d@^tDM13ha z$$USCobi9~u?RzMv~c%FjxA^#fneh{ z?T=@hvHO}c*+m)dp|x-&_J&C-$Hd?UPUGqG&rMY(L_ozsh5&u);4P)r+aSVHqx{(^ ze|CYpLz(z&@73(xEu`Jnlb2QGY9eB};JC)S$9%-=kH44?kNyxrv@Y|E8t+^6-fgrz zxMPTV?Q@amw{7)P6Sa7>44}XnL~k7=jQLLzTez*>yI0+O8QYJ8BMDbWqQoy$llN__ z$=ky7S24?dj!H2|EwRb_PAtR3`wj<``O7ADgHOGO@fVe-&BheLwhPOq5(Yu< zekPdT13}Bp@p4<53sejc)li4IRXp7Kq<~;NrcLIBAIT1ny>G{wEZDe5n@))}*39e$FVG0O2k79utLWt70cV5(UJ>2x`yTi!SdB)a1{ zC)HOrnaWS4jXw3+fUd5?Er!oXi9`V~Q@u@iX!qf_0UQaSq|QvN^9>H|(0nx5xLaFY zQ>K`rH!`X?o>P;X(bo=nk&s~HXl$b-T_$(j8N9&0s92M_pZJ;^aG53_ztF%DJVIMX z!rx-xdu#Xw(eM%e_`MGef83h(7Z{_K>D$;DhcPzgrQqXKFS;KG=m>5oJXZa}PAvRT zCw<^wEc~#@Egg9PP682|b>v(1$Kq@8)baDjj>*?P z(yXhn^rw;PX}+dwcPZ#_tMss4>P}LGTW`~)3SWyJ1MT*B39DrgkUIvLi6M++&{=QW z+8iKNgu4Y68}twU)Zp;?sV)u;XA6u2LrG6(rX_8P_l}~cqtDgK5YJ3ed;d*|T%zVZ z;8QK9AH^Q#lBX%#lLDtm#+REC3o@`n?$lX{1LN{`3b@GofD`>^8PPCnyh@vzmDE z6Tgmo6f%NzEyW(2#%I_xjv$yA6G-4%lthlz(7&R4bNg5G4^%}_^q#cx8Ahb(s^JHy zBbt*RPL~GQniGA*;7(20Vl#IZM}EcP19NOleM?Qa2xT{m4(~FV-bIU4hw1L_>W^Y7 zm`G%!}A#$oAl^1 z*k1Iok$YF*^+%17%b@pAn8_h=Vobo(jDI3<_Fg%_(_?*px@;5r7l}Q0@XWPfC}K%7-6jpR{HYrmRN2^VCY&Y>g_$~;nN>dv_o zlkQ)n(?-8jS-^_9Xgl77xD-k${hOlp@mrrK?GqDA+l2Jfd)+~MkUNSQv|>B2{p@ml zfq5E3J7YzgTsNTlTBtd!enbIv16Iffq`gv#%TJ#Xnw2%R!^gn@pDLEV*EYK1B46JFXj!sQ5*>l2VKJ+d+l9^14Ou+hO%xXA z5Mmm~5pH)YH+qJy+@S=bIRqtZ33UatvMK53^r={dLVP3Kz$OXQS*6E`V|ci@`5YD6 z8HXz$v4F0-4S`7C0jlrSNQqR}9N91yA-0UAn*yTBOlcmWutmmlthuyE7IZ`UFhp{u znvaVTX=@G?l0c|)?!cVjtQ#;kU*q@3WL)NC{V|k8$A#H#7n(e>F6Ac4Jd#YZEAxiX zp4;PL(GAegM|nwB&Y?VCwSQm%9AhPn%ct5vi9T`@%SE_heGzNa_%KxImbI=x zqo_*C!f!a3g%6pVA$~$3nQv&su5x2D&|F-mR`l)Q>4+wh0e4XymPATgLLT| zM8t#Y3YH1(`Tur0_TSx(2SKGw8oM26(a%2i= zg-OaYM`S%YJ|iFIJ;i-D0wh9f)yv#Lt^%FB5dn{y*(Wwqb z;C0sprTs zHdEd;ku8n#?Sd5sIXbN$eFBEIZ8H>Z8+nExI+%t z4Zj>lzLB}hrJJWnBZskmgA^HVolBHI&G8(5V^~_o!y{&AS>wb0YY&BS zC2SabN^luBM<=KyRQ^ynR&IS#H-qCt;duWb-m7_+Idd`7{^U{dRdLlXc@Bj=8twt& zde8CH%<;&XWIp&O`d-eq*!o^M+rpSR#u*doL(U5aG)@D-$N&qu3Uoxsa9No&|- zH3f}}ft7K^iBgs#DY6uqiqvQ#4iQ0ll6Q*g#S+PPEjuq&xDyF zv1^G{>2A5p04a;rlyRrdQec(}432iX4(~P@%@(K_4OOV27;BV$2wkH8bh`ULQ52PC zvXL=Ne7uhT$`GT@pp&C4S{I<>Jv#ny6oKxI#A|>1V@DxL4Y`yW{qAj9BT1XZ4}Z%@ z!s8_TejU!3Gj#POVpfE%_KJ&u{jx(2*)-7iE-l4eZ)oY;2tVQ00c4_S$;~I5_((qO zlFu4DpT*JnOtJGhUFY*M&K$buQ`aq@QGX+!0z044(fRz)&gUg~A@{!>mCw7~^2wF@ zBuYN|vYItAUj97>Y^)%m+r|&U#BluI3DCz{M@C<>W1FD$NOFq-eG_clC7k%P`lScq(|=`AUuLNh zNc**3#oJl>ZND_enWrzG);u2|sjkUqlLlAmxe*ed=BLY%i77LCCuYklmz5Pyo~^*L(vzECKYtGpp${pWsY~l5Lc2@4UgV0c;74)(9{i0D^bYOZEHm00 z`{ab{l*1pzZ9n|lIonq@a06vS&+Q#?rcd_LC(iYNp#Vp=Qk%SoW7dv+H`fY|i#2yS zOt^7W(#mz@H6bt}Y2`0@Fsb)Ry~#fHhDNPE=+bkJ)0LP3{+&RIZX?V|Oz2A{R73oLcTFTx0|x`#CB@K`%z;jz zsL~N}xt2gg@Dc^_5Ar~qSI_8t_m?s#`C6dA_LVkSH9Bb|^P^F^R%(%Fl>q3Jdo<7z zfQ05|sTulhA8#Jsf=d72ha?z-5T*|Bxk#njA>sq0naY08YVuHtOu zyG@hg?0YdthY%=-?c237abia3N^ZMYcJ3A#10v(p$Jf-SOsP*9ST{Si=K9#W*)cWO z$JALhv02jt?;#2;A1B;$=?Gr8%G=1~`ji=bgs4YmeSD8GFR1Ul2ycwfXx7U|kuGh% zw#RI9)idnX#hmezMd-ASDT~Jtf?Savhac4Vx}=@km8UkoZps~>wGGa{f7n?_8l9?eEZ=ROg(67ox$SIVyy$IF+za7D?3o&0Xeq+x1j)7OxKnnJh0 zP=&@{p6k$fndpCfYH1fW;!>I9r2Fawt1Bh7ugoL;Li9sKFMl=_dAXsX!3s>RUn%cC zSZp|`goc3m9xzFpbn*2oR_@d3dj{KjLZHOnKy3ZWG?S{Vrw*G;Sld~VG9qwpg3QlXY6Z8IbC2n+`5*@rS0RWyDFeR=4Bcw9v4fRxhp0PCl%vJkcUlHsAX2ZdX`*69qhrx zGZ{l*_&QLp5m{23n-NR=FNn{_K8l=AFR7iH5gXbe+a=ro9;@DO1T45DBi8bd)W6Bx zE!e0&h3_IA_DkASkU=9d;?)9JS*X#czF-1p95pR(jAz;xLKV4h=B#TS*G{$ZIG6Qb zR!|n7ua;0G!oc}@$$U=zq?ifu8B61Um?`6iM(3-!(g^L0t&fy|uQfYQJ+F)JN9Vry zvOa1JgS*zdzbsMRuiq4X`&y}oQIWK1Mn66^xj1k+s>fyHOI#?58f$ z`Z(3{)ekB!^GB&4Z&mhhu8jQTnaTYmkk zue;QIHbKx|${3kb5b?{{jlSxMm1-qi$)cw=1e+Kzfo&()X<#CeBUL!|He*+hFxvm;F3e6 z+JB_ccC}M=yX7GDlQDL+WnUh}I48iJ-OZr@>6#DMH9!1{)ZC4|QpbuHE_JEq!EZ^t zxU~^6!rr&PPxq(opq9M0@52OC=0{bC6Ak(U6VY1*gO}12tEhIk{D>26RBrUHoK1%e z9)zB2y)BS|j59MKuZ50ky?cU7_lSh{j;Q46&%q^5f0ltynCOdN%9trj)F03CQIhlo z>*9FR zJ%v-~*;!*6(9^sgy0M+X^G0marllWFcq%c|9X{ z>l?fbt_a%}n(PVPxLb^9JM}T}`e}{zg*#b%i=VlA?|oVbW?aAa1+3QlsQ%o^e9C9& z#??tr-1tD!ChrdEI5j*=KZ$n%d`I^aE{S?J1yZchBry{lDPWHgA zxX))napXUk3=u;c7&c_zN3xffw`FxN@vreRb5@=AXSc&lxo{CcdmekG*q zUvjuSBN^Xa{RmBrv9yD*vy(RE_hZFvcx1M0X6(cj$xp}Z7`Y?qiJi4qrvw`dqWNzN zS~6NzU)U0w=1~mMu9A@VLq?0|w$n^a4|!Fbe_${!vF$W>S+IRyEIg<-4w9_x;W#s5 z*!-6CW^Ew8hC+WujV~9VO!J^>c}g#nm}h}ofZ46hm_DBG@KYu|R%q~FSmz#Wp!N0< z@2hzi$DF8yX$qqgDkJ!>y&UV#_9ua8TsQ#s2_X)fGP`~aKAskiDG{sgC1>Q^nGW5#uuD?%$ zcByFuX?-oXj&jMuz&K$u?eL)b!ritHK;bLGJ6qtH&EB_TaKrfK7HK?sN{I>u_Jx}2 zeDO7f>+5`;n!?9RU{~;6U%!&t!atC$ljp`}?`CY9Nxy!JV2kwlgn~L4w=oReLSeE_ zriFWDQm{+Fzw$JUXk>zj7}|UWO0)}$ed?>N!af+>dsVxB1;0vtpkLcTf_j@*{6Frb z_u*sqM)F{K1swR)SS}$0KRz{*mvHNUxIQX!$BldDq7qq3+sTQqool!AVYbZwNO;t~ zopauzi3uMW9-lzn>_d@zAZBqeubm-XZr($)(`eoRITWLQ44YuPJXK=g>*6{%eDy|{M7_Dou;w$l;znrmHD z?K@5FeQx*WZd~Cic4S7lyYruexkl$ zSoTUZMtsKBkZ+d!3_Q0gmqn^FrXqrGyD9~4RmKwu$*4L#b?$}YaRV!sISsNt81Eb4 z?_J{?fb}HkPY%1~7R(73k+L5?Avm0vS5diOu3tvJNV0O(vTSSp>!>YT9BO#-b{~d`+#%$M;P;pQ!?q zWy2&I81c0QOfqNobXk)H=1dzV)xbOrjN2)%Qoihr)Wg=ot&_siDK<|!izapFNpu!s zdsmn20p7l##Cfh*VyR@Rd~el+z`j{+?8_~N&{}DOVrJ8 zd@auBl;cNi-%X-%UDlI*$a+#c_rIIF&%{6DK}T^Y1HFx=6?JJzS7*0bx>$9vl81cX z)pKK~nu7Bym_6%o^%?9L_E#GxP5`-t^nLxESj&FDI1T*)g}W&FjJ(B{U>Pv*e>kh- zOOUBw#*w*um4=FsWx3MG`11K)rCTR_`2@eRmV6Ul+^nv;nQDx#e-QZ(_OF_mR?LSu z86N(ER7_5(se6z!{F1OM&@7&d>=|b{*$U)4C||;@4>E^HkGX587NSq|PvXU%{bXkf z%d4`i(+YCR=P$aYVs2%T8Fy78%Q__gYv@`?9)_yj#obLqYV+cq&no@t3H24iFWDNW z_pvG13Fs#Q*XsZw*AkrW6EH;r%$)cT`FE#3qeoEncEMaitgfIG@mqN*zqTpa9HNcR zfxZ!a4RYk$#)=PK9ePbYd86=7JwfcHm4 z3iAi7i*2Hy>VNp#s(GC|PHq31)*U92*> zBsRWw4n{yFTR9(iuciY6I9ge%+u0)eQf_#@Py&m6KMVqCBVm8kpi3VKi4 zhj3PYDZT#%2m{xN8rNzlv2DX$$!)KR>_gE_3VkF#*7fV7x9Cjdo?!f)_m&e6_&HBR zm=y=5a{eJ%+j+!MKW?Y+vCIlJ3zTH7aec?8v!Pd@@9HKnUhzSLWL%baeJ{3g2jK~JWWMn~cDCFvn>S@kq% zJcF^T=F9k|ALbGg3Uqd(rf-5Cm`sG4M(BVDHCcQ+xtBgp(Nt4C0hbK7&ZpNL)-CkB zypbVn7Gnh&nUu&qaNlH+iQ+Re)cE9;YR{A8CATb!rMqr4K5hk01jOZynM~S3xLTHC zNhtz(Xi*x}ISbPtKAY?g_dq6e_%#ytu7(q-k?YM6ag7YVNQ^OtXg9zE^kr<4I7(ng z;Kj8x+a4mx>$AcSLQnP`xWeNiGJEOf+eFUl@Re?)^@ZvtXhy#Wdv&h>-v@tj(k#WBv&CCv%dz!_FX-m#XF_ zF^AYiXVH9nUdS^=!%u{lnN`VY(nm5usUkX_J}Tq7?i?{@^@J9us6pgJ$0P&gORddM z#e%dZC#~&t_`F{d{oqefV@_&QP8wDYscJt5&di!6gVhZOqy>u^XaSssLC!$oDAJx} z`x5Av=NJnh*?YpT_kmj6*u!Rncc!wlU}peYKBg8!%g~NBtD$?@AW{FuMk}QFOxB-I z%O^T>_OI$O^VO^F&mX&KPS@0oM4n`=_@{~}2*tANop&S;IXfV&E9)vGtXYT2S%Y9> ziWaw41sA7cjMWh4j?XowP608=dJwt~eLEF4lxhV=qEQh&M<^$~ZA?K~kx%^$o8|B1 zW)u|p&@uVYxFq}3x%(Mh()zm}bhWj&UEC>wUVbt&qB=TJcDEszrS;`GLZ7(?oobI%BA(In2I z;81?5DE*09oDyp8zE{z`y^l%mN4Gc4Ztw5NjQ09;d#BQ}M4!40bM_Va?$|YR*6}0AD&?Cbi>K1;kOUR0@%V?=f5;rRZTTSez0)3qFuNPKm z>+o002>TMQ(4=I4xV~`pmLf^otcq#P@}&*w-f4MUx|8%bm;_3tTYoD{_Ri3pRGBb# zEp;X!#Nc|bNvpp7I~p==XRx)1(BO_DGD{^hSQ-in(HBdf;+w$3&7BGADTW1FO?{Yt z^GNRok?g(OMtV1LA%^f4cZzs}!a``fnSs7oC$mHjv(Axw5@I`Ii}vgUs0Wxf>I>i9 zB8n(ssp30z`Ouls>`x8BH8TMS=@D25Nl*1)#JHRq19PTo!5O zLAketoOD0nOCLp430HlUXls%lsLT%BY@uX7;L}4W>3Oe8dcJV~$Q?elYoAPriQOVU zBJx9td_qTJQ~!#rjzt@Y=gwL*kNkPN-unuwP?Qr|!K1!*b=^()PZzzgUY(f%v9LY2wqpSv~M6Cs%I5;i|plxdRxMJmy-ip2!Q~)?YBC=-Vzu{)WV~?&%^~ zl=4sbmcM_sI12Bn-a=7;@lXMaRx{_w;D-Ba?j`K3sgs(3b4eAr1U({~`w6v+(%Y_t zoy|}$fkPPCR3Bq}b`e_H>t#8;n}o9S)OLp9XS!czs&6@QFglB&&XCaaO}7FIO@ZQp zBz?l7WdA_&I$uV1PHHU&Je?Whm}v(`(x%}8MW_9kvUFN41?kzvq&;?f-~8&B?M<`W z`;IgrH)FE27al%SmAz}Xm(j+pM%~(bjT2W$TvU76?^wfp9#&T@ps;pcQh6EK9{jp! z*;!o6qPc-q-Nwsi)Ydg5hp`};CJIP0yTLJm-piL{jL@9Io8GTIkAI-|Cq}OD$#Y zG?^%kmGd?os@J3Ps_ipAx!W0&hHs+Sl?F4d?)@7G)21Vg(+SkV9ew{MjUM@(>a9m) z?46BR-1f0q`Wl@vc3cjHC#@I-DZ>QW&Jg~n{sgyR_H6cQ{-|#Xq2FXP0G`$s&;IEF z!_B;kpcf>BitD=LEA>KE^9|?oKe?JVi*83SdE-yi^_D;~{D%&%JXHy*$6Ha{zDW)J4y5WJsy`ntqRt{e8&Q9tlyGYY z_kTt0Fn&woVYgKJGHr<5qT|i(x9&@sH$}I#+N{Jrb1PWZPl`Btw@6MN9y zmk9E%R_T9{(WCx@jRA9ukora73R184uJM%>A)EVD{9b|8Gav--Z5Zj@%n&GP&SQ$y z^6PP?b+>h2P#Gp;H4n}kZaq_~ZW{oy+hx|A49hP>MUaYgHn^lY78MUp<*_rM8>9}a z-=jz5VYy5nP-_>Zpk?}QIR$tqVneiSO zYLGH|b`O+llv6~M7fEOTVyz$jjN0gP6-Jf!L`bZIfipSSVJ*2%WEV(+v9@5UfNF>9 z{a=+$0sk183$Kbwc2JFGgt&OUmMEE3uLL~Y`ezPmax!?DTy54B_?-)N2T-OmAu7ZC zCvcyL*@WQ(#>bJkUiX(8xUT6?L%X<}YS)EpcT;nWBJy0VQrLbq5WWJgB1sO-NDa;K zOepL`bh;meYpvtkZs~{J();Sthw9R`x&w-J7I6@)UDCitVLE3}uCr{r<^^}z_5&c8&KMup<{K@ZUjMGRN5GNV=DoxaWOuUzB5+S8 zhB9ZfhU<%DBZ@npdhV}6{k-2ma8j8VfSQQM?TFd9XD3W$(F^%%Rtw;$>UHnGcumw8 z@1hie`{B#d3xn26Z;94N_@L`&D!90SJ*nMx1$VqC=?hE$0X5n>YAL)xoreDqU5^4L zA2Hn+E9wXnS4J^N!_>vPfefN8Jlf6EK(1f;4wZ z^O6Qdf0iHw%SSpNA2=UK%?1Pyb}L?WLhdPSuH9`mMmy!O~s>n!}Dvqd{L#>eDlDS@_ zq)&E#j89?$=OPMeTYZjjqV(XB4`BpnN?v;z0ApgA*D+v89L4D4cbj)i;c7p3B=#aQs@GSaAAE%(|%8&>RH-^q!nDc%DQd1=&$q% z-s-@&c-2U~ZLE`3i|PHN+t4BfjD)+WbNSPHI!i=%%2RYPHC6jp%jmo4*TVh8@ath} zV1_I0z7-^>?-K%Qg~ius%9L$L`MN#oOKjiX(Y-cAswHb~(qBw^V)XmxR7O%2x~YOo zWe`23yAi!_ikjUZDj{jO$5+2n1}*oUCWfXkcX1&{|MAGFcBo{23!S1B#=xhjqCe@h zgvaWh(;2?>Jex~bxiRZxzto^FCU7%vqI&a#YJhbnLjlFEM+c;^FH7n~9ki!jPMpL_ z(D--i~p#bPi&lSq;CE$bcO0_H%8Lw z(-Eec`^Z?M`pC+^fIY4*Ke4O}I~?-7m6Wi5-U@kBOGG4blo#Ki9XcwO28LVrvxJH= ziM@eXO%@0xA?%1W{!+;#+`3gD|KaAdOy^?{xKDIms|BLXfoMx@y=$#>AjZ4Dri$ui zqE#C6r~^^@uFiuVx{Y`lW3b!bLniug5w1oPHB%=2hs1|l$4UOLk|83yv2+t%yEz)b z3gr-UVIF)vK0{k_|B*Dzz+<%~_eCY*Oo4L)Xr;x*yayU+xU6H+{e57yPFn541X#qs z<&7SgtkGNOwU9oIVc!Le+_&wbQd_bi~kn1N!&JGbRebg(}BGFh8JT7`4%xIt=C2B=O)=d+ls88s(vA_sH5a$LTX*!0A6ac z2ZZu6bVx>B-UuBsqV4Q@?>ba1;{Q=i{;?R6u7i}uykM3yTag6a4tSO#O(kx}v?Sbm z-7i7)CsLr^Q@x?r6 zM&o%1enQyjob-?^EM5Ab)7%M{%DEXdtbvZU-k|#T2!{ZPVRsUv#F|2P9K=hDSTd^^aPu)7*XGql(cE) z1xcH(8IknFYZG=Xu~nfc7RG7sBX*h(AS-?5L`%7YD8j_bxRF7nc6vCr(!I;H{XLskx2PtqS)GREk-DIE9Mo@g&d4p1#ne#F3NYG0{+(?IN#h zo|OkxiF*9n$*t|&-QJ{r$@*1RyHzO@syzNP^?F~u*{lx>B&a)f=y}fE zODAsWU>4d9Qx7exafT?&jh~EB*$dQ{pI!_)e{zc zq#edLRA@FmgXCDO&qCa!-X-tgoiqsds5mDq(AtI{e&xf`;HAmD{aC-HAfn&L zTgaO-!RuiKwyF)yduZCX?Bm^`oifp+s5_c9O$FqB^P3p#m&#!G3xB{5{Q@g+URmNy zwTOChvZ~)qRl*wwhS;@)wH1yy{LzFKINLjI_{^!faRDdod(Bk8YZTUyJd@md!X>0u zvPYO66R`zl&J}g}I?jpcBi0#f9Dak=BQ}6v_W;`Rbw*o0aHGr<>(pn@QmZBv1U2T= zg`PVTe;_P#y_PK%B?p&s9u@M%IjIE82^6u&ijl*Cd8tjA<+5$=&YLxP1CiadrAo3h zHIdiW}jb5nZ^7`_h>m-+b?p! zhRM(obW(q)ClukZFS#v-`C#`Zf7wH1;lhS%d;RxP?YWuoxtLVTGbyjcl$A}H-m{ExWX5=pf&5rwgq?J!03N18{S*rRQ zUrvst-vHL6j>U48^$#+N7CM?ThsjPF`?r|U%DUp1HVK%+h>1iVGpyeAGJ3mms9UDw zf0?t-(o1{l3-@WW7iky!h+I&+FA+~d?^Q2-&+_9$cArtw>u63HF(@d!^YzXd%-y&P*PNtz7cZJ-uSbx0_RE446M$8NOX_Ct%uq9yU9z{su zi~RNrev;TWh?6p6K~bp4&dF&cCtk?RyHCzQsW^VU`?07=jKOB0^cj(4_KgT!$aYyj ztxv(N0?L##vGt1!3D0pYO6`ZEa3^=<4*OrfPyd7`K_eUiTA;IQ$V?vv*=<)BW^UF1f%xx}E+C<)ln#zl~#v z8b{FEe)VUDIfFEtQKOc_Uu8EAbRK@#K_?4aW*L-n{{F#^SbtwzFi%<`yWY}yB682W zSGwbXq`WDTk^?!fNQEzy3d?#&+ujb*rL-IU9)YtO#8Z{5IQ{~Ovi{*)^4+aVPG8w@ z+Xb|v5Wz(4W&(v;M02pmB>5dlG$_dz+7v#hn{5`a-$N=^Evv!4snF<~5lnND=Ht8m56L|-z zEz=?c741P5Y$b#WPL-0a`T>QiclqPC=4*10KA^8}qp!oQsZy_x!7+1nKhJH$coW_5 zZG-g@+tUU4T+X7=ejSoBXm|6P#8?BdYUN7F=+*nlsJ(urjB95xb7w6KS%+w)1l78h zYS|%m-uGb1dqNyKM1I|a)v3r`E;~MI8DmReX1){KgnwycW_*3K*k;PgKpD}`DLF<; z=9`Al3Jd2ZGPGu5YJ~1PE8l!b9C-g$E1Y7%YwRl+Tx*a4}XlYK~3fdV7DaAL7IKmZTN^MFv}z8obK`zX;w1*BDa$71kOIxJjd157NBmNu!0? zwkrOtcqdR2nj{-Qy(Ube`Fo`KO)5e5s+-g@^AjZN;9azK1fVFrXQhNH5m;-jA&dG+h|JTILqImE@_*4i0oD+dk}zRXN}!U!N63?(G)kB` ztN!*>>>@q(WO&mY>YAHD6XIi%9tb0DBv2l!(MicF4Jj<73K(QBhh`;H9rgByvflS6 z)K2oWB^N|h=0+;x&ib5+)p7|q6O?IFc{)7ZKaS2mkGc@v)V&h5)QBg&AaqT#c)Db5 zg5Ia=#eo5Z(9|?2DV#vn-pBF3B{PX&@}RIIWO7 zSKc`M%Q0Z5{AP8Il>b&pD@&3i<#(s!oYV=6lap3FDIM94vE2Yor%B=jZP0^4WkRWU z(3-QU3qKdQRa&~v?EsrPwO|^0Ro(W1OTmH1qA9p8uiS?hM!oL;7%aLpoZ5Q7Ouw?y z-?A0@-S>U|Tr6arlUhF+c|L_x3WN5G72CiV7pF(?fk;24>3+Hkt;^BaqmSZw(i}X6 z)mO5Dat2ETPfx}u#)h2dm{qvEu?5A3eSo=1t^J&jg{dG1%O0-`hb*``{sJ*JPgH+m zQmS5BZuy6yHTB4z2xq9j#gy;4J=r}njVG8GV$q>`f(`v*;xi!1evZviv$}UOV`yRq z^7@ac1pF%zekS}%U9tju8Zu7Io)*Hi2+n5b!RtVV$ZHHAymhW)Y536ws_9LU6|q(% z+#{%cd?SG^mPI^BE+ekSl7VrN76Y?0UfL$vTefJUBcZ&M|!&ya2; zQN1@+ed8ZgTHyWc6ZybOj|s%E9O7@S*Qar!{kBW#>VeHRnx@x#N7JA)45oY-5fx;d z#ZD-9c@<=&OIwG@5-gL`!?_t5f?|hr&z%I@Eyy^-$WP7cTE5#RL_=ID5QU?+2nS<8 zjph?G%x`&a8*s>*8Rt)`FP!ZpP9cs#u=b+nz)I*qwbrcTSJDmT&BKMnB* zpBWK_nVvJ%VCE;Ym!GI!fSw#>=;OTG+w>nIz}fr?-GSbxXHUNX5~0pH9&Hog>T>4; z?CNs&LjFyY2E?$wIXDg~947_XiriK2QE8*LttZWqYFjz`wAAF)E-KVw0k;*k-iuvD z?NyPwF&ne+Lg~tV9pqD?96uOqG zy9=?a@Q|r5vdPobx9xNg_=PAjc4H_>;8QF~+&N%S>-Uk5CHOLmQh$R+)hI*In0-We zeWcFV{X%5Ac5f_qYj^SbsM>|HWj#(m^Lzcs-7+{lU8hMQ-z9`)1Oc2TYf?YsGrGQY ze8aXoKyPeif@+g)pN3_Q-S<(oZh_t;!)mIa&XZc-Cd12_Q0$6pn>u~&P49v^gJVdf z-m4?^=D6A-7Gs^Yi#gC{Rv(CY6?Q>`q@d>*1FEkSMA6^eOYN{{y;OeXtXnFjifs?{ z2ByQRx{C;>M#f&o_{kjhxPvS?%)DL>7;nScQMU)>lT&)>`M}A^;xSCq;nt7oDDB_U zwmC6*Ej&7}MRs0eqw@;bdHoZ{g#RliFJpB|WpCAnK&heGq5*p`lbY`|hwCb{v@(@( z1Px%FE`0GH-3sk|n+ANf)->Sx-$ymzBfHQ_UFaxXC@4aC6Upo1KSU!#=ks=~r@@dnS2L|_O_K3Z!bbHY zvUg(3gu%w0e~JO@MbT@?ftd4*JJp$LH@PsECKYgBlzEM>yCGw&Xwsg28sKoSaU7gl zc38_M8+-0DkGgxq*W9=ANU~hrG!YMs)pGh~y!w$40=nQ))qxA2OM4>AdS0&0u}>Je z$$P1sNb;I92Ld7t(Xx{6F2B1n{qBljesE^+mf$su$>Bu*Bt9L0lbug)04}M(H`nhk zu3Ttec^WxK+Z%!xHm|QKUH$|g=J*(AhN7ns$Ir%0^-Vhg<67@Bi@ECge{knE$^i zc18o2nPcozZWB(`5n9?|C+~?)RhRmBh+&3VRX!CsR5ZUU7^^_}M1=NH4 zAJKS<4NHfNbcVWJXJyMBZ^K~po@L$pB8zuO#eedoQ}L}HiXyFS3T8%sj3rS0;GfV) zhhDp>pFhO=q?FJbD)0;5NW!u_9as5iQOpOv^0mRr+(E)X^aBTkfB`X`HS>b3q2~yGQJsqAZl_9R!jb03{n2SYY7gfY zRww_`-oy&@ArawP6Ukn%dyxK>WvF`OPE+_Je)*Md$LxKz6wA2N*78@}$6!Y0hvu4o zV3fem@f+H`RwAxbzZI^Q84ul!Y2c6UFR9ige{!nTl`s~_q?Ka0s1vCRDb*asJxAW; zc)1$Pn;P{74!pHJYj26rmy=rZrZ4L{^gZ76WjY7sOs#1}~H*#3Tjf z6pKDTY_!F@+=6!SR@PH}hdMkW&dJLX)J^g(&dJOAs(g7D&*Y`nUD{^$mL~}i=|ZKk z0xQ`vN<71i8;@LR-3tem_Lkr~$O&w_hd^n1bl{s3C|Ce$6r4t_C96lITL{>;jh6b) zCP47%1k95FLF<;Z>?~{RDE_Q%7)jFa55|ZzBbTtT{8_6;5%xX8u%jK`a)|p}8iH3m zKsqaMVd>(HL|*$l8XzHdxPL%t4dH7g$fqVq>}p=a*1U=Z^ZeywzHw1ec{$j#rYxNA zIjpkiT8#X^5&MR}EXv4k_HJ4GZYD6A`Zg=D~ql>Dv%@&;wv`^tw}hBWB;rEB;e zUAL~`yY1gy_U}&nx6%G>uz$Dd-x+LttM`QAaL4TM&34>I`*(x=yWaj?Xa7EG|2}O0 zuCaet+rJOkzpL!u`|RHu`*(%?TdjW?*D_9?dMYwbR?$kA2DcG`|F>lk8kFc5V`FYs zVWPibZ2uaWNwT{4X(uc3#8DTn-rOh%4BQsHqCsB#)6jEWQhmiP9Xevm!@!3IY~*W0 zym}05JR5QqGY$aG5AqzWq*IlRsI22@miIl_W;}avd`O# zy}JaQQnC){=n7yeG=Nd5k9p8`eV-_G$iJh?U%X&ivA=TuyegqfsRzrkrHQ&SO_XH? z&e^h2SLRW^HpFUwW{=4GENUaapywN74uzW6#rZFgHOI0HHchN$XO&r|wiDu(^)HLD z-*e)ZB|MjHjqR@;r0APJq&^}}*$Bz2tXMFkc%EPC!sU2y<{J~SYN@{B&$>2eZ^_*( zsCigw6QkaNBR?YV`7^t8SleZX!f|XkOBrn!%v8T#uO%LpS6|VrYcpcY9$lMtQkyt6O==_WGrIzbT>($m z0QtalY>dpLAZVmmkS-bSqQ>h%ZM!tlS`xvKH*s0QGa5tUO<+f&CHN8NIZ^fTRm@-L zC&=KaUAl}rN|u787j(7G*|KhnAZfi+D?vToNwwsC=BzFqMvcBZ=AGqTQcU1h1l4)L zZ;hy&BfA;m3$$#sN`hLLG_MxjA&iKVOHQ5HuXcJ9wc^bBWhwQ6c3b$I)0~I7H6-_~ zsg?aoH&ciDyb<^}|Mk~ha`lRtl#9y_&m&9aW$uAO$fW8pyx`I3{q(pJLiB zBz|Bd{&Eu^PYkrN|sq9@CSdcrvYEk*zJM1A`g=F+B zV#Swh5gcTmX-*KfzJaNuIYF3NBMi4WL73|}{U%&wHjJh@K}NCCZ$j@4jIibep^(+k zWOIVxauK~4F3k7NKnls7I#u%sEu&JRQ9gDhYy-}nd&d!h{Kt~Uk^dw*hI5uPX@NeM zBk8{zm40`0`o%i^Ls97^Iwp*>ReV;v>7R^Bzb88VW}SXcRCCwu0dq)UsOcNzGDFjx4s{Uv|T`T9>FU-{}efblQd}GAyzTQ z#(dq^H9#V|3urg)NY*^-ibS0T!$ExTO(s*bM9 zF~W{W@7CKX4;e?s-CU6A@Cyqfa`{Cm5#iQ9R7S>(L<_(8maMy1?Ib?>-^Lx0?-jg1 z#M2H{cU+Qfm7kMk?Y=nE+QZYrv;LuM%XeX>Rm5}O-fS!Nm27Lp?b-Sa@$9>^t@i5) ztI4(|-a0)JRQ$xTf1gwTf2GE zRuIoKg1ipQ%eFFjYD%)Lsm0{K1~}qYHBjdEY-`*$!gxPG-lg@~*1pxGZO^hE{s}Dq z$JB%G{k)H+jJ?!%9kT5j(#-}Y-s-WT|AyoZ3D(rls4350o(`U*f}B8=zhc3p%8J0E z?25&q2EkF!BZCEzsbjLaV9=BAFUs*(mLsEw8b*X8_!K-JJmPyl-|gUc3CaI&#&55J z2>t{IJtF~vq79(*k_hHTSk*(at*e=q$9_B80zLAtTK@F160*wY-?}g{J=?mOczKec z4gOVQU~TobdS)%0S6We7HT&sIYdWzk?Z4gwwFrbfeJoG*{M`A|DvF95hGtuvi?Z=v z#qaV6NTSs20m=6>Z2>Wfa@Ng* zo!)JzN9r`x>N#_M)qLiwgOGYWdB`))hLGB(TRo>Q#0TlT?+65D)m`#Lx94oD_w;j06?B-pmVKW(-(Rd7RmS!m`>v5iH14PfuZVxfYsDSo@kg6 zf+Fuic0mNBfTE%U}l2;=T@Z!6Ag2b z`h6@a9JK*$pfb#Vj=G_9xO_R&6hqM=4xp6Lq<7fMFVe=lTNaeWF3iWmE* z&b^}|;Mb6`P}~M$68z-_6^lIn@*GBbaV0O=6@KQ=P{Y_4vw(^G>x}x|$-CmoAg{fn zk0EQ^7Lhe--hc!lb4S*&4l!dN&a!S`9ype)k@$I*k1v+{DP7!*lDY z$r=v?jI6O}J~9K(F6O0bemf6lS&PZPlR6|={WtX6&|||ZT`zZaP@m+EENc``DslG# zlW0p4Q|I1NTwb4PN&9i4a0KD}m z&=^@I?doZNNSiyr#;6D;GL9=0cx<5{<>^c-4a!v@9DK;XYWdU4>ZOH-1yJP41qb1` zXOhdRBc?9|hpd3VBA>O#@nnm{lgk!;PbypVJBe(O)J?WHo?wuCDuTgjCl?HC+2KTj z!RfAGu!@nJ3hFYT{-_S9PO%d6D&_^M?0uF0dHLa3l0oXJNCtyXRWdl^2+1HFG>nTv zgP>!G)mJ2gtaqBSF|=#_@y$ zBS8RkBH>`TGx485IB*3B@;cs(eV#iPpJ>J&;X<8g#ywm;Ie0QfFN5~W$(!3Mu#x~k6Z{yH}-ND0{%B5eIk7| zdr$Z8seDTxtswg&<$(WJ`Y1sUgHVIurlKXIkhUiZY0^=tR^Q3d2qPy_ph#|KxvCLSQc0OblzF5AWvB~vA_YqNsfbBuJ2i7OA0sI9UzEA# zh;|OM5`A;4s&0p@g=mkbXF2BxY3ehw%77I|A>PWcJTr>t7ENDReuuR1SgM%e4Ed9& zV$MCWDn<&7aNuZ#VN_MB&$HrXH7wOQmZk5hx=Q&VC1(uwMb@Y`0XfX`v?&-OzXlx`4>u^Qwdb zq!FHZRr&K5EGjSV7YUPVx{~KrO}~9%aV5Ir+wIvaqOlanC8JhHfpcOpX`hp@af$LX?0^>n~0! zaLd%+b-Wey2$C+eUuf{=FOduK8P*^%2k1 z%0+%V__csdhP|d(@$7>2Lc$%nZPd1y*pX;pE@V?-bJwP>XSyCBr_DT*dn57k zRP$^|1`DTWTP-}E6n5eWOW{f5$>8ZcjW|lECeGP3bI3B(V1avgFU<*-4*Fk^j~|HY zN9o^1??w7mzHjDR`gIZ6A1NRI-`uagTs9DD5S+00=3rV-)(N>^9+8bN((FNGl$}uu zFu`AMiy?|2dOX>=&q?>*qV;3{BRgxy6IK5=XvakQvtset$fG$evY`j8oo@AY7;R2P zz}+4DU*BFko~VjUd=gQ0P&ZLElObQk<5ZTqR-+RW{%Tle^7BTXU33J{V7NFyRnp>4 z=wyA5Zkbr9!n(=3Y$hJH7dXTb7*8h3rny4ui9}h{VfK#UiA346PDPX*>eS4U9FHfX zrXL}r9!mf{J0gIJa40L014m$MnAIb{qS9YnbiB>NbN>I3P%};}p$_jRp^k!t<%y;Y zixEpY&W{{@Cjtyi%%-+jy{>Jd&w!ty5BezS$B*p>!vdy=7JV^qERzeb~dBL zuH)@AYMJ~|7@edj~@+jM>C^^z1pLm{FtG(;Jt_{?zgQuU3EnDhG<`&%aJR(@|Ct_YV zlPO?tP~Gu5yEXEi&ihoJ4)D4e`Z$ps_g}?pHSPGH!0Q8p3|@Eh+s!8J7CdBhA2*nH>h2L(8}ov*p3a9LbU(M z>j55+DgUbF>1FjWM1DLm@4sYXC9|IBf#iuQg*$Y6aHRxgo~l4J_!I=9Ga>@f@#LK$Czp59+&vLN!Ld|sXLb{4 z;vo!qqIWGZu(FM#j%W8Y)R8exB#59M#e#|{|3s>?vmG_q2{t5$IWQ*>AI>?c_>gfj z@j>s6o`fSr^yvsF@rBuYP6}aF)Nf3CbaeY{i;V zf=Bb@Q`I-rA0OpN+q{fU+y7?^=bUhb#yNTI;&k+9j-h<$IVm?Zb2f+JFOb3~6UF=Y zD3~+tp}dKl7dn9J!p_&eydy67x^-3PnsJ=({OB#}@|>y5H@mzCy1eaMQu0j@<$+^-B-f2Lf-Jvo&3pr{2Dw)SQp%YoRXIrI}oNORl&bJmV@3-I}1o zl_uz=tHp<8vw9x%`P2uCAe@;+f|EbofU{9SgMn|h;oq9#X0g!@sApz*SvvyyuvE{7aZ{AB??X1cMMN!6fc{$PlyIxkxsQHPbxA~S41BdW{hcH zL*lMsG5LIZjfJNX+Yj{j|4gyk8@NPe>Znk|OdQxYscSY8r+wiro+G{u9C!WqToE<) z6816n{GVr8eeyD8_+^=Xx|^Z5RgS-s&(C;oy5~$P9@BJBy8PIK@j)^=YA|MYAB&fK zS9{FWJ`&6=q}s!ypz!^J&WO<{#Dm2T@1w-SO+p*~3-xs}XH-8UC2}VNR9HRk+`vHj zT^z&3RvfS1+CdiT6S~d@3-nn23O0`72P&)d+SDxv8IWqK zn?s(HLrhc-|DrNJHHaMAhMR(hI$&>4juiBw25VmsMX{~4S&o)hcG|{_0$~>78dk!m-@#yh4o32Sb8{b;>g?#@%)Z+Io!Qm&rv;`DsA<^3+NLcwPNO8yYtpPB4Hspr7P>pMY_!2v4Gsql1O8x~c5~J<)TsJpQWv>nwO1%_99T$< z>%h$yCk}HnIDUA|SgO&47v&#SQ%$Y|x7#^>m7w3>r$+y3MiI^*ze<|qPpZ+sy7@~e zNc@!?%FN8XG59j0-{AT;F+Uu{xshWSq|CqtY0`|#-x$gt4QB^l)R#!fv2 zh*!JhuKR`9>{-BN{m)RAjOewQGNQjdK}NJ@{Slu1x*)`nm!5>6*Ou+`Agr+ulgcE zd~t?a#{Wo4_ovk8Uy|)3f}g+rQf4?!hnOYlbn>hIOn7+wDyg01CBN!P2{YwS_>+hv z{xfU!FZp~yQ|XFCnGIxi*-Yi=Y^l#7I}iC)3+z1F>mK@oZyNr*Ny(L9Wmc&qBkZMS zY10+ok@Mn74~9edWzamv85bdwCQUr3)rEbfwjld}PS%5Dz}M&kbR7)68DV1ZR}Qg_ z{}K8O%Ri+?|I&s_O|Ii~u0e_PmF_Y~9~`f=qA+U5$STLm10{L5=>Uwa>n&aW~j$&8r3pO-+J?ag<3TR^?xd zcQoPB@xIaxrc#e-fI$F+;xn!{V-AsN=FC#5b zE5O0~;z!13Tt{vq3(b@SWT~OMB{^Rw`8i4A#%9#|Vd7FV{l_W2hXz>;i0)ds{s%<0 zL$=(@M(B0d>vn}&N`0LO?P2v79rY?vnv+56G?~OshEM7E^K`tqb6NXfwC|+RL%u-@ zX*a`v8}H)MDy)ibwX96_9R6X%Ej!}SmlSBb1?AS+EkuZG^n-v-0d&IBj=SQg*Wzld z@L=4V=2m)@vOG#Ii1`l{CgmpWa%KSIwXHqkQp?m$`#}>II&Q^uWrQ(F&Hg{)-UU9& z;(GYs%`V9TfdmW!id=M6G@wz?MiOjfNeK6aB!G$t3Ncbt3cE_>;?hl!&0}oprP|h7 zsBK?s{k5sK6^)ljFo0S`v6zY%+G0C#(WaGRS_9AfJu}aSKkxhh|Kamw=RRl7 z%$zxM=FAzO+-bc65C3T~qx?u@F_k}EEpVQ!;nXH0zehbToZV`G1E&nYtt4dtV(iSf zotI!{rB!*&5bq7WbowNyFLD=+X#D`Fi9fg81F&HD})2@A;&8;18WddlNIkJl^?QV;8kq?_gRW&Es>3wnuI84p^Q;13>=EipScnbbV zx~Wmfr8peYh_k*?6F|tsnHV1-Ahu0oIWkg=+jr;uHkL+#NcF^af%P0SEw7r+XY!D#G@AT+**aYoG`K5c=<96r@8Cq z>F!oLtCg z3PsiQT!?wBSy&HGWaN?1WN-8ofNxb-Xb@|!(ZEZY8yQdirr%8R-PP5#f zq+5QP&OAkDj`S67k4o23sRO$v|7FxEMs+)%6J%TinxtQt&wlK!hmE;lYe#rq4a&PZ z;ZB|K5)z6zEvz}q*5ljiWr*#@9U``q-WU5F(k9`D!cN9Jbw&>v4czh|J4xoxtC{1Z zSfNwA3&5s~6Zp~d5z9GLw@q!Ezz&f$DCFcV(0PAEUa=OkeiZz`)-C(7a?(uiVe1xC zcn>s}c+`(A3=WRFAdM(rOtHchoCP^(sUoCUwL05}kSIN7XbU!lT^Y@v@{ie@tLRQx^;XpqJC5Psf_fm75{CcB#`V;<0iSd) z&vzOAR&@|J41cToDuY9pGH;25Y`y0rWF|L`1`C~rQ%)?(CRm-uncvT+A)<`SlDCsr zVYoR$xovS-B|Q~252JIZ{&}C*lZa;vF|OHyik~{D19A!2sp*>#)1C34P&!!@TVv~O zHlgZz8kDwwFhlG|lYod1Tj6tvcQ%-lTJ${T4MOReEtF?%lJeDn`@J}&Zk4H>0;t-1 zHaU$na+h|FlmyR+)3G-9bV?FyY}GE^V~q zm8AhLZJ6QGz2AdZbKx2XNrRt~UQJxZSa@891w3sH z0O*4O4Wkv;qvcy?3O!0_PrO+V-pE&-WbFC#iu8b9KOikAp@XDGNgj5)^(Somkn2&S zl;q;OLV`kUKngti$=tb7CM6+aD-aTK%h)%?Z z;IrZ~6T-{8EnOz>rc=}M4D3nk5+swZzZ|GioTGQ)VHk`+x%)ri%!2;xC0f#+mNKl%Q(5SZV*6gJgqsbF0mGloq z=`o@MJL4NFJsA5hs}!s5H*6EYuA@TDkHmL$8n(b-;{q!bv|>RpqYh1GY1V=^+0)ON ztapHnrLgLA`7!%A0lVgi;yZHnJk=i7<`aL-S}mhe#{lV{V11cv{`jnHvGEJ7D4G5nk!(L8 zSvE<}hbiYy>2pdW0XU|txGIQTHTE@1iuA%HespDQ!%S~jm-t?wW69PUINgbKC5k+7D>t z#M}9ETQH|qRtPxkoZ3wUl;_kw&QDye%c+%pVTa89v4Yv0S~yCHzW@(EZ{X{YHcs@g zO5b*FPVFCw7~4xH?I+GpNs&`K3TIsP%BejMM~9$vYz7%}Y9G@P89B8-a~)eG#V`3I zJEfQIruVw)?3~&kNC@o6PDbCik(%ia+)SX$9(C+Bd5)A!9+^{nV|vV!CZ_0q!CFr3 zT=B~Dsp`O1T~4j+D^ulIsp$0&>D2`Lu;%QkVI9uq)*C#g z#GtA@3~Y2UA%7txmGz=jsYO3Bl_Id}sq|!ter0RkJCi-yPPe*Yc!sCrVUkEm?FUTR z>@7Sw&y@v`gz(b`nZ$B$0}q->no4?xt=z=@e+f;lPJ|{)w4mis z$NSRUOh#zr^sz^A=hWWE-+0R&=ESOVdu2gO#dURu%!^p_XsRWRMxs+jXUA5;tk41; zZc^JWlx>mF+Ie%K^l?p)M|_p1${tL`bhGnwVlE>FOeL>z=|Ob1S>7^Mm-P_zQ=L@B zx>bMNq8oaCYB=)1qJ1idLhPq`W(vC8S2MFq@Hoe)nIJ+a1!u zg-}8HFA08yXfv!Hs_NQ&`tQ876 zx!z(R$$4T@X1psa=k`n*Xb0=|Q}|oNM)^L){R@6y;OomL;ivM+j+en$Kb&{(^%7!s zz_*GYW>OAxrL!g36SlgRV5oNsn|4mZ%qaLS(Hhth#Jqxdmv`(L`mtw+Nqls@#ML-F z@h^4s^F$|?ky>Fu%-Ykyqe+GvA+bk`EIZr_5Q7&XK z1vu@y$MDzD;}BEV@>uO5>+cQgT@%JK9c90}bD-M^mfjYr@0RESFVzK}B8HOdAqx8G zgLsK98eMTu^5TZ7PAA9D8Q%>v4>7t8+gV`GgI0+CM`wI{hBfoBlkTR=dPq^tE7Xf> zgSrz+(b`cCNpaN@w#yr})$wf?YY4>H>>dk2qcmzff6cyy_%a=T5)yjrMM+YwlT6l0 zXmQmX*4U(w|Lt}G*^so1uy4V-;r7F1l&S^yf3(J%n^Uk8#&7a zLmHmy2mMgPib$`s%0YU62`U{&&`p8557!N<_Xoobvxix~Hw(N7oRj?<<_~kqj$dlq zl$smq*D!^L#d$|iwa;Qoafqt-d0z#zEA%T}?8E14=&en%??_B>m@0oXw?UpB?X5gkDS7?6B=UpCOx)agrZaENO`B5jj}LzygQa{ z4cgH+EzgR3Z47xay{8PkTGNertORqfhT8*N$^NjFb zVN0Z^QWNe5BGYp~+s3#jz?)~@$4PHMIA$a$lYG0IDy zomSRZy|DI&>y7jt+n*hDB$S+n7C>%vvXG)?TV1YeiC)yEDVLC&y+0Syw`}$?+k|PF zNy_sLJbB69F|F_=dVX;2>K1qm0ippJLrR`Aklsk);t!D7tp`p%=D3{pP-b-;8M8>1Sy%2GoF;pz z<_*k#(cZCUN$82@ivQGTk#l$yxlkVGJNb66r+(04blxZIiH-#RQ9sl886-+06j(-q z&b|_8G^`f9frd=;8|ivszo(cUF=VT{U{cvdG0o%4#ryiQ_DCdW>n_(b^DT4h-TkLEe?5Gz#xm^j^+AEe1!)>~xHo zQ!>pYe!E5bR;b&~AEd^uFpr&vUdST2Y^d8NyH{Si4d4|-w01ng&~$BvOLWTi_RrGt z4I={E+avi=qw>-?r6yfQby^vc)VuoZ8byq1m=53n&=7)Zy2QU;`%l3?uH_*qjp5;$ zyllnFn(Ie~ufI0JJ?@mByQnK~x>4?o^KZc^ljJA$ujvH;7W|S>Xw8XtKhp06ZQ<@t zyL`j3XMGx*B+M(2dEgf(N>?iJLSc61aM64Bc6)R3P3mS}J53c|fv7$y>1u^FD2 z%~2_%s->22UuLB?ktg#HLx#XgVCIq)v*?*#OSDDDC5|CSLT45sOU3`7T+`x6S zuUU@$fIBGn%l`eE`0*szMU(zhy(=&6sdpsq6YHHpSU2^bTsa9dTLOb~$H{=wIOMc1 zhoyvgfu#hP{u@|+Onp!Dxv=cQEjUp8y08q?xHuk;E&lN-?n z`r-lnC*s6IT!8S&{O;gu=j-Cj(Qt{)P=lQD!;icXnK$z_Efln6gedqCe)<8z;acprrpB zKVlO05wLQ~bpNuxllzD@+!_3``-qQn|4{BDz9IJz=Y94*VllK!?jug-_w()}4s@Gj z$dX)0Y@7jnzTO(?Vz5Y0W%(mEp94#8;FZ59HsF@tAeO0aSQ5GZTG|}z$s^{WQ+dRc zbmmfw`7XIme&|E1L1f0C9y^^6ZNSGJX5h;V(VuI5zJtOs7Eq4%~ z{_p8D{{y&x%r}w*HP3uG-8s-+;#pjQH4A541#x>lN9{`bGPhDH?EyjVR7gGCsW>4* zpn02`(ngoxGm=1#-0Vknk?Fw7Re5vWUeaWzrO|ysQm-dKn)%l+jnqhz+_WSaPDvTu zxWE3!o?;lKsj39;^3O*x*Waj%0roYc0H|-JHX&>bw)6^QRxHCf%c`tOGhIEI=E`ff zNo72kfT+2?I?}gN|7Z&>9`6FzxQfSnx$C5kx2298lUvN-xQ1a)tmnTia?I(J*SnHC zN2Vm-i4c2z#QDWs<>!EDwXBf*{UyJ)0b~lv`20e|IMo9ty}? zE=!^9bI~EDGq7&cN6${}^m5Je+GQ&vS(9$MX~nW7H(D*(XK47OKDlxB1?c+k>RTXX z@)VW!-G zrV_kZl3A(WGV}5}f;I*2Le5;@Wnd?QtEo`RFF=hq046jIa_NLuaC5wgCU2%G!!15| z7Ht~bL;sg8O|RoKE%T=6Tu&V->X-^j(bQB(4<&YkXxA30JJ-;#`8CUyt@r|Teh$I$ z^wAmE^+cAqC4LSr%a`1^bj30Zu^2Kyoq1B?!WTU z@N4Jv_^-gP@aM4tJ^Dh)XZBf--rQsFb=ZRAZLu%-Cj99YScl^KJX`ED=F_%1?mezz zmE`-sX^S06CjVsFl>JwPU)Jx8t=L4(%J5}mX7tYRWMpLY$_QkP;LdR0rfe*^_G=0> zU4*@>GnxvT`ZS%?l-D$@X+l$R)5NAu`)~F~_J{T%J86Glci77QtNj=IefyyOXZug~ zAMFG7d-l8bJNDc5e)}!^4|co#roGSpz5Ory4STQsy8W8H$Nt#<2lw?4teNB)^9?Lz z-3pG^!WZIh$2}T%jIUrFb_e*{`MUTD*K?nrFM9)hz&DKV*L(;0f_!)Iy?iV=Gylzg;*0E?xciAOvTrgd%}8I*mcnY; z0*t;urDIr1cSB!578_K(ua}qdmS6)g>-rl)D{fl7Ec5ysX0Kd!V;>?|_(GT_4_tpk z#bro+mXJjMlBE3lRpPCfz9g~)ul!I{sOI_`m#tn#-U=w*-1ijp_>bZLCVn{rjW7#Nlxh8+*onD=G4p?F&*Y2V z*h;rI_}|!xF|;`YJU$8ri)pQ6PuKG`3>Xja&cd`so_CP<5;Q%;=3pKax(q>-&odH| z?)Q4Vy}TLTf!^~yxf$nqGCXn5H$Ao3e9iF<@STD+e5^S@J^Fe3d;4U3rRlsTV=+Z& zd_SmsQBw|94F@z0Z8{zM-KRq1gHZi5o6c%FyXpKU&oka9U$A%BtO%XdHD*gEw8>sjm^6|TZ@5i_g^E>3X{8DFtvWM{1K1`W>kMgzf#VD(V zG;i=JzD~X_KF<@>#kYlT7vJP<)XNv)`!!zyVTGjI%y$pp7QVxT$DRZpe*OGr^X2gs zJVpJ@Z~}Y}^ZB0!M#7uEOTHH1`XAzdK{~!L35W~9f{L3!1HtP_A~N6Lj8OP zar^l#{uXtTcH3k4A7_OjToK+$-urj4Qjzc1lvxYz)_}K0@KHk80pjj|j(SL&+eq7= zN21k6TFOf2%9;NKTE^RBwNxhXVHPY56}bW!NP{#pF-G)3+Q!wvd(!;B#{D$kkT071H-nk6=6$^r-@N%xeAbw~V7HD||G&Uzt$ah4#2n8q z>d4_;whAAR1N1L<_}|LNO< z1#kcVOc$m8XBnxCz|HR%Ts}=0VoLqepo7Xr!H38$(*p%(j?FB0C~DbdV><2_X|eG= zxLk;PC7+x*{@;GbF~V5*|6+|9`Fp6weP8~L<3ZA_dy`q-4nM^g+Xo+@SBZg53yE9G zcZe`^d}E#o7d$!VIVM05>Ad6EgJ7$rlXPG9PvV0l_;1cO5YfUuTmc(mwY(f}Y3%6x zOVRdf?8tI{ljb*!E?!CCc7L#yNbSi^_XN{DdFh@Z>7J44o?(us!~X(RqAc3j@fXhY zjLXl7rE&Gg_41mFU`_b$;5$n5dhy$jZxG+SG}w&- zi|FF{P!8d3WX|u$wV<=y-z~jD%^V}A^$nscVV$PcBu}+g2hoHdFlTO9>rKv6yUn$& zaV;FVH_FjKZwkM5m1BKPD&k+34!dmCs+(>}^M_X5w0d=#f9j-VOK#BqK03XK*k_ei z%r|8qNT*yKhMt-UOG`JuqV&Xc^9eCw2BxZ&1_Bc%8=7lZl_SNSvVyk>biJ86Ok|(w zWzD)t1ek7F29ENIl`F27;i~hQuzAOYneu01u;8rj3FhBYHUdw(YqD-s&iK7et3W+85P@eQJV-bLHIm)=N{Ll9`SwO|IYEKae&^5E>%- zzK1CzZvtgJd3+g1;G8L=p~Cwld2XYOmwlftL)lz^Qa5sc0X3DO@rj24+JljvLEBpJv7OE2RWT46~0!&V>8&S=Yuh{TZ)AC$kUKwQQx^k z(3Qvzwn2P7SnW+_Tc6IZ+a2vC z$-PC#*1ySp{X{`MzRRx=^(APG=sQ~_-RiYX^hP_V%C_3W>TYlc+2CUOm5$CT7xL-Z z1PY#=#%@$W@+cjPmRQ19r5>jvF1NZ8YyAx~#f(aunnOr!3tC(+aaA0D;yyaQx4zT* zi+go%$)#{j6Xv4}c6DHS-Trl_glLl(|9I#-*u0Y2p#J#5QM+tB%2w?voYk%=r-cEQrb zNXs{|R|c0EawC_HWuNPboFr;+7bb5VD|Z|sQ_3UfCvR+^LqY+y_Z)75ly-%;P8MRX z+PT+*R}F&zB&Rib)wgnRTozyJ9}q3tT1=XFOSU>jrzFRK!nhg`;g(6C$bjT&sn`P& z+ka;$TP8Br&Sp@AtKgIz(Qy^iDL%1~qCAl-qQ?@gethJptv==t15$>B=&{j0E=guq zZ#!%!{ngt(wy)ammos+3>((6@MX@}s;&yLR-v5uIcA~rhZ;m>MyGQHAz4xp~01ZYP z*%~D36RHz*GaNFlvVugY08CS!%m;^ju_Q8%%L=NS|7@$#f7jp%6at&1`IprhTOW{H zJd);pTlq=DC@jT}4~B}+O|2M7i=?ZyPA0HnBCw#^D!H+zNd$<7<_tYv7zQEZWlS?l zjawahK(ybq9-bR^T>P({c;HIATe=BodhV9KLBqMfReT|eV@>@)LT6(2_@@|r(n-lx z1ngnlot%Tiz03In3g|(jD6Y~s+~I5>T;Jg=8?PpQgxk4)ISRLP|MCiw7<>w%Tt&c$ zgZ#?VK>q5#Y2;6|+UmpQn=8t#@Qg&ojQa56%@vF1HLNUbSX=0rl3Ii}+^{z6dadwy zD>Pn|*8)PpG;T!&S9loR70OoMpmagK9y3I~g^`WtzdLSw{&v!}YDZD$`d-%aQh=Cv z0Zx4xt)V#R)FYjd4Vfs~zAm$f8&Vtc^7mLXf`NQWx=TGQ^R`n|Dy>j1#sU0Jvg{25 zb+T-eY$M4?)B;)Y(`PxKw1+==cV0uNFszm{+v4Vm6yvS}{4+M1|7fdcz@y=noUjA7 z`k5O>ACGHs+Ox-i-&zRMoBJ25Sg%q?0K5L-)alk&VtAHiVRdS8aInIG{TyQHqJ z$Gu=Y-qNMEARJ{pMLU=K=c%8gn{N%$EZ#uY*vQ#dX{Y+&pMtHrBRRGI2IOQ0olq8J zb@_xbcSTH?$IkfrPVS`aC))bt_ym`bfQ4oKp`!JjIkno}jx1P*wYg37v#SEq5$Q!{ z=^|C~T)na#c9wGQhkC^2nn3j@bk`E4Dk-KGN)=ERm8!_1w$g6&o$D}hm#aCf4r z3%h~g8qZ~n*{or*sC*su%-H&FPvnAz(snp!khu@d{f5$Ac(B&E+wn-Oe5#WGP@RE} zc&ovsrf(_qN0*E*5f|bIMccRUUL z%UD(4)S+tlx5REur$)}bVt0_QsI(JSkfaa88<%gG+*X?88dw*&N`@O|wu>>G($4DU?Y4Rx1|zmU ziM`G=iNQ(}TJFl>8D%f$Xrm=mEVhx>l%J&zyvRg=ZbeZcA_4D%5*u>NC4i zR|15-*em^Zfw}?Y>C}VaV0VBp5RqM>ekvD(ghlUg_!CGbRJ(RJO~Wn$=@OZ!KU!k_^!+45ZrKk$1Rp3+?+neMG`1eGnP}Ls#%ZAVzBw4Lhuvn2Z=eZ0+SUV6? zn3A!-x(_mC20B<1efDv-NwZRNu8Tbzlff5R9e;Mbb}Wa6EMivzMz6+MfwMe1gmrk6 z#H%a8zp1)tQbA;*TQAm+z7Cs16HbRCHA#1oRQj$Tbhk|nry#2<*%xjf?D~s7j>48o zPYO)3Rye)niH_Y`PRsH$&9c&~63_afTW3gEnLjNs=Z-sI$hHdi6V`w0H?xOu>=3F= zvO2b#p7%u0iceffI;`jDg2HMwvN#AN8!7cKBdro-J~CI?E_>h7lnx{wq}thI#l0RoQ2#;7ok(EBt^2on&r1n zHd&^CF|IA^$Y0{ldG5`vBeCFQdDH`3kO-?q+)zskyj=%QCD5IabuWTw=E*6bW3CHo zxZtkpW)ArMe`Qy?P)(I~bm>+k*34j25!CL6aGq&diNCt}U0dz@3#^l#6PqWMC(ksf zVvlq2U_B(z^Vi9KnV!tSJC}J*E2iZQ6=7J3CuLu$ZlPb8%wuEg*cW0hP~wF!7o=Qc z3>dIhYg}F`jsK7_-33nz0Zd#ZnRRL`ABX)lGUn7%>175}?Pcwc`GLOjK&fG!#rYDgzPDvPeXd!KI2ckP2 z5277^{B+D{)OJ^DMO<;@PplTQ$~to}(r25-;dX2er1stM9S3CX{+BT6;9SUpT+3QC zL$-1kE=`;+i+NXDuM#4#Tx#a{blJLbhv`qYy7ypeFU9WHz2to@Gcvxu%ac<#2AA~; z3)suD+1dLKSqPotyd612Iz|1(R?|MWC^=V>qOch)#po`)pRVmG2E%jKf`XK=A7zmY*y6)7DS5v(@CbhDy35%BBgazmsL?L*;f|$<`r9^LSI=SsnsGf z>QYHtVpWkAbJtz-Wt)+j3s+mO*3%R0e>=N-u4pDt?)Vv_7SWLOkNOu=T$L-m7lbF) zd|ZW|6+-aDUSw$?wgyu;a~+BiovJCljJQgsXMgRBZ<86|iTWS+CeJbPnloYvJH=Th z=lZRFQe$;d$pnY<5*R!W4@p#YCI>h{**Ykf zpepr!mK)f$$T@E1nX$EtJ<&XOW({B^`#wybY~;lVk>2=ZGIlgTtI>>EXMpe{m}C^`reD_Nle(kBn*7MXgoJTHTL0#XP5DFer&FY3b6HKQy5ifj z<;R*E!1Ci=>ScCK?!2zarB~pKxrh7-8-p%rpv7%t97F7roLXBuG8wALKcwt@BQ`P54Mv_aT?NGrr)$1WHg|28n_I!c%WCE{UIfSEvgdX0ApY@LKIF@DH>PYY zF=u@0tXe?u$)12+hfi6gWa9W-K2Fv=SY1pE{wi0@g^Dqh{GDP>G?3qhMT)Nt5OblL z@6&S++j}5Ujf7p3`GV|i$efhyjqWH3l-ISaTTz0Mi=FHxh3FwM1+A|Gm)T3HTQD-o zc>Sv6{(HD5cc=P2Bv%aq_39+SKX$mCJ6T;MlReY@WNqyj4#`Y*+NIt0%)`+irV@<+ z5(D1*b#jI96X*s;ARRh|T@@3#lt>5m?I*$>@A9m>T+VU~(5Gpj*^nJp+kG17aRT)B z(y|>^BLO-E!&ags`QJ$1+7T59I_;U=n0dFOkEBxVPC;6vA)T3mRQIns=RJrDtO$Jg zc0r*dV*2ed*>Y(UU!O2a8Btp1W$Zx2*HmIJ9&xn#1SECTO1{$W_?iWt=rYsrugOr* z7ydWSb+H~_8}P5|rPx%7am$AALjGDMl_Fj$2MLKu3j`Id>eCHrw;4B+-4wZwB3nD| zgrpg3o8bilz^wovzjJ}X*nD7*7GJvn6)i2MzCz;nni4*U15{`Mce)pb)ei&2MwQNXERpucsFM|{RCmBRGOT)UoF0x*aWZS;wc*>y z<;*)*RC)t5!1}wMfrz@*w6~Z#xA?7{a6vihVItFnetN^Bj%6Eq>!%?#ipB$FvGHY}GjTX37X+ZpGivtQ(bX_4@>$k#idq@JQ# zft*_Du*9rD-R_$MMYD2O`x3Kqh0~#^pPQnJW@SgNNzBSNDe@#mo|7WsrpS$yNWL;o z1#ZqNdS23CCqS37%uSOQ874W)vU}2GJ83R6X`oZp@inKwM?*sPSfOEd#gNpUX1H0s zj_nr2g~aR>?b5VC$!>Kw`}+hO3UWR!D0vK4bro=DxL?&@D7~?dEGTKTz`^r-oL|Y|`)eqm7VXh!IZKYjA91?Ru zo^6Y%R;|URp^V-(wGnEPntU^elgBWG&d7b^Tz*?SUSvWgVXPo^LNO?Wp`*`R&s;rn z^qH&Akv57DKu@4oQ_W&%p2W!l@Q>Ce8FN)IN6)-8D+Le!fgu;3u|Qn_=OLyFlC02D zkVD<}X^6VjCg@sgM~Ohfc+>J`;d|6u$fc;@G?BH!Nrlsj4pB4)5a#q4Kycp7c*W!y z-eW6ah=yW;6jBmVKV@UplZj?g&pwl9XiuJl?MLnUl54Dr+zFGW^dxuc82*aBf;~Wr zjQK&lRgqmZX-s-Ly;d<*0DBls5Nk%ETy+8Zj50Ym$1-G2;)6PVuT_>S)Mv39FXD5Z ze+==Q3gpIHBCK=2fMllTlqQu@Mq#Q9)sXGfLBHwdNqm5Kh()eeC(saAWhWZN-k3h9 zFggb*dj^xhSkD>4f*q_ISB_zoEm@fejozBKKpUuJ4Q@G~V}%<&WVCUtupqH0u(Qlx zvkVQ2AtZqrv|b{SCLR%XK$55?v1r)NvLSm`P4esvE$zhyr!6$a+ZHP4o60xM+ZN|M z5@ALt%s0zZy)$&&c5nP%Jmsod`*xoMN2D!Zg?$O3uGs)kEJi#r|Cy;InHyqS#tS+%x zlali`&MNW5*k5i~DAu)r@jaWjbAXYprp=}REOPj^P#TxbZ(?O&XNms~^yH6B8R^Zr z_jx&Du5RwM)t!<_PK*=VjigoPCKe__)9Yi!oYqeWEe44)*EWY|wp!t!c?2VWygoY- z8$0jP_o5e|ZR{MtZQuPif1UM8pI=qSr%w)88%B%q1>FI^ra??4u?1o}Kzc%*`vPM3 z__dQi(dq)&j$$13W*iZfb&A+o!XGgHPlh`FGmQVQuKyzAf7A6(H2$6VA>N-5BGUn)kQeQTGfE3Yv4*_WJB#?D?ay4&2XAcr7}X#-B5$SL93v z5YFK^Pmw3Dc+W&XU^1_OvFf~Ff((_e`Wx@R?3GbK4%0K6%N9$-K3ly=gqY-aY}cS= zfKe%ETEomhLltYY8arGs02_)H73deNips`Eb2(`(Dl6o`t29tlRvcL}Zg>5>DJ0$l z;S<@qOu!#*-saR!I6pSut_Y!!^23rqJDFycYSS15qImX>4fNe{ZX^ z2>^E}IO%gR<|F5Wv^7MVr;le46xiR1QB2GdKE`Y2V_KRQNm5a8e5wq$Kdtt;Jq4YZ zN{pj0w@q1dO=Tyh2}l~vgXp7aOkBB-a%n4yw7#fGNL)mo`7*~aP`knLZAOOP--?L? zUO|0wGjsn)WEfm2@s5nWzmbqj{Ku=I5!k@nSU%a~7jZ!*w}6biO0o8oI+)TZv9_ z4gIKDgR*$C{b_4QZzx>yZ}gF{FIuvuNv11i${?$pb}&jRrZ6EN=>y-nI*8S9rm)I} zcSboyoR@$n;OYgWdfu4%?aUjiydcrXDj%Pi=EvzPFXY4&udlqAy}d*C2)Qu-l{u)4 zShxD~U!9{(cRF)Hih)J!BeDQW(Ai6h6Oc`4rkpB>CWx+avJhJYw8D4Fj#;w-iuK3? zNBT0OHNk5Xl32B~(CHT~gunhw8QGsH;~w}r(TGt~+!DUymSDyZ_BVx%JuGz!5Bs~T zT^?48?l9Ae4aY8yO8d&W9Z!Q)9o|}u?MHQ?D6q^t%wpfwT;fsl;XlBa7i^rBuzj9glp?_j3H%JiYdl!eIOhlDsW z#nENb=Q7TIJ}qs&lQ#eOv@~vkoa~GO-Gj1gv88q3m7YaaP1%6bjvW0&-%HJ{PHGU! zBu{HRt_SClNUz4X*1A?R)D z2=YraSkY48YJmACvZt?*K)p${X+QFk!zg?S!7nPt*y$iCmbc;N3D3ENtE+IEnAb*2b$mBk;(-iV5Kvk=)JU8KQ-w7o&N<6EzD> zGexgW20Ul}-DcPJG9?*(sv}cMMn*0YQTa|a9g(TX=cWWy4I8-VaO)O1lRQ<}GQA~y z@MS%M`snU)ExrlyQpL~e!{R=gl&K3TC^h`|QWx_`C7@re9U&or?u#kT_-8YTUdm5? z!fQBS$R!UUc{wbXnIMZ0&LK<&G+t#DzCdw~J)Y_>1a!E`*sQq)rR3T@i;;|aNaKOqk)t6RTI!_XD+j;~I8S+RH;FA3xzhP+aR0B z2Fr|5*>|_9|B*siZ1<^`*qFf2wyB%hTIlI<197PVH<^smMMI#ptsSpJ^?K}#O$g79 z4B8x?-BuDd5Elcnng+b^AXYn@Gf!Kn%!9y6o%v^s9ER3J1{#(pSHcDmmIxW9s=sM# zf8AEm&njCWO8^Gr!GCNGlR7iDrpy!Zv0-SEH|pwRvg6~qI^yd~!us913E`=c!JETV zWiR9y=N1N9ZKJOx-Gs(E@baF8nh+$2)xbj1q5{G)WP}Pr<>UsCdj< z-Ta2FHt!N@rs;*|6!c78VZ}xZTenwz_%+$lt-I2y2wG3+u=xS!5rTcU`K*7;Dr$>d zYQ1@v3d@sTtkotX@9?SD$@(j=;hAoh(puH2mv}uGs`f|vO6_mjst>ix5XJ6#d9ZGG zWEfO-fc0%%(cHi^RZSy+`gL^`4nuQOJci~l%4*!P{2w@sJqVD}IE;T{I8~KHbsheq zT)*298V^Yof*(CbbIVkps8LF~jig|Hs9pBr{aQU-D$Trga>IY_0I?Np9qFfTY75O}rZnh`t zQo7^Ay(tRV6CS89nO#06W0ji&?WxgnuE^FxJL>296?4&J=8|jM_^>0^hh_ihYwm;+ zk%eY&y*o5>a&GK7Q6=z3Snm&S9WU$sS_HsplWOT1OsbEW(hTof7*khaySH)J(Q4-e z@W_gt^TS9%`rRLQfn56xgbp zwKCuo&2H=!7Sf&S?RV1_tbfuNnWxvmvbA=M0y5W3vep4F>Ln-T&`mSmSe~PSwoD%7 z+P05|dLkp*GQD%GnYnZ7XJ*fleYCce+)k8z_Z$2bMYU|Bqb=f~S9GSqn5n^hln>i2B)U1sb(zV;F>}<8xsCSCrsg4=`;r=jYAg?P~GO4a*smGbjCw}c2jB&q3V9c0X7_*Y@*LAcMVEA zYo>axVBJP{IC>zzEx$Evtv@*5YV+ZcRQ06NNtg-wJBhBacIr4KNhL*%n?ef7FFl~c z5Ak=Nj-Kj9O97<^rG)t==6qt9S*Db0@T6F~ARtR--IOq-t+nGHO#5WgT}LX$?XGVA zz*Y-d9Dd|T|f4NMTGD{0zItt0SoPLS9|OE=cpA0MWZSJLxKd3IIUgujKr-h z&`NA_#YnB>X|?)N{}|t@tjNL+*()P4_RG6jr(5#UF>&$`C|4zB1oK!pIn8Q**;Z0V za@6OhAaQl`LEa!B2|`3lOO$3OFQUYuI=$XDnu4CO)fy>iNO}Yrs+(W4)godLi8!{6 z_4@QOzBD zHuY5$uHY744#WIS!Oi-`;a}-N^(PPsz@?BjbsDpBbLpoY@{9o9?Z|e_ zybuMXVEkEWlZS1&Ik$MldQ;)eeZXo{dHKxey4D9 z<5&-OvD91L876f*7asN-P+mF2-8(LVy2z@bJUxfi%-a zMW$GykDT2yfq>NDa!$esrzAa%l-U3UW?p7HA?hnKh+0$k4Qa_QbW2WUjmBcdUrlp5D^UFs87ud?Q3*p4tQ$hZ0ltWU zLu2fU(Xf=la64m`P|Z{`iIL@niW6}WYFMGdM7&YZ)f#U$6FU@Z-b_FSV)M9!)R#<$ zlU&_b=Me!%a+FEojpU?K_>YpLw=V5|U79T5vH_i*oj=`gRRr=+qG#nS#quS}3g8Rm zG$jwkUpgR_;UrYfsmI2{DtGYUA*vp zR1ic#xbAg=J9bE1rg;);oOu#!3?<#1D(NAU8FrD3_wB(adA}oh1p|_oVpr8n?8DD3 zOW2LYqIqL|cp`n`$|uia`J%q~c^OuwxhmPWJaS5T$>DP3cPu%0qKK_n6z2uziqg4=C12=(5IASFa?wPeO9)q9tvu4JJaTUGI$lSk^U-%t_Ij@176{mM|5UJRy{U$96szWEic}>#`BiH}CHmxS z|HXF!gl3`>bEaJ9T%(U~DNB71S7JjYfye{>7Ja9RfJ6WQG4jvIun7P3cAlUN%_4?# z=UI2D*$<)6q^Vgc&HDS^$M7>DoWlP*eu)9C)VoW3MhU@PN*Nm5T zh@%`wmHN4CGOb-t?b5;BP>GZDMhRGm(Rcl)u68VD2z*vMkLt=2=8@aj>VZG%TimDP z{5DRjWK2<9)E5wQ@!CrOmwmVRuWXee7tM>WT_`WXgcj<1PRpO5w}zw&)Gx%O=P~?z ze_fk%4xFotl0n8ciV4)$rBk~Khy3ZU(TLl8!`6XzvizwC`_Ga3U~T% zs}s?9ZuG32=cWY0{OJ>}wx;;iIcG67cJ-MV5cOlEo%?O|)NkFxMzcTABAvaoy;O87 zo$=JkfaZY<{rczcKIB!EP)Q)tONL~|meJq9^pCYqB#`PGpf}a=PQOc8|N2W>SsRuOE26AaXPua?J1yOhopgfZ6VnCPn({Iz zZ{3%aHzO@wWm=6I$k~bCJ@w5eLe2a8&z zRmZdp{={+f_Il_1@&FFbFE?1B8Y?V}RKKE%LN`KRWbC$q;Y!r1+X#Po!UbO&)duXk#$g z;;WLX6shCY$IJhPr|B}{Yw2NOzeVz{WKV3HY5O3YA zel*MF5lw%xx=U}4il=%LIhpRw^^Zz#Mue6~Ke0zR2DdZ&E|6Ri!SzpE<}~*`;d1Hg zo$Bk~W)p|X(oXg9-7LJ1YsU3)-7)e$+T8KZTT;Cc2&H;xG<8c4jfXvJ?f9svr-xjg zlrarogrT4fqqycOW3xNHJ@8HjBlzuM?e86UaCL_DZW%#SqaQfNKlGX;^1)q>LIMS> zLQRi*`$NkA~2qCC@9k(}mL(#wa&EVO{54f)hUzFd82s?n7 zI{W*HNN^0EF?jMskX?YM0MD@RBk3NGXFQ(Z_eEOxlq?6Tm^l|$-c@}f+2xUb<&pl$ z{*U{TeW)^%sxlsDm5lEw)B-*^vv${;AuhS%nMBzbtIkJU>5lVqUTh1&@WCuLUfv=N zBjXMi&qck<3X6pM?ikSypDg-V$cSFGRsWysEMd?|kK&Ul0$x}AV>Tt0pC zh3gSmChFG^pFxnC27{M8*?6o$`daruYwj4eiSV|#K2O=QViO8Nae1w{Ee-^pjJCL3 za;5xX@&oo#TID|kQJ>K&M`S@7^jOqpqD6sLC`8kJ=-)OMN_H+8$F&1CtX2K|8P0s; za!R6Ba$0D`$BVP~|3U!G6HH}`z#_q(=eK(u@jl5-9^xD*D9h?Nx~ zrfNS~&0q0*COmY$ly~ zRhJm_DiDKSsYK|eOe3mMy0h-}bvZ>T4aq_m z;V(s)Cz&4oYl_U}0ElG%%}<2PWkFqC)j@YGy6<4BS2AS*tEyR`Vb`Xz_R4B~%Ij$- zjaTdPy4BA}+}iO3!#CL}iQbVV-C6YqXzh&wphjZO7f~<2R}a*i6TxL_9;P+8 zfp1zN^v4%2)Ug=;zzmbo2RI1xpr@A{cjeT*C&LD2wrK&_^*tUFZ)~BsL+j``bHq^e zdyy0@_C|~N>yHlS#6r|PB+F}E-|)rvcwm_hhSf{^Y5SRJu_pM}65L<1%4N}mzBXt%zvXVIz5P*`DDjz2UrJV-Q$KF5$U>ZSa zXkEvK1j3{DQh8>w2Rmq2-r8Yc>3rQPbd_EuyOK{7IY=9geR*>{%Be znFvDBJ}o9p60YgCzUpQmT^A{i?V_7@MZUtf=GZP{s-Q!JW*SB@qKU}Mw9sn`K`Er_ zus7`Q;9*5cl@T#Ue7e+1T3{q*)?I=U(Mg}$?VFRGzsD;^ZZxD-htJ{ioC`HTBo|PK zAK|&K%BMTi#Cr>p#l(3dNHPQr^%6QjZUxeTZUuq-J-&aKJm;*`sG_B}1@z$|H;a+$ zw2H)350FqHT$*g!imDDrHjH~6AyoX|y>5xv!Fv~4lRUfmB7Ajx-{Jca-!J)?borrT zgXD82`ID2=1H6;6ljHK4IMTv%3X*5LZtu!K@{}~s37H($n>7TTUm4q_hP^+mg?K-C z2(pH@%$iP5WU4;kHF)UMY9&K-ZJjLLxsiO=jZ(}A<30G7v4pwd>ThCJLT7sq6p9Hwp%3mRN(^;nskH)s=dAcK&$@HiJ?&HH z5fEE5oy+OkI|6V0prsA${KJc*0TSBLHyw*rSGDSWxb7FuEx6yv(S;WC# zmwQG!3b%VqI!JavT2Fulk=1HUM*^%?sjFn$MB6tAi%Sxo9~P0lyVU&lhi0jPT#vic zWumLN>CZh|`|>J`#h}bYZ_dY+bc=@Yo|TOE}rcYWj<-CJgXRJC8xT+_{veui8CO%1L*#JA-!3+2|R zc*-Z|CYf^Gs**5Sd6KE77=;piX%( zg`EI^NusBJAidciacD{<$gGX%7qT{f>U7t7V5nmkJ(SkF&74D4y%2P($C!0;sQrm< zuGn4?z{_=eWd5Bu1tvx}ri;@fXo+5LL~ns)?-OL&_htz!%ybA(#`)_NLY_B{ZB(Pic z0p8Y*ArQpmyK+viul1<=1rVWO>n=*cTP|US_4fh|Q*Mxf`g|fpd-G{q%^(7>UvbE9 zBf9u=<(3>a4Ws|8dtI&|ip*M$t=iNloRYwe_2%x`KDB(R*Wvq3JTi}otSzR#Z-Zaz z8`iK%^M`xYG~UGOpxKw0y4-T6rpj@$26Z`3p@WYv zCxBOu$D|}7fZW11$LvRJwUmOEd#!i5gE2<9x1DMgLJ!cvIT~{TfoUM8PSlAtgQxH9 zwW--8(SChz4}A>RukY=(sq_8k7 z#%W68UbfWW+zCMk(wCmP*ueQBdCVS|dr&`uA%p_8sX7u;?5hSjZK_HNZBwrUi?f%Oy5;W6&!y9_ z+0hF{J28P-^vMRfMfHOE=u+(8hj$1{?_ z*QWaIO9hljfR-k-d{2*O&Y@E&* zMbn$>phyFaWKo0;COQy%b`5=qyk7e`ZV@xO+|?bAQ3SaZ6vD(paUwLt+7LuXCYzyt z(-_1Pp<&3YHr0?7=gv@2tebCJcufi3(KQ}yU4r?OS=AGvVwuP#PWL22;~Vak23ncw zr29Ay)E*IWeVrwd6{jIILk;I7CPi@bX}QE-0GVv5R zQ*>{bB#{dwK+;HB^-XZJv-AOp$Db&Dx}o%b?Ef}lXaQ7V+jm&=D5V8|b~e3-MFfs;Gt zD_&#-Y!azR&pZ-YOCBtP)fqqLU7xe9@O~soaV`V^cydHTnODt|+X2`huVk<-68A3I z>!`oI1X%yZ)DXSth*xBK(k?BpGCYF5(Tb_ws+t((I#PHMTnG?hbt(X*hSu$*kVSqY zH&2hYc6{smv{jfi#*%)c0S?@m``9_MZg-ZdnhD^uv&`|s@Z`U{Zdl0i?o+?IglJtG z{g(+}^!~UO0aMmqgqQ+`2Q#X=38KeieLT;7V8MzTAln!_5;z`x=&&33D+0}93nQ1G zB)1^szoz(C%D{7zy-2b&T)QHviwq@a$sc8m#I75v4a7PGzPk|p6wr$WRuK~mdVdUT z8t(Wu4YPA?XBgHx!y(W|hvj%E2Merm187C8i;?J6_*_IvyVf8YX zGXxi@y`kwez4c4ogfI^FVaO6-%O?liD-Di1BPUkKa12ypf>u=b?`jlONM19(7nMeyp`|$93nAP5P06e7{4SK@9sYnz+0tp*Yp3-tqGgU4C5b08nl*>P z@)3wPI{v5KBg;p$cf45$temB`sofAwQ0L11h11ug9678R<>I?3<>PvU(LYO#_M1gw z+x#2mQ1u65?Pv=VKlzaxogCV6`*$!Stj_@D6hU>~?)9iM9LU*=3eOVXaZrxyKalC5 z`2d)4J%}+p%$_voj&Dgf=qPag(~Fr3?OIWz%Ab!qVW}rS#QEPCni2^HTs{Bpi1F3>nQAJLe|59u4Z)($mIz_VuiInHcV zyE$^wT9-1h^jeQLx~%p3v@LUDE!ewlNMvPPWkoJ5k6a#CgN<@shs>y69$FJuy>q_# zB{~Hn@Kwu*T zMMaG^)@VRcP$R*1Vc8HAa3Lgs0tST`5P`z3Qn@WIAe$vEt=g+?rP@|ot=B37YRY1Q zmshEx&`MkWt!+=-SYxFSHL}0&%z2*OMW}t>KYX6-^PJ0^`<$6MGjsaCD2LMC^&&@b z$778hkLe}hu&zF_2G$_69O5fkr`9Kt<;9**jlM>g5B7wv!p*T7*;I@f9KNz?eFyaj znhL;+|D_HaU~+SE(6T;Mj}dx(EO40i!WoP9CY$54Dbu-`HKOiW%!d@ku%+$Um41)^ zS`gg&_r2?WA+4y0w|2*u5QEfnX+ig%&=vAFI5{JJbAFBNjcZ#yDBMh|G50g+MEmbr zF{ktunLg<2>F#MB+DQ#JlmON&W#={@{?v`RCKGcvF_Qgs)eW?pZcTiH5F$bRP$_Jb z6FUpSr=#_Ww+Yc>Y%!lT(_PlucO+9W%@4%?HT)e@@IA&>^q^0t7x4apzumPvrMm3G zg;2e*$^t}C;#kVT-;XhIol|u@c3ziF~#`}dOfAu~=Qw~cW zRogoc)ToL~n4mflI5hQCo5|>UGd`_>L$J0Mr3%@>1x8P8SS;Jqw^&f!j8iFhAq`VA?azhHt8L3!_PR#LD?=3m|r2Pe(jB8*QCZtr8iv-#*3>MLK>?W zPyIA{H?@=3M?nSBRHf7QnNr)T?L(x?yz4{}0yMAN3s=z%RpyW9YCjZF=P^tfst@hkK<2GQ0_;Ks<~tsk&oMPn zXrrA@-JAjTZ#uvNJDtqqQYh|w*PkwUe^;?CUZtb%b~cd6cB8WcEfJKXhN731gG23v z8HW)MTVg*!$2!^C&Xma`$aw@>YHfvl37;&5f%_hC_TxB9xvA#v^w+(?X=cO@SvsB5 zNd7GAl%ESUM5Mp6?t|tB(n^jOAx1WE^{6FHngUM+DebZ|Wq}kvFXc#LoD*!LgJjen zwiUOZqRWn^42kOlUiMl`ZV0Go-L6g{4<*6BUZ9Srrxi zkcw-KA0v-c-#o)hqAm7KR_^bemFw_4Z-Qpc-cMxHf+$7GqTL80%!!Zh8NCEy1Vuvx#)lkZ0T&MMRRPEcZY zeDN2@$MNR=nX1no+bma3DD9RszyDvP`OW_#&9_dRMo2P*VUg$U{LN>ltnlZD&vmxJ zUp&ZKgy=#YP5NEbHQ_SZ^vsKlVXM8Q2n4F*fw~mJ!pIA{>O%wZ`%xJ3M%TzWJ=+>u zio#8(Zm<39hNl0WmhBSTDb`8GOvt9l$)q^<*cA9pgUczzV5c{)Q0cAaI{bqj9vA2q zmXAvyRG7}KW`@X!P$Y9w(%D)SISp?$rDVBQc2$f2MKpI`6*vE$BR*&*@PZB}E=uwb zSE6A#uxV0JQ*9wD=KljvG9B}xlLqAod#qDZz@Sy2|Ck4&pN#$j%Pzh4`EEst5j39z z?*x^DQ>^|QU7qn6UDRddo2_)e43NO8%&Slq)!NlTH09Sv&C$^9{LS^Q7i%EdK0yCm z(UlzS=s4ELmzURL?{M){GfS4|1SsjfRHFz^-XW#YeZVG;?IVxG3neixE950KGs}_x z^Rvafe*_HUP?^bb^=nu6&gmAu%;8&9pYME^iSd;nhmqCYX$J6vu46wZ%G?~r79{O= zPqts_y3NP5|Esiz_8$}WW;(28LmPP0QQzpW>1-H6K#L!=@8bI%|E~FLLYv7R-9ACl zbU3X8IwWp&U(P`mL?_I2BYdTBwirt_hsL`>ONK?ZS84VO-5^rkB@m^|pltXn2V_O< zli)!}nsaK+>aFwzxONbSA9o29Gk2C{@;Q4-*D`dqTf;IJ4*HV_55$e~%7B)LDN!_mnj8%_D$mT|DNatd@my;!kSS zVFZIz+q?&9Cs$r+F4zA9T^}ycONx-bgQse#&m2xPgXV`!fd#!6^sY6J^G4_YQX6$@ zt+*A??$CBUtnGS`ztSD*g-`Yxa7%Q%lD6SXTotVIBikbiqgdUJc3g_|V(4Xb!5*rg z8+~sxmHb$a&ib<4?vl*rJw6>G2-(S3JZV&pnxRS{Med}&ci3%&Lh18}OQDSXvC!I~ zB^&iuW#w~aqc^|)uAuHPM7DH~8L(F9iI{#gDG_dFN+m9LeC&n$yXTV6M(A{#PIP_i zx4*{yUw1G^ka63L6=Y1)CjF_3h`IX_m}twp6PS2UOX~=UPhwYt8MdRq<6Zv>xCFX| z{aG$RSY;d=STWKy%7e8+TOp@4kD}fSrDN{mBuIF%KWeKjFDBXHisUYa8csVgZ0#;} z40O3_0K<59)c{b`(DcCx;@`fps!H_4(5V!DO!*N^cm}0g^e)9nu_Y9nXuD*Cv`D^J z{)-tX8f`tF6`HTJ)mK2z%7n1IwfNL4aEr&cq0S48z|i%#rGQRKtsG4COI+88f-9%9 zNm0aaR;x&767P+^afl6Nuz&Dtcd*&FnySh<%aQ|Ln%rLp)p26{E0XD9EE+dm=0-Lt z{9mo7^6#;(2zdncM=Q#c{aUP7Kp;;@3qmL3T{CUa`xHT`yB^~&*1WprkvhqWXHtFr zLxxUN%TKHLD0FgUdtYI7;p#-n4S3nt%S76Aeutz}%a~J|xJc&}nMc1(nK{g@`sf;{ z{5&A4#jstc&Ymx%eayni>~XTcWyQ}wVZ76xoyWIlm$s+*gzb4q>-mN4xklPE;{$Bk zA(ga6r_v(agwY@M+nZCSX^q<^I&@9mEKEvB*)7~(?XPd*3M1=c_F zQk@>;)Z^|ja@+uBkI(uO)>Y(}qO{y8+!1G@Ol9*Xrgu}lFHGvuSd0Jn`t7YLZ&(i!pVOBf!U_^M=Qo8RswS0q%dGb6o!09Zs}W+vvn8|$R@E{|z6Hu2}s1^GwbvENM-aa_P*Mg8`clqsaD8v`FD zi!z}va@Mp`L*w5Nc+SO>(azz6;-U|`NeuNBX2`F1#*tdZo@2sg3Ha@zt)$F93sDB z`YC~hqU2;@#ip+j&scnVNKd!XCHRO5@IWE=3G=~~l?#k}R;84g1hy!E- z&6ukx!Z}7JAU5}`qh)#ZoN&SoMUQraF4hd+%w)(cBRvyJ!(5n2l9n@Mc#!m2p>v`( zhQ_Cl3Z1YE37d^SFOKJQsS3g3V~|=lEab1l(+G_NXS`ZCW5?_ae_t-=V&|eddhA5& z96Ed6{i&3ov&b6E_7HTN4o;FCRm36Cpyv?Bd5N&QKOlxo>QnCNuYZ;j?pU&_HsW4p ze9p1_ZbyA|(%3vvh1V=mvP2KAaj=A}FG0U-*EV|YG12knOgrnhed#gA^%;s+zEycv z*$W5m=1xhq^jqGGeOBaSFz5+$HuhHa+pc_!*E=MW!-H&pIc1J67jqzdc)W!FWBZ=A z_cg!yTV|gz5r8W$v`+K#5#Flf2Wy+5j`WTRGy5>4gMKluJHM^=7amNdlJ=5vv0_b_ z34c&l9hO?pz@*O4QD?0uO1^qL>3ycCrW5^uDej>#(p2ZP`#Bbb=oO}yv2z2u1^&VB z8Nh^z^ixfuGlg}>E4N+o>OIa~V3(mlPhTjWU)n+@3_GGFOeM3Qi@NLajSiU6w8HkE zrW+&a66Q-5_#jaim~KA)2D^A#6#=C+GUrR?Jk88Hklk&+=}UpE=nJNrGT!35P;+dA z4(F8a6m%LA=6wutfKx13EMb-bX9h$Tb2c*d69gwaE4F~XP?)4h(9Uy0EH^oVGdlvHSrPRH1Hx>n|J}( z9cH-X4C$2UnjyIE;)DVM0{8xp5&@$0S@Ztii6&U+?{tY!43diMkEcw`raBG&+xtvS z-qw>r)MoQ4-B-Fxxw2j2CfYsAl?CpQI9lBrrJ20zpJYJvAY;AA_N%?mOv>AKp(S}L zw+S@w`prZP2Xj{DMLSPlGaz)KxDq)(YI=lDj+(sCS;=#v&F}EGw4YqOUYH#4g3##6 zf)`}4@$Zqx5ADR+twKN3LN~B9Ox%lAW-I>r=)=7d))_uSX)o^5`x~bbQlakBxMyqz z%oQQ$pedLOg70XTE=ON|e084pnO0lJGo_BFN*#-&j^5M zc0ejFPlLSD>9Fi7UQFT#Bk3ys;a#VSJ*0|7*;S;5cAjK+`=35jba4)OP8wnNa)Rcl^@AkbUi~E6gKA}U$$giu_fbP zG$%`tc&Czm`2Cc*5EzhLe{~j5n%)vMN~?rpmce=oqx{?F(u}f5%^(SdmsANF?-xS{ zqU3oD1eFSx~ABtf#jS(5YJC6@1T^{l)gnjHTyfaT@* zM2_*Rhh@T?gg1;n@gq1$g9ehBE48Ao4}jqJh@FzafOGw|5G!3mtV}k=lt4mP zCMQIm+FP$_cBh}H>BEk%$c1OxVeirMY* z<_U96cSRf{b)ZAo5k4y;uuYTx<4Gopke7p@D{!yd>|D!36C7^kaVl(aozh9&EU*GM z`gYV{9a>9RujNXQS%rc!=*>{T(J`GZ>s*@e64|FIOWphck5lIzPy<=BuX}_K1L~_RosJRn` zBym>OAWetoM<(T$)iWsxdX78w&C zfR*Oz?yUdVfOvHt2Az01366+W*EkroaD`$!xcVX$uuV#pYrLB2*O9U!A!XGIOUt&djBcM=Aj-{?&yLZHdg4 zVbf%VlI&th)~KPlNZ0g|LVT^uub!&))8t|=Yr08tSq~Vr3-wnRcg;a2c-3)!bhk`# zXAe-Em@xR9sr{T@s6htOwwe4`h_z@s5XX!IAK(|z5GW3av3 z$lsBByz75O4>Qg*FwWRPgQj&lp6+4X&KwE^Bwm}hy7 z-z9OmcTMMS*-o1y-dg4#WdY12SO84T0BFqs*r5O!wcE@t|WW7m9UXZnz%wlV9F z;|P!h;hs-mqV23jX>!5Q=5=h8kf-fpZaE0^dp}kVth9A(Nug3x{HC|5(}`@t^F+MM zIsQoYo$6-nNgM;}fNA^DXQ_v1nlJR_1)Xl-UIG;t_Mcj7QUXh`X{|ZLtGLN56AB7- zPw{z^;MOPZ!@|p$B`7du5Z#6dVT+^B2pa~tQoy0whWyOq{YInIfHRE_a}T9kjkr|!6g7&4Snfc| zS4AjJIv=@(fAnb*BybqNeC}YjwV#&CmUj_5rswe-m90EQHdqs{AXg`7 ziw3d5LE4!IPExD5w63~){MKa-zf6H@HHlr5V^R2X2@B@o2>~1s>w&i{4aV` z1lcb1q0rh)BTK4Y!AQ|R1U3U*igzozt2Q{Lm zw}H>5n)|F|ajg5McEXq!#cLictGTair%bTgQSpfnmrZ=2?00II+#ahj@D|Z>4-Q!o z2xDSTl{%eothqbnyTJLzQ$V|X=R4oD#hhO#UM{ZvA6Wa)ws3zsSk^SJX7)JC3)B&9UBE(+au3kMJFlX^!^%>izbl5{cNdc~{Db82v|@G6q7-aO?zS`0PCIHWV~sR(SP z7~ZIDp;oqnp_lNdD2BJ1r(%T^6WE#)*st-Vekv!hmtrIxBTX^>Q8|I#Ie}fNz`NIY z*B3KL(NzaMs|Upc2Xg~^XhlUgEF#^HShwh^1D@5zcFu8H8#s^~c$HdLbX!F#=R;EM zR~Y+q1G_mOw=kR!iQTI(WS$C)y}8V{ntThx`G}!+;jk!k7^hqGl3UXlR7?px9?=tXaET>n+~xkdqNGz<&S?x_gL)uY%-{e)Lcf;{NNk89 zxDP!+2G>K@b#v_54_a@%qA!ePQOMaL#)@~!J3#Osw*P_?`wuGxEwbm3#`Pa2T(yWJ z=fH@ii|DM=BKpSf5|FIf^Tw%?hvFvd3;vMB*_xPY~BPmJuPBzJPkrP=AmXG}XLnztBN+Uo9dd+oh0!qFoVsUC@ndeE!NV zK^07&X4T;j4L~r<;TMZ%EGUTeXflY zH{SX2RR_yf?IDmoC+*&<>~*-5vbWvKDN}*=tHa+;&!iR9i*oB-M+8kTu$#2~a4s`L z&}?Jy>bTtV)B%UAd#n;}iFmO?*jN0hByTh zmFHbT`IDgEnV(a^k1I zY1Q6L0;fUVb@`;jc8Ybf)pn(r#3A>Fu0Z2adFOJjHT3Skace17f3{+LIHI)n^ki3^}t7N+LXr_FFJ8 zE73s`d7svTSR&r1zbzxuC-0u(eSpybVR{J|MnGQ*@z6bzLz)%OTklDylO~a_kN`SJ zx}IL_6mgQcp9~z}(Vn*v*J$_d%I>}Fk=e_=hSCkv=Oq9(e_kPa%r4koo3j|B)0h{I zX1Xc-Kzi_6vL@QPz;VgHi<*^UA=SDNEh%suXXSz>5D1wYW@YOgZ@Ga(RLgYq{J5Ts8w8H=UQ6to z_6qD9DQw+4dI9zjG6`PSx~WiEF2eDy`vyxwJ3%vlvRd35)->F>H_e?OXpuhB=$@GE zNwhB$O&s=}8-bF>W#foV=izYhcXx_q0vYbD9UlH@%r-xK^oUDxh< zn2kTvnFD9qw##|5`Cd;1d*Er=Uhex=D%HAP5>KTUun^aGR^@{8&E4Np9`*F5z{a4t zC=P@@@eS?L>AnK<6YkoD?r^`i<TNnUr%usAoFiM)j& z(NTO0+^t6ck;vMsOFRIKTsZ_|VJt;k{rM5#TVDVH(lI3QW)ApM{Ih;yj3e*=MY~M2 zmzc$vbV#S~dn-LAbh=Nxt_n8k;(}XM!aDpfaFSPU^N?UHCjPi7YYzX3+!9I#GeJRr zhn16PE1#`%Snq+=y}4bC_1Oef+Pm~^w@kIV6D&VA8tCX2#r`WEb-HldDYVf1VhLT8 zFzYZO>RU*gsa{7Ap(miYPv9HO&p^Am>L#(b)Qo0iM2vXqvMc#@isMo=^Vb`sYCmGi zCOaIx!`k?mJbO(+Prat#)=5}qto_)7{3qmJ`*Du^R;;}}PYxwRm+&HLB%$+pfl>5u z8}ib;wMTIR>A5w3?a|)y+n2ce7z`12&K6=OVQxbGiSeKxxW>*Zp)T3y_JHM)u!HCT zpeM|QZ{j5O-X>bcn@$$fvWiaF6W!T^n8x*J&}*9I$E11QNrScwm)6t-^plSKXeAK`TTbzMBq zen81BrsY>MdkdJo)wW*WhXM;agBxSug67c}QhR@XkEp+(8LhvagA z!2f>f-88tMZ|2=x`Hski)Xu#45AK+IU#NC16wDAzh(+4bWv(J=c1-_t%rIgc0XD~} z<`zChpATwgDX$h|@F^5}&|E`MdR)$VhVZmf>mSog>(}+d0c%i|k!RUmGk?ZqlgJn>5Jq&hMpCsrdV1@sdhbN(Ll4O zX462U5S1YkRT^lWTy+l(qQ7?2nmVfcFXKHq?R735k*b&u3^W9r-u_2-Wii)n90zPi zziwlv9Up6UhGhyUS+tcol3p*fNt=cNS+orpiMFk^^jn53TAQ87c$Z6(dnAdHMf9um ztxH+vS3?|B$vv=MGnMyDPl@k2B!+Sr0gW>TL29R5%N!hBF{UnzwK?9$f<=v26-GYB z&P>&-&0^}Bh`S;im0?Dc^Z>CSTypg!f?On@lDdjzMd3=l6Vk`zYhf~1 zg)aj*k(rX*52qyY{O%qpBrAE7V}|6F@sIE-yDwf@G%{ES$Jt^w0gV&F;%m!xCeNak z6uhJ^e1Mh$Fjyyz?H>2dWiZARYei*Uf;c-H#}(2VQ6=l2tk>ZI;fxeK){*R|!^5|n zQ3CXOF|+EYCAC}|fBE}IJ|+-<5rp74)?duKN?@)lK)K^oTmsRnZbTU~JuVU9e+aTr zx<@L&YLU5LdoVrs@zDl;kFUr>s|w||e2+cRkH8C>EsKenD4q>1aK$(mjUvj8eoPHMVPInOd}UAOjWS-zgpvVtlHi@OJKuo$)!)o*_u`A&4iST0B&KKrs<|u0+aj^yxApg3yKV*YrZbLF7FgHe0D-wkJ)$gzkAfmwcjqCdW(f%Db=5l+rip zi8u>b0{aE(&ioI`{71NOSoAeZC4)|#_*JE`s$ub~hQx4;FHpD~tSc5A(&{UH>Zk%x zD=4p-IWZgWlhhI!?0IH9QL;xyR}T{L$iW2M}+IpV*Ud4Yc+!pH;w~HCobPSD(ix*?0Gs@IIe@NGyy5!=u?!$S|5G1B~KTc4csP z8fUBGIwH?m9q1-Yh#TEQKV*+(rhVL*N?kj{)c%$JKN>&euy)R7U{1%MB$dPlFi*@u zwGZ}yf9%=vey$clg7co>AJtsw8(WfRrhSUjh}Sf%PEV58|D2+lY7WNn6)60B`ql1c zt4!IdgYf2Mfp>-L^MidRctU4j<=u-3a>Z&|OLuq3EhsJKWIiPoyjxRXPmrCABe%do z^PRuo6Rjz{C+ptdrillI)?zK3A|*t{SPNW46hRWoo+D>C%2%@K_C`FVzcXN8+=E= zKkCeK4|pvJL)Ud|mO+{Y9fcEQ`4L%cB^=-NvC692hPyv;L9Y6IyuvE3ZMgT-F&-8A zT_=U!5+7GA%^6oD9x%rZ!UHCABsVs_0EK&8FWHYl%;t*a`RFoC=YUabbA6Gv^W@ly zd>TJa+ci$Bx_l6xTWwSLJ8qCf+lT@NXdVNcRf)G*WQ>HO29+08$7kiQe~CjAUtPQ^ zAFi@bvKzK;qp3;w2%o3NM;FD$6veI@L>RY0X$6CWVv`G!XJb$sA3capwt)pPJOXIy ziYlplFrP2;E@P@}vBiZl?EB+a7e&4fsW8%|UARQFxMJs;3xpjV&nYi|JIf{)RP0YIL^_MGh7HX?vNuKwcowi0weBsqvF2BrOI;f(>`%RP-rLK~&-22Tve7Qg`1Zb`W zDsh`csl>Jl<9e$N7=6!PB+yk+xJo_JOY3DNwW;R6(;c#$xkSe)WX)px7FQ%gJ#HUV z(YoeZCwfWVnrqxPK7vP#T=1aNij|k~N}oE}vDy~OcSLlj7qMAC4RuOSGN$d*bQfJi8~_xa>VK1>&2*+;izsWM7a>U;xF2ik$VNj)fz{un%I`{F#kZtzw7R zpbEX42frmK1$CM&>_OxcBp<3mH=lVZnZYInb&>tcI)lSl#O?0$Cl3kwFr?E5O#qg>r?0b6X59tl5iXICR zv9!$dAk$nN?WUVo({SBCGo%=#ew{R6H`}EAHh`Ap9PcZdMh-EiH`Z^ zR(Ub6tf_P~NNNz~m@8z{m+LG-m&?^?+KJGg%73gMBm4&)HCQ-?4%39RBAe^zFy1KH z1Mf}>KS|D};M`-%1E~be@WW8U#{{$eR&=joL-4K>i6y&&yG@?NfgMg7s|%l%F#$gb zZJF0pU7XG@-&$=>S)6J^)EuJ!ANiN4OtgDYd4gA(UMG(7+baSl+%Gn}Ahv7}6d~9% z>9e7$^JBB~W6O$?!|eB}Quw#9DGRrw0a-}@Xa#&l+O{KLTJbvUQ~Zk{lWW#LYC~N! zL+1t<1R0clAg)B)?}S1^@y$`3xPeIN>QAl`Ch#eZbO_gM{3h4awIffBwshey&{rt_ zs3PW!S*jFzz4~p8?&M}+vtTX+ySj1gVUFG??**gr>Da@3C?A>?LM>wcGSjA;mQUQJ znyDbJAG>WX&9sB}sa`ADEtD=^tJ<0!Ou_UBGXJh zbOk$YW$%b4+M#?-j+S*twwwzR!Toebsr=h1g~8XJ!XFymAA? z3YkijkSl4;x!8S4=sXFPmnvBx$qAUy3Y3;;b2kh0>ip4=e7Ss^`2y{hLteQeVyHsH zh(V$43jvMLQxqC6pU8_V2DdT*xpPN27gm7^39r9CE$M#r!}R*E6@JiE+`tOq_p3Kp zk=(a43Eq_OYC1=FxNs)CvdH}Iryw)9_f2bARzA-E-MdKOlDPEaR-#=iYkN~p!!4ZV zOng@k_=Kbt4GjOV+~)HG(7&e4KSEwj+>gp!ds)r9Wjp1&J?`iBmX5L-W4}98t>6{G z%&M|i$aNyAiHE|C>2GWXKkiMAhrZZckA8@^ApL>^%RCE8X=WM)l0?L_t) zC2OiqBac~A(On19)S{eHpg$zk;j@BR{6*%=w2*P+7@d!|um_Lt)}xUhzYT34KiU*N zpg8BFpW)QKsBzrYP}NmDQ+ayv3~cML7|IM?%6?Lr-*!;GTTLUNf>P^&gkM{>Cnkp8 zCZCVo9+FJUC*&_*lWYZT57}(rb+f%pxMah90;zWJm0QV0=ml*NNjPm7>|lJ_h!`ku zS~;qT@o8wowa5238aiG=fA}SFUiuu?Wp_}3=u2vKt~Rj193Xj zt``rr+x}n^06Mtr(YHR|6$`r6g8u2S&ev!qZOFC-6F!ukFpKkiPgV}g7)sA_p1;=s z>@!B{;u9i*&X?~MyNn;h~-LE5mmur@QG74Au0J76blZjm|YiE zv%NZYfz%bk!#lpRU3DGv2>S{dN-F&2C=kHD=OJYhPDCiAmJK4bl4dE(;mXM6n8;a} zvY@6Oc2^=KK?NKAmO_yR-o^18@;%%Ec5W$uhk!c>U`!(fN)~{bVlgz@1rR(Iz}W)eF#t&a7jS?W?aYz0pE_wzev7Zr)3%&Vi|Yct>qXID z`wxlhiUMf!PIb^SL&P93346Fl1)gWQWeP0mUs-1c05mqPm`R+&k$LiDff=8cM{j8n zgl{QlMksT_O@3g}=THx6>!yVjRaDl6FBQHE2rl2ni@Ak7vDI~2iu_SlLoydY$F#lZ z^gQD4Y20GUkTWmGG3rGym9WdqPQtm)DjkMg%va#V2a80P7-!XzT;_>T zlD@?hQBmo)gO}5Pt>*XqBq!P)61FKltE8cWOt&P>Khw@U{)){U@I;tgT^tJ*o4+uz zv%BHxe*!&WqCidKw(FQL9En=~`&_>usqI%%Y7!(RVjH#56B)g@bHA-f3~s#ZpQAUT zYw943G-a*`XMapGprb11hFG4$AZ2cdEEMF_F_BqjfaI}s6s1gFR0 zPrwlY{OZv%1m)}&C|S62Gby)LNNy3e*;9bKI^A-QC+72^Oda~3Iqwnro}l8-k^Jm5 z`GOCa5#PtVpoQELxfzU%VhKOwhvfsDm9f3^|v_(^m73?u?Iusadh|cMm zz^f5ixu%7Vhc#?B%HILtZ|O#VlPUqtTuLnyZFjO$h{X8wyag_-rEVZUGeRh;ZNg6+ z)7mt^g8+mUGb_QJiMGoWphGFB>{MCBYeh^OzQhit9GIaNF1P)0ZeTH{Wor>li(rY} z0}(Z%C4@3r+uN@*BWm}%A4!12yG~|;BWty%8+BaBBobFU2k0okiM&gAL3@6yC%69= zjO;IGnLs;(hEA>s*5RVysv=H4Mpli*+{IUwGp1P2(Zn^whupP|-=h7o>Y0M=rnE9@ zd(;iN`2-~;3HyqKb;OoUZ|Kiq1ByRpE_OI_PlwnJO#m5SHxy*<{)`zuLr>Kyn~i<= z8y3*x0tkN+vH<*3A)lrP%@qq|TbjvPROEIfG@$Pw2n5_+JwXtO#*pVQBUNp;4>xE9 zEo4{l&s4k0=n8NON0mj&!=tY2waGy`2@@o#=#PmI9*-$I&2@iM{fO#XYlte>K6}?G zeN|}>l`gjeloqr0FZ3h#0QrM4+Gj)kGtJus=hAGBG^O3q<~&{tl9$H)6G&}^A1!9A zWF|VES7K9GVJWRL_Xq&#F|u*(h>1;sHIZI1XU(HWIvU1%uJvHMRjAnZ<;nUg2dKLz zb5paVdj^f0T77$;H_)dY>xwQJ_@a@M3)yj+4Ll5#58eipIx0glTHkZwP zsDy{UK6L1>Q6XQqo{y;M?_EEhC=lM-@;;9dzJ4U1ja4fBV>Y1Pn`%2xQlNdld?xu$ zvmfSKgxKO|0w+~ZatJINL(Ps@a6-JMITplE`LD@|R1JR)By4+^(wx-mNzJRurMk?g zkY!>y=Uw+(sSuX!-gVE&+o}#|-bZ*d4_qUL=;{mr&v8qa0PY?IcSs7qOu$X-V1tsv z9!`T>YJv2}eg4ElvOjg1UvY%mc5NDXkhcY%2I&?3BTZnp{P4HRMD7ZjBdlI#8je-+ z9GkkoU8p7@eIx{(;im*&R^~;viaZuluNR;q%O~=dlCgLRQJ%SD0fmZYBjBY6!`Dew zsrV{vW-=B32=deRgNVs!eUW$lqmpYiF87>UTW+$Y%N1Go!Kt==lXxZFUcP}c*4i@6 zxzfrIAEMP|uD(G^*xg|vhh9;bQde^I3fbEo$ zUs{?~l=Cx{{z|&id4yAGrqd_dCq>?;@r3_EQD6dFxZ}##T;E;XE1ylTIzF}AFq;&$ z@i2-KBd~py{o1=eL7>bIKbM%7%AknIl`~+#b7Cn1q;l@n{4CY>0}{&2k$WA$BH~A< zmrm)m0znZ`Xr{S1YGWfP0FDX`V-xlCx4MyTZU z1!K?!uHwMap}<36#DKP#KVHCPHk<=w))w;1@*XnEeMAx>CM z_)Ir!%^>%UbXBmO(emD_Tn{LfeHE|@III@<-zYGnZWTuhT=A`WE4w1!ldg46)f=dk zbE>|DG@9NduBTD(J@Neu2BZ}`tqR{pe}QA8k9X*+vm?>I+c>*ebkUKhRThehdxLqL znQH5RD~YL1T=>;=bx~6_*Xj*6kKZWd%%JEB4qxtR-smsJ8<$H{CCqK?P8hbIB+g3A z?Wi6nd(@gI__g~kb&I~2v$SXQy_-U3Cxr}}M25(UzG5+!Fim`br}4SP%XNv!iegWw zOk&0JhEzjqH-OqD@qnbF61Mq4LF1zY?y$?~3Z^|=d)LiiJv4YCV6XSC6~bIqTz7VN zv3B&zg`!O#9^9~pFw=uH@%;_^d9OA(eB3Y5(JQC2cvuksWDpvRB)mo9B-D*t_lCqB zB5sQW2TcM+rTdqVyCJVfI`G#L7?Qw2nZWN$;BpBZmI+)Zfh#4jDigR^0wWSQGZT2N z1g?|7P$n=Sfg2@oQzmej1a6YR2Qz`EOWP{KSA~{KSdFFS&5+gbAb>f6Fc7=7s!= z7lr06583Z2^A^sVvuxfmVK&XJ^Oi1~zj#q~Xig}+O!HQ2-V=sjvt(X6WhU({OBOGi z9|Fj<`HSW*zD>$k80qjzsxmrLuXK2IXzBb#HxZ+8MXPB;#XScm?oB)+F2pfXJu0)*%%lg?@?xo@JW1{e&p-hiHDqS9&tV2(3*Glf(ti2j+D8Ypumo|2qokE!KD7$u}XMGMIv9TrM zrLNQi4O+5oSTFE94KS~)K-1oQU7+1B&~ReEOD)YvKZNwdJfsV~Oo|Sv4;{)q<)1p2|57R6Br({pGh1gq?owE|rp#maj*{S9ndaC~16n<_y^SpO; zA0i-c2U=otQExx6?7x}3-=RYY%U^?4S4X|!k0MLy47p8Y(p@&t$aJagsg z>-QA?f$%d&dkTK<^E`akXwO34_Y(eY@o3LF^6nO@IZ?XgQs-kvCS;Vv}-!=o3g%_@_svy;Q8Im zsxKP*`v&+u`{g;o*q5K;KW^-&llF_p9@1ZjMs^(;A{Grw2py>hfY$ezHcOp*9vdXh zx|hMu8fcHFi@-1XH(llu3G$ieyO`JiX`UA`Zwq;_`wn}sieYVqzQva!c<+_+rCCg!D+I5CVaAL|L_ z5@QL<(!I_i3d9(3~Hlb6j8e^D35tH;J~ zFG2cgeMMEgt&XB9T0*D9_kG*UO$enwHts9Y%go!rkOIl2KU?C}J`;g337y>J_tD%@ zWtv`P5Xk?AWu^6xg-(?tu%1|8>|)9wJh9j1eU}dsS~=lixjg4I1QfO*i;JCxh~Wo9 zTbHh-9Ubx2W6@_ni4MR4&!Lq0g{BQ(;$V5I(}Zm>hX=)M_E()u=QpF`_1f?^w)$ZA z&E2IOBD>e0X7$gpa6e3$YmS3ED+9M*Hr%fY+)*ch%YKn%Pt%Xl5m)TUAZb-e!BN@T zrptzR@C>1=OZfB*Vicmk zKxe7Nyv{(HCj{JWC886wCK(@BVzx+tvN)}#4L?OXJ6p~3G*~)B&olK*A#IW`Gr?Z| zTB7oF#0DjF^q`#pI^ILipH;e#haQ=$))0#OQ%cNQk~8@@$%+pYbY<>4ll=S4EYy*t zV0V7`hcI7|zLuIJMXVzXA|#-{1Y9ss7FOIp#5_gCB~L|g2*-mm>+IV2y}I#vMFnRK zcsq-HniIaDV)c-4AEgCFPKezKD@JS3gBqa2p~5k9uCrp?dT6BwH#0V~$5LpE@i}Ft zW!p6Bply^M-Hz4yjFKNBhD*d8hMEdvOyeCtRVQ0#qU1XOT&*@PMBiun<1rcC4CxxP zfv&lQF`{Bc(dUN=p5>%sgSL#N0%RK|EvL2;;7zWxYb4(=` zUVOc28Yr{AqM`!j7D-brD?rMNdYCF;bS2E5jHKI&P_~%4w;bj2r_w z4EJhO-T==be80Jgq**Ihqz~*JGaLZ%%7v!aX#lHSVshly5kdS2s@K^)&LkytQo}(73hAvzcH+kBAa76W+hpEEUKOvF`@g5?+jQRU)3=$t9p$Ya#b;ix zW|}ot-@x0CctdV1ICv+!lq^v_@2$ZF+kV`gR!=aum$D0R1U<^RO!Q*8Oq6vq%5*(P zBL+Ukj&8Ql9;zoOn~1+kgkG~bikm{;XyUZyE%OPaGunl+jNLiL{HABk$XUTqWjye? z0s^DV4>JY$G6fKEheW(7qHdoQuyIz9x~3t^y0LI4pBSz`1J|6It~hWnNW&d#;Z8md zF8xw*^HkuTphJ>7(jBrn1D6hYLn5?8sswKA=Be2|q4jn8d%Ed;-hb-vO&RbP9|L|_ z8vF#?-_z;uMj=^_?{BUD%oEqYEK|UqLFs;>{{7Ph1a19iW5jSW7{Jd;gm%nS0bC!uxh@;BGZ%G^+;HNtye$KIa0WDEIa?xhj!YNO8)x0{xv{j) z;PT_O6U=vDoWp(Nv$>5o)LRG@mwI3k$nnhWy;QZaKQdIY-9W@9p?f(5kQJl2G6!5) zpT>m^sp`4M;6fdUv5^&%1)@FQ{Qt&t?I7Qv68PHl;F`V!ZSL@;|B2^XLi(*|`8}nl0sma7TSsak zzp#_aX^p>Sj#O}22wW+35W|W1}$&CjsCU+Yk_kfoFf(2dtHlNaS|A>zpYkoI?m{#)*p%2FS z%uYT`Cii_x}r2^m3oMN3<15Fd?{t9o>=F0DB6)IjGC9gL#_THc{I4ie`(GW-I&`C z;UlfZf4QgCUoKtO3gN&HMHQBh_LyH_I~{}ZNSI5>l%C%QsFP^FM4;9ZZ6g6I+AqjX zmJbu@xc-K_o8PjDIsRBg4+qiJxGJh{J+a(#y4$We2P4zR%3p4?)Sps*@V)ZTSnc72 zIk16gkT8?Q=?A*_Zy5h@36L=>M!V1;QJ422j+Vs5? zEa0imeysEoZMTDolJ9H5GCqCHN&P7ofjL@RRqBhOS|pngRiy~d^5}PjhEtKZ=BG1KyXR6Wflva0;$SIWe5 zOw`I)I_Uwsib7?!^#`9O+FoUqxc3G!E(f(qUuCAD*YTyP9F8Q+<1{d6PN6*vr#C*> zN_fq-G34YtKAzxiY15+?D;rdtLq|O*J_-wlLySX=Em0l%B@2YBNbmoS zK<`X<&wQYWX47?E>7GXhO82BAH)!M`^A(NUtdT&}nRm2Mrg^911IEsckyL`YA>Ph! zmO{-?O1lnuxAvFCOX>(h8uwLDzN1W+FgqB&ijI|vftm#ay*})iq27vtyBS9X0KFG6 zGNtsZ*Da-IY^xO=g z&P=4k?zjg_1n!0@cM9l10om)J(q`hq1alkB51JWdF!zxk`r2P^*MRz^ajXPo5uK!& zyz9Qk%u{PP5E#B>{iDn{Etva$=@2tgKJ?6vdsE|qBH;lxTqf!~94P^&hZdMefoXS=DHILtT>ma#r^A_A7fzFlY6U%w06jH;o;dZXz8ueY%jJ-= zQS7E)6L+i$Q6?M)K)JY9*YiQZWeZy9tb;OK@v2f)<$v?%G=?epT|6AgDkz0ON^j7* zYkmy`;;jEZ=}3VPEJ6K9hHr#^p<19{K6k*&HKXE&f1Z+*~>(Ygy2jYnDq?hZzskMN5y|*mavrjq(7xkwvq)tz0WZton7ilE^ zBq62}ZU112rd1S#_LB9@1}b#dn^@YZmi;8qw6l(#c+9J@m1G7GERvf#s7mu>A7PHX z>o$VpiQdIpXso<+qyN&z%F8$UFK?_JLFi9ee2tZtZS-G8314$d$di|ZIoHzva#Vi~ zuc$LSn;ZccpRly<{}$bXe`x(UjSn+N%!l`oppNq3L}LC?y7^zs@^N_hPo7HSA?x=J z*VtO)9H+)|7f05-5M5zu>Ea51$x1|?N|#mm zOS4GRr#WfMB29lXpN-){_NVkLssNrK{j)*$iMDt8rI9}Kpkrk1h)}vpXKt5f; zWRlTF|KktwS9F1%cE1oV%I9{pR8Gi=t`2(El*cQ5?B?eDt+eNhef&u zs{WuCci~(UZsSs>T9FmL9j~08s-5cI#o+SIalgR1(1G)1N50}S_X4NFginHm3W(9Y z-)A2A6*bR;pZ%jFLy3*ai&y#9zl8Apx2Bp{E5C6zuaUdymrlmaYMY-7V@-U_7ic;Qa?UN{2qwEe~|fB}S|QzrHc z`Sw+!bK1T`G>FKv6L#UxJ<@dgFnB;`lUL>Q?_pozCflmXl+YQFmFy6pzeY00;O8`^ z{Ki0Lcuym#;DKL~8~>jL#~_KzHL}w*Y2=?Z67K{wRy@@?_}=PMM=^vBU2fmw(+7jf z?ef{#Q>7u8rHjB<^;FHF|Xoan1tSYC{jYOqrzh}(+&@FS8peG`9B3KN2 zJouod8heqotgRL}71z8rVV3ae?gc||pW?7eU%wzd1PRlL+DbVa}-L_fYNB7B#uhjb}Yl{lm z1fAyaBBjX=nfG~Vs@XHc1kbaL)P{Tkl!HHZp>&wXER=Th3l~anfr52{-7jCo;5{|* zUH>HS`pLYFOHDlJU4JHTY1CIqr^wp)My_;LyV;<>UFJfVcIaPFRPtat@r|0e!^|O3 zqU}kE%uxOjjqEgIHS#+e>8v7=U&(orny6UD?n)-NUFC34FK_8c_*mp-V@%wf?Y?=E*MC|3lqzF6Rf_0u#`=WrFZ~FN+*mEwOiR1+P4LBe;GHbxF73 zJY7{?$hM^oALJj?hOtD7rOF_-fJECH8mVhcc-bt+XXZ;%e5*OY*$*r_mquHgjaF-~ zj$U^5cjMra$X`?S@O1URHTfGwO&{|lvOhw0LMveBL#ISO9Uty5m#Iy_0h9<3TR|aK zYugNgYIkjtv@eBb6oU`T58!P}J-wQ#SIQjf$Ys_)@=2GwoF{`n9E=+7%nf(c(m{Fz z`A3oq9WQFL3rEnyP2TdpH2>tl|BcHN&*rflEe%OVS*DkGAN@0S?%Y`oVLS;lJ`9kb`=RgyC#w5L!t&d?cbNXv-O|%krOT`V$=ODB zsJ|!()fwjPFG;U)4OP1qs5onCdcsVn_vjiE`nZcZ@jTl^nozX!+Nc*oHYJ_8iUz@> zATr(Ax_e|wtJ=`D7rNu%V!5r@3zN(Jd`Le#5EOm$Qr!=+4mxD+#OTlTU^1Xv-fq@6 zON`N&MZ5TM0Ip|(6c%>RTWfUM15O)6Ff>W z^~|y7d$r~k)|^V1D)U&;q9<{R5RT4C*QZCj+>@>mB!t@7T#eYgx5&izOI7^^Sbw=R zh;Txmr8_j${oZVOc-}=K5AQEkM8itt;S!ybm`V5-{gZgOERVRv`yzSx!$Wy5cPxY0~kbdAE3aPMLQ@ zc>cnT{L%{!{f5D6W>IFtl6TfI&MDHi^RrGcEEgkJwy`KqV{AsGyoEin7ql+fnKF44(C$boTKQ^UyT66AV%SVC1+$0(@R`zSaIf+x?@UDt=xkknS< zH(sY*t0i>z^z_eJB6@@#nmPmsrPXv`CWWU5DH`V8c=NoulHx*AL}+Ms89hBc$Ih#t z6J8jS6hld|5*WK37?LvI)6;5L&z(w&i%D^a6xlF(d3ujqx;VUKJZp7%^V2@jFHFgk z&sa)V$e-SxK2@ldI?C75B*r8qkI7Ux(#MlmHGffP6wxDydQ67L0Rp*}D)98yGc7Gi zDtr-%rZbM&)#>Z$HD%7+`HN+39-uZ;NfQB3RaR~KvAi1=FAe#_+U{W_`5s9coFoFy z>*-lLf7yIg%MSr0L<)H}W`INrJw2~k&`Qp6)yq19edhWslKd{TxX5sct){^N@=z< zBD?9`Jl$oKmVx^^vf3!gMqQR^vwRQXJIL>20RJNW&i}t{-aFs#8NtI+M?qKCcDz~Y zAZyE*NwR@0frMP$rs7cK8KIviR&ao*CK=1phzl+gBj8<-<>7ylyitpVv>f_!qj7w z;{uW2o}PZeIZN43-O}!3vie9UkDE{`l<&!BI_se}<57M&d%1UNaPgAxlF5OXf_GeJp>;96w3sEsZztAU6A7LHV)YUBu5N!G9ae(y#sB z=I_=e$IjoPrG8Iu+XNZV%~Fq^SpiZ{8PEb}KznJsm}Mz>vie2`)a?Z6=*h&(rbf^IHZ}797gM9x|8{Eh&P)wKhUhY+ zXoMZPzn<9M2zywfkhC@I0KL4v6m?{t{I7Nn%Qe)n~X{{3E>(**zZ>=bDAg zOw+RlUiCY$ZH`Z8p>Pjh;j#?ks%5OWYB6%81zC>CVuo!0jC3Nwyk2SZQvs6f;Cvij zaq`BR&+21=qr;mct5TluIrZ_t(Zhky&|#_X?kVOiPv3mJb7Jt`o)R?P^SLqVIqrX@sM90QNvH?K&4f+x ztfV#n0F^p?1NF1#NFs2zwd5*{QErKh zZT>WBdU@~I#Cw}K{*88yUUho3`AyP#@4)oKQx!G6y?2Q5Pn!s`qs=cw&1v2{eyZljWSrWC@jlwihqh7^M#Ec;-Io~NT`rfeU&SCfsCkzj9T8Zd;qoX@Vn=eb) z=yX_}r0XwXL$#O8VoYAm`=gj16AzJU+kJGT8Axv@3y_b=x=I>oync29Rf{`g$ z6Y>sX5^WofkT7Y5sw^P>F<72T9+6~xf)VID_*feZI61K_;`iE$Ju9!^J>Lo2MMHw5 z*}*T)ch^>^rSd6HqJv=Gr3c|?9mDg}U^vyF-s*zj8)X`*74Gd~=4JrM+Ir_ocb*MT z;oT20o$Z60sT`u)p7m>A^AsolLBzI0BsJAp;lAYSnn8PL_9vZSaqauq}$U1r5dZB5Vk(fU50qH;Vuq58K_j*k&Cnse`ok%)c1QaYQH8MhN|MT5myL@%#Y=} zqb2a3r)>+3;E*8I5=f>hW_7H_{dosDHj#olA>6MBw~MSwK$3jKv`Y*t> z#Z{VGR_{#Y-y*Bt^Mw18)BDXJ#gNSV&2hYB&JOH3qO7hu*eCP&2gv07j&BUB|M0Ij zbh4d^aKq8%-9(}|P6hmhs3)1zSfg@^U=;yvo;PeBt_5)OOeasHFBq>b964r4Cb^^I z^Yn4)OEvvuO+WOw^glQ*edj-^lW!{NE5@kpgrk>e>$Cc}Htd%4!RgwD38oedkSWCG znSERtcWW6lwTuy&H3#zyw-oR8_$~7Zk6+peB!;*O}JqRhEQvW1(&1H0Adq4xvK+t zri>^s)$Zcb--~_!Fm&UG=9rnBQP;;R$F|}Ffq#w~WF_f8rv|C;%%u(>4oD$62Gi`G zEJFmYmD7{f!WVG_vj6uekGpMnU*EjuAJNsN&>mX&rd%*fB}!s9odp7{44R)v(#mr4 zU48{lIi?e1>jCcdKC@@|OBP#xa0la>xet5*vfTueh)SEoC8=;{!(QNXC2~F9cg(|_x~Ia;vQyAv zkJ;4Ol`^lO%9J)My+cT_)<7#l6MkO#DnArE7>uu%c?&l0IaqEH3ZEQZ0r!tTAfJr5 z%y>D>?8b#p;vFLNKG@hGx*kzv|IfhtRAQOBi6qwrBjnp z)MUR?lOdG8JF8ZEc<<8zVZb<1L_2~4)cDS#KTHXA5DlwMjBhadT4AjenK~2d3%{eC zrn^K-3xXQ)cOufedqRdV&}_DR)Wu;%r};j=iMDEHebP9aNrq&Zdf8@Ojd{ou-_qNR1GgKbm{siw^Ru6@p#8ECb?`~Td} z{e14{!slep*?aBR+Iz3P_S$Q&^)-LBrLS@7W{w0VwK=w?9h-D!^?ddtqF;X2Slz?1 z{`^`Nckk@h1Jpy#c&2hp@7O)kx|p_WnP$Y2)?&X>yKU&nxBvm@lp0XT!PRLtwlA*IkOl2 z2bt@Knr3`0mZi{+tgP)RbI=19@kY8#DN&88;Gj6~+I~zki&>^!gu}v2Df#-A3*gt+ z&lT0hOimhwlR3!oS0qcrt&hPi_vnB%5>WYd6SDBj{lAG}`7njTYpVsH36{qm6fE0g z#%#0o7h<~ICh}#g1JT|#{4-JVFo!Qi7@&^)RVa#YkQxBBK({#JR$riI&6|eQT9(C9 z)rBZKSjsed(>k-1P3uRHBZk#|3_J6haj~l1PiZm$Ug?plH2@Upf%}A6wbv?9BRKb+ ze_>3mfU#0uYmfl%9J~1e;W(h7EA?2X=|o#%%L>b^g{9*lHivaT*tQRQFlHrP(SmT? zKJsi=7qK8{;|^zo{|TD9`A+K%V`4k_=V zXa|}-Eh{X;=3hJ+EK#mS$%|4Qm&JePGN@O5gkpI2Rt=5LfVeRIWB?Z!SDuaKa+#v_ za%j8(Nxs=RXm~57@cAU4ft3>s|AN2@O#fXW&Id&mQDvVfV~TvzEv3pA`a!hB$Uu9R z(V|}#Q%zp_)jVB;d#HgBOP#~V3I=8MLyf3T=ELZ08}FqTz0wY{X*h@2$cy`Dl_fTl!ubE&tfq&I>ylwLC3Ul1zk zG)oTfvqvK{d$X5XtBb*(Kg-Usi5z7y>+C4$VpGVr=S!p812GfFU6QJLa`5Zu%E9#a z4w%}!F6|g9P@iM?hD-F)0_x+jcu!VpM`KGoC1T6V2JkfefTbx0`7gs=2O7?_G_KBIg&R|=Hgq7^kFZ;+!7rG)^(iJV?Q(P6Oleykv_GlEH zZwC$5L3-e|(klV=bB?y~`o86%<-h&;O+ZbHVfqQPL zrMHCpfj4HzP!jh8qI0Bm0P<`5?vgb^Jt7wdsBVu6W8Fj7DBWC|xf#|tpyvNmW=Ri) zY15%7740)u>>2;=_)gnYb;`SiGwsM6v$D&)wsZVj@yNFd$?q!leo8FkchoSljLo4R zUd}wH=z|~19J&ZP9qG|dd)l;)$rn%R#%d-_vL9dBiT4UDfP#U?`Bq?TJojuv_&`%!3lYR z@RGUkjJ8HtpK3@G@_IKnU$pA{xWI}pgjXv5MBR!s(S5wFwU~pe{p%rpbUbr)AqR zpFH%2&63^YOSU_f*KEs?C|^iwbv=?^CmSetLQ)K^khH(Xtgfhmr@KI7@LX)#>*nl4 zswtWuHoe2;Jw^+|>IY)FZpI6C=`X_L#l~1Z6se`;1(gMb4tKu~A#<3BZPYzZr-e2{ zmo5L^9pB)%doR_7(PG6Cl^gS+VhCC&Lw~u=ho)IyG2KebzP+sB`$E_D;JX#-&Xy74 zzLHa4XARes`K1qHl=%u?p|yjbO{zpM1v!qsXVb3A;f_%zD$5sRf2G-**OG^N2hKy* zYj=l%Dxi>!4g*?3^CJuNnm#VLa&q)87sT>p7DrT+Q1=TZ^NBk@KIt%bh>cI=g5XNF zL}#!kw6{c9tdPuD9SxwdiAxdk0jzie?2vw<7-6i4PbDbG4p6_jg9eTo_B+nV&Umjs z%3N?w+8Y_kZ7OR;S@Y(1`H{AWhkEoNqgV6&C zY{d30V(Ub!SLgfEo2v5V%1MmJhCdWpM5)*)7)ir?$G7PBJ!BgP)H>IQO!OW(mo{9> z9GixLiJXE^`y}+pFzTzsEL~ogZ+M{o9K+{n_MSVX{9G}fuiVrh(+lsxEQ{{86gXv0 zj<2w3PL8><8Z@6Nn+N|Xf=B3y>;i*34YqKl#Ui4961{co-l8bT@;M~1lH6qjvWON+ zj@DU_&U1qA#-=$FVg?Omi~SsBqqaE2DhN~5a}D3%Si>S0{HF@Y)-$mJ*}4KBP=VO? zL<$zW5LR2x^_^?wlS!v>*B^F*MeJ2xFGMZ0Y0kNUmGBSos{e*LAvv@Z7^XKD`!p`I zFkLK$TF_}P=NLbqwGJcnxk}mSM+OWMW>Gw9?j*r+;hmsw#X# zYC=^NvG&c8{n?bNiPG;A6GF{4!t+qKPY+d1J}O+C7Eh~Ye>j*HysX|9KBf~3Inq`U zY88oGXtKH%^=_^v=`ms{z&O8G0a454S&5t_oDEpYq*aaJIoMfe)JI za81jeB9?Z)?jsCH3oRO{?}*D@eU_;Wpa=o&s&WWu@D7UAd$=5IrKu-TWlY$^-IvQA z?j$IxTwL&bV2-p=n#i%J#m7QfE`T!XC5p`?!Xle@QX zz^^m-M)BG%=Q#yAc||^i!&rW)kCyu)XNhSSKfc0qwXg78ef8rIsEv56Otg_00cGx1 zVL;bh>V=sXH;yxw!be0q4tu=yDMTDIMsadknkxf0S29WG zH?$PnW3KsVZuOSo>f)i7WrS-vRF)(XLVIG^x>lcntHi2pzmTfIK`IEgRE0%?>M&hWHiP#r1BW3vyn+5ajb^9FO*rqCc z%^$UhEP}0!(WyDk+_Y>mwW}wDZ?#O;wCI974Pu}M%9t8lnJwN*XUW0zzt9SnFv;6L zsCkx`u&c<}3Y&l<@8(%o684B47F@|K)>N~s0>6}2Uejf_UOL^JRjt+utEdZ@9F+oQ zlkh?6L0B5&v;xQ)bJko!FSkM|cA_rgdctPLA#XAK_;1MxmHN!GiJ{VZ=>V&b^|^}b zpf-6ueh=y%2)6W?NT-oN$-R8olw7)j3xziCh~%@4xQ$8t`L}pEK>D_LIY9chcsV5c zws<*U`nGsEK>D_LIY9chcsW4&ws<)}Ix5~;#~Fp%p3%}b^(dUdQGm8*G_93!Q$CGZ z@vwfI&f5X~Hkr4==Os3qx4D~Gb;>95_Az16<@M3!KFc=2Wakbf>yMr}a$3VuDfY80 zZXh4Md9f9iN$P%>VY+f4Q?o;La9CycwZ$jQat^qrzQvUPr#9)Py~^rC-u?sB#xmZv z6l?bdxuMd!(46_Ks@k^Om#>qC=v>RTTPK=tVjIJJowCBp^AaSVJL+QLBPNvj0b-436gFC`QG|p}SIt&~_lv=L-rr%) zj1V$~VLIygyawU2*VVJlZ9jzEeEgx@a<}nlcF8?Kb{2tp^o1Mu<;8j1eB-TP z?NXh6WFJ>LVd6AsvTVB~4A6?aZOlq><9SFf6-K@b_NwG6tQNgzi?ub`xQIQ(D+t#1 z55;La!aJZ{YydvAZu@~!`##>Ga!&8qg^JF|q37318xtCE3JqXas1=xm*RH&>DLor| zSUr=X&n9UrYV6cx9GxjNRSO1xPM1(5XBRT{Cv$02_>)d8m5!Xk@Ozt2v5663xCkek z8mymY_`cvR#jI!4Umd#>I%%(G)0_AP6Qrgnn3+z%ozpi^YMfX)6bSo z<4F52mcCsTiRK~~I%d6#GSpJ;mvGvyGMNr+jJFd;n&H&cO)2dG}hQ?E;w(p;7k0v1k5hmNcBMW|Btfd1@Fk= z?S9^@Q~k+iPlqczhwlzM_Pe@(Se)CSYPkzuhKmKp%nx3uI=;OEy5v&vfSmRP1!sJJg4#G@z6f>9I0Y? zs8N0< zGjI8q=gmjZ@Dy}I^Hh54pAVw36`HGFZ4(L?Dv|(fh32Xw62LwzUo~yg%j(S}q_&o9 zCUNaAc%BRJx90nY3gNa^{hwL`2YbB3^Vu^8ZXamCkk-Sb+LVy7Q#Gl#cUy*U)RkWK z)DgNA^Byz%f17l_dQK=?Ph<=cQ;A>~2IHq=C+)glJ*;Cvs7Iv8n3&5}Cr$yOkhwXs zozXPb){8|TI%!vB?ZO)A>T~CZPLTq~Fbq(({q9j^7D%pLoF2z&akdUYKAa9b{cySL zuS6$#a`299!*@2S2F;aj^*T%{(-vX*A-JgK2f4vJTpUEN zNJWVer>Q#bAaORCV_fR>`7=>KqSwVn2=(!?(G?=@_F^lz6%Eo23|wA6<<;ziYY-Mm z_+FqQV~A*wh@RjPjNMr~8uft{tJPRf;e@zdlMyj8GXoYZLw%q%(=*gIv6^%O()Ht| zIBlkgV`s9wge<8gqO){k%@l7o0zhwed%<~zdY4LST6mt&!t<1Ll+06+w?K17vo@)% zuW9>OLz}%Aq1-C|G)P*gK0$ zW}|laM#Gq?t`|*ZS@UGjYWqI2N^>?ER&OztK%%uqUXA!nA0)pnluDgr?GI$wlVQ3X zAIu!5M*WEvL5Ja@hsx_3;)Y|Iz`SI3-lgOGLZXTKVxMle?Eg@%-z9qh@%@uad!b_S z%6ZieaHs2UdZ&?Gianfpe8vHwl3?C{uEMZ_$k z;N#oRdm_|~$_{O5oDQD7D)=R&AZ^hQHM5ryq}Mp|2yWjaX#JewB?PT}sYB4r)TzUe z(chJYbX1M^G+fJU#fMi1Lm;Tm^fcrV*?m3C!vxXq_f-Uy+tU!DK>&TlI@Db%j0Hnm z+o$&2djX$CTKdmYck7KXdRQ}2+dvf^IK-i0-7^3yyUgF!opyBcKC+A@&n3B}UUzJ2 zkCpnp?p=VlmwaLLmZoM1ulj|o!nUdG?~_kp#TQ8!A}@7=p$yNaDi?J7cCD?3QAgZY zgE5fBp@K`upBRf!;TnXfGrr(hM%5vxhusp=;TtPwQQqke*W36~d~xp%PzxG!za7cx zMh(&3VtJ9G^`T%4KPMzMa2920#>TANpI4afKhCN`fdm(fqi94!x>9FL2%P$HH2cf~yd{0ihb(05fu_ZPOw=a4BTcU1FX?8_{g@@tMJc@?UF~`wES2o* zEyzg1aFB%A$I{#PON78|M#CKB2B(u1H#UV9SKBuU&}Pu2GL>H z2FM)r)N=DpJgQNj4;6k;Rwx5jMQmA8Pie$SG$P#Hv4c4szm8BxB1uxcRU&^WkugIc z-CuwwLHN_Ggx$Z8?vo*i5=m?bK1g5;;d?OAA!-pC;dj6p#1MX*q$O1W+Dx}VR6->O z1ea|~9E3Z)@g0Zll7u0S8wUH}h7`?MJhRxO23o1~{ z*rTU)Ua1?i+f__RLexo|Y(R(PJdm$zSk9fCBNszHUZkVEi1fK-6RXAuL0oBi3~p5S zb1(Nt9ajr%>rTSOv+`0+oBa@3Cww_B_K@h5*EX^Gs1@i9aPL8{mVcZZv!5m0$OWPOe>=yHCtYXmb?hAIwL38xu}_s zGk-cGY3y2(1E;;UFT?}nSqwlzQ`{(J72???Hb20$(K{5Jk_ ze^-INlRxtP0%P5J?G?%LuobJB*(Q05U!-Fqqze1Ueuy!kbjh-tmk%+-PC_>A^KCf# z4l(8y3jIDG9_<$1zMyS9RzLu{HvtGvIFMuvC|XjtWSIhMFc49B)>0$>aTi?hG7tnV zTOb#|Ybj_n@$zV-0V9Ceu$VD#*^LWh7AQ6(6e55wW3YAmTo)zvWmg$(OMsGWxEAfT z-RB8N1|SE1fh`gq{srVusxe@u*jty|*JFv7C$T16h%Uc*$r4|!WH6D)1`;O%xDA(J zLwb5L(T^Sz&82=lBqVt*@y{I-KgbwZQR~0?ddWlTa1t=`Bo;B)aO=^6KR*FM#X9Qx zWxN&wnjW(%0lhtN%h6+M|E=-wb-cIBH^Xy(PN8wE&4Z^OD~$OwTl+M29bPLm8g4Dr zc2lbFE;M?sE;L3q6&m^16Ml?8vx&fO*j{L4?J6{;ks^`M<^T z15lav#0IE z-GV{#a{B`DSV>s%!g+N|ZcM*^c?H&sEXR>UEC4&eY-^J;(kqV5U&fN;zh>NR@i9Y~ z;l4foeSo+=9v5S1E!g;fatw9SGyiXlp^4A^@5T_uMvMj{W8;IsZ{XR;GssyAmej8i zykPsm?z<)Rg13E)ojiMVOf&*`LA;D9JNcTzqX-A%M;pLM&nh(L5-(2%GlGAC6#g)! zFJ62D*D|!3jzf%_dlSZubkq=IkeCCp$`;Bnoh-7Mn2E##lQbHL(IM6&t^lOYFplhD zu1QJqc;eP0UZC%dWDMKTOeYul%`gTh43$=@TuVmsI8c(&Fk>+DXSr_~mQ8%R+PPGF z{?kX-=s3e&yyS+P$`|?;h=<6FbO)Acvc(FL?i#`ErpG!dRD8nUATI~u5(qeU#3XDG1 zT802#NAo_N%nCs6ZcP*9UZs4+1psgpomLSFl*Pa@Pw#vp6`bZUk!YBcMZ z0#9~o#^s<}#eR}I7o%SQE}b9GO|UT57^qEjh&2=`u@RVlO5B-%g)D6vNoTWx-r7jD zCvJ~tL#IbiVV#?I{S`v-Bp0s#M5iTyP?B+~kp@V)Z^=@DD5IPWH?Sbx9q-T6Vk_bH z(+iC!fRM*&yVN$@7|gbO-r|`HmNO~D@Q90&EvvdK>*}Q1UkzB zx&lAKZgSd9#pFo@`i^ZP>PE?F?Wru90LYUFG~NM{oE{{ng8;~r2$X}xm&GNE=gXWG zn115rNrai;z%U;Lp=+tKJc%%83qni8l8->FBUYY7h;xioAnF(Trqgp9h?FN0V4|3` z!nLxHj!PETEb*PfOrt9DB*L95Jv?KHfBAyqCATi_0_p`I;PC(>I1Ut{jNCcC*31}B!@+5+u zZwyTYtz0TN+eg*pNd&w=Oz2o6&kfcN5G_w4NUpRKAJofy(uEat;UOU8NrbvE4n-$E z&Dh&do#aV`nj*zjE|!eUHrFa__6@wGn0a&~)}rcn6c|ZW%U=4`Lltif``Pb}tlvz% z`+aLmVHgty)_utpbqj>8$s7jg%O55G@%@>d!ybF;XwWsYfrU4*7#DG#9p6w@6Xm`Y z-e=j(^XdlQx_rjM#S3p{7SEUWdG*%&qmq7*=AYu6lPsxgC3TIRdQi>s8O4_r)nesw zpnjE#4X#;Efwx_;xMIoDH3uZ0!8VU{$qh>uYfMN+`-w@veqs4-%P})1RBzDr3!SRS zt6h`S>lcb~x}3XV*c@I<@>!lF8LTNLJY^t;q%05LI(K343J4#xbcv1E`2*!u+tSO3 zy^-dM#dWt0ivGQRx-CJ}&nr-f&#u0FfVPNMa?tO_#UAjcr zR4V0#3~|GB;gZGk>eA&C_=+W^3&n@jbRd(`D_EuH)iIPY8t4)V%!+W=np)!AIK`@4 zvV4JMa5MQ>gPTdVLBwIN7m`(I8YrVdxfzc1&zmGAAzaejIJ zABv18HsLS$9DGT?$4+E|d#=8%q)FIw9c)96&=B8q?catC&X=*t$rAl2`F+!#Yve1|p3D0-1GbBLzRNH5 zb@p8K`zfD2SHTz9{A4$!dW#GnZOi-|-(h=cAL08b3&A@7WbTLnXAGDym;&N+Gl$<| ze)BPnm}#78Twts+)*H#ju%r``vXaIo$u2I#7-k%oG}1UVd7LpUxg6odXsjC*Z2aCv zW8(=M^EW1K9I$c7#*B?aHxA!8YU4>8PuY0f#BAd-T)jAELjHJ{NtK z3uwQKz8iff`c?Fk=v&b@qrZ(lAKmv6_C7zRzC4F`TnF$`%<}@zn7`0wo?4zJo{4|u zo2Qkhji>k%aK|%W0nej&io3z}-`E!&CXC|x9>owU0)na(m!(-H$@Aj<~E+1?t)n#uRX$FlTdX4BE%ZoXw~ zr;}9ng8zRT+XM7cW3~xiuvIB&6_jlUwUzcZ@N#X>wc)Bl<3XOp6?L#<&sAg!4Et#A z`}F7^HHHHqJCJS+5t4Sx0$5ES63B1bPa?ki*8Swr|G1x=&$y9Nq)MLu&3-cDzwal9 z#rKor?q+DyC?CVmX;d0T9p~&P^>Qc@hk-z?OMqfLVGTEN*Etz+RTlh6e)uR1LNshB zZ3nrH%|+{c6cl)z5~YE|V^(dowD7t@!^O17v70XtBaC#IbCylZfU&Tjf#zwpBiMYbiZ4+TL2qW`{0{-n--Irk`jGtrRBrhMQ*0 zTRacz&$56I1C#PNtxqANF~-oNmwd@FmmH7XoSzimoPX24`{e(=?;iW#_uW~seYaHQ z*gYy$Hcm<0qkhxo`c!LkEu5W)HY+BM({9P*G-IGl$CwB%3s4tDSJErF*8G|e+={eaM&Id@IgscLSWpl4r4hBM^ zEF=-=JlXaAM_EWB)cG-4$b7n@j)LS#gt)+hfQ^0>2p_TXBtqoM9y!jAf0IzHj-H(2W1RAn5Y{BnWyCl*^M?y(JeUuF3N$k5T z1?|qhSMqrR0C^JgnJFDCBH?cmIF-jmNesAe5+zl{MM=m2);v(^H zXZ!!b9wWd1+xO4uU;lq&|2&XWsP#t9#=?ykZXCSvkJ0VXZPDjw+diJ!f5Bw%%ss+h zkH<%w#t`1bwm)vKlqpxevS8`ct7cmJLZqX zrxUi048Ki(L43Zr5dmp=6ysq-LcU$R_a%Hw5r5C2BzzR7n5eanxiDiNb zYsvAyu_i#g^KT>X2NJ#|{7t^INb%p=)t~WyuU)ksr(G$O;#5a|VTtv(kKgo)if7EGQ9h;PDk*9 z=UhNuMRjM<1=jrw`CFxS5u$ak*FTNM4F+M*-Ew0*MRkdm&zm|_Wv?*|>uvMue?_gg z2Hr%!3|*pfEYszkv=k*M-}&Y09I8PkIpyjk>+Mvn%Bl|EhYHv5JAn#igsNSS%Nw`* zRobiEBH0;r?q-sow%@GnT4T3bvK6~IR?5mlk4wO$Hl19QnC@8XC^5-baqJ7#_og2q zvYCdeyjT716;zOP+2VrDQaOx_>JC3*2dfL|0G075Hbt-Fj{{PBH~FC+sY~Okgf2YX z{oqeTbrBs!TQQJ+kY30!KfvlBdZoKH1_onmPCn0|Y;)3PQNKZ*%nceamA?n1YkmAU z?k?4c&8yD#6_l%PumTpr=eyQh&Z2|ms+{)?ZvU|0R3BI{{3nD?l9z}lIJI5}q=rtC zmjrw|_!2nKCb6JqJMB^vP;T|AAMFDFR(`(J^#T@NFHri9!bx=+ei7dwjgNbM?x%Mk_O`^?fT~Fn)2Y(R?0LyjWe0~>NaX7R~}u<#Xo!*?ajYx zd3LQ4AnsEgSNrr&Xu)rJe_RrJHifvz)lIA9uGWE0{2MZ+<0J?1XhzLDxOv&|FEq; z8ppvkVHBb(rcWxK^xdf!=>A7 zom&)(t&zwzK<;M55}fBG$O%rBZZdqQ1*b~aaCZoDpAoNy#70u1!zEJd!$M2XZSzL` znNfcRH{wGdn-{yH!-Ct>tHt3rzT?^kj2Bx&Lc^sXBhIK($tnYgW6LRa7>^dOHfgg znHDM<5E>f{4>7~z+o$$>4CBtdq4Ok1GtC@pmJbMFq23)TAHWsAQ29XUs?ZN+I9DH} zS|RU%$K^M?rovn4TWIT5Nx$gzqO07-!s8E8wU&}D@A?hAcpcoR&zYcyyH0F7+{I0q zL7Qh^Utr`_?(?0(*YOUJl|+r**&nTKAhr4nO9%SE_Ee3pn$S-Q4%D_i#&px=)CLGp z&oC9Z*&AGeUq4VT76{aO)Y-j@`pcEKgGlQRp{xY@pR5~;`m5BP5Mr~dNmtG<@X zX`?a!BCTGV1+Mv|{GSzZ!>`?C_)-F|Ch_LhZ!X@rHB6YBw`Bd6!CQuY%UX1tx|YV* za3vg&WNo}a3b*pCCr>Vo=fxqCxG|m+|8yPZDx8re*&myBJ81(etzwb_D~IXwT!EFx z>6hfdO1oBpm3E~9E3LX`#VSG8^q*i>U!byV4PUy>S<%gRTIchj>bOdxZ+D)HM)zAR zz8J$i15IMCN`CrdqPV^-7d|sjRv+lkzN^&$jEypUY&+0muH1GvaU~gw5pg|y&td%! zckg(B<(vzij5_UZLep+x9M2Fu$pukSgoiW2L=29R<)lUZf@Pe+!x+CNEG`UU_sO+s z1(f<>Mv~UY8iHLkW`cGldak}R($`+nk4Zc6Mk%I}^U>B;-M^+SGY+8#-M6K{P(%L? zH!_d9#p>=RL$Ntqu~w=*RH}{D;h0|vaOm7ESos6868l}^4YfmEb1#eVtuAi%HIe|*KjShP@9kwdN$q9D z7-4|yc+_%=NVskw&N}3tU~|D(+crSV?n$u^gw?lbgnh?6(mV_Q(yD-2V9vrku^OS@ z#6-MG3us$o+M_R}_k}VNi6M){*K&JzQ-vpp;1j^ydxSm;N`0|^JF3U+; zHYf*M+edc#vLj-=13M0;H$A0%VoG_g{_IzujV2E$SYbaE2ckST$$JP#*cOjx<#oQ~ zmAnjd%SYuhIi)<`&gECf=8|vaV)5CQUlV-_mdof3>BB`&)SfFPNr~ ztBCwL1kY*~xYY6MQwu>H^-ap(yucy11m5VbEhq{sFvZ@rsA>%tbxY1+!0< zzFEzsfyN$xf~_1`hqg$%nqVL4c+E0MAqeN@kV|FjbeBuIE-^-7+cgo|f$1yU?1&AO zuVswL%U4_^;YBPgJuYovl#KFh>hP|2Y2GW^$*eAMkFP#-cyHuvI|bv&O7VRwg>U$O zOrdFo_CY0m(lq0%rb;YD^h;fJMejIC8u%m^YJNeFh~W%wkm&BftSczVs;t>O9Cln? zB*jQQbh62tk3>_rIuw!kOrr+DoEmc!#B11W7YNG^2eiq$SgV!+l~BF*1Kk6sx(R@dGAx4F+tH!9!!srG1{Qx1@@-Zg_bI)0-*QyM7FJMod(xAfzd# zAG7#&|LQfj2eez}s;PaTek>#LG4fa6k=6_0pGDFq_3BYBe=t&m_wxIG zLaWqTMhHj^kMEG|XJ%pU*FC;-rmEm(iHV&Er-n((hWf_VM0ffo$e+B(rBaqReZ1vi z{A$@jUtk64f#0vnBuM)Uia|}5AS|a#LL2H7f+T>Ml@Yzaff`{e-}8e7^pV`k_uTi( zqtKGHY?$wKslfU2r>y&49cxuY29$b(fbLsjp($X9Q0c(#xv|jkR_K!wdTA`whW&wr zPS&CHc7ZF{m*%-Ao9}3LGFClUaDCjgQ*MQ5cx5P%?m2wGL2 zDVKd#9$%?WgD<{H!>JdDjLhdIv1jW{u|BJQB>@a!#^OnaPr5Q8A%<3+gpw=tH=a;- zA(7Fn5@b>%?^tW1NtyCp#W%~3T=j+q=W(y!6Ow!Vtb)*^xsW_7e4Ow2kat{rL5|_X z729!Byg9yMP2L<<=0VJ9gZrzD1F`Xemve|=Zvk!`;C$1&|A(^7qRhO`l`gKfr8d5~ zB6-rAdd+i9!sdF-OG!kh=XLsK0IkC_#&0um=^`Zc#Z0bE4mEd7GqTW=RemBW23ZwP|BsQMzxG2r$yUI`$Vj*3IQI zAqcV}YkW);d`xuO>_vf2!o}{32fHs$c&;6u=gk%PTqius4i^_08I8ME41js^;v34P zQYB`MInC9+O0RP51t)ViTM$QVb3nr2GMc<&1o%C86>ARzM)7>m-ru|TL~i4yVlR6# z_HFmbRzQD^Y;gq$c-jh(v~OS%)vNw-JnLg>us+*Zc^38=Q;~xmm0)8$!8)DbB|AZG zEJ5y337(55SfUfO*a;@a5==ZQL2Eq0MLNN35?ECkr^ft9`-h`Bb^~6BLuY8{vw?>H za%lfPMptZAYJqYimkD_@#SxvR{;nFRhrF{UXE)FIO04IkstICLWrTTq#`r!nHB_J3 z7+sNOr|c;Cz*}#$vQyB%uB1|fOfZ^dV$dK+R93g`+9d1~L8DWrvRMpAs)ubdu6DoAuvzPhi@W$6SunIW$ZZCdMqZx~s>ouGD z`$KG4S07}2iOn}B^k+J>htT%bGWM`mt9jrhWR<`J%avPf*UhsFFm*m^=qk!vEs0f% zyxKQ!e?`gm&D$&zSUm3g*pWL!9f<~S$nGaES;SOn_mQ}@A`C0z(`dL1+Qq{dwA`g7 zW8sgXC)UN+u$o4YX<6`?imfA=t=K!maO81;)?DK7eH3U7=$Ay>XTj}yO)u%E+1gBQ zc0jI{>%B}h*I#V&tB}RA-->gAKB1Fq1y@wV&6QqwPr2)ySJHP^%mL3~G2pH}YKbW= zVa1c>K029v@E7W@ZP{Ib8yTz_5q6)1i5Xko@0NGggdXLC?nAK0&&nM?ODrJzetjg0 zrN82Rf zg1cl}wW(3IRravac3Og4`UF>ZjWB~c@%I@GW>9x%4X?VNraU0y!Z)Ew|1#9XmJ~*s zFhEM9t#lJ;xP0i8S$qhu#@5~%Ct`-xt?fr!gT?-a*SZqc5`+X=`=uJ5#=ZO%1bxY5 zX+U&{M;E4KW$jzPN$8{YfIw@L9RXe7>(~gSgU%qOsgdy8B-V*PTAg8P7@1>g3n7u& zF(~z;#B`FAPWO@DE$03}B!wwyS)eZO49H~V3$8YWW#x#}(WDz-2!8#+1_$QB2Z%r$7b zc>#90kFyFE9`GG?3N#9zOktJ9I5n5J^LDH_kFVqS8vl1bWUD)XkCZfa-R86Q1o{FK z*=ALG$}C~9+SR_p46<8YR^EbkEAJfyM~cb7t@BPNyYu<_io`l^ArGJOky7Rgm8F}{ z>Xc#izLU8yVD0KIatUtFirHQiTi%*@3Un^H1UE>~Vcwy!AZx3`DOJq5TB#V*W~MbX5FGCw_>;>#0IvMyyyvS2IrE zEW#$H5^Neb5Bn#Y#>MAKG$2z}CdHM%OPCaD#FyfY#uf!t6UFe0HVJIF`z45TTMR5?HPh9#~!G&ffF$Rdo4lO z`ezdmhV-=_;mwviM0kUV;gUW~L{l{baxA!LPfnQ58%PO+*zWSW!rhBmJv2Vm^y4(? z84<&+I$P|uk^W>M5ZaDXe0|<_XTtg{W`x$~JjeE=v|#h|QgFL^dBc(D=CiE#_jqq# zEr*@Xn!K0f$E?Y+H9#gIBtxuPJw%?Erwd9dxWWA}Qv*v~>uX_s1DG<;3T(-dCi+eY zY|$C}hpwt|aUUYO>TJ(_Mw`LRMW zoV?Qj-Fbk1l$!k{MN51c$E&s^ZowYtw^XBRW zwmK4XQY?mb@l_@(19@chfi^)Kh=2K3q^JWFdIz3{=d3X3Y=);%??PB?n%V@Xl9T$q zQ-(QQ5=inhFk;DoxU}UVL`2e)rlFRRWlN)c!!xv(9CG0;L&Td8Ndwm333gSQh-X{m z8x~{F^96=F>pg^=cdkqja{hzj$S|-@DsUv+eI}8Sze`AKCL#7D{F2w$M9!wIPW#=o zKivKK3KC)D!k+2H0JJnpxoTuk;@_0`PbJe8UyC8)r*1!L(3JG+EuUQ?i_dC`)3QA5 z&pCZDnl#!#GRQ?H$uhbA(M=50q5>W8`jfWk@o&6rE|B>gR;f?%-Xr)9tCM-xkP8OW z7Rh4`i;I5w8sg5*IjokYN2BZ3k!w>>EJU>j(bP7Q+k>bt$`_i(Mhd9(UU;#gj{6)g zsVDSo7J;ET?v7GdC-)TEgV_QLkhbphBxg|qG?GBrrFM1iPv9=))D^E%phI|^wCqA`Cb1V`pu8jskBv4`d9xH2Ti+p(i% zm$npE_pUM8#Yb3;z8G6MTZ*NoY)*snqBp03EhrWnN%}bCJ9#V|Tl5&f>~C1rfKuDv zGq!5$r87hbN2fB9-Tri^=wE7&F_pC+w8qBqF@tFgIe~Y^^}}aSFuy+@qA8Ymx)B-9 zI_ib|!otDHf&;<>fs8=Q7bF2W51w)Qir)m|WV9sjP9V7gj@Sf~~(MYr}W3Owm+Tv432k0OF3(!QQg>{be~6d)%)gb{ zs>^)t=rXTPEOQ6P`>K!GW92S3k@QAq6{37oQ)OfoC(9X1$fD8so=MaFF;G*<3$tt* z3?3?vGIaj#I&ugjuTS$W?Z$eOxP%*ia1bllKYiBmLvX9~1v?>Uk5jOmF@BE(lDGa< z1MrC!sTU^*{$;_f(vyaNVctrYf4*d=eKq{j%C4L=9qNaObt2Qu-$*8npJKw)DYU_Y z8VuA9^}r}{JvDEWIBY z?nREF?t7fkCS2%8d^$kXBy_jVihAg}_voCYWPIG*g}GsIxIv`YI+v&>iL!!5Cg~un zUM}Bhv6NmoP^u{TdDRFhSBkMwV}ZN>9bE8*owJ|Y;5PcKY;cJ?h{{usYksbgWdH-FAOD0mc9@%5&Jgs0YHd2yzxlGu1D_>ru9x)fW^VL^^4c!m%WHf1 zYe%k0h-~FuQd5y9tYBP~3d5++M2Aq;QFjdZh7FI(k)il5wQh1)VaE}6$&HJbEaR@~ zVxQbV#mdTUF+Qwa-3rNPKRQsabAw>xC|Mnt@aOhx>k%O< z>i2+B1XGQ`~(>-q_1-T}+J;#$hkJi{1z>w0CS5CNmFFqU~-%_^E#SE$<6|A+Mo%|B6n-=JWZ8LHjyN`l*3%5yYerBc5<-wtOB{ z+ZOB1m3XVrPPn3MNoVx=-)7pe;-dzGY!Bt2E%!=#Hs-oxs}UQ8)z>${#rGt-8xc8R zC5Mus>DjJOX11wJSGH|5xc6qg1ZJ2-nM5)EsB1*VWjS=^EH;^#&v(m&CTKUt3}ezc zaX7a_%^*nEIK!&(=qTVwLEL#H^``^l%2rPRq@7RfM$gDzv)}`#lzTBKA69>Sf<5RR zm>SQBQ@gPG@OMXKuLN9gQL)=MD)fNR=ye8HdR|}hyk23j?f>OV73kH&!ZMK+m}Q#A^e2g@gw*5^n@nNa=k`w3f}F0w$4 zMK#$MS5Vj*5Hpq`dmnQQ8xX1dfo@VQ&2w2AlBin!osVo5=67F2bJ;b!;Lp zL0?weM84>!G&gP&Sy$tI;ZswBeK~iX?rGQoB@DKG6;vsnyG8oU3%YD-tYsLv`z^XO zs7gHzA4pu=%N!MZf-ey$E8jrooya{k;$gEt+1^ zC5x<1xJE|_{aBQipjoiU9slTA${&GIYG!26pNJRR7PYTdxc`ar%&T>VOw^!i5ZP zv(X=w~M&vGGR^5)awq_qwlSrmcc%*hfo0rv&S0$-%MF6vOcyu}Ds6@Ec4O zZ3NGW$B62~A@$XLV0Wqr6gxGZ(p5zOFTTTa||NXjZF#S$^~R#A)<|x79uF( zuvV`7Eh}r}qZk(M23E=_Tp(C@P$Jo$+R`NpMLl|&t@@|5?p0bB?!H;T{%TQ-seAM} zoX|%Ddm5}iJkV;ba)b1hxhl#xB8PR}IJ36&aRQSWf3c4W`A`Ev1o~#?%)U@zdQ1<> zN}!r#8f$g0Q?$C5*6Mjjy-2V6{rf>E`6^eD!rPmg{mf3_m+gu~hcKVz^Vs;u5g5@b0ooHJkZWkYp%H};Cv{+~vprC0dhxms!kPb~5m z=L|5L))@ZpgQ50-ymKgn4;5@T#CHFIdfbHKF`MNs8>ZnnE$9)u%T{01MFxv)X8XfJ zCtXw<8_r9~ES5dzB2U#ajOA2rP5G5g@Qq!~uIwpV9O)aut0kH26<46biS+;RNc3uO z$+_l~hlM1wRBUTn9VgDQZfsZE>7SSvuP_Pc=su9Mkk4B3v+ctRdgP95^I2hk&E1qR z=!f80)Ny^s=k@tLc{)Z*2m@qcA8-gCY#(V^@sqirGuYytE9leHxq~ybIXIUJHtBs$ zJL926!{sbjTSHN#hYO_R=$^O%VTV!ORg)hr+?OD8=K?(7yLy!;^S!D6F zRkLuFV6UJT1Y4~%XIrAgbIx}r>PgxWrWHDXP=}{XDr1uV)fDYojT`eTC$BswukTu^ z{(PR3m!9f|**T=LqJ-pQ|$CVjdH)o#_nEcC9gM@+9(FZ!(X*GjJXkbay# zq_;vR5t>);@@F`5;Zp@nMO>W9?=^Qgds<6G${9!?OR&QzbBCJ?F1Pf9^+e+sNM@MF z3<`t_?h~&(@$IDS2Q|+=C8`N{rKftNIcNR8XoLLrYLfa?Fzk@)y~0O6PRk)(5d1Mw^<7ulrTOA5Sbu|Nxg zFIpWqn|a(Qi~_?@yQ;&>8J;;BMVKc+YVK{a@Ud%J@`cciq=#gu=6NVQtEyHr-Hp~z z+4V4!A1~VgmTJH*w7MPqh1L{EcA`wMjnnkT22K?jgLw}~DZbGm{cA-dOkX(zk`h*z zfl|hb-k6ra8>NZ< zi=D8WB&-YKB5n`xO4x@A`yn~wsq9(*sBC%82te>=^stcYEzf0Wz^ccfZ)MRL{r)G- zpo1}5bJK&6&S!Oi_ym?s)(g|=ez-+BKj;;LGQ^gCcpBEq?AOV)BFjMgV8EX$aK38V z{Rv0AvO{Q!L5cumGJOzMkOur5{QQ#h z!5FdKONWS8`Bf0vaChDf!dNgjt$mawTxCMIb(e5LBQ!wo3t6M+XZD6C(~$#$N3!o6 z4knU(1A|+%@Ya_adRAWa7@o35CJbtb`d7~RIMOOd+RpfPguM@0drtPpbi^m*J*CSx z8VUSr$%PR*)Tx3MV$BUbhmZR!C<~4RjDbHG4%RH6uRgs~#B9vp&1muk9GW#?b2?w# zIMRAGf(z0*$E|`#(T&V2n(sezvqu2K>Z%8Yimtk2zI-!#!|GRn&_iK$k&a?M@csvm zUt@JZ`@UM;8ZQv)y633K8b#W``9 zGh)R?$qQnB{tp>QyBSC}Jx11YkQGs%#L4J;T8bF{G}7?k?GxF8%I*Yld}cO8Xt-X9 zP5kKv#f>N@?yl^}#a7z<6#prf6g_zRY{NI)#`bJg9S0qe5AowpuE^Te#&al0XF-c5 z*+9r)tk|cBWlnqU9YgsAq2g>*rE&kDQ{G~w%yVUX8b7C%@GK(0@ihE}4-4c*C;6KM zN%D+1UAVwbE=d~yhxou28C@>_?Pd{5kT>O5It2{@QcXu*>vclDKAVscgpA+uM&E5I z!A|4ql+Kw>?4KmI>pRp)IYF;T&{>k8DA!JrqHro2zRDaIeJDT|bql}gfd53mAJ#df z+%(alT8$DKAar~z-(?bXGeNPc&6SX?gis?IlCmSObH!OszC{vwk>PugBIh)eg zQR)V|`5qY%vVkAkQOblj0v)Bu(TqUz&)h^b-y_UmlPf#0RTEdg2QE_B`seh1%U{cc^&uV%lKj7e2+;SF6yT+XBdfc^s zjob#@i%{5{(dDpG+kX!$RelXBHigqeIIv0%mF%~1gYzh}5EW}>7NUrK&@9YEvSJpF zl*==P+WA^x7OY)M$v$vZn?-A#lC6ETR~2bIh>l9YY$HB{s|4^XjQGIg^8Jq(zhcrT z?$@d}t`mO6yju7b&8>(mKB&|BPS;$}tqNS#%3YXaOMBZSmFyLL6d;HE(is-7Exe7h zuPO^(Gys`ng5xIqtxBe9b`#xJn$E4Qgh;DP$@R!50yEBn5k5us+qZ2`l;2xSlyuTw z3_e;6ao)2A)$rB9PhE_>ol|^ew8M>b`G?VEN&XxH{tUZ<+LIRXKP{bfzF#^?6s9%5 zJN7v`>DO0LJDr(MccQ}tN{hcMTaR$fmQ7LhYDL0Hz{gZWP6BS9BWRsW4)y`B-p9Tt zgc%-ewD}_!b)+Jf|3OP82AZYWp?h@LkEHg*OtxZ%4Ou|K z+3|!0I^hK*j11Bca;af1Rp~7#&hj*J3tHqBHD*C^&ENqC{)7~xvY#se#Udfu#iu19 zvGcBDCs4u6`;K}|c*mYthIKWYlQx2z=nJwn^$$`jtC3nSBy$ZCs;^@)_%Uf}HX9q& zdk$2!KotQM+$#NH_)|mr#njz{JlxapDZ!ERtN>N5OSL`_)L6Y(v-w0Ry1~gbMKb+6 z$;?fXDMPcAuEI6h<%qmkGM|l{&%HeEC-*QA@^nf5FG3oYY`#RTux9hf%<3&b_&)&Fi)ujHMsny-XR&=Y z@0l$X6Il!*|DpO&?>j`RbRuI^qf-J4(CJYH&lIj~H)3xY4nAUFIc>utfvMM;aa`a4*8 z0!pMeioZhQtVIS_3trn}exvn1&6)dSf?Ac7v$rbn=aLF()h6|qhhzg}2^U6D$wxlb zH?@TP-p4CfbDw4IGAqlgEa96)WZl-8mZq%1df8}vMClHpjS1v;JArxC6Fm*w!-ZM5 zHng$5h`lwloLx?8lhw(eZJ(F>PPFz+f!nz|65n#$`)9q&F=tLR@0Wd5ARoWW?)%lA z5c}rT`<3EXhh1hD=`Rdy(MLJ{3u)YdyQH6ZDc}V^zbQQ|--`wi@V$?vJAX?DRxL`_ zAro}S&j^u4S7;bI0yWYv_;b`62DN-dADGYISUg4t;_(3;e`jL+!-?^0b^L=)yd|$v zU+&VW+K{qpg3X{XWaYv2*|{mZ8STVsiRN&SDaaLoRbY3c(VaoEYoe#LLi- zS|WtBVq8QnQr2wwT~s}NdBXBAkfgCJA)X$x40jKKYQ{Y%*5)Jvsrfzu`P)oD{w8xt zxI3d=p?mO##Z1UKf^WehtLJ zyPis{zs#&anP7*yUSN9ieA#Yf!erB~Gf^}8qk{mGjL;QuUE%L=5)Kup9jYDmHHmHJ z3C8sW;6>YPF~`LHG90$uEr-tjvuf5?e~cB3!9~T`2q@Mo`(5D@f>*TaUFcG#+J7}x+HmPQkwPndb>wyQiXHZI9hEuM~|H~@fxOCl|F=0)m zI#SQ1E)t>>+T-4l{anM&4F*W^Vy!N>j(w~%aY(_3l2RWX^#)|amE>sLz35LE3J=^dBR<-Eu~VfSAP%Q*2faH9T>BDVHhz9_9+eH8l`P_FjyAz(cM z)?s~Q>5t9UhoL{7v14>@>-dP|CRQ`qKZHGmmF{C=6XRSu&MKgtIF78K1Hz|R=OP+O zGDFq~E#gJ>|BVr89cBADB6^$7*ZQ*->la+7 z74KFZVtcHkHctgQtKX58LxfLvX!aP*SC7>IF9X2grIuu>th;2TpsbY6g#3dmxt+qo zBN$=f5ns_Z{F>V}Yh!8CmTk4_*CcR_yV!iqbeS)!CSU}|`hJ>@5~+6bDi)(KjDp;1 zm}B>WWxYk8dY|@JhXUG)v%dM0dTUnQo*Iq%(`tgZV*uu?Nqaq;3SGU0c$H3nHpy!i zy1lAU`ukPZ(|e>Sb%hAe#iZKk7Fdwd>FVQhmJ3H`c|kFJRJvoFZWdoLM&mn_FMRZO zA&ueggU}x>PKEwCBFIz`fBJ^#x_BPirh2%&q}LRE&Y;E6zkk&}mKultL{Nz~@z80$ z%*d$r)v|yYkqqlaw%s};S?Jw6QPnq%UVEun<9o2VT3$rToB>zx`wsg&K|MQ2uOrqN z(8J~a?PLl!H&6vP3F9T_ACcsZNn$fXPjcZ`;C0K>wdnR_`#i@t++OFocBF^BEYsZY zTkd9sSV6Nqn=W_L>8&TgZm4>%b}^sUQKXMuWkhnep^0p%>+~M>;8SJl`A2Bl2ETv; z{nH|7{250(kqO8alJtW3ZmDiBgOBxg5Sw$a zQnVt>UE@n#!G9*5xa;tH7OSg@SsLtd$)1?09#+2)&F6#)+O}mTwKeYboo!J|6baB` z!6kB7<=rBjq_L;Bc=JO&foDrCGXEoo;NAq#8qm7*sptxxt>23{JZ$IEn4 zkeul@OKV#$9cfl)HtxM8IW)?w&fp~_bd{^+(k!z&-3fI&p@muAmcndr%cWyl3P;NB zKvZw?B`*u5HvekvuPq(^IifD3m7%6ZL>X#2f2VZ%$MhCqCuRhO0oErV&^XJE2}%5xeuw8m2dPTn73E2ip#aotI^kBR66-toK$6;2L&G z8A@4So}a#KJ|KH22Eh0C9l^PEjQlt^Jti;0=u;J0es!jA5P!#^A+Rfw%pmq=->>qI zP9&>b_bb+l)dn6d9bA#R^~vcan7E}Uh6#K5pFrEKyDcu!&g@%1k*jj*4$j&bHIC?J zK5C8X3+RzGL_WJnkA3SJ9EvBEwO8qU?Hd+Ch&_$Zi!?{nR`g+!r{M{^GhV=tjNKXk z7k6(19#wTM{GX5s1PCN3AR;IqQBgjO5*10XLnadf5*SGWsGxi#F~OL`WJaR`4i3SD zWA3GXmEO`;Dy_DcDphMESd9h~RH~@dMnR=Y+Z{tS))XQ{=KZaG&Y27pwD*1P^ZuXb zkDko_So?eLwbx#It+j=ke*p z2c0JoJ!xV|Q?n1#Bl}Q2?xp4bOyniWQ%g_239`e9CSlO7ATqCsYlTryxcclMRxbq) zq{k)JY_=h6@z|aw#D7Z@QcmB5-@vUuWfSg~i2wU0G;4XnsNPPj`K?oR>%@A65X#+Z z3#S!d@mNOL84ZVl+Kbt~B35960;7I~U%z6X_*_u3VB0a?mn%ddZqyL9K;WZqnF!{* z^p`(L>i>!yPvQh-sxC=*_3FGT4XFB5TZ$dUsi!FaUYNyg7lVpPe2OC5k?-~?(Hm)t z14x$1k}pn}qtAxbRQCyU^l_$aWR9MZ${h7FYi;h?61Y79ZTPEOEkhcLVr{Af0~OT& z$zL81xBZvZiPqAK_n%k%0|KHbYT)MSie*y!_HwaL)verwz`(hbR>Qyt`FoeAyz_0WXUx)LC;7K9B;eEV`j_={7vdr6xwmSGzz}bZV+9l8c+B^KY!s{ z=qoczu154e><&Hh52r($y~m{UqVm0fAhEy^QHdE+pL5JyZ0TlJ=)6lMZ|^Zw7R9_^ zVmsuTR^OBEZ5Pr&y+wVT0cs!9mh?T14n)OIU?MBDB83(D*mO&&k|E;^FyJjqUPud{ z7A=aNXYGsj17qXA7S=S^9wH=+LE$SobnolgVv575Uu zgn|}?Reac~q*`(VID!?+))Uay*f?ZSN&hecZES-&N)Jk6(?76zEs||&9T#Y3&H-oB zFGpTm9j8atYpAqv%owE6(|Kw;UZ0vkmDG_6-QgA`5U(~8!-d;sxf9`<&BBM-r8Zuy zpxcFBwY+i}V#RPNF{KD&NRITzEELu3BTBeWK-|=?01f4b8F1F1=4dS)c=`Vnx zM3|{T=!X{}&~-5}b}_%?Scm;@s~GhoIpnpf`)>tFw~G1^JrWuCC#k5^>@M7jA>MB@6 ztiG?SD7D2SOm~HvMBhhU4wZ&h9pr>+V%$*OTrT6-@t6!8)w9t3k*2m5P*7V5M~+Ax z%c*0%_kj94_^+w$apKz{F1oA(gGIaB`qwt)=btC-9r$C}xdhL6EIdQli<_jQ4tu5t z{R8xp;u26;0)Bpm9GJjMX-lT)yB4NvypNXsSk6A6qej_cB68iBiaRVP?!4d*OD^de zCmTnA4w1ZZYRclURya#`*ENIbEHO9tIBwA<5fhZ%CQeG9LIHoyr?g9?G)m$eB*xF! zyZ2aQ@eveNliIl~`V6X%_jmpp5!=%Kx$e z{94qV7XNm#-Km1Zug#U)O{-V0c6#;leEU{L_X~LsmrfdE7c@XTUOQ7vp>*34>`~)% ziuQj=`>*()wg10P(S8a0&i3na{y%NMW*wWs7r-oF5lGv3b7A~7HTzah>`_F}v0Q9D z*UEy_Dh#UsFkwhqBZa*4dzMmywbyp$&bPD@n!QJ4;j)?jL?bRX(<5SrhW#}3C?Vko zH}O|2eFa2;z|^v$Cx|vGpv=dPu)6kgJsxNl%&>>H$6DEX?~%wlXOlNqC7Fv8 zFe+I5>`~OFRljGfq{Tb6_ZW67srMjA*B0{;xy4ZrIjzb<7;Y3+quOtW> z?xSvd{uiIVJ?K}zF&gLoru>DI-)oivMd@#ci=1l0tR#_dn8Opaf`waD!=0F2L+-)i zv^~j9KY819V2@prdug7wOCoxTERK}$BaIZUNz-}UCO$2W5kTTAqee}k!!SVA6@ zYhK5+$0OtsWkg4t_Rx0?7Oz)p7s{rb(Cuu>v}jOfIa~I5h_KPBiE^G1derxE^`SkOI1;9Sy9Jkm2(r~*&=#jiO*h*G)4qRpGm<& zUCa~;yDb(Z(cwNNgxwQj}*GbaCC z2vZ@6GxHFgLk56rVDr7}igvscR_9Fa4twVYJ|uYd??rIVvd9qOL70Jr`c+*&|G6&v z6%4r4G=hi{AJR57B6_?syu!oyWrJ=TBF>@J2{C~_@I@GNVL?j$HP1!gQTXjU3jZy7 z11Kcvxv$DryzORv9FkkCd|lY;nI~OW97f~?{$eqmZHvh`*A@G9%;)5wC&fji=dJ?V zZ;#z-aaN>;@BY=kcaGSmlF%=A2>$0{;R?7wA`5VpOwA@W@(y}xwJYtX_tT2N+4N(J zdUXk5yUiBf2hlzF{-xd0ZIL-Eb4eRwWFqArk4z+o-HQI6i560Vf9S;UQ)D^|Zv1-R z4EjHHC$xW>7%e?oND?A+hM*dK7l-R zIm}rh?jW-1`Ip0yo?kqez5peMUK#QHC~B$Bk{;Cr%V5y?SlemtnN^?Dr7_EV=oSoq zb*qP~HT|qbM)Z|ss@Nxv99)WbQA)(@e#2GL+jCOs?RK$WFKX`c9tHK{Euq0s=dOnl zL;3kcO2?+U&t>NFH=dzvQpIm~^QavdHOa8{hX%(U)A|(01Q4^DG5rZPs^s@Mi%X~0 zyR;VP!k65Jnx(VuuFFWKFm3B{iWA~?LN0JZGM$jYPDr*B(#r{%?SynpkV=zt1q#HE zEtA87Ru)~rTUZgEAOb(zcM~9}CRN4V2;=npuvk5JRi@N?8(3Bd8yM=)Mchqz-$Lkw zc96zboUXgEf!W>ZQ`2su1J8<%5s8>JRnheHiT zPot@=;W9E6%UGs+wy$9?~ zp3%SK)PL*W3iX)&oy}Z5*ES3~)FvTks~LMZ%-stBtC9B2R<{fAtLiJ}sb!P(RrNb; z^k|!`ud4ee_2}WOU_#o>Z=x%D+&NM1*-`GfQSLcCZu_3=J<~H=HN0if&8BZQlyc2G zfrJ%3mg$>Nk%;UA>=z!ls&(MqZZ2dZG6ckBs?tbYrWFT<@+?a86#LJq^Ay9>SVt!t zyrlw5qZU{AK{*wgo`tAd_=nVa3W`E^uQrhCBR(kcxhtdgAt^sob^L+eLO@I`!0G;m z?ip-V?T&~WE;alEw9|B#s#w^c zIv>%!DmJkG&0;#dL>5!t4www#7Zc#7hK_x)GA?wib2We35n`OSQwHgK?Y%hr^!6=a z|DotzH0o7t*V_|nc44G6uuBWP3m)$>Z}RE8Gp>2NB(JW{)h@F zFt*^jH9H^uMr{1OQ}?hqY=%-H>&8M9f>H!o{dgRC$Wjv(&QRk7l?UdeL+Yi15}s18 zZQJ=)xYZiMwBpBEOlvm`3MzgBX65fHpw*p zDBh~k0mvy)rwq)kuaQP$9gx4zOA7T%wqH|sg;YkEUnYlFZqTOa%F)!cj1=y~bSFe7 ztRP_oqfK%OTDL&(nF2$%e-ZK?a)om`5^D~_O|dd=cAt$>zuNS-sI;ZJtx_-50Um5> z`<0~ryS^!;p}BYRXw|KYJb}teUMjbrgwHMXFS4DBcn@`1`O?aQQL~rcSsw6LEjoYF zlxo8$)xJ@FOe7ga+b`c{t%5Vga>jOKfmmbNYReloPH<=Ibv*es6orsP&h{bd*caK1 zxU_3sfq&M#7Kk&m^SFea8E?L9(In8bU2=9PN~@aUuPUmmno@+o=Jk1M80@+*mO$lG z%Vh)LqSZfrg|R?QWX_sOT|hsjslX(2r+R~UhO1c61MxDyS`l*<_0SZFTCif&0yUK2 z_A?V-5_0f*)}l|1ASCQbzwUayvY?SdJ9i3;PuneBk-p+Q^)n#A%4g&$H^VP9nO{BU z#-zcZ6$4Zp;?7pkV+4hErVE`_6n0n3Iw=ZgR~Lne`P6?fijg)uPRcz>% zZMxbVEIzMa96tVre<0rwzGS}f?Nc$fk>*QH{OQZ>mzc9sV`rtCzSLM>dfMxWn_g}o zf%IaUFGXSpnX^)2XH7AEDY3pOI@Wwy4)zv}(E+y5M=D`$RCJrSGdV>_YJ3XZp1$k7 zVb?e4dc>Ml%v1^Ird*$FyT^Omu=yP^K3Dry5#L4fs)AiH zlD3~``C?Lp-z?!5RoE?J-cb&gO)zJW(Cd`KYAV{A(b?rMoKt(z)LdU=}g*zJ5 z?b6foJN&CBzq39+96B0zhd-SB@Rq)r#-M(g#tZ!Zf$t-}&-jk;k^6X0y46D$Ww@|s z92F3gk2B`J2l5E%W`YMnyHpsTk)~vDLU7?ubJu%2S(X34RV(kg`jvQ=zfu`7mu^J_<6l;O%oLwwLZ`a&FogG*mFFM~BMODUU z$55fm$&3+G5Iy1Rbh3}>M7h|q_NUzWh+<3T9qMPCoH^ixjvFiCtw<21-ASPC#B+4_ z4GC5w4wR_7udiiiA|?<|ns8t@3=-)4h@FX!x}5Gh%mjNo@)dfv+PcHd4h8+>Xe}Qi zyUJw=&R&?mEk=zN8NU2&z0@$v5vvj{2k%8#jyUy=v?a0^Tt#{gD9R+urnV0+1aWo9 zB(d6u>SnGZ$*WNeB00ie%DyY9eE}|2jcB)2V_T#e;56?c+0atdTVSpFoI{WoKwdy2 zBBlOLmr6!U?)pL^uOgeKwwt7MW$DW3^F5Tuh|t}B17vieHkAFhkQy=pB4;s?tbZP6f=>Qqy3J^bRUcE@ih|7tN#Rq6Nj$9=8@#_spY&Wp`w01k7Tw}_P)&j_ceB!< z^zhyH*DW8|tM)0?R_vBnKlfTrKeFJ*?pcdce0L zRvlq`drTrj)1*GAG77mP|EVo=iITw3v_m@ToID9HUP97hF*py*27!^->*0}Gh4}m1 z)jdSkys2tsu5<8TX*c>cYN2+MHZ4y2%|Bp8c(XuYSCSapIhc6TOE_o$t`?V8sC4$t z_!Ze|1tl=n{gKdiiTOI7N}Vi!(A$o{i%GjWPWC7TPVlR!51@znh>oC zQ+r<|#Z7aVu2z`+qjr;t<$ijRdc0P5`M`Q#j1{IXzcms)No}*DW1AsybuMn7Dqx1! zd;IkeOGy?j`{Bima>oamVo_Z49>?jHPLFB!Wbk=nnnQ9ZlZNXfS%mXCV$=x-Ww53o zEW^l|K6B1Y&)hjAVocRH=h1EvPFyDkx=`1s+k5*|dJYV>)#zc248ACQIAr=mtFdT4 z5Qc(KO?1$J68@;8=t=NIrfBx<-Mo;wr4~)2 zhB$iGx?F zcheQB225dks)bGA&qulo9P3k!^cbipHCf(MZ^A>Z`hdAv`2s9#C!vzg@6jA4-Cz{< ziBwHg$*1xeCruXZ3wu^-MPl$Y=b5Es(ZrGTI{Af%5>?5WQpwex@HH!SZKp<+G^VE{ z-s{rEEYih%PM7Ioc$K_b6Tu6I+vm$6=}15Z@9Jy#c{gcX#NexWVt9<-HUvvu!gw%K&Iz9g)R*f~QvD7W6*Xi>77FRDJf2C!D0DevXMjMPkrTy-zW zPXhfZK^muOezVXx&O3%8W%26~f@mz+3!W>g)6dbFK|x;jP3C3#CKFK!9rm93Vh2UT z1Mf0txWZ>akPmPO!M5R4gzL<=B@#ODx6Bc9ahG|H*);78@Kxe}K1{ZWYy062bq%@a z+QhXB#o73EsA~Ym58~j&CD;5Noc8RnOk)!@lke)Yd)!V~0rA75U?lv0{GqN9_l!i{ zUUF4K6W9KfT|gdYT>CxpZp-ISNL`t@_F5f(X5v~=ifg-?;Az9R@!(N*;@X=yV^0$y zkb9C7*ItY#?oC<|QhgHdy#U~eEl)}d+Mt!%~ z5B8RY@NcWLB9N1nH`VXPr#$Z?l6o61`+04_i$1k zgtt#+GG*A#67tn*UCLPE^3@gEeU^snYBAtx5;$51_OcSI8SdGpf5CWDLw0C zd118GcgmVz7MF>DEJV?(9R?^{vI8|{NEs9*!|O09IvZ* zwYY%~HAtLTB-Y)84iAZ7N8T&JlJBMD+a{JjO&A8Z3#G3O0P?e@$#{Y72iJVnB1_lm zqc;TBY9`vMc+}K$sqnK_Fsz9+Q}Qx%KT53mnGQkZRA?y1?E%XlY7k<`2>6S4vjEfp zB+mpXbk}W^aL!w9a@UKxcs~GA@1Vr^)b+@^gVnzh>r>uHai~(vleNoTUHIL$iG-`Z z0;p?CYUv+I-*$$TL}%R=Cm!y{V9wECeLS22xr;WB-OPhbXUUc>x}FIv>{xl?6KGqa zr0o^$W%B81{H*xo&N2CMIbkKPeM|zlGso*wzXJzL;D1CEh zLc$LU*P~6$rdV+Qu;4oQao{>NoP_kKn6Sz|qJF|sew7GSH$(avhHr9W&9ek>Xt`{a zD709{L%9E@g_eY|)z$et>WbnTeR=^Z4VF}@HI+mKMw%I}aD`I@U;v%ozU-vHJPFJp zQ0uzD;bCrUq+n~z+9zA!dVWiA`xqI)d9KY}P@wSD3o$y8uf~4O(h!T3!^Pq31MNfF zt{nDX61oMFcg;?DplQ{=zE%T- zV${-lEohwJTtbN6fR;lR0&o)^h}g>+#9s@;M#3uS)$J51B%=C)t(of}IgH!aK`xx( z2L-{hFAL3~6XoiR{8idBNpgVf)H(c`983?>(vKRN=7t5}`yhvz2m!P8Sskfru^>Yo zuA&Z>=w8J_UEMm)sTJ9u7)UugddFOuh0i}Jt$cFLm!!VI_13jR^nK~U&7-J%Jk<6;O|5A}CW zAMIlQ0^ZBRxJhhPf;vRyFc{EtIh|PPrJtoVk6(Chq{3sJvoZW)J|pu(+RF*M7bRJE z9P+b?qxdY>ny*D}+8@8>>qmh@TxOOltyVjSo3jR|)v`T^HU3${(rRVmYi*yA=0EBi zHsO1|4}ZS;`L>vwZfsifwJbiE0=O-?grjm;GOJ)p`=?q$*u4UmI#$J&7-&i9cRI{@ zOM=@iwURRzSoTqUDv37r)Kuq}592^V_swuklTN9uo+bly$8Bm8Lhv#qfh)}`O|MLb z#I$Xxv?|a?1?ByV4jv-&@sK;8D^5^7CiXvO9D$ttOicSFD~`@r_X#E)B3E{4Vp{rN z6Fg}p=q2_bA~vd=It9c|%UK9>i@47BchM_QUVXUfD;U5;je@_{{LJhSN${f3i-O=R z+3r7@>jvWqKa#{>F;l?x$7(rLjO8rxdu+WUk4*ij?->XJWu+AD_zis0L@oT~2#dLr zMJQa?%;K|LYrR4)Mk3_D1!}F8Mc|p3&^@j*{6%&(-k}y&HU4C-+lxE=$R7SmW7OG9 zT?7v^be+<5&=?3Vf-cb>#8|{LMtd-mES@0?)b;e$0_C4BC!XeYYsrmH(*o<<#T;Z+ z?`1t+XXV{jd#ag9p`9a~yGTT)?9~z&&KjZN?)v=rc^ni+F(G|wG)+MZR5Nna{%zgi zhIk55W8xS@L^RM+OAt8?UVGRe;jcU;I@M&K>lQcq$NhEkEVV<2rIZp@pu++l_JY^x z2437#KbBZ|=_j@jc4eYk{Z@;+koRxD_F4 za^>GaZmP6H*0I0$nl~`Lg%ui<4bPX!aA`r^=-dU+%~pXU-O?2F>}`I{5`gRqPjM>p zf|>v9i4|!uz1vP*kw1_hmuPAlHId#?nFOH!G>{>G9D0ZO3h$9uAv6!T3(SMW*lTt5 z;^G2F#$MLTg%>#MMWn~(yHw6#mcy!U!_QSww|a`}0dr4%jqs3F@7}^n73cO;lBuDr z-`fX}Zo6B&VaTKvN%ap)2@H0M+?dsfM{R~+lAc!^amY-#P7NeH(if9RUT=Y3ai*O4 zyVWFqx&I$PYyM(!QDY`CrT8b?08ZhJ+fStwX&vCn`>>1>A7jxh)r;5;#ubHLlDGd1 z|GD)T{*zN#uUb2HiH zLRTLTbK~VHRbR4!=sN)lf$m#iv5+u21`#2u6tlJbmKEApLggIPjiv>;Prx~d*80>A z

^Tn-*?~lU`}&PGJ_5{{-Ou-^HH@N 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

V5F0R1ag^%92-rR?9t zs*ZDD$WV%XAN7(awQl33LA}EH2*iWL%99Flsnr*VyV)d z1({Y?UH?s7@#P7A_g`_vg$byC#T9=mg)5eV?`IUqlUl9`R_1JbIDHdOT$JQ?X~%Ek zi6!(Bu|ug&-8)6s>;ZCC#(4N~*gDODZrKt$g$+ zvekuPifg@Zjf_Y9_ zCUg>z#jkvZ3soLNlrhj#9Ptz*%&K8mtRBCR%3^AtOS7W^&hf}LcBYXbc!~+9x2B zDV1%P|6Zp)0im$#1&nKonqS7k>jlyH$VUy4bAF@q5!%5Pn{!v~hf_|ROE{GX?LZVl zU|BS*Gx_XdbPUSvk3)P!ag?~n*6y5Rhws$kg%u+?kU1C8{i|#pEiv8L6q%!#=+dGoo=fCMU-b=qaodZ967fuFW3_DySXF=U5o$N zdhO;O|Nk!|B|PMePfo@CQH8&TW{sf16+>fy~*AnjOq2~w7Gzv`SQ1u;@DLCD|JoNifx_9skk9nk90$J!6;4g0P}2wTIKU zFZzPB@YR>wpHt1}DEsqFK5>eq$MP8cK7D+&Y%CTsW8*&zfzrf98_*WPfvW`I$Z^jC zru6H(ajC8Fp_J!%N@nJOzON=KcQ)+gL`2O)bHiwE z>pL4J7NL0E^kTBGHP4ZW=#-YfDyQ^$L^=1PPVkKnWUlv(S2r+unHxpE`~d39`D&i| zrhP;M3xjk&>dIpk3r$?y7<2LOa!NG-O{+ao&)9g`Xz}CX^yyW!RN}n<2OP?6+KlWZ zQd+!SYrA!*K@(WK&X*qQzy^p*DQ_2MBmK8x>GA>{uUBE--{igHcDAbo$>x%va*u$s zZL-qzA>W-pXYDg1qkwF`G%{j(-E-Vvs&_F@;10>KV8nT076*0xOI@1|p?DC&rEFek z2b)o7#z~Y51~RQC3$pfuTGA4hR)B1s?N=KZ&uDVtcrPpsgc`IGLr3ERPi*6& zo=RM$N?Xp6xR>mxokX>SrEv`&ZFBWaczhT}qD=unciqWjnzu?$Y!pbd} zjk5WK<@Eg`zP+1*^Ij=jivKVU-V&@4<}(@M@>|BS%$n%L<{Z(Qc%wwO^LIoCs%M_~ zG!yrJ2Wk2rT}hDlp!yNh-v`o-WZ=`b9SMHq0NG*wq{hSgwRatFOX(1cCemAhc?_NP z8+4X>q@#PXexo!2S!_WO+#Y^LFGk{|nTfmSt8tNy(%Qr=|GGG7ZQ>SwDQ?0BnUjHm z>-DeNgozUOZb*3?epJt_wPC!bD}(YI8K8Rct&g*$UnyGT6wr2FG+h78+aviaLJus`2_`Y{4FY z&|BXaB7JO{PBGC67BgxJFth^IZb3EHiNLS-;R0;m1XCeOy&6@)OM=AQMs1_Qq(>6( zz(=X-c%JcaL1M7DsVZ>^mw#_ONA!nwf)*06(24gy_F2qE<7h6lL-YhOz`!Ym(7%np z5MIUc2txwBE()Ow>V_O!8Oe+H=}A5FUP(lI*LNf{PSfSgTcXos4VQF}r=;smP4|>e zcR@-ziB4?H`DV6ybO8K6_do9llqQ36zXVfar0mhiK^4C`Wzn%T81O746TRgpj z=X^QmNw>1oZsSDgqxe&V?cq^8yH}T3`*;S;_0->VQ+-{@(#5s)H$>Z{to=?5loib(Rt-cn*^44f;9MYFZ|SVIjXtI@;^sIQ(=wYYM2UG1$y z>Z?UCbW0=R7S8-`Y6uLjub#TJvdRG%R9`)--cz%1q6vnNQGwA&#DUC zQr~#v8>l@m9{pc$|NAyswuq0@|1> zUp{9_9qaqon6bWlZOMOh&e;I`#1MHgmSwE3`#$G+x0i4LBLDjEJcdkluKinK|5n<+ zh^;MGeX&(5zt)HG58{X7v3M4FkLQ`nQ^RA1m1#VwSHIK%srX7}#*oCU7^t%Z^;fhp z`f?CZRlS%Y!$6UIcT-aGK4D1rvofV~rSI&b$0_~^AemNQKoC04rEVjsv54@UX(7M; z5%Oz*X?2xV%LPpZ5Tk)~pa2RDum()4L*Y)eEE?~j9wNz?#{qI7)#1#_OsFP7L&L@8 zaUcXumeptO(m-w1`h}CN4aCWl8qa~17EOCfnncyJpv zFV%ekySaTaM;#6w^jQ@WvTV3kUu{?6g(Cf6fhp&upd>#RbC>LA*+y8n-plBjN6bhE zh#}4$;M~9W$7k1cRX~vIoAx%z_0(6k zNyzimKWzl4tBZ*Vy7uH`Z=6p9pS^K@4lq`0Xbo=sh87KXQUBn{;pL;Pz%bKE(V@}e z(RZssc)WNrE&77^N!1&$6=U&Ec#6J~v=p_-zP@>S!~0LM?kg2XcET4F{q~r!5B5Gt zWKFh$aSIhm?8im&lTbpBo!sT6O3rv;Fa9tV1nU2u)|k+zrL2h6>TfI(sVEN$pwTk}P0)@!B$FOL!kH0dpk1yt)BKGlwl_tWb#>+~Q za*|a!azSiR46(hvYma5iBq%mRydianm#cHhE-}RC$@nfSPmXWv@5%9fYWUc!;E1(r zGJlEuDmZ9aPdPq`(XWICh+LM@fFq}Di!tiR7vA5JGS)xC1_v3swiNyS<1&_JY}&`N z6DjpM!4K=;hR)LYLVh|*18l9dEa@{4eMw>4M2{Y2(Y{ycb{ueI%A7R! zy2mMExM!BT`M-FHF2Z*}W}oXt_R!PU{e86l;O3gwu%!N-=f8O3_VX^kukk$3gAq7l z-FnCmJa+jusWrnHZU5+$vG|Fmb=fI!s~Lm+&L{X7Cm&pNyH-BVm5)Pl6_5{Hl4jxS zwP?!1z~IP~g%TBus|7?cT|3og8bPLO+0}CAWp#Ml-DCwh#9B=xL*aX*yc=0^EV&QU zjIHk_#@5Ps*>WAW?KYh(+ay}26NUI|_L88L>(+27XyWhSJ-(6E#Kgn@Bg|$lZHF1K zH~Ze+yVXPrmzWMO5GNwAvTd@#Jq;=o>xMMQoCm2;p0u`Jj6K%_Crb&!@g82G6}ZQw zf|4cw2JtJ)zqfK}K=W*TgF}u~+SSo#5X{Ma-tEuMy^XYQtH-y~P8sU-oyX$8U8y?9 z>5C5B9mrbw+@?Q+9}9NDExjcFs84wJX2;GO?@BYf6V~2~*Ev;;dd!Gw^=_uDGf1cU zJ#sAG>D?^vj&ip5F){4+%+>NdX1&_DLkQIttYEqL3NzLt9$#^wf2Vi%M{%}~{djRv zj;Mb(ZfC>=P!mOme5h+l$LUnC%|wZFMfIa!66UE@-ANOermss{lYW%6?2^EEHK6S z5$_|dGdIiDS>J0|sISMntku7nLGS?0cf|XyE6{)KbYF;iQsgDRHT3Th@4mD^-|%!_ zTFez*;yW&uYM%Lt5n4mnQs(W#tEfGY>GrOhp&hZ9m@nD)mI&F9a~E%Biw{mj1<|Y5 z-Y#=6qz#pAFQavsu5<5&eKW^aQ5Z47+#v@I*tyWz|X<}yzB$Wy8s#TZj8UXC8 zHA!?06T@H`MUjd3D0~+FA6RhgOEy^lQuwHg_1HbDyykirRzfNhqcxxUoWHodK_D+T z1l%tMMJJWdQ(OO+7p|bibA&!74PUR_;0Pa6R=#$34+Rn`=*)w_nDC0R77hh=`)c|y znro`aLU5`JbT0eB3&q^6PGX$tBfhd)wUOek-JJ*)KzP&BP9!R~RgMw+(TXE4JebqS($Yo^6TI2NP z1p1OeynSvtGqqj4h;67b&O??YFfx%AR5j_oXZ^Hh)thl3@3X}wfPZ~?M=fVbm2C6) zCp*$f->Gj5@aufDwQs!D{ucOYH`LWPR+)Io13`m^?Z^A9`nmPacP8KDZvuE1e6*w` zk`;ce@a{b|o7Yp{GMe=v;iGGwlFt(P%;a-fij9r2$x#;OKM9K)ZK3lLNwkH|(&I7& zt_Ps{p?nbt?;hK3EkSBjS$o6vHFloPcPVB9=$O?mUQ%VvtE)u1vBVc>OxnM=Dc=E* ztSj(JQLX*F2e7k|fBSf^vBUTBJ{L|^{_WxY4jbk*-bdT-FY$iJe&5aeBb>I#zc$`W z?C_nu@3zCY@xIx{xlY3Eyh6NBw8K~OzS4eQ&U=rY)|LhSJ>tw~dQ>(j1=Zmzq)|8} zsoo?nKIO$qYTF&WK0A=YM2E}%SsjEuNKC~Kz{351zhaalaNH0cBdF4v+}rj`H$BPJ zRE5kPnMd5s(c5V?&^?zjj!4Uc1Yld4C)EsAVp?))VU^hf}q6?r{>ESQ@s?v zT=u)N0w(9sg_TS?{>}IJu17N3fFAAis#{AD7?xF`_Nc>A+M0Cp;-$4>JLzj&dNXX> z4Uhxj?fZjYGi{|V_PTw2YW*Jxuo?UNHYIF<-`uPjd*rQL^cv_pC+^EyASQa+&xH;f zflvTds4SlBva12e4)4y9s}0zoXK5c}(l68QaQY?QC!0Z(Xb2w>?Ok`mNI5cXiB4;O zgmC9y>bn!Ro%lRH{@r-WYIS67P-ZRo5(+eMZrPlwB_g`4YD|?O-2ISg76wm;`tE}; zt?aABPOpmhNGVzgx_8hIs_jhkD%9{KUH_>}7S>%qTC_$6dvdf-Jhf_J^OdQr^=XF_LSo*zTd>InBrN4Qg3 zE`FI}a+;mU$;*B9?q~i;gjz{X(d_6e8B<+FS^2>%_cOTBNb`wfj^XZSK$4M_U-V|M zzYae?dutkIqE zZkd=nr?DZFejj<4)9>Tn)4rg3)hA+G@9)_*o+$O-z@b%D&n7&f4v5d@5q}^p8ghG z`D#JUfM0Pt%%aOQLOI>sSBxW#tv`mJg)UZ)CUlXOnFy$PsXF&RQgeGp&F$@he`;Aa zqOG^fe2wu&%9Z<&U9RTLldRNa!oHTB6H3;m` za6{_Ue4EIk%bOWkUhJ;s*j)=dZ<_Y%-N?N8yI%gUt;%*@?Xzbvr|;F;Gu72~?y~DVTU?~h``dNSeHo$3%CfFQMiKO@ds)1sKuM3<1*$_n%wvobvSk$Ak`*IVk?*+XtaziKB`X1hvqlxX z#BuFQTL^ZfIkU}Z&in{C34ErC^L;8s)Qr!j{Rw?q%!#j1pceDzjZ9|V-VDN7GC^oD z-QQ#^DzYDzD2Vui5x3;U^l6#Tt#Dazn&S#;c$uvqMWzQF*fD zl+B8aiQ3OSK7mUrP9?`^{Pfg%fBW@eT?TB}{|DHC(7vsO@BSUUx#v5(P z;^K{CUv{x}RR2#8BN)%6@=#YrJnuzu%ZRY}{hH*j9r)s3E~AcSqVzU z_yv{s#ss}1D({U$TM5hve&%gVqk1&#t6*1Jf%!4LzqIMUV>Y(_@<|Xkoi?rZ<5Qy> zNj|~aOJ|=y@NPlP!fx4GK3H=OFfx!c3hhKy2k*Twc2{=ywBO&$piO|(QRa`4&lHHO zIfq*oHT~7@uuF8d(SP3GG|FmIbfJhDF`kD{t_N;G*kC! znK9*PnU9HF7%g3P%$1q!I&{`%cT~spQ`4#j3zcyc!u)KLW>#*`*(e@<8TTW&JLA=d zkV&p(P57}?TPNL!eJ#t9mn&V;h{tVO2BYG`=duZSp#M=~S@$!jWY7Qd9n$s>pbk9{Xr&cdR3&l(#LhetAAHMYL_Lm`zlJ>CWu zJ*UU|42pHfLo%C`&0>q7YB z>hIgs4n~a%=Z_RT8e53T=;kKkY=28FxL(%HF&E z#1CzZ+s3wjMP&+sihZfZs|1$c%b0CZW(fr_U*?}3yzn?43^``;f_E`%fL?glF-5iMJ&C~b8;=Rz-4w~p204e`xp)ZP4GbRa zf8qZ%=^aI<^URpg|Hu^5#`_}+@4sujvjp!)`RCvrL-vAqw8Hx!MLq@Z zUhQm!gK*Fn6ZEmn>M}24?tZ$aR-$s?9tUGZV{4hpK{qw_GId`hBc9T{EA61AkMuw3 zJbn6aS?On~^yAK&{+0B~n&9uD5vb|Jk(9(AN*S&91Gm&*_!E-S4s8;`D)Rw@4daF!@L=uN@P9bez5K1*(s8<^=aQ z87vDN+VY6STt;t@Qz!#iU6pupRVl{I7DrYKnaXT7ZxGY`Ictf)zPd*x7#)`R2Bo6UE{G*`T$9=}XfZ$~?uGrI=M zz{Bvf@Wj?=4g}1b#(N8)PSIlv#`xjjiY4Slf zTn%&046Yi%dLxz5=1&`#X6l2(pE_PLzwcfwHx3pSZVY$T_dY1uC@Dapq`+_{k{9_i z?`ECA7WCzT+dJDvgBIG0^C6q8+E|Fl=_)%kKX~tCFg5b9f12St>XhRVGLcL(Zx!i* zvsr3{X&c$0JUh({P;G3T(9`oxJcR-?=tUb_hbd3BzaFY1RYhS#)7#7|!bxzb(jmbM zj+bC_@)k{kN5fqm5{#hB=t%-rqJ}t{C9G0<5#pQFP)|ZUbhHmbY#}SjItA*}|FfV8 zBgBi!v(uag!i}wCdwRZurx4;sy5+{!XyvI-8r1w)?)?iP+G}n%)k|S}Ir%X&EKLpj zhEYb1&_mt&dc*NlYi-$ll}0vIZc)6qNK@yzP#8-NeV}75nyxakCLfWh6q-#~H2#56 zMife+SC$o|N=S)$?d{7;lFSpgn#Ff^1=HvHe(P|^ugOJny@WbxY`y$@JqUA9d3Kn) ztEKEQJv~q0$qN!axyqpPZ*2YOyF?dd5ONUXtRGZEv8RK6CY+&$d^v2axST4!P`=Hd zzkHUq`(4@92({f`GBGfJM!rso9wY~;Fd1hXTW=AREY)VLKYDaqKZke7ojz)-e1XIF z#WXJi2MQtUD9(1UsG*T z8P2sbls6IL9nts{?vXLMIh<|FUS)kRH|8tgg6#g=vZU5lRXQ=CLK;{-O=ckB|QF$vIa|^l1 zpHDunXM5(8+smGTJ(Ya=diN22R@+4S{}q{EWfJ~py#4q&>olMP`(RBQPA9o7PQKh- zmpaQ(4uYt>=!iC=r3&)P@5<j0i~M5pEX^5^qbL27skL0n-$ zC=ahX23X7>)p|7{qI-pK8PPTiWPFfnTtkqUupn~V0f}TBrk3(PLrMLU^O=;eAd(OF z=+#S$d{6$Y{1ap)2R8yXzJ&1)P%VBW(v@^lusTJ90bwobEo zgqar`ts?`xU>*$q)l09D&p19w0-Nr8s&lSYXQuMTzc~}+GcPv^_9oC>C*M$&8DZRa zrMK(`_gsYE5BDw{U(G`qZ<;oyx2+w2^?K|X<1d(wk=|Bx!=?j~5-?}{Qx8NK-W$e0 zn}7`_zT;T_@2==hVR*J34Euw zjRcp-wmAMrv<(ux+FbY={(G)9yaRqK)yNTd@RmhpB0HKaZmZA)li7~JY+!)-hS;xvp0~bR zb7=qO;}5a-%RR)z=B%L+H6`O(vXVA!XP9d?fAKJUkeL)=X8cCR;&G5Pf(?EB;#~TA z^*T0%hob|V(=Rv7Z;>)g#)AT>Fw|irn(HNr^dzp8GL|3`H}EO?NnUhOkk6hect+}1 zW-=*k*K+pRx&ilq(#8?*Uza!x$~5!dpkG^*7)C8pbE`8F&kO9^@LKsf)48G(g&K$R zYe!X|pO)JFn(uR5;*nv`wk`z~QRdecRNi~N;hnHZG$GZkOH6WdUTT*8`eg9RtZ`iZ znMk}u4yo8^$w~<>nz|zbk+w3TaX+lG>1d!sr~6}-u5UhQjN-(`1t zjQdyka<3&C!Rn({#=SU&#CE6f&)(VpG@A?hB5Al@*v=1s5`5Pv@T$2NrOZ>~o<|p; zC?S@Aam_R25bnW|(lnTKsB02iK%nOxkbdS)|0?y2PIGT8E3hEfW)j&sbS7x=KQtF+$h>>ZCGxKlUk?F8Gkhh=WOk@=lW zB)0$3t}Jn_eOn(2>=UGw>bGe2D$PGAMH7W9*baZOi3qz7@ekf-DjJO#gTlYkW?wvZ zibvc^DIG&{Vw@fc7|n8MwbF$|Y842zreJE~aHaU|0Sh1YVVT#NZ<^V$Qm zyP0;L${Wi|nYk_Zy1k`t#((!RU&RDTlXh;(1sIMIV(1ZEwGRm2(Tt;O7sXfSCW;ot z4F}85O?zH$1`cGs|8DJ)i$+wBnx5MIx=#)ta?D>oue2~2w04)4(IJb?sbDBw(Zzw7 z!~lxHnoT+XxB90T|GlmV)l>D8PG^+#IhKGM3O7aG;Z``!M^y|!-HbWyeYS?&4NOOi)qrOopFOD-6ET2Qk|iqo9R$xAAj zjs;WtH`#-9$sGUYz`GRQT)KlM&>4BMkbCRK0v1iEG|E{SVg82RAB7s-5y2Pp zDV@o4pa~NG@U)Y6MF(20Y-GC8yjLj#Y*s3xtiJ4@G-|zq2}UJ__hp@UG`4hs%ON-Es0q*7zqzS3MnVRIixP)zc%Yhc#-i2+K#A`1Gs3Ia0=Xxlmub)J@`zm7SNxe(wbc zAG_foELhojY3zgf{pcMMtNuv^b?(eC=Kkit4+DRlVVnb!h9JXtRjpFcv zIH>1TExYT*VXHXEncVn9%w)3$q7MojaywTe27u#@b>Pncp+b(i(lGh|ByT`lT z+-+T*SCa28-_DcU!Gx8)Ubl)fu}7S{^D5K~!?VV-ocpoP zxOJ5dJ25={a*r(9J^Aisp5=K+_I77Xzu8?>;V$=;l<=}#KU!>FMfislw=B;rTl_1qx zMscA-nhw_kM=P8P#Te?f6Ly#7mGg?5ciKr6m%B^xC@pX!`F#Z=x1=RwZStB)lcl`5 zg&y~6&+5|hweI55<%;rBOeLm3Do5^W3xy@#cpY!b8RAKq^Oj4EiUfJWhsC>E;!Rhc z?tD*4ktctgTP`)bFLiUpSrOOsEgzdJQlS#>5}n^Q5>LOpCU6;BGm5l%_7!LqHc5xQ z_SCSeks#bFf|dRl9cOBfI2E21B1&1s2&2Df!hmMi>9F7Od3ajk_UK7(7_QUBUs#M8 zPC?NMAJZjxIV>>=d!b5evf`U;O?xECmlq(`!A??@X@m}^cw>eKsmn#nd-!Xfn5=k0 z>an6Y?=BB)L&cZCX4Kva_`prl=%R6#!w5ws9!M{BTH(%PZXUw_VwKlatDV_%c&mlk zj71p1U$^6_3NPfemio$}MF}-2%?xf+OyJaxjx$=PuW*%0ze=hcbw5(=Hls`0GN(vh zGga}X1fe}~2VPS#uXu%Q&lIkfNUMwBF&Z#GH9u45x9a7S^{PUKn(k zFA$m&!`=C$Z!TmK#l|+eyE*({hs*Ab{8P&dt}~qwm00~)=g2)bKJO-KO?w|e59-i6@ zPcpNq-sW^ygqqJW1Lw(lk~!*xe&cci^oRAEFqtY>zhV4WJS94bIVS0>&i+c>;ZuiZ zEB4yF#33Ee$C6@q`DI>Dy?3g2nSl`!wV+wR$L5^j`P1Ml=mHM=u7Wg={?SnTys?9|5oYDg=YoKcD{lnc!%@83^b~Blgyvx9frb#6~{<+K@=|i zjNS6y31qT0GBX`yYEws6&v3U*!{PJPb0g$wP<#Xy<$kgH7*#!EMD>i3eAnfiN4|fD zFAGq`&eIJ-yZw5yq}Ckl0v}u^GQ3c zlCG@T+)XQx&FAVx?zUL=3$wsu6dhk=b=FArTAzKjP#$0P%tMGR@&^c?VCNAn<;Zfk z4Ym?Hw>oQ#O2}?2NKZYfFZTPQxri@q1MEAcCPW@=&bd||k*XXE`oq`kMN1wl398C5 zo)5A~iSxQrhWpMZ#4dPjQEm1~>8BgbhbUBa=9g{Pp-!-E3Ymy(Nx`ds?MT@gxHxSG ziP!E6R3z2T8G3G@=8 zfIHb=qk!pl0mt?uAbzSDpeyARoL+#=BL6-xXE;Kje zu1o*h)OkJv>I|j4kFolOI#X=wTxzkg&}DB&A9NX1y}+&Zp(7$fAx^ncXvOm#QXuDkS+p?Y&L>r%Ip5qV%S<`@gJ5nz@GW~#a>rMg^+Z36`>mk5f0 z5p)$v|AD4unsDFUk;s@xkaYU$jqcN#Uu{?2Wj(5nC-LUi|5PZnn45Lw4U)=>`c*{D z-HA^9$@<^!LVn-7I~1kNTO^UJP;V%OUxbunGsry`s%4zr@-MauACKQ<5=mnJz-Alz z7l&==Q6 z#BW{#J2Wx1jHB=Tjtn~jhsbgsD%07sV^i9_9_!&k7Q0VLR9B)(TRbZ9_^o(6hzEOT z19D{F|9N@0k*jj!aelM;BSN$l(!PfFCrm^R|Ax!IxSZNKiRZi!N03jORc1r1%vMQ^ zYj9u22T4W~a43nsq#Jlb?F@xJuOeo+$F>c@=Q_>YiZ+hSCEe#LIo!?WR$p`?)e=eoy_4g3+yMfz+$Og{Jp_hfmt;i_Faa<*&|P1|?ZDDEe5A)_unF7O7CztCm7tSvs| z-fY%sREJ5ND?1}3*}H#Ah7q-yvY)BDR%_p}sM($@1*67=?>m;^(b!tTq}M(}5pPH4 z;nuKt$>H&yRq?I~iznVrym!OmO$m>8OvURi4&^7_5sinYpnH@KUCf&-bGBv9vCM4C zoNJl$EHfF?D(B5Dp>j?Q&v!8%jja!a#-vIp^N=6tf8GYZNU+?<{5rdVy zKNZR|Ag#0%MW`i#hG&V-JqY6GSjtNob>t-6Ft*_p-1~bgaIYBXtoJccv&t=6N!=tH$aqiq10x$i)Xsts9gDP^qDXQ2}cZ4;d{7kN_Z_pXyg1+UJu!i;g^VgDupjzn|_Ln zz^P$+zqTC9=%M#(&)>Mu4xCQ!*U|U6t}smN{W^3$c>@1idcP9eGaS8NDSy>^zfwQQ zPU2d-;?!N$-Xi93>Z%-z#}$CZ2f84J1lP#@eCtpA9OR3N&I zH~qk3V0$ZfQ*iSFPXHazAc3?_t>r+2&~?D69zy;E)N&3qqS^IR>MIRn2Vuj1o8Ac7 z3;A9TM1PGssfP}I>0)d67+O4+eu{p&#f1OARVN95MBmlBS{K_6^6yg@TUedAjNv=Z z+aZ*H>OV7#dcZ}jL_jypLXXEQbQut`3fY8~mxO3}kstW0-!d z(`mjMM+oqEl|XV?D}!^G>MM>!CR6d>aHB>&uhg3cZQk)|P3*i`>L}HHMTrF>zrM**1 zC;K9ay+{;kL^3jjD|{lR{QQyxT13O*%hjeiz2du!D5Y-gbZR}%wbdY#@(I zzdgX%+gna<_!zjeqi276wlVNd!vEjuZ@=ysxbAbU`!fEYdJJ@*kTdCo9Z@@`?nv8l z-HwQUk^OcB-wf^#HU+;5z8d^8nEFMAu?08=B>kI_1laf`$BjTTsqFa_N!CEpXM_Qo zNU@AuxcN!XVNH8B360T}8RjIlFqJMG9ar{HIMLWh7oS1}Cy_vSB@Z+P>6wuva5{C* zgU+Jvd9b7U@pOt7QT>=^DOx;Tzd58wzbSpkR2orljfA4887*38(nyHrN73bcW`)ma zew09GQusXV>?6|fvyMpT=n+YZg9!KFVP-~QRw zw@l9_PNyC5Vznkw+7V^BG>Bx{dnH2`N;3B9N(#1y;)m-{6mGf1(V-~l#F5U1fAmBr zQDvpZOi5%0h3>6$d#p3+N{2s+Lue1ZHah{@A_FMqe zPp3C=f*pp=L+JPf)g=&~*HveoFC^RZ1wZH}gQ`Gy5)+MBr8hA&8$F$d#YtaN!{TIT z>To6vi&LCXXPRJKEkv;Njtdcv!fpcLCAcOu!8o0UMWyudtXjvF(nlQ%nx9U?;&mYn zi|kt*4$V8%M5Nch9r(L&JKMc7c~fqjWSt5OMu$WRtSSl+8i+rXHK^l|Ra(9}&l^LM zLIRP6C&@c<6wAE@&RL^(jn`PfE?SE#QLaGB4Mc=NE<#fc;unv6fgB58l=;3(B%t4l z$X~rj_b%J4Cfe!dU8gqi#;@$avg~S6Cp3jqu0RK|`hW4KOTK99H~5Q1$~Qy#{)O{F zy?3|g-JUc_`EyVEIP7sCH0sEi--merovPk#Y&e-}Z2L0R*l+|{0bivW>yEN^2jaRJ zxZgu2z+aFZ5Q#o_*L33v_9(UyZy(SOtRXKG*w>Y6>>+L^aq0@uOe z7ib3t>n)^m`kV^En|B`cnhU(jK?>FZ(ne^y!`806i3q&G_HNvt*oRudRbBJRTjhBY zdufjJ)}y4QFD%OYrNV(c6hL6JIdF;)b~1!TQP>C`w{LxxtB~e|yX5G-%S2@sGJ0do z^&BxfM~{CaDLIgyc!wN1o?OfpUk-nwPgQG4l+5Nt?{w%dV&|59mo*AKm`1dYpjLRf5L(eO5Y&|PDAy9 z`O8ZMujPVQn|_7H{v5Qpzsbb`K~81UA+~inhyKwqw%%)gbW}FrofpEz)T{k8EygT3 z(jBZkb{`tRT*#KJ+!ul3(7LMQ5-+o(1>9gGv?1jzDvYv9RX<5e^}$9}s@~kW#Q)~1!~8eu9u*7aoGee+|fDkWX+-`y_dUUduQHmwT+iZ@h+yDa=hDg4sFPw|H$hP=%?R+D|yuCF9`TGOB< z^SHF!o<;oQL@8o0U{~BRD(>jkLMhzm6;eq@YkY^AGY?a7hbYi8B?;@8xk#>g-j0+V zOH9I5&m+QSk3K6L)A2hCKRfs-@a>C6T)qznkx78 z6BVy5=9_n_=a!rrA))`fu&YzThd|Py|Nps7N|?==l|z3y-I2#w_r_HJM?7nFUV%1FiJ-mb ztQ-vQd^|zWIv2G3pCR%Qq4G!u;{y8{OtXxPK~n45WVB+hK* z8A=@T;NMCjTVrDI{LeW$jy#6Y8i6;mvT_vtrhrx0Eo@8CuVLH|I=meji?^b~1CqFT zP!fAUvNv1Qr%OKfs87kjd|p0neIFFjx~KitJo}!uBjbMzF~em1Ct?jg!aQ3J7#Z++ z9k&S`67}b+V3y4O1Qm$+x+T+}I^x__%h>$o7u2#G-d)cess6pJ>IfnhuCydp9_y;y7hN+WQFv;>S~)MWc0DFfqK@QIn(3p^T3aI` zcE?igP2(Vb1DaBl5ByQ6Ual~g9t$I~J!rH zM|9v3DHLHY0^2~Ps_-{%lA)$XS=9Xnd7z?V&;;UyoncWA0Sss=fV9~@8$56y=V z{vK$qv7N8BocD_JAFTSm`kQnKy6RuOvPado9PJK50HvJ5;)b2ti8;2)ui5-w&nTNM ze>En_Jw4_Go$Bcb*F7(1$3XY?*FPx@A@P1?!cetg4^7Y*!l*D|JYg~<+uHPj2dq-3& z6ERo)EiIAXk(idun8~j#EF8)9MSgH%e$B<#Z<4;kdmVwV@YhROQDZGrG= zP!I)&1=Aj3XU6c}#+Ao=X4E~}DPbbbiYyT$C>G{4ToiOcNn{z+Jt}Ez-GHcbGk+!M zsWfS>3d8k+;XUMCP@@uso&N^893+1yNLEP-<~)Vxd4lK1mfR1`Kd1;OjM1&7e)!;c_=97(PW4Gu>vgVZclA{p#vH3#aJ4r(?O%z`DH}yf|6w}5L z8cS#C_4cH3Z01>MYzY26Xnc_r;XJZ02vkaaSeucS?{B zJ{I+Vf3p(3!Aw5L`U#L zPOo*1wqza?MD#>KW<~Kcs~TcAuE#A^WN99eCL5Y@BMbRh&VoWU<3_LSSV8V(E^jk^ zox>CjDJJ`fpk^IfkV)pgnoK?AzFn^+GWWC0Xxge~<=M{1d;t18fLNyC+xqjK<&L(7a9k}yJd-N3-iUq`_@7_GU3X5Nt)3{LCt4qwFg z0={$1d$qHc3#?x}`wrF|<}awp~9k z7+e`810eDLeTk&}2U2#%zK73K?d-R-bGVJSyG${dN=WEC-qCy&(v9@c`KYf+cSrbQ zTl&j$3wxkO_)6oZ&r_NHL?Ig(Eo3tHW?mN%?a~a2q9HvbTP92}vM}j6TuIPO+LJrit%NhVNGBqzd+?ePp@fiGmw98| zSCYpxn|bRg0`@B*-smx^{BH3wKbPf3W>-t9sx=Gg)#)G|2M2cgw#e<;X7fI3!(qbn zK}$r^d`WlO*xG~)1Y4YxeiNzg`N`bo5R@IkOm|VBTORno$Xo-l0!xLI=9?xHk)}8) zzRVqLF^&D8jT)>)9{)3cXJrt@N5)It!L2*Vc5qf|O;#%0*KBTMKGOVv%;O_0DWn$> zH*9qvZ#2m;f?P%aft7IJ0h!{!Z5K}4kwL>((swt>7icLz6TyG1O#B~6!TW#cEDLr) z6_S*B{+Ghywr(z&M+B9=Z2cw_|9;Y=*#0t`461pl@(-vvR@Fi8kif%ox9DMWDN+m@ zEB7&`!%GY4pFZ~Q{g>q6i_C7D1QM^wPSN4nRY%q(rlXEgVHxmCs5Gf zMCOdyzV`#aQ@e-K2SCa{nD5YORxVHM0(W@Tnsl0nC|TfM9_s~09D1AOTKsgyl>=4l zyNcYUYDi<+CTZy2gc@bqISpZs>sOP-C!m(DcRl|TN1FG=(xA!Q$J-6N?c~z~3{-6Q z67xoqSN*fRpO#5lyTli^AIa?ni|s3QWyNk-4?_)}C6;Ju+W_A3Jyo zja=fb$7CSBb{TAx-OfxwZ6z+|E~dGF@ejs(g8o#g%dC(OX6llKmGoQYlTfoNxNal? zOT~X57bP13xm?UCK0Swmp`P1cOgeN5-w>jo3=uuEOLbi!61 zm(wShR}bced6^V^I`_$MkR)#8MBl16NrIj(F+7R$S|93}#HWKuVmwK}X|}vzyC3+H zm`*>C$F||t9i&d%m$llvOizE8Lg)X0Y6DtDhdcGu*53e~q)nNF@l?Zzj!_t$UG?$0 zgiIRKp90FsoF1gK2WwR0oRRJOhvocTva$PuAAp9nMeuXbb98iAO{!9mG5_671ZELA zu(!45dWR}!D2elqrrI;Bzml;ozOr7HZPanVFCP*m2JhdHhiaz_W$2#v6372M&Hj*( zcn&148b;?9sd0o3&Mkfaz5i1?Xv#${0=VF=moP_g^;0OW{c*6IM z=9j#AX;sn=g5H~0%l+gPwVTso&f428TK%rEa~U6aKw?i*x%fsC^vDHj3>gghn$0wF zL6@lvC)Y}bDws5Xbk%mh+#Re@$dcd~JHhjMBsf^dFz;nx(&rx1PyI8{Iqh*({LPJY zAP?GW{0ug*F14&OTbtIgZfKYlsd9vFF)x${JuT*K^#0P31sVd?sg$AWHE(p_m4{`? zoo|i1?DJcKHKh}QE_*3lj`;#L|UUIF}L8QH-csg zTtY4)upvgh9YNjKOERVy-Z9jCw2wRMB>WIAfl6^Vuen}tN{GeYd*hW1)vFm#w8?l2 z%=E9|rcPcH_~O+vHAede=mSL@QQ&>$8keq}r!9{54WE3ZZD`dICgz&e7e~*gW;BoA z-X-t!NZ9E^`cFIQ+cUXAH9(%d&>xFTU)4=mT_W)rcSfgA{+uqua(l--hm_!<%$VT9 z=&aekn738!h9iN2B3ezcKK-%#Z`oKK>(xw7W@4$J0;VjOEvfE^*#7FVCN)^Zl! zNZ=32dldD?b@!Zj<{3-oV*s5alAj1}VgayufV|ec#S%ztUJzyFF{N%a zpQ3Yi#+y1~%X08RddtSvn{SlyMs=Dpchd7uIx^Kn5WILN^~qRo^`DJq5wAvM2TWmT zGsCk~q2MX;J61-pYtJB+30fi+_)Unh$B9b&ePn)ak*;ftfh-Je@& z=Ha8#3A`Hkz4<4y(rL=nr8zJnpLJ4CN)Co%EPF_*~U0qduA z!%6L2@?e5Bz*m9l8(7~-Opai&Xu$NuP5;xlju(WWAE z2qChN>xsb*&+4}#deiJnOP9p?|F-F-mMnUcNYz5R^s*vuspbjkU1b*VRc9#h!otTK z8>-U+Wyw;1ov39upSecWU%cpBYBv8-PfhUEXbyQ%)k(lF>B&T68@q1At(!SjEkz1m zIv6zf6WOkxwhLRYgYi`FByr3mQ<&_npT@u6^RIU449AP<=+o3Q1IRFO+oZCfX0u^< zwaz&DT-X+ji&7IzCIu3(vGvdN*=--&`4(P`zijw@#@wQ@^=0u?;*OchSbV1rWrQa6 z4gmuTTol(OL$I{48LVpqMx`0!9XLMtOPX3j+Z1>$upk;mAZB(N<)X7_LC-E*Eawxr z7Ij=L=Ci+nNVer|A&}mqxS72TYXj-G3cD_Ip~7yogPoGmX?IJaAx4(^sXgFhjH#2nqZFk zbcrnO*UeDv;C5MTcKG+|`D^UT2qj{z(fmsKKiM8|Lz{gp`q-2op%!`fVPPKdAJX%C zWx#8(*j@S!Ybm9H_eGhf@&js7wizGu8{C!W`i zM_UkD43_-?A|7B?q$08wqFxsSUO^qi!yzHkJ>8?Ug6(rVxxu;c<^|O63iy zn9TaNikXAVAv7{}B40HyV$WfEwJTXn*SCl47hrd)w3g%=TXX67`{zD;SyQ|M#td?C#kH9i%+mB2%3>b*qr zV`)ap7uO>>=8!PGH=Pe+56S^K)#VfieA(M*!vlS%R(1+58)EY z>!-YBNT)jNSO|U;i^~{Lw7gUzAH&9bh2mw!SdKduBAF^&w1mSpsa^RECZH{Rv;&v^ z#^B|vm)R~SRG2}Mm=;^xse%k5h~?1bq+-iKm1kZ9j3LVlmxaWUx^Rm&27B_ocBp7v zqKqg~&Yc(&`kovY`koRW`o4Np==<6PzN3vOQp=s_4t-Bf41G^Y3VmNaF7$nEGT%sK zg^Z%>a|$+>VUuLyRIE|P0FcT-u3?IbHi&FQCJ53XQgMhdq>|FgOYg4mWT@anqznkK zsaRd)os~aRx%Houx6D&KagIu1h#=|&$Wd-FxbeQs!_%@^`MEf8pSrZnQ<71XS6sRx z(iny`cW!U{;-ZguWv{Sb=S z6Rb`|my{*Rz}(4f%iJm(yNqR(LU8l_2k7zDr!0I^*n~(B=_lIrHt`gjFoD^%BWz55 znha#?@jga;#$LS-{umbazbDf#{!Jb3$lN>ZF2i$IF+E4Ih-@P>+E?5led@x(;S^jW ztA-lyIFiibk!zRfBS9qyb2HR82e6e|lNHj6avt$yK6sLjxUuzjlVsetb|ANqQ_mep zdtbw>!AoI)QoHNO%HCACkZ)^KVG%(Xp!7JS#KUQ0mgPn*U-prjhaX5&WgF;L`h=%@SN8rZQAgRlS2r zLF$I!Qo+4~zqdXVTvg`L?N)|TXP~zqyP#)Exqgh0A-hghB|T^P3Te!$Fke+Cn=D_c z7IQ_Iud0Ib@RVnT`6`O%hNpaGn6D!6HTViy;(`zFhyQ2BR$T@)E59SE`7Y!utntox zR2r{S1Li#USHYa#Eg9j>R*jffDgR#0IEJlo6+~4^_0P$j?dm3O!{)r$t1auKROC{vOT`#GL{?pFg8(}VUH>)wZA5oxE@716kL{w!3f7UbVeOA;fRn%Th z*@>!JW0OQhO+>FIdkflrHEybYpVXnuKXdUm=fz&_)=5xRc7+vG?&#+9ZnI8MRr52g zpc_=sUhUNhs@UK{E9k8%Xs@>F1XVoo=}&d7Oi)3?+bR1GB5h;XrHC{|e1fwA*h0@L z#}0l59msF4!9@QDLx?Dww6-7{Id0-7qj+ywy)+3&-Y*TnSgt3QPWW&+zIGbDWdO6G z+Czpg%xjEYqw^HMa2djq$N#q6F2PG?B8h;t&iXZ6s7LZ(R0fM8hhBT|XlxyGrCu?K zt_bmtXpA4oBJ2!5@t3lkZSEv*4Tk0_83Z$t?O4o9gH1`qMP}F}!BKw0fP%^!ZX#m? z#jythQFHhVj+n`R8SC+zAM(ppemNn(+mv5SAZm&7Su8%A7Tt1xlT;dl=TZ`p+c9+d zXWK|;nF>3U)o)b33VkR42?;89ES0=Y6K`cGUa^W-`1RtIhvIovys}>LsGs|r+SzYn z6M?NG)FLD3>z-(teGM6G*V*LHEANRhVjp-2Lb0PC6}IH@@w@;q-_3%iIGUkBl4dno(y(p zc6Yzwd#$cYkYPZ05dj_O6URq8nIGUT2?j6EjEU?}2t8N|g&kIkCslIQGtNZtX>5I+ z*{yvASI&%e8(@Sp#!i|rX^mU)=lxCFtnzasimPeCn!3a4Kl>3fD-~M&G~S`b!L4hc zp?S-4E-lUFDiV7f?%)2zL`#UbiJGh#a2lj*2j+^@@x2+ z8&An;QtzDRNZ>Vn=JY94wn~sLIa#u;ANiQ$rYmh*6}FX8=I})vZQQVlGIF|6zd;iH z6F1pgU!@DuD6ZS3j;z>AyRUcge-!9N)}0dnZ)AUJ@ox_y^_*OlAF`1=nRh2W&Qjsd z+FTpqnGY_*TC>va68z1$D z1%oOw&>>EeaO|#znH)^4|0~Uz`yaL`G#b=da_TX=%_nrS$z>Zqw| zAlv4uCjQgL+H0!zDf@o0*F7qp>IzbQ+(@$hHdEE$uZ7_X$BDg}rJKWt!nS5{t%Q(I ziw~ueo^Xt|2NGUGfb1rjT#Y*Hw6@aPGE?9+Y$dnMAcDO z-qTK({EW;@Z*RZcM({<&{`r z6NPhF?~U(-VW;Z%TMyd!hqK<5ePTB;gxz|!xSgbXv);#qJGE?|UE!21hS<7hyDxzC zKBijCZaSWFJ}&pQNBBA-d?&2Vqvqw)bzetb zW@9GE$RtL12NU^T=J6vh%czH^7~u>N8Q$Bt&IP|1X1_hKP88Py@H>?x$5@|Q)m;R# zib)^*CS!x$bUviVG)J;8;jomdv^`vb?~zA_bEPjKfTiVcbK<(>+U*S!`o*lurL`3jGB!h{J57sT(_xVQ`Q z(CeN*!M)(_BJc7-m0_uS8L}nvOA!^1z;Ohyi==Wpzf0LW7wO&MxVV?AgA3AeFI($I zn0>jCYIJS)L~{vn_$|f~LY#-WI1*7J0Mlwgi&nr2OOtMqYk? z`Sr?u(n+E1nfHoi2@;3({2WRetZ+46F|L#4-XYFutbk~p%iyxhV=^0KmD zE|G22W9OsaPH-!LhF~r6WW5z$=8QaVo*Osu>xqX|sqTCU;o!l!yP@LPiCCFQe7Ojm zG0*WOKYg8(Z&+C*oTzhmSNN3V{Q_Tc@mhC2stSrl{Yt(x2G(z~yDw`L_j&dj zg}YBRQ8Q)IkQq~>7PH)ns)>>{YalbeCQ6pDfy_}gQL{#Tdw(QWGT$$UvsMCQ8<ry zkkh4Q#ojw;rgxNi@>WeKDk&0wwLUf&BDsTuj_8*qg0-BlKPm;P zOKBgKV3xy^IP5+V3h-SCpu@%zw>e5Ji6DboRvMsRFAEl(hPil*+}P22h6JBs!>1 z@7_ry^F9y=JSwSyG^Nr@*MCDxZ8vY?@|Yfi?__f3kp3AW>-R#M`j61vH@05KAk=26 z9$(XbEM>|ls<8THyV3R8?OUtFCx>&(Rncm*d`bPAwR}-%#q*ls#U}i&nO$tc>zdKU zCVZ}$Tx`PQn!&{;{H>W=-4Ubak*wOex9kFD>e6q1_RO|BmWm8&esS|)oU}Q)N*7iR zjDs6IW5?Mhab)8mJdWFr<5NAl#8S~kz-Dt%zRJ5}|=v}v{T1=7&hCfJp! z+uHURr>(uWOt-a71Tpg?;wP$EoQk1_sMNv#|&LSzbBnpgBtDz{i z9UPW23EbHF`AG8Nc156J9QmBUZQq>;i~;uFo@(R+M^~j9+kyDvRO2}2#@ADgB|ujR zVSq!gr5e@y_&$hy4dCdTga>lwPB*q?PdEI3qm}cYyJN`x*z|>>Yjc8yUkO~;U0phn0PB)$a;x9=zj*m$<_RmQ( zwgAbTJ0D$$v@*;kK)o-+s0RE%4$x7<*))*55lNGPn+=VQ$1;r6?;{@sNc;)$pCJrp zK9Ky248s7rp3gA$1K#EgBLg@N>;$$0>wqOlB^n28PN1P5cMs%_v;B*|7(K>gkZ^TrsxjYJ;w@TjslRc{ zFVE{vwtmFZ`u+k9$rC3{o^tgy*G|1|dRlr$W|j*2KlnFf5ICLYx8;shV-C=@G}Z88 zp8gkT7;PjNqm7F!2>-gUPxsTOrG28;rrJULe2Aq1P(L{z=m*H=ll}9*v2BjAX9XJ7W0WSKV7$6=<01|<5z!V?_$N=U5xxf-2 zA1DUAz&c<9uo2h{Yyq|b+ku_H9-s*joaJZZtp+OWGJls}zBUXQXXLk18%9cbs`}b& zneCSORE2i$w9Fi@wm)l`OMKcMf0s7BmYH<7w(qy>e#`!K&7)TM4d2q~Jh4Wb2EX<< zp(haY7H+8tS-Ck`$>J_QsW)V!sB;~={#4oV5ck0r$hUxsV0{a%AZ{0%Pe?MjfDIddxPX10z zc*Y;Me7fPn9ESg`ChIi+W=z&|{_U9P@bWido{M=HlXarM z9g}IsXu~7rrQDd5$JmG|^}Y==8*>k)AM*g_{g~~T>oHvg(~So(6ELeWr(kZy%)xvb zvk>!nOh4uem``Bt#@vCqA9Ek(UoekheuCMFDfJP*LgT}y!beQ`>IZcZ!3!;QUkL8n zOZmn@yZ+G21+Ai>UnI2ZCxW-3x#ChMtSd6mARrEY>mO{v&#(T3SAdT2E;oO#! z7~$VyPw=N35mx&Ud-(6xR$b;zp44#XQ@#`KPE$zr!${mQ-=$CvFl} z|NP1hzpL^{TY!c4?e&9aC_%{#$YJqCtOW-8X1$+erfo`B5-~u)P>wzku67T~N zKqO!Y@H<=C)|r$I`aEvjqQcv_3!d^5yZlr=>CgX_|3WXJf&EM6!);qE{s?!ooD?GA z@f~-A0K-p%njS{<6|0+nyp_K;%)j1M-vaPO)<{Uw%?9`Smshdq1!q zke}G)+YhK8go(B*0K&+;ZX8ftoT}z-8O*O_z9sl1CTFU7-kdk_2S#CELRi63=3*}F zDa7lVoN07ilWAlSM&@ntEv&T&7xM=5KHOy9c$DugeCGl}zm3>)G3Njoz=mS-#4VAy z@uZcAJwf~=9%-%vWG)ydI7mA9yGVBqrp!Y(V#Z*u12()#T>&oQ#$ZmtZ=IwA9N(|! zqucq8pOk4F#Xg60=MZl*u${c~@rx#(1Yp0L{IC}TiKG=n*b{sk_-!U^4CW!yNFa~R z_;-xK9skX^J;ZnQwVB4aH%W`{ zCB%6G_oIAo#I0TMAXOLzh_IT{$_--Q16uyPO;&I=Jy{j3XB7O>P8-WDkiC&rG zNttSnFY|aWaoP#Hjx=1U$Up!H776vE{L+i>6ZW~z}&n#I_234a{? zHeh;j-@o7Z^g#k`o_{H&k2s0k{ zDTF(Lxf8n!^EhemBb=Ku?zlSBm_qy};Q#&3PJxseQO2n0YUSeu{`0ITV`ne7_?x1P zre1EjxE<={b{w}8z1(tVM;Y;HJ@eR%TVgM_p*c~;xb&Xk8giqIjEtUc4=;@}wrBNp z`x$OKd$~2-NxqaX{PzKF3BBBG|C?~X6IcUm0-gn$fP=sXz$ZW#5I++U{eb*F#Owt6Ltpug z!Mp~@vh2$+*8sJ^4}hNmyMY6M{5};Enhym=3GIPo;6^}x%P{W(9)SfTw}&Km%|PFo7?DxcTG{qyRI4CBRCc7I+${2lfGn02BBe z7`lM+0^@)b;3i-RuoCbCn}BV=4xkA*1eic45J!8v6qpLk0hR&lfQNynf!_e~+mHDd z;3J?Dh+asZz$73GSPGN@)xcxGPk?%$8F&Zy2SM=fTKVMU@Rd%a1oFUqyRSoi-2W78L$D^1Uv=205kyyfWH7A0o}mR+bKUV0k{#E z1Kb9z1l9nxz>~mpKm%|PI0k$I81&h3z!+c(kOt%e%YZe2{I*zTJ?25+BcR_M)HyH# zxCvMZ_<_fO?LY(Y4)77s4aCvsCjqIzVxSOM4?G6^43OVjmf3;XFAu%|5`knO1(*rQ zZxy=NJ;jqJS!%5fG}xi-q?`*LxrOCiW0;jMp)x$hXkkxBnR(Ijyy69NS*5fD_ctAMUeCNFlGd=-YinT2xf-_2m_3m3us-Y}rJY;BvuWPAM5%e(KxtQ74Fm zTII>l@GLL)tOj?95#~OtB+T7P`DUM|e655-(}jnZtL3?+O7%$^Hz#m)zH>|M0Js)c zc+0s{GF{@y_wur}>U$1%6Xp~xE6*!mo4H20Ku1kLg{-8Ai@LnyE1OkPP%43N$u7XXp8WR~R5D-dU~&-WHDEV;X=M3_P@xj625 zMHQaRHOoC^7Gvnr=IiGN5|c7W;008D$dkVjq|)O5-M{(xj;!u&c~* zFhp&o&l`%rh}%YaC0=>ryuu^7XRaYf+qJZ8E$Y{Ba9oJ4DY&*mBRIz+4aPwBuvC_I z)Asou#mnKr2-VB2cRS53uAp*MX-EYd1P-%VEd_U{ohYX2vjz3VhyPRh^~N{6wJ4s; zDKEMUPJ~YjgfEl=230HJ9C=G#k(c+%3%Dau?3uT0rKsO@`Ua;3_wFke_$sK@e22*w z6ni{nLTi|>v|zrcf~#-K6+c75Uahq6HgK2Kr$~D!FE1^p+1l}YwhvE*Z*^GfA}?at zvBO&o{YysCT_7br+p2J!gr|Gkt+uV`bGknFOnvK&;?iY#G~HtIl03EDVm!wl)>>6~ z!7LQoVjU~49ucOat2GqDW;LDq^!$ABRyYfDYJDfVrG@M&HnqTecCM7^o*Um@wSo&x z!s}TreWKv&Q5_svlJTD6NpPSnio6zSZe@jEebr<@S(u zy7B*X^N8M~Qm+v~jajN0DSR3H%D8PA)@Ou|87uNb-TuN7qRMo`={tzz;X-R#v6>^$ zo^OF1rFYLOU!gj58S!w*_IUH8ylF*V8A8Q%QIY3vxs)3oGM86~>7~V`_E;H8-0C2R zH-BEvB%MM|(Hc*&m0D&=VIO&9%t}+qA)Q{2x5Q5?_f-_ynTmZ?DD5=bjFWpYonsF5 z;8pXN17sI7Q-!CP9cEuznu0ZnBl--kfg5?x`h%na!QNW7K>gu zemUGs4l9DVpl(^yRJ1+imTGEd=T)rI&N5TUm8PrbWff$GXo@nWP+7H(UiARS_fZeH z3e6#1dC~F;VFt@Z$rbUcnTzGB`wI(y__4gmBUMTG1z!5K5M^+2YDT^_346rQffer& zBCO!21eWx}{AV&p(le=^?lxcHn&G*tXt^gnugt;@9?(oDe!clY+|q4kki6`^!qTa& zsV?r&mU)oS8(R+^5_^$%bzYg352O>C&hvStfK1|weN2c$btCON3su>Q+|2B?Eh}$z zQ86Ud{kd+}A)0D?7$HbmyJ;TO?R!CKaZ$d)P4Lui!VvRU$W%$&b37%?tcuEU4!Jp8 zuEWgCD=zSsmV_~@b{DMe$Wk`#st8Q+aR|ADmNb@|>SMe`w8LHp)^!6?97~$ z!$L7d45NqQC45!m=sC;P4I!(%bhTn<(!yn?r?^bTkr|QIyW_L4jJw<(9Yb)D{%%DP z17&%7abAV4v4tgtrKPKMn2MQvDkf3VXNrj&O3VnkWz3QpC>O9*e}((ARJ>$N4h7w^Grlhf>vc zYZNB7)pzm5P_1i+Zz0hvYo=o3XORtGhG)-;awa>f`^ZYfRKn!V2Vtfp_ak<~W4M&~nL@rq+tMf4R8_kmGTK@Wvr1S}J4`BAhFr9*Kzao$G-HKE zRnKk1r=&8jSbla(bX=_V8?x)(+p+g(nU1T|G94Gijo45CuCo$qVAtJ`H4EtFraCAc z#-1FB&9}_vbg}hp>yC@n)*ZXm*0I}-Msn8*Yc(bgTDVIFVRKT)1#((AN{AkPgB3=( zW#|;`FyX5q3w1)v+QU+^Ed8;SuDvV5{*sfI?KUTmmtNjEG+&*5Pj|=7j!GVckj*H& zgT+PIFGPzz`Y^&|m0Eom-xz&yb*FpB{a-PSEG>n(m3cw6siHIA0&*^ zxv=cWvr^UFT8K~8fM<_G5+~GmV(Zm+X34;1#g+At#!dL2S%0zRVPt-b{YcA_$-GC0 zk{&{Ax=Dn)<>%zFb0+xdb{s0PwrjT2W1)7jD_i0yjj~o#l5g?TVZ|m@V24uJr!%=J zFID5S_$%^TxQab9UyoxfM9cD6@PzjlR0vVmI_Oz;i_0vVm7!&GYD3TBtf0*43Un&c zGYI*_B|Br5>W{+R6w0=Po`>m(dj6oaCBb=vmItpj(&N z^NNdmA|@_#p{_FlGSV2+N}L*#fn!eT-JbF^UjbJdRhpKIvQ5ul>8r3hJR!55X)Cs( z&Gl|n>>fH>hqEdaAI(@eE5le`x_Y@cY`0zM zjK17umr3yN5fYYIp&WYph_lSW=CX{`dp)68Y4+`rmqbxJRHwMAJ%Jvs zY@JE)9&V~uPI1+96#|Bpia`G#dtU+`MX|NrSqTsz?28d1`=<83O?OX#fB^zT5&;F2 zkOUIRW)gOUh=_=&D99oxC?JT4kzE#vhzf{`8Ufjiih_z55fv55|DNv5WU>KX@4esi zea}DI>FJ*8s_Lp!XL-*##dv2H%KA+A%9p|@`B=$iCGmDu-XEBpMQURysg;!n)Kso@ z&wP2DB{PWG>Ys7J)1-{<^pCFEXIF8~tgkvGft;De&$1WUi<9Hv( zVH~G$oWoHAQK3PoI}k1TBa$$fsg&`Rl$OTy8<~nZ9+f(pRCruOCEG)5f6GbCPIY`G zxb)nn$)hw**p95h#^ZiWy~ti-FS866$~EV@a+A2J+;r|4ZVk7N+s7T^3b~`)39g7c&7I}W zam8FMz5(BYZ_Rh+d0ywc^L_Y%{9XJ={$4(tpTtk+XY)_-&+sqsYxxcQc76|kfd803 z#(&9w$6w(8;QfVKLIa_N&|2s$@PaOM7y1a}gsH+z;c;Ps@SO0XuwK|I92JU$XmNnJ zP^v2rmsiMJq8Io%P%Ff%JRFR^=0}idVzjGKct`1 zPwVIOD|#(gb5}dp%`Vktx%#?pca3pnyQa8iy5_o;x>mckx!!QS<2vLz}TF%rCH0YRn{BUyVfD=xOLk4-ulDxbGLC%anEpLOd}8*fm2Pk z1KXA5+2`1m>?U>>>(ABZZsOcrUoMWD$>nngxQpChTphkKe*@o^@4~aZ%=gBaW%1+q zsr(v#Jzu~d1XMnd_^9nEL7U6hT2a}QS;O%)o0W(=6G|e zIm=vVK5xEk?lM0?Yd@G5%|A^)E5xd2HMJtFP8MgmEVtDYeHdWHS!1j$Ymzn1dfZxM zye~9kxzc-&p6ZU#$?g=I-ep>YnC)7`@%(-s9fq{?h$3^?3xt?_Z=el!!xPjbV z+(_j`;z;PyTJXy`Sbt&)jJUMI#Re-$QC9E z(}mff+Gm6pgtfv3VY{$LI3Rp192342z7sA8e+d3!EwO>vLToK|7I{$@yNi9qf#O}_ zNbz1VTbv|L7iWXUpAlaW*NPj&?cyHsfcUX^O#D*(PP`!g0lKdxHIQ0Jt)Wu zsgE>Jx=R`<-795Flced=Z0RZK8R-RSt+YYfF71&HNFPhbq%WoKqzlp?lD}L_ZXmai zTg#ngUe@LAavyo1e3v{@zE{qcC&|<0+458JGx7`aT6u%KUEU)fkUz#s`cnQ5tLYEf zU#X=uP+EY_J1e}RE8Ueo%0T5VWu$VilC4ZqrYp0Rr<7-u7nHTi24%al2h{tqa!mPB z`A)f@{Gs@(wbTY`3$?Y{88oe{-LV=5s&`>M+^c4*lho!u^WowhP>Dp}VDeW2U1#PXi zLEEnF(GF-IYsa)NwYT(rdZGT6{-eIpwcB;jb;|X<>o-@R(ZmQh+8SLA(J+iCBgTj~ zh8amlnvrWvF=iNZjQPe=W2Ldq*ktT9_8JF`LgR#S+Bj!iG%g!~W~kZ73^&`FT}{z6 z%qTO)j5mjwNoJavYfdp|m~+he=2CN|xz5~V?lkwB2hBqBgn8OLhxK&X475V6Mpn4h z*6M1BmSII%F;=`a%t`|1&9$ajGpsq*d~2z-(pqP2vUXZ~txv4at#j5DE70A@9pM(; zhC9+7<&Jj8xMSV%?ji1B?t8(Vm%3NF*I=dPW36oicPMc0bsusUyDzyf)0)e|{}kxY z2C^Y+C>zE$Vw-`3$3Qv`VTZ9J*d#Uuax#m}WoNN#*nDvHZR}3AfZfaPV-K>2*doZv z5J<}~t`XOa3+E!Zwp>R}<%V!0xFjxxOXIS*Ty6q4h0Eg>fr}P!dm%{=`pD8^E{t!+ zhw~AT2p##ZkO?BM^3i+>xNR;!fuF+X@iX{Y{2YERzZ~*mAAgWP#1}$NoZyQfE6(zl z`Ea4F&{60ru!1P4f+0i-Q9`_sD@+mcgc-stVU93Ym@h06mI~{HgF+!>>Iq2I(~v0V zgks^M5D1ylRb)j`R7FFK6r;pwF-9CFP7!B_v&1>#TyZ|6%~El>xKi9C7K$gtBJs3% zRy-#bix;_BB8SRhaz{B@j+NsfM~2BGP}(Y@60ZzXMkq;2ijoE$Ay=88Oi|`4`N}qBr&6Ho zRrV8)LeCfItBcHhB`}~qs~?5t83JK z>LImIJ*u8ii`3KVS@oP+tcGf=W@xe65N((?LQB$8v@|VC%he`mGqt1IB`w`pV(c)! zGGw!x`JL6$J&5Qn4>}l5AM*pnLEv?FgWHV)zsmr}8wZ{@6%!KF6J z)74e#`|7W17}okUZ4*}TMeP$k)|h8bvhpo|H}78HE~2_2v}t?p8`#e5V(4=c`2UmK z``ky|r`%`UN$v~oYwla_2ks~C7w&gxA%1)if1VE!5`~9_CBmzqht{HkS-%CGbU66t z5$QK6M2^6mB+2u^`+k?}C^tc#-=Vyti0T;iL3OOQPn)i9*LUkdu3XpC(4)QqC;8nK zZuA95XlCAHjy0#751Wgz$}gLBt@hSHYqj+{G^j7Fj#!_MxtF=OK>nfA%bmX8&CbR8 z`i5=BMRFPFa{zRtyC6-*3lBmY`~-A+L1-%W#(2F984wJ8r;jvDnhUD>OzH`0c|=|S zedi7N2sm_CrHh(wbJCUSX7vs9_CamA_L9cy3How~09+h({Rt}fRU ze4`Vj_z*4u(mMzIVgqFLWv&T$!5sc&{%5|0FhnR2Hi$opQF1>yKxqzn6RV5?jXwbi zvsrmV`Aj(n?Wz&vNjLRQNRe@%;6>^dQ0*D@7quBAL~rd*EkPRx?P`g(Mw_f}*7xe4 z=wIrWbmk>pu6Y=TKqK6Y059(dZq9apPKL%`WbfVZcB zyJvyFPXLF{1CO5tEpJn!1WJ-?;i!{F9KDZ1@|uo z|GxzKV5~ssRAIIhh_E`^azM2rZAlPo4Y6fG3Un)y26@&jTOKU3mfI2`-`Zx&gngi` zLhFQ8WSxaqab$4{LrILc=1WAbz?j(1bJIg)6*5qfo=ep-Z zW-Pa521yK(7Y89RK%)hY{WOT34y$PqyOdoHE&n8DuoGtN1K34>aJBhXd@P?PJtl?9 zH_1(uW#Bn|)F;#>YQDNdeH&clnEJK)qx!oVsMXb)LkGV_Q?(viKX8$e;2-0(JV@>N z+H;tn4ccDqxON6w@b6lHUPo`BtNI{45jM^g{c(N1zEoeSuhTc_J28s~A~(#$=rk7Yusk;b#52;Cie-r)`R>L z`~t|nm-$`L+za_1_+|nJITtG|7j{CLT@oV25n_s%CT5Ab;si*oJX>xp6?ckz#eL#I z@epLz(Nd{(No*!XNNuH#Qdh_ma)dlp^IU z)^@RSQMsgChW!)>3o1g5RHGrUV%2zch&oIip(ep#pcbNqYGGO1pV#P4r+(ALddfdu*XhA z@-))J^$5MK-cj$Wv$_bHH1ueFh@PaU=vjKMJ^|F3r_a!5>2vhCpwdO4(--x%pwjoj zaZl^N>&-xy9btz@f-a*$nX#bFA)w9?pwARgXclO60;n_(bUF)^Iv2FM2-Lb9^tuKV zn-7}Z2C6Lp-R=YB9)kW_?7HIe2hHN2RWhQDA;t*kttrr4v!J_9fcBaP{dE>J*tyVQ z7eR|%4n1}aG}(OUvfH4|7C@if2aWa+blRiPYKx%Po`q&x4Bhq;WEo?InKzm3zz2t1 zh3_r3_1fxqTnKm?3*A8X9gabX?+WBf!_@!d_fz^RqS3ar2?&5>G3Drn?XP zjB$t9e5{ep$s%lC*45@_Dm35NQVx~}G-8%}j?Kju*?epzI2m|X5yON+&mG53f;^he z&SYn^kF!rfCOreJ;sr>hwd@{fvxPu_F4_1`U=>?|jz>C&Fr!Dl+XwUJ* z{6+o}G}{m%9BVyR7$%Gm(u6EwLKQmga$%*g2AXZYuu0ekj!*!sWS?+YxB?q97*=Lo z*qKdWX|{x|*&f#BEwDFbXt+b5;iid?itB71QN|&B^;$*>ltQFXDNJexZV_o~wnLzE zjF6I~6zI2EQf?J|qrASmP1-3HfRmh%&cpHy1ov1hzbqe;&&Z9TwI(WKl?BQYtnV?9 z*ahl)kP$4bxuMWkX2E(3(VJp@W$TaWtFVst+FZU^zo=gVr)OM&t`KnhB&?dI&{_H$ z>Be)Q;q8#LH(PgFqpXS63Tv0O$BKhB^pg7=(Lyo9%)#kawik4iVzvf195c5S$W&`y zYs?XFn=>R^fkBGg?c77$GVUwTOEUi;dUJ-aC)^}h!f049e?m*WT^udGBYq_|mwHO~ zV{GfdVt7XWME*-o!#HkG4l4~*OT9xKudY`|Y4<~x9@j2tP0_P=^s{<>*Nd+0kamrY z?#7+q344s*W)wzhEHsJ&Xr?~_qfy+qxktlBWWxMNy<<89k4a~zu=CiAPLISLmmxP;u1dkENicg5^qz|Plax0~c(n0B> z+^Pr|QJ3OYdH`|ks|--$l)=hSATF1baP>AIi$AK-+F&h1>keIaFyu=^qlMAN=ww7< z)eJHc@J0_nMm&f9zh-QQMEJ<)XMSroveJRxy-e#S($B^eyRbjQeyV9>xLsg@w-7o3 z_4-xlD!O2|eF(a|0BiUIWuL}E`qgnwb3F#B^|R|X;K_>F%N%D;HXj3;xYc~aJYari zer5h@`UCmsXx$7HaiDbJ*6&&y@hF5od)d}!eI)@4-cMKu>9Hxc zCYuXgc9HuvccJ^Vn~C*f=$~q1*ye0Bdl&GG3BWFnu({mhK=3bd#E*TsaT)$#fG-c> z)A{>=JuK#T+Ni@(AP%R2H1&;0{B;tqI3p0QB!UAox3k z-QdQ@gi{!$Kfsk6i_OIwfiw^Y9w8=Gp}Eb$ih4nOQQRu-5O<45#LvZFf%sh!n*i@? z35_ip*g|z2c#(}Xye{pM-h@?nQu+cYL#P}sx2-~Fi}4~3De_o(qK){imEV^?g|2o{ z4pnAA8zW7O^sr4;pa>_Ro1LygI}26A)JEm-1yPLxx;F?qS}yPf!WIZwSOk4-c?FH_ zfQ>Vp1HyL&ynuzCW@wS%2hmy#(1v&$Z^(j%wg@`fa&0BJ+d3^DxWG2>ibK%Sih(^` z))+ld579&QFujr9tO}hiQjdb(7Nf`N@sKXV^bxiOmsYC7&C(a@OJH4)U2znaMG>UV zS@=;Lxf2T8f-DOaw#7f!;tsk#bDe|+7iKhr%@F|vvLi4^7AT|&95MzNWZJ($i(|~% zW<9e#Y*|7jM^vy~ds}C$uI{Psk7%8b@MEUn6bAV?nSBLldjnwXL%@r2xrN*fQWvQW zcujw$rdk(%j1J)3&%w6)1h~+Ru(2P9?Ut{d*FyE?`U-H*j_^74b9I0nJ=%QAeARpx z9Pt;k0oM39tnY8EpRM|kH8Jo2K-vI|bmYygSgSeUg-hA>?0al`PUfPyQNZrca8n@> z1BGTnJ3$kAf$yYYrL7m5h;77;qFb5@jBPWJn_6;D`Eg*><6$%Ssh!kYAPq-?($1id z!?Y>dW7=ZS%~tJZ-32b6pg*FIaQ)$GVd%ho(~O6}&tEa#H;x;>7>&&~rfCj0$C#7M zC&96rK!be@9!B@em0KPo4pgbYaV+X8fjN}p@u?7 z+0T8$MLYSg=T<;R=ktsBrTmBd*TA*@t?DTC0d+MbbfNl{+75{SerN=@>i6m)t`@GLkX##0iF{@G ze#{V@nz8-Zq3o0FVlIK7#=iuM`7Hw@{ggcq$q`;Zy+VB$l;l0K|-*3VX=O5<3<+}i#+bC{_`<{HS%jf6yE_Y9Fh@fL}8mTKi<>VdZh#lM@1N9}dr9 zw9VHS*gl&kT1%}h__qnI<6i9*ZL_vRdsq8VtF1TDHPHTJ`aJllSHll;9y;l8S2BFk zem4`Tp4vooMy-2p5$*-SMv%^ZyA{pN!}RUgB8Txc$VXL1#^3F0iD z08_gFU80uN0Qy90tFv{hr9*$2Y&~Q>XT4~xx3<88P5#I)t?#T0&>H>SwcHKdE!?f$ zoq;3k?(XhB?t$)m++(0a%*F~|0l&!}_YwD3@R%?~jxOQP)?;r#1cA=p2Bh;Yct@tP zk3iqt1^?vN@JyDl4Y`(F8+-mNt_Rm2Jb_TnOz_X?+@qMwr@0k~CwPt90xR)-;G9Q* z@to&=hCUL^*Mn`?obLcHh=hoOX#RG75dW|+4@l1j*mcK%^@NCx#AadyJQf|R@L9x) z@wQ!8onGPV$yfu+FCYGlZQ@R`zy~QR^K69J`Ucs3vCugF6{~MA?7o9lU`Q9sc|V%j z+KDE2lkb!hixm!VmIKat)=P(hz!XKX?|Oh90ul_9ObKHPt#mf_kgB ztC_HN=0ls<1(fj%^;@;3Rv&gmSJ0nmdj)f}$?zUL4U1wMaGhgXiPl!{t*7fx0tr8< z`?)#*he-p{veL#^cKVb{N^VEOgBT6z z9Seyv1Ty^ZATs5Vm}0}v3^JRTEn)FQUlo6u{||8IP#bw}hIJDGA7n?M&sAeJNmizn z18?M9tf%+jgFKH_RNvhk7NgsJmwTjplzUPsdR*ZC+RYUEF|oj1Lg3R^z?1KQOiP0= zaXz~RF*ij(S^^Ot(g%L~ETAb1xaYVX+*^pQIR_-UA%82c*zq)X^JDpm{QZz_%MnHM z1}x&w_%9&k{^UvPjuevNX@3>ok>7;o;DvXK4~nbA_r#yX#*zyt#RH%|7RcmW8;@L5 z$(MEzNJJrcTV<4zQ7Ze`IwFdMg{MuegkDzmyyZcEo&_mKnC5nPDE7c}bU^t4HrZj& z?0#Jwx|j%xd6E4KJ{P~ez}W4J1g(F5Uo;m3nH&#&cvux4 z?ip30fsVZ1>Eru8#+?G*L|9-1IK9C~g44&qa}p1ma~MB@PlES5tqT9Qqv0(Frm+T? zVLrc!-v-;XfZtn%SG+1KwGlMua3P}9TOJ87d9)A%bdhYK$uu<4A zdz7N`6nZ64v z#7SPP7XR*uh>s}5Ox_JYufNb!(8RZZckGki0S2*5sSWz*0}oFq?DFNV`o`_X>&8#; z%^L8+-eYD!6Qrn`LPVwYvr??O(Bmcm1N66TvexWiXwnMdR&wn0Y~GN2h4!-wIEc@aqAZsQ&JT)s0d7=Ic5W*tNkMdIy7{ENQjBJ(HM*TGg@#NmyH zoL&H*3i(sWmqMPDgSLm5X1)kfoa7}gw*ADFku{HxMfXM&Ww~cUD_#Pvcs2aOhukL+ zcX1Y&da?VWC!Q$MpUl?^@kHTl1ltxIyQ`OH_hI|913^`3?1PB!TLeGy8auM6z#CUo z2;O`G8p7!cak*7-Xc^XVAMoQ$_@QUO;#`MFQ?ihJIqu(~$ld%bMC-Kxx0{LhyG&R~ zv*lb!@}-#5y@;JT2Os2CbrA4_dirQ!>K)*#JMLNmIkywh5{2-Z)kV|*&Ek+Mu$DZ; z2`n`?0{?v5eBb;I7E3LwiFFHNCkJDF-Vc;`Iehxttk0}3Z2x^TM0XjmNk+rBH6Oaw z$_mk3`)vPwq5G&kAE(RD2$ZjVmEyZ9&&T!2&@x}yddSW%fp=Vl1{aQquP81Ney_I> z*>%*8jV^|CyHt(Gi&i{q$9R$4i~6@nK0;=T;4>pUwgDold3a0Wfx=D{9ze|38sM+* z3SSGg#fI>G#UavYF*L*-So`ma$AMR$5&skeq#CewdPsexRQP$GfJEB_&&o;ZYspWp zi3nc@J*9}^R9MAhvFoCu`5c z?megdsWsEv19iLyGUZuFjc?#r=l~5W3ZC6JU{}-v;ui}9elI+(fo2H!K(qg$7!=1A zAp4nzq#(}WcwzrO?_hzTs8vKJjwpxLPjOfF+vdC9gnx`M{EHN+IKrO^vvK@DpE$*T zm5!^@1vgcQYplqBF2he)8#w_t!d}r4Yuw9@GoB7Vg2Qk2BhKs`Xuclb6tV3Ryf)q7 zOHAY+;2+{2;UD8yz_0i+|0*&7K0pq@VbCghcf)|rS%`8UB-|}b6CMSn<_qr$=Y{(4 z4+xM_j(=dhI1M(<5^)8*Y&+o#I3s=!WU-#qP->6J-@d?h1_RleCoO>%wi6Wlt@HzY zf{o?oGAC=mbm9?DI1yI$1M)+5JnxI3+_&ZZu&#Y=Yw{rVLv-7nu(78i5`2ZSOWCh{ zu6z#!wGLtg2LVBys6GU=cP(OZKY)#0R}(ZhC_D*1#^-^^eX4y2bf+nBITuj%5&AfN zI-(!e=zH`JK<#yamnXn~_aJne7hUhUj=)lAV8<(vPV;x{;T|ScfyyIirB=7 zh(DSm-Yt!mG7%eaKVpfVlU5^FVxM$a`W(^cze_a`@7f%g<1MlxyXEmf8J8n&@vK}I zeqj+_%qYZ?Cn%Z7nwSoRaW(u;SCl4*3x5$lq1r(3p94p|p!vbG^PzqZaKKrF{pR^I zDLAFG_pxKyi5Qay5PA3r`xrYJ9=rjFpLh~d{bzVk8EG6MoEpjx%Jbw*MSs(EC;)D5L$a0k1PVh98=0qE?zh!%cZsxSAFZwI=XD3ew6kUSXv+1sHR zs;*V8J+6;{F?9pwy#w97tu++we~Wm_h0wS50$Yb}g?5L-mOan@$=2rD!6)(*_bT@- zG}-}(QaFuxSr+wAmS+O%ctyTTO$ClHAJLzC)$g^2`U3qa*PHM*{f-E?RY_`i(iE2x}Ehjq7{6jZlc`JAeNlsKK&U=0UQP$t`2x& zEcXt4stgd!PKan(f*9>Fhz{6I0Td6Vl-vGo>ABBG306y{+%BM<*+6E|flKL1hl??cSPD9(T z33Ov9GN*pgOZ0WFTM;$22!8yxjXGvy#26%%#_Ydkeqf$7&zL1<$-QW{sE)3T)wFk6$+A8Rf zh1%Cz3ta-XG8^$?%k;PPd59c&*|pX6mg_^z)l$Td95>Dzzr(&$&A*^6K4xtMO`7hB z?k|WJ6!|l2aPqH!0{kx4gmpew+AXQbPU??wNJnJe0z{AhEC&HkZLdhkhZ=~uyL5O# z@{}j-T#Z)|OS=mg)e)dmKPubQcM<2^5^(RY_udqKi9NIA{*#+YcjAve`W;wS%{5xZ+12#t$tQEVji|(W}5-;!izxR$;0V=@bsF_LP!4=@5H}DC_l{=33 zumI=|vN!{C`~@Pbu1FogO@EMU0VkiL+yXyY9mF{bT0U@!Bl;Q4+pUBl3g?G>UOHo*ROqiO-6?aST`3DF5rlkr?SvOqtDm#Zni08ueN z3aucwra?A-B{r3M0w@0*QGhAP{hEo9T@G*W4)C8()DD`a_0(<$*W9SNz^Nb6C%ImA z{fImZ4!ui7-!>aNAjg92e2cT@9H1J#+_~--+)QKur9v_tI0YF;H4q0TLJk#)b>ROD zgB3RzvBpQ0JJfMnExjdhzbO4>td+~ICPq7>r*WV086sbk;A0H8G~_a(qSydCe`Pm2 z87pEvH->*4n#E%RD?W*=yhYL*pr*6%l^+1LG({fedf)^Dp%*9Wfz{}d24Z1fw2It+ z!Nv(-I%2)8VfVA20{8fn9RaV%(}-b9g16&5e}#__QV>zJRY*ph)vvHw>mpNSF5-MX zlLF*X$k$uslOgoaycz>Q|09t@G){RynP=zk?F3$XO!)%Vz(w0v5sx^YDcAH;97Lwj z^{s~?$Q#PDW3R7;+7=^>_3m`DTHMcf=C|G zj@}t(YZL1bU46oislHemQC-52@KyUe?xgN+A*y97BmZ~qTRnHaR4((a5%QdSwI@2{9de>8kGJeMO9CYLtU29$Ip@nThZ0{SeB;IiyaD4z-f7o>l`2k-d zGwnNQF&Ci6{9)$`1RJ%Cx<&)!ytXh}8m*1?MrUYNydfh7%0gstFYE!(-x!F<(7TMg zu^YfB><5rxWFt?066C>jTOvGeJOvHn8R%m#0Lfl!tT#3oTa4|-8{oz77zcobery~z zj=?|irR||O4?E*mL_%Ky&K+#lf{u8z$-xiUA6WMUJ9}#GKgykQaI4C;I%U%iK^(|^ zz{BTzGp7EV$ktq-w%d?>dkE{7@bXK9Y2^hlY1e_3UmrI6_b@HT;~8S(Su8BK%HGU2 zh(YNB54->$yo+}OEx3*E%MSozFc|)nDagrPdYxX#sOp6_7gI@$kFlN!U&9La3uGSt!d_wP1Gyf7sDs}*5olc>yjunky4U$&p{{TP zcAsDcm(UH7bBV$jAjwmKi!6ji`x+!L`9@D7dzkobxOg)#kYPYR?iU{xmx=kn==LKD z>nC7zt)*Ke85%9&AP-2-OD`ij@s#ux@VVclzYuxV5S*_y;&NH+>hTVAhZAW>%cDS0^O)DawU>54hxapxf#gFAvWEvPRk~mNEz^w5`Q1q9!iGZYnXz9$gBLP9dTh{lQo3 zB4RHIZ)-x*^6<3afkTe|xDhd0Iz04wh(OuGpGOS$!-)7hB9@PRKBC=;43G`F=o$%h z^NcGGoba&0o9oS%hdP! zIm=vtSk{w>3<`2Lfo*==wj~2?pX^PD3th}^g=g983X-l!XDu}V_lvE zHYp%$e82du7%Dv}HG6NUJpT%eT}A|mfZp7B{|^@CjpjA+nRFm_(J4T#`SM2Kbr zi#bp485>A22U8pKQ3u@hChlhBi;;IS9!TscZVVzvCnGA>i2_{Ct-{_Uo3S^^ZtP9+ zA$Aw~9Nx2Ufz1zC;#2);tB z@2^r2@YvR{lY7g9fJ|n}Q(zy@msi@m4(u%5bKsv@6w%%+PfwgwHmr*oc5Kut57`YZPp zqW2MjHs%(L-2W~>!()*pHW86lixA)UhSz_8g$>4DJuTrSrr4<@>hWj-V)y1(bA*RE7Av`=y2?3GYWB}uOg1bL<~uSTA~^HjnHw&LVJDHNJ7?iAoeVp zfjte@BKKjB`vAR9Rv;rnPiVzvur7G^hGPe>gM3}oK3Gb$RExrpQmg1F-^Gao@_dq2=^a=G!su+e%TTLK{~q`di3SFRj15 zQbyU<3R%?iv07fzUe`_`p3e{3Kzro9!~!pRLVp!;OMmH|ka?Wxy5ALSbilq3-HbRR z(HH})Cm1|40~qT~mW*+Vv+hRR=XAtTQ^a&zw}3q$9!D(5D(JC+_CJ3+8M{nTG{>Xt z6NtN6$Ue!vf*CI2!jY%&EHA>#nPlrtr-Yw`0mxqr$6URK(HjK(KOWH)Q9%FWupd?u z(4QstJ|pL_%g80fG6o`ZI}CZ-;mF#i7)BACoic(bA7}`?K}pzqBny#W6!%5;*%ECv z(6rYP$+Tw2L!;EWdEAfK;Vg-72yO2#>0?C92Vj>L+6^qa zG|%0`0n-pS@RG6{Igm{u-6`ia8u?AmyO6DUeR#-0=zE2wxZ!zZ%XakUrTf0?kV-jD zQ!3@DFW3ED_rSW`18nVftP;v(+zKtACZaVHk)x7{{Vm>v486gQD2qgH?OH?tAA#0( z$?A;g-`Vc%?(d)%2HLSwEfM206$nK%c41kL+?8*UZPxMB9{GcJX2ZAd@0{4OsV~~6|ayQ0fmw^R#7Rf&BD{xVc z#W+p?=ItAA>)8I=pdB8)?i@AN-UG)#%vmh>MKWa2R7j!cfkM8eo>IR-Bv(zXy_SWn z{2FFMc$9hgW2(xBf8YGrJOWSA6>}3PEUxk5M041g<&V8$}uu`ArJTmteszk-(fNN!3$ec^h9UgDBc8bY$sSE9P*Vl z(G@Q7jQjXesU1^%!V zI}&_k?}Nh_LBMB=jh5K|C*B%vF$IB4A=b$wVqYNfN%A=OU!TA%u9tVf)+?01v2zY- zU!zd$X%vpkZ~@t@G0NRQbXH=OoW|Y{5kMRdfj4+K15;^Nhql)h}_7e=aTCNaC8$mc5m>tB;$VMwY>n8=1t>_@xAdQ zY`lhuQd7-4%>=|zK4d>)(Cf_HIuBN}kL9i_Sn z(GQ2Q>)-EOE9e^C5%Dmae+4|~L;eW7Xy^G~`T9b0d;d*}!kGl0?aSCb;Sg5Z@5t1> z5uB+9;u>ggm4~5Quf}?zHS!5!pnnw`!G|S7x4skWBw3matL-gl1a+WE4~7?h86^AH z$aQDoW1R{b-Usx&zN#S8eTvWSTE5Z!JJsWA7WjVE*{ucTqL!~0VN{Xl(ho=?+1wvu z$Aqr1PS-&<4lxE}|BtVYCT1M68@FH&A{H^U3&7F8w`7W=Eef=K9W4>L>Be4gIqYDJ z=u+-w?il|j(2a0l8Ap*rRug-`jEAPR9$3u{*bDGp*wn|BAC#`xuP+8(?o4PF_Zvsd zQHW~XXw`J=!QwzB5Om|mwnX&)6zs?0k|s(s<=ybZ{RaO+TkHtfOZ@=|hpN4--3kfa z1G|pzpLv&A?Ik7?a%qTI6Gw8q$nQzTbmez2*jzpk9{bD;PqZ%XN47Fzp_8L60SWExHx14WbyM6!SWj7 z#*QFr>@U6pcDfscsE3E38E+C^hc-1;90BUfgKoMUo~`!~`*0qSCT+o^W8{0lYafEg zGanK7$AOjyE46_s$=E3_0TOeex&k=&9(Xa&Lffk7t7)sbv|iA&2E$XCqUAs*nXWCv zev0|p5onWV5&zl(yW#Z3&K!U0gRu+8lbDTfU5$Vy#{ngtgZOmXLF}y22st0^;N|XZ z4m9t@ep$;Ao&E(PmHSxtAjaiBL?$0ZE}n?IyE%w1ehp)_9~S-z>_35j6BT1r12VEd zyNcb+zKxy3P9w(2jr|esN9;=oFv(=X0`yo?_~*FK~Er2Yndv#z}p)k1h1cW7^8-;6fM z6CV$+<4JhYe?smH?Jv~;*coNO+~Sh$9j5xYh9a)*w5tXX^=Ry!HX6FqcEoZXfY+zk zyNk|$*Mcmna)+_%QSwOGm(kdhXQ;(Q;NOgekEs!MgADiX`N)>r&GCA3U8;+`rX3by zknu7Mx-#W5PXTT?2b4~@@;YR;>_j{ZS%W7^cU++T9M^%~cVc%N+Qab#_HR6gy&ErM z_r_4=l(&b(SU!yd~E#kpDOHU?$oYuM#S z;6C78l1X`BkCf|@2lRtkgEQ^*Uw|{!cNFIuI3xWv4=1Lqo;u9MddOe&XYzi*IRfWj zaaM8u4d+;#FX5bm^Y1vLvAjQUUWD_XIOpSh8E52l*v%W?h_=WRG&#u@IAyuWZh zi}MwnnLxCQb2FTAtX0)v(I(fjU&>eTeHS@3Yn1kF4f?Y&G{sRC7P8n)`Xx z+@D*`{pHo%&#&fwK{fXeRdc_nn)}7o+-I!&Htn)O6bJmYROjId-(Ctk>2hkR+-cRmD{2L|SE0q5wh?znQ zz4UYLQV_G(=Q{r~+ViRJG+uHBF|*Q7Nv`?_-vkeTXG5x~^rJqAl!Av911jiC=$|M-=ZTw%%|mvMcWnO1ViKHMe63>~dXif|N^ z9(!@VOoyMlGNYr$(d#)CC8SOl>Br&ZoS*4$0S1qbqJXlaxJF6IB^r!Y7*u!JLDzJje)lc!sRPw{KGcJ8q0`E9bzy%it6h54)_V43($n=y|Hg=M%=%z2=yqo8Au| z^?twVmw+N?tbpugsQMrLSb(~ zzw3&1*9-bf4~Xk-4=_yRn>Z4{zc?(>7T}b1ow9YCm62YBp}Ou%A{`Hlf9uVXk_U@R zN*=)43%fL}q}h~dCE>=jl9u7qN?L_ZE2%eQTFDayB_$6Rm6W{sg(DW|S*oKa(~e1E zBA8Sr2Y(Zo4EuWq_;Lc1hP(7zEWVFslA)($;5r$6IimFUvADVgS5=ouXU3w|T>Lr` z<($8{%y@iHw%cKGk6NTQs2A7zG-d8U=>*i4X4jX?Wa7zG+{?jrw%t+!?ohuo>=Hff z?^$>v6VGMaEhXW5vi-Ih_(r|UK|izbUuJ0?y_rOOr&=3V+2VMVOU0A)PEH@%p=?v8 zyM33&k=pl+R3>VtRx%;)BJd==F^%S}(DY~=#^P=Vynhb(Z!AwFK zXO29xK>Z$zdr8ar4gp5B1-4U^G-KFgHAyIh&qU-oViJ~uW9z_4pC3V=OU_n zj^>YQ^31dIWCE_s&o5DK>ndxYcc;Fk;_QsCr~RsHsk$FTD-QjPWbVcHMEk1h8mjIG z(F@h!X}z^gZLM*q>RPJqho_cIjNrBUVSu*BV)SzH?lCsS5OtMNoWl>|F*d|OBES=f zdWrYM+cOl4+0DUo^gPjtXIP-*x(sBZ(HmMDf!<#D+hv1%dO)$QnRp|5t~dVX z;2ec#(qJ9Op^vF{@4KMY9%w%s_q(9JZuV$(xq9dEEA`v6Dr?*Id)7P6r88PJP&19% zC|qZwzky79=1%m0deR=YW+vq10NAC$C`a6b-a8F7x5xX@w=De99z7ziNnDk#2I3d$ z?L?*qu6kpPXay35Q|;9IG^Q5nZjZa3mFL{8UD~$iuBUV$_~jUT=hM(kt2SYh39G9h;vuR{hRu5f2U4Iu2xsRVTJM@iRa;T z)H9mLrg+=27=xQ_I(4LrBilWr=8OwbG5vajO%KE!=$cxmbwqQOYS)mB_ouNSeSkQt zNBTwrv7mP)$=TZ;6Q}=)D3M{;M0GmroaQ6Pu7{)){qBq|jTUi6qFRz_#37ts(R!z~ znGTsq_p544sxWhjc5So@X!bm-;ud`GkNP7peo^RY*)Ps}Q4dHSjK$ORop?f8saz#a zn`(3J&YeWEjjmyLP!!h?KG(H21)pZG%aUzJa16bo_XTk zw4R-@Y+!RFXDn&fN!sUwic26=;C+QW}`ZO>1JiQOq zM6$`ln?3YZra3nCwts!)8&`UV>g&F#!q}DP1&%gEnq4Y14eFz#eL1v8D~0%DxUJol z*Z!QbB%L7@iXlyxDAv)Ha%`H;w%241b7N_5X>5oZh=b6Y zaP$~jDa1w6aF@80LkAA88O=1X*H_u7mLE&c8`iH>s<(HBNCH#uXg4VfZ(LCvuZGGeyttjU{tusfvEze=8AH*Ms#>>_p zahhCkt};n@?V4ytY3y?#Z5^rSp;ww$TK^6|pf{k=^6)u&Pe*D{53eQext36 zITo4IW>qqWXx`DosmC25*^-z}_*OQ@#P=M1iMU#2DOYt3zOB>xqc({0>6>#VZdvuS zU9jF9samGxRJC@T)l0KLYoEr2)+CLRLxUbFqt#7!+Cf^(>7i? zM?Ix+bR<=oRY+sm4sYvlENAsPHY(AQGpadQZJAZ;p=#m|zWmHHGF7$Ls@8zFsyejjJe6uGb7hUko0R7^u@oTY-VDKE87vk%r`^V!s zqIT!HCbS4zUqmOKdm$*3V$-tcPB3^Btug1B5Ue>`14Ql4ofZ{1vcspzqVs5q^tK-R zfvAVB8&`O$OqLM8^yo@X*@hL$IyySlUcOxYQhwmbsY;IUG+qbopwaQrOBp>? z)=4}Z(RowSM9Wr~GuoADrSj_V?OB;-O|#qBwitc2AP?WDT<^7LFaR`2)ECI~!I%=Q zIp1id1cUC$W^s_lnwXnpjHaWBk@b-cnjHY%N~7akhuHQ2;W6pnJ5jhI9m8`c0QFEy z)G|>&S*S$!0j2a#*F@t1rIbzO>8;7ach(j4_gbF-ybsBBswEkHao#f<=WcihIy>)8 z<(%HoInDl^-kDmZw+$$L!+_E^bMS^lytz~VShPZP7gE{|p)SsyAiD+9Qd406JFOC3 zUi;Ik5~n0CO4LYiM6^j#i+H0)Z=(?>Ytq3enqTvIj~(sEOPYn&u<^^cLFYg4rnp;`< zn<|wr`^}N&j`n>u&8RVYOFA%(DB-n)=Mo@ zsa@dIM)w_U+tdHbBN$ey0g!H(!*oU4qzO4_uA?p1MVlk>8}TiwkLaN%zB_2L8^0#n ztvINFg8&f!DeE77CmkaR{}DfPO18t>Ib%dv0nIwC2cj{Lu6+x>JN(OI@l~#&1?HXl zD=<7tm-UODjQ}U4dXpJPvL?a5QOmB8By2>vC%ZwSJBR|UP6sU@Iwek6HoDhdOZ7pK zL?w2?35#i@FXU>>~+3SVoh)NNPMOZw28-)>Y?8e@xgXolIgVuxdi!-W@bwxTI zy*Z6-<@MDH{DJDK?g^4l9t+5MPsam67B=;=={26O*yCo`DDQAm-*>FcHOk(|Gb$DB zgvuIVnJrkxrHFSBy|Vv^Hm`^J>Vj*Nh3w35#WAU4(_fhtc{8pfKoKP6o7ftpGY3TV zLxQ-^0oI<5KArK6ovA3U1BLvfXDBI1lB+lkN9m^f%9@rCmDJ-UbIOt=KmxTg=- zUV}Gz%Tj-RB}heU#aTaP>(F^K(hfRacO6$>nPoLLyY3oElP2zP{ZA0DrE$IfH}|yR zpbR z;h4U3=h5{&9?pi);xh3ctpwt~4w6Cq!{Omh-8n$u%G#lIOY+f?N7Q#hP-z`D_39N4 z?mZDTlTPovDV-gOb+gzcKS%nv|ET`Ee$GE*42h0#uA(g5^5_QfmLWME*Aq3zHne_VoJ{>yl>ddc)TIrlwqFiIU%>SL|W4%$V37-TEhGkBefMd$MSx$L5S=nB`Ha32B)q$+Q@fm=%|t zo12&y{rgrztY%~;?J25S}M##t< zr-wCqBxF&0!6BZiLNUn68M)EPsiRYJ18(-K?OYE|P0CFPXzUl%BQq^CyGG5#wC=eX zy%G|WLwjM|Z|RYeke!p9Tcci7&tBc`h>5?aM|8J=aXsT}IltP^geKC+f|}x!C*;<) ze{fpy|D~pV)juIUIk-;0xQIB6P()mEcIqhSdArlKnYshgl6qt(C*&p%pjQbAiOtMO zrQX-5o0S=tn4O%Q(F0vi&aM-iIw3hNCpI~|cSd50|A<=DVrg4-nBe%{>7c}5`>$XR zlYbbEl7Co`{hI!*gG&oH4e2&EH#07EQgY4E*wn<_vDwMD(4^FQrY54X;=8BjrYB@Q zj_=+3(O>$=I4FjxHIAk@{J_!aGo2M2KxK^ z2LuG@Lm1BoL zq((NpnjaKI5y^w@7_?`1!SSOIwT~S>lAe~1x56WvH*ECb2Sq1N zWe?hpx~=+~AGz;syvBeI+dlh*T5$fqBR(FD;Ge6<;COF3Uwqr~{`AGkQ@wii!Xv|m z4)bXTzkl$~XMNjl;g~JGBR0q1yldY5`+Xn6XyBp63m18BdcRcJ4t{-Z>9csGYgZ^$ z-m>`e_KqXNwOwY|CNwof+O~Oh8NpyEoFQMk<|W@pobS>0`pM3sar6Cu?V2@cr+xeO z<=a{L)Iq^->!@D4#DL8lvw8jlZ+RcWJYbtZJd~52NQi9rH6Q>z%yOZ{n4dkWFhAmkr(Yya(`5ojP@1UBA9Ued}Ld2hsu& zE`4SRrUiAP!0J`2YS*p}Qov9%3`pzY^nKG3_eVA&629%mEr$;sKl#~-yRCd&%0XMQ zZr`);f%iT?ehMVip+g5W6%rDHE~ciWWM*U@+)o`r-SKg8_z6_sy<7LpjEtDRF%EI| z>e&-?1AQuG54w&j@qe!yw(i+hIwwazIexdk1FvWQv}Mnhqo{9BK|!ZZolu|mgDRa7 z0h5Ru7>C|_f5I2jFh2U=Llj_`18*M7iF+%h*BeiaKk)H;$DD_pzo$MsweqPC@4Nl2 zi9_G|>=WWI`2XmqhiA=v7&MN#kLlZY^Tv(dM?fnpo_{_$DQQ6e0VD3Y=h-DoyeptQ z9eAJkw}1J+*A94Md`!Z~uk7e}k+zQ4pj5|`Jvv?;uMS)@$@8HKViPiw(`sgA zr1i>#R-WzD!Pwe#Z9k_H=);~`S_gGYOC6n2BP1cMduDEKW_qpe$>WmK28_j{HG)Tu z>z|pC91@=}($-uNW)9_XEQ)0Wjm*s$(ATLv*6v_PX$Sjys&4A-p#OlrHKLM7CBVF? z=~G#a0U1!z6UWr3Wmjf@FKeMDZuUsXNK8(%TM1Zhzk~l(nhAD_m$l&MZK1BWveH(V zPz==QahGQQ=V?W!=6vE0jSa7-S5D_k&9`yI{crJXK9Q7#80utNdP}OhuBnC)wN1ZlVK>K!pz; za_)G)R49N;?@!LG;x&AU-T98bI5S-7eJb?wdfvn-g9oW@@6swy@|D`DFzQvdQ)QXb zaXYxUl;mxu;$0S%+ClLu>-N1_T^a9CqX0g*bOsI2+U?-V8DqRVh8cf-i#RP@PZ{67 zRQSG|=m3pe7bmzDx2RCJ@1^}dct;x4t8%vMDdSslh3|GdL@HjMb~R32j>UqyFv#8+ zs8Df*%d+?RPe~r9LAxFF2?Xf-!5jX&B&pNR?ozpcrmACs-VwN-GTy=!zS!?m;og7Z zk}_vK3V+(jG_Q_VPT>!j$9NR#GL64wTvl>o>Zpkk6EnwVN01%~9kEQ0^j2FN)kY^| zCyh_YPImOiwzjVBD%I6FZ`CzzGawx>bd9>X2?Gg4?=vbuz0-%(n9=f6{ZNNGi7wNvlACyY%R2;|(UKG?24v$XmFf2aB|stIa#azw|z zBeQZkl{Hfb&DhS3^wiwmNlrsS)KEZvss8UD=WWS58Vx*;MD&h|=$Mi`!KX&YeB*qp z+JBX*>cdBp40n@nO*P};su`KtJ##|s#PpG#k#}kwYL9|eItrPdzBLYVoFsJ5F7Yt`xvUzx|LP=_vZZh=3E96f%)waG1XM_l&^u17ReX2viK z>=;jnYN12rCf(^z+`rZz|Eu<=W@$qatWR$MZ=g3R$%$hyJarONM#ANl45KN@Gke4A z*_-7V^7}j^RNp&$VRz&tM|d8?xaX9;E1=1sc=D>%PEN`#PkzpeW|Y2YhNs%bWe>wb zb{?*ShdmVH>6ZO?z&cO2s(L=q^L!|tFC~lekH2%Z#|iN)GdOF&IwjYf_pR#==@A=I z=B)EIH~l^4W(b*^aLJWY@Bd|c^Zy=z^q-JYmFxUBjobfsFjXGf>$&s)+Piw5Hi96U zj3PO@myq^6*O9{~S>n%|X~ zo!z|;+ZSwE7R9%mn-{ovBz4 z8aTz6fw3x02^F7a2wi)W?O9Kx_-sqQ-B5fx5tf!|dA*)6@T}%TzgL=1LXA<20g|hk z@d_Tv@dAE1fR4gcQVxs8#pqfeWl~a(fRO}b)u0cGt!&^@4EqxS8-}fKgqbfEcL&Y9 z#i<Y#6p_;llnG`W#TJnEr5>7A^>dY2h+0T$wIFeS1uGF{kgj|Gwtp zUPm+R5~>Qah*}jiSn=3_;;{*J6ayq~uggw3j9B!bHtl>&1PTEq8~z&t>O@jvZxm{^ z6S-l8Ropm-tL7i?By#DF2k5P8#$Owf)S#O^+(pF zt(!5_cuj6cLCK@?h&h`%&@BSp!M$0xs@VN~baR#FpdYg{*8>pX*&%bb0E(*bC9J+v z@U45wB0kGwYRM~`gQWZ@(#r3!zz>9olpjS^`TZ#H(<*`3Cxub@T^0CgX+ro>q@*8& zy}%J<1(?)vj$pEi=4Z+{WF;?UXC9~_cBxkH`o0abJJ9}TZ@1!}8+aG2?e%`c(|PEI z9`CcNShYSBKZaj?pNT0WwAavDD>+`|bGy>vK8yurQbqCZT94vAvHs$=#N!Rjo3K~A m@cdf*rvmI?&D$VqBQ`Aa<=5e1^EMPl@-};nZ3%2I|M3r(>`;FI literal 0 HcmV?d00001 diff --git a/Host/openblt_can_peak.ini b/Host/openblt_can_peak.ini new file mode 100644 index 00000000..3e08adc7 --- /dev/null +++ b/Host/openblt_can_peak.ini @@ -0,0 +1,14 @@ +[can] +hardware=0 +channel=0 +baudrate=500 +extended=0 +txid=1639 +rxid=2017 +[xcp] +seedkey= +t1=1000 +t3=2000 +t4=10000 +t5=1000 +t7=2000 diff --git a/Host/openblt_can_vector.dll b/Host/openblt_can_vector.dll new file mode 100644 index 0000000000000000000000000000000000000000..19ec27e2b401d25070419b4318e1a66665267f96 GIT binary patch literal 397824 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åggq`9^dT{26;^hXrcOuNug8@+*dAO_m+ZnF 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

sQo7negy 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%0A&k&yb2LxdH#p8SU?OGfto4@3S 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 Bn~?wj literal 0 HcmV?d00001 diff --git a/Host/openblt_can_vector.ini b/Host/openblt_can_vector.ini new file mode 100644 index 00000000..b19f2962 --- /dev/null +++ b/Host/openblt_can_vector.ini @@ -0,0 +1,14 @@ +[can] +hardware=2 +channel=0 +baudrate=500 +extended=0 +txid=1639 +rxid=2017 +[xcp] +seedkey= +t1=1000 +t3=2000 +t4=10000 +t5=1000 +t7=2000 diff --git a/Host/openblt_uart.dll b/Host/openblt_uart.dll new file mode 100644 index 0000000000000000000000000000000000000000..66698418bd5696eb0e9b127050f18220c947f262 GIT binary patch literal 391680 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

>?_5g(&u~kd7$!lX#HD{t$~4=mq-oENrntMPRWi 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 z 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 FX+QI{lF5nnm;HEt+3k9Bs2&$a5HF z#v(ExhO#Ocr48Dmk=(ux+W_Mxq{h*}~lMnV%*RH{5SRkYN4IWgF#6){R+ z-tXG`oHLUEYM=Lc|M`7>lh4XN`@Z(tYp;FZ3%hKN9q-&)=vvdxHUHVUwLL%Szm_nL zTw>M9G-)Imtg*;?g5Wc-zq24Mr_)a6_xaB+=!IaWI2xX z1CNDxHj+EhmN1bA5hf92Tu2b#Idbx7s2zkOV_vtk z8JS+@goKl}G(cCWv=M0<%sK-lAwdYiGXc?dGm>_|s&rsgzaSh4(k(_fd@=zxgai;q z9Apg8O+r{$j@i8s5>K-mN;3JD~03XTJ59+Z^i08iY#6W(?JV!P9r zZLYBEaMJ92BvwR#ogs-$AP~oZax2QpIKalMO!_UEVuA_SX^A=9h}DPPGV*86;1r>| zToNoHlz<&l&J~Z~%BI)DnxKW9(4&kn0(Q7vqj2x5#TJKc#ZF08@0~>QHD}_4JPb7_6+WMH`6a>cYxC8&G{&p0G7OEHgV-pI*zjWB z2xbhz>%itWe<45CJasNIMqxx7!8&Q}{yVv5AsY#54@i!8vC+hu!#)bz5ShRPmaU7w zj!WpcWEZG5coO7f36B&1wJag}gMW1l-7N)}{4;eLi-lM)a-|x^Z5hF{Ah&JMLn<}2 z3;PY{o>s3Sn86hyVdu82#PFu9aod^^cIFPoR&7~H12+#eZxjTwCbeZHN3>;K&Y6%a zfXUo-n?g+9b&&)R+e{PMv$6w$_N*M8TCO-0O_2X32f3$ICXCdURm|sd9io!e-GxZYvGS84pM|v4wm2Xh6eCHq+1h4Cy*PG3M!?iM; zJQ&2Q)%-QQ3tq8p>AX*uK2GMK{~&p1RDM|HiEdey=i3`4Po=Ml`6ZeQ>Tgb>EQ8@c zlsilHQ`FfiNzXt&zoIQeBK8#9(vysayh#MS%=T_IJMdQTh;p|fFB!j6gMKfB`dyBn z>^?H3mODQiLjB}1&c6r!R)zXa#;-l-R}$(s1;5`0{c>zSYfrex*Kyw(^4b4`R3esL0>;^8SdXNZ(6E zq&)Ghuf9SXa%zqsrO)aV*B*_kjx63DWfV`YF7l*;_5DaHXgx&k$9Zzi^(>YYH&hql zvrPMN*)?`67kR7zzht3_m)`M5r;aoVYYl(DEXHwnXurR^>GqF=`Dz}p8wKl$ZRQ0k zx!6^5T+83iu^SfMki8Fb>}H^Ra&(fV&USXmu=wsMW(&M_Ms!?b)?}`G$jg#Lx=vm( zBbpx1;B>~+=-OS8Lxr9VQ==QRrr;mW!r9d5p>hm(C<7t!XhMId%>B{hxor*Tn3vGV zyyuz4%uuhCu};;g$eEYT@GB+RCDFz0Q->LGU2(+?Q-`rRue{{D*blH#*O-+Y8C5@Z zL}S(!^;1u3%(}dO>d3aKqlULl9evUqe^x@S`2t5}*huFgTN+E^Q~H`+s}#8dhm-wT z8EDN;0SLRx3G1}MJ3&&A4r39iwR6TJ(gypicf(P}9Qqh}2mgS-+mhFi_cb9QdBoP$ z@x^6ipBQMS;*+lyKO&}!mYr*Ed{v}s0&#wdhr(+XmP=W)5eo-P+RSPAbX`TaC6%E& znsz!X#}UQ)Qh=c$y`og!@`MVoW`{+S-OxsLec$c-dt97o~6og)W%Av@F zIM1LBCSeA*`a7_?upS6nIi$6rJ81P`J!o0|tv7%nIPsIx!8fploR*>=@%i}Ad5C&# zf=hi)LRdZ9XWfdW<(?<#Bu{+Lw;W1wKIyfv+Sej|Qxep7cFP@wUD)y&m6my_EhN$X1DltWxXzi-hFDGi+%zBkf?5fq2+PsnapuegMEV&J@ zd%-DoE2@E)+~~Wbk{6J1DsI_wu209- z)$pHiy{r()`gkeUTGde)u|JVz3ThXHGxAR%_e`6r-Rxpf9MnT`Vqa>ROhqrPQpBJn z!bPz!rDqeqM#qT*dD_jGTH({tT#>$6bZAE=a5=w*V@2un19|geU&_mFOiwabvBnpc zzMLK)`+VV_X-mhZ>8=$-sFgsd#PsuT)K7D+ZtyOFe zb6G_`P3Loo%Hbl4JlpUjh7@^jATJ*sxmi$EAFo%PVXTsrG#Zg&s-Kg7?ZSubek~9c zAG$_22@mdnu0v>BYq;Va)_OPY_HSRvx9#>1+(h1d*BWlog^aDw*YMH$3}e&78N30@ zTY8T&mB%!J4Zq;V%m$wR+Q`}lum_lgza6i?dF=UyVb*JWT%WPliF3&7+kWfu7yMHw z$G4r&5&U<7OX4pxjQ-H&l+igm_NHqJ1&qhXYa=pOc z(=-)b+h)|m*!A(45AX_^GRW~5UAOk$s4VN!Af>A7p|Bp;i(q3F7cVYa$gyVG$owe7(;*YQ2mHu41qxo1!5ik;K*PI05=I2hdvVzP9l{=-{vQTbW1R zCl3+M>LRI}wnPtrmEmEPA>;ptB(Jxb7pV;l?hoiSZ}tit(lm;Odxsc#=#!zdwsw>B z`ndEjtf#XVA0+30!=OQOvOnXbAm?J$rFotqQYzU!(}ey%cOuBH_@uDj!235He8|SQ z>zvLnsZ8mz_j^)|Z3LFzvzT2`W-$dYpXHw&yks99Yzvu>{agz8@3m6E_cIS#JxsJS zw>t*!CK}a$g!fD*g5Z7kv3Oq@f_D{x<+m6Uyq^Rw^9cVOyw~C(cpqRY-`aV__s2UE zLGT~pJ=lpLc$=Rd?oaQ!`-1eofWY!Q2NS#xQ6w`n6z?271n)@-@0Iv}PkJA5(2!>L zJ@{mY6G8A^8#o5<*Y6GD{UL$n_dX_g|4{I5;-5qBNMxqqy&Os2+W9I)J_hf8?d%p} zXhH|PF##|04$gKQI&o7gRyp*VKTtW8s2pI!pw9Jv>A!TG^l$x^^xLfTxBXN~5dEF$ zpN&-3_`i?V?wtqUo09O5l;IB_pSTPc5J$qyR(U)Ifo*ZYnaP%8Wl^n@N03JM$nwVt z#8IP_{vm{3YiCBk^liD9L`B-)9Ep-PoHy~kMqVTv^RUU%S)P({&c5A>od#R?YUryL z)6yf&caR3TCDMU4)rlutbus44;>ZmDIc2t)Pl;)sw;gnMH9a7~5Lo6_6y1>?);ySf zK_x#9>Z|)A#a^J_($wW)8?#s?N$i`fJZ4#WOjmhykp~adT&&)A>uJmE9U>hM?O@iy zjnN$1HMg?|NDsp4!uoPf7kN{+oKb&Hyd{+hzwfDkm#AEFd=^810UJ?{FX`qQf`Y@a}V(p`T17)Az}=wKM%E zQVz#+lk)5_r+_NwU;BFg5l^AO^GKuC&OypkEuIDINV+C22RS``JL8H_66{{#kl;6t zmtb>$z9vCasH;PQ1{!o<5-?Hnh@<%#r=R)};!SF(FCm7$dmKWnB`e8#FIgl1@99H` zr<7-pIT3_gJ5THD`39ash%Jb>)=oot>SaXQiGG_y2yvj{CR4rUXCL|am=TtyhJ6cg z%3W%XCM?nFc&hU-azIiVSu(RZ)0?NM^Q&MO?iz7J6k{>wU>#g5Qygcjk*#)mf{RW4azWN#l_z_)cQrI1j}GH7$^PPT|$Y0o)o zur#Zr>9=+zi0jO~`mm9_Q^f$8;u*}Z%rm}_;@vvnxyJ~-t(kvZucYln`+K$w_SdTH z^Gp^O0z+c&`Zu@-5?*`}Vtx(;fZ@N%FwO=h0I5JOa0^fl+z#9gJOpfsv=SRYVx7Mx zp)FCC%RwmIDQkvX23Rg1ii@l_ZW(B~?7^jL$(Cr#`m$ITZW&}*w}^GFgYPfJI&I4k z%Xh6mihpQjQ4A`l(o_Ih5-V>lF^! zUJ>h9hi2QvI>sT`Z^b&)A=rAX@a_?$xzp&@f{Bc@4j{vj|Memi)M$})OBwsf+k&8uwfe8EiA2K-rh51LEHNgdZM7 zOk`G7Ra6lty~0~oB@>ICkSaV6D<2ip#%;DkVC#ohx_~C%+U(_5> z-4wJ(8Z&=qv$~wDjon%+?JNaV^au3<*(eujnXPQM)$WW$v^U-_0qWzldG)Hds!mJW z%>ClVU4HMuCeJXmKQ``a%o!3{KP=_wtKLsyxB4YQs`RS5n6IJuF?Op;CT;Q#Z>hQR z8QN%1#O=NQr=`)*w=xUfZ)4Z85oPL~qd+(Cuv4m7fHPn=m+w?D* z^6VyZCuz&M?k`9sK)){A7fkqDJH2#DU7rO{b*}OIR15wS zjn00P=>dmUfhZS3*5QZsc(is-kR+^iCh-nyJ&3#g3;nj;20Y1oNLap020uf%zUxA= zKQmaQa!!R@dr`8_UTV3N5ttmyQ+vpx?vzbpmuwkiCCI_RrmQjMB)SVZ$J>^5CU6!o zik+6M_-MXH%hv!ig8$Kb*Z|8Ktp3NuoyYeuTRLic2F2d> z8@|DO1~Ezqu>@EJ9IpiT;l2U5(5DK21u?T@SEXtrTN^VlI%o6G-@eV*0#76~aJV>A zJ4_OXlf+??c9<^?;o@+%c33A4|3Z*lK?RHr~A0mhcB`@5+!yuGpx%!smlmQcY5l>q3`{yMl`g%8Oi;TzEyBP(_ui zdRcj4NmWI8>1_pa+mf)-AGuVVi~Gb`T2QTe5OSp(1y!8NlgIX}&v$Vu%vDkBLX*})dUQ#PZdUM~DCNyBal00~7gtm*bCp#TD#}YS z)w6F>Idb<^C@k?V)bS>LOFSuaL7~*BXyhV%NW4oVUaInR6}ihx-9_VEa!J&6u8S+9 zin#6{c}uHQg-Sfx-UZJ~C7yoCiolfx3*Cye1@@Ivl}Dlud)cvJ7jxpRUjz%Uvvi!~ zK5?qu3q>`JiV;G8(JTlqm+P=U^18XI?sDrvO$e^3;x8=5=%%=Ip_gG4yd094ggs5A zHBs@+bWM9Sb5#{{64y>rm1&d?r+8zk8!a}ag?;=rPfS!iA@x{YR>3*hF@iTA@_#(oJv&L!uFmmN4Q$dr7Bg)!W@T}j^Mv$j5(NOOXLym z=ce>Ya}HO6(g$dt>|=cfYoGjMePXoF{9}EFX`ixVeMT^%eby^C#ts{bbdN!IXApS^ z@(LLkQ5fbQ82`u&qY<;Uv*X9~2Y;sr2sv*ylwet+9=D1bwl0uM-OG{TYItLjdzs=h znRnC_R;q7F+7oh5)e~|z)iX)+m>s`*$HOIk7vthHO>3^qBs?&P{lP)IhCel78)n{RGCTVkZia)VZ z{FF7_|7nVaDn(Bmgb3>ztp0N`uQ$whd#^k+knZw1EHVPBK_HZ~3T>`XOHwZ^gEyGC z@RIlS+|1$Z%AD)uK#bfcUz*5>zqh!3wUjc9+1;E0u;9P{B}MSu=%1R%-I}A`XkSf~ zA=d>tCKKk(@Es2GUWFeOe5frY%4ka&01PymvZMWT5?J2)4K+%zuX#Zgw8yD2xCd_Sh9ISdxhRd_qG_roSt1FfZm09315aLDDXN^{` zpF!_n9!L7-A;kV#9UI|}sg*~xlq1X4HN;A6Kz-I(Dj_9*X)9=>IIJ&9d!xD7ENuhq zd!!~rzeer=D~||Oj=TZz^#eMOTM4SlaUmaMGbPRwIc0>GbJXTmcx-m#^ur>jTh-a2 z`pj>-E=N6k*CaBLxB3OI0ga<&Mt`O~qpwbE%o#So-@W1!4ni6J+k5L{E|XdPhmD!v zP`~io4knaxW@gT;>*`|?WLdT?BO%N}`m4r~3H7;A{FhWuw^D748RqX<@u^C2QDS}0 zl>;QnkC|abCKT7Ug!}Vomn(&1g|SotnfwdKrrQM^*QbCehA`iOjT%8f9$hS_&g#LU z>m(`PFhR&JVES2&*z{8e8t))~z8Tt1hEa8|{zI{|ys(f2uPM@=qdCzc?Fg7}9ywz? zr5Od*balziTQy!k0bTZJy2z=tCFlN+sq<7A)EP#3AJn(|CfU?E*J5L#%l7W$&}DFa zo~tWL(IrR@g{!K-$ONnYUTMr5?fWeJ+v+aLuDkTn!FqEr>s7ZrJr~)Son>J*3d|C~ zOjTE{R99p|*C4?vQXbxu$Mw`J8Q=s)>Sc`MiX(ZmZ;YgKJZW^N&ioR)>dxy^bv!X< zZv3Z0p`HC{K03MvOXWp99oDdvGi$c|V*ZajQzGO~{l(#*;ga=|NLEl9O5tatHO36E zCkfMzvs?a|R^dnDcb-I&*gv<~2KnN!jmU60Nhk$xH@B+lja}7C6KtG%WqVog}g zWOsu^jZ9E!i$^UUL&W1QJUFm6FqiXpQBTP|_Od5GG6x!HtlA zak-5-2`6odBgmsVv!PaITP4P&xIf8<9O)zAFcM{(MrbvrajHU}Tjo<;=X4Fl=W@;5 ziZ+~;lvs0FXGi+*DG-$qy6!jmlzr^N5xwi5>LFHc(;ed8y6aHm5O(D zNIdZlYu!63)0l=p7xQY%yv8zfEOWYLUTc{%EHeqyD(9CW`6h+t+pF?@t1?(l@eXT^ zY301x@O<^Ji;r;J6h7D2gr|XxQ2c}h2l(`Ga{Vh4fkBE`@xfRvCO z9`^yBYTT;_d8+k0>D5C$)mdc)Tv(G=)2r9)B24tqe6*Y|C7i}PGJ2qOi*&ek<_|B+ zMQL_aFKiDK<;N%q9TCapEKihN#q<~hQh8o$i91-f#GN*6rn)^!!TgDCX^P6oJ_&~n zR^j`&t!W{>(BJ+)2JNf(-UTF6_!jiG_J4Ez?!N@}D5vb}t4DeMUwKm%|I`Z`!VMvfq1^B0BcF7 z1vs{r{VhV*fya6X`70MGh0Cn^rF*K%c>62AEm#LqHX-6-m$tPi8RGd0!dz7maJz%zXJLbv}{byC@y?&!A8C;#K>whpP2NMpq2Q#K3b zGrBU2dB7%0vkTA-v&8N82wesStwJ`T<=IBGP0P~_(KqZuP2`vmZLmU9Ubhd?H+&*Z z!h;=6!ilJ6ozC=mUWk%fNoUA+>(h;K^y!{RQ|?f$DOWDCP9cw-Kc!vhpAW-_f{JXn z$R-JJfWoYUfJ!RiDdEu69BkSWh|^ku{C=r$Wm)9hx*OAvxsNKD#GXkj! z)+;ND5_+JTKxj5&B!DP3IgvtHG(pcOpI*V{!M7=tJ>3cQZ3<=2_#O&nT|tGif-~2M z0s^5ppJ}UeIgu_|6hWi?!BZfQ0ThTnlAW(POinEsM)&TZy`Jw6fNbQg2Vwnfec;>! zedXTKzi%Jt`Zsq8dee<&aFIT6=Rajndd%ji&B>e7HebFuEIcB7YvA?3 z?!eB#k-(0?H-V3ck@5w-A+Y-(x<|g`R>UE;8-cx~GXEbLh6mUUtRl6NZeA57P7IG* zEOcALo;5<_fqk5$7WUCgqBGbQ-xnK6i1;Z~@a}&Fn=>`!8)OXDBO^(3{_J$)8XCyR z2ZL&}r5*UqkydWMw9YW1)SN{g&KQCJ&VK$bhED|x^l0Kl+UCzx za}uR(UZzWfNoLK5ed`4gN;3BBN(#nxx;{GTrDo1{bkYktaio*@_rB>QsH{|@NJ<`uVYTAW3N_h$n)yKq%tlq)!y?huorL{s3$t5E|w}36oh~ zBm(9{dg#a7VGtfd$8}VfKxjG_edl-~$sR8x&=V$ssz7KG7t5O=_QX^T5>KSDe!}qIKViO#`?>G;|C~yqESY2FcdUD zk;eMVgBt5ux7ZsTcfk3_{POXS#Pz$*mC60T$LNilfg!wnR1SlQLb)R14`UAMIAm2+ zEiUlHkfcY-_2;v{>Ixt7)okT^@I3K- zlKnxwb~pdO`_g28Kl>i+aUfLo?zg{L9@&$k^dFA=hN1u0DMsR-8O8Lb7_JTm7{CU; z_hG*9mkc8#Jk{6@Oks^;67l8&%YiZPaC{e-dzc4@2w#6B#hCXlYXL{;nF923z?v}T z)4+1#57A3VRmhxb!5f`#G~+yva*%>$yq5y%&TxmN-4@xCeU0VaqIZ~pUG_Ftrarq# zj*_#M#$6?Sjl>5I`gpv0bzsm*L`;t{pF3Ab7Xe|p*D{KWh#NO?%G5l>PNMAIqk@vAr?w}ChItecwg(9OcxH~1ur+4XykQmlp2KVd-!r8CHZ-B7(@UZ?Q-{XFpM z();9$*THSY&PX;0a%*?)Wm%Vf=!f^S^xp9BK3RZwZe_+%pY}C^7<2R+M+5q)pJ?9d zuiX{akoi$l-A58Hv%8(=Vqhb*%jV85iLy#na*hym3!A`{Dy^wb^2lv^Kr-1lMauS2 z4dtj4d&9GP`QKL8!GELa0kNQaCPK=oqL~SDFtWYr0m<(<$;#YP7;^OZWKeBVDd}=I z6-a$-y^(U8tQ*S#0mU1t!XqvGcJYcst~mny6n`jUNPX>Zn7+@huiXv}+A}|rmfN?8 zbt;KBxw)e&Za)>bZ)1rRZu?THq7CU1P0v*qsnO}tuaU1@z= z(9hhbasShN!Tsw%KYIlWGQ|uW$ zP^7NLu)Bn|r|7`FEtH0ZdtIOb7EPWxTWE5W8#ol`a-R551sW+Ax;|f`3Y6P$`|h^P zJwu#=?N%of=9;s9rwg}?HGF9(*Yoa%Q^IFK(kbCTZ;=w7qDpAhj%qJ3qnwFQ#k1N= z4)Q@4&Z0lfsV~Oi3gaA&F>OaWEC>WNea(wy^wCF$SETR7$oS?63xxFv_7js4ihB_hr z|C`5@gt@+EZ%F9>7ueOI|0N*ll(6Dvq5se3N(n9c%kB<)JN`Rj>VGkkxjI_JS|^3k z-g9pq0`EM0rl9rd-JH_-f+zG*(#1>5q97X6tRy3nvF?r7=dIh=5|f9gIyi9MYVQ8% zXkgo!bd!7^e4g)@;Xb}&UN|bcv0KfBRO7}eto}Bnry##aBHqo4>nKro!_zS!)NpeQ z&b#KO8|Ik%cp4aImhudxUgr6yB$18tze%IctvK>V9C0|Voy5e+-|D+P!0QoaJy?aD z!sd!Pr$azx1;E=|Kf+tlVYMV~o-T>4mh8=w)Muo8MypTBz&w&m0PB6%*D0cPPWuNW z13{3rj?T2Rh#8_YEdgube#Y6B&a};8^!eyO`+*8(=|CH!0x@2!sjP|T-$ND7rD=Rk#&Ga!BonkSV~aC5QiXn;rFw?#;^ zYBj6=M5BD(!UX%#D4d^`$|U-Qw8&biW4YxS?Z00NMVQmU)?ceC{Nx$Z)o^73AHhj* z&@tr3Ai5pK!+lCO;fvR5j+K!9`&FV!5oI(9ZlsV6wN~mQ4;~c`k^6g6?H3T<@SJj8 zfv0j?c~Ti||XG(79&|C8URIMQ=(Z$RA=7T!XaC4uFk2Qbf=%?nD2y1f55 zO`2;mC&_EGBEu!0yz9`WK}Hi)MknRlnM_idFb{z(lp>YUSGVF-eon-%&`*Fx*I?7m02a*SOqBxTwK&} z<`rv1R(LKa@CCkRDXZZ*Q-;cuWXSVcImJ|00mpTu7-lnPP0d9Vqh7@__ad8|!oEzJ zGID-tjudvNDlDQ{jZI;mfT&t&k`Fy*U+|$#_TtI+vod3NZs5q{?Ngf`=#elH=1W&| zbfQiyjA=M17zriiI{E{W#>RS7N15XUJ(VWSRbe<&Fnk4ZUfiG(g}wg{0URVt$+f9Y zQZP?ec)AJO^|?KsRQ!X=wUQX!T9*Dmn%&DBs-;5gw*@r*r?PTmvCaKLHji8ty}DdKJs}ypp}%lYHNVdpMLA;T@zp&zUlwY(>Xd2!YQc zMfYqsQ;;yKvVx`v!oE8B8M&NBa3{`%Rt588gr}p z{utFB&fxv0tnexsAQQ!hd?Fg>*{M(;lg#e zhiGA1KG*KtDdTS54BXc+YgfapomvoF#m=>^(e}*!f`}d{s7vJ8buF=Xuf#1ybQ8QM zO*S~yNIAh9s1IF=B|cJJ>k{qrihxVy4Bw+;4x`BZ? z#Ye%q>8<76wAhmafyv#T5wrP@;5*lx#er}bY9J3eEZ`hGL!nl)bC6bBD{@}sW;#y+ zrAOxaBjghL?$HwM9Vt+H46Rl7ZJ!-J8n`t|IzZz8S_SzfDLZ{%T8wIE6|{4tZ=C8> z7)nU!*jF@PIeoI3Iuv!F>8>zuZ2JJYZee%ST$FEJb0~$kVx!ELKezfx#&!OwD8!7u zu!FYjiOcpT$}nzgz%0+ER!+5uB5utA^9I~NAc{fB)R-k zqNxKRry`wWge30MrLn& zimEjW>F1_`bQ~Pm<6SSOYun6=28S@=cF^J~gSi9AhW^VO0?SQdnWk&LlXHI3H}8eA zqZsMV_8)EHO}pn9YZzZVezTC$y!|}}BEhq7_Ppa-Xrnr7(Qh`ZgPB1T9|zIkxp6K# z@qIU+|eY%Fmh#XFw08VzgmVkaNB8EUS>U$YAD3Co;%jrXtqKdRM3sS8N?wz>KfNL`rFD`Q_d zd#VPV=BmFi0=t9Ddj3&0Y(ARvGZj}3QmyYIau?1djmc|78hFMuDAUeqC}Uio8Z54Z zTDsm<(zW79^FC7=G?{w`2HQ>%5@3*GyXP4fTdqUUAfN74}o+_2H~1B?{ZQexsu^kToD|AX2mXF52Li~3@4i&;&3(Afhei;-+4a-XiUB*A8>@)#n z(G~Ygb$Bj=sYkcf%6Ay0*2#Q~#OXSX}wWB!#ntpNTJAyZ*_%l2{Y^9k=A2t=NqtA@F7CL}}W%f4u%18&HaFr1K z7hMj~GkcZjdOAJ0MAtR1)0K5NVCz@rQRk1390`~&&?LH2xgK$)B=KS2B#?BKp-G(5 z`93TblEkBu#4?hA(`@}Kwj9XH2$2H?EE{gjXLp^pFLN~+o(@k%_^(!NK&w0~BS!z$ z-vXWB`B~;1D>=W8Q4&49?(^kiGHFbI)=uVyypqBwK{d{))4iWs&hMsxhb0Ss4jPs$ z_=5=Epq4CZmX4*xQ&(-Wt2#M!utswYAE_@MQWQR8!Jg31@bGpr+AD{` z;F$Xi5q>L{$xli+&nUJae#+VzeBWw*!=0B-KS|dGJXbT9oBfPh&1pBk-h5QFq+e?1 za-n~<#Gb5j@t#3Y|1i~u41s*yy?Odbpi8&wPxR!XPTXIv&<|0I(OF4zhHEUSjo;|1Oj^rk9 zx7Bmqa6cc^!}e438em&6Za(+swzF zr2l2Fh|j1V)gslR)b-{|L#cE9CcV?&Tuf}44$eSYwst<8CjE^Pnj(L+!g&OlY9c(6 zHJ|#FbuL--kmcJ_ZjHzan8MIz26?|w@Ra!7yp#PZvz!N2J1m#^C};OQ6DDsL2hRo8 zz;)x5YKU+u?P{hhVD16;XXUDj9_y~eTXI%1k-Y2P^F&X6S~6vpCxgv%kUX$vOzo>g zF@H?VuK3B1NEY5W&^&s`O0xhTm5zUh|4-(h$x5fG)_eS;qB-hnJ~c(*GJLY4JM1oX zw@L;|@^RTfl|sKd_!S4SbRFm_IFn(eRRt?`-nt6pp)r?3``-~uX#X}HAn$+C?*wVj zSgO@r&4Vs=Ez6}-|1qC3rm%%oyb`ob6A$76NzEUV7?)n96W9;6EiNE z=$&Pm)ehCO+7Foq<(lJU^MLu&@)6{5GI=n-8fZ-_csE#xZt-Ms?H!SWycgU$+%&70 zw6hIy`mJ&1KK&j0@DAb+0UNYa${0e3Eab{Q>a1t#yCQng>>Eor-*yhVX}YN?i(cVS zwU91SR-Tz^SSQj|Mgbc`0;A^JvH5u-w=xMP8@1{hR{H;Sg{r@iqQ92=F2AKF_-Zv@ zlrNDqlAdUfc#Ksy;x=U`tEouw^KS*r_{kwdlhZouU_2*|dEVs=_TIRPf2Sdq8*iTK zcrhG(lzOHE87^*XR2J0ibQoUEGw$9PvIMgU)Cneo0tv|bf27&q z`+wr89!%2fVES!MX@SsW-j_B3{XFZ_W=2XEEG=v*^IE@AYsPp6T^RU1O>IoqBzVoA z7mZ>?a}*pWg>Eo+X1{D8oXs5fpm=l&WZ*_JnjKzfbhI&!l%B@4+?xb`%K-6Fah z`#C4YhgvL&#!Z>lo7D&{dhECc)jRpKQ1NKqxj`|7#k2oznv(GN;|$Pw(L7mr$5V~i zg685|?|tlWMO_#$?pDQOsQP?NT({_wp8=f7JZFNVP9m2W{>S+W(H-snYQz z*V?%O!6!GPYA=)|!&+D28v65n!x@bp?nq$DFB5YLvx@oGrm6G0`)*G&#@v}^thtDD z92?V&=nFa90r+t1iRRSmsx)Kwm#C*&k!CChDpwNTx-YS&k(PU9s?qUsnvuUe?YQT6 zEAL7(I=t5Blmf5B(Kwr*-&67Etq=`mE~nw6+B&1wF`Tg5w*ZmKI59*>U$91=>)>_hE@N29_39lw;eEjr$5^3(By3tS%5N|MIqfSCoOR83REomvSYkXoJZ{-uB>Che!9)CIUq*t4&vVGt(>D8>&zcO;_ zJO8)W6wK@KQW&71dk|UK6Z+4S7=vh?uICbj&OyugiLYG8PX@+nJ?c#((?V8Vo<+0j zNS2jFZ^naEi~pKv)+E&HnSc9*^kX~_X%b^w5C7B~FT9?)hqY_g%cwas|I{M^9@vZw zJ8lqZ=Y^URDqE0X(Myrh%JKa~~F$)FIHtW@>= z=+UFr12L2Ogqjmg>gJp~NX7~-(!flU;CooFdoJZT!4pG*i@-2XlHhUY5j^KO!N0ye zn7YUm^CQMq`W2bE#|i#wNN^E5=Ccx9Ayagm;17ia7s+I^bEEMNA>c8+R(kCPo?TWs^ox@;s6!NVB}QW1b$8xgy*k z%U94fjSyc&r!K}(5?4rNez-iCvLegtmaj^AXNa$&!tX6#mGZAbd{v?E#a9Xz7r1XX zrOJ-2D}*6ye=Pd5ukXv6Sq}?qI#e;Y#2*Rd_UF?Whf3ys%D*3z#_%AK3ZiK8_g|1Z zD<=I|a89HhO3~&;9m+ffRvgJ%?LC7ptJ5e8+@Poru`oHtU%4mUaPr;6n7|Gp~x^uPY@ku^4LqE%@L9Eh62K+-AF zT0D6FRj{|-{S@!8)&sbI+fV$ZeBagQ$@%PI`Rd+wHt+nEaXNdA5uPdUEKQJJPJY9I z;@T_I$k^}o04Ah;|ROXCLXH2J;sP#eJ_M!6|Q#w8TI-g3r`DW23+(E zX2PXRes2m~v+BL7Dd}yQN2Tx12T&7fM6zizlWlBy zU5vgM~}YdeWj^RkU<(g$D;;@d5&knQzZNNY-nO0$bXI-%4kAp zv0|u0i?=pbLPPWIxg7NP>@Im*tLObOsFtXcNamXRDV2)P5n~*-ts|!S215t`17dHg z+s}VpxNKat-HgI*wH9vD-=EL=KZVtllAicNZl>*my-RlWc?RaZx#PZIbJ+;6?rmf zT3*KxZ{MAPz%Q5Muu=Y*zxGkZb^6dlL)~6#;jh0FTgN3&kiq*mee{qHw}NnH2kR)Z zC}4K+(Y#qOs3QX%VkseFx3j+K9-IkRWJzdf@DYQvQB_fM{~j<@T@RgNn|Yc1$7|=6Sg&@ z@0AepY4M>5OLH5fIhJ58j7BYjF`AH_O#iHIT_s0&d`7tDSt$lbw-k#eZX(~2twY)#>N zS^VuRi6YX}V^I72C;b>aUy3mHxQRbL(IL$O5)Wkd1g7tgt-Aoa>WqAM1grfVunej8 z<`PM_kZ2AA+|=WLTgRJAJgPaj*#{e{n)Q$BrB5>-Vy}nt{wj<^d zQ3>kW+Yca;A7_y1zv;k=zl*pmX1P1E_<19&#HUCnHE|4cp<4CZnd>=Wf)M74LQp$G zPBGVS?>QcG-2|Al#^%gSQbg)ybH&kIKpP{Vx5_lYo-5+Hts6?{4l4U_B>He&@;<&Nz3dW8hwyxRH zXTy4*%fw3bt@K5$inIECdWRNak|o?iJT>n9d%H zwFg&=prs(InDnk2=^N~(^9d5u+=Be-OPRS`7wD76m^kuy@VI%z1@m~F1$Hfz#y)!- zcDdu1)M*YWIqZ^rOwJ$pZFUc3mo>-D`9a1LR_XG{*-5%TyUaXp?76|%@3V@o+2vCg z?6O_N+rvx<`w}G`)cO#`Cq!96GRG4B@OTHcW+(AiWqrl!bnYM{Sm+`=%?Zb3)zR25 zt4)&C=;LO!CYaT9Nv(%%8D|t$&(NZ&PKk*)<}aE_^-Lu}>@27Bu*}ffnRPB>v;Sr@ zNv10X3=%jCDzF49+89_+b9qYKE}lp!ua*@{S6RU_chz{8=Sn?>OCYRzSHccyy)wL5 z?A7w_b49rhZ5ZQ^QT8z2mCN&0)oxdnyV~t>E#v867mrjdbbH2+AFpuX$r2kES8+jU znY(DbD{pD3r?5n2Sm9bA_wg%uUYkdnd9+$ycee98mvu^c@i-J0SD{+$B^}p-WiHajE31x12eF*F2gi6`@|&@yKfcnVy&iCNOoN)b`ZE(7qUI}?aSc&2 z&Gcs`HAKmb(Vsb~Axb8Y{!CXxl+0QEnF$SQ3d_KH6FNG~m)0||mf<0bPb?)Sos2xu z>%kwFsb;?|ZUhp=CktTqK=QT6*a;2WxIxA}zd!YG;FliatL51Et4Wd*B!OSbWNV@| z=ep$@CR9aGMNh%zW8ElGa!aC_QEJBWlAWI116D>s&i>W zvLmpd%yWyEW;edHyj1+u+}NOdWN8-thc8NCYbxKoSqgI(CkM7Y!&g(C1T()FO-Ub+ zV3xx+9JcKW2KbEx&|yy^Zd;U^4nYDnrSx6Rv_d8;It{ZsQBF9>F&}BItW#Wg;e{@_ znlIHa{E5JfI?IKtg=-H;FgC2~Rb9Ha%_^xn$>s~4Uzj*d`hcVc(v(V1Tki!eZ8xvwu#N71lNgveWM4*PeZN8r{;`Pq*3MaUKwYMi z_L}bJP^OI1YBs69Q{-DS#BHZ=q)*XmvwTV2o4?|VLMwjP%q}+JbCTHP1_wJ=-%zGD??8$QO@4cFWCHg~ZH&Y0`4?U9(bW=Hmyy z*x@}AUTW=&$BUg9Bkb^ACCODRwNA@C%AIOWBkUt_XZf`;lTi>=Z*WxA`>#WHs%vW<1X_i+5P(F#@-CULbj> z^}w;@u^G2X^La1T( z{&m6w%crFpd$LoFC-$(f{3dVlz02MlFy=3*#(@ri?-zicS?R`lAZcuxVE`T=8E{>g zW^|8BGxmKz8bHx|sm3H=6Ho?>1A2*{@(ugLU#A%*!_$pqVD4o0rGZuK2POggfz3cn z5ick8#|~9E*Hp9rFL{ zzX>P#Tf*5}mGhJKFY-*@BRvcIxhcj>Z@H&*v0JOAaLKR0<4UrA#M64j{4GfrPnbCA zl1nd3zC1N8JtH$q1^vJHH*_#Ko!}RJON!BabBa*{><3Q#^S7K~j4{sOG=hfEuhWj} ze&V#W&+?iSJBW`Dv9ti{C+q0pfXGMt=X>q39An}^ z+HP9r`X$<)Vwng3Lo;`&j^9(M&6r?a8S`Io<1*%s)6b%G_VMC|qx$>B{p(_W4FF}vsS5u1m{%BsR;p6Kd zrhG)-gdH;;Qydb-&R??F@yJpBK4TtcOG}GUh8d8M;?Kt#v14u!I}Xn%|A4Vm`3H;+ zTS7GW|M^3`B6SM%MC$=t@b0dpi~3nud! zUk4_7e|+7TCu2s=Pvs>x!xxW9_j|@TO!;lVq&!A5rqt&i%;}gWrVq0ha|LF6L8`G5 zGYNAwW;SL$=6uYJn9DIA#axT|6y_6{TQGNGZo}M%xf}B!<_DND3sQ}LU?yNneWYO8 zKfy=;!oVrQ;Mq=Ssbw6v+n(SZ2kizxuSjSW1^ptRRXFsGhUSXbfSaCw5ice)Z?We5*paQ6h2(G z#o~uhH_J&O5*p7Tv>jl+m54%I^PH4L*N4r6(bS*J)2oVE^4jC4!`Qe4CbeV1j z_F&4&>V8aCRRi6avPof7ryDG*2S#GDEFDP1WGyx@1(Q|FKrSZhc7Y;HmhJ*Im|XG? z)MKLMB(NS6l^lW1n9NcGJ29E)1v)TM=n*)8`8j4UCa1##ah`Oe3)6*(rs2ROOx9Eb z*_iT^y0hy^mr6OSe^PGS&vBK?OaXj={KCSx;wWVgg%L zD3+g3{qLKuzeVy8H=(uQ;I!lZjxIb?03V<*>mMKmcb~E6HO3ske!v9e*W=~QxFx)i z28;p50aJh+U>;Bc)Btw_-NfmUc)L@KXdoVN0f|5okPM^%aX>j~kD~x{L1i-qm_Nuc zTBO4`2UL^syasp>w|6oB2J9fPy2=+}tbdfb1R(F-tpVgG-|GQ6`71w?RKNbFl-vib zRKA*i@-1%aM>eA2RsA4p;^GuzLm4z#q{nYEMw2m@lqDf4Q;qdn_}&l1W8XtqDW8nT zBC&5KUhl+AKUjZt`Bn)VY($9 z(wmE2#-uL3M^0cF3cHL+Tgt#4a}#-Y5H^~8#sIrrWXm zG&bxeExz{iC5ANxAuts{K%B23)tv2WlzneR<}yNFxQcOtL>x;{bt&BQZs zUqd|6TM7Z z!8GxUGIAd^BbWVUlpG-wj;=7j8bvJfH74{JIHu5Ly`EREb|4-`SY; zxF->=gm8)2Yp~A+b_wp6WEz`rOD6vR|NDLvh@2W_M5Z#*5BaT{7G-)Kt&yO;C`?=Z096`AgffQgaPzl@({2cfV@CRTgun#y0L}o`BKLC<|DL^)G15gIs z0jvdn1^fZn1-t`%1at%8&}js4I&c9n1;_zz07`%*fc(~AJ_>BM?7K1d1KpNA20ESv zOad~1e4q%p4Upe@%-;abzz*OI;9bB30A>TlfCpFw zJP7;>Xa@EICU6vpyB55GBp?Hr4U_>Zfpx%Rz%#%OU@!0ya0m#8pT+=_fNWqsPy^Hh z4+6gent?Vzejj2U1j2K{6}SNSA#g3Q04M`$fO~*Pfi1vxU^lQ2H~<_1!moo?z!+dW za0QS9%mx+!Wxx`k5m*mw0d@lK0tbNsGvOEDTwoHA50n8bf%||*fGt1^&;fh`90CU9 zfj4k2FbTLCxB(~!ZUgQC9s#xhJAikAZXldCHX0ZQWC8PlGQbDO??KE>z%#%O;4R=2 zpcjanMLPnn0A>R7fl6Q{um;!wJOi`=?*IpYqrl+V&<7X?OaZchnLsg639JV010DgM z0JZ~f03QI|z)>J(4)OxH0LTF5169CE;2vNDuo-9p-T?Lip8>tVu({+9Bm$QL89**D z4=4wGz}>();0fRlz%HNz_zdU)23!w61CxLZARo9DSPnD-KL?%!wgbC?cYy;yFA#GB zxC0455|9SW1d4$rKqIgg_zkcfcnA0l=m7@bNL*k%a0QSJ%ma#na^Mc25qJc664(yx z20j2j1A2hSdDI@J%)!BTx|@R&Fn5vn-QkY7^8w*9ms z37z3CLsN4)3Xe+*3(E53aE8)~p5sQ#^RdoGrs#b>j{CH7Qb3XTZO4f;yR^#VEhx*X za=XdVvWdR2Lct&hh2XZI`gVLojaL<+7P*Tu+=W$c(U>hULfog7hqzlQU*~mKEt7D( zhVSMz`>Om3r5+)TlLELp-}x1G09?z^*TWf#REa0wg_X-hzn2I&nOmWvCs6B%_?7t zx(oTH{vG#%(rR~RO`%&Uj+c5FH?SNfnj)Nh}>%5*|{MnqJDJb`7#RiglW(_&ot`(KbcwZj}$3;%Kh@BTlHG(@P*qh?MWa-0LF}Pz1G}W0&z>Oq z>!od3F0^YUH2SodTrX$IEKHCl8Kp}EKk8*sD89nq{q0suR4~K>^LU zjJzaIZMT@vv4^x=6<#n4hPK$qimT;+D%u-^A#CQ-sizhdiMPU87*%UP(5)_LSFw?d z+_2@ql$O)@_NygaXdWK-Vv&G?uUm;Tvf!wmkX^f+fV&8-rK&EVjnVg(w9?T?6vgu4TvWMdA-wJI;vn{{(yD4D`JE6-3@TrQG^Ne2P!dDQY+ZQ!GruCEqFPF5 z5hb(SyEwgoUa+X3%I>00)Zd?I+@SjdUF|~We*J^$E!2H2g)aoEP6aF z#wz*Job|}8n#{OBU#Zltsuta^9%vcIsRvwz=8&$cw6I#(!*a>2@gT<4$i{NjGQ`3k z4y`J6OXDJZo(EYMqzo=j&B(VVVV@W}u;NBSgcSUkz>P(%J<{syZu1qc8SW*e zh3@o%N((!9Kr@~A_2&n1OShRp^0H-$rFmCVUEHB9<0PRswmv*0_EOK{f=VkNNGCL% z;q^!X8RV6D84?HUMp}GU1zIXq`E6TP!Q#>~NUCMLZs|dqYI_JFNLjmS9@H&9ucEB9 zNZ}@UYBynsnG0norR}-yaz z2~KJ(HzjpErL@CPjDxP4guygaG3?BoltV%>gbbmFq9wknar7Mp>xPh3Rk2vHGil+H z?JlcSab(0~$$NZeRdRaStz!r-BJUQK(s@>;mlag&8k<#KQcL-(MWwfLy1U#f`Phw%Bks%$tE%muK-9Peu@RfrwU(v^ z%VHM=b44mG;dgO?g;Bw$QnjVAW&leTBb_a@g#buEoq_PIqKM;yg0w!VAfyVN`JfXj zr=onJ9Z&i+J7)PR4NHonFz1aC!WW$#Z+r6-g z!B3GxCgobFdw#wha>#c)k4`;6k^YNr~E8ScdtmZ`j=x)n~%6`45}RBF^!lM*(; z#hO+y8&om+&Nan0jdRK3CEvPQY@2S^V!NiaOpO%f-s&$6J9@Tcq zESKJ00@*Hn@-4ZQs@0BZ)%sVIqMpX~ULWif)cUXRQYja$zHX5{R3GLYXv_8kxX?>21;y7%m0@hgx zHLz{W~VeA2r*t`pDZWfzT^60c@$Hi*Tj@@d{*zJZPx#u$CRE>sj2Q9uO zgOHJ^;{rJ?93@1b_HTtzZW+34c9_svkcB#-WzJ!#TNRmWrE9N@II~Sc+HN@o++XtK z&_s3mecc^5JF1Q;OHQ^B#YNaJNQ>jhDZ*q`SaOQ*jIxDNBn!I?cl9D}zBr^38fK)c zo<@CX9CRZJ)_^1H2;&G4CL0A-s#g?%~$n5qiZ2aCTVzlE#VGmCUz#iX>dfJsfLyr4pey39e(vRhnc*{lpL zn^PNlq-F(W+*Yhp5y>Fr6PM{3)08|4byFzY4tlJmBkD1tb_pFuXcs#lZL?{ht3JO% z_hOQ3dWpLb@vmE#*bBW|Htp0hhfggSjZu#`+PpknGC~{B$;hk zW?S2wO04o>l^jY%sf3WERZfYTLq(}nLXJy9CGAr}CHp^L_r3StJL1!)@AvzE{2smQ z-hIBV>%Okn^*TIXuh%7h4B!B-Y>>nl_f_gGe;IU{^sN3c6+Mi{e-HK2ZExf&d6(?D z@+G>+RJnR!HMt6vzXtl3Qc**xC*4sgch%EJ%GET<8wG!fcyUtcr_f6!EMfnX___+O z4@ycW)v$=v{LceoD%DQkc=_10|H+~mQ|f7te%+SA&q07hT58b*20H;&B&LihCK%$6 zgiRC3P>lW4yZ`+DFM8m?^bjTh6;~E}hTjfbZXF!gg^v?k4z`8Z z=3#pR&n>~W8rxggwqe_i?Q?90u${pc#so1TC_flA1tJ15v~5~d*

{}(;`|KmCl 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 literal 0 HcmV?d00001 diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/bin/openbtl_olimex_lpc_l2294_20mhz.hex b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/bin/openbtl_olimex_lpc_l2294_20mhz.hex new file mode 100644 index 00000000..b2a52ca8 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/bin/openbtl_olimex_lpc_l2294_20mhz.hex @@ -0,0 +1,361 @@ +:1000000018F09FE518F09FE518F09FE518F09FE5C0 +:1000100018F09FE50000A0E118F09FE510F09FE5C3 +:100020005000000034150000A0000000341500004E +:1000300034150000E41400000C150000000000005E +:10004000E4009FE50110A0E3001080E5000000EF50 +:10005000D8009FE5DBF021E300D0A0E1040040E2FE +:10006000D7F021E300D0A0E1040040E2D1F021E389 +:1000700000D0A0E1040040E2D2F021E300D0A0E1F2 +:10008000040040E2D3F021E300D0A0E1040040E20C +:10009000DFF021E300D0A0E1150000EB290000EA29 +:1000A00088009FE5DBF021E300D0A0E1040040E2FE +:1000B000D7F021E300D0A0E1040040E2D1F021E339 +:1000C00000D0A0E1040040E2D2F021E300D0A0E1A2 +:1000D000040040E2D3F021E300D0A0E1040040E2BC +:1000E000DFF021E300D0A0E1010000EBB80000EB5D +:1000F000140000EA38109FE538209FE538309FE56E +:10010000030052E10400913404008234FBFFFF3A03 +:100110000000A0E324109FE524209FE5020051E1A8 +:1001200004008134FCFFFF3A1EFF2FE140C01FE0B6 +:10013000DC1E00407C16000000020040000200406F +:1001400000020040F406004010402DE908D04DE2C6 +:10015000FC309FE5003093E504308DE503308DE2FF +:100160000040A0E3EC109FE5EC209FE50100F3E5E3 +:10017000910000E0260A40E2160E40E2020050E143 +:100180000800009A014084E2FF4004E2040054E3C6 +:10019000F5FFFF1AC4009FE57010A0E3C0309FE593 +:1001A0000FE0A0E113FF2FE18422A0E1022082E30F +:1001B000FF2002E2AC309FE58420C3E55510E0E368 +:1001C0008C10C3E55520A0E38C20C3E50100A0E31B +:1001D0008000C3E58C10C3E58C20C3E5B828D3E1CB +:1001E000010B12E3FCFFFF0A78309FE50320A0E338 +:1001F0008020C3E55520E0E38C20C3E5AB2082E2FC +:100200008C20C3E50020A0E30020C3E5042082E2A7 +:100210000420C3E50220A0E30020C3E50120A0E301 +:10022000013C83E20020C3E53C309FE5002093E5DC +:10023000052082E3002083E530309FE50FE0A0E158 +:1002400013FF2FE128409FE50FE0A0E114FF2FE10D +:10025000FCFFFFEA58150000C0D40100A080020096 +:10026000241600007C0A000000C01FE000C002E06D +:1002700078020000C402000008402DE930309FE5FC +:100280000FE0A0E113FF2FE128309FE50FE0A0E190 +:1002900013FF2FE120309FE50FE0A0E113FF2FE1D6 +:1002A00018309FE50FE0A0E113FF2FE10840BDE803 +:1002B0001EFF2FE1740A0000440A0000800D0000B8 +:1002C0000003000008402DE924309FE50FE0A0E185 +:1002D00013FF2FE11C309FE50FE0A0E113FF2FE19A +:1002E00014309FE50FE0A0E113FF2FE10840BDE8C7 +:1002F0001EFF2FE1780A000068030000C809000013 +:1003000004E02DE50CD04DE20030E0E30430CDE513 +:100310000030A0E30530CDE538309FE50FE0A0E1E7 +:1003200013FF2FE130309FE50FE0A0E113FF2FE135 +:1003300028309FE50030D3E5010053E304008D022F +:100340001C309F050FE0A00113FF2F010CD08DE2A0 +:1003500004E09DE41EFF2FE148040000DC0B0000D8 +:10036000000200409C04000008402DE924009FE5A5 +:1003700024309FE50FE0A0E113FF2FE1010050E3DF +:1003800010009F0514309F050FE0A00113FF2F01FF +:100390000840BDE81EFF2FE104020040C40C00002D +:1003A0009C04000008402DE9FF1001E218309FE591 +:1003B0000FE0A0E113FF2FE110309FE50FE0A0E177 +:1003C00013FF2FE10840BDE81EFF2FE11C0C0000C9 +:1003D000880400000120A0E304309FE50020C3E56D +:1003E0001EFF2FE10002004004309FE50000D3E52E +:1003F0001EFF2FE10002004008402DE90C309FE570 +:100400000FE0A0E113FF2FE10840BDE81EFF2FE140 +:10041000700400000020A0E304309FE50120C3E544 +:100420001EFF2FE14402004014309FE50120E0E36D +:100430000320C3E50400C3E50220A0E3B424C3E124 +:100440001EFF2FE1440200401C309FE50020A0E386 +:100450000020C3E5482083E54320C3E5B424C3E17D +:100460000220C3E50120C3E51EFF2FE14402004046 +:100470000C309FE50000D3E5000050E20100A0131E +:100480001EFF2FE1440200400020A0E304309FE55E +:100490004320C3E51EFF2FE14402004038402DE910 +:1004A0000040A0E10030D0E5FF0053E31200001A45 +:1004B000D7FFFFEBEC349FE50120A0E30020C3E56C +:1004C0000010E0E30310C3E51010A0E30410C3E53F +:1004D0000010A0E30510C3E54000A0E30600C3E55B +:1004E0000700C3E50810C3E50920C3E50A20C3E5FA +:1004F0000820A0E3B424C3E11B0100EAA4249FE583 +:100500000020D2E5010052E32401001AC93043E281 +:10051000350053E303F19F97110100EAC80700007B +:100520006409000064090000580900006409000023 +:1005300064090000340900001C080000F0080000F5 +:10054000B8080000640900006409000064090000A4 +:1005500064090000640900006409000064090000E7 +:1005600064090000640900006409000064090000D7 +:1005700064090000640900006409000064090000C7 +:1005800064090000640900006409000064090000B7 +:1005900064090000640900006409000064090000A7 +:1005A0006409000064090000640900006409000097 +:1005B0006409000064090000640900006409000087 +:1005C00064090000CC0600004C060000F4050000A1 +:1005D000AC06000064090000640900006409000022 +:1005E0002C07000064090000640700007007000089 +:1005F000A40700000120D0E53F0052E30200009A6A +:100600002200A0E387FFFFEBD70000EA94539FE5A9 +:10061000040085E2481095E58C339FE50FE0A0E1EA +:1006200013FF2FE10030E0E30330C5E50120D4E5FE +:10063000483095E5033082E0483085E50130D4E567 +:10064000013083E2B434C5E1C70000EA0130D0E5EF +:100650003F0053E30200009A2200A0E371FFFFEB8A +:10066000C10000EA041090E538539FE5481085E585 +:10067000040085E20120D4E52C339FE50FE0A0E1E2 +:1006800013FF2FE10030E0E30330C5E50120D4E59E +:10069000483095E5033082E0483085E50130D4E507 +:1006A000013083E2B434C5E1AF0000EAF4329FE5E3 +:1006B0000020E0E30320C3E5042090E5482083E523 +:1006C0000120A0E3B424C3E1A70000EAD4C29FE55F +:1006D0000030E0E30330CCE548109CE5043090E5C1 +:1006E000000053E30020A0030500000A0020A0E35F +:1006F0000100D1E4002082E0FF2002E2013053E259 +:10070000FAFFFF1A07208CE598329FE50120A0E34D +:100710000420C3E50020A0E30520C3E50620C3E5CF +:100720000820A0E3B424C3E18F0000EA74329FE5FF +:100730000020E0E30320C3E570229FE5482083E525 +:100740000020A0E30420C3E50520C3E50620C3E59F +:100750000720A0E3072083E50820A0E3B424C3E139 +:10076000810000EA0000A0E32EFFFFEB7E0000EA1C +:1007700030329FE50020E0E30320C3E50020A0E342 +:100780000420C3E50110D3E50510C3E50620C3E549 +:100790000720C3E50820C3E50620A0E3B424C3E195 +:1007A000710000EAFC419FE50030A0E30030C4E5A1 +:1007B00017FFFFEB0030E0E30330C4E50130A0E3B6 +:1007C000B434C4E1680000EAD8319FE5480093E5FD +:1007D0003F10A0E3012084E2D4319FE50FE0A0E1C7 +:1007E00013FF2FE1000050E30200001A3100A0E3E4 +:1007F0000CFFFFEB5C0000EAA8319FE50020E0E37E +:100800000320C3E5482093E53F2082E2482083E5AA +:100810000120A0E3B424C3E1530000EA0130D0E595 +:100820003E0053E30200009A2200A0E3FDFEFFEB2E +:100830004D0000EA6C319FE50020E0E30320C3E5B2 +:100840000120A0E3B424C3E10110D0E5000051E38E +:100850000700001A5C319FE50FE0A0E113FF2FE1D4 +:10086000000050E34000001A3100A0E3EDFEFFEB72 +:100870003D0000EA2C319FE5480093E5022084E228 +:100880002C319FE50FE0A0E113FF2FE1000050E3C2 +:100890000200001A3100A0E3E2FEFFEB320000EAA2 +:1008A00000319FE50110D4E5482093E5022081E066 +:1008B000482083E52C0000EAE8309FE50020E0E3D3 +:1008C0000320C3E50020A0E30420C3E50520C3E521 +:1008D0004010A0E30610C3E50720C3E50820C3E5E8 +:1008E0000920C3E50720A0E3B424C3E11E0000EA09 +:1008F000B0309FE5480093E5041094E5B8309FE5DB +:100900000FE0A0E113FF2FE1000050E30200001A06 +:100910003100A0E3C3FEFFEB130000EA84309FE543 +:100920000020E0E30320C3E50120A0E3B424C3E1F9 +:100930000D0000EA84309FE50FE0A0E113FF2FE1F6 +:1009400060309FE50020E0E30320C3E50120A0E341 +:10095000B424C3E1040000EA3100A0E3B1FEFFEBE0 +:10096000010000EA2000A0E3AEFEFFEB34309FE57B +:100970004330D3E5010053E31000A003A9FEFF0BB1 +:1009800020309FE50120A0E34320C3E5030083E27C +:10099000B414D3E128309FE50FE0A0E113FF2FE16D +:1009A0003840BDE81EFF2FE144020040A40A0000C9 +:1009B0005C1500009C0D0000F00D0000B80D00005B +:1009C000380B0000A403000008402DE95C309FE5CF +:1009D0000FE0A0E113FF2FE1010050E31100000A36 +:1009E0004C309FE50030D3E5010053E30D00001AC1 +:1009F00040309FE50FE0A0E113FF2FE1310050E30D +:100A00000800009A0020A0E324309FE50020C3E501 +:100A100024309FE50FE0A0E113FF2FE11C309FE59C +:100A20000FE0A0E113FF2FE10840BDE81EFF2FE11A +:100A3000F803000090020040C80E0000240E0000E1 +:100A4000E80A000008402DE90120A0E318309FE5E6 +:100A50000020C3E514309FE50FE0A0E113FF2FE174 +:100A6000D8FFFFEB0840BDE81EFF2FE190020040D9 +:100A7000800E00001EFF2FE11EFF2FE110402DE928 +:100A800014309FE5000083E5041083E50C409FE5EA +:100A90000FE0A0E114FF2FE1FCFFFFEA9402004009 +:100AA000780A0000F8402DE90140A0E1005052E230 +:100AB0000900000A0060A0E124709FE50130D4E441 +:100AC0000130C6E40FE0A0E117FF2FE1015045E23D +:100AD0000558A0E12558B0E1F7FFFF1AF840BDE83E +:100AE0001EFF2FE1780A000008402DE93C309FE509 +:100AF0000FE0A0E113FF2FE1000050E30900000A1E +:100B00000101A0E3021AA0E34020A0E3E4FFFFEB11 +:100B10000220A0E318309FE5402083E50131A0E3E7 +:100B20000FE0A0E113FF2FE10840BDE81EFF2FE119 +:100B3000D40D000000C01FE008402DE90C309FE5F7 +:100B40000FE0A0E113FF2FE10840BDE81EFF2FE1F9 +:100B5000500000001C309FE51430D3E5010013E382 +:100B600010309F150030D3150030C0150100A013C0 +:100B70000000A0031EFF2FE100C000E038402DE977 +:100B80004C309FE51430D3E5200013E30000A003B0 +:100B90000D00000A38309FE50000C3E51430D3E5AE +:100BA000200013E30100A0130700001A24509FE562 +:100BB0001C409FE50FE0A0E115FF2FE11430D4E5C4 +:100BC000200013E3FAFFFF0A0100A0E33840BDE86C +:100BD0001EFF2FE100C000E0780A000034309FE5DE +:100BE0000020A0E30420C3E50820C3E51420C3E5EA +:100BF0007F10E0E30C10C3E54110A0E30010C3E553 +:100C00000420C3E50320A0E30C20C3E50720A0E3F4 +:100C10000820C3E51EFF2FE100C000E0F8452DE9E4 +:100C20000050A0E10140A0E1400051E384009F8515 +:100C30008310A08380309F850FE0A08113FF2F8158 +:100C40000400A0E1CCFFFFEB010050E364009F151E +:100C50008610A01360309F150FE0A01113FF2F1115 +:100C60000460A0E1000054E31000000A0040A0E38B +:100C700048709FE53C809FE53CA09FE50FE0A0E128 +:100C800017FF2FE10400D5E7BBFFFFEB010050E3A6 +:100C90000800A0118E10A0130FE0A0111AFF2F1151 +:100CA000014084E20438A0E1230856E1F2FFFF8A04 +:100CB000F845BDE81EFF2FE12C1600007C0A00005D +:100CC000780A000070402DE90050A0E1A0309FE5B7 +:100CD0000030D3E5000053E30A00001A94009FE5BA +:100CE0009BFFFFEB010050E30000A0131E00001A61 +:100CF0007C309FE50120A0E30020C3E50000A0E3D5 +:100D00004500C3E5180000EA64009FE54540D0E5D2 +:100D1000040080E0050080E28DFFFFEB010050E35E +:100D20000000A0131000001A014084E2FF2004E23A +:100D30003C309FE54520C3E50430D3E5020053E194 +:100D40000000A0130800001A24609FE50500A0E140 +:100D5000051086E220309FE50FE0A0E113FF2FE1B0 +:100D60000030A0E30030C6E50100A0E37040BDE81C +:100D70001EFF2FE19C020040A0020040A40A0000D8 +:100D800008402DE90C309FE50FE0A0E113FF2FE1B3 +:100D90000840BDE81EFF2FE11C12000008402DE9AD +:100DA0000C309FE50FE0A0E113FF2FE10840BDE804 +:100DB0001EFF2FE13412000008402DE90C309FE5A2 +:100DC0000FE0A0E113FF2FE10840BDE81EFF2FE177 +:100DD000A012000008402DE90C309FE50FE0A0E1D3 +:100DE00013FF2FE10840BDE81EFF2FE14014000073 +:100DF00008402DE920309FE50FE0A0E113FF2FE12F +:100E0000000050E30000A00310309F150FE0A01178 +:100E100013FF2F110840BDE81EFF2FE1D41300007F +:100E20008814000014309FE50020A0E3042083E52F +:100E30000C2083E5082083E5102083E51EFF2FE1C9 +:100E4000004000E01C309FE5082093E518309FE546 +:100E5000001093E5011082E0040093E5011060E0CA +:100E6000060083E81EFF2FE1004000E0E40200409E +:100E700004309FE5000083E51EFF2FE1E4020040FF +:100E800008402DE930309FE50000A0E3140083E521 +:100E9000280083E524209FE50C2083E50120A0E3C2 +:100EA000042083E5082093E514309FE5042083E5C2 +:100EB000EEFFFFEB0840BDE81EFF2FE1004000E021 +:100EC0005FEA0000E402004008402DE9DCFFFFEB90 +:100ED00008309FE5000093E50840BDE81EFF2FE1C4 +:100EE000E4020040F0412DE90060A0E10040A0E3F1 +:100EF0000450A0E158809FE558709FE50FE0A0E105 +:100F000018FF2FE1043097E7060053E10900008A3B +:100F1000041087E0041091E5013083E0030056E1FE +:100F20000400002A852085E028309FE5023183E017 +:100F30000800D3E5040000EA015085E20C4084E299 +:100F4000C00054E3ECFFFF1AFF00A0E3F041BDE84E +:100F50001EFF2FE1780A00006415000030402DE9E3 +:100F600024D04DE20040A0E1000090E5DCFFFFEB63 +:100F7000FF0050E30000A0033D00000A3230A0E370 +:100F80000C308DE510008DE514008DE50130A0E3F7 +:100F900000308DE5E4309FE50FE0A0E113FF2FE185 +:100FA0000C008DE20D10A0E13A31E0E30FE0A0E18A +:100FB00013FF2FE100309DE5000053E30000A01374 +:100FC0002B00001A3330A0E30C308DE50450A0E173 +:100FD000043095E410308DE514508DE5023CA0E31B +:100FE00018308DE598309FE51C308DE50130A0E389 +:100FF00000308DE584309FE50FE0A0E113FF2FE185 +:101000000C008DE20D10A0E13A31E0E30FE0A0E129 +:1010100013FF2FE100309DE5000053E30000A01313 +:101020001300001A3830A0E30C308DE5003094E551 +:1010300010308DE514508DE5023CA0E318308DE5AD +:101040000130A0E300308DE530309FE50FE0A0E1F6 +:1010500013FF2FE10C008DE20D10A0E13A31E0E327 +:101060000FE0A0E113FF2FE100009DE5010070E219 +:101070000000A03324D08DE23040BDE81EFF2FE1F8 +:10108000780A000060EA000008402DE9813BB0E1E9 +:101090000000A0130900001A003090E5010053E1A0 +:1010A0000100A0030500000A041080E4022CA0E364 +:1010B00010309FE50FE0A0E113FF2FE10100A0E356 +:1010C0000840BDE81EFF2FE1A40A000038402DE9CA +:1010D0000040A0E10150A0E14C309FE5030050E149 +:1010E0000600000A020A51E30600000A9AFFFFEB1D +:1010F000000050E30040A0030800000A020000EADC +:1011000028409FE5000000EA1C409FE50400A0E1A4 +:101110000510A0E1DBFFFFEB000050E30040A0035F +:101120000400A0E13840BDE81EFF2FE1F0040040BC +:10113000EC020040F0472DE90050A0E10140A0E1A1 +:101140000270A0E10360A0E1A194A0E18994A0E174 +:10115000003090E5010073E30400001A0910A0E1DB +:10116000C8FFFFEB000050E30000A0032600000AC8 +:10117000003095E5090053E10500000A0500A0E1F3 +:101180000910A0E1D0FFFFEB005050E20000A003E7 +:101190001D00000A003095E5044063E0044085E04E +:1011A000044084E268809FE568A09FE5029C89E294 +:1011B0000FE0A0E118FF2FE1043085E2043063E086 +:1011C0000A0053E10500009A0500A0E10910A0E122 +:1011D000BDFFFFEB005050E20800000A044085E22A +:1011E0000130D7E40030C4E5016046E20668A0E1C2 +:1011F0002668B0E10300000A014084E2EBFFFFEA49 +:101200000000A0E3000000EA0100A0E3F047BDE811 +:101210001EFF2FE1780A0000FF0100000C309FE55F +:101220000020E0E3002083E5042283E51EFF2FE198 +:10123000EC02004070402DE90040A0E10150A0E127 +:101240000260A0E126FFFFEBFF0050E30000A003D7 +:101250000E00000A010044E2050080E020FFFFEBE1 +:10126000FF0050E30000A0030800000AA434A0E13E +:10127000100053E30538A0E118009F0518009F15E2 +:101280000410A0E10620A0E12338A0E1A8FFFFEBB5 +:101290007040BDE81EFF2FE1F0040040EC0200406A +:1012A00070402DE920D04DE20050A0E10160A0E1A6 +:1012B0000BFFFFEB0040A0E1010045E2060080E0EB +:1012C00007FFFFEB0050A0E1FF0050E3FF005413C5 +:1012D0000000A0033900000A050054E10000A083CB +:1012E0003600008A000054E30000A0033300000A27 +:1012F000100055E30000A0833000008A3230A0E3E4 +:1013000038008DE80130A0E314308DE5B8309FE55A +:101310000FE0A0E113FF2FE10D00A0E114108DE21A +:101320003A31E0E30FE0A0E113FF2FE114309DE537 +:10133000000053E30000A0132000001A3430A0E3A3 +:1013400038008DE884309FE50C308DE50130A0E356 +:1013500014308DE570309FE50FE0A0E113FF2FE121 +:101360000D00A0E114108DE23A31E0E30FE0A0E1BE +:1013700013FF2FE114309DE5000053E30000A0139C +:101380000E00001A3530A0E338008DE80130A0E3EC +:1013900014308DE530309FE50FE0A0E113FF2FE121 +:1013A0000D00A0E114108DE23A31E0E30FE0A0E17E +:1013B00013FF2FE114009DE5010070E20000A0334F +:1013C00020D08DE27040BDE81EFF2FE1780A0000BA +:1013D00060EA000004E02DE50CD04DE254209FE5CA +:1013E000823F82E2030093E9011080E0082292E547 +:1013F000021081E00C2093E5021081E0102093E5BB +:10140000021081E0182093E5021081E01C2093E592 +:10141000023081E0003063E208208DE2043022E5F2 +:1014200014009FE50410A0E381FFFFEB0CD08DE2D8 +:1014300004E09DE41EFF2FE1EC02004014200000B8 +:10144000023AA0E3050093E8000082E0082093E55B +:10145000020080E00C2093E5020080E0102093E57C +:10146000020080E0142093E5020080E0182093E55C +:10147000020080E01C3093E5030080E0010070E290 +:101480000000A0331EFF2FE108402DE948309FE502 +:10149000043293E5010073E30400000A3C009FE579 +:1014A000ADFEFFEB000050E30000A0030800000ABF +:1014B00024309FE5003093E5010073E30100A003B1 +:1014C0000300000A10009FE5A3FEFFEB000050E2BE +:1014D0000100A0130840BDE81EFF2FE1EC02004010 +:1014E000F004004004E04EE21F402DE910009FE5AB +:1014F0003810A0E30C309FE50FE0A0E113FF2FE1CF +:101500001F80FDE8501600007C0A000004E04EE257 +:101510000F502DE910009FE54610A0E30C309FE529 +:101520000FE0A0E113FF2FE10F90FDE8501600003F +:101530007C0A00000F502DE910009FE55410A0E335 +:101540000C309FE50FE0A0E113FF2FE10F90FDE8C5 +:10155000501600007C0A0000010204084F70656EFE +:10156000424C540000200000002000000100000058 +:1015700000400000002000000200000000600000A9 +:101580000020000003000000008000000020000098 +:101590000400000000A00000002000000500000082 +:1015A00000C00000002000000600000000E0000075 +:1015B0000020000007000000000001000000010002 +:1015C0000800000000000200000001000900000007 +:1015D00000000300002000000A00000000200300BB +:1015E000002000000B00000000400300002000006D +:1015F0000C00000000600300002000000D0000004F +:1016000000800300002000000E00000000A0030086 +:10161000002000000F00000000C0030000200000B8 +:10162000100000006D61696E2E6300002E2E2F2EBB +:101630002E2F2E2E2F536F757263652F41524D370B +:101640005F4C5043323030302F756172742E63001E +:101650002E2E2F2E2E2F2E2E2F536F757263652F49 +:1016600041524D375F4C5043323030302F47434367 +:0C1670002F766563746F72732E630000A8 +:00000001FF diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/bin/openbtl_olimex_lpc_l2294_20mhz.map b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/bin/openbtl_olimex_lpc_l2294_20mhz.map new file mode 100644 index 00000000..49cf82a0 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/bin/openbtl_olimex_lpc_l2294_20mhz.map @@ -0,0 +1,176 @@ + +bin/openbtl_olimex_lpc_l2294_20mhz.elf: file format elf32-littlearm +bin/openbtl_olimex_lpc_l2294_20mhz.elf +architecture: arm, flags 0x00000112: +EXEC_P, HAS_SYMS, D_PAGED +start address 0x00000000 + +Program Header: + LOAD off 0x00008000 vaddr 0x00000000 paddr 0x00000000 align 2**15 + filesz 0x0000167c memsz 0x0000167c flags r-x + LOAD off 0x00010200 vaddr 0x40000200 paddr 0x0000167c align 2**15 + filesz 0x00000000 memsz 0x000004f4 flags rw- +private flags = 5000000: [Version5 EABI] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 0000167c 00000000 00000000 00008000 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .bss 000004f4 40000200 0000167c 00010200 2**2 + ALLOC + 2 .ARM.attributes 00000030 00000000 00000000 0000967c 2**0 + CONTENTS, READONLY + 3 .comment 0000002a 00000000 00000000 000096ac 2**0 + CONTENTS, READONLY + 4 .debug_abbrev 00000a61 00000000 00000000 000096d6 2**0 + CONTENTS, READONLY, DEBUGGING + 5 .debug_info 0000173b 00000000 00000000 0000a137 2**0 + CONTENTS, READONLY, DEBUGGING + 6 .debug_line 00000873 00000000 00000000 0000b872 2**0 + CONTENTS, READONLY, DEBUGGING + 7 .debug_pubtypes 00000312 00000000 00000000 0000c0e5 2**0 + CONTENTS, READONLY, DEBUGGING + 8 .debug_str 000008fa 00000000 00000000 0000c3f7 2**0 + CONTENTS, READONLY, DEBUGGING + 9 .debug_loc 00000be6 00000000 00000000 0000ccf1 2**0 + CONTENTS, READONLY, DEBUGGING + 10 .debug_pubnames 000003af 00000000 00000000 0000d8d7 2**0 + CONTENTS, READONLY, DEBUGGING + 11 .debug_aranges 000001a0 00000000 00000000 0000dc86 2**0 + CONTENTS, READONLY, DEBUGGING + 12 .debug_frame 0000063c 00000000 00000000 0000de28 2**2 + CONTENTS, READONLY, DEBUGGING +SYMBOL TABLE: +00000000 l d .text 00000000 .text +40000200 l d .bss 00000000 .bss +00000000 l d .ARM.attributes 00000000 .ARM.attributes +00000000 l d .comment 00000000 .comment +00000000 l d .debug_abbrev 00000000 .debug_abbrev +00000000 l d .debug_info 00000000 .debug_info +00000000 l d .debug_line 00000000 .debug_line +00000000 l d .debug_pubtypes 00000000 .debug_pubtypes +00000000 l d .debug_str 00000000 .debug_str +00000000 l d .debug_loc 00000000 .debug_loc +00000000 l d .debug_pubnames 00000000 .debug_pubnames +00000000 l d .debug_aranges 00000000 .debug_aranges +00000000 l d .debug_frame 00000000 .debug_frame +00000004 l *ABS* 00000000 UND_STACK_SIZE +00000004 l *ABS* 00000000 ABT_STACK_SIZE +00000004 l *ABS* 00000000 FIQ_STACK_SIZE +00000004 l *ABS* 00000000 IRQ_STACK_SIZE +00000004 l *ABS* 00000000 SVC_STACK_SIZE +00000010 l *ABS* 00000000 MODE_USR +00000011 l *ABS* 00000000 MODE_FIQ +00000012 l *ABS* 00000000 MODE_IRQ +00000013 l *ABS* 00000000 MODE_SVC +00000017 l *ABS* 00000000 MODE_ABT +0000001b l *ABS* 00000000 MODE_UND +0000001f l *ABS* 00000000 MODE_SYS +00000080 l *ABS* 00000000 I_BIT +00000040 l *ABS* 00000000 F_BIT +e01fc040 l *ABS* 00000000 MEMMAP +00000000 l .text 00000000 _vectors +00000020 l .text 00000000 Reset_Addr +00000024 l .text 00000000 Undef_Addr +00000028 l .text 00000000 SWI_Addr +0000002c l .text 00000000 PAbt_Addr +00000030 l .text 00000000 DAbt_Addr +00000038 l .text 00000000 IRQ_Addr +00000034 l .text 00000000 FIQ_Addr +000000a0 l .text 00000000 Reset_Handler_SWI +00000000 l df *ABS* 00000000 hooks.c +00000000 l df *ABS* 00000000 main.c +00001558 l O .text 00000004 C.0.2157 +00000000 l df *ABS* 00000000 boot.c +00000000 l df *ABS* 00000000 com.c +40000200 l O .bss 00000001 comEntryStateConnect +40000204 l O .bss 00000040 xcpCtoReqPacket.1371 +00000000 l df *ABS* 00000000 xcp.c +00000414 l F .text 00000014 XcpProtectResources +00000428 l F .text 00000020 XcpSetCtoError +0000155c l O .text 00000008 xcpStationId +40000244 l O .bss 0000004c xcpInfo +00000000 l df *ABS* 00000000 backdoor.c +40000290 l O .bss 00000001 backdoorOpen +00000000 l df *ABS* 00000000 cop.c +00000000 l df *ABS* 00000000 assert.c +40000294 l O .bss 00000004 assert_failure_file +40000298 l O .bss 00000004 assert_failure_line +00000000 l df *ABS* 00000000 cpu.c +00000000 l df *ABS* 00000000 can.c +00000000 l df *ABS* 00000000 uart.c +00000b54 l F .text 00000028 UartReceiveByte +00000b7c l F .text 00000060 UartTransmitByte +4000029c l O .bss 00000001 xcpCtoRxInProgress.1383 +400002a0 l O .bss 00000041 xcpCtoReqPacket.1381 +400002e1 l O .bss 00000001 xcpCtoRxLength.1382 +00000000 l df *ABS* 00000000 nvm.c +00000000 l df *ABS* 00000000 timer.c +400002e4 l O .bss 00000004 millisecond_counter +400002e8 l O .bss 00000004 free_running_counter_last +00000000 l df *ABS* 00000000 flash.c +00000ee4 l F .text 00000078 FlashGetSector +00000f5c l F .text 0000012c FlashWriteBlock +00001088 l F .text 00000044 FlashInitBlock +000010cc l F .text 00000068 FlashSwitchBlock +00001134 l F .text 000000e8 FlashAddToBlock +00001564 l O .text 000000c0 flashLayout +400002ec l O .bss 00000204 blockInfo +400004f0 l O .bss 00000204 bootBlockInfo +00000000 l df *ABS* 00000000 vectors.c +00000300 g F .text 00000068 ComInit +00001234 g F .text 0000006c FlashWrite +00000a7c g F .text 00000028 AssertFailure +0000150c g F .text 00000028 IRQ_ISR +00000e44 g F .text 0000002c TimerUpdate +00000488 g F .text 00000014 XcpPacketTransmitted +00000368 g F .text 0000003c ComTask +000003d4 g F .text 00000014 ComSetConnectEntryState +00000278 g F .text 0000004c BootInit +00000a44 g F .text 00000030 BackDoorInit +00000a78 g F .text 00000004 CopService +0000167c g .text 00000000 _etext +00000e24 g F .text 00000020 TimerReset +000002c4 g F .text 0000003c BootTask +000013d4 g F .text 0000006c FlashWriteChecksum +40000200 g .bss 00000000 _bss_start +000003a4 g F .text 00000030 ComTransmitPacket +00000000 g .text 00000000 _startup +00000470 g F .text 00000018 XcpIsConnected +00000d80 g F .text 0000001c NvmInit +0000121c g F .text 00000018 FlashInit +400006f4 g *ABS* 00000000 _bss_end +00000050 g .text 00000000 Reset_Handler +00000bdc g F .text 00000040 UartInit +00000db8 g F .text 0000001c NvmErase +0000049c g F .text 0000052c XcpPacketReceived +00001488 g F .text 0000005c FlashDone +00000040 g .text 00000000 EntryFromProg +000003e8 g F .text 00000010 ComIsConnectEntryState +00000448 g F .text 00000028 XcpInit +000012a0 g F .text 00000134 FlashErase +00000148 g F .text 00000130 main +00000df0 g F .text 00000034 NvmDone +00000c1c g F .text 000000a8 UartTransmitPacket +00000dd4 g F .text 0000001c NvmVerifyChecksum +00000aa4 g F .text 00000044 CpuMemCopy +40001edc g *ABS* 00000000 _stack_end +00000e70 g F .text 00000010 TimerSet +000014e4 g F .text 00000028 FIQ_ISR +00000cc4 g F .text 000000bc UartReceivePacket +40000200 g .text 00000000 _data +00000a74 g F .text 00000004 CopInit +00000b38 g F .text 0000001c CpuReset +000000f4 g .text 00000000 SetupRAM +00000d9c g F .text 0000001c NvmWrite +00000ae8 g F .text 00000050 CpuStartUserProgram +00001440 g F .text 00000048 FlashVerifyChecksum +40000200 g .text 00000000 _edata +400006f4 g *ABS* 00000000 _end +00001534 g F .text 00000024 UNDEF_ISR +000003f8 g F .text 0000001c ComIsConnected +000009c8 g F .text 0000007c BackDoorCheck +00000ec8 g F .text 0000001c TimerGet +00000e80 g F .text 00000048 TimerInit + + diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/build.bat b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/build.bat new file mode 100644 index 00000000..44c0c1b8 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/build.bat @@ -0,0 +1,2 @@ +@echo off +make --directory=../ all diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/clean.bat b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/clean.bat new file mode 100644 index 00000000..32c4b5f2 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/clean.bat @@ -0,0 +1,2 @@ +@echo off +make --directory=../ clean diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/debug.bat b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/debug.bat new file mode 100644 index 00000000..12fe88aa --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/debug.bat @@ -0,0 +1,5 @@ +@echo off +REM Establishes a JTAG connection with the CPU so that a GDB or Insight +REM debugging session can be started. Settings are for Remote/TCP +REM with hostname localhost on port 3333. +"C:\Program Files (x86)\OpenOCD\0.4.0\bin\openocd.exe" -f debug.cfg \ No newline at end of file diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/debug.cfg b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/debug.cfg new file mode 100644 index 00000000..bb1c2f58 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/debug.cfg @@ -0,0 +1,67 @@ +set CPUTAPID 0x4f1f0f0f + +source [find interface/olimex-arm-usb-tiny-h.cfg] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME lpc2294 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +if { [info exists CPUTAPID ] } { + set _CPUTAPID $CPUTAPID +} else { + # force an error till we get a good number + set _CPUTAPID 0xffffffff +} + +jtag_nsrst_delay 200 +jtag_ntrst_delay 200 + +#use combined on interfaces or targets that can't set TRST/SRST separately +reset_config trst_and_srst srst_pulls_trst + +#jtag scan chain +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME -variant arm7tdmi-s_r4 +$_TARGETNAME configure -work-area-phys 0x40000000 -work-area-size 0x4000 -work-area-backup 0 + +#flash configuration +#flash bank lpc2000 0 0 +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME lpc2000 0x0 0x40000 0 0 $_TARGETNAME lpc2000_v1 20000 calc_checksum + +jtag_khz 0 + +flash bank none cfi 0x80000000 0x200000 2 2 $_TARGETNAME + +init +arm7_9 dcc_downloads enable +arm7_9 fast_memory_access enable +reset +sleep 500 +halt +soft_reset_halt +gdb_breakpoint_override hard +#PLL according to Ecos +mww 0xE01FC080 0x1 +mww 0xE01FC084 0x22 +mww 0xE01FC08C 0xAA +mww 0xE01FC08C 0x55 +sleep 200 +mww 0xE01FC080 0x3 +mww 0xE01FC08C 0xAA +mww 0xE01FC08C 0x55 +mww 0xE01FC004 0x4 +mww 0xE01FC000 0x2 + +#MEMMAP +mww 0xE01FC040 0x0001 diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/flash.bat b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/flash.bat new file mode 100644 index 00000000..9fae8956 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/flash.bat @@ -0,0 +1,3 @@ +@echo off +REM Loads the program into flash eeprom through the JTAG interface +"C:\Program Files (x86)\OpenOCD\0.4.0\bin\openocd.exe" -f flash.cfg \ No newline at end of file diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/flash.cfg b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/flash.cfg new file mode 100644 index 00000000..157b9de3 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/cmd/flash.cfg @@ -0,0 +1,79 @@ +set CPUTAPID 0x4f1f0f0f + +source [find interface/olimex-arm-usb-tiny-h.cfg] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME lpc2294 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +if { [info exists CPUTAPID ] } { + set _CPUTAPID $CPUTAPID +} else { + # force an error till we get a good number + set _CPUTAPID 0xffffffff +} + +jtag_nsrst_delay 200 +jtag_ntrst_delay 200 + +#use combined on interfaces or targets that can't set TRST/SRST separately +reset_config trst_and_srst srst_pulls_trst + +#jtag scan chain +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME -variant arm7tdmi-s_r4 +$_TARGETNAME configure -work-area-phys 0x40000000 -work-area-size 0x4000 -work-area-backup 0 + +#flash configuration +#flash bank lpc2000 0 0 +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME lpc2000 0x0 0x40000 0 0 $_TARGETNAME lpc2000_v1 20000 calc_checksum + +jtag_khz 0 + +flash bank none cfi 0x80000000 0x200000 2 2 $_TARGETNAME + + + +init +arm7_9 dcc_downloads enable +arm7_9 fast_memory_access enable +reset +sleep 500 +halt +soft_reset_halt +#PLL according to Ecos +mww 0xE01FC080 0x1 +mww 0xE01FC084 0x22 +mww 0xE01FC08C 0xAA +mww 0xE01FC08C 0x55 +sleep 200 +mww 0xE01FC080 0x3 +mww 0xE01FC08C 0xAA +mww 0xE01FC08C 0x55 +sleep 200 +mww 0xE01FC004 0x4 +mww 0xE01FC000 0x2 +sleep 200 + +#MEMMAP +mww 0xE01FC040 0x0001 + +reset run +sleep 500 +halt +flash probe 0 +sleep 1000 +flash write_image erase unlock ../bin/openbtl_olimex_lpc_l2294_20mhz.elf +reset run +shutdown diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/config.h b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/config.h new file mode 100644 index 00000000..57d6bc31 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/config.h @@ -0,0 +1,128 @@ +/**************************************************************************************** +| Description: bootloader configuration header file +| File Name: config.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef CONFIG_H +#define CONFIG_H + +/**************************************************************************************** +* C P U D R I V E R C O N F I G U R A T I O N +****************************************************************************************/ +/* To properly initialize the baudrate clocks of the communication interface, typically + * the speed of the crystal oscillator and/or the speed at which the system runs is + * needed. Set these through configurables BOOT_CPU_XTAL_SPEED_KHZ and + * BOOT_CPU_SYSTEM_SPEED_KHZ, respectively. To enable data exchange with the host that is + * not dependent on the targets architecture, the byte ordering needs to be known. + * Setting BOOT_CPU_BYTE_ORDER_MOTOROLA to 1 selects little endian mode and 0 selects + * big endian mode. + */ +#define BOOT_CPU_XTAL_SPEED_KHZ (20000) +#define BOOT_CPU_SYSTEM_SPEED_KHZ (60000) +#define BOOT_CPU_BYTE_ORDER_MOTOROLA (0) + + +/**************************************************************************************** +* C O M M U N I C A T I O N I N T E R F A C E C O N F I G U R A T I O N +****************************************************************************************/ +/* The CAN communication interface is selected by setting the BOOT_COM_CAN_ENABLE + * configurable to 1. Configurable BOOT_COM_CAN_BAUDRATE selects the communication speed + * in bits/second. Two CAN messages are reserved for communication with the host. The + * message identifier for sending data from the target to the host is configured with + * BOOT_COM_CAN_TXMSG_ID. The one for receiving data from the host is configured with + * BOOT_COM_CAN_RXMSG_ID. The maximum amount of data bytes in a message for data + * transmission and reception is set through BOOT_COM_CAN_TX_MAX_DATA and + * BOOT_COM_CAN_RX_MAX_DATA, respectively. It is common for a microcontroller to have more + * than 1 CAN controller on board. The zero-based BOOT_COM_CAN_CHANNEL_INDEX selects the + * CAN controller channel. + * + */ +#define BOOT_COM_CAN_ENABLE (0) +#define BOOT_COM_CAN_BAUDRATE (500000) +#define BOOT_COM_CAN_TX_MSG_ID (0x7E1) +#define BOOT_COM_CAN_TX_MAX_DATA (8) +#define BOOT_COM_CAN_RX_MSG_ID (0x667) +#define BOOT_COM_CAN_RX_MAX_DATA (8) +#define BOOT_COM_CAN_CHANNEL_INDEX (0) + +/* The UART communication interface is selected by setting the BOOT_COM_UART_ENABLE + * configurable to 1. Configurable BOOT_COM_UART_BAUDRATE selects the communication speed + * in bits/second. The maximum amount of data bytes in a message for data transmission + * and reception is set through BOOT_COM_UART_TX_MAX_DATA and BOOT_COM_UART_RX_MAX_DATA, + * respectively. It is common for a microcontroller to have more than 1 UART interface + * on board. The zero-based BOOT_COM_UART_CHANNEL_INDEX selects the UART interface. + * + */ +#define BOOT_COM_UART_ENABLE (1) +#define BOOT_COM_UART_BAUDRATE (57600) +#define BOOT_COM_UART_TX_MAX_DATA (64) +#define BOOT_COM_UART_RX_MAX_DATA (64) +#define BOOT_COM_UART_CHANNEL_INDEX (0) + + +/**************************************************************************************** +* B A C K D O O R E N T R Y C O N F I G U R A T I O N +****************************************************************************************/ +/* It is possible to implement an application specific method to force the bootloader to + * stay active after a reset. Such a backdoor entry into the bootloader is desired in + * situations where the user program does not run properly and therefore cannot + * reactivate the bootloader. By enabling these hook functions, the application can + * implement the backdoor, which overrides the default backdoor entry that is programmed + * into the bootloader. When desired for security purposes, these hook functions can + * also be implemented in a way that disables the backdoor entry altogether. + */ +#define BOOT_BACKDOOR_HOOKS_ENABLE (0) + + +/**************************************************************************************** +* N O N - V O L A T I L E M E M O R Y D R I V E R C O N F I G U R A T I O N +****************************************************************************************/ +/* The NVM driver typically supports erase and program operations of the internal memory + * present on the microcontroller. Through these hook functions the NVM driver can be + * extended to support additional memory types such as external flash memory and serial + * eeproms. The size of the internal memory in kilobytes is specified with configurable + * BOOT_NVM_SIZE_KB. + */ +#define BOOT_NVM_HOOKS_ENABLE (0) +#define BOOT_NVM_SIZE_KB (256) + + +/**************************************************************************************** +* W A T C H D O G D R I V E R C O N F I G U R A T I O N +****************************************************************************************/ +/* The COP driver cannot be configured internally in the bootloader, because its use + * and configuration is application specific. The bootloader does need to service the + * watchdog in case it is used. When the application requires the use of a watchdog, + * set BOOT_COP_HOOKS_ENABLE to be able to initialize and service the watchdog through + * hook functions. + */ +#define BOOT_COP_HOOKS_ENABLE (0) + + +#endif /* CONFIG_H */ +/*********************************** end of config.h ***********************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/hooks.c b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/hooks.c new file mode 100644 index 00000000..e46906ec --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/hooks.c @@ -0,0 +1,187 @@ +/**************************************************************************************** +| Description: bootloader callback source file +| File Name: hooks.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ +#include "lpc2294.h" /* CPU register definitions */ + + +/**************************************************************************************** +* B A C K D O O R E N T R Y H O O K F U N C T I O N S +****************************************************************************************/ + +#if (BOOT_BACKDOOR_HOOKS_ENABLE > 0) +/**************************************************************************************** +** NAME: BackDoorInitHook +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the backdoor entry option. +** +****************************************************************************************/ +void BackDoorInitHook(void) +{ + /* configure the button connected to P0.16 as a digital input */ + IO0DIR &= ~(1<<16); +} /*** end of BackDoorInitHook ***/ + + +/**************************************************************************************** +** NAME: BackDoorEntryHook +** PARAMETER: none +** RETURN VALUE: BLT_TRUE if the backdoor entry is requested, BLT_FALSE otherwise. +** DESCRIPTION: Checks if a backdoor entry is requested. +** +****************************************************************************************/ +blt_bool BackDoorEntryHook(void) +{ + /* button P0.16 has a pullup, so will read high by default. enter backdoor only when + * this button is pressed. this is the case when it reads low */ + if ((IO0PIN & (1<<16)) == 0) + { + return BLT_TRUE; + } + return BLT_FALSE; +} /*** end of BackDoorEntryHook ***/ +#endif /* BOOT_BACKDOOR_HOOKS_ENABLE > 0 */ + + +/**************************************************************************************** +* N O N - V O L A T I L E M E M O R Y D R I V E R H O O K F U N C T I O N S +****************************************************************************************/ + +#if (BOOT_NVM_HOOKS_ENABLE > 0) +/**************************************************************************************** +** NAME: NvmInitHook +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Callback that gets called at the start of the internal NVM driver +** initialization routine. +** +****************************************************************************************/ +void NvmInitHook(void) +{ +} /*** end of NvmInitHook ***/ + + +/**************************************************************************************** +** NAME: NvmWriteHook +** PARAMETER: addr start address +** len length in bytes +** data pointer to the data buffer. +** RETURN VALUE: BTL_NVM_OKAY if successful, BTL_NVM_NOT_IN_RANGE if the address is +** not within the supported memory range, or BTL_NVM_ERROR is the write +** operation failed. +** DESCRIPTION: Callback that gets called at the start of the NVM driver write +** routine. It allows additional memory to be operated on. If the address +** is not within the range of the additional memory, then +** BTL_NVM_NOT_IN_RANGE must be returned to indicate that the data hasn't +** been written yet. +** +** +****************************************************************************************/ +blt_int8u NvmWriteHook(blt_addr addr, blt_int32u len, blt_int8u *data) +{ + return BTL_NVM_NOT_IN_RANGE; +} /*** end of NvmWriteHook ***/ + + +/**************************************************************************************** +** NAME: NvmEraseHook +** PARAMETER: addr start address +** len length in bytes +** RETURN VALUE: BTL_NVM_OKAY if successful, BTL_NVM_NOT_IN_RANGE if the address is +** not within the supported memory range, or BTL_NVM_ERROR is the erase +** operation failed. +** DESCRIPTION: Callback that gets called at the start of the NVM driver erase +** routine. It allows additional memory to be operated on. If the address +** is not within the range of the additional memory, then +** BTL_NVM_NOT_IN_RANGE must be returned to indicate that the memory +** hasn't been erased yet. +** +****************************************************************************************/ +blt_bool NvmEraseHook(blt_addr addr, blt_int32u len) +{ + return BTL_NVM_NOT_IN_RANGE; +} /*** end of NvmEraseHook ***/ + + +/**************************************************************************************** +** NAME: NvmDoneHook +** PARAMETER: none +** RETURN VALUE: BLT_TRUE is successful, BLT_FALSE otherwise. +** DESCRIPTION: Callback that gets called at the end of the NVM programming session. +** +****************************************************************************************/ +blt_bool NvmDoneHook(void) +{ + return BLT_TRUE; +} /*** end of NvmDoneHook ***/ +#endif /* BOOT_NVM_HOOKS_ENABLE > 0 */ + + +/**************************************************************************************** +* W A T C H D O G D R I V E R H O O K F U N C T I O N S +****************************************************************************************/ + +#if (BOOT_COP_HOOKS_ENABLE > 0) +/**************************************************************************************** +** NAME: CopInitHook +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Callback that gets called at the end of the internal COP driver +** initialization routine. It can be used to configure and enable the +** watchdog. +** +****************************************************************************************/ +void CopInitHook(void) +{ +} /*** end of CopInitHook ***/ + + +/**************************************************************************************** +** NAME: CopServiceHook +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Callback that gets called at the end of the internal COP driver +** service routine. This gets called upon initialization and during +** potential long lasting loops and routine. It can be used to service +** the watchdog to prevent a watchdog reset. +** +****************************************************************************************/ +void CopServiceHook(void) +{ +} /*** end of CopServiceHook ***/ +#endif /* BOOT_COP_HOOKS_ENABLE > 0 */ + + +/*********************************** end of hooks.c ************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/DemoBoot.project b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/DemoBoot.project new file mode 100644 index 00000000..d496df15 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/DemoBoot.project @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + break main +continue + + + + + + + make clean + make + + + + None + $(WorkspacePath)/.. + + + + + + + + + + + + + + + + + + + + + + + make clean + make + + + + None + $(WorkspacePath) + + + + + + + + diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/DemoBoot.workspace b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/DemoBoot.workspace new file mode 100644 index 00000000..7957a1d7 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/DemoBoot.workspace @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/readme.txt b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/readme.txt new file mode 100644 index 00000000..8a340a19 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/ide/readme.txt @@ -0,0 +1,4 @@ +Integrated Development Environment +---------------------------------- +Codelite was used as the editor during the development of this software program. This directory contains the Codelite +workspace and project files. Codelite is a cross platform open source C/C++ IDE, available at http://www.codelite.org/. \ No newline at end of file diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/lpc2294.h b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/lpc2294.h new file mode 100644 index 00000000..209015fb --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/lpc2294.h @@ -0,0 +1,409 @@ +/**************************************************************************************** +| Description: NXP LPC2294 register definitions +| File Name: lpc2294.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef LPC2294_H +#define LPC2294_H + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/* EXTERNAL MEMORY CONTROLLER (EMC) */ +#define BCFG0 (*((volatile unsigned long *) 0xFFE00000)) /* lpc22xx only */ +#define BCFG1 (*((volatile unsigned long *) 0xFFE00004)) /* lpc22xx only */ +#define BCFG2 (*((volatile unsigned long *) 0xFFE00008)) /* lpc22xx only */ +#define BCFG3 (*((volatile unsigned long *) 0xFFE0000C)) /* lpc22xx only */ + +/* External Interrupts */ +#define EXTINT (*((volatile unsigned char *) 0xE01FC140)) +#define EXTWAKE (*((volatile unsigned char *) 0xE01FC144)) +#define EXTMODE (*((volatile unsigned char *) 0xE01FC148)) /* no in lpc210x*/ +#define EXTPOLAR (*((volatile unsigned char *) 0xE01FC14C)) /* no in lpc210x*/ + +/* SMemory mapping control. */ +#define MEMMAP (*((volatile unsigned long *) 0xE01FC040)) + +/* Phase Locked Loop (PLL) */ +#define PLLCON (*((volatile unsigned char *) 0xE01FC080)) +#define PLLCFG (*((volatile unsigned char *) 0xE01FC084)) +#define PLLSTAT (*((volatile unsigned short*) 0xE01FC088)) +#define PLLFEED (*((volatile unsigned char *) 0xE01FC08C)) + +/* Power Control */ +#define PCON (*((volatile unsigned char *) 0xE01FC0C0)) +#define PCONP (*((volatile unsigned long *) 0xE01FC0C4)) + +/* VPB Divider */ +#define VPBDIV (*((volatile unsigned char *) 0xE01FC100)) + +/* Memory Accelerator Module (MAM) */ +#define MAMCR (*((volatile unsigned char *) 0xE01FC000)) +#define MAMTIM (*((volatile unsigned char *) 0xE01FC004)) + +/* Vectored Interrupt Controller (VIC) */ +#define VICIRQStatus (*((volatile unsigned long *) 0xFFFFF000)) +#define VICFIQStatus (*((volatile unsigned long *) 0xFFFFF004)) +#define VICRawIntr (*((volatile unsigned long *) 0xFFFFF008)) +#define VICIntSelect (*((volatile unsigned long *) 0xFFFFF00C)) +#define VICIntEnable (*((volatile unsigned long *) 0xFFFFF010)) +#define VICIntEnClr (*((volatile unsigned long *) 0xFFFFF014)) +#define VICSoftInt (*((volatile unsigned long *) 0xFFFFF018)) +#define VICSoftIntClear (*((volatile unsigned long *) 0xFFFFF01C)) +#define VICProtection (*((volatile unsigned long *) 0xFFFFF020)) +#define VICVectAddr (*((volatile unsigned long *) 0xFFFFF030)) +#define VICDefVectAddr (*((volatile unsigned long *) 0xFFFFF034)) +#define VICVectAddr0 (*((volatile unsigned long *) 0xFFFFF100)) +#define VICVectAddr1 (*((volatile unsigned long *) 0xFFFFF104)) +#define VICVectAddr2 (*((volatile unsigned long *) 0xFFFFF108)) +#define VICVectAddr3 (*((volatile unsigned long *) 0xFFFFF10C)) +#define VICVectAddr4 (*((volatile unsigned long *) 0xFFFFF110)) +#define VICVectAddr5 (*((volatile unsigned long *) 0xFFFFF114)) +#define VICVectAddr6 (*((volatile unsigned long *) 0xFFFFF118)) +#define VICVectAddr7 (*((volatile unsigned long *) 0xFFFFF11C)) +#define VICVectAddr8 (*((volatile unsigned long *) 0xFFFFF120)) +#define VICVectAddr9 (*((volatile unsigned long *) 0xFFFFF124)) +#define VICVectAddr10 (*((volatile unsigned long *) 0xFFFFF128)) +#define VICVectAddr11 (*((volatile unsigned long *) 0xFFFFF12C)) +#define VICVectAddr12 (*((volatile unsigned long *) 0xFFFFF130)) +#define VICVectAddr13 (*((volatile unsigned long *) 0xFFFFF134)) +#define VICVectAddr14 (*((volatile unsigned long *) 0xFFFFF138)) +#define VICVectAddr15 (*((volatile unsigned long *) 0xFFFFF13C)) +#define VICVectCntl0 (*((volatile unsigned long *) 0xFFFFF200)) +#define VICVectCntl1 (*((volatile unsigned long *) 0xFFFFF204)) +#define VICVectCntl2 (*((volatile unsigned long *) 0xFFFFF208)) +#define VICVectCntl3 (*((volatile unsigned long *) 0xFFFFF20C)) +#define VICVectCntl4 (*((volatile unsigned long *) 0xFFFFF210)) +#define VICVectCntl5 (*((volatile unsigned long *) 0xFFFFF214)) +#define VICVectCntl6 (*((volatile unsigned long *) 0xFFFFF218)) +#define VICVectCntl7 (*((volatile unsigned long *) 0xFFFFF21C)) +#define VICVectCntl8 (*((volatile unsigned long *) 0xFFFFF220)) +#define VICVectCntl9 (*((volatile unsigned long *) 0xFFFFF224)) +#define VICVectCntl10 (*((volatile unsigned long *) 0xFFFFF228)) +#define VICVectCntl11 (*((volatile unsigned long *) 0xFFFFF22C)) +#define VICVectCntl12 (*((volatile unsigned long *) 0xFFFFF230)) +#define VICVectCntl13 (*((volatile unsigned long *) 0xFFFFF234)) +#define VICVectCntl14 (*((volatile unsigned long *) 0xFFFFF238)) +#define VICVectCntl15 (*((volatile unsigned long *) 0xFFFFF23C)) + +/* Pin Connect Block */ +#define PINSEL0 (*((volatile unsigned long *) 0xE002C000)) +#define PINSEL1 (*((volatile unsigned long *) 0xE002C004)) +#define PINSEL2 (*((volatile unsigned long *) 0xE002C014)) /* no in lpc210x*/ + +/* General Purpose Input/Output (GPIO) */ +#define IOPIN (*((volatile unsigned long *) 0xE0028000)) /* lpc210x only */ +#define IOSET (*((volatile unsigned long *) 0xE0028004)) /* lpc210x only */ +#define IODIR (*((volatile unsigned long *) 0xE0028008)) /* lpc210x only */ +#define IOCLR (*((volatile unsigned long *) 0xE002800C)) /* lpc210x only */ + +#define IO0PIN (*((volatile unsigned long *) 0xE0028000)) /* no in lpc210x*/ +#define IO0SET (*((volatile unsigned long *) 0xE0028004)) /* no in lpc210x*/ +#define IO0DIR (*((volatile unsigned long *) 0xE0028008)) /* no in lpc210x*/ +#define IO0CLR (*((volatile unsigned long *) 0xE002800C)) /* no in lpc210x*/ + +#define IO1PIN (*((volatile unsigned long *) 0xE0028010)) /* no in lpc210x*/ +#define IO1SET (*((volatile unsigned long *) 0xE0028014)) /* no in lpc210x*/ +#define IO1DIR (*((volatile unsigned long *) 0xE0028018)) /* no in lpc210x*/ +#define IO1CLR (*((volatile unsigned long *) 0xE002801C)) /* no in lpc210x*/ + +#define IO2PIN (*((volatile unsigned long *) 0xE0028020)) /* lpc22xx only */ +#define IO2SET (*((volatile unsigned long *) 0xE0028024)) /* lpc22xx only */ +#define IO2DIR (*((volatile unsigned long *) 0xE0028028)) /* lpc22xx only */ +#define IO2CLR (*((volatile unsigned long *) 0xE002802C)) /* lpc22xx only */ + +#define IO3PIN (*((volatile unsigned long *) 0xE0028030)) /* lpc22xx only */ +#define IO3SET (*((volatile unsigned long *) 0xE0028034)) /* lpc22xx only */ +#define IO3DIR (*((volatile unsigned long *) 0xE0028038)) /* lpc22xx only */ +#define IO3CLR (*((volatile unsigned long *) 0xE002803C)) /* lpc22xx only */ + +/* Universal Asynchronous Receiver Transmitter 0 (UART0) */ +#define U0RBR (*((volatile unsigned char *) 0xE000C000)) +#define U0THR (*((volatile unsigned char *) 0xE000C000)) +#define U0IER (*((volatile unsigned char *) 0xE000C004)) +#define U0IIR (*((volatile unsigned char *) 0xE000C008)) +#define U0FCR (*((volatile unsigned char *) 0xE000C008)) +#define U0LCR (*((volatile unsigned char *) 0xE000C00C)) +#define U0LSR (*((volatile unsigned char *) 0xE000C014)) +#define U0SCR (*((volatile unsigned char *) 0xE000C01C)) +#define U0DLL (*((volatile unsigned char *) 0xE000C000)) +#define U0DLM (*((volatile unsigned char *) 0xE000C004)) + +/* Universal Asynchronous Receiver Transmitter 1 (UART1) */ +#define U1RBR (*((volatile unsigned char *) 0xE0010000)) +#define U1THR (*((volatile unsigned char *) 0xE0010000)) +#define U1IER (*((volatile unsigned char *) 0xE0010004)) +#define U1IIR (*((volatile unsigned char *) 0xE0010008)) +#define U1FCR (*((volatile unsigned char *) 0xE0010008)) +#define U1LCR (*((volatile unsigned char *) 0xE001000C)) +#define U1MCR (*((volatile unsigned char *) 0xE0010010)) +#define U1LSR (*((volatile unsigned char *) 0xE0010014)) +#define U1MSR (*((volatile unsigned char *) 0xE0010018)) +#define U1SCR (*((volatile unsigned char *) 0xE001001C)) +#define U1DLL (*((volatile unsigned char *) 0xE0010000)) +#define U1DLM (*((volatile unsigned char *) 0xE0010004)) + +/* I2C (8/16 bit data bus) */ +#define I2CONSET (*((volatile unsigned long *) 0xE001C000)) +#define I2STAT (*((volatile unsigned long *) 0xE001C004)) +#define I2DAT (*((volatile unsigned long *) 0xE001C008)) +#define I2ADR (*((volatile unsigned long *) 0xE001C00C)) +#define I2SCLH (*((volatile unsigned long *) 0xE001C010)) +#define I2SCLL (*((volatile unsigned long *) 0xE001C014)) +#define I2CONCLR (*((volatile unsigned long *) 0xE001C018)) + +/* SPI (Serial Peripheral Interface) */ + /* only for lpc210x*/ +#define SPI_SPCR (*((volatile unsigned char *) 0xE0020000)) +#define SPI_SPSR (*((volatile unsigned char *) 0xE0020004)) +#define SPI_SPDR (*((volatile unsigned char *) 0xE0020008)) +#define SPI_SPCCR (*((volatile unsigned char *) 0xE002000C)) +#define SPI_SPINT (*((volatile unsigned char *) 0xE002001C)) + +#define S0PCR (*((volatile unsigned char *) 0xE0020000)) /* no in lpc210x*/ +#define S0PSR (*((volatile unsigned char *) 0xE0020004)) /* no in lpc210x*/ +#define S0PDR (*((volatile unsigned char *) 0xE0020008)) /* no in lpc210x*/ +#define S0PCCR (*((volatile unsigned char *) 0xE002000C)) /* no in lpc210x*/ +#define S0PINT (*((volatile unsigned char *) 0xE002001C)) /* no in lpc210x*/ + +#define S1PCR (*((volatile unsigned char *) 0xE0030000)) /* no in lpc210x*/ +#define S1PSR (*((volatile unsigned char *) 0xE0030004)) /* no in lpc210x*/ +#define S1PDR (*((volatile unsigned char *) 0xE0030008)) /* no in lpc210x*/ +#define S1PCCR (*((volatile unsigned char *) 0xE003000C)) /* no in lpc210x*/ +#define S1PINT (*((volatile unsigned char *) 0xE003001C)) /* no in lpc210x*/ + +/* CAN CONTROLLERS AND ACCEPTANCE FILTER */ +#define CAN1MOD (*((volatile unsigned long *) 0xE0044000)) /* All CAN Parts */ +#define CAN1CMR (*((volatile unsigned long *) 0xE0044004)) /* All CAN Parts */ +#define CAN1GSR (*((volatile unsigned long *) 0xE0044008)) /* All CAN Parts */ +#define CAN1ICR (*((volatile unsigned long *) 0xE004400C)) /* All CAN Parts */ +#define CAN1IER (*((volatile unsigned long *) 0xE0044010)) /* All CAN Parts */ +#define CAN1BTR (*((volatile unsigned long *) 0xE0044014)) /* All CAN Parts */ +#define CAN1EWL (*((volatile unsigned long *) 0xE0044018)) /* All CAN Parts */ +#define CAN1SR (*((volatile unsigned long *) 0xE004401C)) /* All CAN Parts */ +#define CAN1RFS (*((volatile unsigned long *) 0xE0044020)) /* All CAN Parts */ +#define CAN1RID (*((volatile unsigned long *) 0xE0044024)) /* All CAN Parts */ +#define CAN1RDA (*((volatile unsigned long *) 0xE0044028)) /* All CAN Parts */ +#define CAN1RDB (*((volatile unsigned long *) 0xE004402C)) /* All CAN Parts */ +#define CAN1TFI1 (*((volatile unsigned long *) 0xE0044030)) /* All CAN Parts */ +#define CAN1TID1 (*((volatile unsigned long *) 0xE0044034)) /* All CAN Parts */ +#define CAN1TDA1 (*((volatile unsigned long *) 0xE0044038)) /* All CAN Parts */ +#define CAN1TDB1 (*((volatile unsigned long *) 0xE004403C)) /* All CAN Parts */ +#define CAN1TFI2 (*((volatile unsigned long *) 0xE0044040)) /* All CAN Parts */ +#define CAN1TID2 (*((volatile unsigned long *) 0xE0044044)) /* All CAN Parts */ +#define CAN1TDA2 (*((volatile unsigned long *) 0xE0044048)) /* All CAN Parts */ +#define CAN1TDB2 (*((volatile unsigned long *) 0xE004404C)) /* All CAN Parts */ +#define CAN1TFI3 (*((volatile unsigned long *) 0xE0044050)) /* All CAN Parts */ +#define CAN1TID3 (*((volatile unsigned long *) 0xE0044054)) /* All CAN Parts */ +#define CAN1TDA3 (*((volatile unsigned long *) 0xE0044058)) /* All CAN Parts */ +#define CAN1TDB3 (*((volatile unsigned long *) 0xE004405C)) /* All CAN Parts */ + +#define CAN2MOD (*((volatile unsigned long *) 0xE0048000)) /* All CAN Parts */ +#define CAN2CMR (*((volatile unsigned long *) 0xE0048004)) /* All CAN Parts */ +#define CAN2GSR (*((volatile unsigned long *) 0xE0048008)) /* All CAN Parts */ +#define CAN2ICR (*((volatile unsigned long *) 0xE004800C)) /* All CAN Parts */ +#define CAN2IER (*((volatile unsigned long *) 0xE0048010)) /* All CAN Parts */ +#define CAN2BTR (*((volatile unsigned long *) 0xE0048014)) /* All CAN Parts */ +#define CAN2EWL (*((volatile unsigned long *) 0xE0048018)) /* All CAN Parts */ +#define CAN2SR (*((volatile unsigned long *) 0xE004801C)) /* All CAN Parts */ +#define CAN2RFS (*((volatile unsigned long *) 0xE0048020)) /* All CAN Parts */ +#define CAN2RID (*((volatile unsigned long *) 0xE0048024)) /* All CAN Parts */ +#define CAN2RDA (*((volatile unsigned long *) 0xE0048028)) /* All CAN Parts */ +#define CAN2RDB (*((volatile unsigned long *) 0xE004802C)) /* All CAN Parts */ +#define CAN2TFI1 (*((volatile unsigned long *) 0xE0048030)) /* All CAN Parts */ +#define CAN2TID1 (*((volatile unsigned long *) 0xE0048034)) /* All CAN Parts */ +#define CAN2TDA1 (*((volatile unsigned long *) 0xE0048038)) /* All CAN Parts */ +#define CAN2TDB1 (*((volatile unsigned long *) 0xE004803C)) /* All CAN Parts */ +#define CAN2TFI2 (*((volatile unsigned long *) 0xE0048040)) /* All CAN Parts */ +#define CAN2TID2 (*((volatile unsigned long *) 0xE0048044)) /* All CAN Parts */ +#define CAN2TDA2 (*((volatile unsigned long *) 0xE0048048)) /* All CAN Parts */ +#define CAN2TDB2 (*((volatile unsigned long *) 0xE004804C)) /* All CAN Parts */ +#define CAN2TFI3 (*((volatile unsigned long *) 0xE0048050)) /* All CAN Parts */ +#define CAN2TID3 (*((volatile unsigned long *) 0xE0048054)) /* All CAN Parts */ +#define CAN2TDA3 (*((volatile unsigned long *) 0xE0048058)) /* All CAN Parts */ +#define CAN2TDB3 (*((volatile unsigned long *) 0xE004805C)) /* All CAN Parts */ + +#define CAN3MOD (*((volatile unsigned long *) 0xE004C000)) /* lpc2194\lpc2294 only */ +#define CAN3CMR (*((volatile unsigned long *) 0xE004C004)) /* lpc2194\lpc2294 only */ +#define CAN3GSR (*((volatile unsigned long *) 0xE004C008)) /* lpc2194\lpc2294 only */ +#define CAN3ICR (*((volatile unsigned long *) 0xE004C00C)) /* lpc2194\lpc2294 only */ +#define CAN3IER (*((volatile unsigned long *) 0xE004C010)) /* lpc2194\lpc2294 only */ +#define CAN3BTR (*((volatile unsigned long *) 0xE004C014)) /* lpc2194\lpc2294 only */ +#define CAN3EWL (*((volatile unsigned long *) 0xE004C018)) /* lpc2194\lpc2294 only */ +#define CAN3SR (*((volatile unsigned long *) 0xE004C01C)) /* lpc2194\lpc2294 only */ +#define CAN3RFS (*((volatile unsigned long *) 0xE004C020)) /* lpc2194\lpc2294 only */ +#define CAN3RID (*((volatile unsigned long *) 0xE004C024)) /* lpc2194\lpc2294 only */ +#define CAN3RDA (*((volatile unsigned long *) 0xE004C028)) /* lpc2194\lpc2294 only */ +#define CAN3RDB (*((volatile unsigned long *) 0xE004C02C)) /* lpc2194\lpc2294 only */ +#define CAN3TFI1 (*((volatile unsigned long *) 0xE004C030)) /* lpc2194\lpc2294 only */ +#define CAN3TID1 (*((volatile unsigned long *) 0xE004C034)) /* lpc2194\lpc2294 only */ +#define CAN3TDA1 (*((volatile unsigned long *) 0xE004C038)) /* lpc2194\lpc2294 only */ +#define CAN3TDB1 (*((volatile unsigned long *) 0xE004C03C)) /* lpc2194\lpc2294 only */ +#define CAN3TFI2 (*((volatile unsigned long *) 0xE004C040)) /* lpc2194\lpc2294 only */ +#define CAN3TID2 (*((volatile unsigned long *) 0xE004C044)) /* lpc2194\lpc2294 only */ +#define CAN3TDA2 (*((volatile unsigned long *) 0xE004C048)) /* lpc2194\lpc2294 only */ +#define CAN3TDB2 (*((volatile unsigned long *) 0xE004C04C)) /* lpc2194\lpc2294 only */ +#define CAN3TFI3 (*((volatile unsigned long *) 0xE004C050)) /* lpc2194\lpc2294 only */ +#define CAN3TID3 (*((volatile unsigned long *) 0xE004C054)) /* lpc2194\lpc2294 only */ +#define CAN3TDA3 (*((volatile unsigned long *) 0xE004C058)) /* lpc2194\lpc2294 only */ +#define CAN3TDB3 (*((volatile unsigned long *) 0xE004C05C)) /* lpc2194\lpc2294 only */ + +#define CAN4MOD (*((volatile unsigned long *) 0xE0050000)) /* lpc2194\lpc2294 only */ +#define CAN4CMR (*((volatile unsigned long *) 0xE0050004)) /* lpc2194\lpc2294 only */ +#define CAN4GSR (*((volatile unsigned long *) 0xE0050008)) /* lpc2194\lpc2294 only */ +#define CAN4ICR (*((volatile unsigned long *) 0xE005000C)) /* lpc2194\lpc2294 only */ +#define CAN4IER (*((volatile unsigned long *) 0xE0050010)) /* lpc2194\lpc2294 only */ +#define CAN4BTR (*((volatile unsigned long *) 0xE0050014)) /* lpc2194\lpc2294 only */ +#define CAN4EWL (*((volatile unsigned long *) 0xE0050018)) /* lpc2194\lpc2294 only */ +#define CAN4SR (*((volatile unsigned long *) 0xE005001C)) /* lpc2194\lpc2294 only */ +#define CAN4RFS (*((volatile unsigned long *) 0xE0050020)) /* lpc2194\lpc2294 only */ +#define CAN4RID (*((volatile unsigned long *) 0xE0050024)) /* lpc2194\lpc2294 only */ +#define CAN4RDA (*((volatile unsigned long *) 0xE0050028)) /* lpc2194\lpc2294 only */ +#define CAN4RDB (*((volatile unsigned long *) 0xE005002C)) /* lpc2194\lpc2294 only */ +#define CAN4TFI1 (*((volatile unsigned long *) 0xE0050030)) /* lpc2194\lpc2294 only */ +#define CAN4TID1 (*((volatile unsigned long *) 0xE0050034)) /* lpc2194\lpc2294 only */ +#define CAN4TDA1 (*((volatile unsigned long *) 0xE0050038)) /* lpc2194\lpc2294 only */ +#define CAN4TDB1 (*((volatile unsigned long *) 0xE005003C)) /* lpc2194\lpc2294 only */ +#define CAN4TFI2 (*((volatile unsigned long *) 0xE0050040)) /* lpc2194\lpc2294 only */ +#define CAN4TID2 (*((volatile unsigned long *) 0xE0050044)) /* lpc2194\lpc2294 only */ +#define CAN4TDA2 (*((volatile unsigned long *) 0xE0050048)) /* lpc2194\lpc2294 only */ +#define CAN4TDB2 (*((volatile unsigned long *) 0xE005004C)) /* lpc2194\lpc2294 only */ +#define CAN4TFI3 (*((volatile unsigned long *) 0xE0050050)) /* lpc2194\lpc2294 only */ +#define CAN4TID3 (*((volatile unsigned long *) 0xE0050054)) /* lpc2194\lpc2294 only */ +#define CAN4TDA3 (*((volatile unsigned long *) 0xE0050058)) /* lpc2194\lpc2294 only */ +#define CAN4TDB3 (*((volatile unsigned long *) 0xE005005C)) /* lpc2194\lpc2294 only */ + + +#define CANTxSR (*((volatile unsigned long *) 0xE0040000)) /* ALL CAN Parts */ +#define CANRxSR (*((volatile unsigned long *) 0xE0040004)) /* ALL CAN Parts */ +#define CANMSR (*((volatile unsigned long *) 0xE0040008)) /* ALL CAN Parts */ + +#define CANAFMR (*((volatile unsigned char *) 0xE003C000)) /* ALL CAN Parts */ +#define CANSFF_sa (*((volatile unsigned short*) 0xE003C004)) /* ALL CAN Parts */ +#define CANSFF_GRP_sa (*((volatile unsigned short*) 0xE003C008)) /* ALL CAN Parts */ +#define CANEFF_sa (*((volatile unsigned short*) 0xE003C00C)) /* ALL CAN Parts */ +#define CANEFF_GRP_sa (*((volatile unsigned short*) 0xE003C010)) /* ALL CAN Parts */ +#define CANENDofTable (*((volatile unsigned short*) 0xE003C014)) /* ALL CAN Parts */ +#define CANLUTerrAd (*((volatile unsigned short*) 0xE003C018)) /* ALL CAN Parts */ +#define CANLUTerr (*((volatile unsigned char *) 0xE003C01C)) /* ALL CAN Parts */ + + +/* Timer 0 */ +#define T0IR (*((volatile unsigned long *) 0xE0004000)) +#define T0TCR (*((volatile unsigned long *) 0xE0004004)) +#define T0TC (*((volatile unsigned long *) 0xE0004008)) +#define T0PR (*((volatile unsigned long *) 0xE000400C)) +#define T0PC (*((volatile unsigned long *) 0xE0004010)) +#define T0MCR (*((volatile unsigned long *) 0xE0004014)) +#define T0MR0 (*((volatile unsigned long *) 0xE0004018)) +#define T0MR1 (*((volatile unsigned long *) 0xE000401C)) +#define T0MR2 (*((volatile unsigned long *) 0xE0004020)) +#define T0MR3 (*((volatile unsigned long *) 0xE0004024)) +#define T0CCR (*((volatile unsigned long *) 0xE0004028)) +#define T0CR0 (*((volatile unsigned long *) 0xE000402C)) +#define T0CR1 (*((volatile unsigned long *) 0xE0004030)) +#define T0CR2 (*((volatile unsigned long *) 0xE0004034)) +#define T0CR3 (*((volatile unsigned long *) 0xE0004038)) +#define T0EMR (*((volatile unsigned long *) 0xE000403C)) + +/* Timer 1 */ +#define T1IR (*((volatile unsigned long *) 0xE0008000)) +#define T1TCR (*((volatile unsigned long *) 0xE0008004)) +#define T1TC (*((volatile unsigned long *) 0xE0008008)) +#define T1PR (*((volatile unsigned long *) 0xE000800C)) +#define T1PC (*((volatile unsigned long *) 0xE0008010)) +#define T1MCR (*((volatile unsigned long *) 0xE0008014)) +#define T1MR0 (*((volatile unsigned long *) 0xE0008018)) +#define T1MR1 (*((volatile unsigned long *) 0xE000801C)) +#define T1MR2 (*((volatile unsigned long *) 0xE0008020)) +#define T1MR3 (*((volatile unsigned long *) 0xE0008024)) +#define T1CCR (*((volatile unsigned long *) 0xE0008028)) +#define T1CR0 (*((volatile unsigned long *) 0xE000802C)) +#define T1CR1 (*((volatile unsigned long *) 0xE0008030)) +#define T1CR2 (*((volatile unsigned long *) 0xE0008034)) +#define T1CR3 (*((volatile unsigned long *) 0xE0008038)) +#define T1EMR (*((volatile unsigned long *) 0xE000803C)) + +/* Pulse Width Modulator (PWM) */ +#define PWMIR (*((volatile unsigned long *) 0xE0014000)) +#define PWMTCR (*((volatile unsigned long *) 0xE0014004)) +#define PWMTC (*((volatile unsigned long *) 0xE0014008)) +#define PWMPR (*((volatile unsigned long *) 0xE001400C)) +#define PWMPC (*((volatile unsigned long *) 0xE0014010)) +#define PWMMCR (*((volatile unsigned long *) 0xE0014014)) +#define PWMMR0 (*((volatile unsigned long *) 0xE0014018)) +#define PWMMR1 (*((volatile unsigned long *) 0xE001401C)) +#define PWMMR2 (*((volatile unsigned long *) 0xE0014020)) +#define PWMMR3 (*((volatile unsigned long *) 0xE0014024)) +#define PWMMR4 (*((volatile unsigned long *) 0xE0014040)) +#define PWMMR5 (*((volatile unsigned long *) 0xE0014044)) +#define PWMMR6 (*((volatile unsigned long *) 0xE0014048)) +#define PWMPCR (*((volatile unsigned long *) 0xE001404C)) +#define PWMLER (*((volatile unsigned long *) 0xE0014050)) + +/* A/D CONVERTER */ +#define ADCR (*((volatile unsigned long *) 0xE0034000)) /* no in lpc210x*/ +#define ADDR (*((volatile unsigned long *) 0xE0034004)) /* no in lpc210x*/ + +/* Real Time Clock */ +#define ILR (*((volatile unsigned char *) 0xE0024000)) +#define CTC (*((volatile unsigned short*) 0xE0024004)) +#define CCR (*((volatile unsigned char *) 0xE0024008)) +#define CIIR (*((volatile unsigned char *) 0xE002400C)) +#define AMR (*((volatile unsigned char *) 0xE0024010)) +#define CTIME0 (*((volatile unsigned long *) 0xE0024014)) +#define CTIME1 (*((volatile unsigned long *) 0xE0024018)) +#define CTIME2 (*((volatile unsigned long *) 0xE002401C)) +#define SEC (*((volatile unsigned char *) 0xE0024020)) +#define MIN (*((volatile unsigned char *) 0xE0024024)) +#define HOUR (*((volatile unsigned char *) 0xE0024028)) +#define DOM (*((volatile unsigned char *) 0xE002402C)) +#define DOW (*((volatile unsigned char *) 0xE0024030)) +#define DOY (*((volatile unsigned short*) 0xE0024034)) +#define MONTH (*((volatile unsigned char *) 0xE0024038)) +#define YEAR (*((volatile unsigned short*) 0xE002403C)) +#define ALSEC (*((volatile unsigned char *) 0xE0024060)) +#define ALMIN (*((volatile unsigned char *) 0xE0024064)) +#define ALHOUR (*((volatile unsigned char *) 0xE0024068)) +#define ALDOM (*((volatile unsigned char *) 0xE002406C)) +#define ALDOW (*((volatile unsigned char *) 0xE0024070)) +#define ALDOY (*((volatile unsigned short*) 0xE0024074)) +#define ALMON (*((volatile unsigned char *) 0xE0024078)) +#define ALYEAR (*((volatile unsigned short*) 0xE002407C)) +#define PREINT (*((volatile unsigned short*) 0xE0024080)) +#define PREFRAC (*((volatile unsigned short*) 0xE0024084)) + +/* Watchdog */ +#define WDMOD (*((volatile unsigned char *) 0xE0000000)) +#define WDTC (*((volatile unsigned long *) 0xE0000004)) +#define WDFEED (*((volatile unsigned char *) 0xE0000008)) +#define WDTV (*((volatile unsigned long *) 0xE000000C)) + +#endif /* LPC2294_H */ +/*********************************** end of lpc2294.h **********************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/main.c b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/main.c new file mode 100644 index 00000000..bd9c8bab --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/main.c @@ -0,0 +1,158 @@ +/**************************************************************************************** +| Description: bootloader application source file +| File Name: main.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ +#include "lpc2294.h" /* CPU register definitions */ + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +static void Init(void); + + +/**************************************************************************************** +** NAME: main +** PARAMETER: none +** RETURN VALUE: program return code +** DESCRIPTION: This is the entry point for the bootloader application and is called +** by the reset interrupt vector after the C-startup routines executed. +** +****************************************************************************************/ +int main(void) +{ + /* initialize the microcontroller */ + Init(); + /* initialize the bootloader */ + BootInit(); + /* start the infinite program loop */ + while (1) + { + /* run the bootloader task */ + BootTask(); + } + + /* program should never get here */ + return 0; +} /*** end of main ***/ + + +/**************************************************************************************** +** NAME: Init +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the microcontroller. The Fpll is set to 60MHz and Fvpb is +** configured equal to Fpll. The GPIO pin of the status LED is configured +** as digital output. +** +****************************************************************************************/ +static void Init(void) +{ + blt_int8u m_sel; /* pll multiplier register value */ + blt_int8u pll_dividers[] = { 1, 2, 4, 8 }; /* possible pll dividers */ + blt_int8u p_sel_cnt; /* loop counter to find p_sel */ + blt_int32u f_cco; /* current controller oscillator */ + + /* check that pll multiplier value will be in the range 1..32 */ + ASSERT_CT((BOOT_CPU_SYSTEM_SPEED_KHZ + ((BOOT_CPU_XTAL_SPEED_KHZ+1)/2)) / \ + BOOT_CPU_XTAL_SPEED_KHZ >= 1); + + ASSERT_CT((BOOT_CPU_SYSTEM_SPEED_KHZ + ((BOOT_CPU_XTAL_SPEED_KHZ+1)/2)) / \ + BOOT_CPU_XTAL_SPEED_KHZ <= 32); + + /* calculate MSEL: M = round(Fcclk / Fosc) */ + m_sel = (BOOT_CPU_SYSTEM_SPEED_KHZ + ((BOOT_CPU_XTAL_SPEED_KHZ+1)/2)) / \ + BOOT_CPU_XTAL_SPEED_KHZ; + /* value for the PLLCFG register is -1 */ + m_sel--; + + /* find PSEL value so that Fcco(= Fcclk * 2 * P) is in the 156000..320000 kHz range. */ + for (p_sel_cnt=0; p_sel_cnt= 156000) && (f_cco <= 320000) ) + { + /* found a valid pll divider value */ + break; + } + } + /* check that a valid value was found */ + ASSERT_RT(p_sel_cnt < (sizeof(pll_dividers)/sizeof(pll_dividers[0]))); + + /* set multiplier and divider values */ + PLLCFG = (p_sel_cnt << 5) | m_sel; + PLLFEED = 0xAA; + PLLFEED = 0x55; + /* enable the PLL */ + PLLCON = 0x1; + PLLFEED = 0xAA; + PLLFEED = 0x55; + /* wait for the PLL to lock to set frequency */ + while(!(PLLSTAT & 0x400)) { ; } + /* connect the PLL as the clock source */ + PLLCON = 0x3; + PLLFEED = 0xAA; + PLLFEED = 0x55; + /* enable MAM and set number of clocks used for Flash memory fetch. Recommended: + * Fcclk >= 60 MHz: 4 clock cycles + * Fcclk >= 40 MHz: 3 clock cycles + * Fcclk >= 20 MHz: 2 clock cycles + * Fcclk < 20 MHz: 1 clock cycle + */ + MAMCR = 0x0; +#if (BOOT_CPU_SYSTEM_SPEED_KHZ >= 60) + MAMTIM = 4; +#elif (BOOT_CPU_SYSTEM_SPEED_KHZ >= 40) + MAMTIM = 3; +#elif (BOOT_CPU_SYSTEM_SPEED_KHZ >= 20) + MAMTIM = 2; +#else + MAMTIM = 1; +#endif + MAMCR = 0x2; + /* setting peripheral Clock (pclk) to System Clock (cclk) */ + VPBDIV = 0x1; +#if (BOOT_COM_UART_ENABLE > 0) + /* configure P0.0 for UART0 Tx and P0.1 for UART0 Rx functionality */ + PINSEL0 |= 0x05; +#endif +#if (BOOT_COM_CAN_ENABLE > 0) + /* configure P0.25 for CAN1 Rx functionality */ + PINSEL1 |= 0x00040000L; +#endif +} /*** end of Init ***/ + + +/*********************************** end of main.c *************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/makefile b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/makefile new file mode 100644 index 00000000..40744340 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Boot/makefile @@ -0,0 +1,163 @@ +#**************************************************************************************** +#| Description: Makefile for NXP LPC2000 using CodeSourcery GNU GCC compiler toolset +#| File Name: makefile +#| +#|--------------------------------------------------------------------------------------- +#| C O P Y R I G H T +#|--------------------------------------------------------------------------------------- +#| Copyright (c) 2011 by Feaser LLC http://www.feaser.com All rights reserved +#| +#|--------------------------------------------------------------------------------------- +#| L I C E N S E +#|--------------------------------------------------------------------------------------- +#| This file is part of OpenBTL. OpenBTL is free software: you can redistribute it and/or +#| modify it under the terms of the GNU General Public License as published by the Free +#| Software Foundation, either version 3 of the License, or (at your option) any later +#| version. +#| +#| OpenBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +#| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +#| PURPOSE. See the GNU General Public License for more details. +#| +#| You should have received a copy of the GNU General Public License along with OpenBTL. +#| If not, see . +#| +#**************************************************************************************** +SHELL = sh + +#|---------------------------------------------------------------------------------------| +#| Configure project name | +#|---------------------------------------------------------------------------------------| +PROJ_NAME=openbtl_olimex_lpc_l2294_20mhz + + +#|---------------------------------------------------------------------------------------| +#| Speficy project source files | +#|---------------------------------------------------------------------------------------| +PROJ_FILES= \ +config.h \ +hooks.c \ +main.c \ +lpc2294.h \ +../../../Source/boot.c \ +../../../Source/boot.h \ +../../../Source/com.c \ +../../../Source/com.h \ +../../../Source/xcp.c \ +../../../Source/xcp.h \ +../../../Source/backdoor.c \ +../../../Source/backdoor.h \ +../../../Source/cop.c \ +../../../Source/cop.h \ +../../../Source/assert.c \ +../../../Source/assert.h \ +../../../Source/plausibility.h \ +../../../Source/ARM7_LPC2000/types.h \ +../../../Source/ARM7_LPC2000/cpu.c \ +../../../Source/ARM7_LPC2000/cpu.h \ +../../../Source/ARM7_LPC2000/can.c \ +../../../Source/ARM7_LPC2000/can.h \ +../../../Source/ARM7_LPC2000/uart.c \ +../../../Source/ARM7_LPC2000/uart.h \ +../../../Source/ARM7_LPC2000/nvm.c \ +../../../Source/ARM7_LPC2000/nvm.h \ +../../../Source/ARM7_LPC2000/timer.c \ +../../../Source/ARM7_LPC2000/timer.h \ +../../../Source/ARM7_LPC2000/GCC/flash.c \ +../../../Source/ARM7_LPC2000/GCC/flash.h \ +../../../Source/ARM7_LPC2000/GCC/vectors.c \ +../../../Source/ARM7_LPC2000/GCC/cstart.s + + +#|---------------------------------------------------------------------------------------| +#| Compiler binaries | +#|---------------------------------------------------------------------------------------| +CC = arm-none-eabi-gcc +LN = arm-none-eabi-gcc +OC = arm-none-eabi-objcopy +OD = arm-none-eabi-objdump +AS = arm-none-eabi-as +SZ = arm-none-eabi-size + + +#|---------------------------------------------------------------------------------------| +#| Extract file names | +#|---------------------------------------------------------------------------------------| +PROJ_ASRCS = $(filter %.s,$(foreach file,$(PROJ_FILES),$(notdir $(file)))) +PROJ_CSRCS = $(filter %.c,$(foreach file,$(PROJ_FILES),$(notdir $(file)))) +PROJ_CHDRS = $(filter %.h,$(foreach file,$(PROJ_FILES),$(notdir $(file)))) +PROJ_CCMPL = $(patsubst %.c,%.cpl,$(PROJ_CSRCS)) +PROJ_ACMPL = $(patsubst %.s,%.cpl,$(PROJ_ASRCS)) + + +#|---------------------------------------------------------------------------------------| +#| Set important path variables | +#|---------------------------------------------------------------------------------------| +VPATH = $(foreach path,$(sort $(foreach file,$(PROJ_FILES),$(dir $(file)))) $(subst \,/,$(OBJ_PATH)),$(path) :) +OBJ_PATH = ./obj +BIN_PATH = ./bin +INC_PATH = $(patsubst %,-I%,$(sort $(foreach file,$(filter %.h,$(PROJ_FILES)),$(dir $(file))))) +INC_PATH += -I. +LIB_PATH = -L../../../Source/ARM7_LPC2000/GCC/ + + +#|---------------------------------------------------------------------------------------| +#| Options for compiler binaries | +#|---------------------------------------------------------------------------------------| +AFLAGS = -ahls -mapcs-32 -mcpu=arm7tdmi-s -mfpu=softfpa +CFLAGS = $(INC_PATH) -O1 -Wall -fmessage-length=0 -mcpu=arm7tdmi-s -g -mlong-calls +CFLAGS += -Wa,-adhlns="$(OBJ_PATH)/$(subst .o,.lst,$@)" +LFLAGS = $(LIB_PATH) -T"memory.x" -g -mcpu=arm7tdmi-s -nostartfiles +OCFLAGS = -O ihex +ODFLAGS = -x +SZFLAGS = -B -d + + +#|---------------------------------------------------------------------------------------| +#| Define targets | +#|---------------------------------------------------------------------------------------| +AOBJS = $(patsubst %.s,%.o,$(PROJ_ASRCS)) +COBJS = $(patsubst %.c,%.o,$(PROJ_CSRCS)) + + +#|---------------------------------------------------------------------------------------| +#| Make ALL | +#|---------------------------------------------------------------------------------------| +all : $(BIN_PATH)/$(PROJ_NAME).hex + +$(BIN_PATH)/$(PROJ_NAME).hex : $(BIN_PATH)/$(PROJ_NAME).elf + @$(OC) $(OCFLAGS) $< $@ + @$(OD) $(ODFLAGS) $< > $(BIN_PATH)/$(PROJ_NAME).map + @echo +++ Summary of memory consumption: + @$(SZ) $(SZFLAGS) $< + @echo +++ Build complete [$(notdir $@)] + +$(BIN_PATH)/$(PROJ_NAME).elf : $(AOBJS) $(COBJS) + @echo +++ Linking [$(notdir $@)] + @$(LN) $(LFLAGS) -o $@ $(patsubst %.o,$(OBJ_PATH)/%.o,$(^F)) + + +#|---------------------------------------------------------------------------------------| +#| Compile and assemble | +#|---------------------------------------------------------------------------------------| +$(AOBJS): %.o: %.s $(PROJ_CHDRS) + @echo +++ Assembling [$@] + @$(AS) $(AFLAGS) $< -o $(OBJ_PATH)/$(@F) > $(subst .o,.lst,$(OBJ_PATH)/$(@F)) + +$(COBJS): %.o: %.c $(PROJ_CHDRS) + @echo +++ Compiling [$@] + @$(CC) $(CFLAGS) -c -o $(OBJ_PATH)/$(@F) $< + +#|---------------------------------------------------------------------------------------| +#| Make CLEAN | +#|---------------------------------------------------------------------------------------| +clean : + @echo +++ Cleaning build environment + @rm -f $(foreach file,$(AOBJS),$(OBJ_PATH)/$(file)) + @rm -f $(foreach file,$(COBJS),$(OBJ_PATH)/$(file)) + @rm -f $(patsubst %.o,%.lst,$(foreach file,$(AOBJS),$(OBJ_PATH)/$(file))) + @rm -f $(patsubst %.o,%.lst,$(foreach file,$(COBJS),$(OBJ_PATH)/$(file))) + @rm -f $(BIN_PATH)/$(PROJ_NAME).hex $(BIN_PATH)/$(PROJ_NAME).map $(BIN_PATH)/$(PROJ_NAME).elf + @echo +++ Clean complete + + diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.elf b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.elf new file mode 100644 index 0000000000000000000000000000000000000000..3ccf6e27bbb05b9a46c3a09f18889951007d5aba GIT binary patch literal 19463 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 BA`<`r literal 0 HcmV?d00001 diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.map b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.map new file mode 100644 index 00000000..618fbdae --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.map @@ -0,0 +1,122 @@ + +bin/demoprog_olimex_lpc_l2294_20mhz.elf: file format elf32-littlearm +bin/demoprog_olimex_lpc_l2294_20mhz.elf +architecture: arm, flags 0x00000112: +EXEC_P, HAS_SYMS, D_PAGED +start address 0x00002000 + +Program Header: + LOAD off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**15 + filesz 0x000028e8 memsz 0x000028e8 flags r-x + LOAD off 0x00008200 vaddr 0x40000200 paddr 0x000028e8 align 2**15 + filesz 0x00000000 memsz 0x0000005c flags rw- +private flags = 5000002: [Version5 EABI] [has entry point] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 000008e8 00002000 00002000 00002000 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .bss 0000005c 40000200 000028e8 00008200 2**2 + ALLOC + 2 .ARM.attributes 00000030 00000000 00000000 000028e8 2**0 + CONTENTS, READONLY + 3 .comment 0000002a 00000000 00000000 00002918 2**0 + CONTENTS, READONLY + 4 .debug_abbrev 0000029c 00000000 00000000 00002942 2**0 + CONTENTS, READONLY, DEBUGGING + 5 .debug_info 000004b9 00000000 00000000 00002bde 2**0 + CONTENTS, READONLY, DEBUGGING + 6 .debug_line 00000222 00000000 00000000 00003097 2**0 + CONTENTS, READONLY, DEBUGGING + 7 .debug_loc 00000390 00000000 00000000 000032b9 2**0 + CONTENTS, READONLY, DEBUGGING + 8 .debug_pubnames 00000175 00000000 00000000 00003649 2**0 + CONTENTS, READONLY, DEBUGGING + 9 .debug_aranges 000000c0 00000000 00000000 000037be 2**0 + CONTENTS, READONLY, DEBUGGING + 10 .debug_str 000002a8 00000000 00000000 0000387e 2**0 + CONTENTS, READONLY, DEBUGGING + 11 .debug_frame 000002e0 00000000 00000000 00003b28 2**2 + CONTENTS, READONLY, DEBUGGING +SYMBOL TABLE: +00002000 l d .text 00000000 .text +40000200 l d .bss 00000000 .bss +00000000 l d .ARM.attributes 00000000 .ARM.attributes +00000000 l d .comment 00000000 .comment +00000000 l d .debug_abbrev 00000000 .debug_abbrev +00000000 l d .debug_info 00000000 .debug_info +00000000 l d .debug_line 00000000 .debug_line +00000000 l d .debug_loc 00000000 .debug_loc +00000000 l d .debug_pubnames 00000000 .debug_pubnames +00000000 l d .debug_aranges 00000000 .debug_aranges +00000000 l d .debug_str 00000000 .debug_str +00000000 l d .debug_frame 00000000 .debug_frame +00000100 l *ABS* 00000000 UND_STACK_SIZE +00000100 l *ABS* 00000000 ABT_STACK_SIZE +00000100 l *ABS* 00000000 FIQ_STACK_SIZE +00000100 l *ABS* 00000000 IRQ_STACK_SIZE +00000100 l *ABS* 00000000 SVC_STACK_SIZE +00000010 l *ABS* 00000000 MODE_USR +00000011 l *ABS* 00000000 MODE_FIQ +00000012 l *ABS* 00000000 MODE_IRQ +00000013 l *ABS* 00000000 MODE_SVC +00000017 l *ABS* 00000000 MODE_ABT +0000001b l *ABS* 00000000 MODE_UND +0000001f l *ABS* 00000000 MODE_SYS +00000080 l *ABS* 00000000 I_BIT +00000040 l *ABS* 00000000 F_BIT +00002000 l .text 00000000 _vectors +00002020 l .text 00000000 Reset_Addr +00002024 l .text 00000000 Undef_Addr +00002028 l .text 00000000 SWI_Addr +0000202c l .text 00000000 PAbt_Addr +00002030 l .text 00000000 DAbt_Addr +0000203c l .text 00000000 FIQ_Addr +00002038 l .text 00000000 IRQ_Addr +00000000 l df *ABS* 00000000 vectors.c +00000000 l df *ABS* 00000000 main.c +0000217c l F .text 000001f0 Init +000028e4 l O .text 00000004 C.0.2054 +00000000 l df *ABS* 00000000 boot.c +0000236c l F .text 0000002c BootActivate +00002538 l F .text 00000064 UartReceiveByte +40000200 l .bss 00000000 xcpCtoRxInProgress.1301 +40000204 l .bss 00000000 xcpCtoReqPacket.1299 +40000245 l .bss 00000000 xcpCtoRxLength.1300 +00000000 l df *ABS* 00000000 irq.c +40000248 l .bss 00000000 oldInterruptStatus +4000024c l .bss 00000000 interruptNesting +0000259c l F .text 00000028 IrqGetCPSR +000025c4 l F .text 00000024 IrqSetCPSR +00000000 l df *ABS* 00000000 led.c +40000250 l .bss 00000000 timer_counter_last.1292 +40000254 l .bss 00000000 led_toggle_state.1291 +00000000 l df *ABS* 00000000 timer.c +40000258 l .bss 00000000 millisecond_counter +00002868 g F .text 0000002c TimerUpdate +000025e8 g F .text 00000030 IrqInterruptEnable +000020d8 g F .text 00000044 TIMER0_ISR +000028e8 g .text 00000000 _etext +40000200 g .bss 00000000 _bss_start +00002000 g .text 00000000 _startup +4000025c g *ABS* 00000000 _bss_end +00002040 g .text 00000000 Reset_Handler +000026f4 g F .text 0000003c LedInit +00002684 g F .text 00000070 IrqInterruptRestore +0000213c g F .text 00000040 main +40003edc g *ABS* 00000000 _stack_end +00002894 g F .text 0000002c TimerSet +00002398 g F .text 000000b8 BootComInit +00002128 g F .text 00000008 FIQ_ISR +40000200 g .text 00000000 _data +00002730 g F .text 000000b4 LedToggle +40000200 g .text 00000000 _edata +4000025c g *ABS* 00000000 _end +00002130 g F .text 0000000c UNDEF_ISR +0000211c g F .text 0000000c SWI_ISR +00002618 g F .text 0000006c IrqInterruptDisable +00002450 g F .text 000000e8 BootComCheckActivationRequest +000028c0 g F .text 00000024 TimerGet +000027e4 g F .text 00000084 TimerInit + + diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.sx b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.sx new file mode 100644 index 00000000..a7897859 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/bin/demoprog_olimex_lpc_l2294_20mhz.sx @@ -0,0 +1,145 @@ +S029000062696E2F64656D6F70726F675F6F6C696D65785F6C70635F6C323239345F32306D687A2E7378C1 +S113200018F09FE518F09FE518F09FE518F09FE59C +S113201018F09FE50000A0E1F0FF1FE518F09FE530 +S113202040200000302100001C210000302100006D +S11320303021000000000000000000002821000002 +S113204078009FE5DBF021E300D0A0E1010C40E241 +S1132050D7F021E300D0A0E1010C40E2D1F021E36C +S113206000D0A0E1010C40E2D2F021E300D0A0E1D5 +S1132070010C40E2D3F021E300D0A0E1010C40E2E6 +S1132080DFF021E300D0A0E134109FE534209FE588 +S113209034309FE5030052E104009134040082349B +S11320A0FBFFFF3A0000A0E320109FE520209FE5FE +S11320B0020051E104008134FCFFFF3A1E0000EAF3 +S11320C0DC3E0040E828000000020040000200401E +S11320D0000200405C02004004E04EE21F582DE97B +S11320E01CB08DE224309FE50120A0E3002083E5AD +S11320F01C309FE50020A0E3002083E514309FE519 +S11321000FE0A0E113FF2FE11CD04BE21F98FDE884 +S1132110004000E030F0FFFF6828000004B02DE527 +S113212000B08DE2FEFFFFEA04B04DE2FEFFFFEADD +S113213004B02DE500B08DE2FEFFFFEA00482DE972 +S113214004B08DE20C0000EB20309FE50FE0A0E12D +S113215013FF2FE118309FE50FE0A0E113FF2FE1FB +S113216010309FE50FE0A0E113FF2FE1F8FFFFEA35 +S113217098230000302700005024000000482DE977 +S113218004B08DE210D04DE2A8319FE5003093E514 +S113219010300BE50330A0E306304BE506305BE579 +S11321A0013043E206304BE50030A0E305304BE557 +S11321B01A0000EA05205BE50B30E0E304104BE273 +S11321C0022081E0033082E00030D3E50320A0E167 +S11321D00230A0E18332A0E1033062E00331A0E1E8 +S11321E0023083E00322A0E1022063E00233A0E195 +S11321F00C300BE50C201BE53C319FE5030052E15C +S11322000300009A0C201BE530319FE5030052E1E6 +S11322100600009A05305BE5013083E205304BE5AA +S113222005305BE5030053E3E1FFFF9A000000EA99 +S11322300000A0E108319FE505205BE58222A0E1D2 +S1132240FF1002E206205BE5022081E1FF2002E2AA +S1132250FF2002E20020C3E5E8309FE55520E0E3DB +S11322600020C3E5DC309FE55520A0E30020C3E552 +S1132270D4309FE50120A0E30020C3E5C4309FE5EE +S11322805520E0E30020C3E5B8309FE55520A0E3E6 +S11322900020C3E50000A0E1B0309FE5B030D3E1F9 +S11322A00338A0E12338A0E1013B03E2000053E33B +S11322B0F8FFFF0A90309FE50320A0E30020C3E568 +S11322C080309FE55520E0E30020C3E574309FE5AE +S11322D05520A0E30020C3E574309FE50020A0E36F +S11322E00020C3E56C309FE50420A0E30020C3E593 +S11322F05C309FE50220A0E30020C3E558309FE551 +S11323000120A0E30020C3E550309FE50FE0A0E1E9 +S113231013FF2FE148309FE50FE0A0E113FF2FE109 +S113232040309FE50FE0A0E113FF2FE104D04BE222 +S11323300048BDE81EFF2FE1E42800005F610200B1 +S113234000E2040084C01FE08CC01FE080C01FE0D6 +S113235088C01FE000C01FE004C01FE000C11FE0F0 +S1132360F4260000E4270000E825000000482DE9D9 +S113237004B08DE208D04DE24030A0E308300BE514 +S113238008301BE50FE0A0E113FF2FE104D04BE27E +S11323900048BDE81EFF2FE104B02DE500B08DE23A +S11323A00CD04DE28C309FE588209FE5002092E51B +S11323B0052082E3002083E57C309FE50020A0E334 +S11323C00020C3E574309FE50020A0E30020C3E5AE +S11323D06C309FE50020A0E30020C3E564309FE556 +S11323E07F20E0E30020C3E54130A0E308300BE5A3 +S11323F054309FE508201BE5FF2002E20020C3E5DE +S113240034309FE508201BE52224A0E1FF2002E2EE +S11324100020C3E52C309FE50320A0E30020C3E5A2 +S113242018309FE50720A0E30020C3E500D08BE22D +S113243004B09DE41EFF2FE100C002E004C000E0F0 +S113244008C000E014C000E00CC000E000C000E0E0 +S113245000482DE904B08DE2CC309FE50030D3E58F +S1132460000053E30B00001AC0009FE5310000EBAD +S11324700030A0E1010053E32800001AA8309FE5D2 +S11324800120A0E30020C3E5A4309FE50020A0E3E1 +S11324900020C3E5210000EA94309FE50030D3E535 +S11324A0012083E284309FE5033082E00300A0E151 +S11324B0200000EB0030A0E1010053E31700001AF4 +S11324C06C309FE50030D3E5013083E2FF2003E266 +S11324D05C309FE50020C3E550309FE50020D3E544 +S11324E04C309FE50030D3E5030052E10B00001AA5 +S11324F034309FE50020A0E30020C3E52C309FE5A5 +S11325000130D3E5FF0053E30400001A1C309FE5BB +S11325100230D3E5000053E30000001A92FFFFEB02 +S113252004D04BE20048BDE81EFF2FE1000200404A +S1132530040200404502004004B02DE500B08DE2E5 +S11325400CD04DE208000BE544309FE50030D3E5A4 +S1132550FF3003E2013003E2FF3003E2000053E303 +S11325600600000A2C309FE50030D3E5FF2003E28B +S113257008301BE50020C3E50130A0E3000000EAB9 +S11325800030A0E30300A0E100D08BE204B09DE49E +S11325901EFF2FE114C000E000C000E010082DE988 +S11325A004B08DE208D04DE200400FE108400BE595 +S11325B008301BE50300A0E104D04BE21008BDE89D +S11325C01EFF2FE104B02DE500B08DE20CD04DE2EA +S11325D008000BE508301BE503F029E100D08BE28D +S11325E004B09DE41EFF2FE100482DE904B08DE204 +S11325F008D04DE2E8FFFFEB08000BE508301BE5CF +S11326008030C3E30300A0E1EDFFFFEB04D04BE215 +S11326100048BDE81EFF2FE100482DE904B08DE21B +S113262008D04DE250309FE50030D3E5000053E37D +S11326300800001AD8FFFFEB08000BE508301BE583 +S1132640803083E30300A0E1DDFFFFEB2C309FE546 +S113265008201BE5002083E51C309FE50030D3E50E +S1132660013083E2FF2003E20C309FE50020C3E544 +S113267004D04BE20048BDE81EFF2FE14C020040AD +S11326804802004000482DE904B08DE208D04DE234 +S113269054309FE50030D3E5013043E2FF2003E2EC +S11326A044309FE50020C3E53C309FE50030D3E58E +S11326B0000053E30900001AB7FFFFEB08000BE525 +S11326C008301BE58020C3E320309FE5003093E50C +S11326D0803003E2033082E10300A0E1B8FFFFEBA6 +S11326E004D04BE20048BDE81EFF2FE14C0200403D +S11326F04802004004B02DE500B08DE224309FE58F +S113270020209FE5002092E5022582E3002083E556 +S113271014309FE50225A0E3002083E500D08BE27E +S113272004B09DE41EFF2FE1188002E0148002E053 +S113273000482DE904B08DE208D04DE288309FE5D1 +S11327400FE0A0E113FF2FE108000BE57C309FE5CB +S1132750003093E508201BE5022063E070309FE51C +S1132760030052E11400009A68309FE50030D3E57D +S1132770000053E30600001A58309FE50120A0E34F +S11327800020C3E550309FE50225A0E3002083E547 +S1132790050000EA3C309FE50020A0E30020C3E5EB +S11327A038309FE50225A0E3002083E51C309FE537 +S11327B008201BE5002083E5000000EA0000A0E1FA +S11327C004D04BE20048BDE81EFF2FE1C028000002 +S11327D050020040F3010000540200401C8002E05B +S11327E0148002E000482DE904B08DE254309FE5E6 +S11327F054209FE5002083E550309FE50320A0E3AB +S1132800002083E548309FE50120A0E3002083E514 +S113281040309FE540209FE5002083E53C309FE564 +S11328202420A0E3002083E534309FE51020A0E3BA +S1132830002083E50000A0E3150000EB04D04BE288 +S11328400048BDE81EFF2FE1184000E05FEA0000E9 +S1132850144000E0044000E000F1FFFFD820000035 +S113286000F2FFFF10F0FFFF04B02DE500B08DE291 +S113287018309FE5003093E5012083E20C309FE59A +S1132880002083E500D08BE204B09DE41EFF2FE11D +S11328905802004004B02DE500B08DE20CD04DE2AA +S11328A008000BE510309FE508201BE5002083E5B8 +S11328B000D08BE204B09DE41EFF2FE158020040DB +S11328C004B02DE500B08DE210309FE5003093E5B3 +S11328D00300A0E100D08BE204B09DE41EFF2FE1D1 +S10B28E0580200400102040843 +S9032000DC diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/boot.c b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/boot.c new file mode 100644 index 00000000..b375cc13 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/boot.c @@ -0,0 +1,353 @@ +/**************************************************************************************** +| Description: demo program bootloader interface source file +| File Name: boot.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "header.h" /* generic header */ + + +/**************************************************************************************** +** NAME: BootActivate +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Bootloader activation function. +** +****************************************************************************************/ +static void BootActivate(void) +{ + void (*pEntryFromProgFnc)(void); + + /* set pointer to the address of function EntryFromProg in the bootloader */ + pEntryFromProgFnc = (void*)0x00000040; + /* call EntryFromProg to activate the bootloader. */ + pEntryFromProgFnc(); +} /*** end of BootActivate ***/ + + +#if (BOOT_COM_UART_ENABLE > 0) +/**************************************************************************************** +* U N I V E R S A L A S Y N C H R O N O U S R X T X I N T E R F A C E +****************************************************************************************/ + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +#define UART_DLAB (0x80) /* divisor latch access bit */ +#define UART_MODE_8N1 (0x03) /* 8 data and 1 stop bit, no parity */ +#define UART_FIFO_RX1 (0x07) /* FIFO reset and RX FIFO 1 deep */ +#define UART_RDR (0x01) /* receiver data ready */ + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +static unsigned char UartReceiveByte(unsigned char *data); + + +/**************************************************************************************** +** NAME: BootComInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the UART communication interface +** +****************************************************************************************/ +void BootComInit(void) +{ + unsigned long baud_reg_value; /* baudrate register value */ + + /* configure P0.0 for UART0 Tx and P0.1 for UART0 Rx functionality */ + PINSEL0 |= 0x05; + /* disable UART related interrupt generation. this driver works in polling mode */ + U0IER = 0; + /* clear interrupt id register */ + U0IIR = 0; + /* clear line status register */ + U0LSR = 0; + /* set divisor latch DLAB = 1 so buadrate can be configured */ + U0LCR = UART_DLAB; + /* Baudrate calculation: + * y = BOOT_CPU_SYSTEM_SPEED_KHZ * 1000 / 16 / BOOT_COM_UART_BAUDRATE and add + * smartness to automatically round the value up/down using the following trick: + * y = x/n can round with y = (x + (n + 1)/2 ) / n + */ + baud_reg_value = (((BOOT_CPU_SYSTEM_SPEED_KHZ*1000/16)+ \ + ((BOOT_COM_UART_BAUDRATE+1)/2))/BOOT_COM_UART_BAUDRATE); + /* write the calculated baudrate selector value to the registers */ + U0DLL = (unsigned char)baud_reg_value; + U0DLM = (unsigned char)(baud_reg_value >> 8); + /* configure 8 data bits, no parity and 1 stop bit and set DLAB = 0 */ + U0LCR = UART_MODE_8N1; + /* enable and reset transmit and receive FIFO. necessary for UART operation */ + U0FCR = UART_FIFO_RX1; +} /*** end of BootComInit ***/ + + +/**************************************************************************************** +** NAME: BootComCheckActivationRequest +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Receives the CONNECT request from the host, which indicates that the +** bootloader should be activated and, if so, activates it. +** +****************************************************************************************/ +void BootComCheckActivationRequest(void) +{ + static unsigned char xcpCtoReqPacket[BOOT_COM_UART_RX_MAX_DATA+1]; + static unsigned char xcpCtoRxLength; + static unsigned char xcpCtoRxInProgress = 0; + + /* start of cto packet received? */ + if (xcpCtoRxInProgress == 0) + { + /* store the message length when received */ + if (UartReceiveByte(&xcpCtoReqPacket[0]) == 1) + { + /* indicate that a cto packet is being received */ + xcpCtoRxInProgress = 1; + + /* reset packet data count */ + xcpCtoRxLength = 0; + } + } + else + { + /* store the next packet byte */ + if (UartReceiveByte(&xcpCtoReqPacket[xcpCtoRxLength+1]) == 1) + { + /* increment the packet data count */ + xcpCtoRxLength++; + + /* check to see if the entire packet was received */ + if (xcpCtoRxLength == xcpCtoReqPacket[0]) + { + /* done with cto packet reception */ + xcpCtoRxInProgress = 0; + + /* check if this was an XCP CONNECT command */ + if ((xcpCtoReqPacket[1] == 0xff) && (xcpCtoReqPacket[2] == 0x00)) + { + /* connection request received so start the bootloader */ + BootActivate(); + } + } + } + } +} /*** end of BootComCheckActivationRequest ***/ + + +/**************************************************************************************** +** NAME: UartReceiveByte +** PARAMETER: data pointer to byte where the data is to be stored. +** RETURN VALUE: 1 if a byte was received, 0 otherwise. +** DESCRIPTION: Receives a communication interface byte if one is present. +** +****************************************************************************************/ +static unsigned char UartReceiveByte(unsigned char *data) +{ + /* check if a new byte was received by means of the RDR-bit */ + if((U0LSR & UART_RDR) != 0) + { + /* store the received byte */ + data[0] = U0RBR; + /* inform caller of the newly received byte */ + return 1; + } + /* inform caller that no new data was received */ + return 0; +} /*** end of UartReceiveByte ***/ +#endif /* BOOT_COM_UART_ENABLE > 0 */ + + +#if (BOOT_COM_CAN_ENABLE > 0) +/**************************************************************************************** +* C O N T R O L L E R A R E A N E T W O R K I N T E R F A C E +****************************************************************************************/ + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +#define CAN_TBS1 (0x00000004) /* transmit buffer 1 idle */ +#define CAN_TCS1 (0x00000008) /* transmit buffer 1 complete */ +#define CAN_RRB (0x04) /* receive buffer release */ +#define CAN_RBS (0x01) /* receive buffer status */ +#define CAN_TR (0x01) /* transmission request */ +#define CAN_STB1 (0x20) /* select tx buffer 1 for transmit */ + + +/**************************************************************************************** +* Type definitions +****************************************************************************************/ +typedef struct t_can_bus_timing +{ + unsigned char tseg1; /* CAN time segment 1 */ + unsigned char tseg2; /* CAN time segment 2 */ +} tCanBusTiming; /* bus timing structure type */ + + +/**************************************************************************************** +* Local constant declarations +****************************************************************************************/ +/* According to the CAN protocol 1 bit-time can be made up of between 8..25 time quanta + * (TQ). The total TQ in a bit is SYNC + TSEG1 + TSEG2 with SYNC always being 1. + * The sample point is (SYNC + TSEG1) / (SYNC + TSEG1 + SEG2) * 100%. This array contains + * possible and valid time quanta configurations with a sample point between 68..78%. + */ +static const tCanBusTiming canTiming[] = +{ /* TQ | TSEG1 | TSEG2 | SP */ + /* ------------------------- */ + { 5, 2 }, /* 8 | 5 | 2 | 75% */ + { 6, 2 }, /* 9 | 6 | 2 | 78% */ + { 6, 3 }, /* 10 | 6 | 3 | 70% */ + { 7, 3 }, /* 11 | 7 | 3 | 73% */ + { 8, 3 }, /* 12 | 8 | 3 | 75% */ + { 9, 3 }, /* 13 | 9 | 3 | 77% */ + { 9, 4 }, /* 14 | 9 | 4 | 71% */ + { 10, 4 }, /* 15 | 10 | 4 | 73% */ + { 11, 4 }, /* 16 | 11 | 4 | 75% */ + { 12, 4 }, /* 17 | 12 | 4 | 76% */ + { 12, 5 }, /* 18 | 12 | 5 | 72% */ + { 13, 5 }, /* 19 | 13 | 5 | 74% */ + { 14, 5 }, /* 20 | 14 | 5 | 75% */ + { 15, 5 }, /* 21 | 15 | 5 | 76% */ + { 15, 6 }, /* 22 | 15 | 6 | 73% */ + { 16, 6 }, /* 23 | 16 | 6 | 74% */ + { 16, 7 }, /* 24 | 16 | 7 | 71% */ + { 16, 8 } /* 25 | 16 | 8 | 68% */ +}; + + +/**************************************************************************************** +** NAME: CanGetSpeedConfig +** PARAMETER: baud The desired baudrate in kbps. Valid values are 10..1000. +** btr Pointer to where the value for register CANxBTR will be stored. +** RETURN VALUE: 1 if the CAN bustiming register values were found, 0 otherwise. +** DESCRIPTION: Search algorithm to match the desired baudrate to a possible bus +** timing configuration. +** +****************************************************************************************/ +static unsigned char CanGetSpeedConfig(unsigned short baud, unsigned long *btr) +{ + unsigned short prescaler; + unsigned char cnt; + + /* loop through all possible time quanta configurations to find a match */ + for (cnt=0; cnt < sizeof(canTiming)/sizeof(canTiming[0]); cnt++) + { + if ((BOOT_CPU_SYSTEM_SPEED_KHZ % (baud*(canTiming[cnt].tseg1+canTiming[cnt].tseg2+1))) == 0) + { + /* compute the prescaler that goes with this TQ configuration */ + prescaler = BOOT_CPU_SYSTEM_SPEED_KHZ/(baud*(canTiming[cnt].tseg1+canTiming[cnt].tseg2+1)); + + /* make sure the prescaler is valid */ + if ( (prescaler > 0) && (prescaler <= 1024) ) + { + /* store the prescaler and bustiming register value */ + *btr = prescaler - 1; + *btr |= ((canTiming[cnt].tseg2 - 1) << 20) | ((canTiming[cnt].tseg1 - 1) << 16); + /* found a good bus timing configuration */ + return 1; + } + } + } + /* could not find a good bus timing configuration */ + return 0; +} /*** end of CanGetSpeedConfig ***/ + + +/**************************************************************************************** +** NAME: BootComInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the CAN communication interface +** +****************************************************************************************/ +void BootComInit(void) +{ + unsigned long btr_reg_value; + + /* configure acceptance filter for bypass mode so it receives all messages */ + CANAFMR = 0x00000002L; + /* take CAN controller offline and go into reset mode */ + CAN1MOD = 1; + /* disable all interrupts. driver only needs to work in polling mode */ + CAN1IER = 0; + /* reset CAN controller status */ + CAN1GSR = 0; + /* configure the bittiming */ + if (CanGetSpeedConfig(BOOT_COM_CAN_BAUDRATE/1000, &btr_reg_value) == 1) + { + /* write the bittiming configuration to the register */ + CAN1BTR = btr_reg_value; + } + /* enter normal operating mode and synchronize to the CAN bus */ + CAN1MOD = 0; +} /*** end of BootComInit ***/ + + +/**************************************************************************************** +** NAME: BootComCheckActivationRequest +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Receives the CONNECT request from the host, which indicates that the +** bootloader should be activated and, if so, activates it. +** +****************************************************************************************/ +void BootComCheckActivationRequest(void) +{ + unsigned char data[2]; + + /* check if a new message was received */ + if ((CAN1SR & CAN_RBS) == 0) + { + return; + } + /* see if this is the message identifier that we are interested in */ + if (CAN1RID != BOOT_COM_CAN_RX_MSG_ID) + { + return; + } + /* store the message data */ + data[0] = (unsigned char)CAN1RDA; + data[1] = (unsigned char)(CAN1RDA >> 8); + /* release the receive buffer */ + CAN1CMR = CAN_RRB; + /* check if this was an XCP CONNECT command */ + if ((data[0] == 0xff) && (data[1] == 0x00)) + { + /* connection request received so start the bootloader */ + BootActivate(); + } +} /*** end of BootComCheckActivationRequest ***/ +#endif /* BOOT_COM_CAN_ENABLE > 0 */ + + +/*********************************** end of boot.c *************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/boot.h b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/boot.h new file mode 100644 index 00000000..92789052 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/boot.h @@ -0,0 +1,42 @@ +/**************************************************************************************** +| Description: demo program bootloader interface header file +| File Name: boot.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef BOOT_H +#define BOOT_H + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void BootComInit(void); +void BootComCheckActivationRequest(void); + + +#endif /* BOOT_H */ +/*********************************** end of boot.h *************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cmd/build.bat b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cmd/build.bat new file mode 100644 index 00000000..44c0c1b8 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cmd/build.bat @@ -0,0 +1,2 @@ +@echo off +make --directory=../ all diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cmd/clean.bat b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cmd/clean.bat new file mode 100644 index 00000000..32c4b5f2 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cmd/clean.bat @@ -0,0 +1,2 @@ +@echo off +make --directory=../ clean diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cstart.s b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cstart.s new file mode 100644 index 00000000..dd3af60a --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/cstart.s @@ -0,0 +1,136 @@ +/**************************************************************************************** +| Description: demo program C-startup assembly file +| File Name: cstart.s +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/* stack Sizes */ +.set UND_STACK_SIZE, 0x00000100 /* stack for "undef" interrupts is 4 bytes */ +.set ABT_STACK_SIZE, 0x00000100 /* stack for "abort" interrupts is 4 bytes */ +.set FIQ_STACK_SIZE, 0x00000100 /* stack for "FIQ" interrupts is 4 bytes */ +.set IRQ_STACK_SIZE, 0X00000100 /* stack for "IRQ" normal interrupts is 4 bytes */ +.set SVC_STACK_SIZE, 0x00000100 /* stack for "SVC" supervisor mode is 4 bytes */ + +/* mode bits and Interrupt (I & F) flags in program status registers (PSRs) */ +.set MODE_USR, 0x10 /* Normal User Mode */ +.set MODE_FIQ, 0x11 /* FIQ Processing Fast Interrupts Mode */ +.set MODE_IRQ, 0x12 /* IRQ Processing Standard Interrupts Mode */ +.set MODE_SVC, 0x13 /* Supervisor Processing Software Interrupts Mode */ +.set MODE_ABT, 0x17 /* Abort Processing memory Faults Mode */ +.set MODE_UND, 0x1B /* Undefined Processing Undefined Instructions Mode */ +.set MODE_SYS, 0x1F /* System Running Priviledged OS Tasks Mode */ +.set I_BIT, 0x80 /* when I bit is set, IRQ is disabled */ +.set F_BIT, 0x40 /* when F bit is set, FIQ is disabled */ + + +.text +.arm + +.global Reset_Handler +.global _startup +.func _startup + +_startup: +/**************************************************************************************** +* Interrupt vector table +****************************************************************************************/ +_vectors: ldr PC, Reset_Addr /* point to Reset_Handler address */ + ldr PC, Undef_Addr /* point to UNDEF_ISR address */ + ldr PC, SWI_Addr /* point to SWI_ISR address */ + ldr PC, PAbt_Addr /* point to UNDEF_ISR address */ + ldr PC, DAbt_Addr /* point to UNDEF_ISR address */ + nop /* reserved for OpenBLT checksum */ + ldr PC, [PC,#-0xFF0] /* point to VIC table */ + ldr PC, FIQ_Addr /* point to FIQ_ISR address */ + +Reset_Addr: .word Reset_Handler /* defined in this module below */ +Undef_Addr: .word UNDEF_ISR /* defined in vectors.c */ +SWI_Addr: .word SWI_ISR /* defined in vectors.c */ +PAbt_Addr: .word UNDEF_ISR /* defined in vectors.c */ +DAbt_Addr: .word UNDEF_ISR /* defined in vectors.c */ + .word 0 +IRQ_Addr: .word 0 +FIQ_Addr: .word FIQ_ISR /* defined in vectors.c */ + + +/**************************************************************************************** +** NAME: Reset_Handler +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Reset interrupt service routine. Configures the stack for each mode, +** disables the IRQ and FIQ interrupts, initializes RAM and jumps to +** function main. +** +****************************************************************************************/ +Reset_Handler: + /* setup a stack and disable interrupts for each mode */ + ldr r0, =_stack_end + msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */ + mov sp, r0 + sub r0, r0, #UND_STACK_SIZE + msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */ + mov sp, r0 + sub r0, r0, #ABT_STACK_SIZE + msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */ + mov sp, r0 + sub r0, r0, #FIQ_STACK_SIZE + msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */ + mov sp, r0 + sub r0, r0, #IRQ_STACK_SIZE + msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */ + mov sp, r0 + sub r0, r0, #SVC_STACK_SIZE + msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* User Mode */ + mov sp, r0 + /* copy .data section (Copy from ROM to RAM) */ + ldr R1, =_etext + ldr R2, =_data + ldr R3, =_edata +1: cmp R2, R3 + ldrlo R0, [R1], #4 + strlo R0, [R2], #4 + blo 1b + /* clear .bss section (Zero init) */ + mov R0, #0 + ldr R1, =_bss_start + ldr R2, =_bss_end +2: cmp R1, R2 + strlo R0, [R1], #4 + blo 2b + /* start bootloader program by jumping to main() */ + b main +/*** end of Reset_Handler ***/ +.endfunc + + +.end +/*********************************** end of cstart.s ***********************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/header.h b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/header.h new file mode 100644 index 00000000..1a21e96e --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/header.h @@ -0,0 +1,46 @@ +/**************************************************************************************** +| Description: generic header file +| File Name: header.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef HEADER_H +#define HEADER_H + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "../Boot/config.h" /* bootloader configuration */ +#include "lpc2294.h" /* CPU register definitions */ +#include "boot.h" /* bootloader interface driver */ +#include "irq.h" /* IRQ driver */ +#include "led.h" /* LED driver */ +#include "timer.h" /* Timer driver */ + + +#endif /* HEADER_H */ +/*********************************** end of header.h ***********************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/DemoProg.project b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/DemoProg.project new file mode 100644 index 00000000..6d9b215c --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/DemoProg.project @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + break main +continue + + + + + + + make clean + make + + + + None + $(WorkspacePath)/.. + + + + + + + + + + + + + + + + + + + + + + + make clean + make + + + + None + $(WorkspacePath) + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/DemoProg.workspace b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/DemoProg.workspace new file mode 100644 index 00000000..4060139b --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/DemoProg.workspace @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/readme.txt b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/readme.txt new file mode 100644 index 00000000..8a340a19 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/ide/readme.txt @@ -0,0 +1,4 @@ +Integrated Development Environment +---------------------------------- +Codelite was used as the editor during the development of this software program. This directory contains the Codelite +workspace and project files. Codelite is a cross platform open source C/C++ IDE, available at http://www.codelite.org/. \ No newline at end of file diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/irq.c b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/irq.c new file mode 100644 index 00000000..ceec7732 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/irq.c @@ -0,0 +1,140 @@ +/**************************************************************************************** +| Description: IRQ driver source file +| File Name: irq.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "header.h" /* generic header */ + + +/**************************************************************************************** +* Local data definitions +****************************************************************************************/ +static unsigned long oldInterruptStatus; /* used for global interrupt en/disable */ +static unsigned char interruptNesting = 0; /* used for global interrupt en/disable */ + + +/**************************************************************************************** +** NAME: IrqGetCPSR +** PARAMETER: none +** RETURN VALUE: CPSR value +** DESCRIPTION: Obtains current value of CPSR CPU register. +** NOTE: Derived from a sample by R O Software that is Copyright 2004, +** R O SoftWare, and can be used for hobby or commercial purposes. +** +****************************************************************************************/ +static unsigned long IrqGetCPSR(void) +{ + unsigned long retval; + asm volatile (" mrs %0, cpsr" : "=r" (retval) : /* no inputs */ ); + return retval; +} /*** end of IrqGetCPSR ***/ + + +/**************************************************************************************** +** NAME: IrqSetCPSR +** PARAMETER: CPSR value +** RETURN VALUE: none +** DESCRIPTION: Update value of CPSR CPU register. +** NOTE: Derived from a sample by R O Software that is Copyright 2004, +** R O SoftWare, and can be used for hobby or commercial purposes. +** +****************************************************************************************/ +static void IrqSetCPSR(unsigned long val) +{ + asm volatile (" msr cpsr, %0" : /* no outputs */ : "r" (val) ); +} /*** end of IrqSetCPSR ***/ + + +/**************************************************************************************** +** NAME: IrqInterruptEnable +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Enables the generation IRQ interrupts. Typically called once during +** software startup after completion of the initialization. +** +****************************************************************************************/ +void IrqInterruptEnable(void) +{ + unsigned _cpsr; + + _cpsr = IrqGetCPSR(); + IrqSetCPSR(_cpsr & ~0x00000080); +} /*** end of IrqInterruptEnable ***/ + + +/**************************************************************************************** +** NAME: HwInterruptDisable +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Disables the generation IRQ interrupts and stores information on +** whether or not the interrupts were already disabled before explicitly +** disabling them with this function. Normally used as a pair together +** with IrqInterruptRestore during a critical section. +** +****************************************************************************************/ +void IrqInterruptDisable(void) +{ + unsigned long _cpsr; + + if (interruptNesting == 0) + { + _cpsr = IrqGetCPSR(); + IrqSetCPSR(_cpsr | 0x00000080); + oldInterruptStatus = _cpsr; + } + interruptNesting++; +} /*** end of IrqInterruptDisable ***/ + + +/**************************************************************************************** +** NAME: IrqInterruptRestore +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Restore the generation IRQ interrupts to the setting it had prior to +** calling IrqInterruptDisable. Normally used as a pair together with +** IrqInterruptDisable during a critical section. +** +****************************************************************************************/ +void IrqInterruptRestore(void) +{ + unsigned _cpsr; + + interruptNesting--; + if (interruptNesting == 0) + { + _cpsr = IrqGetCPSR(); + IrqSetCPSR((_cpsr & ~0x00000080) | (oldInterruptStatus & 0x00000080)); + } +} /*** end of IrqInterruptRestore ***/ + + +/*********************************** end of irq.c **************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/irq.h b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/irq.h new file mode 100644 index 00000000..9f12faf4 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/irq.h @@ -0,0 +1,43 @@ +/**************************************************************************************** +| Description: IRQ driver header file +| File Name: irq.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef IRQ_H +#define IRQ_H + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void IrqInterruptEnable(void); +void IrqInterruptDisable(void); +void IrqInterruptRestore(void); + + +#endif /* IRQ_H */ +/*********************************** end of irq.h **************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/led.c b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/led.c new file mode 100644 index 00000000..7e579999 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/led.c @@ -0,0 +1,100 @@ +/**************************************************************************************** +| Description: LED driver source file +| File Name: led.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "header.h" /* generic header */ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +#define LED_TOGGLE_MS (500) /* toggle interval time in millisecodns */ + + +/**************************************************************************************** +** NAME: LedInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the LED. +** +****************************************************************************************/ +void LedInit(void) +{ + /* set io pins for led P1.23 */ + IO1DIR |= 0x00800000; + /* turn the led off */ + IO1SET = 0x00800000; +} /*** end of LedInit ***/ + + +/**************************************************************************************** +** NAME: LedToggle +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Toggles the LED at a fixed time interval. +** +****************************************************************************************/ +void LedToggle(void) +{ + static unsigned char led_toggle_state = 0; + static unsigned long timer_counter_last = 0; + unsigned long timer_counter_now; + + /* check if toggle interval time passed */ + timer_counter_now = TimerGet(); + if ( (timer_counter_now - timer_counter_last) < LED_TOGGLE_MS) + { + /* not yet time to toggle */ + return; + } + + /* determine toggle action */ + if (led_toggle_state == 0) + { + led_toggle_state = 1; + /* turn the LED on */ + IO1CLR = 0x00800000; + } + else + { + led_toggle_state = 0; + /* turn the LED off */ + IO1SET = 0x00800000; + } + + /* store toggle time to determine next toggle interval */ + timer_counter_last = timer_counter_now; +} /*** end of LedToggle ***/ + + +/*********************************** end of led.c **************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/led.h b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/led.h new file mode 100644 index 00000000..f69b6a44 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/led.h @@ -0,0 +1,42 @@ +/**************************************************************************************** +| Description: LED driver header file +| File Name: led.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef LED_H +#define LED_H + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void LedInit(void); +void LedToggle(void); + + +#endif /* LED_H */ +/*********************************** end of led.h **************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/lpc2294.h b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/lpc2294.h new file mode 100644 index 00000000..209015fb --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/lpc2294.h @@ -0,0 +1,409 @@ +/**************************************************************************************** +| Description: NXP LPC2294 register definitions +| File Name: lpc2294.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef LPC2294_H +#define LPC2294_H + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/* EXTERNAL MEMORY CONTROLLER (EMC) */ +#define BCFG0 (*((volatile unsigned long *) 0xFFE00000)) /* lpc22xx only */ +#define BCFG1 (*((volatile unsigned long *) 0xFFE00004)) /* lpc22xx only */ +#define BCFG2 (*((volatile unsigned long *) 0xFFE00008)) /* lpc22xx only */ +#define BCFG3 (*((volatile unsigned long *) 0xFFE0000C)) /* lpc22xx only */ + +/* External Interrupts */ +#define EXTINT (*((volatile unsigned char *) 0xE01FC140)) +#define EXTWAKE (*((volatile unsigned char *) 0xE01FC144)) +#define EXTMODE (*((volatile unsigned char *) 0xE01FC148)) /* no in lpc210x*/ +#define EXTPOLAR (*((volatile unsigned char *) 0xE01FC14C)) /* no in lpc210x*/ + +/* SMemory mapping control. */ +#define MEMMAP (*((volatile unsigned long *) 0xE01FC040)) + +/* Phase Locked Loop (PLL) */ +#define PLLCON (*((volatile unsigned char *) 0xE01FC080)) +#define PLLCFG (*((volatile unsigned char *) 0xE01FC084)) +#define PLLSTAT (*((volatile unsigned short*) 0xE01FC088)) +#define PLLFEED (*((volatile unsigned char *) 0xE01FC08C)) + +/* Power Control */ +#define PCON (*((volatile unsigned char *) 0xE01FC0C0)) +#define PCONP (*((volatile unsigned long *) 0xE01FC0C4)) + +/* VPB Divider */ +#define VPBDIV (*((volatile unsigned char *) 0xE01FC100)) + +/* Memory Accelerator Module (MAM) */ +#define MAMCR (*((volatile unsigned char *) 0xE01FC000)) +#define MAMTIM (*((volatile unsigned char *) 0xE01FC004)) + +/* Vectored Interrupt Controller (VIC) */ +#define VICIRQStatus (*((volatile unsigned long *) 0xFFFFF000)) +#define VICFIQStatus (*((volatile unsigned long *) 0xFFFFF004)) +#define VICRawIntr (*((volatile unsigned long *) 0xFFFFF008)) +#define VICIntSelect (*((volatile unsigned long *) 0xFFFFF00C)) +#define VICIntEnable (*((volatile unsigned long *) 0xFFFFF010)) +#define VICIntEnClr (*((volatile unsigned long *) 0xFFFFF014)) +#define VICSoftInt (*((volatile unsigned long *) 0xFFFFF018)) +#define VICSoftIntClear (*((volatile unsigned long *) 0xFFFFF01C)) +#define VICProtection (*((volatile unsigned long *) 0xFFFFF020)) +#define VICVectAddr (*((volatile unsigned long *) 0xFFFFF030)) +#define VICDefVectAddr (*((volatile unsigned long *) 0xFFFFF034)) +#define VICVectAddr0 (*((volatile unsigned long *) 0xFFFFF100)) +#define VICVectAddr1 (*((volatile unsigned long *) 0xFFFFF104)) +#define VICVectAddr2 (*((volatile unsigned long *) 0xFFFFF108)) +#define VICVectAddr3 (*((volatile unsigned long *) 0xFFFFF10C)) +#define VICVectAddr4 (*((volatile unsigned long *) 0xFFFFF110)) +#define VICVectAddr5 (*((volatile unsigned long *) 0xFFFFF114)) +#define VICVectAddr6 (*((volatile unsigned long *) 0xFFFFF118)) +#define VICVectAddr7 (*((volatile unsigned long *) 0xFFFFF11C)) +#define VICVectAddr8 (*((volatile unsigned long *) 0xFFFFF120)) +#define VICVectAddr9 (*((volatile unsigned long *) 0xFFFFF124)) +#define VICVectAddr10 (*((volatile unsigned long *) 0xFFFFF128)) +#define VICVectAddr11 (*((volatile unsigned long *) 0xFFFFF12C)) +#define VICVectAddr12 (*((volatile unsigned long *) 0xFFFFF130)) +#define VICVectAddr13 (*((volatile unsigned long *) 0xFFFFF134)) +#define VICVectAddr14 (*((volatile unsigned long *) 0xFFFFF138)) +#define VICVectAddr15 (*((volatile unsigned long *) 0xFFFFF13C)) +#define VICVectCntl0 (*((volatile unsigned long *) 0xFFFFF200)) +#define VICVectCntl1 (*((volatile unsigned long *) 0xFFFFF204)) +#define VICVectCntl2 (*((volatile unsigned long *) 0xFFFFF208)) +#define VICVectCntl3 (*((volatile unsigned long *) 0xFFFFF20C)) +#define VICVectCntl4 (*((volatile unsigned long *) 0xFFFFF210)) +#define VICVectCntl5 (*((volatile unsigned long *) 0xFFFFF214)) +#define VICVectCntl6 (*((volatile unsigned long *) 0xFFFFF218)) +#define VICVectCntl7 (*((volatile unsigned long *) 0xFFFFF21C)) +#define VICVectCntl8 (*((volatile unsigned long *) 0xFFFFF220)) +#define VICVectCntl9 (*((volatile unsigned long *) 0xFFFFF224)) +#define VICVectCntl10 (*((volatile unsigned long *) 0xFFFFF228)) +#define VICVectCntl11 (*((volatile unsigned long *) 0xFFFFF22C)) +#define VICVectCntl12 (*((volatile unsigned long *) 0xFFFFF230)) +#define VICVectCntl13 (*((volatile unsigned long *) 0xFFFFF234)) +#define VICVectCntl14 (*((volatile unsigned long *) 0xFFFFF238)) +#define VICVectCntl15 (*((volatile unsigned long *) 0xFFFFF23C)) + +/* Pin Connect Block */ +#define PINSEL0 (*((volatile unsigned long *) 0xE002C000)) +#define PINSEL1 (*((volatile unsigned long *) 0xE002C004)) +#define PINSEL2 (*((volatile unsigned long *) 0xE002C014)) /* no in lpc210x*/ + +/* General Purpose Input/Output (GPIO) */ +#define IOPIN (*((volatile unsigned long *) 0xE0028000)) /* lpc210x only */ +#define IOSET (*((volatile unsigned long *) 0xE0028004)) /* lpc210x only */ +#define IODIR (*((volatile unsigned long *) 0xE0028008)) /* lpc210x only */ +#define IOCLR (*((volatile unsigned long *) 0xE002800C)) /* lpc210x only */ + +#define IO0PIN (*((volatile unsigned long *) 0xE0028000)) /* no in lpc210x*/ +#define IO0SET (*((volatile unsigned long *) 0xE0028004)) /* no in lpc210x*/ +#define IO0DIR (*((volatile unsigned long *) 0xE0028008)) /* no in lpc210x*/ +#define IO0CLR (*((volatile unsigned long *) 0xE002800C)) /* no in lpc210x*/ + +#define IO1PIN (*((volatile unsigned long *) 0xE0028010)) /* no in lpc210x*/ +#define IO1SET (*((volatile unsigned long *) 0xE0028014)) /* no in lpc210x*/ +#define IO1DIR (*((volatile unsigned long *) 0xE0028018)) /* no in lpc210x*/ +#define IO1CLR (*((volatile unsigned long *) 0xE002801C)) /* no in lpc210x*/ + +#define IO2PIN (*((volatile unsigned long *) 0xE0028020)) /* lpc22xx only */ +#define IO2SET (*((volatile unsigned long *) 0xE0028024)) /* lpc22xx only */ +#define IO2DIR (*((volatile unsigned long *) 0xE0028028)) /* lpc22xx only */ +#define IO2CLR (*((volatile unsigned long *) 0xE002802C)) /* lpc22xx only */ + +#define IO3PIN (*((volatile unsigned long *) 0xE0028030)) /* lpc22xx only */ +#define IO3SET (*((volatile unsigned long *) 0xE0028034)) /* lpc22xx only */ +#define IO3DIR (*((volatile unsigned long *) 0xE0028038)) /* lpc22xx only */ +#define IO3CLR (*((volatile unsigned long *) 0xE002803C)) /* lpc22xx only */ + +/* Universal Asynchronous Receiver Transmitter 0 (UART0) */ +#define U0RBR (*((volatile unsigned char *) 0xE000C000)) +#define U0THR (*((volatile unsigned char *) 0xE000C000)) +#define U0IER (*((volatile unsigned char *) 0xE000C004)) +#define U0IIR (*((volatile unsigned char *) 0xE000C008)) +#define U0FCR (*((volatile unsigned char *) 0xE000C008)) +#define U0LCR (*((volatile unsigned char *) 0xE000C00C)) +#define U0LSR (*((volatile unsigned char *) 0xE000C014)) +#define U0SCR (*((volatile unsigned char *) 0xE000C01C)) +#define U0DLL (*((volatile unsigned char *) 0xE000C000)) +#define U0DLM (*((volatile unsigned char *) 0xE000C004)) + +/* Universal Asynchronous Receiver Transmitter 1 (UART1) */ +#define U1RBR (*((volatile unsigned char *) 0xE0010000)) +#define U1THR (*((volatile unsigned char *) 0xE0010000)) +#define U1IER (*((volatile unsigned char *) 0xE0010004)) +#define U1IIR (*((volatile unsigned char *) 0xE0010008)) +#define U1FCR (*((volatile unsigned char *) 0xE0010008)) +#define U1LCR (*((volatile unsigned char *) 0xE001000C)) +#define U1MCR (*((volatile unsigned char *) 0xE0010010)) +#define U1LSR (*((volatile unsigned char *) 0xE0010014)) +#define U1MSR (*((volatile unsigned char *) 0xE0010018)) +#define U1SCR (*((volatile unsigned char *) 0xE001001C)) +#define U1DLL (*((volatile unsigned char *) 0xE0010000)) +#define U1DLM (*((volatile unsigned char *) 0xE0010004)) + +/* I2C (8/16 bit data bus) */ +#define I2CONSET (*((volatile unsigned long *) 0xE001C000)) +#define I2STAT (*((volatile unsigned long *) 0xE001C004)) +#define I2DAT (*((volatile unsigned long *) 0xE001C008)) +#define I2ADR (*((volatile unsigned long *) 0xE001C00C)) +#define I2SCLH (*((volatile unsigned long *) 0xE001C010)) +#define I2SCLL (*((volatile unsigned long *) 0xE001C014)) +#define I2CONCLR (*((volatile unsigned long *) 0xE001C018)) + +/* SPI (Serial Peripheral Interface) */ + /* only for lpc210x*/ +#define SPI_SPCR (*((volatile unsigned char *) 0xE0020000)) +#define SPI_SPSR (*((volatile unsigned char *) 0xE0020004)) +#define SPI_SPDR (*((volatile unsigned char *) 0xE0020008)) +#define SPI_SPCCR (*((volatile unsigned char *) 0xE002000C)) +#define SPI_SPINT (*((volatile unsigned char *) 0xE002001C)) + +#define S0PCR (*((volatile unsigned char *) 0xE0020000)) /* no in lpc210x*/ +#define S0PSR (*((volatile unsigned char *) 0xE0020004)) /* no in lpc210x*/ +#define S0PDR (*((volatile unsigned char *) 0xE0020008)) /* no in lpc210x*/ +#define S0PCCR (*((volatile unsigned char *) 0xE002000C)) /* no in lpc210x*/ +#define S0PINT (*((volatile unsigned char *) 0xE002001C)) /* no in lpc210x*/ + +#define S1PCR (*((volatile unsigned char *) 0xE0030000)) /* no in lpc210x*/ +#define S1PSR (*((volatile unsigned char *) 0xE0030004)) /* no in lpc210x*/ +#define S1PDR (*((volatile unsigned char *) 0xE0030008)) /* no in lpc210x*/ +#define S1PCCR (*((volatile unsigned char *) 0xE003000C)) /* no in lpc210x*/ +#define S1PINT (*((volatile unsigned char *) 0xE003001C)) /* no in lpc210x*/ + +/* CAN CONTROLLERS AND ACCEPTANCE FILTER */ +#define CAN1MOD (*((volatile unsigned long *) 0xE0044000)) /* All CAN Parts */ +#define CAN1CMR (*((volatile unsigned long *) 0xE0044004)) /* All CAN Parts */ +#define CAN1GSR (*((volatile unsigned long *) 0xE0044008)) /* All CAN Parts */ +#define CAN1ICR (*((volatile unsigned long *) 0xE004400C)) /* All CAN Parts */ +#define CAN1IER (*((volatile unsigned long *) 0xE0044010)) /* All CAN Parts */ +#define CAN1BTR (*((volatile unsigned long *) 0xE0044014)) /* All CAN Parts */ +#define CAN1EWL (*((volatile unsigned long *) 0xE0044018)) /* All CAN Parts */ +#define CAN1SR (*((volatile unsigned long *) 0xE004401C)) /* All CAN Parts */ +#define CAN1RFS (*((volatile unsigned long *) 0xE0044020)) /* All CAN Parts */ +#define CAN1RID (*((volatile unsigned long *) 0xE0044024)) /* All CAN Parts */ +#define CAN1RDA (*((volatile unsigned long *) 0xE0044028)) /* All CAN Parts */ +#define CAN1RDB (*((volatile unsigned long *) 0xE004402C)) /* All CAN Parts */ +#define CAN1TFI1 (*((volatile unsigned long *) 0xE0044030)) /* All CAN Parts */ +#define CAN1TID1 (*((volatile unsigned long *) 0xE0044034)) /* All CAN Parts */ +#define CAN1TDA1 (*((volatile unsigned long *) 0xE0044038)) /* All CAN Parts */ +#define CAN1TDB1 (*((volatile unsigned long *) 0xE004403C)) /* All CAN Parts */ +#define CAN1TFI2 (*((volatile unsigned long *) 0xE0044040)) /* All CAN Parts */ +#define CAN1TID2 (*((volatile unsigned long *) 0xE0044044)) /* All CAN Parts */ +#define CAN1TDA2 (*((volatile unsigned long *) 0xE0044048)) /* All CAN Parts */ +#define CAN1TDB2 (*((volatile unsigned long *) 0xE004404C)) /* All CAN Parts */ +#define CAN1TFI3 (*((volatile unsigned long *) 0xE0044050)) /* All CAN Parts */ +#define CAN1TID3 (*((volatile unsigned long *) 0xE0044054)) /* All CAN Parts */ +#define CAN1TDA3 (*((volatile unsigned long *) 0xE0044058)) /* All CAN Parts */ +#define CAN1TDB3 (*((volatile unsigned long *) 0xE004405C)) /* All CAN Parts */ + +#define CAN2MOD (*((volatile unsigned long *) 0xE0048000)) /* All CAN Parts */ +#define CAN2CMR (*((volatile unsigned long *) 0xE0048004)) /* All CAN Parts */ +#define CAN2GSR (*((volatile unsigned long *) 0xE0048008)) /* All CAN Parts */ +#define CAN2ICR (*((volatile unsigned long *) 0xE004800C)) /* All CAN Parts */ +#define CAN2IER (*((volatile unsigned long *) 0xE0048010)) /* All CAN Parts */ +#define CAN2BTR (*((volatile unsigned long *) 0xE0048014)) /* All CAN Parts */ +#define CAN2EWL (*((volatile unsigned long *) 0xE0048018)) /* All CAN Parts */ +#define CAN2SR (*((volatile unsigned long *) 0xE004801C)) /* All CAN Parts */ +#define CAN2RFS (*((volatile unsigned long *) 0xE0048020)) /* All CAN Parts */ +#define CAN2RID (*((volatile unsigned long *) 0xE0048024)) /* All CAN Parts */ +#define CAN2RDA (*((volatile unsigned long *) 0xE0048028)) /* All CAN Parts */ +#define CAN2RDB (*((volatile unsigned long *) 0xE004802C)) /* All CAN Parts */ +#define CAN2TFI1 (*((volatile unsigned long *) 0xE0048030)) /* All CAN Parts */ +#define CAN2TID1 (*((volatile unsigned long *) 0xE0048034)) /* All CAN Parts */ +#define CAN2TDA1 (*((volatile unsigned long *) 0xE0048038)) /* All CAN Parts */ +#define CAN2TDB1 (*((volatile unsigned long *) 0xE004803C)) /* All CAN Parts */ +#define CAN2TFI2 (*((volatile unsigned long *) 0xE0048040)) /* All CAN Parts */ +#define CAN2TID2 (*((volatile unsigned long *) 0xE0048044)) /* All CAN Parts */ +#define CAN2TDA2 (*((volatile unsigned long *) 0xE0048048)) /* All CAN Parts */ +#define CAN2TDB2 (*((volatile unsigned long *) 0xE004804C)) /* All CAN Parts */ +#define CAN2TFI3 (*((volatile unsigned long *) 0xE0048050)) /* All CAN Parts */ +#define CAN2TID3 (*((volatile unsigned long *) 0xE0048054)) /* All CAN Parts */ +#define CAN2TDA3 (*((volatile unsigned long *) 0xE0048058)) /* All CAN Parts */ +#define CAN2TDB3 (*((volatile unsigned long *) 0xE004805C)) /* All CAN Parts */ + +#define CAN3MOD (*((volatile unsigned long *) 0xE004C000)) /* lpc2194\lpc2294 only */ +#define CAN3CMR (*((volatile unsigned long *) 0xE004C004)) /* lpc2194\lpc2294 only */ +#define CAN3GSR (*((volatile unsigned long *) 0xE004C008)) /* lpc2194\lpc2294 only */ +#define CAN3ICR (*((volatile unsigned long *) 0xE004C00C)) /* lpc2194\lpc2294 only */ +#define CAN3IER (*((volatile unsigned long *) 0xE004C010)) /* lpc2194\lpc2294 only */ +#define CAN3BTR (*((volatile unsigned long *) 0xE004C014)) /* lpc2194\lpc2294 only */ +#define CAN3EWL (*((volatile unsigned long *) 0xE004C018)) /* lpc2194\lpc2294 only */ +#define CAN3SR (*((volatile unsigned long *) 0xE004C01C)) /* lpc2194\lpc2294 only */ +#define CAN3RFS (*((volatile unsigned long *) 0xE004C020)) /* lpc2194\lpc2294 only */ +#define CAN3RID (*((volatile unsigned long *) 0xE004C024)) /* lpc2194\lpc2294 only */ +#define CAN3RDA (*((volatile unsigned long *) 0xE004C028)) /* lpc2194\lpc2294 only */ +#define CAN3RDB (*((volatile unsigned long *) 0xE004C02C)) /* lpc2194\lpc2294 only */ +#define CAN3TFI1 (*((volatile unsigned long *) 0xE004C030)) /* lpc2194\lpc2294 only */ +#define CAN3TID1 (*((volatile unsigned long *) 0xE004C034)) /* lpc2194\lpc2294 only */ +#define CAN3TDA1 (*((volatile unsigned long *) 0xE004C038)) /* lpc2194\lpc2294 only */ +#define CAN3TDB1 (*((volatile unsigned long *) 0xE004C03C)) /* lpc2194\lpc2294 only */ +#define CAN3TFI2 (*((volatile unsigned long *) 0xE004C040)) /* lpc2194\lpc2294 only */ +#define CAN3TID2 (*((volatile unsigned long *) 0xE004C044)) /* lpc2194\lpc2294 only */ +#define CAN3TDA2 (*((volatile unsigned long *) 0xE004C048)) /* lpc2194\lpc2294 only */ +#define CAN3TDB2 (*((volatile unsigned long *) 0xE004C04C)) /* lpc2194\lpc2294 only */ +#define CAN3TFI3 (*((volatile unsigned long *) 0xE004C050)) /* lpc2194\lpc2294 only */ +#define CAN3TID3 (*((volatile unsigned long *) 0xE004C054)) /* lpc2194\lpc2294 only */ +#define CAN3TDA3 (*((volatile unsigned long *) 0xE004C058)) /* lpc2194\lpc2294 only */ +#define CAN3TDB3 (*((volatile unsigned long *) 0xE004C05C)) /* lpc2194\lpc2294 only */ + +#define CAN4MOD (*((volatile unsigned long *) 0xE0050000)) /* lpc2194\lpc2294 only */ +#define CAN4CMR (*((volatile unsigned long *) 0xE0050004)) /* lpc2194\lpc2294 only */ +#define CAN4GSR (*((volatile unsigned long *) 0xE0050008)) /* lpc2194\lpc2294 only */ +#define CAN4ICR (*((volatile unsigned long *) 0xE005000C)) /* lpc2194\lpc2294 only */ +#define CAN4IER (*((volatile unsigned long *) 0xE0050010)) /* lpc2194\lpc2294 only */ +#define CAN4BTR (*((volatile unsigned long *) 0xE0050014)) /* lpc2194\lpc2294 only */ +#define CAN4EWL (*((volatile unsigned long *) 0xE0050018)) /* lpc2194\lpc2294 only */ +#define CAN4SR (*((volatile unsigned long *) 0xE005001C)) /* lpc2194\lpc2294 only */ +#define CAN4RFS (*((volatile unsigned long *) 0xE0050020)) /* lpc2194\lpc2294 only */ +#define CAN4RID (*((volatile unsigned long *) 0xE0050024)) /* lpc2194\lpc2294 only */ +#define CAN4RDA (*((volatile unsigned long *) 0xE0050028)) /* lpc2194\lpc2294 only */ +#define CAN4RDB (*((volatile unsigned long *) 0xE005002C)) /* lpc2194\lpc2294 only */ +#define CAN4TFI1 (*((volatile unsigned long *) 0xE0050030)) /* lpc2194\lpc2294 only */ +#define CAN4TID1 (*((volatile unsigned long *) 0xE0050034)) /* lpc2194\lpc2294 only */ +#define CAN4TDA1 (*((volatile unsigned long *) 0xE0050038)) /* lpc2194\lpc2294 only */ +#define CAN4TDB1 (*((volatile unsigned long *) 0xE005003C)) /* lpc2194\lpc2294 only */ +#define CAN4TFI2 (*((volatile unsigned long *) 0xE0050040)) /* lpc2194\lpc2294 only */ +#define CAN4TID2 (*((volatile unsigned long *) 0xE0050044)) /* lpc2194\lpc2294 only */ +#define CAN4TDA2 (*((volatile unsigned long *) 0xE0050048)) /* lpc2194\lpc2294 only */ +#define CAN4TDB2 (*((volatile unsigned long *) 0xE005004C)) /* lpc2194\lpc2294 only */ +#define CAN4TFI3 (*((volatile unsigned long *) 0xE0050050)) /* lpc2194\lpc2294 only */ +#define CAN4TID3 (*((volatile unsigned long *) 0xE0050054)) /* lpc2194\lpc2294 only */ +#define CAN4TDA3 (*((volatile unsigned long *) 0xE0050058)) /* lpc2194\lpc2294 only */ +#define CAN4TDB3 (*((volatile unsigned long *) 0xE005005C)) /* lpc2194\lpc2294 only */ + + +#define CANTxSR (*((volatile unsigned long *) 0xE0040000)) /* ALL CAN Parts */ +#define CANRxSR (*((volatile unsigned long *) 0xE0040004)) /* ALL CAN Parts */ +#define CANMSR (*((volatile unsigned long *) 0xE0040008)) /* ALL CAN Parts */ + +#define CANAFMR (*((volatile unsigned char *) 0xE003C000)) /* ALL CAN Parts */ +#define CANSFF_sa (*((volatile unsigned short*) 0xE003C004)) /* ALL CAN Parts */ +#define CANSFF_GRP_sa (*((volatile unsigned short*) 0xE003C008)) /* ALL CAN Parts */ +#define CANEFF_sa (*((volatile unsigned short*) 0xE003C00C)) /* ALL CAN Parts */ +#define CANEFF_GRP_sa (*((volatile unsigned short*) 0xE003C010)) /* ALL CAN Parts */ +#define CANENDofTable (*((volatile unsigned short*) 0xE003C014)) /* ALL CAN Parts */ +#define CANLUTerrAd (*((volatile unsigned short*) 0xE003C018)) /* ALL CAN Parts */ +#define CANLUTerr (*((volatile unsigned char *) 0xE003C01C)) /* ALL CAN Parts */ + + +/* Timer 0 */ +#define T0IR (*((volatile unsigned long *) 0xE0004000)) +#define T0TCR (*((volatile unsigned long *) 0xE0004004)) +#define T0TC (*((volatile unsigned long *) 0xE0004008)) +#define T0PR (*((volatile unsigned long *) 0xE000400C)) +#define T0PC (*((volatile unsigned long *) 0xE0004010)) +#define T0MCR (*((volatile unsigned long *) 0xE0004014)) +#define T0MR0 (*((volatile unsigned long *) 0xE0004018)) +#define T0MR1 (*((volatile unsigned long *) 0xE000401C)) +#define T0MR2 (*((volatile unsigned long *) 0xE0004020)) +#define T0MR3 (*((volatile unsigned long *) 0xE0004024)) +#define T0CCR (*((volatile unsigned long *) 0xE0004028)) +#define T0CR0 (*((volatile unsigned long *) 0xE000402C)) +#define T0CR1 (*((volatile unsigned long *) 0xE0004030)) +#define T0CR2 (*((volatile unsigned long *) 0xE0004034)) +#define T0CR3 (*((volatile unsigned long *) 0xE0004038)) +#define T0EMR (*((volatile unsigned long *) 0xE000403C)) + +/* Timer 1 */ +#define T1IR (*((volatile unsigned long *) 0xE0008000)) +#define T1TCR (*((volatile unsigned long *) 0xE0008004)) +#define T1TC (*((volatile unsigned long *) 0xE0008008)) +#define T1PR (*((volatile unsigned long *) 0xE000800C)) +#define T1PC (*((volatile unsigned long *) 0xE0008010)) +#define T1MCR (*((volatile unsigned long *) 0xE0008014)) +#define T1MR0 (*((volatile unsigned long *) 0xE0008018)) +#define T1MR1 (*((volatile unsigned long *) 0xE000801C)) +#define T1MR2 (*((volatile unsigned long *) 0xE0008020)) +#define T1MR3 (*((volatile unsigned long *) 0xE0008024)) +#define T1CCR (*((volatile unsigned long *) 0xE0008028)) +#define T1CR0 (*((volatile unsigned long *) 0xE000802C)) +#define T1CR1 (*((volatile unsigned long *) 0xE0008030)) +#define T1CR2 (*((volatile unsigned long *) 0xE0008034)) +#define T1CR3 (*((volatile unsigned long *) 0xE0008038)) +#define T1EMR (*((volatile unsigned long *) 0xE000803C)) + +/* Pulse Width Modulator (PWM) */ +#define PWMIR (*((volatile unsigned long *) 0xE0014000)) +#define PWMTCR (*((volatile unsigned long *) 0xE0014004)) +#define PWMTC (*((volatile unsigned long *) 0xE0014008)) +#define PWMPR (*((volatile unsigned long *) 0xE001400C)) +#define PWMPC (*((volatile unsigned long *) 0xE0014010)) +#define PWMMCR (*((volatile unsigned long *) 0xE0014014)) +#define PWMMR0 (*((volatile unsigned long *) 0xE0014018)) +#define PWMMR1 (*((volatile unsigned long *) 0xE001401C)) +#define PWMMR2 (*((volatile unsigned long *) 0xE0014020)) +#define PWMMR3 (*((volatile unsigned long *) 0xE0014024)) +#define PWMMR4 (*((volatile unsigned long *) 0xE0014040)) +#define PWMMR5 (*((volatile unsigned long *) 0xE0014044)) +#define PWMMR6 (*((volatile unsigned long *) 0xE0014048)) +#define PWMPCR (*((volatile unsigned long *) 0xE001404C)) +#define PWMLER (*((volatile unsigned long *) 0xE0014050)) + +/* A/D CONVERTER */ +#define ADCR (*((volatile unsigned long *) 0xE0034000)) /* no in lpc210x*/ +#define ADDR (*((volatile unsigned long *) 0xE0034004)) /* no in lpc210x*/ + +/* Real Time Clock */ +#define ILR (*((volatile unsigned char *) 0xE0024000)) +#define CTC (*((volatile unsigned short*) 0xE0024004)) +#define CCR (*((volatile unsigned char *) 0xE0024008)) +#define CIIR (*((volatile unsigned char *) 0xE002400C)) +#define AMR (*((volatile unsigned char *) 0xE0024010)) +#define CTIME0 (*((volatile unsigned long *) 0xE0024014)) +#define CTIME1 (*((volatile unsigned long *) 0xE0024018)) +#define CTIME2 (*((volatile unsigned long *) 0xE002401C)) +#define SEC (*((volatile unsigned char *) 0xE0024020)) +#define MIN (*((volatile unsigned char *) 0xE0024024)) +#define HOUR (*((volatile unsigned char *) 0xE0024028)) +#define DOM (*((volatile unsigned char *) 0xE002402C)) +#define DOW (*((volatile unsigned char *) 0xE0024030)) +#define DOY (*((volatile unsigned short*) 0xE0024034)) +#define MONTH (*((volatile unsigned char *) 0xE0024038)) +#define YEAR (*((volatile unsigned short*) 0xE002403C)) +#define ALSEC (*((volatile unsigned char *) 0xE0024060)) +#define ALMIN (*((volatile unsigned char *) 0xE0024064)) +#define ALHOUR (*((volatile unsigned char *) 0xE0024068)) +#define ALDOM (*((volatile unsigned char *) 0xE002406C)) +#define ALDOW (*((volatile unsigned char *) 0xE0024070)) +#define ALDOY (*((volatile unsigned short*) 0xE0024074)) +#define ALMON (*((volatile unsigned char *) 0xE0024078)) +#define ALYEAR (*((volatile unsigned short*) 0xE002407C)) +#define PREINT (*((volatile unsigned short*) 0xE0024080)) +#define PREFRAC (*((volatile unsigned short*) 0xE0024084)) + +/* Watchdog */ +#define WDMOD (*((volatile unsigned char *) 0xE0000000)) +#define WDTC (*((volatile unsigned long *) 0xE0000004)) +#define WDFEED (*((volatile unsigned char *) 0xE0000008)) +#define WDTV (*((volatile unsigned long *) 0xE000000C)) + +#endif /* LPC2294_H */ +/*********************************** end of lpc2294.h **********************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/main.c b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/main.c new file mode 100644 index 00000000..1c4b590a --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/main.c @@ -0,0 +1,151 @@ +/**************************************************************************************** +| Description: demo program application source file +| File Name: main.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "header.h" /* generic header */ + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +static void Init(void); + + +/**************************************************************************************** +** NAME: main +** PARAMETER: none +** RETURN VALUE: program return code +** DESCRIPTION: This is the entry point for the bootloader application and is called +** by the reset interrupt vector after the C-startup routines executed. +** +****************************************************************************************/ +int main(void) +{ + /* initialize the microcontroller */ + Init(); + + /* initialize the bootloader interface */ + BootComInit(); + + /* start the infinite program loop */ + while (1) + { + /* toggle LED with a fixed frequency */ + LedToggle(); + + /* check for bootloader activation request */ + BootComCheckActivationRequest(); + } + + /* program should never get here */ + return 0; +} /*** end of main ***/ + + +/**************************************************************************************** +** NAME: Init +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the microcontroller. The Fpll is set to 60MHz and Fvpb is +** configured equal to Fpll. The GPIO pin of the status LED is configured +** as digital output. +** +****************************************************************************************/ +static void Init(void) +{ + unsigned char m_sel; /* pll multiplier register value */ + unsigned char pll_dividers[] = { 1, 2, 4, 8 }; /* possible pll dividers */ + unsigned char p_sel_cnt; /* loop counter to find p_sel */ + unsigned long f_cco; /* current controller oscillator */ + + /* calculate MSEL: M = round(Fcclk / Fosc) */ + m_sel = (BOOT_CPU_SYSTEM_SPEED_KHZ + ((BOOT_CPU_XTAL_SPEED_KHZ+1)/2)) / \ + BOOT_CPU_XTAL_SPEED_KHZ; + /* value for the PLLCFG register is -1 */ + m_sel--; + + /* find PSEL value so that Fcco(= Fcclk * 2 * P) is in the 156000..320000 kHz range. */ + for (p_sel_cnt=0; p_sel_cnt= 156000) && (f_cco <= 320000) ) + { + /* found a valid pll divider value */ + break; + } + } + + /* set multiplier and divider values */ + PLLCFG = (p_sel_cnt << 5) | m_sel; + PLLFEED = 0xAA; + PLLFEED = 0x55; + /* enable the PLL */ + PLLCON = 0x1; + PLLFEED = 0xAA; + PLLFEED = 0x55; + /* wait for the PLL to lock to set frequency */ + while(!(PLLSTAT & 0x400)) { ; } + /* connect the PLL as the clock source */ + PLLCON = 0x3; + PLLFEED = 0xAA; + PLLFEED = 0x55; + /* enable MAM and set number of clocks used for Flash memory fetch. Recommended: + * Fcclk >= 60 MHz: 4 clock cycles + * Fcclk >= 40 MHz: 3 clock cycles + * Fcclk >= 20 MHz: 2 clock cycles + * Fcclk < 20 MHz: 1 clock cycle + */ + MAMCR = 0x0; +#if (BOOT_CPU_SYSTEM_SPEED_KHZ >= 60) + MAMTIM = 4; +#elif (BOOT_CPU_SYSTEM_SPEED_KHZ >= 40) + MAMTIM = 3; +#elif (BOOT_CPU_SYSTEM_SPEED_KHZ >= 20) + MAMTIM = 2; +#else + MAMTIM = 1; +#endif + MAMCR = 0x2; + /* setting peripheral Clock (pclk) to System Clock (cclk) */ + VPBDIV = 0x1; + /* init the led driver */ + LedInit(); + /* init the timer driver */ + TimerInit(); + /* enable IRQ's */ + IrqInterruptEnable(); +} /*** end of Init ***/ + + +/*********************************** end of main.c *************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/makefile b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/makefile new file mode 100644 index 00000000..bf7e81b1 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/makefile @@ -0,0 +1,144 @@ +#**************************************************************************************** +#| Description: Makefile for NXP LPC2000 using CodeSourcery GNU GCC compiler toolset +#| File Name: makefile +#| +#|--------------------------------------------------------------------------------------- +#| C O P Y R I G H T +#|--------------------------------------------------------------------------------------- +#| Copyright (c) 2011 by Feaser LLC http://www.feaser.com All rights reserved +#| +#|--------------------------------------------------------------------------------------- +#| L I C E N S E +#|--------------------------------------------------------------------------------------- +#| This file is part of OpenBTL. OpenBTL is free software: you can redistribute it and/or +#| modify it under the terms of the GNU General Public License as published by the Free +#| Software Foundation, either version 3 of the License, or (at your option) any later +#| version. +#| +#| OpenBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +#| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +#| PURPOSE. See the GNU General Public License for more details. +#| +#| You should have received a copy of the GNU General Public License along with OpenBTL. +#| If not, see . +#| +#**************************************************************************************** +SHELL = sh + +#|---------------------------------------------------------------------------------------| +#| Configure project name | +#|---------------------------------------------------------------------------------------| +PROJ_NAME=demoprog_olimex_lpc_l2294_20mhz + + +#|---------------------------------------------------------------------------------------| +#| Speficy project source files | +#|---------------------------------------------------------------------------------------| +PROJ_FILES= \ +lpc2294.h \ +vectors.c \ +main.c \ +boot.c \ +boot.h \ +irq.c \ +irq.h \ +led.c \ +led.h \ +timer.c \ +timer.h \ +header.h \ +cstart.s + + +#|---------------------------------------------------------------------------------------| +#| Compiler binaries | +#|---------------------------------------------------------------------------------------| +CC = arm-none-eabi-gcc +LN = arm-none-eabi-gcc +OC = arm-none-eabi-objcopy +OD = arm-none-eabi-objdump +AS = arm-none-eabi-as +SZ = arm-none-eabi-size + + +#|---------------------------------------------------------------------------------------| +#| Extract file names | +#|---------------------------------------------------------------------------------------| +PROJ_ASRCS = $(filter %.s,$(foreach file,$(PROJ_FILES),$(notdir $(file)))) +PROJ_CSRCS = $(filter %.c,$(foreach file,$(PROJ_FILES),$(notdir $(file)))) +PROJ_CHDRS = $(filter %.h,$(foreach file,$(PROJ_FILES),$(notdir $(file)))) +PROJ_CCMPL = $(patsubst %.c,%.cpl,$(PROJ_CSRCS)) +PROJ_ACMPL = $(patsubst %.s,%.cpl,$(PROJ_ASRCS)) + + +#|---------------------------------------------------------------------------------------| +#| Set important path variables | +#|---------------------------------------------------------------------------------------| +VPATH = $(foreach path,$(sort $(foreach file,$(PROJ_FILES),$(dir $(file)))) $(subst \,/,$(OBJ_PATH)),$(path) :) +OBJ_PATH = ./obj +BIN_PATH = ./bin +INC_PATH = $(patsubst %,-I%,$(sort $(foreach file,$(filter %.h,$(PROJ_FILES)),$(dir $(file))))) +INC_PATH += -I. +LIB_PATH = -L. + + +#|---------------------------------------------------------------------------------------| +#| Options for compiler binaries | +#|---------------------------------------------------------------------------------------| +AFLAGS = -ahls -mapcs-32 -mcpu=arm7tdmi-s -mfpu=softfpa +CFLAGS = $(INC_PATH) -O0 -Wall -fmessage-length=0 -mcpu=arm7tdmi-s -g -mlong-calls +CFLAGS += -Wa,-adhlns="$(OBJ_PATH)/$(subst .o,.lst,$@)" +LFLAGS = $(LIB_PATH) -T"memory.x" -g -mcpu=arm7tdmi-s -nostartfiles +OCFLAGS = -O srec +ODFLAGS = -x +SZFLAGS = -B -d + + +#|---------------------------------------------------------------------------------------| +#| Define targets | +#|---------------------------------------------------------------------------------------| +AOBJS = $(patsubst %.s,%.o,$(PROJ_ASRCS)) +COBJS = $(patsubst %.c,%.o,$(PROJ_CSRCS)) + + +#|---------------------------------------------------------------------------------------| +#| Make ALL | +#|---------------------------------------------------------------------------------------| +all : $(BIN_PATH)/$(PROJ_NAME).sx + +$(BIN_PATH)/$(PROJ_NAME).sx : $(BIN_PATH)/$(PROJ_NAME).elf + @$(OC) $(OCFLAGS) $< $@ + @$(OD) $(ODFLAGS) $< > $(BIN_PATH)/$(PROJ_NAME).map + @echo +++ Summary of memory consumption: + @$(SZ) $(SZFLAGS) $< + @echo +++ Build complete [$(notdir $@)] + +$(BIN_PATH)/$(PROJ_NAME).elf : $(AOBJS) $(COBJS) + @echo +++ Linking [$(notdir $@)] + @$(LN) $(LFLAGS) -o $@ $(patsubst %.o,$(OBJ_PATH)/%.o,$(^F)) + + +#|---------------------------------------------------------------------------------------| +#| Compile and assemble | +#|---------------------------------------------------------------------------------------| +$(AOBJS): %.o: %.s $(PROJ_CHDRS) + @echo +++ Assembling [$@] + @$(AS) $(AFLAGS) $< -o $(OBJ_PATH)/$(@F) > $(subst .o,.lst,$(OBJ_PATH)/$(@F)) + +$(COBJS): %.o: %.c $(PROJ_CHDRS) + @echo +++ Compiling [$@] + @$(CC) $(CFLAGS) -c -o $(OBJ_PATH)/$(@F) $< + +#|---------------------------------------------------------------------------------------| +#| Make CLEAN | +#|---------------------------------------------------------------------------------------| +clean : + @echo +++ Cleaning build environment + @rm -f $(foreach file,$(AOBJS),$(OBJ_PATH)/$(file)) + @rm -f $(foreach file,$(COBJS),$(OBJ_PATH)/$(file)) + @rm -f $(patsubst %.o,%.lst,$(foreach file,$(AOBJS),$(OBJ_PATH)/$(file))) + @rm -f $(patsubst %.o,%.lst,$(foreach file,$(COBJS),$(OBJ_PATH)/$(file))) + @rm -f $(BIN_PATH)/$(PROJ_NAME).sx $(BIN_PATH)/$(PROJ_NAME).map $(BIN_PATH)/$(PROJ_NAME).elf + @echo +++ Clean complete + + diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/memory.x b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/memory.x new file mode 100644 index 00000000..a3b8a9e4 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/memory.x @@ -0,0 +1,51 @@ +/* identify the Entry Point */ +ENTRY(_startup) + +/* specify the LPC2294 memory areas */ +MEMORY +{ + flash : ORIGIN = 0x00002000, LENGTH = 240K /* FLASH ROM for the user program */ + ram_vectors(A) : ORIGIN = 0x40000000, LENGTH = 64 /* RAM vectors of the user program */ + ram_monitor(A) : ORIGIN = 0x40000040, LENGTH = 224 /* variables used by Philips RealMonitor */ + ram_isp_low(A) : ORIGIN = 0x40000120, LENGTH = 224 /* variables used by Philips ISP bootloader */ + ram : ORIGIN = 0x40000200, LENGTH = 15584 /* free RAM area */ + ram_isp_high(A) : ORIGIN = 0x40003EE0, LENGTH = 288 /* variables used by Philips ISP bootloader */ +} + +/* define a global symbol _stack_end, placed at the very end of unused RAM */ +_stack_end = 0x40003EE0 - 4; + +/* now define the output sections */ +SECTIONS +{ + . = 0; /* set location counter to address zero */ + startup : { *(.startup)} >flash /* the startup code goes into FLASH */ + + .text : /* collect all sections that should go into FLASH after startup */ + { + *(.text) /* all .text sections (code) */ + *(.rodata) /* all .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* all .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* all .glue_7 sections (no idea what these are) */ + *(.glue_7t) /* all .glue_7t sections (no idea what these are) */ + _etext = .; /* define a global symbol _etext just after the last code byte */ + } >flash /* put all the above into FLASH */ + + .data : /* collect all initialized .data sections that go into RAM */ + { + _data = .; /* create a global symbol marking the start of the .data section */ + *(.data) /* all .data sections */ + _edata = .; /* define a global symbol marking the end of the .data section */ + } >ram AT >flash /* put all the above into RAM (but load the LMA copy into FLASH) */ + + .bss : /* collect all uninitialized .bss sections that go into RAM */ + { + _bss_start = .; /* define a global symbol marking the start of the .bss section */ + *(.bss) /* all .bss sections */ + } >ram /* put all the above in RAM (it will be cleared in the startup code */ + + . = ALIGN(4); /* advance location counter to the next 32-bit boundary */ + _bss_end = . ; /* define a global symbol marking the end of the .bss section */ +} + _end = .; /* define a global symbol marking the end of application RAM */ + diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/timer.c b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/timer.c new file mode 100644 index 00000000..6aa579af --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/timer.c @@ -0,0 +1,119 @@ +/**************************************************************************************** +| Description: Timer driver source file +| File Name: timer.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "header.h" /* generic header */ + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +static unsigned long millisecond_counter; + + +/**************************************************************************************** +* External functions +****************************************************************************************/ +extern void TIMER0_ISR(void); + + +/**************************************************************************************** +** NAME: TimerInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the timer. +** +****************************************************************************************/ +void TimerInit(void) +{ + /* configure timer0 as 1 ms software output compare */ + T0MR0 = BOOT_CPU_SYSTEM_SPEED_KHZ-1; + /* enable interrupt and automatic reset upon compare */ + T0MCR = 0x01 | 0x02; + /* enable the output compare */ + T0TCR = 0x01; + /* set the interrupt service routine for the output compare event */ + VICVectAddr0 = (unsigned long)TIMER0_ISR; + /* connect vectored IRQ slot 0 to Timer0's channel 4 */ + VICVectCntl0 = 0x20 | 4; + /* enable the timer0 interrupt */ + VICIntEnable = 0x10; + /* reset the millisecond counter */ + TimerSet(0); +} /*** end of TimerInit ***/ + + +/**************************************************************************************** +** NAME: TimerUpdate +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Updates the millisecond timer. Should be called every millisecond by +** the timer interrupt service routine. +** +****************************************************************************************/ +void TimerUpdate(void) +{ + /* increment the millisecond counter */ + millisecond_counter++; +} /*** end of TimerUpdate ***/ + + +/**************************************************************************************** +** NAME: TimerSet +** PARAMETER: timer_value initialize value of the millisecond timer. +** RETURN VALUE: none +** DESCRIPTION: Sets the initial counter value of the millisecond timer. +** +****************************************************************************************/ +void TimerSet(unsigned long timer_value) +{ + /* set the millisecond counter */ + millisecond_counter = timer_value; +} /*** end of TimerSet ***/ + + +/**************************************************************************************** +** NAME: TimerGet +** PARAMETER: none +** RETURN VALUE: current value of the millisecond timer +** DESCRIPTION: Obtains the counter value of the millisecond timer. +** +****************************************************************************************/ +unsigned long TimerGet(void) +{ + /* read and return the millisecond counter value */ + return millisecond_counter; +} /*** end of TimerGet ***/ + + +/*********************************** end of timer.c ************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/timer.h b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/timer.h new file mode 100644 index 00000000..e1bb1754 --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/timer.h @@ -0,0 +1,44 @@ +/**************************************************************************************** +| Description: Timer driver header file +| File Name: timer.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef TIMER_H +#define TIMER_H + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void TimerInit(void); +void TimerUpdate(void); +void TimerSet(unsigned long timer_value); +unsigned long TimerGet(void); + + +#endif /* TIMER_H */ +/*********************************** end of timer.h ************************************/ diff --git a/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/vectors.c b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/vectors.c new file mode 100644 index 00000000..7b5682bc --- /dev/null +++ b/Target/Demo/ARM7_LPC2000_Olimex_LPC_L2294_GCC/Prog/vectors.c @@ -0,0 +1,107 @@ +/**************************************************************************************** +| Description: demo program interrupt vectors source file +| File Name: vectors.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "header.h" /* generic header */ + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void __attribute__ ((interrupt("IRQ"))) TIMER0_ISR(void); +void __attribute__ ((interrupt("SWI"))) SWI_ISR(void); +void __attribute__ ((interrupt("FIQ"))) FIQ_ISR(void); +void __attribute__ ((interrupt("UNDEF"))) UNDEF_ISR(void); + + +/**************************************************************************************** +** NAME: TIMER0_ISR +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Timer0 exception routine. +** +****************************************************************************************/ +void TIMER0_ISR(void) +{ + /* clear the interrupt flag */ + T0IR = 0x01; + /* acknowledge interrupt */ + VICVectAddr = 0; + /* process time tick */ + TimerUpdate(); +} /*** end of TIMER0_ISR ***/ + + +/**************************************************************************************** +** NAME: SWI_ISR +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: SWI exception routine. +** +****************************************************************************************/ +void SWI_ISR(void) +{ + /* unexpected interrupt so halt program */ + for (;;) { ; } +} /*** end of SWI_ISR ***/ + + +/**************************************************************************************** +** NAME: FIQ_ISR +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: FIQ exception routine. +** +****************************************************************************************/ +void FIQ_ISR(void) +{ + /* unexpected interrupt so halt program */ + for (;;) { ; } +} /*** end of FIQ_ISR ***/ + + +/**************************************************************************************** +** NAME: UNDEF_ISR +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: UNDEF exception routine. +** +****************************************************************************************/ +void UNDEF_ISR(void) +{ + /* unexpected interrupt so halt program */ + for (;;) { ; } +} /*** end of UNDEF_ISR ***/ + + +/*********************************** end of vectors.c **********************************/ diff --git a/Target/Source/ARM7_LPC2000/GCC/cstart.s b/Target/Source/ARM7_LPC2000/GCC/cstart.s new file mode 100644 index 00000000..8888deea --- /dev/null +++ b/Target/Source/ARM7_LPC2000/GCC/cstart.s @@ -0,0 +1,237 @@ +/**************************************************************************************** +| Description: bootloader C-startup assembly file +| File Name: cstart.s +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/* stack Sizes */ +.set UND_STACK_SIZE, 0x00000004 /* stack for "undef" interrupts is 4 bytes */ +.set ABT_STACK_SIZE, 0x00000004 /* stack for "abort" interrupts is 4 bytes */ +.set FIQ_STACK_SIZE, 0x00000004 /* stack for "FIQ" interrupts is 4 bytes */ +.set IRQ_STACK_SIZE, 0X00000004 /* stack for "IRQ" normal interrupts is 4 bytes */ +.set SVC_STACK_SIZE, 0x00000004 /* stack for "SVC" supervisor mode is 4 bytes */ + +/* mode bits and Interrupt (I & F) flags in program status registers (PSRs) */ +.set MODE_USR, 0x10 /* Normal User Mode */ +.set MODE_FIQ, 0x11 /* FIQ Processing Fast Interrupts Mode */ +.set MODE_IRQ, 0x12 /* IRQ Processing Standard Interrupts Mode */ +.set MODE_SVC, 0x13 /* Supervisor Processing Software Interrupts Mode */ +.set MODE_ABT, 0x17 /* Abort Processing memory Faults Mode */ +.set MODE_UND, 0x1B /* Undefined Processing Undefined Instructions Mode */ +.set MODE_SYS, 0x1F /* System Running Priviledged OS Tasks Mode */ +.set I_BIT, 0x80 /* when I bit is set, IRQ is disabled */ +.set F_BIT, 0x40 /* when F bit is set, FIQ is disabled */ + +/* microcontroller registers */ +.set MEMMAP, 0xE01FC040 /* MEMMAP register */ + +.text +.arm + +.extern ComSetConnectEntryState +.global EntryFromProg +.global Reset_Handler +.global SetupRAM +.global _startup +.func _startup + +_startup: +/**************************************************************************************** +* Interrupt vector table +****************************************************************************************/ +_vectors: ldr PC, Reset_Addr /* point to Reset_Handler address */ + ldr PC, Undef_Addr /* point to UNDEF_ISR address */ + ldr PC, SWI_Addr /* point to SWI_ISR address */ + ldr PC, PAbt_Addr /* point to UNDEF_ISR address */ + ldr PC, DAbt_Addr /* point to UNDEF_ISR address */ + nop /* reserved for Philips ISP checksum */ + ldr PC, IRQ_Addr /* point to IRQ_ISR address */ + ldr PC, FIQ_Addr /* point to FIQ_ISR address */ + +Reset_Addr: .word Reset_Handler /* defined in this module below */ +Undef_Addr: .word UNDEF_ISR /* defined in vectors.c */ +SWI_Addr: .word Reset_Handler_SWI /* defined in this module below */ +PAbt_Addr: .word UNDEF_ISR /* defined in vectors.c */ +DAbt_Addr: .word UNDEF_ISR /* defined in vectors.c */ +FIQ_Addr: .word FIQ_ISR /* defined in vectors.c */ +IRQ_Addr: .word IRQ_ISR /* defined in vectors.c */ + .word 0 /* rounds vectors and ISR addresses to */ + /* 64 bytes */ + + +/**************************************************************************************** +** NAME: EntryFromProg +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Called by the user program to activate the bootloader. Do not place +** any assembly code between this function and the end of the vector +** table. This guarantees that this function is located at address +** 0x00000040. The user program can call this function from C in the +** following way: +** void ActivateBootloader(void) +** { +** void (*pEntryFromProgFnc)(void); +** +** pEntryFromProgFnc = (void*)0x00000040; +** pEntryFromProgFnc(); +** } +** +****************************************************************************************/ +EntryFromProg: + /* remap interrupt vector table back to ROM to make sure the bootloader + * vectors are used: + * MEMMAP = 0x01; + */ + ldr r0, =MEMMAP + mov r1, #1 + str r1, [r0, #0] + /* trigger SWI to entry supervisor mode and run Reset_Handler_SWI */ + swi 0 + /*** end of EntryFromProg ***/ + + +/**************************************************************************************** +** NAME: Reset_Handler +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Reset interrupt service routine. Configures the stack for each mode, +** disables the IRQ and FIQ interrupts, initializes RAM and jumps to +** function main. +** +****************************************************************************************/ +Reset_Handler: + /* setup a stack and disable interrupts for each mode */ + ldr r0, =_stack_end + msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */ + mov sp, r0 + sub r0, r0, #UND_STACK_SIZE + msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */ + mov sp, r0 + sub r0, r0, #ABT_STACK_SIZE + msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */ + mov sp, r0 + sub r0, r0, #FIQ_STACK_SIZE + msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */ + mov sp, r0 + sub r0, r0, #IRQ_STACK_SIZE + msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */ + mov sp, r0 + sub r0, r0, #SVC_STACK_SIZE + msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* User Mode */ + mov sp, r0 + /* copy .data section from ROM to RAM and zero out .bss section */ + bl SetupRAM + /* start bootloader program by jumping to main() */ + b main +/*** end of Reset_Handler ***/ + + +/**************************************************************************************** +** NAME: Reset_Handler_SWI +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Reset handler for a software reset after the user program activated +** the bootloader. Configures the stack for each mode, disables the IRQ +** and FIQ interrupts, initializes RAM. Most importantly, before jumping +** to function main to start the bootloader program, the COM interface +** is configured to start in a connected state. Here is why: +** At the start of a new programming session, the host sends the XCP +** CONNECT command. Upon reception, the user program activates the +** bootloader by jumping to function EntryFromProg(), which triggers the +** SWI instruction that gets the program to this point. When the +** bootloader is started, it now needs to send the response to the XCP +** CONNECT command, because the host is waiting for this before it can +** continue. +** +****************************************************************************************/ +Reset_Handler_SWI: + /* setup a stack and disable interrupts for each mode */ + ldr r0, =_stack_end + msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */ + mov sp, r0 + sub r0, r0, #UND_STACK_SIZE + msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */ + mov sp, r0 + sub r0, r0, #ABT_STACK_SIZE + msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */ + mov sp, r0 + sub r0, r0, #FIQ_STACK_SIZE + msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */ + mov sp, r0 + sub r0, r0, #IRQ_STACK_SIZE + msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */ + mov sp, r0 + sub r0, r0, #SVC_STACK_SIZE + msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* User Mode */ + mov sp, r0 + /* copy .data section from ROM to RAM and zero out .bss section */ + bl SetupRAM + /* this part makes the difference with the normal Reset_Handler */ + bl ComSetConnectEntryState + /* start bootloader program by jumping to main() */ + b main +/*** end of Reset_Handler_SWI ***/ + + +/**************************************************************************************** +** NAME: SetupRAM +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes RAM by copying .data section from ROM to RAM and zero-ing +** out .bss section. +** +****************************************************************************************/ +SetupRAM: + /* copy .data section (Copy from ROM to RAM) */ + ldr R1, =_etext + ldr R2, =_data + ldr R3, =_edata +1: cmp R2, R3 + ldrlo R0, [R1], #4 + strlo R0, [R2], #4 + blo 1b + + /* clear .bss section (Zero init) */ + mov R0, #0 + ldr R1, =_bss_start + ldr R2, =_bss_end +2: cmp R1, R2 + strlo R0, [R1], #4 + blo 2b + /* return */ + bx lr +/*** end of SetupRAM ***/ +.endfunc + + +.end +/*********************************** end of cstart.s ***********************************/ diff --git a/Target/Source/ARM7_LPC2000/GCC/flash.c b/Target/Source/ARM7_LPC2000/GCC/flash.c new file mode 100644 index 00000000..5e10bc44 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/GCC/flash.c @@ -0,0 +1,705 @@ +/**************************************************************************************** +| Description: bootloader flash driver source file +| File Name: flash.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +#define FLASH_INVALID_SECTOR (0xff) +#define FLASH_INVALID_ADDRESS (0xffffffff) +#define FLASH_WRITE_BLOCK_SIZE (512) +#define FLASH_TOTAL_SECTORS (sizeof(flashLayout)/sizeof(flashLayout[0])) +/* entry address for the IAP algorithms, enabling a switch to thumb mode */ +#define IAP_ENTRY_ADDRESS (0x7ffffff1) +/* command codes */ +#define IAP_CMD_PREPARE_SECTORS (50) +#define IAP_CMD_COPY_RAM_TO_FLASH (51) +#define IAP_CMD_ERASE_SECTORS (52) +#define IAP_CMD_BLANK_CHECK_SECTORS (53) +#define IAP_CMD_COMPARE (56) +/* result codes */ +#define IAP_CMD_SUCCESS (0) + + +/**************************************************************************************** +* Type definitions +****************************************************************************************/ +/* function pointer type that is needed to call IAP functions of the NXP LPC2xxx */ +typedef void (*pIapHandler)(blt_int32u command[], blt_int32u result[]); + +/* flash sector descriptor type */ +typedef struct +{ + blt_addr sector_start; /* sector start address */ + blt_int32u sector_size; /* sector size in bytes */ + blt_int8u sector_num; /* sector number */ +} tFlashSector; /* flash sector description */ + +/* programming is done per block of max FLASH_WRITE_BLOCK_SIZE. for this a flash block + * manager is implemented in this driver. this flash block manager depends on this + * flash block info structure. It holds the base address of the flash block and the + * data that should be programmed into the flash block. Note that the .data member must + * be 32-bit aligned by the linker. the .base_addr must be a multiple of + * FLASH_WRITE_BLOCK_SIZE. + */ +typedef struct +{ + blt_addr base_addr; + blt_int8u data[FLASH_WRITE_BLOCK_SIZE] __attribute__ ((aligned (4))); +} tFlashBlockInfo; + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +static blt_bool FlashInitBlock(tFlashBlockInfo *block, blt_addr address); +static tFlashBlockInfo *FlashSwitchBlock(tFlashBlockInfo *block, blt_addr base_addr); +static blt_bool FlashAddToBlock(tFlashBlockInfo *block, blt_addr address, + blt_int8u *data, blt_int16u len); +static blt_bool FlashWriteBlock(tFlashBlockInfo *block); +static blt_bool FlashEraseSectors(blt_int8u first_sector, blt_int8u last_sector); +static blt_int8u FlashGetSector(blt_addr address); + + +/**************************************************************************************** +* Local constant declarations +****************************************************************************************/ +/* The current flash layout supports the NXP LPC21xx and LPC22xx targets. LPC23xx have + * a slightly different layout. To support the LPC23xx, simply update this flash layout. + */ +static const tFlashSector flashLayout[] = +{ +#if (BOOT_NVM_SIZE_KB == 64) + /* { 0x00000000, 0x02000, 0}, flash sector 0 - reserved for bootloader */ + { 0x00002000, 0x02000, 1}, /* flash sector 1 */ + { 0x00004000, 0x02000, 2}, /* flash sector 2 */ + { 0x00006000, 0x02000, 3}, /* flash sector 3 */ + { 0x00008000, 0x02000, 4}, /* flash sector 4 */ + { 0x0000A000, 0x02000, 5}, /* flash sector 5 */ + { 0x0000C000, 0x02000, 6}, /* flash sector 6 */ + /* { 0x0000E000, 0x02000, 7}, flash sector 7 - used by NXP bootcode */ +#endif +#if (BOOT_NVM_SIZE_KB == 128) + /* { 0x00000000, 0x02000, 0}, flash sector 0 - reserved for bootloader */ + { 0x00002000, 0x02000, 1}, /* flash sector 1 */ + { 0x00004000, 0x02000, 2}, /* flash sector 2 */ + { 0x00006000, 0x02000, 3}, /* flash sector 3 */ + { 0x00008000, 0x02000, 4}, /* flash sector 4 */ + { 0x0000A000, 0x02000, 5}, /* flash sector 5 */ + { 0x0000C000, 0x02000, 6}, /* flash sector 6 */ + { 0x0000E000, 0x02000, 7}, /* flash sector 7 */ + { 0x00010000, 0x02000, 8}, /* flash sector 8 */ + { 0x00012000, 0x02000, 9}, /* flash sector 9 */ + { 0x00014000, 0x02000, 10}, /* flash sector 10 */ + { 0x00016000, 0x02000, 11}, /* flash sector 11 */ + { 0x00018000, 0x02000, 12}, /* flash sector 12 */ + { 0x0001A000, 0x02000, 13}, /* flash sector 13 */ + { 0x0001C000, 0x02000, 14}, /* flash sector 14 */ + /* { 0x0001E000, 0x02000, 15}, flash sector 15 - used by NXP bootcode */ +#endif +#if (BOOT_NVM_SIZE_KB == 256) + /* { 0x00000000, 0x02000, 0}, flash sector 0 - reserved for bootloader */ + { 0x00002000, 0x02000, 1}, /* flash sector 1 */ + { 0x00004000, 0x02000, 2}, /* flash sector 2 */ + { 0x00006000, 0x02000, 3}, /* flash sector 3 */ + { 0x00008000, 0x02000, 4}, /* flash sector 4 */ + { 0x0000A000, 0x02000, 5}, /* flash sector 5 */ + { 0x0000C000, 0x02000, 6}, /* flash sector 6 */ + { 0x0000E000, 0x02000, 7}, /* flash sector 7 */ + { 0x00010000, 0x10000, 8}, /* flash sector 8 */ + { 0x00020000, 0x10000, 9}, /* flash sector 9 */ + { 0x00030000, 0x02000, 10}, /* flash sector 10 */ + { 0x00032000, 0x02000, 11}, /* flash sector 11 */ + { 0x00034000, 0x02000, 12}, /* flash sector 12 */ + { 0x00036000, 0x02000, 13}, /* flash sector 13 */ + { 0x00038000, 0x02000, 14}, /* flash sector 14 */ + { 0x0003A000, 0x02000, 15}, /* flash sector 15 */ + { 0x0003C000, 0x02000, 16}, /* flash sector 16 */ + /* { 0x0003E000, 0x02000, 17}, flash sector 17 - used by NXP bootcode */ +#endif +}; + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/* The smallest amount of flash that can be programmed is FLASH_WRITE_BLOCK_SIZE. A flash + * block manager is implemented in this driver and stores info in this variable. Whenever + * new data should be flashed, it is first added to a RAM buffer, which is part of this + * variable. Whenever the RAM buffer, which has the size of a flash block, is full or + * data needs to be written to a different block, the contents of the RAM buffer are + * programmed to flash. The flash block manager requires some software overhead, yet + * results is faster flash programming because data is first harvested, ideally until + * there is enough to program an entire flash block, before the flash device is actually + * operated on. + */ +static tFlashBlockInfo blockInfo; + +/* The first block of the user program holds the vector table, which on the LPC2000 is + * also the where the checksum is written to. Is it likely that the vector table is + * first flashed and then, at the end of the programming sequence, the checksum. This + * means that this flash block need to be written to twice. Normally this is not a + * problem with flash memory, as long as you write the same values to those bytes that + * are not supposed to be changed and the locations where you do write to are still in + * the erased 0xFF state. Unfortunately, writing twice to flash this way, does not work + * reliably on the LPC2000. This is why we need to have an extra block, the bootblock, + * placed under the management of the block manager. This way is it possible to implement + * functionality so that the bootblock is only written to once at the end of the + * programming sequency. + */ +static tFlashBlockInfo bootBlockInfo; + + +/**************************************************************************************** +** NAME: FlashInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the flash driver. +** +****************************************************************************************/ +void FlashInit(void) +{ + /* check the flash block data buffer alignments */ + if ((((blt_addr)blockInfo.data % 4) != 0) || (((blt_addr)bootBlockInfo.data % 4) != 0)) + { + /* incorrect alignment */ + ASSERT_RT(BLT_FALSE); + } + /* init the flash block info structs by setting the address to an invalid address */ + blockInfo.base_addr = FLASH_INVALID_ADDRESS; + bootBlockInfo.base_addr = FLASH_INVALID_ADDRESS; +} /*** end of FlashInit ***/ + + +/**************************************************************************************** +** NAME: FlashWrite +** PARAMETER: addr start address +** len length in bytes +** data pointer to the data buffer. +** RETURN VALUE: BLT_TRUE if successful, BLT_FALSE otherwise. +** DESCRIPTION: Writes the data to flash through a flash block manager. Note that this +** function also checks that no data is programmed outside the flash +** memory region, so the bootloader can never be overwritten. +** +****************************************************************************************/ +blt_bool FlashWrite(blt_addr addr, blt_int32u len, blt_int8u *data) +{ + blt_addr base_addr; + + /* make sure the addresses are within the flash device */ + if ( (FlashGetSector(addr) == FLASH_INVALID_SECTOR) || \ + (FlashGetSector(addr+len-1) == FLASH_INVALID_SECTOR) ) + { + return BLT_FALSE; + } + + /* if this is the bootblock, then let the boot block manager handle it */ + base_addr = (addr/FLASH_WRITE_BLOCK_SIZE)*FLASH_WRITE_BLOCK_SIZE; + if (base_addr == flashLayout[0].sector_start) + { + /* let the boot block manager handle it */ + return FlashAddToBlock(&bootBlockInfo, addr, data, len); + } + /* let the block manager handle it */ + return FlashAddToBlock(&blockInfo, addr, data, len); +} /*** end of FlashWrite ***/ + + +/**************************************************************************************** +** NAME: FlashErase +** PARAMETER: addr start address +** len length in bytes +** RETURN VALUE: BLT_TRUE if successful, BLT_FALSE otherwise. +** DESCRIPTION: Erases the flash memory. Note that this function also checks that no +** data is erased outside the flash memory region, so the bootloader can +** never be erased. +** +****************************************************************************************/ +blt_bool FlashErase(blt_addr addr, blt_int32u len) +{ + blt_int8u first_sector; + blt_int8u last_sector; + + /* obtain the first and last sector number */ + first_sector = FlashGetSector(addr); + last_sector = FlashGetSector(addr+len-1); + /* check them */ + if ( (first_sector == FLASH_INVALID_SECTOR) || (last_sector == FLASH_INVALID_SECTOR) ) + { + return BLT_FALSE; + } + /* erase the sectors */ + return FlashEraseSectors(first_sector, last_sector); +} /*** end of FlashErase ***/ + + +/**************************************************************************************** +** NAME: FlashWriteChecksum +** PARAMETER: none +** RETURN VALUE: BLT_TRUE is successful, BTL_FALSE otherwise. +** DESCRIPTION: Writes a checksum of the user program to non-volatile memory. This is +** performed once the entire user program has been programmed. Through +** the checksum, the bootloader can check if the programming session +** was completed, which indicates that a valid user programming is +** present and can be started. +** +****************************************************************************************/ +blt_bool FlashWriteChecksum(void) +{ + blt_int32u signature_checksum = 0; + + /* The ARM7 core already has a spot reserved for a checksum that the bootloader can + * store at the end of a programming session. In order for the bootloader to be able + * to program the checksum, it is important that address 0x******14, which is reserved + * for the checksum, is set to 0xffffffff in the user program. + * + * Layout of the vector table (* = don't care) + * 0x******00 Reset Exception + * 0x******04 Undefined Instruction Exception + * 0x******08 Software Interrupt Exception + * 0x******0C Prefetch Exception + * 0x******10 Abort Exception + * 0x******14 [reserved for signature checksum] + * 0x******18 IRQ Exception + * 0x******1C FIQ Exception + * + * signature_checksum = Two's complement of (SUM(exception address values)) + */ + + /* compute the checksum. note that the user program's vectors are not yet written + * to flash but are present in the bootblock data structure at this point. + */ + signature_checksum += *((blt_int32u*)(&bootBlockInfo.data[0+0x00])); + signature_checksum += *((blt_int32u*)(&bootBlockInfo.data[0+0x04])); + signature_checksum += *((blt_int32u*)(&bootBlockInfo.data[0+0x08])); + signature_checksum += *((blt_int32u*)(&bootBlockInfo.data[0+0x0C])); + signature_checksum += *((blt_int32u*)(&bootBlockInfo.data[0+0x10])); + signature_checksum += *((blt_int32u*)(&bootBlockInfo.data[0+0x18])); + signature_checksum += *((blt_int32u*)(&bootBlockInfo.data[0+0x1C])); + signature_checksum = ~signature_checksum; /* one's complement */ + signature_checksum += 1; /* two's complement */ + + /* write the checksum */ + return FlashWrite(flashLayout[0].sector_start+0x14, sizeof(blt_addr), + (blt_int8u*)&signature_checksum); +} /*** end of FlashWriteChecksum ***/ + + +/**************************************************************************************** +** NAME: FlashVerifyChecksum +** PARAMETER: none +** RETURN VALUE: BLT_TRUE is successful, BTL_FALSE otherwise. +** DESCRIPTION: Verifies the checksum, which indicates that a valid user program is +** present and can be started. +** +****************************************************************************************/ +blt_bool FlashVerifyChecksum(void) +{ + blt_int32u signature_checksum = 0; + + /* verify the checksum based on how it was written by CpuWriteChecksum() */ + signature_checksum += *((blt_int32u*)(flashLayout[0].sector_start)); + signature_checksum += *((blt_int32u*)(flashLayout[0].sector_start+0x04)); + signature_checksum += *((blt_int32u*)(flashLayout[0].sector_start+0x08)); + signature_checksum += *((blt_int32u*)(flashLayout[0].sector_start+0x0C)); + signature_checksum += *((blt_int32u*)(flashLayout[0].sector_start+0x10)); + signature_checksum += *((blt_int32u*)(flashLayout[0].sector_start+0x14)); + signature_checksum += *((blt_int32u*)(flashLayout[0].sector_start+0x18)); + signature_checksum += *((blt_int32u*)(flashLayout[0].sector_start+0x1C)); + + /* sum should add up to an unsigned 32-bit value of 0 */ + if (signature_checksum == 0) + { + /* checksum okay */ + return BLT_TRUE; + } + /* checksum incorrect */ + return BLT_FALSE; +} /*** end of FlashVerifyChecksum ***/ + + +/**************************************************************************************** +** NAME: FlashDone +** PARAMETER: none +** RETURN VALUE: BLT_TRUE is succesful, BLT_FALSE otherwise. +** DESCRIPTION: Finilizes the flash driver operations. There could still be data in +** the currently active block that needs to be flashed. +** +****************************************************************************************/ +blt_bool FlashDone(void) +{ + /* check if there is still data waiting to be programmed in the boot block */ + if (bootBlockInfo.base_addr != FLASH_INVALID_ADDRESS) + { + if (FlashWriteBlock(&bootBlockInfo) == BLT_FALSE) + { + return BLT_FALSE; + } + } + + /* check if there is still data waiting to be programmed */ + if (blockInfo.base_addr != FLASH_INVALID_ADDRESS) + { + if (FlashWriteBlock(&blockInfo) == BLT_FALSE) + { + return BLT_FALSE; + } + } + /* still here so all is okay */ + return BLT_TRUE; +} /*** end of FlashDone ***/ + + +/**************************************************************************************** +** NAME: FlashInitBlock +** PARAMETER: block pointer to flash block info structure to operate on. +** address base address of the block data. +** RETURN VALUE: BLT_TRUE is succesful, BLT_FALSE otherwise. +** DESCRIPTION: Copies data currently in flash to the block->data and sets the +** base address. +** +****************************************************************************************/ +static blt_bool FlashInitBlock(tFlashBlockInfo *block, blt_addr address) +{ + /* check address alignment */ + if ((address % FLASH_WRITE_BLOCK_SIZE) != 0) + { + return BLT_FALSE; + } + /* make sure that we are initializing a new block and not the same one */ + if (block->base_addr == address) + { + /* block already initialized, so nothing to do */ + return BLT_TRUE; + } + /* set the base address and copies the current data from flash */ + block->base_addr = address; + CpuMemCopy((blt_addr)block->data, address, FLASH_WRITE_BLOCK_SIZE); + return BLT_TRUE; +} /*** end of FlashInitBlock ***/ + + +/**************************************************************************************** +** NAME: FlashSwitchBlock +** PARAMETER: block pointer to flash block info structure to operate on. +** base_addr base address for the next block +** RETURN VALUE: the pointer of the block info struct that is no being used, or a NULL +** pointer in case of error. +** DESCRIPTION: Switches blocks by programming the current one and initializing the +** next. +** +****************************************************************************************/ +static tFlashBlockInfo *FlashSwitchBlock(tFlashBlockInfo *block, blt_addr base_addr) +{ + /* check if a switch needs to be made away from the boot block. in this case the boot + * block shouldn't be written yet, because this is done at the end of the programming + * session by FlashDone(), this is right after the checksum was written. + */ + if (block == &bootBlockInfo) + { + /* switch from the boot block to the generic block info structure */ + block = &blockInfo; + } + /* check if a switch back into the bootblock is needed. in this case the generic block + * doesn't need to be written here yet. + */ + else if (base_addr == flashLayout[0].sector_start) + { + /* switch from the generic block to the boot block info structure */ + block = &bootBlockInfo; + base_addr = flashLayout[0].sector_start; + } + else + { + /* need to switch to a new block, so program the current one and init the next */ + if (FlashWriteBlock(block) == BLT_FALSE) + { + return BLT_NULL; + } + } + + /* initialize tne new block when necessary */ + if (FlashInitBlock(block, base_addr) == BLT_FALSE) + { + return BLT_NULL; + } + + /* still here to all is okay */ + return block; +} /*** end of FlashSwitchBlock ***/ + + +/**************************************************************************************** +** NAME: FlashAddToBlock +** PARAMETER: block pointer to flash block info structure to operate on. +** address flash destination address +** data pointer to the byte array with data +** len number of bytes to add to the block +** RETURN VALUE: BLT_TRUE if successful, BLT_FALSE otherwise. +** DESCRIPTION: Programming is done per block. This function adds data to the block +** that is currently collecting data to be written to flash. If the +** address is outside of the current block, the current block is written +** to flash an a new block is initialized. +** +****************************************************************************************/ +static blt_bool FlashAddToBlock(tFlashBlockInfo *block, blt_addr address, + blt_int8u *data, blt_int16u len) +{ + blt_addr current_base_addr; + blt_int8u *dst; + blt_int8u *src; + + /* determine the current base address */ + current_base_addr = (address/FLASH_WRITE_BLOCK_SIZE)*FLASH_WRITE_BLOCK_SIZE; + + /* make sure the blockInfo is not uninitialized */ + if (block->base_addr == FLASH_INVALID_ADDRESS) + { + /* initialize the blockInfo struct for the current block */ + if (FlashInitBlock(block, current_base_addr) == BLT_FALSE) + { + return BLT_FALSE; + } + } + + /* check if the new data fits in the current block */ + if (block->base_addr != current_base_addr) + { + /* need to switch to a new block, so program the current one and init the next */ + block = FlashSwitchBlock(block, current_base_addr); + if (block == BLT_NULL) + { + return BLT_FALSE; + } + } + + /* add the data to the current block, but check for block overflow */ + dst = &(block->data[address - block->base_addr]); + src = data; + do + { + /* keep the watchdog happy */ + CopService(); + /* buffer overflow? */ + if ((blt_addr)(dst-&(block->data[0])) >= FLASH_WRITE_BLOCK_SIZE) + { + /* need to switch to a new block, so program the current one and init the next */ + block = FlashSwitchBlock(block, current_base_addr+FLASH_WRITE_BLOCK_SIZE); + if (block == BLT_NULL) + { + return BLT_FALSE; + } + /* reset destination pointer */ + dst = &(block->data[0]); + } + /* write the data to the buffer */ + *dst = *src; + /* update pointers */ + dst++; + src++; + /* decrement byte counter */ + len--; + } + while (len > 0); + /* still here so all is good */ + return BLT_TRUE; +} /*** end of FlashAddToBlock ***/ + + +/**************************************************************************************** +** NAME: FlashWriteBlock +** PARAMETER: block pointer to flash block info structure to operate on. +** RETURN VALUE: BLT_TRUE if successful, BLT_FALSE otherwise. +** DESCRIPTION: Programs FLASH_WRITE_BLOCK_SIZE bytes to flash from the block->data +** array. +** +****************************************************************************************/ +static blt_bool FlashWriteBlock(tFlashBlockInfo *block) +{ + blt_int32u iap_command[5]; + blt_int32u iap_result[3]; + blt_int8u sector_num; + pIapHandler iapHandler = (void *)IAP_ENTRY_ADDRESS; + + /* check that address is actually within flash */ + sector_num = FlashGetSector(block->base_addr); + if (sector_num == FLASH_INVALID_SECTOR) + { + return BLT_FALSE; + } + /* send the prepare sector command for just this one sector */ + iap_command[0] = IAP_CMD_PREPARE_SECTORS; + iap_command[1] = sector_num; + iap_command[2] = sector_num; + iap_result[0] = !IAP_CMD_SUCCESS; + /* service the watchdog before calling the IAP handler */ + CopService(); + iapHandler(iap_command, iap_result); + if (iap_result[0] != IAP_CMD_SUCCESS) + { + return BLT_FALSE; + } + /* send the erase sector command */ + iap_command[0] = IAP_CMD_COPY_RAM_TO_FLASH; + iap_command[1] = (blt_int32u)block->base_addr; + iap_command[2] = (blt_int32u)block->data; + iap_command[3] = FLASH_WRITE_BLOCK_SIZE; + iap_command[4] = BOOT_CPU_SYSTEM_SPEED_KHZ; + iap_result[0] = !IAP_CMD_SUCCESS; + /* service the watchdog before calling the IAP handler */ + CopService(); + iapHandler(iap_command, iap_result); + if (iap_result[0] != IAP_CMD_SUCCESS) + { + return BLT_FALSE; + } + /* perform a comparison for verification purposes */ + iap_command[0] = IAP_CMD_COMPARE; + iap_command[1] = (blt_int32u)block->base_addr; + iap_command[2] = (blt_int32u)block->data; + iap_command[3] = FLASH_WRITE_BLOCK_SIZE; + iap_result[0] = !IAP_CMD_SUCCESS; + /* service the watchdog before calling the IAP handler */ + CopService(); + iapHandler(iap_command, iap_result); + if (iap_result[0] != IAP_CMD_SUCCESS) + { + return BLT_FALSE; + } + /* still here so all is okay */ + return BLT_TRUE; + +} /*** end of FlashWriteBlock ***/ + + +/**************************************************************************************** +** NAME: FlashEraseSectors +** PARAMETER: first_sector first flash sector number +** last_sector last flash sector number +** RETURN VALUE: BLT_TRUE if successful, BLT_FALSE otherwise. +** DESCRIPTION: Erases the flash sectors from first_sector up until last_sector +** +****************************************************************************************/ +static blt_bool FlashEraseSectors(blt_int8u first_sector, blt_int8u last_sector) +{ + blt_int32u iap_command[5]; + blt_int32u iap_result[3]; + pIapHandler iapHandler = (void *)IAP_ENTRY_ADDRESS; + + /* validate the sector numbers */ + if (first_sector > last_sector) + { + return BLT_FALSE; + } + if ( (first_sector < flashLayout[0].sector_num) || \ + (last_sector > flashLayout[FLASH_TOTAL_SECTORS-1].sector_num) ) + { + return BLT_FALSE; + } + + /* send the prepare sector command for just this one sector */ + iap_command[0] = IAP_CMD_PREPARE_SECTORS; + iap_command[1] = first_sector; + iap_command[2] = last_sector; + iap_result[0] = !IAP_CMD_SUCCESS; + /* service the watchdog before calling the IAP handler */ + CopService(); + iapHandler(iap_command, iap_result); + if (iap_result[0] != IAP_CMD_SUCCESS) + { + return BLT_FALSE; + } + /* send the erase sector command */ + iap_command[0] = IAP_CMD_ERASE_SECTORS; + iap_command[1] = first_sector; + iap_command[2] = last_sector; + iap_command[3] = BOOT_CPU_SYSTEM_SPEED_KHZ; + iap_result[0] = !IAP_CMD_SUCCESS; + /* service the watchdog before calling the IAP handler */ + CopService(); + iapHandler(iap_command, iap_result); + if (iap_result[0] != IAP_CMD_SUCCESS) + { + return BLT_FALSE; + } + /* perform a blank check for verification purposes */ + iap_command[0] = IAP_CMD_BLANK_CHECK_SECTORS ; + iap_command[1] = first_sector; + iap_command[2] = last_sector; + iap_result[0] = !IAP_CMD_SUCCESS; + /* service the watchdog before calling the IAP handler */ + CopService(); + iapHandler(iap_command, iap_result); + if (iap_result[0] != IAP_CMD_SUCCESS) + { + return BLT_FALSE; + } + /* still here so all went okay */ + return BLT_TRUE; +} /*** end of FlashEraseSectors ***/ + + +/**************************************************************************************** +** NAME: FlashGetSector +** PARAMETER: address address in the flash sector +** RETURN VALUE: flash sector number or FLASH_INVALID_SECTOR +** DESCRIPTION: Determines the flash sector the address is in. +** +****************************************************************************************/ +static blt_int8u FlashGetSector(blt_addr address) +{ + blt_int8u sectorIdx; + + /* search through the sectors to find the right one */ + for (sectorIdx = 0; sectorIdx < FLASH_TOTAL_SECTORS; sectorIdx++) + { + /* keep the watchdog happy */ + CopService(); + /* is the address in this sector? */ + if ( (address >= flashLayout[sectorIdx].sector_start) && \ + (address < (flashLayout[sectorIdx].sector_start + \ + flashLayout[sectorIdx].sector_size)) ) + { + /* return the sector number */ + return flashLayout[sectorIdx].sector_num; + } + } + /* still here so no valid sector found */ + return FLASH_INVALID_SECTOR; +} /*** end of FlashGetSector ***/ + + +/*********************************** end of flash.c ************************************/ diff --git a/Target/Source/ARM7_LPC2000/GCC/flash.h b/Target/Source/ARM7_LPC2000/GCC/flash.h new file mode 100644 index 00000000..9cae116f --- /dev/null +++ b/Target/Source/ARM7_LPC2000/GCC/flash.h @@ -0,0 +1,46 @@ +/**************************************************************************************** +| Description: bootloader flash driver header file +| File Name: flash.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef FLASH_H +#define FLASH_H + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void FlashInit(void); +blt_bool FlashWrite(blt_addr addr, blt_int32u len, blt_int8u *data); +blt_bool FlashErase(blt_addr addr, blt_int32u len); +blt_bool FlashWriteChecksum(void); +blt_bool FlashVerifyChecksum(void); +blt_bool FlashDone(void); + + +#endif /* FLASH_H */ +/*********************************** end of flash.h ************************************/ diff --git a/Target/Source/ARM7_LPC2000/GCC/memory.x b/Target/Source/ARM7_LPC2000/GCC/memory.x new file mode 100644 index 00000000..a31919b0 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/GCC/memory.x @@ -0,0 +1,54 @@ +/* identify the Entry Point */ +ENTRY(_startup) + +/* specify the LPC2xxx memory areas. note that the RAM is configured to be only 8kb. this is + * the smallest in the LPC2xxx series, making this memory layout compatible with all devices + * in this serie of microcontrollers. + */ +MEMORY +{ + flash : ORIGIN = 0x00000000, LENGTH = 16K /* FLASH ROM reserved for the bootloader */ + ram_vectors(A) : ORIGIN = 0x40000000, LENGTH = 64 /* RAM vectors of the user program */ + ram_monitor(A) : ORIGIN = 0x40000040, LENGTH = 224 /* variables used by Philips RealMonitor */ + ram_isp_low(A) : ORIGIN = 0x40000120, LENGTH = 224 /* variables used by Philips ISP bootloader */ + ram : ORIGIN = 0x40000200, LENGTH = 7392 /* free RAM area */ + ram_isp_high(A) : ORIGIN = 0x40001EE0, LENGTH = 288 /* variables used by Philips ISP bootloader */ +} + +/* define a global symbol _stack_end, placed at the very end of unused RAM */ +_stack_end = 0x40001EE0 - 4; + +/* now define the output sections */ +SECTIONS +{ + . = 0; /* set location counter to address zero */ + startup : { *(.startup)} >flash /* the startup code goes into FLASH */ + + .text : /* collect all sections that should go into FLASH after startup */ + { + *(.text) /* all .text sections (code) */ + *(.rodata) /* all .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* all .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* all .glue_7 sections (no idea what these are) */ + *(.glue_7t) /* all .glue_7t sections (no idea what these are) */ + _etext = .; /* define a global symbol _etext just after the last code byte */ + } >flash /* put all the above into FLASH */ + + .data : /* collect all initialized .data sections that go into RAM */ + { + _data = .; /* create a global symbol marking the start of the .data section */ + *(.data) /* all .data sections */ + _edata = .; /* define a global symbol marking the end of the .data section */ + } >ram AT >flash /* put all the above into RAM (but load the LMA copy into FLASH) */ + + .bss : /* collect all uninitialized .bss sections that go into RAM */ + { + _bss_start = .; /* define a global symbol marking the start of the .bss section */ + *(.bss) /* all .bss sections */ + } >ram /* put all the above in RAM (it will be cleared in the startup code */ + + . = ALIGN(4); /* advance location counter to the next 32-bit boundary */ + _bss_end = . ; /* define a global symbol marking the end of the .bss section */ +} + _end = .; /* define a global symbol marking the end of application RAM */ + diff --git a/Target/Source/ARM7_LPC2000/GCC/vectors.c b/Target/Source/ARM7_LPC2000/GCC/vectors.c new file mode 100644 index 00000000..7ea10d06 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/GCC/vectors.c @@ -0,0 +1,88 @@ +/**************************************************************************************** +| Description: bootloader interrupt vectors source file +| File Name: vectors.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void __attribute__ ((interrupt("FIQ"))) FIQ_ISR(void); +void __attribute__ ((interrupt("IRQ"))) IRQ_ISR(void); +void __attribute__ ((interrupt("UNDEF"))) UNDEF_ISR(void); + + +/**************************************************************************************** +** NAME: FIQ_ISR +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: FIQ exception routine. +** +****************************************************************************************/ +void FIQ_ISR(void) +{ + /* unexpected interrupt so trigger assertion */ + ASSERT_RT(BLT_FALSE); +} /*** end of FIQ_ISR ***/ + + +/**************************************************************************************** +** NAME: IRQ_ISR +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: IRQ exception routine. +** +****************************************************************************************/ +void IRQ_ISR(void) +{ + /* unexpected interrupt so trigger assertion */ + ASSERT_RT(BLT_FALSE); +} /*** end of IRQ_ISR ***/ + + +/**************************************************************************************** +** NAME: UNDEF_ISR +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: UNDEF exception routine. +** +****************************************************************************************/ +void UNDEF_ISR(void) +{ + /* unexpected interrupt so trigger assertion */ + ASSERT_RT(BLT_FALSE); +} /*** end of UNDEF_ISR ***/ + + +/*********************************** end of vectors.c **********************************/ diff --git a/Target/Source/ARM7_LPC2000/can.c b/Target/Source/ARM7_LPC2000/can.c new file mode 100644 index 00000000..91e07874 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/can.c @@ -0,0 +1,253 @@ +/**************************************************************************************** +| Description: bootloader CAN communication interface source file +| File Name: can.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +#if (BOOT_COM_CAN_ENABLE > 0) +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +#define CAN_TBS1 (0x00000004) /* transmit buffer 1 idle */ +#define CAN_TCS1 (0x00000008) /* transmit buffer 1 complete */ +#define CAN_RRB (0x04) /* receive buffer release */ +#define CAN_RBS (0x01) /* receive buffer status */ +#define CAN_TR (0x01) /* transmission request */ +#define CAN_STB1 (0x20) /* select tx buffer 1 for transmit */ + + +/**************************************************************************************** +* Register definitions +****************************************************************************************/ +#define CANAFMR (*((volatile blt_int8u *) 0xE003C000)) +#define CAN1MOD (*((volatile blt_int32u *) 0xE0044000)) +#define CAN1IER (*((volatile blt_int32u *) 0xE0044010)) +#define CAN1GSR (*((volatile blt_int32u *) 0xE0044008)) +#define CAN1BTR (*((volatile blt_int32u *) 0xE0044014)) +#define CAN1TFI1 (*((volatile blt_int32u *) 0xE0044030)) +#define CAN1TID1 (*((volatile blt_int32u *) 0xE0044034)) +#define CAN1TDA1 (*((volatile blt_int32u *) 0xE0044038)) +#define CAN1TDB1 (*((volatile blt_int32u *) 0xE004403C)) +#define CAN1CMR (*((volatile blt_int32u *) 0xE0044004)) +#define CAN1SR (*((volatile blt_int32u *) 0xE004401C)) +#define CAN1RID (*((volatile blt_int32u *) 0xE0044024)) +#define CAN1RDA (*((volatile blt_int32u *) 0xE0044028)) +#define CAN1RDB (*((volatile blt_int32u *) 0xE004402C)) + + +/**************************************************************************************** +* Type definitions +****************************************************************************************/ +typedef struct t_can_bus_timing +{ + blt_int8u tseg1; /* CAN time segment 1 */ + blt_int8u tseg2; /* CAN time segment 2 */ +} tCanBusTiming; /* bus timing structure type */ + + +/**************************************************************************************** +* Local constant declarations +****************************************************************************************/ +/* According to the CAN protocol 1 bit-time can be made up of between 8..25 time quanta + * (TQ). The total TQ in a bit is SYNC + TSEG1 + TSEG2 with SYNC always being 1. + * The sample point is (SYNC + TSEG1) / (SYNC + TSEG1 + SEG2) * 100%. This array contains + * possible and valid time quanta configurations with a sample point between 68..78%. + */ +static const tCanBusTiming canTiming[] = +{ /* TQ | TSEG1 | TSEG2 | SP */ + /* ------------------------- */ + { 5, 2 }, /* 8 | 5 | 2 | 75% */ + { 6, 2 }, /* 9 | 6 | 2 | 78% */ + { 6, 3 }, /* 10 | 6 | 3 | 70% */ + { 7, 3 }, /* 11 | 7 | 3 | 73% */ + { 8, 3 }, /* 12 | 8 | 3 | 75% */ + { 9, 3 }, /* 13 | 9 | 3 | 77% */ + { 9, 4 }, /* 14 | 9 | 4 | 71% */ + { 10, 4 }, /* 15 | 10 | 4 | 73% */ + { 11, 4 }, /* 16 | 11 | 4 | 75% */ + { 12, 4 }, /* 17 | 12 | 4 | 76% */ + { 12, 5 }, /* 18 | 12 | 5 | 72% */ + { 13, 5 }, /* 19 | 13 | 5 | 74% */ + { 14, 5 }, /* 20 | 14 | 5 | 75% */ + { 15, 5 }, /* 21 | 15 | 5 | 76% */ + { 15, 6 }, /* 22 | 15 | 6 | 73% */ + { 16, 6 }, /* 23 | 16 | 6 | 74% */ + { 16, 7 }, /* 24 | 16 | 7 | 71% */ + { 16, 8 } /* 25 | 16 | 8 | 68% */ +}; + + +/**************************************************************************************** +** NAME: CanGetSpeedConfig +** PARAMETER: baud The desired baudrate in kbps. Valid values are 10..1000. +** btr Pointer to where the value for register CANxBTR will be stored. +** RETURN VALUE: BLT_TRUE if the CAN bustiming register values were found, BLT_FALSE +** otherwise. +** DESCRIPTION: Search algorithm to match the desired baudrate to a possible bus +** timing configuration. +** +****************************************************************************************/ +static blt_bool CanGetSpeedConfig(blt_int16u baud, blt_int32u *btr) +{ + blt_int16u prescaler; + blt_int8u cnt; + + /* loop through all possible time quanta configurations to find a match */ + for (cnt=0; cnt < sizeof(canTiming)/sizeof(canTiming[0]); cnt++) + { + if ((BOOT_CPU_SYSTEM_SPEED_KHZ % (baud*(canTiming[cnt].tseg1+canTiming[cnt].tseg2+1))) == 0) + { + /* compute the prescaler that goes with this TQ configuration */ + prescaler = BOOT_CPU_SYSTEM_SPEED_KHZ/(baud*(canTiming[cnt].tseg1+canTiming[cnt].tseg2+1)); + + /* make sure the prescaler is valid */ + if ( (prescaler > 0) && (prescaler <= 1024) ) + { + /* store the prescaler and bustiming register value */ + *btr = prescaler - 1; + *btr |= ((canTiming[cnt].tseg2 - 1) << 20) | ((canTiming[cnt].tseg1 - 1) << 16); + /* found a good bus timing configuration */ + return BLT_TRUE; + } + } + } + /* could not find a good bus timing configuration */ + return BLT_FALSE; +} /*** end of CanGetSpeedConfig ***/ + + +/**************************************************************************************** +** NAME: CanInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the CAN controller and synchronizes it to the CAN bus. +** +****************************************************************************************/ +void CanInit(void) +{ + blt_bool result; + blt_int32u btr_reg_value; + + /* the current implementation supports CAN1, which has channel index 0. throw an + * assertion error in case a different CAN channel is configured. + */ + ASSERT_CT(BOOT_COM_CAN_CHANNEL_INDEX == 0); + /* configure acceptance filter for bypass mode so it receives all messages */ + CANAFMR = 0x00000002L; + /* take CAN controller offline and go into reset mode */ + CAN1MOD = 1; + /* disable all interrupts. driver only needs to work in polling mode */ + CAN1IER = 0; + /* reset CAN controller status */ + CAN1GSR = 0; + /* configure the bittiming */ + result = CanGetSpeedConfig(BOOT_COM_CAN_BAUDRATE/1000, &btr_reg_value); + /* check that a valid baudrate configuration was found */ + ASSERT_RT(result == BLT_TRUE); + /* write the bittiming configuration to the register */ + CAN1BTR = btr_reg_value; + /* enter normal operating mode and synchronize to the CAN bus */ + CAN1MOD = 0; +} /*** end of CanInit ***/ + + +/**************************************************************************************** +** NAME: CanTransmitPacket +** PARAMETER: data pointer to byte array with data that it to be transmitted. +** len number of bytes that are to be transmitted. +** RETURN VALUE: none +** DESCRIPTION: Transmits a packet formatted for the communication interface. +** +****************************************************************************************/ +void CanTransmitPacket(blt_int8u *data, blt_int8u len) +{ + /* check that transmit buffer 1 is ready to accept a new message */ + ASSERT_RT((CAN1SR & CAN_TBS1) != 0); + /* write dlc and configure message as a standard message with 11-bit identifier */ + CAN1TFI1 = (len << 16); + /* write the message identifier */ + CAN1TID1 = BOOT_COM_CAN_TX_MSG_ID; + /* write the first set of 4 data bytes */ + CAN1TDA1 = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; + /* write the second set of 4 data bytes */ + CAN1TDB1 = (data[7] << 24) + (data[6] << 16) + (data[5] << 8) + data[4]; + /* write transmission request for transmit buffer 1 */ + CAN1CMR = CAN_TR | CAN_STB1; + /* wait for transmit completion */ + while ((CAN1SR & CAN_TCS1) == 0) + { + /* keep the watchdog happy */ + CopService(); + } +} /*** end of CanTransmitPacket ***/ + + +/**************************************************************************************** +** NAME: CanReceivePacket +** PARAMETER: data pointer to byte array where the data is to be stored. +** RETURN VALUE: BLT_TRUE is a packet was received, BLT_FALSE otherwise. +** DESCRIPTION: Receives a communication interface packet if one is present. +** +****************************************************************************************/ +blt_bool CanReceivePacket(blt_int8u *data) +{ + /* check if a new message was received */ + if ((CAN1SR & CAN_RBS) == 0) + { + return BLT_FALSE; + } + /* see if this is the message identifier that we are interested in */ + if (CAN1RID != BOOT_COM_CAN_RX_MSG_ID) + { + return BLT_FALSE; + } + /* store the message data */ + data[0] = (blt_int8u)CAN1RDA; + data[1] = (blt_int8u)(CAN1RDA >> 8); + data[2] = (blt_int8u)(CAN1RDA >> 16); + data[3] = (blt_int8u)(CAN1RDA >> 24); + data[4] = (blt_int8u)CAN1RDB; + data[5] = (blt_int8u)(CAN1RDB >> 8); + data[6] = (blt_int8u)(CAN1RDB >> 16); + data[7] = (blt_int8u)(CAN1RDB >> 24); + /* release the receive buffer */ + CAN1CMR = CAN_RRB; + /* inform called that a new data was received */ + return BLT_TRUE; +} /*** end of CanReceivePacket ***/ +#endif /* BOOT_COM_CAN_ENABLE > 0 */ + + +/*********************************** end of can.c **************************************/ diff --git a/Target/Source/ARM7_LPC2000/can.h b/Target/Source/ARM7_LPC2000/can.h new file mode 100644 index 00000000..2a60a6f9 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/can.h @@ -0,0 +1,45 @@ +/**************************************************************************************** +| Description: bootloader CAN communication interface header file +| File Name: can.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef CAN_H +#define CAN_H + +#if (BOOT_COM_CAN_ENABLE > 0) +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void CanInit(void); +void CanTransmitPacket(blt_int8u *data, blt_int8u len); +blt_bool CanReceivePacket(blt_int8u *data); +#endif /* BOOT_COM_CAN_ENABLE > 0 */ + + +#endif /* CAN_H */ +/*********************************** end of can.h **************************************/ diff --git a/Target/Source/ARM7_LPC2000/cpu.c b/Target/Source/ARM7_LPC2000/cpu.c new file mode 100644 index 00000000..7b8fec93 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/cpu.c @@ -0,0 +1,138 @@ +/**************************************************************************************** +| Description: bootloader cpu module source file +| File Name: cpu.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +#define CPU_USER_PROG_VECTORS_START_ADDR ((blt_addr)0x00002000) +#define CPU_RAM_VECTORS_START_ADDR ((blt_addr)0x40000000) +#define CPU_VECTORS_TABLE_SIZE (64) + + +/**************************************************************************************** +* Register definitions +****************************************************************************************/ +#define MEMMAP (*((volatile blt_int32u *) 0xE01FC040)) + + +/**************************************************************************************** +* External functions +****************************************************************************************/ +extern void Reset_Handler(void); /* reset service routine in cstart.s */ + + +/**************************************************************************************** +** NAME: CpuStartUserProgram +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Starts the user program, if one is present. In this case this function +** does not return. +** +****************************************************************************************/ +void CpuStartUserProgram(void) +{ + void (*pProgResetHandler)(void); + + /* check if a user program is present by verifying the checksum */ + if (NvmVerifyChecksum() == BLT_FALSE) + { + /* not a valid user program so it cannot be started */ + return; + } + + /* copy the user program's interrupt vector table to RAM */ + CpuMemCopy(CPU_RAM_VECTORS_START_ADDR, CPU_USER_PROG_VECTORS_START_ADDR, \ + CPU_VECTORS_TABLE_SIZE); + + /* select RAM vector table */ + MEMMAP = 0x02; + + /* set the address where the bootloader needs to jump to */ + pProgResetHandler = (void*)CPU_RAM_VECTORS_START_ADDR; + + /* start the user program by acticating its reset interrupt service routine */ + pProgResetHandler(); +} /*** end of CpuStartUserProgram ***/ + + +/**************************************************************************************** +** NAME: CpuMemCopy +** PARAMETER: dest destination address for the data. +** src source address of the data. +** len length of the data in bytes. +** RETURN VALUE: none +** DESCRIPTION: Copies data from the source to the destination address. +** +****************************************************************************************/ +void CpuMemCopy(blt_addr dest, blt_addr src, blt_int16u len) +{ + blt_int8u *from, *to; + + /* set casted pointers */ + from = (blt_int8u *)src; + to = (blt_int8u *)dest; + + /* copy all bytes from source address to destination address */ + while(len-- > 0) + { + /* store byte value from source to destination */ + *to++ = *from++; + /* keep the watchdog happy */ + CopService(); + } +} /*** end of CpuMemCopy ***/ + + +/**************************************************************************************** +** NAME: CpuReset +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Perform a soft reset of the microcontroller by starting from the reset +** ISR. +** +****************************************************************************************/ +void CpuReset(void) +{ + /* perform a software reset by calling the reset ISR routine. note that this requires + * access to the processor status registers (PSRs), which works because the entire + * bootloader runs in supervisor mode. + */ + Reset_Handler(); +} /*** end of CpuReset ***/ + + +/*********************************** end of cpu.c **************************************/ diff --git a/Target/Source/ARM7_LPC2000/cpu.h b/Target/Source/ARM7_LPC2000/cpu.h new file mode 100644 index 00000000..3b558162 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/cpu.h @@ -0,0 +1,44 @@ +/**************************************************************************************** +| Description: bootloader cpu module header file +| File Name: cpu.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef CPU_H +#define CPU_H + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void CpuStartUserProgram(void); +void CpuMemCopy(blt_addr dest, blt_addr src, blt_int16u len); +void CpuReset(void); + + +#endif /* CPU_H */ +/*********************************** end of cpu.h **************************************/ diff --git a/Target/Source/ARM7_LPC2000/nvm.c b/Target/Source/ARM7_LPC2000/nvm.c new file mode 100644 index 00000000..a6bc6040 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/nvm.c @@ -0,0 +1,201 @@ +/**************************************************************************************** +| Description: bootloader non-volatile memory driver source file +| File Name: nvm.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +/**************************************************************************************** +* Hook functions +****************************************************************************************/ +#if (BOOT_NVM_HOOKS_ENABLE > 0) +extern void NvmInitHook(void); +extern blt_int8u NvmWriteHook(blt_addr addr, blt_int32u len, blt_int8u *data); +extern blt_int8u NvmEraseHook(blt_addr addr, blt_int32u len); +extern blt_bool NvmDoneHook(void); +#endif + + +/**************************************************************************************** +** NAME: NvmInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the NVM driver. +** +****************************************************************************************/ +void NvmInit(void) +{ +#if (BOOT_NVM_HOOKS_ENABLE > 0) + /* give the application a chance to initialize a driver for operating on NVM + * that is not by default supported by this driver. + */ + NvmInitHook(); +#endif + + /* init the internal driver */ + FlashInit(); +} /*** end of NvmInit ***/ + + +/**************************************************************************************** +** NAME: NvmWrite +** PARAMETER: addr start address +** len length in bytes +** data pointer to the data buffer. +** RETURN VALUE: BLT_TRUE if successful, BLT_FALSE otherwise. +** DESCRIPTION: Programs the non-volatile memory. +** +****************************************************************************************/ +blt_bool NvmWrite(blt_addr addr, blt_int32u len, blt_int8u *data) +{ +#if (BOOT_NVM_HOOKS_ENABLE > 0) + blt_int8u result = BTL_NVM_NOT_IN_RANGE; +#endif + +#if (BOOT_NVM_HOOKS_ENABLE > 0) + /* give the application a chance to operate on memory that is not by default supported + * by this driver. + */ + result = NvmWriteHook(addr, len, data); + + /* process the return code */ + if (result == BTL_NVM_OKAY) + { + /* data was within range of the additionally supported memory and succesfully + * programmed, so we are all done. + */ + return BLT_TRUE; + } + else if (result == BTL_NVM_ERROR) + { + /* data was within range of the additionally supported memory and attempted to be + * programmed, but an error occurred, so we can't continue. + */ + return BLT_FALSE; + } +#endif + + /* still here to the internal driver should try and perform the program operation */ + return FlashWrite(addr, len, data); +} /*** end of NvmWrite ***/ + + +/**************************************************************************************** +** NAME: NvmErase +** PARAMETER: addr start address +** len length in bytes +** RETURN VALUE: BLT_TRUE if successful, BLT_FALSE otherwise. +** DESCRIPTION: Erases the non-volatile memory. +** +****************************************************************************************/ +blt_bool NvmErase(blt_addr addr, blt_int32u len) +{ +#if (BOOT_NVM_HOOKS_ENABLE > 0) + blt_int8u result = BTL_NVM_NOT_IN_RANGE; +#endif + +#if (BOOT_NVM_HOOKS_ENABLE > 0) + /* give the application a chance to operate on memory that is not by default supported + * by this driver. + */ + result = NvmEraseHook(addr, len); + + /* process the return code */ + if (result == BTL_NVM_OKAY) + { + /* address was within range of the additionally supported memory and succesfully + * erased, so we are all done. + */ + return BLT_TRUE; + } + else if (result == BTL_NVM_ERROR) + { + /* address was within range of the additionally supported memory and attempted to be + * erased, but an error occurred, so we can't continue. + */ + return BLT_FALSE; + } +#endif + + /* still here to the internal driver should try and perform the erase operation */ + return FlashErase(addr, len); +} /*** end of NvmErase ***/ + + +/**************************************************************************************** +** NAME: NvmVerifyChecksum +** PARAMETER: none +** RETURN VALUE: BLT_TRUE is successful, BTL_FALSE otherwise. +** DESCRIPTION: Verifies the checksum, which indicates that a valid user program is +** present and can be started. +** +****************************************************************************************/ +blt_bool NvmVerifyChecksum(void) +{ + /* check checksum */ + return FlashVerifyChecksum(); +} /*** end of NvmVerifyChecksum ***/ + + +/**************************************************************************************** +** NAME: NvmDone +** PARAMETER: none +** RETURN VALUE: BLT_TRUE is successful, BLT_FALSE otherwise. +** DESCRIPTION: Once all erase and programming operations are completed, this +** function is called, so at the end of the programming session and +** right before a software reset is performed. It is used to calculate +** a checksum and program this into flash. This checksum is later used +** to determine if a valid user program is present in flash. +** +****************************************************************************************/ +blt_bool NvmDone(void) +{ +#if (BOOT_NVM_HOOKS_ENABLE > 0) + /* give the application's NVM driver a chance to finish up */ + if (NvmDoneHook() == BLT_FALSE) + { + /* error so no need to continue */ + return BLT_FALSE; + } +#endif + /* compute and write checksum, which is programmed by the internal driver */ + if (FlashWriteChecksum() == BLT_FALSE) + { + return BLT_FALSE; + } + /* finish up internal driver operations */ + return FlashDone(); +} /*** end of NvmDone ***/ + + +/*********************************** end of nvm.c **************************************/ diff --git a/Target/Source/ARM7_LPC2000/nvm.h b/Target/Source/ARM7_LPC2000/nvm.h new file mode 100644 index 00000000..943ca0a2 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/nvm.h @@ -0,0 +1,60 @@ +/**************************************************************************************** +| Description: bootloader non-volatile memory driver header file +| File Name: nvm.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef NVM_H +#define NVM_H + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "flash.h" /* LPC2xxx flash driver */ + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void NvmInit(void); +blt_bool NvmWrite(blt_addr addr, blt_int32u len, blt_int8u *data); +blt_bool NvmErase(blt_addr addr, blt_int32u len); +blt_bool NvmVerifyChecksum(void); +blt_bool NvmDone(void); + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/* return codes for hook function NvmWrite/Erase */ +#define BTL_NVM_ERROR (0x00) /* return code for success */ +#define BTL_NVM_OKAY (0x01) /* return code for error */ +#define BTL_NVM_NOT_IN_RANGE (0x02) /* return code for not in range */ + + +#endif /* NVM_H */ +/*********************************** end of nvm.h **************************************/ diff --git a/Target/Source/ARM7_LPC2000/timer.c b/Target/Source/ARM7_LPC2000/timer.c new file mode 100644 index 00000000..d8943a77 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/timer.c @@ -0,0 +1,152 @@ +/**************************************************************************************** +| Description: bootloader timer driver source file +| File Name: timer.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +static blt_int32u free_running_counter_last; +static blt_int32u millisecond_counter; + + +/**************************************************************************************** +* Register definitions +****************************************************************************************/ +#define T0MCR (*((volatile blt_int32u *) 0xE0004014)) +#define T0CCR (*((volatile blt_int32u *) 0xE0004028)) +#define T0PR (*((volatile blt_int32u *) 0xE000400C)) +#define T0PC (*((volatile blt_int32u *) 0xE0004010)) +#define T0TCR (*((volatile blt_int32u *) 0xE0004004)) +#define T0TC (*((volatile blt_int32u *) 0xE0004008)) + + +/**************************************************************************************** +** NAME: TimerInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the polling based millisecond timer driver. +** +****************************************************************************************/ +void TimerInit(void) +{ + /* disable timer 0 interrupts */ + T0MCR = 0x00; + T0CCR = 0x00; + /* set prescaler so that free running counter runs at 1 kHz */ + T0PR = BOOT_CPU_SYSTEM_SPEED_KHZ - 1; + /* start free running counter for timer 0 */ + T0TCR = 0x01; + /* store the start value of the free running counter */ + free_running_counter_last = T0TC; + /* reset the millisecond counter value */ + TimerSet(0); +} /*** end of TimerInit ***/ + + +/**************************************************************************************** +** NAME: TimerReset +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Reset the timer by placing the timer back into it's default reset +** configuration. +** +****************************************************************************************/ +void TimerReset(void) +{ + /* reset the timer */ + T0TCR = 0; + /* reset the prescaler */ + T0PR = 0; + /* reset the timer counter */ + T0TC = 0; + /* reset the prescaled counter */ + T0PC = 0; +} /* TimerReset */ + + +/**************************************************************************************** +** NAME: TimerUpdate +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Updates the millisecond timer. +** +****************************************************************************************/ +void TimerUpdate(void) +{ + blt_int32u free_running_counter_now; + + /* update the millisecond counter */ + free_running_counter_now = T0TC; + millisecond_counter += (free_running_counter_now - free_running_counter_last); + /* store current free running counter value for next time around */ + free_running_counter_last = free_running_counter_now; +} /*** end of TimerUpdate ***/ + + +/**************************************************************************************** +** NAME: TimerSet +** PARAMETER: timer_value initialize value of the millisecond timer. +** RETURN VALUE: none +** DESCRIPTION: Sets the initial counter value of the millisecond timer. +** +****************************************************************************************/ +void TimerSet(blt_int32u timer_value) +{ + /* set the millisecond counter value */ + millisecond_counter = timer_value; +} /*** end of TimerSet ***/ + + +/**************************************************************************************** +** NAME: TimerGet +** PARAMETER: none +** RETURN VALUE: current value of the millisecond timer +** DESCRIPTION: Obtains the counter value of the millisecond timer. +** +****************************************************************************************/ +blt_int32u TimerGet(void) +{ + /* updating timer here allows this function to be called in a loop with timeout + * detection. + */ + TimerUpdate(); + + /* read and return the amount of milliseconds that passed since initialization */ + return millisecond_counter; +} /*** end of TimerGet ***/ + + +/*********************************** end of timer.c ************************************/ diff --git a/Target/Source/ARM7_LPC2000/timer.h b/Target/Source/ARM7_LPC2000/timer.h new file mode 100644 index 00000000..9e7f7e8c --- /dev/null +++ b/Target/Source/ARM7_LPC2000/timer.h @@ -0,0 +1,45 @@ +/**************************************************************************************** +| Description: bootloader timer driver header file +| File Name: timer.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef TIMER_H +#define TIMER_H + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void TimerInit(void); +void TimerUpdate(void); +void TimerSet(blt_int32u timer_value); +blt_int32u TimerGet(void); +void TimerReset(void); + + +#endif /* TIMER_H */ +/*********************************** end of timer.h ************************************/ diff --git a/Target/Source/ARM7_LPC2000/types.h b/Target/Source/ARM7_LPC2000/types.h new file mode 100644 index 00000000..339a0f20 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/types.h @@ -0,0 +1,58 @@ +/**************************************************************************************** +| Description: bootloader types header file +| File Name: types.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef TYPES_H +#define TYPES_H + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +#define BLT_TRUE (1) +#define BLT_FALSE (0) +#define BLT_NULL ((void *)0) + + +/**************************************************************************************** +* Type definitions +****************************************************************************************/ +typedef unsigned char blt_bool; /* boolean type */ +typedef char blt_char; /* character type */ +typedef unsigned long blt_addr; /* memory address type */ +typedef unsigned char blt_int8u; /* 8-bit unsigned integer */ +typedef signed char blt_int8s; /* 8-bit signed integer */ +typedef unsigned short blt_int16u; /* 16-bit unsigned integer */ +typedef signed short blt_int16s; /* 16-bit signed integer */ +typedef unsigned int blt_int32u; /* 32-bit unsigned integer */ +typedef signed int blt_int32s; /* 32-bit signed integer */ + + +#endif /* TYPES_H */ +/*********************************** end of types.h ************************************/ diff --git a/Target/Source/ARM7_LPC2000/uart.c b/Target/Source/ARM7_LPC2000/uart.c new file mode 100644 index 00000000..4bb19095 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/uart.c @@ -0,0 +1,251 @@ +/**************************************************************************************** +| Description: bootloader UART communication interface source file +| File Name: uart.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +#if (BOOT_COM_UART_ENABLE > 0) +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +#define UART_DLAB (0x80) /* divisor latch access bit */ +#define UART_MODE_8N1 (0x03) /* 8 data and 1 stop bit, no parity */ +#define UART_FIFO_RX1 (0x07) /* FIFO reset and RX FIFO 1 deep */ +#define UART_RDR (0x01) /* receiver data ready */ +#define UART_THRE (0x20) /* transmitter holding register empty */ + + +/**************************************************************************************** +* Register definitions +****************************************************************************************/ +#define U0RBR (*((volatile blt_int8u *) 0xE000C000)) +#define U0THR (*((volatile blt_int8u *) 0xE000C000)) +#define U0IER (*((volatile blt_int8u *) 0xE000C004)) +#define U0IIR (*((volatile blt_int8u *) 0xE000C008)) +#define U0FCR (*((volatile blt_int8u *) 0xE000C008)) +#define U0LCR (*((volatile blt_int8u *) 0xE000C00C)) +#define U0LSR (*((volatile blt_int8u *) 0xE000C014)) +#define U0SCR (*((volatile blt_int8u *) 0xE000C01C)) +#define U0DLL (*((volatile blt_int8u *) 0xE000C000)) +#define U0DLM (*((volatile blt_int8u *) 0xE000C004)) + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +static blt_bool UartReceiveByte(blt_int8u *data); +static blt_bool UartTransmitByte(blt_int8u data); + + +/**************************************************************************************** +** NAME: UartInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the UART communication interface +** +****************************************************************************************/ +void UartInit(void) +{ + blt_int32u baud_reg_value; /* baudrate register value */ + + /* the current implementation supports UART0. throw an assertion error in case + * a different UART channel is configured. + */ + ASSERT_CT(BOOT_COM_UART_CHANNEL_INDEX == 0); + /* disable UART related interrupt generation. this driver works in polling mode */ + U0IER = 0; + /* clear interrupt id register */ + U0IIR = 0; + /* clear line status register */ + U0LSR = 0; + /* set divisor latch DLAB = 1 so buadrate can be configured */ + U0LCR = UART_DLAB; + /* Baudrate calculation: + * y = BOOT_CPU_SYSTEM_SPEED_KHZ * 1000 / 16 / BOOT_COM_UART_BAUDRATE and add + * smartness to automatically round the value up/down using the following trick: + * y = x/n can round with y = (x + (n + 1)/2 ) / n + */ + /* check that baudrate register value is not 0 */ + ASSERT_CT((((BOOT_CPU_SYSTEM_SPEED_KHZ*1000/16)+((BOOT_COM_UART_BAUDRATE+1)/2))/ \ + BOOT_COM_UART_BAUDRATE) > 0); + /* check that baudrate register value is not greater than max 16-bit unsigned value */ + ASSERT_CT((((BOOT_CPU_SYSTEM_SPEED_KHZ*1000/16)+((BOOT_COM_UART_BAUDRATE+1)/2))/ \ + BOOT_COM_UART_BAUDRATE) <= 65535); + baud_reg_value = (((BOOT_CPU_SYSTEM_SPEED_KHZ*1000/16)+ \ + ((BOOT_COM_UART_BAUDRATE+1)/2))/BOOT_COM_UART_BAUDRATE); + /* write the calculated baudrate selector value to the registers */ + U0DLL = (blt_int8u)baud_reg_value; + U0DLM = (blt_int8u)(baud_reg_value >> 8); + /* configure 8 data bits, no parity and 1 stop bit and set DLAB = 0 */ + U0LCR = UART_MODE_8N1; + /* enable and reset transmit and receive FIFO. necessary for UART operation */ + U0FCR = UART_FIFO_RX1; +} /*** end of UartInit ***/ + + +/**************************************************************************************** +** NAME: UartTransmitPacket +** PARAMETER: data pointer to byte array with data that it to be transmitted. +** len number of bytes that are to be transmitted. +** RETURN VALUE: none +** DESCRIPTION: Transmits a packet formatted for the communication interface. +** +****************************************************************************************/ +void UartTransmitPacket(blt_int8u *data, blt_int8u len) +{ + blt_int16u data_index; + + /* verify validity of the len-paramenter */ + ASSERT_RT(len <= BOOT_COM_TX_MAX_DATA); + + /* first transmit the length of the packet */ + ASSERT_RT(UartTransmitByte(len) == BLT_TRUE); + + /* transmit all the packet bytes one-by-one */ + for (data_index = 0; data_index < len; data_index++) + { + /* keep the watchdog happy */ + CopService(); + /* write byte */ + ASSERT_RT(UartTransmitByte(data[data_index]) == BLT_TRUE); + } +} /*** end of UartTransmitPacket ***/ + + +/**************************************************************************************** +** NAME: UartReceivePacket +** PARAMETER: data pointer to byte array where the data is to be stored. +** RETURN VALUE: BLT_TRUE if a packet was received, BLT_FALSE otherwise. +** DESCRIPTION: Receives a communication interface packet if one is present. +** +****************************************************************************************/ +blt_bool UartReceivePacket(blt_int8u *data) +{ + static blt_int8u xcpCtoReqPacket[XCP_CTO_PACKET_LEN+1]; /* one extra for length */ + static blt_int8u xcpCtoRxLength; + static blt_bool xcpCtoRxInProgress = BLT_FALSE; + + /* start of cto packet received? */ + if (xcpCtoRxInProgress == BLT_FALSE) + { + /* store the message length when received */ + if (UartReceiveByte(&xcpCtoReqPacket[0]) == BLT_TRUE) + { + /* indicate that a cto packet is being received */ + xcpCtoRxInProgress = BLT_TRUE; + + /* reset packet data count */ + xcpCtoRxLength = 0; + } + } + else + { + /* store the next packet byte */ + if (UartReceiveByte(&xcpCtoReqPacket[xcpCtoRxLength+1]) == BLT_TRUE) + { + /* increment the packet data count */ + xcpCtoRxLength++; + + /* check to see if the entire packet was received */ + if (xcpCtoRxLength == xcpCtoReqPacket[0]) + { + /* copy the packet data */ + CpuMemCopy((blt_int32u)data, (blt_int32u)&xcpCtoReqPacket[1], xcpCtoRxLength); + /* done with cto packet reception */ + xcpCtoRxInProgress = BLT_FALSE; + + /* packet reception complete */ + return BLT_TRUE; + } + } + } + + /* packet reception not yet complete */ + return BLT_FALSE; +} /*** end of UartReceivePacket ***/ + + +/**************************************************************************************** +** NAME: UartReceiveByte +** PARAMETER: data pointer to byte where the data is to be stored. +** RETURN VALUE: BLT_TRUE if a byte was received, BLT_FALSE otherwise. +** DESCRIPTION: Receives a communication interface byte if one is present. +** +****************************************************************************************/ +static blt_bool UartReceiveByte(blt_int8u *data) +{ + /* check if a new byte was received by means of the RDR-bit */ + if((U0LSR & UART_RDR) != 0) + { + /* store the received byte */ + data[0] = U0RBR; + /* inform caller of the newly received byte */ + return BLT_TRUE; + } + /* inform caller that no new data was received */ + return BLT_FALSE; +} /*** end of UartReceiveByte ***/ + + +/**************************************************************************************** +** NAME: UartTransmitByte +** PARAMETER: data value of byte that is to be transmitted. +** RETURN VALUE: BLT_TRUE if the byte was transmitted, BLT_FALSE otherwise. +** DESCRIPTION: Transmits a communication interface byte. +** +****************************************************************************************/ +static blt_bool UartTransmitByte(blt_int8u data) +{ + /* check if tx holding register can accept new data and throw assertion error if not */ + if ((U0LSR & UART_THRE) == 0) + { + /* UART not ready. should not happen */ + return BLT_FALSE; + } + /* write byte to transmit holding register */ + U0THR = data; + /* wait for tx holding register to be empty */ + while((U0LSR & UART_THRE) == 0) + { + /* keep the watchdog happy */ + CopService(); + } + /* byte transmitted */ + return BLT_TRUE; +} /*** end of UartTransmitByte ***/ +#endif /* BOOT_COM_UART_ENABLE > 0 */ + + +/*********************************** end of uart.c *************************************/ diff --git a/Target/Source/ARM7_LPC2000/uart.h b/Target/Source/ARM7_LPC2000/uart.h new file mode 100644 index 00000000..9121ac81 --- /dev/null +++ b/Target/Source/ARM7_LPC2000/uart.h @@ -0,0 +1,45 @@ +/**************************************************************************************** +| Description: bootloader UART communication interface header file +| File Name: uart.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef UART_H +#define UART_H + +#if (BOOT_COM_UART_ENABLE > 0) +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void UartInit(void); +void UartTransmitPacket(blt_int8u *data, blt_int8u len); +blt_bool UartReceivePacket(blt_int8u *data); +#endif /* BOOT_COM_UART_ENABLE > 0 */ + + +#endif /* UART_H */ +/*********************************** end of uart.h *************************************/ diff --git a/Target/Source/assert.c b/Target/Source/assert.c new file mode 100644 index 00000000..1a56d4ec --- /dev/null +++ b/Target/Source/assert.c @@ -0,0 +1,70 @@ +/**************************************************************************************** +| Description: bootloader assertion module source file +| File Name: assert.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +#ifndef NDEBUG +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +static volatile blt_char *assert_failure_file; +static volatile blt_int32u assert_failure_line; + + +/**************************************************************************************** +** NAME: AssertFailure +** PARAMETER: file name of the source file where the assertion occurred. +** line linenumber in the source file where the assertion occurred. +** RETURN VALUE: none +** DESCRIPTION: Called when a runtime assertion failed. It stores information about +** where the assertion occurred and halts the software program. +** +****************************************************************************************/ +void AssertFailure(blt_char *file, blt_int32u line) +{ + /* store the file string and line number so that it can be read on a breakpoint*/ + assert_failure_file = file; + assert_failure_line = line; + /* hang the software so that it requires a hard reset */ + for(;;) + { + /* keep servicing the watchdog so that this one does not cause a reset */ + CopService(); + } +} /*** end of AssertFailure ***/ +#endif /* !NDEBUG */ + + +/*********************************** end of assert.c ***********************************/ diff --git a/Target/Source/assert.h b/Target/Source/assert.h new file mode 100644 index 00000000..e366c445 --- /dev/null +++ b/Target/Source/assert.h @@ -0,0 +1,63 @@ +/**************************************************************************************** +| Description: bootloader assertion module header file +| File Name: assert.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef ASSERT_H +#define ASSERT_H + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/* declare assertion macro's. ASSERT_CT is for compile time assertions and ASSERT_RT is + * for runtime assertions. + */ +#ifdef NDEBUG + #define ASSERT_CT(cond) ((void)0) + #define ASSERT_RT(cond) ((void)0) +#else + #define ASSERT_CONCAT_(a, b) a##b + #define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) + #define ASSERT_CT(cond) enum { ASSERT_CONCAT(assert_error_on_line_, __LINE__) = 1/(!!(cond)) } + #define ASSERT_RT(cond) \ + if (cond) \ + { ; } \ + else \ + AssertFailure(__FILE__, __LINE__) +#endif /* NDEBUG */ + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +#ifndef NDEBUG +void AssertFailure(blt_char *file, blt_int32u line); +#endif + +#endif /* ASSERT_H */ +/*********************************** end of assert.h ***********************************/ diff --git a/Target/Source/backdoor.c b/Target/Source/backdoor.c new file mode 100644 index 00000000..84d0944f --- /dev/null +++ b/Target/Source/backdoor.c @@ -0,0 +1,135 @@ +/**************************************************************************************** +| Description: bootloader backdoor entry source file +| File Name: backdoor.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0) + /* set the time in milliseconds that the backdoor is open */ + #define BACKDOOR_ENTRY_TIMEOUT_MS (50) +#endif + +/**************************************************************************************** +* Hook functions +****************************************************************************************/ +#if (BOOT_BACKDOOR_HOOKS_ENABLE > 0) +void BackDoorInitHook(void); +blt_bool BackDoorEntryHook(void); +#endif + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0) +static blt_bool backdoorOpen; +#endif + + +/**************************************************************************************** +** NAME: BackDoorInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the backdoor entry option. +** +****************************************************************************************/ +void BackDoorInit(void) +{ +#if (BOOT_BACKDOOR_HOOKS_ENABLE > 0) + /* initialize application's backdoor functionality */ + BackDoorInitHook(); + + /* attempt to start the user program when no backdoor entry is requested or + * a pending COM module connection request. + */ + if ( (BackDoorEntryHook() == BLT_FALSE) && (ComIsConnectEntryState() == BLT_FALSE) ) + { + /* this function does not return if a valid user program is present */ + CpuStartUserProgram(); + } + +#else + /* open the backdoor after a reset */ + backdoorOpen = BLT_TRUE; + /* initialize default backdoor entry */ + TimerInit(); +#endif + /* perform the first check that open/closes the backdoor */ + BackDoorCheck(); +} /*** end of BackDoorInit ***/ + + +/**************************************************************************************** +** NAME: BackDoorCheck +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: The default backdoor entry feature keeps the bootloader active for a +** predetermined time after reset, allowing the host application to +** establish a connection and start a programming sequence. This function +** controls the opening/closing of the backdoor. +** +****************************************************************************************/ +void BackDoorCheck(void) +{ +#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0) + /* check if a connection with the host was already established. in this case the + * backdoor stays open anyway, so no need to check if it needs to be closed + */ + if (ComIsConnected() == BLT_TRUE) + { + return; + } + + /* when the backdoor is still open, check if it's time to close it */ + if (backdoorOpen == BLT_TRUE) + { + /* check if the backdoor entry time window elapsed */ + if (TimerGet() >= BACKDOOR_ENTRY_TIMEOUT_MS) + { + /* close the backdoor */ + backdoorOpen = BLT_FALSE; + /* reset the timer */ + TimerReset(); + /* this function does not return if a valid user program is present */ + CpuStartUserProgram(); + } + } +#endif +} /*** end of BackDoorCheck ***/ + + +/*********************************** end of backdoor.c *********************************/ diff --git a/Target/Source/backdoor.h b/Target/Source/backdoor.h new file mode 100644 index 00000000..007cb48b --- /dev/null +++ b/Target/Source/backdoor.h @@ -0,0 +1,41 @@ +/**************************************************************************************** +| Description: bootloader backdoor entry header file +| File Name: backdoor.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef BACKDOOR_H +#define BACKDOOR_H + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void BackDoorInit(void); +void BackDoorCheck(void); + +#endif /* BACKDOOR_H */ +/*********************************** end of backdoor.h *********************************/ diff --git a/Target/Source/boot.c b/Target/Source/boot.c new file mode 100644 index 00000000..fb31811c --- /dev/null +++ b/Target/Source/boot.c @@ -0,0 +1,76 @@ +/**************************************************************************************** +| Description: bootloader core module source file +| File Name: boot.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +/**************************************************************************************** +** NAME: BootInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the bootloader core. +** +****************************************************************************************/ +void BootInit(void) +{ + /* initialize the watchdog */ + CopInit(); + /* initialize the backdoor entry */ + BackDoorInit(); + /* initialize the non-volatile memory driver */ + NvmInit(); + /* initialize the communication module */ + ComInit(); +} /*** end of BootInit ***/ + + +/**************************************************************************************** +** NAME: BootTask +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Task function of the bootloader core that drives the program. +** +****************************************************************************************/ +void BootTask(void) +{ + /* service the watchdog */ + CopService(); + /* process possibly pending communication data */ + ComTask(); + /* control the backdoor */ + BackDoorCheck(); +} /*** end of BootTask ***/ + + +/*********************************** end of boot.c *************************************/ diff --git a/Target/Source/boot.h b/Target/Source/boot.h new file mode 100644 index 00000000..880004f7 --- /dev/null +++ b/Target/Source/boot.h @@ -0,0 +1,58 @@ +/**************************************************************************************** +| Description: bootloader core module header file +| File Name: boot.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef BOOT_H +#define BOOT_H + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "types.h" /* variable types */ +#include "assert.h" /* assertion checks */ +#include "config.h" /* bootloader configuration */ +#include "plausibility.h" /* plausibility checks */ +#include "cpu.h" /* cpu driver module */ +#include "cop.h" /* watchdog driver module */ +#include "nvm.h" /* memory driver module */ +#include "timer.h" /* timer driver module */ +#include "backdoor.h" /* backdoor entry module */ +#include "com.h" /* communication interface */ +#include "xcp.h" /* xcp communication layer */ + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void BootInit(void); +void BootTask(void); + + +#endif /* BOOT_H */ +/*********************************** end of boot.h *************************************/ diff --git a/Target/Source/com.c b/Target/Source/com.c new file mode 100644 index 00000000..805ade4e --- /dev/null +++ b/Target/Source/com.c @@ -0,0 +1,191 @@ +/**************************************************************************************** +| Description: bootloader communication interface source file +| File Name: com.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ +#if (BOOT_COM_CAN_ENABLE > 0) + #include "can.h" /* can driver module */ +#endif +#if (BOOT_COM_UART_ENABLE > 0) + #include "uart.h" /* uart driver module */ +#endif + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/* This variable holds state information about the bootloader being started by a reset + * event or by an activation from a running user program. In the latter case, the COM + * interface should proceed after initialization as if it already received a connection + * request, which the running user program did before it activated the bootloader. It's + * volatile because some targets might call functions that access this variable from + * assembly, which might cause the C compiler to incorrectly remove this variable during + * an optimization step. + */ +static volatile blt_bool comEntryStateConnect = BLT_FALSE; + + +/**************************************************************************************** +** NAME: ComInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the communication module including the hardware needed for +** the communication. +** +****************************************************************************************/ +void ComInit(void) +{ + blt_int8u xcpCtoConnectCmdPacket[2] = { 0xff, 0x00 }; + + /* initialize the XCP communication protocol */ + XcpInit(); +#if (BOOT_COM_CAN_ENABLE > 0) + /* initialize the CAN controller */ + CanInit(); +#endif +#if (BOOT_COM_UART_ENABLE > 0) + /* initialize the UART interface */ + UartInit(); +#endif + /* simulate the reception of a CONNECT command if requested */ + if (comEntryStateConnect == BLT_TRUE) + { + XcpPacketReceived(&xcpCtoConnectCmdPacket[0]); + } +} /*** end of ComInit ***/ + + +/**************************************************************************************** +** NAME: ComTask +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Updates the communication module by checking if new data was received +** and submitting the request to process newly received data. +** +****************************************************************************************/ +void ComTask(void) +{ + /* make xcpCtoReqPacket static for runtime efficiency */ +#if (BOOT_COM_CAN_ENABLE > 0) + static unsigned char xcpCtoReqPacket[BOOT_COM_CAN_RX_MAX_DATA]; +#endif +#if (BOOT_COM_UART_ENABLE > 0) + static unsigned char xcpCtoReqPacket[BOOT_COM_UART_RX_MAX_DATA]; +#endif + +#if (BOOT_COM_CAN_ENABLE > 0) + if (CanReceivePacket(&xcpCtoReqPacket[0]) == BLT_TRUE) + { + /* process packet */ + XcpPacketReceived(&xcpCtoReqPacket[0]); + } +#endif +#if (BOOT_COM_UART_ENABLE > 0) + if (UartReceivePacket(&xcpCtoReqPacket[0]) == BLT_TRUE) + { + /* process packet */ + XcpPacketReceived(&xcpCtoReqPacket[0]); + } +#endif +} /*** end of ComTask ***/ + + +/**************************************************************************************** +** NAME: ComTransmitPacket +** PARAMETER: data pointer to the byte buffer with packet data. +** len number of data bytes that need to be transmitted. +** RETURN VALUE: none +** DESCRIPTION: Transmits the packet using the xcp transport layer. +** +****************************************************************************************/ +void ComTransmitPacket(blt_int8u *data, blt_int16u len) +{ +#if (BOOT_COM_CAN_ENABLE > 0) + /* transmit the packet. note that len can only be 8 on CAN, so cast is okay */ + CanTransmitPacket(data, (blt_int8u)len); +#endif +#if (BOOT_COM_UART_ENABLE > 0) + /* transmit the packet */ + UartTransmitPacket(data, len); +#endif + + /* send signal that the packet was transmitted */ + XcpPacketTransmitted(); +} /*** end of ComTransmitPacket ***/ + + +/**************************************************************************************** +** NAME: ComSetConnectEntryState +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: This function should be called by the function that is called to +** enter the bootloader from a running user program after the stack +** pointer, data section and bss section are initialized, but before +** function main is called. It stores state information that indicates +** that the COM module must be initialized in a connected state. +** +****************************************************************************************/ +void ComSetConnectEntryState(void) +{ + comEntryStateConnect = BLT_TRUE; +} /*** end of ComSetConnectEntryState ***/ + + +/**************************************************************************************** +** NAME: ComIsConnectEntryState +** PARAMETER: none +** RETURN VALUE: BLT_TRUE is there is a pending connection request, BLT_FALSE otherwise +** DESCRIPTION: This function checks if there is a pending request for a connection +** upon COM module initialization. +** +****************************************************************************************/ +blt_bool ComIsConnectEntryState(void) +{ + return comEntryStateConnect; +} /*** end of ComIsConnectEntryState ***/ + + +/**************************************************************************************** +** NAME: ComIsConnected +** PARAMETER: none +** RETURN VALUE: BLT_TRUE when an XCP connection is established, BLT_FALSE otherwise. +** DESCRIPTION: This function obtains the XCP connection state. +** +****************************************************************************************/ +blt_bool ComIsConnected(void) +{ + return XcpIsConnected(); +} /*** end of ComIsConnected ***/ + + +/*********************************** end of com.c **************************************/ diff --git a/Target/Source/com.h b/Target/Source/com.h new file mode 100644 index 00000000..9e80d429 --- /dev/null +++ b/Target/Source/com.h @@ -0,0 +1,63 @@ +/**************************************************************************************** +| Description: bootloader communication interface header file +| File Name: com.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef COM_H +#define COM_H + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +#if (BOOT_COM_CAN_ENABLE > 0) + #define BOOT_COM_TX_MAX_DATA (BOOT_COM_CAN_TX_MAX_DATA) + #define BOOT_COM_RX_MAX_DATA (BOOT_COM_CAN_RX_MAX_DATA) +#endif +#if (BOOT_COM_UART_ENABLE > 0) + #define BOOT_COM_TX_MAX_DATA (BOOT_COM_UART_TX_MAX_DATA) + #define BOOT_COM_RX_MAX_DATA (BOOT_COM_UART_RX_MAX_DATA) +#endif + + + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void ComInit(void); +void ComTask(void); +void ComTransmitPacket(blt_int8u *data, blt_int16u len); +void ComSetConnectEntryState(void); +blt_bool ComIsConnectEntryState(void); +void ComSetConnected(blt_bool connected); +blt_bool ComIsConnected(void); + + +#endif /* COM_H */ +/*********************************** end of com.h **************************************/ diff --git a/Target/Source/cop.c b/Target/Source/cop.c new file mode 100644 index 00000000..f5c2904f --- /dev/null +++ b/Target/Source/cop.c @@ -0,0 +1,77 @@ +/**************************************************************************************** +| Description: bootloader watchdog module source file +| File Name: cop.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +/**************************************************************************************** +* Hook functions +****************************************************************************************/ +#if (BOOT_COP_HOOKS_ENABLE > 0) +extern void CopInitHook(void); +extern void CopServiceHook(void); +#endif + + +/**************************************************************************************** +** NAME: CopInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Watchdog initialization function +** +****************************************************************************************/ +void CopInit(void) +{ +#if (BOOT_COP_HOOKS_ENABLE > 0) + CopInitHook(); +#endif +} /*** end of CopInit ***/ + + +/**************************************************************************************** +** NAME: CopService +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Watchdog service function to prevent the watchdog from timing out. +** +****************************************************************************************/ +void CopService(void) +{ +#if (BOOT_COP_HOOKS_ENABLE > 0) + CopServiceHook(); +#endif +} /*** end of CopService ***/ + + +/*********************************** end of cop.c **************************************/ diff --git a/Target/Source/cop.h b/Target/Source/cop.h new file mode 100644 index 00000000..b70a8af4 --- /dev/null +++ b/Target/Source/cop.h @@ -0,0 +1,42 @@ +/**************************************************************************************** +| Description: bootloader watchdog module header file +| File Name: cop.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef COP_H +#define COP_H + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void CopInit(void); +void CopService(void); + + +#endif /* COP_H */ +/*********************************** end of cop.h **************************************/ diff --git a/Target/Source/plausibility.h b/Target/Source/plausibility.h new file mode 100644 index 00000000..1ca171f8 --- /dev/null +++ b/Target/Source/plausibility.h @@ -0,0 +1,212 @@ +/**************************************************************************************** +| Description: bootloader plausibility check header file +| File Name: plausibility.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef PLAUSIBILITY_H +#define PLAUSIBILITY_H + +/**************************************************************************************** +* C P U D R I V E R C O N F I G U R A T I O N C H E C K +****************************************************************************************/ +#ifndef BOOT_CPU_XTAL_SPEED_KHZ +#error "BOOT_CPU_XTAL_SPEED_KHZ is missing in config.h" +#endif + +#if (BOOT_CPU_XTAL_SPEED_KHZ <= 0) +#error "BOOT_CPU_XTAL_SPEED_KHZ must be > 0" +#endif + +#ifndef BOOT_CPU_SYSTEM_SPEED_KHZ +#error "BOOT_CPU_SYSTEM_SPEED_KHZ is missing in config.h" +#endif + +#if (BOOT_CPU_SYSTEM_SPEED_KHZ <= 0) +#error "BOOT_CPU_SYSTEM_SPEED_KHZ must be > 0" +#endif + +#ifndef BOOT_CPU_BYTE_ORDER_MOTOROLA +#error "BOOT_CPU_BYTE_ORDER_MOTOROLA is missing in config.h" +#endif + +#if (BOOT_CPU_BYTE_ORDER_MOTOROLA < 0) || (BOOT_CPU_BYTE_ORDER_MOTOROLA > 1) +#error "BOOT_CPU_BYTE_ORDER_MOTOROLA must be 0 or 1" +#endif + + +/**************************************************************************************** +* C O M M U N I C A T I O N I N T E R F A C E C O N F I G U R A T I O N C H E C K +****************************************************************************************/ +#ifndef BOOT_COM_CAN_ENABLE +#define BOOT_COM_CAN_ENABLE (0) +#endif + +#if (BOOT_COM_CAN_ENABLE > 0) + #ifndef BOOT_COM_CAN_BAUDRATE + #error "BOOT_COM_CAN_BAUDRATE is missing in config.h" + #endif + + #if (BOOT_COM_CAN_BAUDRATE <= 0) + #error "BOOT_COM_CAN_BAUDRATE must be > 0" + #endif + + #ifndef BOOT_COM_CAN_TX_MSG_ID + #error "BOOT_COM_CAN_TX_MSG_ID is missing in config.h" + #endif + + #if (BOOT_COM_CAN_TX_MSG_ID <= 0) + #error "BOOT_COM_CAN_TX_MSG_ID must be > 0" + #endif + + #ifndef BOOT_COM_CAN_TX_MAX_DATA + #error "BOOT_COM_CAN_TX_MAX_DATA is missing in config.h" + #endif + + #if (BOOT_COM_CAN_TX_MAX_DATA <= 0) + #error "BOOT_COM_CAN_TX_MAX_DATA must be > 0" + #endif + + #ifndef BOOT_COM_CAN_RX_MSG_ID + #error "BOOT_COM_CAN_RX_MSG_ID is missing in config.h" + #endif + + #if (BOOT_COM_CAN_RX_MSG_ID <= 0) + #error "BOOT_COM_CAN_RX_MSG_ID must be > 0" + #endif + + #ifndef BOOT_COM_CAN_RX_MAX_DATA + #error "BOOT_COM_CAN_RX_MAX_DATA is missing in config.h" + #endif + + #if (BOOT_COM_CAN_RX_MAX_DATA <= 0) + #error "BOOT_COM_CAN_RX_MAX_DATA must be > 0" + #endif + + #ifndef BOOT_COM_CAN_CHANNEL_INDEX + #error "BOOT_COM_CAN_CHANNEL_INDEX is missing in config.h" + #endif + + #if (BOOT_COM_CAN_CHANNEL_INDEX < 0) + #error "BOOT_COM_CAN_CHANNEL_INDEX must be >= 0" + #endif +#endif /* BOOT_COM_CAN_ENABLE > 0 */ + +#ifndef BOOT_COM_UART_ENABLE +#define BOOT_COM_UART_ENABLE (0) +#endif + +#if (BOOT_COM_UART_ENABLE > 0) + #ifndef BOOT_COM_UART_BAUDRATE + #error "BOOT_COM_UART_BAUDRATE is missing in config.h" + #endif + + #if (BOOT_COM_UART_BAUDRATE <= 0) + #error "BOOT_COM_UART_BAUDRATE must be > 0" + #endif + + #ifndef BOOT_COM_UART_TX_MAX_DATA + #error "BOOT_COM_UART_TX_MAX_DATA is missing in config.h" + #endif + + #if (BOOT_COM_UART_TX_MAX_DATA <= 0) + #error "BOOT_COM_UART_TX_MAX_DATA must be > 0" + #endif + + #ifndef BOOT_COM_UART_RX_MAX_DATA + #error "BOOT_COM_UART_RX_MAX_DATA is missing in config.h" + #endif + + #if (BOOT_COM_UART_RX_MAX_DATA <= 0) + #error "BOOT_COM_UART_RX_MAX_DATA must be > 0" + #endif + + #ifndef BOOT_COM_UART_CHANNEL_INDEX + #error "BOOT_COM_UART_CHANNEL_INDEX is missing in config.h" + #endif + + #if (BOOT_COM_UART_CHANNEL_INDEX < 0) + #error "BOOT_COM_UART_CHANNEL_INDEX must be >= 0" + #endif +#endif /* BOOT_COM_UART_ENABLE > 0 */ + +#if (BOOT_COM_CAN_ENABLE == 0) && \ + (BOOT_COM_UART_ENABLE == 0) +#error "No communication interface enabled (BOOT_COM_XXX_ENABLE) in config.h" +#endif + +#if ((BOOT_COM_CAN_ENABLE + BOOT_COM_UART_ENABLE) > 1) +#error "Too many communication interfaces enabled (BOOT_COM_XXX_ENABLE) in config.h" +#endif + + +/**************************************************************************************** +* B A C K D O O R E N T R Y C H E C K +****************************************************************************************/ +#ifndef BOOT_BACKDOOR_HOOKS_ENABLE +#define BOOT_BACKDOOR_HOOKS_ENABLE (0) +#endif + +#if (BOOT_BACKDOOR_HOOKS_ENABLE < 0) || (BOOT_BACKDOOR_HOOKS_ENABLE > 1) +#error "BOOT_BACKDOOR_HOOKS_ENABLE must be 0 or 1" +#endif + + +/**************************************************************************************** +* N V M D R I V E R C O N F I G U R A T I O N C H E C K +****************************************************************************************/ +#ifndef BOOT_NVM_HOOKS_ENABLE +#define BOOT_NVM_HOOKS_ENABLE (0) +#endif + +#if (BOOT_NVM_HOOKS_ENABLE < 0) || (BOOT_NVM_HOOKS_ENABLE > 1) +#error "BOOT_NVM_HOOKS_ENABLE must be 0 or 1" +#endif + +#ifndef BOOT_NVM_SIZE_KB +#error "BOOT_NVM_SIZE_KB is missing in config.h" +#endif + +#if (BOOT_NVM_SIZE_KB <= 0) +#error "BOOT_NVM_SIZE_KB must be > 0" +#endif + + +/**************************************************************************************** +* W A T C H D O G D R I V E R C O N F I G U R A T I O N C H E C K +****************************************************************************************/ +#ifndef BOOT_COP_HOOKS_ENABLE +#define BOOT_COP_HOOKS_ENABLE (0) +#endif + +#if (BOOT_COP_HOOKS_ENABLE < 0) || (BOOT_COP_HOOKS_ENABLE > 1) +#error "BOOT_COP_HOOKS_ENABLE must be 0 or 1" +#endif + + +#endif /* PLAUSIBILITY_H */ +/*********************************** end of plausibility.h *****************************/ diff --git a/Target/Source/xcp.c b/Target/Source/xcp.c new file mode 100644 index 00000000..138d4a0d --- /dev/null +++ b/Target/Source/xcp.c @@ -0,0 +1,1326 @@ +/**************************************************************************************** +| Description: XCP 1.0 protocol core source file +| File Name: xcp.c +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include "boot.h" /* bootloader generic header */ + + +/**************************************************************************************** +* Defines +****************************************************************************************/ +/* XCP protocol layer version number (16-bit) */ +#define XCP_VERSION_PROTOCOL_LAYER (0x0100) + +/* XCP transport layer version number (16-bit) */ +#define XCP_VERSION_TRANSPORT_LAYER (0x0100) + +/* XCP packet identifiers */ +#define XCP_PID_RES (0xff) /* command response packet */ +#define XCP_PID_ERR (0xfe) /* error packet */ + +/* XCP error codes */ +#define XCP_ERR_CMD_SYNCH (0x00) /* cmd processor synchronization */ +#define XCP_ERR_CMD_BUSY (0x10) /* command was not executed */ +#define XCP_ERR_CMD_UNKNOWN (0x20) /* unknown or unsupported command*/ +#define XCP_ERR_OUT_OF_RANGE (0x22) /* parameter out of range */ +#define XCP_ERR_ACCESS_LOCKED (0x25) /* protected. seed/key required */ +#define XCP_ERR_PAGE_NOT_VALID (0x26) /* cal page not valid */ +#define XCP_ERR_SEQUENCE (0x29) /* sequence error */ +#define XCP_ERR_GENERIC (0x31) /* generic error */ + +/* XCP command codes */ +#define XCP_CMD_CONNECT (0xff) /* CONNECT command code */ +#define XCP_CMD_DISCONNECT (0xfe) /* DISCONNECT command code */ +#define XCP_CMD_GET_STATUS (0xfd) /* GET_STATUS command code */ +#define XCP_CMD_SYNCH (0xfc) /* SYNCH command code */ +#define XCP_CMD_GET_ID (0xfa) /* GET_ID command code */ +#define XCP_CMD_GET_SEED (0xf8) /* GET_SEED command code */ +#define XCP_CMD_UNLOCK (0xf7) /* UNLOCK command code */ +#define XCP_CMD_SET_MTA (0xf6) /* SET_MTA command code */ +#define XCP_CMD_UPLOAD (0xf5) /* UPLOAD command code */ +#define XCP_CMD_SHORT_UPLOAD (0xf4) /* SHORT_UPLOAD command code */ +#define XCP_CMD_BUILD_CHECKSUM (0xf3) /* BUILD_CHECKSUM command code */ +#define XCP_CMD_DOWNLOAD (0xf0) /* DOWNLOAD command code */ +#define XCP_CMD_DOWLOAD_MAX (0xee) /* DOWNLOAD_MAX command code */ +#define XCP_CMD_SET_CAL_PAGE (0xeb) /* SET_CALPAGE command code */ +#define XCP_CMD_GET_CAL_PAGE (0xea) /* GET_CALPAGE command code */ +#define XCP_CMD_PROGRAM_START (0xd2) /* PROGRAM_START command code */ +#define XCP_CMD_PROGRAM_CLEAR (0xd1) /* PROGRAM_CLEAR command code */ +#define XCP_CMD_PROGRAM (0xd0) /* PROGRAM command code */ +#define XCP_CMD_PROGRAM_RESET (0xcf) /* PROGRAM_RESET command code */ +#define XCP_CMD_PROGRAM_PREPARE (0xcc) /* PROGRAM_PREPARE command code */ +#define XCP_CMD_PROGRAM_MAX (0xc9) /* PROGRAM_MAX command code */ + + +/**************************************************************************************** +* Type definitions +****************************************************************************************/ +/* XCP internal module information type */ +typedef struct +{ + blt_int8u connected; /* connection established */ + blt_int8u protection; /* protection state */ + blt_int8u s_n_k_resource; /* for seed/key sequence */ + blt_int8u ctoData[XCP_CTO_PACKET_LEN]; /* cto packet data buffer */ + blt_int8u ctoPending; /* cto transmission pending flag */ + blt_int16s ctoLen; /* cto current packet length */ + blt_int32u mta; /* memory transfer address */ +} tXcpInfo; + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +/* transport layer specific functions */ +static void XcpTransmitPacket(blt_int8u *data, blt_int16s len); + +/* application specific functions */ +static blt_int8u XcpComputeChecksum(blt_int32u address, blt_int32u length, + blt_int32u *checksum); + +#if (XCP_SEED_KEY_PROTECTION_EN == 1) +static blt_int8u XcpGetSeed(blt_int8u resource, blt_int8u *seed); +static blt_int8u XcpVerifyKey(blt_int8u resource, blt_int8u *key, blt_int8u len); +#endif + +/* general utility functions */ +static void XcpProtectResources(void); +static void XcpSetCtoError(blt_int8u error); + +/* XCP command processors */ +static void XcpCmdConnect(blt_int8u *data); +static void XcpCmdDisconnect(blt_int8u *data); +static void XcpCmdGetStatus(blt_int8u *data); +static void XcpCmdSynch(blt_int8u *data); +static void XcpCmdGetId(blt_int8u *data); +static void XcpCmdSetMta(blt_int8u *data); +static void XcpCmdUpload(blt_int8u *data); +static void XcpCmdShortUpload(blt_int8u *data); +static void XcpCmdBuildCheckSum(blt_int8u *data); +#if (XCP_SEED_KEY_PROTECTION_EN == 1) +static void XcpCmdGetSeed(blt_int8u *data); +static void XcpCmdUnlock(blt_int8u *data); +#endif +#if (XCP_RES_CALIBRATION_EN == 1) +static void XcpCmdDownload(blt_int8u *data); +static void XcpCmdDownloadMax(blt_int8u *data); +#endif +#if (XCP_RES_PAGING_EN == 1) +static void XcpCmdSetCalPage(blt_int8u *data); +static void XcpCmdGetCalPage(blt_int8u *data); +#endif +#if (XCP_RES_PROGRAMMING_EN == 1) +static void XcpCmdProgramMax(blt_int8u *data); +static void XcpCmdProgram(blt_int8u *data); +static void XcpCmdProgramStart(blt_int8u *data); +static void XcpCmdProgramClear(blt_int8u *data); +static void XcpCmdProgramReset(blt_int8u *data); +static void XcpCmdProgramPrepare(blt_int8u *data); +#endif + + +/**************************************************************************************** +* Hook functions +****************************************************************************************/ +#if F_CAL_RES_PAGING_EN == 1 +blt_int8u AppCalSetPage(blt_int8u segment, blt_int8u page); +blt_int8u AppCalGetPage(blt_int8u segment); +#endif + + +/**************************************************************************************** +* Local constants +****************************************************************************************/ +/* string buffer with station id */ +static const blt_int8s xcpStationId[] = XCP_STATION_ID_STRING; + + +/**************************************************************************************** +* Local data definitions +****************************************************************************************/ +static tXcpInfo xcpInfo; /* XCP internal module info */ + + +/**************************************************************************************** +** NAME: XcpInit +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Initializes the XCP driver. Should be called once upon system startup. +** +****************************************************************************************/ +void XcpInit(void) +{ + /* reset xcp module info */ + xcpInfo.connected = 0; + xcpInfo.mta = 0; + xcpInfo.ctoPending = 0; + xcpInfo.ctoLen = 0; + xcpInfo.s_n_k_resource = 0; + xcpInfo.protection = 0; +} /*** end of XcpInit ***/ + + +/**************************************************************************************** +** NAME: XcpIsConnected +** PARAMETER: none +** RETURN VALUE: BLT_TRUE is an XCP connection is established, BLT_FALSE otherwise. +** DESCRIPTION: Obtains information about the XCP connection state. +** +****************************************************************************************/ +blt_bool XcpIsConnected(void) +{ + if (xcpInfo.connected == 0) + { + return BLT_FALSE; + } + return BLT_TRUE; +} /*** end of XcpIsConnected ***/ + + +/**************************************************************************************** +** NAME: XcpPacketTransmitted +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Informs the core that a pending packet transmission was completed by +** the transport layer. +** +****************************************************************************************/ +void XcpPacketTransmitted(void) +{ + /* reset packet transmission pending flag */ + xcpInfo.ctoPending = 0; +} /*** end of XcpPacketTransmitted ***/ + + +/**************************************************************************************** +** NAME: XcpPacketReceived +** PARAMETER: data pointer to byte buffer with packet data +** RETURN VALUE: none +** DESCRIPTION: Informs the core that a new packet was received by the transport +** layer. +** +****************************************************************************************/ +void XcpPacketReceived(blt_int8u *data) +{ + /* was this a connect command? */ + if (data[0] == XCP_CMD_CONNECT) + { + /* process the connect command */ + XcpCmdConnect(data); + } + /* only continue if connected */ + else if (xcpInfo.connected == 1) + { + switch (data[0]) + { + case XCP_CMD_UPLOAD: + XcpCmdUpload(data); + break; + case XCP_CMD_SHORT_UPLOAD: + XcpCmdShortUpload(data); + break; + case XCP_CMD_SET_MTA: + XcpCmdSetMta(data); + break; + case XCP_CMD_BUILD_CHECKSUM: + XcpCmdBuildCheckSum(data); + break; + case XCP_CMD_GET_ID: + XcpCmdGetId(data); + break; + case XCP_CMD_SYNCH: + XcpCmdSynch(data); + break; + case XCP_CMD_GET_STATUS: + XcpCmdGetStatus(data); + break; + case XCP_CMD_DISCONNECT: + XcpCmdDisconnect(data); + break; +#if (XCP_RES_CALIBRATION_EN == 1) + case XCP_CMD_DOWNLOAD: + XcpCmdDownload(data); + break; + case XCP_CMD_DOWLOAD_MAX: + XcpCmdDownloadMax(data); + break; +#endif +#if (XCP_RES_PROGRAMMING_EN == 1) + case XCP_CMD_PROGRAM_MAX: + XcpCmdProgramMax(data); + break; + case XCP_CMD_PROGRAM: + XcpCmdProgram(data); + break; + case XCP_CMD_PROGRAM_START: + XcpCmdProgramStart(data); + break; + case XCP_CMD_PROGRAM_CLEAR: + XcpCmdProgramClear(data); + break; + case XCP_CMD_PROGRAM_RESET: + XcpCmdProgramReset(data); + break; + case XCP_CMD_PROGRAM_PREPARE: + XcpCmdProgramPrepare(data); + break; +#endif +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + case XCP_CMD_GET_SEED: + XcpCmdGetSeed(data); + break; + case XCP_CMD_UNLOCK: + XcpCmdUnlock(data); + break; +#endif +#if (XCP_RES_PAGING_EN == 1) + case XCP_CMD_SET_CAL_PAGE: + XcpCmdSetCalPage(data); + break; + case XCP_CMD_GET_CAL_PAGE: + XcpCmdGetCalPage(data); + break; +#endif + default: + XcpSetCtoError(XCP_ERR_CMD_UNKNOWN); + break; + } + } + else + { + /* return to make sure response packet is not send because we are not connected */ + return; + } + + /* make sure the previous command was completed */ + if (xcpInfo.ctoPending == 1) + { + /* command overrun occurred */ + XcpSetCtoError(XCP_ERR_CMD_BUSY); + } + + /* set cto packet transmission pending flag */ + xcpInfo.ctoPending = 1; + + /* transmit the cto response packet */ + XcpTransmitPacket(xcpInfo.ctoData, xcpInfo.ctoLen); +} /*** end of XcpPacketReceived ***/ + + +/**************************************************************************************** +** NAME: XcpTransmitPacket +** PARAMETER: data pointer to the byte buffer with packet data. +** len number of data bytes that need to be transmitted. +** RETURN VALUE: none +** DESCRIPTION: Transmits the packet using the xcp transport layer. +** +****************************************************************************************/ +static void XcpTransmitPacket(blt_int8u *data, blt_int16s len) +{ + /* submit packet to the communication interface for transmission */ + ComTransmitPacket(data, len); +} /*** end of XcpTransmitPacket ***/ + + +/**************************************************************************************** +** NAME: XcpComputeChecksum +** PARAMETER: address the start address of the memory region. +** length length of the memory region in bytes. +** checksum pointer to where the calculated checksum is to be stored. +** RETURN VALUE: none +** DESCRIPTION: Called by the BUILD_CHECKSUM command to perform a checksum calculation +** over the specified memory region. +** +****************************************************************************************/ +static blt_int8u XcpComputeChecksum(blt_int32u address, blt_int32u length, + blt_int32u *checksum) +{ + blt_int8u cs = 0; + + /* this example computes the checksum using the add byte to byte algorithm */ + while (length-- > 0) + { + cs += *((blt_int8u*)(blt_addr)address); + address++; + } + + *checksum = cs; + + return XCP_CS_ADD11; +} /*** end of XcpComputeChecksum ***/ + + +#if (XCP_SEED_KEY_PROTECTION_EN == 1) +/**************************************************************************************** +** NAME: XcpGetSeed +** PARAMETER: resource resource that the seed if requested for (XCP_RES_XXX). +** seed pointer to byte buffer wher the seed will be stored. +** RETURN VALUE: none +** DESCRIPTION: Provides a seed to the XCP master that will be used for the key +** generation when the master attempts to unlock the specified resource. +** Called by the GET_SEED command. +** +****************************************************************************************/ +static blt_int8u XcpGetSeed(blt_int8u resource, blt_int8u *seed) +{ + /* request seed for unlocking ProGraMming resource */ + if ((resource & XCP_RES_PGM) != 0) + { + seed[0] = 0x55; + } + + /* request seed for unlocking CALibration and PAGing resource */ + if ((resource & XCP_RES_CALPAG) != 0) + { + seed[0] = 0xaa; + } + + /* return seed length */ + return 1; +} /*** end of XcpGetSeed ***/ + + +/**************************************************************************************** +** NAME: XcpVerifyKey +** PARAMETER: resource resource to unlock (XCP_RES_XXX). +** key pointer to the byte buffer holding the key. +** len length of the key in bytes. +** RETURN VALUE: none +** DESCRIPTION: Called by the UNLOCK command and checks if the key to unlock the +** specified resource was correct. If so, then the resource protection +** will be removed. +** +****************************************************************************************/ +static blt_int8u XcpVerifyKey(blt_int8u resource, blt_int8u *key, blt_int8u len) +{ + /* suppress compiler warning for unused parameter */ + len = len; + + /* the example key algorithm in "FeaserKey.dll" works as follows: + * - PGM will be unlocked if key = seed - 1 + * - CAL_PAG will be unlocked if key = seed + 1 + */ + + /* check key for unlocking ProGraMming resource */ + if ((resource == XCP_RES_PGM) && (key[0] == (0x55-1))) + { + /* correct key received for unlocking PGM resource */ + return 1; + } + + /* check key for unlocking CALibration and PAGing resource */ + if ((resource == XCP_RES_CALPAG) && (key[0] == (0xaa+1))) + { + /* correct key received for unlocking CAL_PAG resource */ + return 1; + } + + /* still here so key incorrect */ + return 0; +} /*** end of XcpVerifyKey ***/ +#endif /* XCP_SEED_KEY_PROTECTION_EN == 1 */ + + +/**************************************************************************************** +** NAME: XcpProtectResources +** PARAMETER: none +** RETURN VALUE: none +** DESCRIPTION: Utility function to protects all the available resources. +** +****************************************************************************************/ +static void XcpProtectResources(void) +{ + xcpInfo.protection = 0; + +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + #if (XCP_RES_CALIBRATION_EN == 1) + xcpInfo.protection |= XCP_RES_CALPAG; + #endif + + #if (XCP_RES_PAGING_EN == 1) + xcpInfo.protection |= XCP_RES_CALPAG; + #endif + + #if (XCP_RES_PROGRAMMING_EN == 1) + xcpInfo.protection |= XCP_RES_PGM; + #endif + + #if (XCP_RES_DATA_ACQUISITION_EN == 1) + xcpInfo.protection |= XCP_RES_DAQ; + #endif + + #if (XCP_RES_DATA_STIMULATION_EN == 1) + xcpInfo.protection |= XCP_RES_STIM; + #endif +#endif /* XCP_SEED_KEY_PROTECTION_EN == 1 */ +} /*** end of XcpProtectResources ***/ + + +/**************************************************************************************** +** NAME: XcpSetCtoError +** PARAMETER: error xcp error code (XCP_ERR_XXX) +** RETURN VALUE: none +** DESCRIPTION: Prepares the cto packet data for the specified error. +** +****************************************************************************************/ +static void XcpSetCtoError(blt_int8u error) +{ + /* prepare the error packet */ + xcpInfo.ctoData[0] = XCP_PID_ERR; + xcpInfo.ctoData[1] = error; + xcpInfo.ctoLen = 2; +} /*** end of XcpSetCtoError ***/ + + +/**************************************************************************************** +** NAME: XcpCmdConnect +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the CONNECT command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdConnect(blt_int8u *data) +{ + /* suppress compiler warning for unused parameter */ + data = data; + + /* enable resource protection */ + XcpProtectResources(); + + /* indicate that the connection is established */ + xcpInfo.connected = 1; + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* report available resources */ + xcpInfo.ctoData[1] = 0; +#if (XCP_RES_CALIBRATION_EN == 1) + xcpInfo.ctoData[1] |= XCP_RES_CALPAG; +#endif + +#if (XCP_RES_PAGING_EN == 1) + xcpInfo.ctoData[1] |= XCP_RES_CALPAG; +#endif + +#if (XCP_RES_PROGRAMMING_EN == 1) + xcpInfo.ctoData[1] |= XCP_RES_PGM; +#endif + +#if (XCP_RES_DATA_ACQUISITION_EN == 1) + xcpInfo.ctoData[1] |= XCP_RES_DAQ; +#endif + +#if (XCP_RES_DATA_STIMULATION_EN == 1) + xcpInfo.ctoData[1] |= XCP_RES_STIM; +#endif + + /* report communication mode info. only byte granularity is supported */ + xcpInfo.ctoData[2] = 0; + /* configure for motorola or intel byte ordering */ + xcpInfo.ctoData[2] |= XCP_MOTOROLA_FORMAT; + + /* report max cto data length */ + xcpInfo.ctoData[3] = XCP_CTO_PACKET_LEN; + + /* report max dto data length */ +#if (XCP_MOTOROLA_FORMAT == 0) + xcpInfo.ctoData[4] = (blt_int8u)XCP_DTO_PACKET_LEN; + xcpInfo.ctoData[5] = (blt_int8u)(XCP_DTO_PACKET_LEN >> 8); +#else + xcpInfo.ctoData[4] = (blt_int8u)(XCP_DTO_PACKET_LEN >> 8); + xcpInfo.ctoData[5] = (blt_int8u)XCP_DTO_PACKET_LEN; +#endif + + /* report msb of protocol layer version number */ + xcpInfo.ctoData[6] = XCP_VERSION_PROTOCOL_LAYER >> 8; + + /* report msb of transport layer version number */ + xcpInfo.ctoData[7] = XCP_VERSION_TRANSPORT_LAYER >> 8; + + /* set packet length */ + xcpInfo.ctoLen = 8; +} /*** end of XcpCmdConnect ***/ + + +/**************************************************************************************** +** NAME: XcpCmdDisconnect +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the DISCONNECT command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdDisconnect(blt_int8u *data) +{ + /* suppress compiler warning for unused parameter */ + data = data; + + /* indicate that the xcp connection is disconnected */ + xcpInfo.connected = 0; + + /* enable resource protection */ + XcpProtectResources(); + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* set packet length */ + xcpInfo.ctoLen = 1; +} /*** end of XcpCmdDisconnect ***/ + + +/**************************************************************************************** +** NAME: XcpCmdGetStatus +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the GET_STATUS command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdGetStatus(blt_int8u *data) +{ + /* suppress compiler warning for unused parameter */ + data = data; + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* report session status */ + xcpInfo.ctoData[1] = 0; + + /* report current resource protection status */ + xcpInfo.ctoData[2] = xcpInfo.protection; + + /* reset reserved and session configuration id values */ + xcpInfo.ctoData[3] = 0; + xcpInfo.ctoData[4] = 0; + xcpInfo.ctoData[5] = 0; + + /* set packet length */ + xcpInfo.ctoLen = 6; +} /*** end of XcpCmdGetStatus ***/ + + +/**************************************************************************************** +** NAME: XcpCmdSynch +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the SYNCH command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdSynch(blt_int8u *data) +{ + /* suppress compiler warning for unused parameter */ + data = data; + + /* synch requires a negative response */ + XcpSetCtoError(XCP_ERR_CMD_SYNCH); +} /*** end of XcpCmdSynch ***/ + + +/**************************************************************************************** +** NAME: XcpCmdGetId +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the GET_ID command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdGetId(blt_int8u *data) +{ + /* suppress compiler warning for unused parameter */ + data = data; + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* point mta to start of station id string */ + xcpInfo.mta = (blt_int32u)&xcpStationId[0]; + + /* set station id mode to 0 */ + xcpInfo.ctoData[1] = 0; + + /* reset reserved values */ + xcpInfo.ctoData[2] = 0; + xcpInfo.ctoData[3] = 0; + + /* store station id length (excl. null termination) for response packet */ + *(blt_int32u*)&xcpInfo.ctoData[4] = (sizeof(xcpStationId)/sizeof(xcpStationId[0])) - 1; + + /* set packet length */ + xcpInfo.ctoLen = 8; +} /*** end of XcpCmdGetId ***/ + + +/**************************************************************************************** +** NAME: XcpCmdSetMta +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the SET_MTA command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdSetMta(blt_int8u *data) +{ + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* update mta. current implementation ignores address extension */ + xcpInfo.mta = *(blt_int32u*)&data[4]; + + /* set packet length */ + xcpInfo.ctoLen = 1; +} /*** end of XcpCmdSetMta ***/ + + +/**************************************************************************************** +** NAME: XcpCmdUpload +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the UPLOAD command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdUpload(blt_int8u *data) +{ + /* validate length of upload request */ + if (data[1] > (XCP_CTO_PACKET_LEN-1)) + { + /* requested data length is too long */ + XcpSetCtoError(XCP_ERR_OUT_OF_RANGE); + return; + } + + /* copy the data from memory to the data packet */ + CpuMemCopy(((blt_addr)(blt_int32u)&xcpInfo.ctoData[1]),(blt_addr)xcpInfo.mta, data[1]); + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* post increment the mta */ + xcpInfo.mta += data[1]; + + /* set packet length */ + xcpInfo.ctoLen = data[1]+1; +} /*** end of XcpCmdUpload ***/ + + +/**************************************************************************************** +** NAME: XcpCmdShortUpload +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the SHORT_UPLOAD command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdShortUpload(blt_int8u *data) +{ + /* validate length of upload request */ + if (data[1] > (XCP_CTO_PACKET_LEN-1)) + { + /* requested data length is too long */ + XcpSetCtoError(XCP_ERR_OUT_OF_RANGE); + return; + } + + /* update mta. current implementation ignores address extension */ + xcpInfo.mta = *(blt_int32u*)&data[4]; + + /* copy the data from memory to the data packet */ + CpuMemCopy((blt_addr)((blt_int32u)&xcpInfo.ctoData[1]),(blt_addr)xcpInfo.mta, data[1]); + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* post increment the mta */ + xcpInfo.mta += data[1]; + + /* set packet length */ + xcpInfo.ctoLen = data[1]+1; +} /*** end of XcpCmdShortUpload ***/ + + +#if (XCP_RES_CALIBRATION_EN == 1) +/**************************************************************************************** +** NAME: XcpCmdDownload +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the DOWNLOAD command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdDownload(blt_int8u *data) +{ +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + /* check if CAL_PAG resource is unlocked */ + if ((xcpInfo.protection & XCP_RES_CALPAG) != 0) + { + /* resource is locked. use seed/key sequence to unlock */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + return; + } +#endif + + /* validate length of download request */ + if (data[1] > (XCP_CTO_PACKET_LEN-2)) + { + /* requested data length is too long */ + XcpSetCtoError(XCP_ERR_OUT_OF_RANGE); + return; + } + + /* copy the data from the data packet to memory */ + CpuMemCopy((blt_addr)xcpInfo.mta, (blt_addr)((blt_int32u)&data[2]), data[1]); + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* post increment the mta */ + xcpInfo.mta += data[1]; + + /* set packet length */ + xcpInfo.ctoLen = 1; +} /*** end of XcpCmdDownload ***/ + + +/**************************************************************************************** +** NAME: XcpCmdDownloadMax +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the DOWNLOAD_MAX command +** as defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdDownloadMax(blt_int8u *data) +{ +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + /* check if CAL_PAG resource is unlocked */ + if ((xcpInfo.protection & XCP_RES_CALPAG) != 0) + { + /* resource is locked. use seed/key sequence to unlock */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + return; + } +#endif + + /* copy the data from the data packet to memory */ + CpuMemCopy((blt_addr)xcpInfo.mta, (blt_addr)((blt_int32u)&data[1]), \ + XCP_CTO_PACKET_LEN-1); + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* post increment the mta */ + xcpInfo.mta += XCP_CTO_PACKET_LEN-1; + + /* set packet length */ + xcpInfo.ctoLen = 1; +} /*** end of XcpCmdDownloadMax ***/ +#endif /* XCP_RES_CALIBRATION_EN == 1 */ + + +/**************************************************************************************** +** NAME: XcpCmdBuildCheckSum +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the BUILD_CHECKSUM +** command as defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdBuildCheckSum(blt_int8u *data) +{ + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* obtain checksum and checksum type */ + xcpInfo.ctoData[1] = XcpComputeChecksum(xcpInfo.mta, *(blt_int32u*)&data[4], + (blt_int32u*)&xcpInfo.ctoData[4]); + + /* initialize reserved parameters */ + xcpInfo.ctoData[2] = 0; + xcpInfo.ctoData[3] = 0; + + /* set packet length */ + xcpInfo.ctoLen = 8; +} /*** end of XcpCmdBuildCheckSum ***/ + + +#if (XCP_SEED_KEY_PROTECTION_EN == 1) +/**************************************************************************************** +** NAME: XcpCmdGetSeed +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the GET_SEED command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdGetSeed(blt_int8u *data) +{ + blt_int8u resourceOK; + + /* init resource check variable as if an illegal resource is requested */ + resourceOK = 0; + + /* check if calibration/paging resource is requested for seed/key and make + * sure this is the only requested resource + */ + if (((data[2] & XCP_RES_CALPAG) > 0) && ((data[2] & ~XCP_RES_CALPAG) == 0)) + { + resourceOK = 1; + } + + /* check if programming resource is requested for seed/key and make + * sure this is the only requested resource + */ + if (((data[2] & XCP_RES_PGM) > 0) && ((data[2] & ~XCP_RES_PGM) == 0)) + { + resourceOK = 1; + } + + /* check if data acquisition resource is requested for seed/key and make + * sure this is the only requested resource + */ + if (((data[2] & XCP_RES_DAQ) > 0) && ((data[2] & ~XCP_RES_DAQ) == 0)) + { + resourceOK = 1; + } + + /* check if data stimulation resource is requested for seed/key and make + * sure this is the only requested resource + */ + if (((data[2] & XCP_RES_STIM) > 0) && ((data[2] & ~XCP_RES_STIM) == 0)) + { + resourceOK = 1; + } + + /* now process the resource validation */ + if (resourceOK == 0) + { + XcpSetCtoError(XCP_ERR_OUT_OF_RANGE); + return; + } + + /* store resource for which the seed/key sequence is started */ + xcpInfo.s_n_k_resource = data[2]; + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* request the seed from the application */ + xcpInfo.ctoData[1] = XcpGetSeed(xcpInfo.s_n_k_resource, &xcpInfo.ctoData[2]); + + /* seed cannot be longer than XCP_CTO_PACKET_LEN-2 */ + if (xcpInfo.ctoData[1] > (XCP_CTO_PACKET_LEN-2)) + { + /* seed length length is too long */ + XcpSetCtoError(XCP_ERR_OUT_OF_RANGE); + return; + } + + /* set packet length */ + xcpInfo.ctoLen = xcpInfo.ctoData[1] + 2; +} /*** end of XcpCmdGetSeed ***/ + + +/**************************************************************************************** +** NAME: XcpCmdUnlock +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the UNLOCK command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdUnlock(blt_int8u *data) +{ + /* key cannot be longer than XCP_CTO_PACKET_LEN-2 */ + if (data[1] > (XCP_CTO_PACKET_LEN-2)) + { + /* key is too long incorrect */ + XcpSetCtoError(XCP_ERR_SEQUENCE); + return; + } + + /* verify the key */ + if (XcpVerifyKey(xcpInfo.s_n_k_resource, &data[2], data[1]) == 0) + { + /* invalid key so inform the master and do a disconnect */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + + /* indicate that the xcp connection is disconnected */ + xcpInfo.connected = 0; + + /* enable resource protection */ + XcpProtectResources(); + + return; + } + + /* key correct so unlock the resource */ + xcpInfo.protection &= ~xcpInfo.s_n_k_resource; + + /* reset seed/key resource variable for possible next unlock */ + xcpInfo.s_n_k_resource = 0; + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* report the current resource protection */ + xcpInfo.ctoData[1] = xcpInfo.protection; + + /* set packet length */ + xcpInfo.ctoLen = 2; +} /*** end of XcpCmdUnlock ***/ +#endif /* XCP_SEED_KEY_PROTECTION_EN == 1 */ + + +#if (XCP_RES_PAGING_EN == 1) +/**************************************************************************************** +** NAME: XcpCmdSetCalPage +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the SET_CAL_PAGE command +** as defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdSetCalPage(blt_int8u *data) +{ +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + /* check if CAL_PAG resource is unlocked */ + if ((xcpInfo.protection & XCP_RES_CALPAG) == XCP_RES_CALPAG) + { + /* resource is locked. use seed/key sequence to unlock */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + return; + } +#endif + + /* select the page. note that the mode parameter is ignored */ + if (AppCalSetPage(data[2], data[3]) == 0) + { + /* calibration page could not be selected */ + XcpSetCtoError(XCP_ERR_PAGE_NOT_VALID); + return; + } + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* set packet length */ + xcpInfo.ctoLen = 1; +} /*** end of XcpCmdSetCalPage ***/ + + +/**************************************************************************************** +** NAME: XcpCmdGetCalPage +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the GET_CAL_PAGE command +** as defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdGetCalPage(blt_int8u *data) +{ +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + /* check if CAL_PAG resource is unlocked */ + if ((xcpInfo.protection & XCP_RES_CALPAG) == XCP_RES_CALPAG) + { + /* resource is locked. use seed/key sequence to unlock */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + return; + } +#endif + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* initialize reserved parameters */ + xcpInfo.ctoData[1] = 0; + xcpInfo.ctoData[2] = 0; + + /* store the calibration page */ + xcpInfo.ctoData[3] = AppCalGetPage(data[2]); + + /* set packet length */ + xcpInfo.ctoLen = 4; +} /*** end of XcpCmdGetCalPage ***/ +#endif /* XCP_RES_PAGING_EN == 1 */ + + +#if (XCP_RES_PROGRAMMING_EN == 1) +/**************************************************************************************** +** NAME: XcpCmdProgramStart +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the PROGRAM_START command +** as defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdProgramStart(blt_int8u *data) +{ + /* suppress compiler warning for unused parameter */ + data = data; + +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + /* check if PGM resource is unlocked */ + if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM) + { + /* resource is locked. use seed/key sequence to unlock */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + return; + } +#endif + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* initialize reserved parameter */ + xcpInfo.ctoData[1] = 0; + + /* no special communication mode supported during programming */ + xcpInfo.ctoData[2] = 0; + + /* cto packet length stays the same during programming */ + xcpInfo.ctoData[3] = XCP_CTO_PACKET_LEN; + + /* no block size, st-min time, or queue size supported */ + xcpInfo.ctoData[4] = 0; + xcpInfo.ctoData[5] = 0; + xcpInfo.ctoData[6] = 0; + + /* set packet length */ + xcpInfo.ctoLen = 7; +} /*** end of XcpCmdProgramStart ***/ + + +/**************************************************************************************** +** NAME: XcpCmdProgramMax +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the PROGRAM_MAX command +** as defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdProgramMax(blt_int8u *data) +{ +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + /* check if PGM resource is unlocked */ + if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM) + { + /* resource is locked. use seed/key sequence to unlock */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + return; + } +#endif + + /* program the data */ + if (NvmWrite((blt_addr)xcpInfo.mta, XCP_CTO_PACKET_LEN-1, &data[1]) == 0) + { + /* error occurred during programming */ + XcpSetCtoError(XCP_ERR_GENERIC); + return; + } + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* post increment the mta */ + xcpInfo.mta += XCP_CTO_PACKET_LEN-1; + + /* set packet length */ + xcpInfo.ctoLen = 1; +} /*** end of XcpCmdProgramMax ***/ + + +/**************************************************************************************** +** NAME: XcpCmdProgram +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the PROGRAM command as +** defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdProgram(blt_int8u *data) +{ +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + /* check if PGM resource is unlocked */ + if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM) + { + /* resource is locked. use seed/key sequence to unlock */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + return; + } +#endif + + /* validate length of download request */ + if (data[1] > (XCP_CTO_PACKET_LEN-2)) + { + /* requested data length is too long */ + XcpSetCtoError(XCP_ERR_OUT_OF_RANGE); + return; + } + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* set packet length */ + xcpInfo.ctoLen = 1; + + /* end of programming sequence (datasize is 0)? */ + if (data[1] == 0) + { + /* call erase/programming cleanup routine */ + if (NvmDone() == BLT_FALSE) + { + /* error occurred while finishing up programming */ + XcpSetCtoError(XCP_ERR_GENERIC); + } + return; + } + /* program the data */ + if (NvmWrite((blt_addr)xcpInfo.mta, data[1], &data[2]) == 0) + { + /* error occurred during programming */ + XcpSetCtoError(XCP_ERR_GENERIC); + return; + } + + /* post increment the mta */ + xcpInfo.mta += data[1]; +} /*** end of XcpCmdProgram ***/ + + +/**************************************************************************************** +** NAME: XcpCmdProgramClear +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the PROGRAM_CLEAR command +** as defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdProgramClear(blt_int8u *data) +{ +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + /* check if PGM resource is unlocked */ + if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM) + { + /* resource is locked. use seed/key sequence to unlock */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + return; + } +#endif + + /* erase the memory */ + if (NvmErase((blt_addr)xcpInfo.mta, *(blt_int32u*)&data[4]) == 0) + { + /* error occurred during erasure */ + XcpSetCtoError(XCP_ERR_GENERIC); + return; + } + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* set packet length */ + xcpInfo.ctoLen = 1; +} /*** end of XcpCmdProgramClear ***/ + + +/**************************************************************************************** +** NAME: XcpCmdProgramReset +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the PROGRAM_RESET command +** as defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdProgramReset(blt_int8u *data) +{ + /* suppress compiler warning for unused parameter */ + data = data; + +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + /* check if PGM resource is unlocked */ + if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM) + { + /* resource is locked. use seed/key sequence to unlock */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + return; + } +#endif + + /* reset the ecu. it is okay if the code does not return here after the reset */ + CpuReset(); + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* set packet length */ + xcpInfo.ctoLen = 1; +} /*** end of XcpCmdProgramReset ***/ + + +/**************************************************************************************** +** NAME: XcpCmdProgramPrepare +** PARAMETER: data pointer to a byte buffer with the packet data. +** RETURN VALUE: none +** DESCRIPTION: XCP command processor function which handles the PROGRAM_PREPARE +** command as defined by the protocol. +** +****************************************************************************************/ +static void XcpCmdProgramPrepare(blt_int8u *data) +{ +#if (XCP_SEED_KEY_PROTECTION_EN == 1) + /* check if PGM resource is unlocked */ + if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM) + { + /* resource is locked. use seed/key sequence to unlock */ + XcpSetCtoError(XCP_ERR_ACCESS_LOCKED); + return; + } +#endif + + /* programming with kernel currently not needed and therefore not supported */ + XcpSetCtoError(XCP_ERR_GENERIC); + return; + + /* set packet id to command response packet */ + xcpInfo.ctoData[0] = XCP_PID_RES; + + /* set packet length */ + xcpInfo.ctoLen = 1; +} /*** end of XcpCmdProgramPrepare ***/ +#endif /* XCP_RES_PROGRAMMING_EN == 1 */ + + +/******************************** end of xcp.c *****************************************/ diff --git a/Target/Source/xcp.h b/Target/Source/xcp.h new file mode 100644 index 00000000..0110cee9 --- /dev/null +++ b/Target/Source/xcp.h @@ -0,0 +1,226 @@ +/**************************************************************************************** +| Description: XCP 1.0 protocol core header file +| File Name: xcp.h +| +|---------------------------------------------------------------------------------------- +| C O P Y R I G H T +|---------------------------------------------------------------------------------------- +| Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +| +|---------------------------------------------------------------------------------------- +| L I C E N S E +|---------------------------------------------------------------------------------------- +| This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +| modify it under the terms of the GNU General Public License as published by the Free +| Software Foundation, either version 3 of the License, or (at your option) any later +| version. +| +| OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +| PURPOSE. See the GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License along with OpenBLT. +| If not, see . +| +| A special exception to the GPL is included to allow you to distribute a combined work +| that includes OpenBLT without being obliged to provide the source code for any +| proprietary components. The exception text is included at the bottom of the license +| file . +| +****************************************************************************************/ +#ifndef XCP_H +#define XCP_H + +/**************************************************************************************** +* Configuration +****************************************************************************************/ +/* Maximum length of the transport layer's command transmit object packet. + */ +#define XCP_CTO_PACKET_LEN (BOOT_COM_RX_MAX_DATA) + +/* Maximum length of the transport layer's data transmit object packet. + */ +#define XCP_DTO_PACKET_LEN (BOOT_COM_TX_MAX_DATA) + +/* Name in string format that is used to identify the ECU to the XCP master + * using the GET_ID command. + */ +#define XCP_STATION_ID_STRING "OpenBLT" + +/* XCP byte ordering + */ +#if (BOOT_CPU_BYTE_ORDER_MOTOROLA > 0) + #define XCP_MOTOROLA_FORMAT (0x01) +#else + #define XCP_MOTOROLA_FORMAT (0x00) +#endif + +/* Enable (=1) or disable (=0) support for the calibration resource. This is + * required when data is written to RAM during the XCP session. + */ +#define XCP_RES_CALIBRATION_EN (0) + +/* Enable (=1) or disable (=0) support for the paging resource. This is + * required when switching between application specific calibration pages + * should be supported. In this case the application specific external + * functions AppCalSetPage and AppCalGetPage must be provided. + */ +#define XCP_RES_PAGING_EN (0) + +/* Enable (=1) or disable (=0) support for the programming resource. This is + * required when non-volatile memory will be erased or programmed during an + * XCP session. In this case the following external hardware specific + * functions must be provided: HwNvmWriteMemory, HwNvmEraseMemory and + * HwCpuReset. + */ +#define XCP_RES_PROGRAMMING_EN (1) + +/* Enable (=1) or disable (=0) support for the data acquisition resource. This + * note that this feature is currently not supported by the XCP driver. + */ +#define XCP_RES_DATA_ACQUISITION_EN (0) + +/* Enable (=1) or disable (=0) support for the data stimulation resource. This + * note that this feature is currently not supported by the XCP driver. + */ +#define XCP_RES_DATA_STIMULATION_EN (0) + +/* Enable (=1) or disable (=0) support for the seed/key protection feature. + * If enabled, the XCP master has to perform a GET_SEED/UNLOCK sequence to + * obtain access to a resource. The protection algorithm is implemented in + * XcpGetSeed and XcpVerifyKey. + */ +#define XCP_SEED_KEY_PROTECTION_EN (0) + + +/**************************************************************************************** +* Defines +****************************************************************************************/ +/* xcp supported resources */ +#define XCP_RES_PGM (0x10) /* ProGraMming */ +#define XCP_RES_STIM (0x08) /* data STIMulation */ +#define XCP_RES_DAQ (0x04) /* Data AcQuisition */ +#define XCP_RES_CALPAG (0x01) /* CALibration and PAGing */ + +/* xcp checksum types */ +#define XCP_CS_ADD11 (0x01) /* add byte into byte checksum */ +#define XCP_CS_ADD12 (0x02) /* add byte into word checksum */ +#define XCP_CS_ADD14 (0x03) /* add byte into dword checksum */ +#define XCP_CS_ADD22 (0x04) /* add word into word checksum */ +#define XCP_CS_ADD24 (0x05) /* add word into dword checksum */ +#define XCP_CS_ADD44 (0x06) /* add dword into dword checksum */ +#define XCP_CS_CRC16 (0x07) /* use 16-bit CRC algorithm */ +#define XCP_CS_CRC16CITT (0x08) /* use 16-bit CRC CITT algorithm */ +#define XCP_CS_CRC32 (0x09) /* use 32-bit CRC algorithm */ +#define XCP_CS_USER (0xff) /* use user defined algorithm */ + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void XcpInit(void); +blt_bool XcpIsConnected(void); +void XcpPacketTransmitted(void); +void XcpPacketReceived(blt_int8u *data); + + +/**************************************************************************************** +* Configuration check +****************************************************************************************/ +#if (XCP_RES_DATA_ACQUISITION_EN == 1) +#error "XCP.H, Current XCP driver does not support Data AcQuisition resource." +#endif + + +#if (XCP_RES_DATA_STIMULATION_EN == 1) +#error "XCP.H, Current XCP driver does not support Data StIMulation resource." +#endif + + +#ifndef XCP_CTO_PACKET_LEN +#error "XCP.H, Configuration macro XCP_CTO_PACKET_LEN is missing." +#endif + +#if (XCP_CTO_PACKET_LEN < 1) +#error "XCP.H, XCP_CTO_PACKET_LEN must be at least 1." +#endif + +#if (XCP_CTO_PACKET_LEN > 256) +#error "XCP.H, XCP_CTO_PACKET_LEN cannot be larger than 256." +#endif + + +#ifndef XCP_DTO_PACKET_LEN +#error "XCP.H, Configuration macro XCP_DTO_PACKET_LEN is missing." +#endif + +#if (XCP_DTO_PACKET_LEN < 1) +#error "XCP.H, XCP_DTO_PACKET_LEN must be at least 1." +#endif + +#if (XCP_DTO_PACKET_LEN > 65536) +#error "XCP.H, XCP_DTO_PACKET_LEN cannot be larger than 256." +#endif + + +#ifndef XCP_STATION_ID_STRING +#error "XCP.H, Configuration macro XCP_STATION_ID_STRING is missing." +#endif + + +#ifndef XCP_RES_CALIBRATION_EN +#error "XCP.H, Configuration macro XCP_RES_CALIBRATION_EN is missing." +#endif + +#if (XCP_RES_CALIBRATION_EN < 0) || (XCP_RES_CALIBRATION_EN > 1) +#error "XCP.H, XCP_RES_CALIBRATION_EN must be 0 or 1." +#endif + + +#ifndef XCP_RES_PAGING_EN +#error "XCP.H, Configuration macro XCP_RES_PAGING_EN is missing." +#endif + +#if (XCP_RES_PAGING_EN < 0) || (XCP_RES_PAGING_EN > 1) +#error "XCP.H, XCP_RES_PAGING_EN must be 0 or 1." +#endif + + +#ifndef XCP_RES_PROGRAMMING_EN +#error "XCP.H, Configuration macro XCP_RES_PAGING_EN is missing." +#endif + +#if (XCP_RES_PROGRAMMING_EN < 0) || (XCP_RES_PROGRAMMING_EN > 1) +#error "XCP.H, XCP_RES_PROGRAMMING_EN must be 0 or 1." +#endif + + +#ifndef XCP_RES_DATA_ACQUISITION_EN +#error "XCP.H, Configuration macro XCP_RES_DATA_ACQUISITION_EN is missing." +#endif + +#if (XCP_RES_DATA_ACQUISITION_EN < 0) || (XCP_RES_DATA_ACQUISITION_EN > 1) +#error "XCP.H, XCP_RES_DATA_ACQUISITION_EN must be 0 or 1." +#endif + + +#ifndef XCP_RES_DATA_STIMULATION_EN +#error "XCP.H, Configuration macro XCP_RES_DATA_STIMULATION_EN is missing." +#endif + +#if (XCP_RES_DATA_STIMULATION_EN < 0) || (XCP_RES_DATA_STIMULATION_EN > 1) +#error "XCP.H, XCP_RES_DATA_STIMULATION_EN must be 0 or 1." +#endif + + +#ifndef XCP_SEED_KEY_PROTECTION_EN +#error "XCP.H, Configuration macro XCP_SEED_KEY_PROTECTION_EN is missing." +#endif + +#if (XCP_SEED_KEY_PROTECTION_EN < 0) || (XCP_SEED_KEY_PROTECTION_EN > 1) +#error "XCP.H, XCP_SEED_KEY_PROTECTION_EN must be 0 or 1." +#endif + + +#endif /* XCP_H */ +/******************************** end of xcp.h *~~~~~***********************************/

QMw{GfAjA)!@RNxRtOLFuP2PpZpXk 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 literal 0 HcmV?d00001 diff --git a/Host/Pcan_usb.dll b/Host/Pcan_usb.dll new file mode 100644 index 0000000000000000000000000000000000000000..25a0b7fc36ba44bf9a9642ea15e05a0eac0f94e9 GIT binary patch literal 90112 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 literal 0 HcmV?d00001 diff --git a/Host/Source/MainUnit.dfm b/Host/Source/MainUnit.dfm new file mode 100644 index 0000000000000000000000000000000000000000..8e824357d830885c3f166963396264063a934a26 GIT binary patch literal 6720 zcmeHMeQX>@7619p_vw!~v3*V)QZIxSCnP3zKAbddeCIFh)Q*qbHYued*}EItEAQ=| zb~o{dLTe%sRVbo~1yxm{s8m3!fCN+!5+Q*JD2l3(2sJb%HQf^H7Y98a%$2r zS#FT2hv2YM=A^YOrQd&gfdFrkTRw)|O41gvu^OW~$l8d*Q$k8o4I#yJdDxb>jITh1&#$Fh zGNtHG!yqW5pCE7wc$HdW^lT;+2;+ohu)1NooGLDqxdc#MU5&uQ523BC4ZC*j0+MaO z{&wKW9l(J{fi$(TI55@?SqH^l6+q za|U0zTEGw9F5vw6^SFHZGOl00j$5~G;qKkLC=?2KEf&X7$2HBr>POul&K2tuMDO(Q zL)7mgwQVOe>;8BS->m|clV6{o2Fi){!pfRBeAM9fKUnq(HjwNO317cYJ|*}n(HH9D z7Ja;$+(#6bd+F5Qf!X``{pKK=r|$s+Pv8-%&u`;`&&?2@^Ei-Aw;S8gK{i!>K>y0w zYt;W*QTL6ywT5@D#OeeURJ! zCir|f@b<5hzmEUu99mZ0Bl~E538p4rL4&m?d#$<;?~%Vkw2yCF?Ogu$_Zo0@ax3Uz z>FXvPTi&QcoSvNjDvbwR!(XU=|MXL;?>i2S(&IQ3!L?_n7i#&zu|DZMg@eB8Gh47ny zebVBcTn@aow%nqx)B+Jl-^8!|II%iTXYCT+`C7NdAKjP%$KRCqP_IjvouF|?enPYj zSMLnKi+t{UUVo0=v3$h+bmMH?qWPY3_oFNS-+Vs0`H{`r+P1ZAY1^`HbLrRiVaF_M zCD^#Wx%t7hA8l&-$f}yE%4jIyvvv#D(bq}^NB+`lB5dHBEx?bP1;lSBemn8&Eqq`( zY7q#`<8xjeVJ(^(Q9hS%>;EK4SYxaqBIuFl25$OP%ZBFWPdxPTj|r<+E?-s=3A_6L zW6%2f#Z|4KO|%%4uUL#r8`}GUSiI}M!YyA>M^H}?BWQ1L=f#elMHO}R?b~-eypujX z4wN@HwRd!s__6u?t<5nHzkWVHR$K3tkHw1WJ38X=M52>JNq;QnFJDnh26DT$I}o4C ze_sdB_?C4Z^PO1~?f-u!=$luVrIq*MO(5j0&!-DFpD7e>b~yM9m*@RIH1aWBs2)a5$+MG7rf@)p;$I(HT>_C=O$KXh`i+G=qgGNYZl_8Kx#nG(_>+%gbw_9@dLv>dB`qy2r9sQA zZ7gTTLe<5rg`Auj1E0?#uB~zBnAEiqZnEp$T90>K-U1%>ea^7@F|$E(xz>(7gRUF9E?RXQGn(u6NtJj1?KrJ2(N`58z`Djlo5s`N35&bzJE zK34ATzgg7U>g>dTq|h;Pa;^~NPouKQysCp@e~z|gM9z(P^!m@*YZP|YNN`;sgcFBM zEhSH}NM%yan1^&`=TpC=Z+1ZB`PEWZwUkv+hC`Vaho!7)DXZey)lycqlvPDs^ui_6?Smg=+u-fqDe`o&lboR))l3M0XeNp`lLX~Uq+X$D}EuVkiJnGmg%%Y-mtz)QZr1k z{Nsf6{%4(FbfLIDX!kG0pZ+;Pz0GxkdUu!#iuO~?H0fUlJNxoKVE>!3*gzGo#GDku zR~)UzqtqF%LLAC7wOf`HZ6sPEgOqoXM}yL!W@_}Gi6o>p?qwPJw?t@O-(s}x*hyvE zc3y67=j8+yIn7*mWHIiMgrW#Mqcgac^}O@?fGC>^3$FC$Zo`^hOxtWPPuqcc4PSJg e1?wb6WvEA$(hAFlX^M73)OuKjEqSmgiGKq2i}70k literal 0 HcmV?d00001 diff --git a/Host/Source/MainUnit.pas b/Host/Source/MainUnit.pas new file mode 100644 index 00000000..1883e99c --- /dev/null +++ b/Host/Source/MainUnit.pas @@ -0,0 +1,767 @@ +unit MainUnit; +//*************************************************************************************** +// Project Name: MicroBoot for Borland Delphi +// Description: Contains the GUI for MicroBoot +// File Name: MainUnit.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + ExtCtrls, StdCtrls, Menus, ComCtrls, uBootInterface, Registry, SettingsUnit, StopWatch; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TmainForm = class(TForm) + pnlHeader: TPanel; + imgHeader: TImage; + lblAppName: TLabel; + lblInterfaceName: TLabel; + bvlFooter: TBevel; + btnCancel: TButton; + btnSettings: TButton; + ntbPages: TNotebook; + edtDownloadFile: TEdit; + btnBrowse: TButton; + lblDownloadFile: TLabel; + prgDownload: TProgressBar; + lblDownloadProgress: TLabel; + OpenDialog: TOpenDialog; + Timer: TTimer; + lblElapsedTime: TLabel; + procedure btnCancelClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure btnBrowseClick(Sender: TObject); + procedure btnSettingsClick(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure TimerTimer(Sender: TObject); + procedure edtDownloadFileKeyPress(Sender: TObject; var Key: Char); + private + { Private declarations } + MbiLogging : Boolean; + MbiLibFile : ShortString; + MbiInterfaced : Boolean; + MbiInterface : TMicroBootInterface; + LogLines : TStrings; + ExePath : string; + StopWatch : TStopWatch; + StayOpen : Boolean; + FormCaption : string; + procedure OnMbiStarted(length: Longword); + procedure OnMbiProgress(progress: Longword); + procedure OnMbiDone; + procedure OnMbiError(error: ShortString); + procedure OnMbiLog(info: ShortString); + procedure OnMbiInfo(info: ShortString); + procedure StartFileDownload(fileName : ShortString); + procedure UpdateInterfaceLabel; + public + { Public declarations } + function IsMbiInterface(libFile : string) : Boolean; + function GetMbiInfoString(libFile : string) : string; + function GetActiveMbi : string; + procedure SetActiveMbi(libFile : string); + procedure ConfigureMbi; + procedure GetInterfaceFileList(fileList : TStrings); + end; + + +//*************************************************************************************** +// Global Variables +//*************************************************************************************** +var + mainForm: TmainForm; + +implementation + +{$R *.DFM} + +//*************************************************************************************** +// NAME: OnMbiStarted +// PARAMETER: length of the download in bytes. +// RETURN VALUE: none +// DESCRIPTION: Called by the Mbi interface DLL after successfully starting a down- +// load. The value of the length parameter can be used to set the max +// value of the progress bar. +// +//*************************************************************************************** +procedure TmainForm.OnMbiStarted(length: Longword); +begin + prgDownload.Max := length; // set max length for progress bar + lblElapsedTime.Caption := 'Elapsed time: ' + StopWatch.Interval; + StopWatch.Start; // start the stopwatch + Timer.Enabled := true; // start the timer to update the stopwatch interval display +end; //*** end of OnMbiStarted *** + + +//*************************************************************************************** +// NAME: OnMbiProgress +// PARAMETER: number of already downloaded bytes. +// RETURN VALUE: none +// DESCRIPTION: Called by the Mbi interface DLL to provide us with an update on the +// download progress. The progress parameter can be used to update the +// position of the progress bar. +// +//*************************************************************************************** +procedure TmainForm.OnMbiProgress(progress: Longword); +begin + prgDownload.Position := progress; // update the progress bar +end; //*** end of OnMbiProgress *** + + +//*************************************************************************************** +// NAME: OnMbiDone +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the Mbi interface DLL when a download was successfully +// completed. +// +//*************************************************************************************** +procedure TmainForm.OnMbiDone; +begin + Timer.Enabled := false; // stop the timer + StopWatch.Stop; // stop the stopwatch + mainForm.Caption := FormCaption; // restore caption + + if StayOpen then + begin + NtbPages.PageIndex := 0; // go to the next page + btnSettings.Enabled := true; // settings can't be changed anymore + end + else + Close; // done so close the application +end; //*** end of OnMbiDone *** + + +//*************************************************************************************** +// NAME: OnMbiError +// PARAMETER: additional info on the error that occurred in string format. +// RETURN VALUE: none +// DESCRIPTION: Called by the Mbi interface DLL in case an error occurred. The para- +// meter contains more information on the error. +// +//*************************************************************************************** +procedure TmainForm.OnMbiError(error: ShortString); +begin + ShowMessage(error); // display error + Timer.Enabled := false; // stop the timer + StopWatch.Stop; // stop the stopwatch + mainForm.Caption := FormCaption; // restore caption + + if StayOpen then + begin + NtbPages.PageIndex := 0; // go to the next page + btnSettings.Enabled := true; // settings can't be changed anymore + end + else + Close; // can't continue so close the application +end; //*** end of OnMbiError *** + + +//*************************************************************************************** +// NAME: OnMbiLog +// PARAMETER: info on the log event in string format. +// RETURN VALUE: none +// DESCRIPTION: Called by the Mbi interface DLL in case info for logging purpose +// was made available by the DLL. +// +//*************************************************************************************** +procedure TmainForm.OnMbiLog(info: ShortString); +begin + if MbiLogging = True then + begin + LogLines.Add(info); // add to log + end; +end; //*** end of OnMbiLog *** + + +//*************************************************************************************** +// NAME: OnMbiInfo +// PARAMETER: details on the info event in string format. +// RETURN VALUE: none +// DESCRIPTION: Called by the Mbi interface DLL in case details for info purposes +// were made available by the DLL. +// +//*************************************************************************************** +procedure TmainForm.OnMbiInfo(info: ShortString); +begin + if NtbPages.PageIndex = 1 then + lblDownloadProgress.Caption := info; +end; //*** end of OnMbiLog *** + + +//*************************************************************************************** +// NAME: GetActiveMbi +// PARAMETER: none +// RETURN VALUE: filename with full path +// DESCRIPTION: Returns the file name with full path of the active Mbi interface +// library +// +//*************************************************************************************** +function TmainForm.GetActiveMbi : string; +begin + if IsMbiInterface(MbiLibFile) then + Result := MbiLibFile + else + Result := ''; +end; //*** end of GetActiveMbi *** + + +//*************************************************************************************** +// NAME: SetActiveMbi +// PARAMETER: filename with full path +// RETURN VALUE: none +// DESCRIPTION: Enables the Mbi interface library that is specified as the parameter. +// +//*************************************************************************************** +procedure TmainForm.SetActiveMbi(libFile : string); +begin + MbiInterfaced := false; // reset + + if IsMbiInterface(libFile) then + begin + MbiLibFile := libFile; + MbiInterfaced := MbiInterface.Enable(libFile, OnMbiStarted, OnMbiProgress, + OnMbiDone, OnMbiError, OnMbiLog, OnMbiInfo); + end; + + UpdateInterfaceLabel; +end; //*** end of SetActiveMbi *** + + +//*************************************************************************************** +// NAME: ConfigureMbi +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Submits request to the Mbi interface library for the user to configure +// the interface. +// +//*************************************************************************************** +procedure TmainForm.ConfigureMbi; +begin + if MbiInterfaced = True then + begin + MbiInterface.Configure; + end; +end; //*** end of ConfigureMbi *** + + +//*************************************************************************************** +// NAME: IsMbiInterface +// PARAMETER: filename with full path of the Mbi interface DLL +// RETURN VALUE: true if it is a valid Mbi interface DLL, otherwise false +// DESCRIPTION: Called to check whether a specified interface DLL is truly an Mbi +// interface DLL. +// +//*************************************************************************************** +function TmainForm.IsMbiInterface(libFile : string) : Boolean; +var + LibHandle : THandle; + LibValid : Boolean; +begin + LibValid := False; + + // make sure the file exists + if FileExists(libFile) then + begin + // make sure it is a DLL file + if LowerCase(ExtractFileExt(libFile)) = '.dll' then + begin + // make sure the DLL file is a microBoot interface library + LibHandle := LoadLibrary(PChar(ExtractShortPathName(libFile))); // get handle + if LibHandle <> 0 then + begin + if GetProcAddress(LibHandle, 'MbiInit') <> nil then + begin + LibValid := True; + FreeLibrary(LibHandle); + end; + end; + end; + end; + Result := LibValid; +end; //*** end of IsMbiInterface *** + + +//*************************************************************************************** +// NAME: GetMbiInfoString +// PARAMETER: filename with full path of the Mbi interface DLL +// RETURN VALUE: string that described the name and version of the Mbi interface DLL +// DESCRIPTION: Used to obtain a string that describes the Mbi interface DLL. +// +//*************************************************************************************** +function TmainForm.GetMbiInfoString(libFile : string) : string; +var + LibHandle : THandle; + DescriptionFnc : TDllMbiDescription; + VersionFnc : TDllMbiVersion; + Major : integer; + Minor : integer; + Bugfix : integer; +begin + Result := ''; + + // make sure the file is a valid Mbi interface library + if IsMbiInterface(libFile) then + begin + LibHandle := LoadLibrary(PChar(ExtractShortPathName(libFile))); // get handle + if LibHandle <> 0 then + begin + // obtain DLL function pointers + @DescriptionFnc := GetProcAddress(LibHandle, 'MbiDescription'); + @VersionFnc := GetProcAddress(LibHandle, 'MbiVersion'); + + if Assigned(DescriptionFnc) then + begin + Result := Result + DescriptionFnc; + end; + + if Assigned(VersionFnc) then + begin + // split up version numbers + Major := VersionFnc div 10000; + Minor := (versionFnc mod 10000) div 100; + Bugfix := (versionFnc mod 100); + + Result := Result + ' (' + Format('v%d.%2.2d.%2.2d', [Major, Minor, Bugfix]) + ')'; + end; + FreeLibrary(LibHandle); + end; + end; +end; //*** end of GetMbiInfoString *** + + +//*************************************************************************************** +// NAME: GetInterfaceFileList +// PARAMETER: string list where filelist will be stored +// RETURN VALUE: none +// DESCRIPTION: Searches all the DLL files in the directory where the program's EXE +// runs from. If the found DLL file is a valib Mbi interface library, +// then it is added to the list. +// +//*************************************************************************************** +procedure TmainForm.GetInterfaceFileList(fileList : TStrings); +var + SR : TSearchRec; +begin + // search all dll's in the applicatioin's directory + fileList.BeginUpdate; + if FindFirst(ExePath + '*.dll', faAnyFile, SR) = 0 then + begin + repeat + if (SR.Attr <> faDirectory) then + begin + if IsMbiInterface(ExePath + SR.Name) = True then + fileList.Add(SR.Name); + end; + until FindNext(SR) <> 0; + FindClose(SR); + end; + fileList.EndUpdate; +end; //*** end of GetInterfaceFileList *** + + +//*************************************************************************************** +// NAME: StartFileDownload +// PARAMETER: file that is to be downloaded +// RETURN VALUE: none +// DESCRIPTION: Initiates the file download. The file is verified for existence and if +// all is okay, the next page is shown and the download is started. +// +//*************************************************************************************** +procedure TmainForm.StartFileDownload(fileName : ShortString); +begin + if FileExists(fileName) and (MbiInterfaced = True) then + begin + FormCaption := mainForm.Caption; // backup original caption + mainForm.Caption := FormCaption + ' - Downloading ' + + ExtractFileName(fileName) + '...'; + prgDownload.Position := 0; // reset the progress bar + NtbPages.PageIndex := 1; // go to the next page + btnSettings.Enabled := false; // settings can't be changed anymore + MbiInterface.Download(fileName); + end; +end; //*** end of StartFileDownload *** + + +//*************************************************************************************** +// NAME: UpdateInterfaceLabel +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Updates the interface label caption based on the active Mbi interface +// library +// +//*************************************************************************************** +procedure TmainForm.UpdateInterfaceLabel; +begin + // display interface library description + if MbiInterfaced = True then + begin + lblInterfaceName.Caption := 'for ' + MbiInterface.Description; + end + else + begin + lblInterfaceName.Caption := 'Error - No Interface Library Loaded'; + end; +end; //*** end of UpdateInterfaceLabel *** + + +//*************************************************************************************** +// NAME: btnCancelClick +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Exits the application +// +//*************************************************************************************** +procedure TmainForm.btnCancelClick(Sender: TObject); +begin + // pass on cancel request to the library + if MbiInterfaced = True then + begin + MbiInterface.Cancel; + end; + + Close; +end; //*** end of btnCancelClick *** + + +//*************************************************************************************** +// NAME: FormCreate +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Initializes all the class properties and attempts to search and enable +// the Mbi interface library. +// +//*************************************************************************************** +procedure TmainForm.FormCreate(Sender: TObject); +var + cnt : integer; + foundInterface : boolean; + foundLibrary : string; + winRegistry : TRegistry; + libFileList : TStrings; +begin + LogLines := TStringList.Create; + StayOpen := false; + MbiLogging := false; + MbiInterfaced := false; // Mbi interface not enabled at startup + MbiLibFile := ''; // reset lib file + MbiInterface := TMicroBootInterface.Create(Self); // create instance + foundInterface := false; // init before searching + ExePath := ExtractFilePath(Application.ExeName); + + // determine if logging should be enabled + if (ParamCount > 0) then + begin + // no options will be in Param 0 + for cnt := 1 to ParamCount do + begin + // look for -l option + if System.Pos('-l', ParamStr(cnt)) > 0 then + begin + MbiLogging := True; + end; + end; + end; + + // this feature is unstable so do not yet support it in a release version + // determine if tool should stay open after a download completion + //if (ParamCount > 0) then + //begin + // // no options will be in Param 0 + // for cnt := 1 to ParamCount do + // begin + // // look for -l option + // if System.Pos('-s', ParamStr(cnt)) > 0 then + // begin + // StayOpen := True; + // end; + // end; + //end; + + // determine what interface library to use on startup + // 1) -------- From commandline parameter --------------- + foundLibrary := ''; + // parameters okay, now extract the command line options if any + if (ParamCount > 0) then + begin + // no options will be in Param 0 + for cnt := 1 to ParamCount do + begin + // look for -i option + if System.Pos('-i', ParamStr(cnt)) > 0 then + begin + foundLibrary := ExePath + System.Copy(ParamStr(cnt), + System.Pos('-i', ParamStr(cnt))+2, Length(ParamStr(cnt))); + end; + end; + end; + + // interface library specified on the commandline? + if foundLibrary <> '' then + begin + // is it a valid Mbi interface library? + if IsMbiInterface(foundLibrary) = True then + begin + MbiLibFile := foundLibrary; + foundInterface := True; + end; + end; + + // 2) -------- From registry --------------- + if not foundInterface then + begin + // open registry key + winRegistry := TRegistry.Create; + winRegistry.RootKey := HKEY_LOCAL_MACHINE; + winRegistry.OpenKeyReadOnly('Software\Feaser\MicroBoot'); + + // attempt to read out the stored interface filename (without path) + if winRegistry.ReadString('Interface') <> '' then + begin + // obtain the interface library file name from the registry key + foundLibrary := ExePath + winRegistry.ReadString('Interface'); + + // is it a valid Mbi interface library? + if IsMbiInterface(foundLibrary) = True then + begin + MbiLibFile := foundLibrary; + foundInterface := True; + end; + end; + winRegistry.Free; // registry access no longer needed + end; + + // 3) -------- first interface library found --------------- + if not foundInterface then + begin + libFileList := TStringList.Create; + libFileList.Clear; + GetInterfaceFileList(libFileList); + if libFileList.Count > 0 then + begin + foundLibrary := ExePath + libFileList.Strings[0]; + // is it a valid Mbi interface library? + if IsMbiInterface(foundLibrary) = True then + begin + MbiLibFile := foundLibrary; + foundInterface := True; + end; + end; + libFileList.Free; + end; + + // did we find a Mbi interface library? + if foundInterface = True then + begin + SetActiveMbi(MbiLibFile); + end; + + // create the stopwatch timer + StopWatch := TStopWatch.Create; +end; //*** end of FormCreate *** + + +//*************************************************************************************** +// NAME: FormDestroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: DeInitializes all the class properties that where instanciated. +// +//*************************************************************************************** +procedure TmainForm.FormDestroy(Sender: TObject); +begin + MbiInterface.Free; // release the interface + LogLines.Free; + + // release the stopwatch timer + StopWatch.Free; +end; //*** end of FormDestroy *** + + +//*************************************************************************************** +// NAME: FormShow +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Loads and displays the interface library description. If a valid +// download file is selected as a command line parameter the download +// is started right away. If the -p command line parameter was specified, +// then the open file dialog is displayed automatically. +// +//*************************************************************************************** +procedure TmainForm.FormShow(Sender: TObject); +var + cnt : integer; +begin + UpdateInterfaceLabel; + + // was an existing download file specified as a command line param? + if (ParamCount > 0) and (FileExists(ParamStr(ParamCount))) then + begin + edtDownloadFile.Text := ParamStr(ParamCount); + StartFileDownload(ParamStr(ParamCount)); + Exit; // nothing more todo + end; + + // was the -p command line option specified? + // parameters okay, now extract the command line options if any + if (ParamCount > 0) then + begin + // no options will be in Param 0 + for cnt := 1 to ParamCount do + begin + // look for -i option + if System.Pos('-p', ParamStr(cnt)) > 0 then + begin + if OpenDialog.Execute then + begin + if FileExists(OpenDialog.FileName) then + begin + edtDownloadFile.Text := OpenDialog.FileName; + StartFileDownload(OpenDialog.FileName); + end; + end; + end; + end; + end; +end; //*** end of FormShow *** + + +//*************************************************************************************** +// NAME: btnBrowseClick +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Prompts the user to select a file to download. +// +//*************************************************************************************** +procedure TmainForm.btnBrowseClick(Sender: TObject); +begin + if OpenDialog.Execute then + begin + if FileExists(OpenDialog.FileName) then + begin + edtDownloadFile.Text := OpenDialog.FileName; + StartFileDownload(OpenDialog.FileName); + end; + end; +end; //*** end of btnBrowseClick *** + + +//*************************************************************************************** +// NAME: btnSettingsClick +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Opens the settings form where the user can select and configure the +// Mbi interface library. +// +//*************************************************************************************** +procedure TmainForm.btnSettingsClick(Sender: TObject); +var + winRegistry : TRegistry; +begin + if SettingsForm.ShowModal = mrOK then + begin + if MbiInterfaced then + begin + // store last used library in register + winRegistry := TRegistry.Create; + winRegistry.RootKey := HKEY_LOCAL_MACHINE; + winRegistry.OpenKey('Software\Feaser\MicroBoot', true); + winRegistry.WriteString('Interface', ExtractFileName(MbiLibFile)); + winRegistry.Free; + end; + UpdateInterfaceLabel; + end; +end; //*** end of btnSettingsClick *** + + +//*************************************************************************************** +// NAME: FormClose +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Saves the log to a file before closing the application. +// +//*************************************************************************************** +procedure TmainForm.FormClose(Sender: TObject; var Action: TCloseAction); +begin + // save the log to a file before closing the app + if MbiLogging = True then + begin + LogLines.SaveToFile(ExePath + 'log.txt'); + end; +end; //*** end of FormClose *** + + +//*************************************************************************************** +// NAME: TimeTimer +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Timer event handler to update stopwatch info +// +//*************************************************************************************** +procedure TmainForm.TimerTimer(Sender: TObject); +begin + lblElapsedTime.Caption := 'Elapsed time: ' + StopWatch.Interval; +end; //*** end of TimerTimer *** + +procedure TmainForm.edtDownloadFileKeyPress(Sender: TObject; + var Key: Char); +begin + // filter out enter key + if key = #13 then + begin + // ignore further enter key processing + key := #0; + + // start the download + if FileExists(edtDownloadFile.Text) then + begin + StartFileDownload(edtDownloadFile.Text); + end; + + end; +end; + +end. +//******************************** end of MainUnit.pas ********************************** + diff --git a/Host/Source/MicroBoot.cfg b/Host/Source/MicroBoot.cfg new file mode 100644 index 00000000..baee3e0e --- /dev/null +++ b/Host/Source/MicroBoot.cfg @@ -0,0 +1,35 @@ +-$A+ +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J+ +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-E../ +-LNc:\program files (x86)\borland\delphi4\Lib diff --git a/Host/Source/MicroBoot.dof b/Host/Source/MicroBoot.dof new file mode 100644 index 00000000..07fb676d --- /dev/null +++ b/Host/Source/MicroBoot.dof @@ -0,0 +1,86 @@ +[Compiler] +A=1 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=1 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir=../ +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages=Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40 +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1031 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +$(DELPHI)\Lib\dclusr40.bpl=Borland User +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlOutputDirectorry] +Count=1 +Item0=../ diff --git a/Host/Source/MicroBoot.dpr b/Host/Source/MicroBoot.dpr new file mode 100644 index 00000000..dc5a1876 --- /dev/null +++ b/Host/Source/MicroBoot.dpr @@ -0,0 +1,55 @@ +program MicroBoot; +//*************************************************************************************** +// Project Name: MicroBoot for Borland Delphi +// Description: Contains the main program entry +// File Name: MicroBoot.dpr +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** + +uses + Forms, + MainUnit in 'MainUnit.pas' {mainForm}, + SettingsUnit in 'SettingsUnit.pas' {settingsForm}, + StopWatch in 'StopWatch.pas'; + +{$R *.RES} + +begin + Application.Initialize; + Application.Title := 'MicroBoot'; + Application.CreateForm(TmainForm, mainForm); + Application.CreateForm(TsettingsForm, settingsForm); + Application.Run; +end. +//******************************** end of MicroBoot.dpr ********************************* + diff --git a/Host/Source/MicroBoot.ico b/Host/Source/MicroBoot.ico new file mode 100644 index 0000000000000000000000000000000000000000..3846b3923a63d82076166380770019f477c70a71 GIT binary patch literal 2238 zcmd5-e@L8V9RHl&O}Cs)@9w?Lwa!{wSGm<*b+69Ndkq`T_J={ZF-99#qlQC97U@yU z1|1R7^r#ULGNRb9!D^Iw^v_`+GA<=%bD4k02(1t*Are?PCp4m z4gjwU4+6bU0e!+FK$JWi0^U6aoI4JDcmnw7B=B(uaQQ{xvzLIOE+ED{;TZ7ctH9`M zz?BFv{swTh2l%!Z_^uC_jxyggFkqo+$U>Vng0>M0kw^s5XcYbZ{TLV+z~JB@-kh-T z$qfs`!^0RG8^hGp6lP~! z%7gedES|ZJ`MokvO25Va%QheBcaY}PcdxYkYs&4Un1Of z9zJy^_o{v#ZgIZ~c#r4QxWvz0@?oN@8f;X)M&_ux>Ve5t^b4F1n8YvaFZSHT4R;dH z(DvN);V9eQH3=l>BXM>ggY$Nj%`3mr!H|l{#8uGuxNo^8`2_i7cQ~QgLcjM5`Cbr* zX*X;#v)T#v|KJ&a{!S9(W3*ePq5b^WZ(t38r^njSKhEq5w&A2ad)WxJB>cUL^f35X;S58&ROSBT4r7Nkt(Do0+%C7%Jb(VSvFQE~JVaTJlE}O#RHEL>i z)$!AlhBM$dg25$S%hjs`noalS>YCeYkJq$p`e4vB8yX%JEalgjPf5J^-!^5=4E_YKsG)fP literal 0 HcmV?d00001 diff --git a/Host/Source/SettingsUnit.dfm b/Host/Source/SettingsUnit.dfm new file mode 100644 index 0000000000000000000000000000000000000000..4e0f9173e7dcc7f0880f969a9b2720ba8a8493e1 GIT binary patch literal 996 zcmZWoOK#gR5T)c=v}HR9(iT}2@Ukl-?G0i%N{l3y5wS>jEhUd-A{6ORbUwG}NqUnW zr|XsyWhq5h;*c}%y_q-q<0BHE6Ea_1#9?%MgHDfrbr2%U@N`59(3**?2&Kx0uY)(& zu-2WQPKU^C=Z7lY5VmlQKbxy*1tx0*@e9nXaZwWcYI;~H@oa0WtO0?Rhq zeH_^Ej;-{j^Wby?$)&>mluxw?P2Dh*LQjGXRYnCqoSlbfU#`iw;PUL&i1+PlRWnTa z9TO}0MBrHus)w57cfX1jGzV{V6OUsm3ZqA{wXLtz570rxSAhbmAu4<7^_H?=WgGZl zE8|oFh`=Z}FOjf$*wm}sp8JuQL7|m=!G>Jrb>KxJ-pD81EAPtFXvv;|7fVock#5}Y zekr#WIzk>hmQ8{jR(cO>9s|!AM&p68j?omFKTFcy@!Xxl#XDYFm zJT9bw9-&Fqkn13X$#iG(L^shQy0>P2sLXV~T6Fhn4}Q|v=tfs~25Y+Gy5GVfZ05jO zdXN1ItvVyrCl^ZYwp00hoT-FRm4R;7;B`CbzjhXFJ9aG^1t&3ZNcGsljT^jHjcbSl znJ3Z^kJ2P*QVPp?RE=<4b2`qx%lBQoya#D9Q*t|#PvV*t+MjF4_qL46pqRv3mH&j} zd8=KXzkI5{pHZs. +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, ExtCtrls; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TsettingsForm = class(TForm) + btnOk: TButton; + pnlFooter: TPanel; + grbTargetInterface: TGroupBox; + cbbInterfaces: TComboBox; + btnOptions: TButton; + procedure btnOkClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure btnOptionsClick(Sender: TObject); + procedure cbbInterfacesChange(Sender: TObject); + private + { Private declarations } + libFileNameList : TStrings; + libFileInfoList : TStrings; + ExePath : string; + public + { Public declarations } + end; + +//*************************************************************************************** +// Global Variables +//*************************************************************************************** +var + settingsForm: TsettingsForm; + +implementation + +//*************************************************************************************** +// Local Includes +//*************************************************************************************** +uses MainUnit; + +{$R *.DFM} + + +//*************************************************************************************** +// NAME: btnOkClick +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Closes the dialog and sends a positive response back to the +// application. +// +//*************************************************************************************** +procedure TsettingsForm.btnOkClick(Sender: TObject); +begin + ModalResult := mrOK; +end; //*** end of btnOkClick *** + + +//*************************************************************************************** +// NAME: FormCreate +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Constructs the form an creates instances of the objects we intend to +// use. +// +//*************************************************************************************** +procedure TsettingsForm.FormCreate(Sender: TObject); +begin + // instanciate string lists + libFileNameList := TStringList.Create; + libFileInfoList := TStringList.Create; + + ExePath := ExtractFilePath(Application.ExeName); + +end; //*** end of FormCreate *** + + +//*************************************************************************************** +// NAME: FormDestroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Destroys the form an frees instances of the objects we used. +// +//*************************************************************************************** +procedure TsettingsForm.FormDestroy(Sender: TObject); +begin + libFileNameList.Free; + libFileInfoList.Free; +end; //*** end of FormDestroy *** + + +//*************************************************************************************** +// NAME: FormShow +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Obtains list with interface libraries and adds each one of these +// to the combobox with a description so it's easy for users to select +// one. +// +//*************************************************************************************** +procedure TsettingsForm.FormShow(Sender: TObject); +var + cnt : integer; + activeLib : string; +begin + // clear string lists before using them + libFileNameList.Clear; + libFileInfoList.Clear; + cbbInterfaces.Items.Clear; + + // obtian list with available Mbi interface DLL's that are found in the EXE path + mainForm.GetInterfaceFileList(libFileNameList); + + activeLib := ExtractFileName(mainForm.GetActiveMbi); + + for cnt := 0 to libFileNameList.Count-1 do + begin + cbbInterfaces.Items.Add(mainForm.GetMbiInfoString(ExePath + + libFileNameList[cnt])); + + //select the active one + if libFileNameList[cnt] = activeLib then + begin + cbbInterfaces.ItemIndex := cnt; + end; + end; +end; //*** end of FormShow *** + + +//*************************************************************************************** +// NAME: btnOptionsClick +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Submits a request to the interface library to display extra +// configuration options. +// +//*************************************************************************************** +procedure TsettingsForm.btnOptionsClick(Sender: TObject); +var + cnt : integer; + activeLib : string; +begin + // submit configuration request to interface library + mainForm.ConfigureMbi; + + // clear string lists before using them + libFileNameList.Clear; + libFileInfoList.Clear; + cbbInterfaces.Items.Clear; + + // obtian list with available Mbi interface DLL's that are found in the EXE path + mainForm.GetInterfaceFileList(libFileNameList); + + activeLib := ExtractFileName(mainForm.GetActiveMbi); + + for cnt := 0 to libFileNameList.Count-1 do + begin + cbbInterfaces.Items.Add(mainForm.GetMbiInfoString(ExePath + + libFileNameList[cnt])); + + //select the active one + if libFileNameList[cnt] = activeLib then + begin + cbbInterfaces.ItemIndex := cnt; + end; + end; +end; //*** end of btnOptionsClick *** + + +//*************************************************************************************** +// NAME: cbbInterfacesChange +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Updates the interface library that is linked to the application. +// +//*************************************************************************************** +procedure TsettingsForm.cbbInterfacesChange(Sender: TObject); +begin + // enable the selected mbi interface + mainForm.SetActiveMbi(ExePath + libFileNameList[cbbInterfaces.ItemIndex]); +end; //*** end of cbbInterfacesChange *** + +end. +//******************************** end of SettingsUnit.pas ****************************** + diff --git a/Host/Source/StopWatch.pas b/Host/Source/StopWatch.pas new file mode 100644 index 00000000..11a9fbf4 --- /dev/null +++ b/Host/Source/StopWatch.pas @@ -0,0 +1,143 @@ +unit StopWatch; +//*************************************************************************************** +// Description: StopWatch timer for counting minutes and seconds +// File Name: StopWatch.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, ExtCtrls; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TStopWatch = class(TObject) + private + FStartTime : TDateTime; + FRunning : boolean; + public + constructor Create; + procedure Start; + procedure Stop; + function Interval : string; + end; + + +implementation +//*************************************************************************************** +// NAME: Create +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class constructor +// +//*************************************************************************************** +constructor TStopWatch.Create; +begin + // call inherited constructor + inherited Create; + + // initialize variables + FRunning := false; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Start +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Starts the stopwatch timer +// +//*************************************************************************************** +procedure TStopWatch.Start; +begin + // store the start time + FStartTime := Time; + + // start the stopwatch + FRunning := true; +end; //*** end of Start *** + + +//*************************************************************************************** +// NAME: Stop +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Stops the stopwatch timer +// +//*************************************************************************************** +procedure TStopWatch.Stop; +begin + // stop the stopwatch + FRunning := false; +end; //*** end of Stop *** + + +//*************************************************************************************** +// NAME: Interval +// PARAMETER: none +// RETURN VALUE: stopwatch time as string in format [min]:[sec]. +// DESCRIPTION: Obtains the stopwatch time as a formatted string. +// +//*************************************************************************************** +function TStopWatch.Interval : string; +var + hr : word; + min : word; + sec : word; + ms : word; +begin + // decode the elased stopwatch time + DecodeTime(Time-FStartTime, hr, min, sec, ms); + + // check if stopwatch is running + if not FRunning then + begin + min := 0; + sec := 0; + end; + + // update the formatted stopwatch time string + result := Format('%2.2d:%2.2d', [min, sec]); +end; //*** end of Interval *** + + +end. +//******************************** end of StopWatch.pas ********************************* + diff --git a/Host/Source/interfaces/SRecReader.pas b/Host/Source/interfaces/SRecReader.pas new file mode 100644 index 00000000..66ed33d0 --- /dev/null +++ b/Host/Source/interfaces/SRecReader.pas @@ -0,0 +1,649 @@ +unit SRecReader; +//*************************************************************************************** +// Project Name: Motorola S-Record Reader +// Description: Class used to read S-Record files. Supports both S19 and S28 records. +// File Name: SRecReader.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Forms; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + PByte = ^Byte; + TSRecLineType = (ltInvalid, ltS0, ltS1, ltS2, ltS3, ltS7, ltS8, ltS9); + TSRecType = (tpS1, tpS2, tpS3, tpMixed); + +type + TSRecData = record + val : Byte; + addr : LongWord; + end; + +type + PRegion = ^TRegion; + TRegion = record + addr : LongWord; + size : LongWord; + end; + +type + TSRecReader = class(TObject) + private + FFileName : String; + FDataSize : Longword; + FFirstAddr : LongWord; + FLastAddr : LongWord; + FFileType : TSRecType; + FRegions : TList; + FRegionsCnt : Word; + function GetLineType(line: String) : TSRecLineType; + function GetLineSize(line: String; var size: Word) : Boolean; + function GetLineData(line: String; index: Word; var data: TSRecData) : Boolean; + function GetLineAddress(line: String; var address: LongWord) : Boolean; + procedure UpdateRegions(addr: LongWord; size: Word); + public + constructor Create; + destructor Destroy; override; + function SetFileName(fileName : String) : Boolean; + function GetFileName : String; + function GetDataSize : Longword; + function GetFirstAddress : Longword; + function GetLastAddress : Longword; + function GetRegionCount : Word; + procedure GetRegion(index : Word; var addr : Longword; var length : Longword); + procedure GetData(var buffer : array of Byte; addr : Longword; length : Longword); + function GetFileType : TSRecType; + function BlankCheck(addr : Longword; length : Longword) : Boolean; + end; + + +implementation + +//*************************************************************************************** +// NAME: Create +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class constructore +// +//*************************************************************************************** +constructor TSRecReader.Create; +begin + inherited Create; + FRegions := TList.Create; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class destructor +// +//*************************************************************************************** +destructor TSRecReader.Destroy; +var + index : Word; + region: PRegion; +begin + if FRegions.Count > 0 then + begin + for index := 0 to FRegions.Count-1 do + begin + region := FRegions.Items[index]; + Dispose(region); + end; + end; + + FRegions.Free; + inherited; +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: UpdateRegions +// PARAMETER: addr: start address of data +// size: length of data +// RETURN VALUE: none +// DESCRIPTION: Processes the data by categorizing it into a region. +// +//*************************************************************************************** +procedure TSRecReader.UpdateRegions(addr: LongWord; size: Word); +var + index : Word; + added : Boolean; + region: PRegion; +begin + added := False; + + if FRegions.Count > 0 then + begin + // loop through all existing regions + for index := 0 to FRegions.Count-1 do + begin + // set pointer to this region + region := FRegions.Items[index]; + + // does data fit at the end? + if (region^.addr+region^.size) = addr then + begin + // add at the end of this region + region^.size := region^.size + size; + added := True; + end + // does data fit at the start? + else if region^.addr = (addr+size) then + begin + // add at the start of this region + region^.addr := region^.addr - size; + added := True; + end; + + // was data added to a region? + if added then + begin + Break; // no need to continue loop + end; + end; + end; + + // data couldn't be added to an existing region? + if not added then + begin + // create a new region and add the data there + New(region); + region^.addr := addr; + region^.size := size; + FRegions.Add(region); + end; +end; //*** end of UpdateRegions *** + + +//*************************************************************************************** +// NAME: GetLineType +// PARAMETER: Line from S-Record +// RETURN VALUE: line type +// DESCRIPTION: Determines what type of S-Record line we're dealing with. +// +//*************************************************************************************** +function TSRecReader.GetLineType(line: String) : TSRecLineType; +begin + Result := ltInvalid; + + if Pos('S0', UpperCase(line)) > 0 then Result := ltS0; + if Pos('S1', UpperCase(line)) > 0 then Result := ltS1; + if Pos('S2', UpperCase(line)) > 0 then Result := ltS2; + if Pos('S3', UpperCase(line)) > 0 then Result := ltS3; + if Pos('S7', UpperCase(line)) > 0 then Result := ltS7; + if Pos('S8', UpperCase(line)) > 0 then Result := ltS8; + if Pos('S9', UpperCase(line)) > 0 then Result := ltS9; +end; //*** end of GetLineType *** + + +//*************************************************************************************** +// NAME: GetLineSize +// PARAMETER: Line from S-Record +// RETURN VALUE: Number of data bytes +// DESCRIPTION: Obtains the number of databytes in the specified S-Record line. +// +//*************************************************************************************** +function TSRecReader.GetLineSize(line: String; var size: Word) : Boolean; +var + unusedBytes : Byte; +begin + Result := false; // init + + if GetLineType(line) = ltS1 then + unusedBytes := 3 // 2 for address and 1 for checksum + else if GetLineType(line) = ltS2 then + unusedBytes := 4 // 3 for address and 1 for checksum + else if GetLineType(line) = ltS3 then + unusedBytes := 5 // 4 for address and 1 for checksum + else + Exit; // not a S1 or S2 line + + size := StrToInt('$' + Copy(line, 3, 2)) - unusedBytes; + Result := true; +end; //*** end of GetLineSize *** + + +//*************************************************************************************** +// NAME: GetLineData +// PARAMETER: Line from S-Record +// RETURN VALUE: data at a specific index (starts at 0) +// DESCRIPTION: Obtains the data at a specific index in the specified S-Record line. +// +//*************************************************************************************** +function TSRecReader.GetLineData(line: String; index: Word; var data: TSRecData) : Boolean; +var + dataOffset : Byte; + lineSize : Word; + lineAddr : LongWord; +begin + Result := false; // init + + if GetLineType(line) = ltS1 then + dataOffset := 9 // characters untill we reach actual data + else if GetLineType(line) = ltS2 then + dataOffset := 11 // characters untill we reach actual data + else if GetLineType(line) = ltS3 then + dataOffset := 13 // characters untill we reach actual data + else + Exit; // not a S1, S2 or S3 line + + // make sure index parameter is valid + if not GetLineSize(line, lineSize) then + Exit + else + if index > (lineSize-1) then Exit; + + // obtain the start address of the line + if not GetLineAddress(line, lineAddr) then + Exit; + + data.val := StrToInt('$' + Copy(line, dataOffset+(index*2), 2)); + data.addr := lineAddr + index; + + Result := true; +end; //*** end of GetLineData *** + + +//*************************************************************************************** +// NAME: GetLineAddress +// PARAMETER: Line from S-Record +// RETURN VALUE: Start address +// DESCRIPTION: Obtains the start address as specified in the S-Record line. +// +//*************************************************************************************** +function TSRecReader.GetLineAddress(line: String; var address: LongWord) : Boolean; +var + addrLength : Byte; +begin + Result := false; // init + + if GetLineType(line) = ltS1 then + addrLength := 4 // 2 byte address + else if GetLineType(line) = ltS2 then + addrLength := 6 // 3 byte address + else if GetLineType(line) = ltS3 then + addrLength := 8 // 4 byte address + else + Exit; // not a S1, S2 or S3 line + + address := StrToInt('$' + Copy(line, 5, addrLength)); + Result := true; +end; //*** end of GetLineAddress *** + + +//*************************************************************************************** +// NAME: SetFileName +// PARAMETER: Filename with full path +// RETURN VALUE: True when the S-Record was valid and could be loaded, otherwise False. +// DESCRIPTION: Function verifies that the file is actually a S-Record. If so, then +// the most class properties are set based on the info in the S-Record. +// +//*************************************************************************************** +function TSRecReader.SetFileName(fileName : String) : Boolean; +var + SRecFile : TextFile; + Line : string; + ValidSRec : Boolean; + LineSize : Word; + LineAddr : LongWord; + S1RecFound : Boolean; + S2RecFound : Boolean; + S3RecFound : Boolean; +begin + // first reset all the internal properties + FFileName := ''; + FDataSize := 0; + FFirstAddr := $ffffffff; + FLastAddr := 0; + FFileType := tpS1; + FRegionsCnt := 0; + FRegions.Clear; + + // init locals + S1RecFound := false; + S2RecFound := false; + S3RecFound := false; + Result := false; + ValidSRec := false; + + // 1. Verify if file exists + if not FileExists(fileName) then Exit; + + // 2. Verify if file contains S-Records + AssignFile(SRecFile, fileName); // get file handle + Reset(SRecFile); // go to start of file + while not Eof(SRecFile) do + begin + ReadLn(SRecFile, Line); // read line from file + if (GetLineType(Line) = ltS1) or (GetLineType(Line) = ltS2) or + (GetLineType(Line) = ltS3) then + begin + ValidSRec := true; + Break; // valid S-Record + end; + end; + CloseFile(SRecFile); // release file + if not ValidSRec then Exit; + + // 3. Calculate datasize, first address and last address + AssignFile(SRecFile, fileName); // get file handle + Reset(SRecFile); // go to start of file + while not Eof(SRecFile) do + begin + ReadLn(SRecFile, Line); // read line from file + LineSize := 0; // init + if GetLineSize(Line, LineSize) then + FDataSize := FDataSize + LineSize; // add to previous value + + if GetLineAddress(Line, LineAddr) then + begin + if LineAddr < FFirstAddr then + FFirstAddr := LineAddr; + + if LineAddr > FLastAddr then + FLastAddr := LineAddr + LineSize -1; + end; + + // check line type + if GetLineType(line) = ltS1 then + S1RecFound := true; + if GetLineType(line) = ltS2 then + S2RecFound := true; + if GetLineType(line) = ltS3 then + S3RecFound := true; + + end; + CloseFile(SRecFile); // release file + + // set file type + if (S1RecFound) and (not S2RecFound) and (not S3RecFound) then + FFileType := tpS1 + else if (S2RecFound) and (not S1RecFound) and (not S3RecFound) then + FFileType := tpS2 + else if (not S2RecFound) and (not S1RecFound) and (S3RecFound) then + FFileType := tpS3 + else + FFileType := tpMixed; + + // 4. Determine regions + AssignFile(SRecFile, fileName); // get file handle + Reset(SRecFile); // go to start of file + while not Eof(SRecFile) do + begin + ReadLn(SRecFile, Line); // read line from file + LineSize := 0; // init + + if GetLineAddress(Line, LineAddr) then + begin + if GetLineSize(Line, LineSize) then + begin + UpdateRegions(LineAddr, LineSize); + end; + end; + end; + CloseFile(SRecFile); // release file + + // set region count + FRegionsCnt := FRegions.Count; + + // 5. Verify properties and if ok, set the FFilename property + if (FDataSize <> 0) and (FFirstAddr <> $ffffffff) and (FLastAddr <> 0) then + begin + FFileName := fileName; // set the filename property + Result := true; + end; +end; //*** end of SetFileName *** + + +//*************************************************************************************** +// NAME: GetFileName +// PARAMETER: none +// RETURN VALUE: Filename with full path or '' when invalid. +// DESCRIPTION: S-Record filename that is configured to be read be this class. +// +//*************************************************************************************** +function TSRecReader.GetFileName : String; +begin + Result := FFileName; +end; //*** end of GetFileName *** + + +//*************************************************************************************** +// NAME: GetDataSize +// PARAMETER: none +// RETURN VALUE: Size of data. +// DESCRIPTION: Obtains the number of databytes in the S-Record. 0xFF values are +// not included. +// +//*************************************************************************************** +function TSRecReader.GetDataSize : Longword; +begin + Result := FDataSize; +end; //*** end of GetDataSize *** + + +//*************************************************************************************** +// NAME: GetFirstAddress +// PARAMETER: none +// RETURN VALUE: First address in S-Record. +// DESCRIPTION: Obtains the first memory address with data in the S-Record. +// +//*************************************************************************************** +function TSRecReader.GetFirstAddress : Longword; +begin + Result := FFirstAddr; +end; //*** end of GetFirstAddress *** + + +//*************************************************************************************** +// NAME: GetLastAddress +// PARAMETER: none +// RETURN VALUE: Last address in S-Record. +// DESCRIPTION: Obtains the last memory address with data in the S-Record. +// +//*************************************************************************************** +function TSRecReader.GetLastAddress : Longword; +begin + Result := FLastAddr; +end; //*** end of GetLastAddress *** + + +//*************************************************************************************** +// NAME: GetRegionCount +// PARAMETER: none +// RETURN VALUE: Number of address regions +// DESCRIPTION: Obtains the number of address regions found in the S-record. +// +//*************************************************************************************** +function TSRecReader.GetRegionCount : Word; +begin + Result := FRegionsCnt; +end; //*** end of GetRegionCount *** + + +//*************************************************************************************** +// NAME: GetRegion +// PARAMETER: index: region index to retrieve info from +// addr: destination for region's start address +// length: destination for region's length +// RETURN VALUE: none +// DESCRIPTION: Obtains the address region info. +// +//*************************************************************************************** +procedure TSRecReader.GetRegion(index : Word; var addr : Longword; var length : Longword); +var + region: PRegion; +begin + // initialize return values + addr := 0; + length := 0; + + if FRegions.Count > 0 then + begin + if index < FRegions.Count then + begin + // set pointer to this region + region := FRegions.Items[index]; + + // obtain region info + addr := region^.addr; + length := region^.size; + end; + end; +end; //*** end of GetRegion *** + + +//*************************************************************************************** +// NAME: GetData +// PARAMETER: buffer is a pointer to a byte buffer where the data will be written +// to from memory address addr to addr+length. +// RETURN VALUE: none +// DESCRIPTION: Obtains the data in the S-Record for a memory block that starts at +// addr and goes until addr+length and stores the data in buffer. empty +// data will be filled with 0xFF. +// +//*************************************************************************************** +procedure TSRecReader.GetData(var buffer : array of Byte; addr : Longword; length : Longword); +var + data : TSRecData; + line : string; + lineAddr : LongWord; + lineSize : Word; + SRecFile : TextFile; + cnt : Word; + ok2Continue : boolean; +begin + // check parameters + if length = 0 then Exit; + + // first init entire buffer to 0xff + for cnt := 0 to length-1 do + begin + buffer[cnt] := $ff; + end; + + // go through each line to see if it has data for us + AssignFile(SRecFile, FFileName); // get file handle + Reset(SRecFile); // go to start of file + while not Eof(SRecFile) do + begin + // this can take a while so process messages to not stall the parent app + Application.ProcessMessages; + + ReadLn(SRecFile, line); // read line from file + ok2Continue := true; // init + + // obtain line properties + if not GetLineAddress(line, lineAddr) then ok2Continue := false; + if not GetLineSize(line, lineSize) then ok2Continue := false; + + if ok2Continue then + begin + // process all data on the line + for cnt := 0 to lineSize-1 do + begin + // read data info + if not GetLineData(line, cnt, data) then ok2Continue := false; + if ok2Continue then + begin + // is this one for us? + if (data.addr >= addr) and (data.addr <= (addr+length-1)) then + begin + // store it in the memory buffer + buffer[data.addr-addr] := data.val; + end; + end; + end; + end; + + end; + CloseFile(SRecFile); // release file +end; //*** end of GetData *** + + +//*************************************************************************************** +// NAME: GetFileType +// PARAMETER: none +// RETURN VALUE: S-Record file type +// DESCRIPTION: Determines is the file contains just S1 data lines, just S2 data +// lines. or a combination of these two. +// +//*************************************************************************************** +function TSRecReader.GetFileType : TSRecType; +begin + Result := FFileType; +end; //*** end of GetFileType *** + + +//*************************************************************************************** +// NAME: BlankCheck +// PARAMETER: checks from addr to addr+length-1. +// RETURN VALUE: true if all bytes are 0xff, false otherwise +// DESCRIPTION: Checks if a memory range in the S-Record file is empty (0xff) or not. +// +//*************************************************************************************** +function TSRecReader.BlankCheck(addr : Longword; length : Longword) : Boolean; +var + buffer : array of Byte; + cnt : LongWord; +begin + Result := true; + SetLength(buffer, length); // init size of the dynamic array + GetData(buffer, addr, length); // fill it with the data contents from the S-Record + + for cnt := 0 to length-1 do + begin + if buffer[cnt] <> $ff then + begin + Result := false; // memory range is not blank + Break; // no need to continue loop + end; + end; +end; //*** end of BlankCheck *** + +end. +//******************************** end of SRecReader.pas ******************************** + diff --git a/Host/Source/interfaces/XcpDataFile.pas b/Host/Source/interfaces/XcpDataFile.pas new file mode 100644 index 00000000..00ee8fa6 --- /dev/null +++ b/Host/Source/interfaces/XcpDataFile.pas @@ -0,0 +1,219 @@ +unit XcpDataFile; +//*************************************************************************************** +// Description: XCP data file interface. +// File Name: XcpDataFile.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Forms, SRecReader; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TXcpDataFile = class(TObject) + private + FDataFileReady : Boolean; + FRegionCount : Word; + FDataFile : TSRecReader; + public + constructor Create(dataFile: string); + destructor Destroy; override; + function GetDataCnt : LongWord; + function GetRegionCnt : Word; + procedure GetRegionInfo(region : Word; var addr : Longword; var len : Longword); + function GetRegionData(region : Word; var data : array of Byte) : LongWord; + end; + + +implementation + +//*************************************************************************************** +// NAME: Create +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class constructor +// +//*************************************************************************************** +constructor TXcpDataFile.Create(dataFile: string); +begin + // call inherited constructor + inherited Create; + + // instantiate S-Record reader object + FDataFile := TSRecReader.Create; + + // reset data file ready flag + FDataFileReady := false; + + // reset the region count + FRegionCount := 0; + + // open the data file as an S-Record file + if FDataFile.SetFileName(dataFile) then + begin + // set data file ready flag + FDataFileReady := true; + + // obtain the number of data regions + FRegionCount := FDataFile.GetRegionCount; + end; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class destructor +// +//*************************************************************************************** +destructor TXcpDataFile.Destroy; +begin + // release S-Record reader object + FDataFile.Free; + + // call inherited destructor + inherited; +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: GetDataCnt +// PARAMETER: none +// RETURN VALUE: number of data bytes +// DESCRIPTION: Returns the number of data bytes in the data file +// +//*************************************************************************************** +function TXcpDataFile.GetDataCnt : LongWord; +begin + // init return value + result := 0; + + // verify data file state + if not FDataFileReady then Exit; + + // return the number of data bytes in the data file + result := FDataFile.GetDataSize; +end; //*** end of GetDataCnt *** + + +//*************************************************************************************** +// NAME: GetRegionCnt +// PARAMETER: none +// RETURN VALUE: number of data regions +// DESCRIPTION: Returns the number of data regions in the data file +// +//*************************************************************************************** +function TXcpDataFile.GetRegionCnt : Word; +begin + // init return value + result := 0; + + // verify data file state + if not FDataFileReady then Exit; + + // return the number of data regions + result := FRegionCount; +end; //*** end of GetRegionCnt *** + + +//*************************************************************************************** +// NAME: GetRegionInfo +// PARAMETER: region index and parameters where to store the region start address +// and length info. +// RETURN VALUE: none +// DESCRIPTION: Returns the number of data bytes in the specified region and its +// start address. +// +//*************************************************************************************** +procedure TXcpDataFile.GetRegionInfo(region : Word; var addr : Longword; var len : Longword); +begin + // init return parameters + addr := 0; + len := 0; + + // verify data file state + if not FDataFileReady then Exit; + + // validate input parameter + if region > FRegionCount-1 then Exit; + + // obtain the region information + FDataFile.GetRegion(region, addr, len); +end; //*** end of GetRegionInfo *** + + +//*************************************************************************************** +// NAME: GetRegionData +// PARAMETER: region index and a pointer to the data buffer where the data will be +// stored. +// RETURN VALUE: Number of data bytes stored in the data buffer +// DESCRIPTION: Reads the data from a specific region into the specified data buffer. +// +//*************************************************************************************** +function TXcpDataFile.GetRegionData(region : Word; var data : array of Byte) : LongWord; +var + addr : LongWord; + len : LongWord; +begin + // init return value + result := 0; + + // verify data file state + if not FDataFileReady then Exit; + + // validate input parameter + if region > FRegionCount-1 then Exit; + + // obtain region info + FDataFile.GetRegion(region, addr, len); + + // obtain the region data + FDataFile.GetData(data, addr, len); + + // return the number of data bytes stored in the data buffer + result := len; +end; //*** end of GetRegionData *** + + +end. +//******************************** end of XcpDataFile.pas ******************************* + diff --git a/Host/Source/interfaces/XcpIcon.bmp b/Host/Source/interfaces/XcpIcon.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c7923878ddf089caf7b6e3fb2a992a38227b4abb GIT binary patch literal 2446 zcmeHH{Yz6(7(R1T79th~CJ~0FCK%**g-RLCax1CX5-JVS((vkZhV+Hn4{7~SVWpW? zl!{umOx>M1S30xOB(2%L?!K&lr04F+X@)=c0nz2$!+YQNKJW9M_dMrh@4vo^_?|S( zoAE~B4aX}Y>o5~iuoU-wEKT1$-ajx1`2!@N_|LOqpZj`xR4UcXyZ0+be_h{lb8{i9 zi{~%=W}cj!9PrehJ^S~07G0jP0n7NX-ECjtAbC0O{ItVq_4pUc+3aJZ25tYdp%;TL z2ZxaVdW?p#mOFR4J3B4r1&Sg>`|xwBgiR6a_eUE#Z_a;pFR{U3`xXikjcGypBU{Iu zRu@2Cr>nK4B|0ifB9R0H1c=4r`no#GQ?0J@aL$;R81zsi5=BHrG&MGQoIH?_H=|ZC z>D78cgtc8~H@ zRjPqy7$!0@GCZ8Wh)_$7rpCvE38kB7xrWnIDPlHBq}H-p7>D!oL6V-Hj^d?U>Nv)tEIjflT{J@68qDnep`Qf0!vDl4)?bGXx-)d27p3B zLY`~2KjqUt?T54=!j60G*cRl(4?W%8!NI|h0$NQ7q}9m0uRA%tb1g67oDHmHo^#oq zg;@jmObcYy2TiRFA3U5J5{iq91C>-NMTuplrIi(xv(tPb$epiLA_UcE@5-*Ms8Gli zf;eS+_CPm;TrM@Cbfm!4k+T68~+~9ckFYA&j0`b literal 0 HcmV?d00001 diff --git a/Host/Source/interfaces/XcpLoader.pas b/Host/Source/interfaces/XcpLoader.pas new file mode 100644 index 00000000..59307b58 --- /dev/null +++ b/Host/Source/interfaces/XcpLoader.pas @@ -0,0 +1,1241 @@ +unit XcpLoader; +//*************************************************************************************** +// Description: XCP Master Communication Protocol Layer for Bootloader. +// File Name: XcpLoader.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Forms, XcpTransport, XcpProtection, IniFiles; + +//*************************************************************************************** +// Global Constants +//*************************************************************************************** +// XCP command codes +const kCmdCONNECT = $FF; +const kCmdDISCONNECT = $FE; +const kCmdGET_STATUS = $FD; +const kCmdSYNCH = $FC; +const kCmdGET_ID = $FA; +const kCmdGET_SEED = $F8; +const kCmdUNLOCK = $F7; +const kCmdSET_MTA = $F6; +const kCmdUPLOAD = $F5; +const kCmdSHORT_UPLOAD = $F4; +const kCmdBUILD_CHECKSUM = $F3; +const kCmdDOWNLOAD = $F0; +const kCmdDOWNLOAD_MAX = $EE; +const kCmdSET_CAL_PAGE = $EB; +const kCmdGET_CAL_PAGE = $EA; +const kCmdPROGRAM_START = $D2; +const kCmdPROGRAM_CLEAR = $D1; +const kCmdPROGRAM = $D0; +const kCmdPROGRAM_RESET = $CF; +const kCmdPROGRAM_PREPARE = $CC; +const kCmdPROGRAM_MAX = $C9; + +// XCP command response packet IDs +const kCmdPidRES = $FF; // positive response packet +const kCmdPidERR = $FE; // error packet +const kCmdPidEV = $FD; // event packet +const kCmdPidSERV = $FC; // service request packet + +// XCP resources +const kResPGM = $10; // programming resource + +// XCP error codes +const kErrCMD_SYNCH = $00; // Command processor synchronization +const kErrCMD_BUSY = $10; // Command was not executed. +const kErrDAQ_ACTIVE = $11; // Command rejected because DAQ is running. +const kErrPGM_ACTIVE = $12; // Command rejected because PGM is running. +const kErrCMD_UNKNOWN = $20; // Unknown command or not implemented optional command. +const kErrCMD_SYNTAX = $21; // Command syntax invalid +const kErrOUT_OF_RANGE = $22; // Command syntax valid but command parameter(s) out of range. +const kErrWRITE_PROTECTED = $23; // The memory location is write protected. +const kErrACCESS_DENIED = $24; // The memory location is not accessible. +const kErrACCESS_LOCKED = $25; // Access denied, Seed & Key is required +const kErrPAGE_NOT_VALID = $26; // Selected page not available +const kErrMODE_NOT_VALID = $27; // Selected page mode not available +const kErrSEGMENT_NOT_VALID = $28; // Selected segment not valid +const kErrSEQUENCE = $29; // Sequence error +const kErrDAQ_CONFIG = $2A; // DAQ configuration not valid +const kErrMEMORY_OVERFLOW = $30; // Memory overflow error +const kErrGENERIC = $31; // Generic error +const kErrVERIFY = $32; // The slave internal program verify routine detects an error. + +// Feaser error Codes +const kErrFsrExecuteCmd = $80; // Could not execute command +const kErrFsrResourceUnavailable = $81; // Resource needed but not available +const kErrFsrSeedKeyDllInvalid = $82; // Seed/Key DLL is invalid +const kErrFsrKeyAlgoMissing = $83; // Key computation algorithm is missing + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TXcpLoader = class(TObject) + private + FIsConnected : Boolean; + FTimerInterval : array[1..7] of Word; + FIsIntel : Boolean; + FCtoPacketLen : Byte; + FCtoPGMPacketLen : Byte; + FDtoPacketLen : Word; + FSeedKeyDll : string; + FLastError : Byte; + FResources : Byte; + FProtection : Byte; + FMta : LongWord; + procedure WaitT7; + function GetOrderedWord(data : PByteArray) : Word; + procedure SetOrderedLong(value: LongWord; data : PByteArray); + function SendSynchedPacket(timeMs : Word; useMta : Boolean) : Boolean; + function CmdSynch(useMta : Boolean) : Boolean; + function CmdConnect : Boolean; + function CmdDisconnect : Boolean; + function CmdProgramStart : Boolean; + function CmdGetStatus : Boolean; + function CmdGetSeed(seed : PByteArray; resource : Byte; var len : Byte) : Boolean; + function CmdUnlock(key : PByteArray; len : Byte) : Boolean; + function CmdProgramReset : Boolean; + function CmdProgram(data : PByteArray; len : Byte) : Boolean; + function CmdProgramMax(data : PByteArray) : Boolean; + function CmdSetMta(addr : LongWord) : Boolean; + function CmdProgramClear(len : LongWord) : Boolean; + public + comDriver : TXcpTransport; + constructor Create; + destructor Destroy; override; + function GetLastError(var info : string) : Byte; + procedure Configure(iniFile : string); + procedure Connect; + procedure Disconnect; + function StartProgrammingSession : Boolean; + function StopProgrammingSession : Boolean; + function ClearMemory(addr : LongWord; len : LongWord) : Boolean; + function WriteData(addr : LongWord; len : LongWord; data : PByteArray) : Boolean; + end; + + +implementation +//*************************************************************************************** +// NAME: Create +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class constructor +// +//*************************************************************************************** +constructor TXcpLoader.Create; +begin + // call inherited constructor + inherited Create; + + // reset error + FLastError := 0; + + // reset memory transfer address + FMta := 0; + + // not connected upon creation + FIsConnected := false; + + // reset seed/key dll filename + FSeedKeyDll := ''; + + // set communication defaults + FIsIntel := False; // motorola byte order by default + FResources := 0; // no resources available + FProtection := 0; // all resources unprotected by default + + // set XCP packet length defaults + FCtoPacketLen := 8; // must be at least 8 for connect command response + FDtoPacketLen := 8; + FCtoPGMPacketLen := 8; + + // set interval time defaults + FTimerInterval[1] := 1000; // t1 = 1000ms - standard command timeout + FTimerInterval[2] := 2000; // t2 = 2000ms - build checksum timeout + FTimerInterval[3] := 2000; // t3 = 2000ms - program start timeout + FTimerInterval[4] := 10000; // t4 = 10000ms - erase timeout + FTimerInterval[5] := 1000; // t5 = 1000ms - write and reset timeout + FTimerInterval[6] := 1000; // t6 = 1000ms - user specific connect + FTimerInterval[7] := 2000; // t7 = 2000ms - wait timer + + // create instance of XCP transport layer object + comDriver := TXcpTransport.Create; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class destructor +// +//*************************************************************************************** +destructor TXcpLoader.Destroy; +begin + // disconnect the XCP transport layer + comDriver.Disconnect; + + // release XCP transport layer object + comDriver.Free; + + // call inherited destructor + inherited; +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: WaitRoutine +// PARAMETER: number of milliseconds to wait +// RETURN VALUE: none +// DESCRIPTION: Basic routine that waits for the specified amount of time before +// continueing. +// +//*************************************************************************************** +procedure TXcpLoader.WaitT7; +begin + Sleep(FTimerInterval[7]); +end; //*** end of WaitRoutine *** + + +//*************************************************************************************** +// NAME: GetOrderedWord +// PARAMETER: pointer to byte array +// RETURN VALUE: word value +// DESCRIPTION: Returns the word value from the byte array taking into account Intel +// or Motorola byte ordering. +// +//*************************************************************************************** +function TXcpLoader.GetOrderedWord(data : PByteArray) : Word; +begin + result := 0; + + if FIsIntel then + begin + result := result or (data[1] shl 8); + result := result or (data[0]); + end + else + begin + result := result or (data[0] shl 8); + result := result or (data[1]); + end; +end; //*** end of GetOrderedWord *** + + +//*************************************************************************************** +// NAME: SetOrderedLong +// PARAMETER: pointer to byte array and 32-bit value +// RETURN VALUE: none +// DESCRIPTION: Stores a 32-bit value into a byte buffer taking into account Intel +// or Motorola byte ordering. +// +//*************************************************************************************** +procedure TXcpLoader.SetOrderedLong(value: LongWord; data : PByteArray); +begin + if FIsIntel then + begin + data[3] := Byte(value shr 24); + data[2] := Byte(value shr 16); + data[1] := Byte(value shr 8); + data[0] := Byte(value); + end + else + begin + data[0] := Byte(value shr 24); + data[1] := Byte(value shr 16); + data[2] := Byte(value shr 8); + data[3] := Byte(value); + end; +end; //*** end of SetOrderedLong *** + + +//*************************************************************************************** +// NAME: GetLastError +// PARAMETER: destination string from error information +// RETURN VALUE: error code +// DESCRIPTION: Return the last error value. +// +//*************************************************************************************** +function TXcpLoader.GetLastError(var info : string) : Byte; +begin + // set info string + case FLastError of + kErrCMD_SYNCH : info := '0x00 - Command processor synchronization'; + kErrCMD_BUSY : info := '0x10 - Command was not executed'; + kErrDAQ_ACTIVE : info := '0x11 - Command rejected because DAQ is running'; + kErrPGM_ACTIVE : info := '0x12 - Command rejected because PGM is running'; + kErrCMD_UNKNOWN : info := '0x20 - Unknown command or not implemented optional command'; + kErrCMD_SYNTAX : info := '0x21 - Command syntax invalid'; + kErrOUT_OF_RANGE : info := '0x22 - Command syntax valid but command parameter(s) out of range'; + kErrWRITE_PROTECTED : info := '0x23 - The memory location is write protected'; + kErrACCESS_DENIED : info := '0x24 - The memory location is not accessible'; + kErrACCESS_LOCKED : info := '0x25 - Access denied, Seed & Key is required'; + kErrPAGE_NOT_VALID : info := '0x26 - Selected page not available'; + kErrMODE_NOT_VALID : info := '0x27 - Selected page mode not available'; + kErrSEGMENT_NOT_VALID : info := '0x28 - Selected segment not valid'; + kErrSEQUENCE : info := '0x29 - Sequence error'; + kErrDAQ_CONFIG : info := '0x2A - DAQ configuration not valid'; + kErrMEMORY_OVERFLOW : info := '0x30 - Memory overflow error'; + kErrGENERIC : info := '0x31 - Generic error'; + kErrVERIFY : info := '0x32 - The slave internal program verify routine detects an error'; + kErrFsrExecuteCmd : info := '0x80 - Could not execute command'; + kErrFsrResourceUnavailable: info := '0x81 - Resource needed but not available'; + kErrFsrSeedKeyDllInvalid : info := '0x82 - Seed/Key DLL is invalid'; + kErrFsrKeyAlgoMissing : info := '0x83 - Key computation algorithm is missing'; + end; + + // return the error code + result := FLastError; +end; //*** end of GetLastError *** + + +//*************************************************************************************** +// NAME: Configure +// PARAMETER: filename of the INI +// RETURN VALUE: none +// DESCRIPTION: Configures both this class and the transport layer from the settings +// in the INI. +// +//*************************************************************************************** +procedure TXcpLoader.Configure(iniFile : string); +var + settingsIni : TIniFile; + wasConnected : Boolean; +begin + // backup connection state + wasConnected := FIsConnected; + + // disconnect + if FIsConnected then DisConnect; + + // configure comDriver + comDriver.Configure(iniFile); + + // read XCP configuration from INI + if FileExists(iniFile) then + begin + // create ini file object + settingsIni := TIniFile.Create(iniFile); + + FSeedKeyDll := settingsIni.ReadString('xcp', 'seedkey', ExtractFilePath(ParamStr(0))+'FeaserKey.dll'); + + // if no path specified, then assume dll is located in the executable's path + if ExtractFilePath(FSeedKeyDll) = '' then + FSeedKeyDll := ExtractFilePath(ParamStr(0))+FSeedKeyDll; + + FTimerInterval[1] := settingsIni.ReadInteger('xcp', 't1', 1000); + FTimerInterval[3] := settingsIni.ReadInteger('xcp', 't3', 1000); + FTimerInterval[4] := settingsIni.ReadInteger('xcp', 't4', 1000); + FTimerInterval[5] := settingsIni.ReadInteger('xcp', 't5', 1000); + FTimerInterval[7] := settingsIni.ReadInteger('xcp', 't7', 1000); + + // release ini file object + settingsIni.Free; + end; + + // restore connection + if WasConnected then Connect; +end; //*** end of Configure *** + + +//*************************************************************************************** +// NAME: Connect +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Connects the XCP transport layer +// +//*************************************************************************************** +procedure TXcpLoader.Connect; +begin + // connect the XCP transport layer + comDriver.Connect; + FIsConnected := true; +end; //*** end of Connect *** + + +//*************************************************************************************** +// NAME: Disconnect +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Disconnects the XCP transport layer +// +//*************************************************************************************** +procedure TXcpLoader.Disconnect; +begin + // disconnect the XCP transport layer + FIsConnected := false; + comDriver.Disconnect; +end; //*** end of Disconnect *** + + +//*************************************************************************************** +// NAME: SendSynchedPacket +// PARAMETER: timeout time in ms and info if mta should be resend +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Sends out the XCP packet using the "2 Retry with SYNCH" method at +// outlined in the XCP protocol error handling. in case an error +// occurred, a FLastError will be set. If useMta = true then a SET_MTA +// packet will be send right after the SYNCH packet. +// +//*************************************************************************************** +function TXcpLoader.SendSynchedPacket(timeMs : Word; useMta : Boolean) : Boolean; +var + dataCpy : array of Byte; + cnt : Word; +begin + // init return value + Result := false; + + // make a copy of the packet data because the synch command could overwrite it + SetLength(dataCpy, comDriver.packetLen); + for cnt := 0 to comDriver.packetLen-1 do + dataCpy[cnt] := comDriver.packetData[cnt]; + + // send out the command with t1 timeout + if not comDriver.SendPacket(timeMs) then + begin + CmdSynch(useMta); // perform pre-action for 1st retry + + // prepare to send the command packet again + comDriver.packetLen := Length(dataCpy); + for cnt := 0 to comDriver.packetLen-1 do + comDriver.packetData[cnt] := dataCpy[cnt]; + + if not comDriver.SendPacket(timeMs) then + begin + CmdSynch(useMta); // perform pre-action for 2nd and last retry + + // prepare to send the command packet again + comDriver.packetLen := Length(dataCpy); + for cnt := 0 to comDriver.packetLen-1 do + comDriver.packetData[cnt] := dataCpy[cnt]; + + if comDriver.SendPacket(timeMs) then + result := true; // success + end + else + result := true; // success + end + else + result := true; // sucess + + if result = false then + FLastError := kErrFsrExecuteCmd; // Could not execute command +end; //*** end of SendSynchedPacket *** + + +//*************************************************************************************** +// NAME: CmdSynch +// PARAMETER: useMta is a SET_MTA should be included +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Sends out the synchronise command +// +//*************************************************************************************** +function TXcpLoader.CmdSynch(useMta : Boolean) : Boolean; +begin + // init return value + Result := false; + + // prepare the command packet + comDriver.packetData[0] := kCmdSYNCH; + comDriver.packetLen := 1; + + // send out the command with t1 timeout + if not comDriver.SendPacket(FTimerInterval[1]) then + begin + Exit; + end; + + // is response an error packet as expected? + if comDriver.packetData[0] = kCmdPidERR then + begin + // is it the expected processor synchronization error? + if comDriver.packetData[1] = kErrCMD_SYNCH then + begin + result := true; + end; + end; + + // should MTA be resend aswell? + if (useMta = true) and (result = true) then + begin + // prepare the command packet + comDriver.packetData[0] := kCmdSET_MTA; + comDriver.packetData[1] := 0; // reserved + comDriver.packetData[2] := 0; // reserved + comDriver.packetData[3] := 0; // address extension not supported + + // set address taking into account byte ordering + SetOrderedLong(FMta, @comDriver.packetData[4]); + + comDriver.packetLen := 8; + + // send packet with SYNCH retry feature + if not SendSynchedPacket(FTimerInterval[1], false) then + begin + result := false; + Exit; + end; + end; +end; //*** end of CmdSynch *** + + +//*************************************************************************************** +// NAME: CmdConnect +// PARAMETER: none +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Connects the XCP slave to start the XCP session +// +//*************************************************************************************** +function TXcpLoader.CmdConnect : Boolean; +begin + // init return value + Result := false; + + // prepare the connect command packet + comDriver.packetData[0] := kCmdCONNECT; + comDriver.packetData[1] := 0; // normal mode + comDriver.packetLen := 2; + + // send out the command with 20ms timeout. note that this timeout is not required at + // all by the XCP protocol. here it is set quite short to accomodate the OpenBTL + // bootloader default backdoor entry feature + if comDriver.SendPacket(20) then + begin + // check to see if it was an error packet + if comDriver.packetData[0] = kCmdPidERR then + begin + // store error and stop + FLastError := comDriver.packetData[1]; + Exit; + end; + + // store byte order configuration + if (comDriver.packetData[2] and $01) = $00 then FIsIntel := true; + + // store available resources + FResources := comDriver.packetData[1]; + + // store cto packet length + FCtoPacketLen := comDriver.packetData[3]; + FCtoPGMPacketLen := FCtoPacketLen; + + // store dto packet length + FDtoPacketLen := GetOrderedWord(@comDriver.packetData[4]); + + // success + result := true; + end + else + begin + FLastError := kErrFsrExecuteCmd; // Could not execute command; + end; +end; //*** end of CmdConnect *** + + +//*************************************************************************************** +// NAME: CmdDisconnect +// PARAMETER: none +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Disconnects the XCP slave to end the XCP session +// +//*************************************************************************************** +function TXcpLoader.CmdDisconnect : Boolean; +begin + // init return value + Result := false; + + // prepare the disconnect command packet + comDriver.packetData[0] := kCmdDISCONNECT; + comDriver.packetLen := 1; + + // send packet with SYNCH retry feature + if not SendSynchedPacket(FTimerInterval[1], false) then Exit; + + // was the response an error packet? + if comDriver.packetData[0] = kCmdPidERR then + begin + // busy or programming active error received? + if (comDriver.packetData[1] = kErrCMD_BUSY) or + (comDriver.packetData[1] = kErrPGM_ACTIVE) then + begin + WaitT7; // wait the predescribed time + result := CmdDisconnect; // repeat this command + Exit; + end + else + begin + FLastError := comDriver.packetData[1]; // Store error info + Exit; + end; + end; + + // no error so it must have been a positive response + result := true; +end; //*** end of CmdDisconnect *** + + +//*************************************************************************************** +// NAME: CmdProgramStart +// PARAMETER: none +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Informs the slave that programming of non volatile memory starts. +// +//*************************************************************************************** +function TXcpLoader.CmdProgramStart : Boolean; +begin + // init return value + Result := false; + + // prepare the command packet + comDriver.packetData[0] := kCmdPROGRAM_START; + comDriver.packetLen := 1; + + // send packet with SYNCH retry feature + if not SendSynchedPacket(FTimerInterval[3], false) then Exit; + + // was the response an error packet? + if comDriver.packetData[0] = kCmdPidERR then + begin + // busy or programming active error received? + if comDriver.packetData[1] = kErrCMD_BUSY then + begin + WaitT7; // wait the predescribed time + result := CmdProgramStart; // repeat this command + Exit; + end + else + begin + FLastError := comDriver.packetData[1]; // Store error info + Exit; + end; + end; + + // no error so it must have been a positive response + result := true; + + // update max cto packet length in programming mode if supported + if comDriver.packetData[3] <> 0 then + FCtoPGMPacketLen := comDriver.packetData[3]; +end; //*** end of CmdProgramStart *** + + +//*************************************************************************************** +// NAME: CmdGetStatus +// PARAMETER: none +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Obtains the resource protection info from the XCP slave +// +//*************************************************************************************** +function TXcpLoader.CmdGetStatus : Boolean; +begin + // init return value + result := false; + + // prepare the get status command packet + comDriver.packetData[0] := kCmdGET_STATUS; + comDriver.packetLen := 1; + + // send packet with SYNCH retry feature + if not SendSynchedPacket(FTimerInterval[1], false) then Exit; + + // was the response an error packet? + if comDriver.packetData[0] = kCmdPidERR then + begin + FLastError := comDriver.packetData[1]; // Store error info + Exit; + end; + + // no error so it must have been a positive response + result := true; + + // store protection info + FProtection := comDriver.packetData[2]; +end; //*** end of CmdGetStatus *** + + +//*************************************************************************************** +// NAME: CmdGetSeed +// PARAMETER: seed destination buffer and the resource +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Obtains the seed from the specified resource +// +//*************************************************************************************** +function TXcpLoader.CmdGetSeed(seed : PByteArray; resource : Byte; var len : Byte) : Boolean; +var + cnt : byte; +begin + // init return value + result := false; + + // prepare the get seed command packet + comDriver.packetData[0] := kCmdGET_SEED; + comDriver.packetData[1] := 0; // seeds of up to six bytes are supported + comDriver.packetData[2] := resource; + comDriver.packetLen := 3; + + // send packet with SYNCH retry feature + if not SendSynchedPacket(FTimerInterval[1], false) then Exit; + + // was the response an error packet? + if comDriver.packetData[0] = kCmdPidERR then + begin + // busy or programming active error received? + if (comDriver.packetData[1] = kErrCMD_BUSY) or + (comDriver.packetData[1] = kErrPGM_ACTIVE) then + begin + WaitT7; // wait the predescribed time + result := CmdGetSeed(seed, resource, len); // repeat this command + Exit; + end + else + begin + FLastError := comDriver.packetData[1]; // Store error info + Exit; + end; + end; + + // no error so it must have been a positive response + result := true; + + // now store the seed info + len := comDriver.packetData[1]; + for cnt := 0 to len-1 do + seed[cnt] := comDriver.packetData[cnt+2]; +end; //*** end of CmdGetSeed *** + + +//*************************************************************************************** +// NAME: CmdUnlock +// PARAMETER: key source buffer and key length +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Unlocks the resource by sending the key +// +//*************************************************************************************** +function TXcpLoader.CmdUnlock(key : PByteArray; len : Byte) : Boolean; +var + cnt : byte; +begin + // init return value + result := false; + + // prepare the command packet + comDriver.packetData[0] := kCmdUNLOCK; + comDriver.packetData[1] := len; // key length + for cnt := 0 to len-1 do + comDriver.packetData[cnt+2] := key[cnt]; + comDriver.packetLen := len + 2; + + // send packet with SYNCH retry feature + if not SendSynchedPacket(FTimerInterval[1], false) then Exit; + + // was the response an error packet? + if comDriver.packetData[0] = kCmdPidERR then + begin + // busy or programming active error received? + if (comDriver.packetData[1] = kErrCMD_BUSY) or + (comDriver.packetData[1] = kErrPGM_ACTIVE) then + begin + WaitT7; // wait the predescribed time + result := CmdUnlock(key, len); // repeat this command + Exit; + end + else + begin + FLastError := comDriver.packetData[1]; // Store error info + Exit; + end; + end; + + // no error so it must have been a positive response + result := true; + + // store the new resource protection mask + FProtection := comDriver.packetData[1]; +end; //*** end of CmdUnlock *** + + +//*************************************************************************************** +// NAME: CmdProgramReset +// PARAMETER: none +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Requests the ECU to perform a reset. +// +//*************************************************************************************** +function TXcpLoader.CmdProgramReset : Boolean; +begin + // init return value + result := false; + + // prepare the command packet + comDriver.packetData[0] := kCmdPROGRAM_RESET; + comDriver.packetLen := 1; + + // send packet without SYNCH retry feature. ignore negative return value because this + // command does not require a response + if not comDriver.SendPacket(FTimerInterval[5]) then + begin + result := true; // ok to not have a response + Exit; // no response to process to stop here + end; + + // was the response an error packet? + if comDriver.packetData[0] = kCmdPidERR then + begin + // busy or programming active error received? + if (comDriver.packetData[1] = kErrCMD_BUSY) or + (comDriver.packetData[1] = kErrPGM_ACTIVE) then + begin + WaitT7; // wait the predescribed time + result := CmdProgramReset; // repeat this command + Exit; + end + else + begin + FLastError := comDriver.packetData[1]; // Store error info + Exit; + end; + end; + + // no error so it must have been a positive response + result := true; +end; //*** end of CmdProgramReset *** + + +//*************************************************************************************** +// NAME: CmdProgram +// PARAMETER: data source buffer and data length +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Programs the data into non-volatile memory +// +//*************************************************************************************** +function TXcpLoader.CmdProgram(data : PByteArray; len : Byte) : Boolean; +var + cnt : byte; +begin + // init return value + result := false; + + // prepare the command packet + comDriver.packetData[0] := kCmdPROGRAM; + comDriver.packetData[1] := len; // key length + + if len > 0 then + begin + for cnt := 0 to len-1 do + comDriver.packetData[cnt+2] := data[cnt]; + end; + comDriver.packetLen := len + 2; + + // send packet with SYNCH retry feature + if not SendSynchedPacket(FTimerInterval[5], true) then Exit; + + // was the response an error packet? + if comDriver.packetData[0] = kCmdPidERR then + begin + // busy or programming active error received? + if (comDriver.packetData[1] = kErrCMD_BUSY) then + begin + WaitT7; // wait the predescribed time + result := CmdProgram(data, len); // repeat this command + Exit; + end + else + begin + FLastError := comDriver.packetData[1]; // Store error info + Exit; + end; + end; + + // no error so it must have been a positive response + result := true; +end; //*** end of CmdProgram *** + + +//*************************************************************************************** +// NAME: CmdProgramMax +// PARAMETER: data source buffer +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Programs the data into non-volatile memory +// +//*************************************************************************************** +function TXcpLoader.CmdProgramMax(data : PByteArray) : Boolean; +var + cnt : byte; +begin + // init return value + result := false; + + // prepare the command packet + comDriver.packetData[0] := kCmdPROGRAM_MAX; + for cnt := 0 to FCtoPGMPacketLen-2 do + comDriver.packetData[cnt+1] := data[cnt]; + comDriver.packetLen := FCtoPGMPacketLen; + + // send packet with SYNCH retry feature + if not SendSynchedPacket(FTimerInterval[5], true) then Exit; + + // was the response an error packet? + if comDriver.packetData[0] = kCmdPidERR then + begin + // busy or programming active error received? + if (comDriver.packetData[1] = kErrCMD_BUSY) then + begin + WaitT7; // wait the predescribed time + result := CmdProgramMax(data); // repeat this command + Exit; + end + else + begin + FLastError := comDriver.packetData[1]; // Store error info + Exit; + end; + end; + + // no error so it must have been a positive response + result := true; +end; //*** end of CmdProgramMax *** + + +//*************************************************************************************** +// NAME: CmdSetMta +// PARAMETER: 32-bit address +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Sets the memory transfer address +// +//*************************************************************************************** +function TXcpLoader.CmdSetMta(addr : LongWord) : Boolean; +begin + // init return value + result := false; + + // prepare the command packet + comDriver.packetData[0] := kCmdSET_MTA; + comDriver.packetData[1] := 0; // reserved + comDriver.packetData[2] := 0; // reserved + comDriver.packetData[3] := 0; // address extension not supported + + // set address taking into account byte ordering + SetOrderedLong(addr, @comDriver.packetData[4]); + + comDriver.packetLen := 8; + + // send packet with SYNCH retry feature + if not SendSynchedPacket(FTimerInterval[1], false) then Exit; + + // was the response an error packet? + if comDriver.packetData[0] = kCmdPidERR then + begin + // busy or programming active error received? + if (comDriver.packetData[1] = kErrCMD_BUSY) or + (comDriver.packetData[1] = kErrPGM_ACTIVE) then + begin + WaitT7; // wait the predescribed time + result := CmdSetMta(addr); // repeat this command + Exit; + end + else + begin + FLastError := comDriver.packetData[1]; // Store error info + Exit; + end; + end; + + // no error so it must have been a positive response + result := true; + + // store current memory transfer address + FMta := addr; +end; //*** end of CmdSetMta *** + + +//*************************************************************************************** +// NAME: CmdProgramClear +// PARAMETER: number of bytes in memory to clear +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Clears the number of bytes in non-volatile memory starting at the +// mta address. +// +//*************************************************************************************** +function TXcpLoader.CmdProgramClear(len : LongWord) : Boolean; +begin + // init return value + result := false; + + // prepare the command packet + comDriver.packetData[0] := kCmdPROGRAM_CLEAR; + comDriver.packetData[1] := 0; // use absolute mode + comDriver.packetData[2] := 0; // reserved + comDriver.packetData[3] := 0; // reserved + + // set address taking into account byte ordering + SetOrderedLong(len, @comDriver.packetData[4]); + + comDriver.packetLen := 8; + + // send packet with SYNCH retry feature + if not SendSynchedPacket(FTimerInterval[4], true) then Exit; + + // was the response an error packet? + if comDriver.packetData[0] = kCmdPidERR then + begin + // busy or programming active error received? + if comDriver.packetData[1] = kErrCMD_BUSY then + begin + WaitT7; // wait the predescribed time + result := CmdProgramClear(len); // repeat this command + Exit; + end + else + begin + FLastError := comDriver.packetData[1]; // Store error info + Exit; + end; + end; + + // no error so it must have been a positive response + result := true; +end; //*** end of CmdProgramClear *** + + +//*************************************************************************************** +// NAME: StartProgrammingSession +// PARAMETER: none +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Starts the programming session using the following XCP command +// sequence: +// * CONNECT +// * GET_STATUS +// * GETSEED (if applicable) +// * UNLOCK (if applicable) +// * PROGRAM_START +// +//*************************************************************************************** +function TXcpLoader.StartProgrammingSession : Boolean; +var + xcpProtection : TXcpProtection; + supportedRes : Byte; + seedData : array[0..5] of Byte; + seedLen : byte; + keyData : array[0..5] of Byte; + keyLen : byte; +begin + // init return value + result := false; + + // send the CONNECT command + if not CmdConnect then Exit; + + // make sure the programming resource is supported + if (FResources and kResPGM) <> kResPGM then + begin + FLastError := kErrFsrResourceUnavailable; + Exit; + end; + + // send the GET_STATUS command + if not CmdGetStatus then Exit; + + // check if we need to unlock the programming resource + if (FProtection and kResPGM) = kResPGM then + begin + // ceate xcp protection object + xcpProtection := TXcpProtection.Create(FSeedKeyDll); + + // make sure it contains the unlock algorithm for the PGM resource + if xcpProtection.GetPrivileges(@supportedRes) <> 0 then + begin + FLastError := kErrFsrSeedKeyDllInvalid; // error calling DLL function + xcpProtection.Free; // release the object + Exit; + end; + if (supportedRes and kResPGM) <> kResPGM then + begin + FLastError := kErrFsrKeyAlgoMissing; // key algorithm not present + xcpProtection.Free; // release the object + Exit; + end; + + // obtain the seed for the programming resource + if not CmdGetSeed(@seedData, kResPGM, seedLen) then + begin + xcpProtection.Free; // release the object + Exit; + end; + + // compute the key + keyLen := Length(keyData); + if xcpProtection.ComputKeyFromSeed(kResPGM, seedLen, @seedData, @keyLen, @keyData) <> 0 then + begin + FLastError := kErrFsrSeedKeyDllInvalid; // error calling DLL function + xcpProtection.Free; // release the object + Exit; + end; + + // release the object..no longer needed + xcpProtection.Free; + + // we have the key so now unlock the resource + if not CmdUnlock(@keyData, keyLen) then Exit; + + // make sure the PGM resource is really unprotected now + if (FProtection and kResPGM) = kResPGM then + begin + FLastError := kErrACCESS_LOCKED; + Exit; + end; + end; + + // send the PROGRAM_START command + if not CmdProgramStart then Exit; + + // successfully started the programming session + result := true; +end; //*** end of StartProgrammingSession *** + + +//*************************************************************************************** +// NAME: StopProgrammingSession +// PARAMETER: none +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Stops the programming session using the following XCP command +// sequence: +// * PROGRAM (size=0) +// * PROGRAM_RESET +// +//*************************************************************************************** +function TXcpLoader.StopProgrammingSession : Boolean; +begin + // init return value + result := false; + + // send the program command with size 0 to indicate end of programming session + if not CmdProgram(nil, 0) then Exit; + + // finish off by resetting the ECU + if not CmdProgramReset then Exit; + + // successfully stopped the programming session + result := true; +end; //*** end of StopProgrammingSession *** + + +//*************************************************************************************** +// NAME: ClearMemory +// PARAMETER: start address and the number of bytes to clear +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Clears the specified memory range using the following XCP command +// sequence: +// * SET_MTA +// * PROGRAM_CLEAR +// +//*************************************************************************************** +function TXcpLoader.ClearMemory(addr : LongWord; len : LongWord) : Boolean; +begin + // init return value + result := false; + + // set the start address for the erase operation + if not CmdSetMta(addr) then Exit; + + // finish off by resetting the ECU + if not CmdProgramClear(len) then Exit; + + // successfully cleared the memory + result := true; +end; //*** end of ClearMemory *** + + +//*************************************************************************************** +// NAME: WriteData +// PARAMETER: start address, the number of bytes to program, and the data buffer +// RETURN VALUE: True is successful, False otherwise +// DESCRIPTION: Programs specified memory range using the following XCP command +// sequence: +// * SET_MTA +// * PROGRAM(_MAX) +// +//*************************************************************************************** +function TXcpLoader.WriteData(addr : LongWord; len : LongWord; data : PByteArray) : Boolean; +var + currentWriteCnt : Byte; + bufferOffset : LongWord; +begin + // init return value + result := false; + + // set the start address for the program operation + if not CmdSetMta(addr) then Exit; + + // init buffer indexer + bufferOffset := 0; + + while len > 0 do + begin + // set the current write length to make optimal use of the available packet data + currentWriteCnt := len mod (FCtoPGMPacketLen-1); + if currentWriteCnt = 0 then currentWriteCnt := FCtoPGMPacketLen-1; + + // prepare the packet data for PROGRAM + if currentWriteCnt < FCtoPGMPacketLen-1 then + begin + if not CmdProgram(@data[bufferOffset], currentWriteCnt) then Exit; + end + // prepare the packet data for PROGRAM_MAX + else + begin + if not CmdProgramMax(@data[bufferOffset]) then Exit; + end; + + // update loop variables + len := len - currentWriteCnt; + bufferOffset := bufferOffset + currentWriteCnt; + end; + + // successfully programmed the memory + result := true; +end; //*** end of WriteData *** + + +end. +//******************************** end of XcpLoader.pas ********************************* + diff --git a/Host/Source/interfaces/XcpProtection.pas b/Host/Source/interfaces/XcpProtection.pas new file mode 100644 index 00000000..e0b23cbf --- /dev/null +++ b/Host/Source/interfaces/XcpProtection.pas @@ -0,0 +1,172 @@ +unit XcpProtection; +//*************************************************************************************** +// Description: XCP seed and key resource protection interface. +// File Name: XcpProtection.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Forms; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +// DLL Interface Methods +type + TXcpGetAvailablePrivileges = function(resourcePtr: PByte) : DWORD; cdecl; + TXcpComputKeyFromSeed = function(resource: Byte; seedLen: Byte; seedPtr: PByteArray; + keyLenPtr: PByte; keyPtr: PByteArray) : DWORD; cdecl; + +type + TXcpProtection = class(TObject) + private + FLibHandle : THandle; + FLibInitialized : Boolean; + FGetAvailablePrivileges: TXcpGetAvailablePrivileges; + FComputKeyFromSeed : TXcpComputKeyFromSeed; + public + constructor Create(libFile: string); + destructor Destroy; override; + function GetPrivileges(resourcePtr: PByte) : DWORD; + function ComputKeyFromSeed(resource: Byte; seedLen: Byte; seedPtr: PByteArray; + keyLenPtr: PByte; keyPtr: PByteArray) : DWORD; + end; + + +implementation + +//*************************************************************************************** +// NAME: Create +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class constructor +// +//*************************************************************************************** +constructor TXcpProtection.Create(libFile: string); +begin + // call inherited constructor + inherited Create; + + // library not yet initialized + FLibInitialized := false; + + // attempt to obtain the library handle + if (FileExists(libFile)) and (LowerCase(ExtractFileExt(libFile)) = '.dll') then + begin + FLibHandle := LoadLibrary(PChar(libFile)); + + if FLibHandle <> 0 then FLibInitialized := true; + end; + + // only continue if everything was okay sofar + if FLibInitialized = false then Exit; + + // attempt to obtain the function pointers from the interface library + @FComputKeyFromSeed := GetProcAddress(FLibHandle, 'XCP_ComputeKeyFromSeed'); + @FGetAvailablePrivileges := GetProcAddress(FLibHandle, 'XCP_GetAvailablePrivileges'); + + // check if the functions were found in the interface library + if not Assigned(FComputKeyFromSeed) then FLibInitialized := false; + if not Assigned(FGetAvailablePrivileges) then FLibInitialized := false; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class destructor +// +//*************************************************************************************** +destructor TXcpProtection.Destroy; +begin + // release the library and its handle + if FLibHandle <> 0 then + begin + FreeLibrary(FLibHandle); + end; + + // call inherited destructor + inherited; +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: GetPrivileges +// PARAMETER: resourcePtr : pointer where to store the supported resources +// for the key computation +// RETURN VALUE: 0 if success +// DESCRIPTION: obtains the privileges with available unlock algorithms in the +// external library file +// +//*************************************************************************************** +function TXcpProtection.GetPrivileges(resourcePtr: PByte) : DWORD; +begin + if FLibInitialized then + result := FGetAvailablePrivileges(resourcePtr) + else + result := 0; +end; //*** end of GetPrivileges *** + + +//*************************************************************************************** +// NAME: ComputKeyFromSeed +// PARAMETER: resource : resource for which the unlock key is requested +// seedLen : length of the seed +// seedPtr : pointer to the seed data +// keyLenPtr: pointer where to store the key length +// keyPtr : pointer where to store the key data +// RETURN VALUE: 0 if success +// DESCRIPTION: Computes the key for the requested resource. +// +//*************************************************************************************** +function TXcpProtection.ComputKeyFromSeed(resource: Byte; seedLen: Byte; + seedPtr: PByteArray; keyLenPtr: PByte; + keyPtr: PByteArray) : DWORD; +begin + if FLibInitialized then + result := FComputKeyFromSeed(resource, seedLen, seedPtr, keyLenPtr, keyPtr) + else + result := 0; +end; //*** end of ComputKeyFromSeed *** + + +end. +//******************************** end of XcpProtection.pas ***************************** + diff --git a/Host/Source/interfaces/can/peak/CANIcon.bmp b/Host/Source/interfaces/can/peak/CANIcon.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6ca58cdf8ac60d52fbb6ced81fecd8ecad40ba31 GIT binary patch literal 2446 zcmchYJx;?w5QUc#DK$`}az$!O9Dtsl6Zi^gsZvr#@@ael-vJ~JV!r*!_+@MdBN0~4 zYG(6x-pt$a`uXMkHl*>y{K&83chB!8JTQmwTK-Q?nZ7`p`~99-N87f) z#V9`8!^lJIyYsQ#ZkwiI-S(})7+4MAsj4b8A-sh+pA3kVXAMTfn=L$KU&2FmdN!Ml z@+3?h+S&jZ4r8&^5T2APF-DRcgA=nIyWKAIeHi*emB8>Q#=vTHAyTNjrwCN%&CZWfKb zi3cxhOzp_btdPvG2BWz+yNi7Q$*P;+r`y8CRyWl{jZxH#H`^MF26lGhiLGLH+NGQN z?24tk5ZO+^1$ORO&$YfhnK1E?6Ah??3jgX$nt8hNU4Uxo3N!`QU<~YxRF7M`hC2-3 DijuO8 literal 0 HcmV?d00001 diff --git a/Host/Source/interfaces/can/peak/PCANdrvD.pas b/Host/Source/interfaces/can/peak/PCANdrvD.pas new file mode 100644 index 00000000..f3928d13 --- /dev/null +++ b/Host/Source/interfaces/can/peak/PCANdrvD.pas @@ -0,0 +1,547 @@ +unit PCANdrvD; +//*************************************************************************************** +// Project Name: TPCanDriver component for Borland Delphi +// Description: Encapsulates PCAN's Light driver into a VCL component for PCANUSB 1CH. +// File Name: PCANdrvD.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Pcan_usb; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TPCanChannel = ( pcanchannel0 ); + TPCanHardware = ( PCAN_USB1CH ); + TPCanDirection = ( PcanTx, PCanRx ); + TPCanMessage = packed record + id : LongInt; + dlc : Byte; + data : array [0..7] of Byte; + time : LongInt; + ext : Boolean; + end; + +type + TPCanMessageEvent = procedure( Sender: TObject; Direction: TPCanDirection; Message: TPCanMessage ) of object; + +type + TPCanEventThread = class(TThread) + private + { Private declarations } + FMethod: TThreadMethod; + protected + procedure Execute; override; + public + property Method : TThreadMethod read FMethod write FMethod; + end; + +type + TPCanDriver = class(TComponent) + private + { Private declarations } + FCanEventThread: TPCanEventThread; + FThreadRunning : boolean; + FCanConnected : boolean; + FStartTickCnt : DWORD; + function IsThreadRunning: boolean; + procedure ProcessReception; + protected + { Protected declarations } + FBaudRate : LongInt; + FChannel : TPCanChannel; + FHardware : TPCanHardware; + FPriority : TThreadPriority; + FExtendedId : Boolean; + FOnMessage : TPCanMessageEvent; + procedure SetBaudRate( Value: LongInt ); + procedure SetChannel( Value: TPCanChannel ); + procedure SetHardware( Value: TPCanHardware ); + procedure SetPriority( Value: TThreadPriority ); + procedure SetExtendedId( Value: Boolean ); + public + { Public declarations } + constructor Create( AOwner: TComponent ); override; + destructor Destroy; override; + function Connect: boolean; virtual; + procedure Disconnect; virtual; + function Transmit( Message: TPCanMessage): boolean; virtual; + function IsConnected: boolean; virtual; + published + { Published declarations } + property BaudRate : LongInt read FBaudRate write SetBaudRate default 500000; + property Channel : TPCanChannel read FChannel write SetChannel default pcanchannel0; + property Hardware : TPCanHardware read FHardware write SetHardware default PCAN_USB1CH; + property Priority : TThreadPriority read FPriority write SetPriority default tpNormal; + property ExtendedId : Boolean read FExtendedId write SetExtendedId default False; + property OnMessage : TPCanMessageEvent read FOnMessage write FOnMessage; + end; + + +//*************************************************************************************** +// Prototypes +//*************************************************************************************** +procedure Register; + +implementation +//*************************************************************************************** +// NAME: Execute +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Overriden Execute function for the CanEventThread. Calls and synchro- +// nizes with the TCanDriver.ProcessEvents function. +// +//*************************************************************************************** +procedure TPCanEventThread.Execute; +begin + while not Terminated do + begin + if Assigned(Method) then // make sure TPCanDriver.ProcessEvents is set + Synchronize(Method); // call and synchronize + end; +end; //*** end of Execute *** + + +//*************************************************************************************** +// NAME: Create +// PRECONDITIONS: none +// PARAMETER: AOwner : owner of the component +// RETURN VALUE: none +// DESCRIPTION: Component constructor. Calls TComponent's constructor and initializes +// the private property variables to their default values. +// +//*************************************************************************************** +constructor TPCanDriver.Create( AOwner: TComponent ); +begin + // call inherited constructor + inherited Create( AOwner ); + + // set defaults for internal variables + FThreadRunning := False; + FCanConnected := False; + + // set defaults for properties + FBaudRate := 500000; + FChannel := pcanchannel0; + FHardware := PCAN_USB1CH; + FPriority := tpNormal; + FExtendedId := False; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Component destructor. Calls TComponent's destructor +// +//*************************************************************************************** +destructor TPCanDriver.Destroy; +begin + Disconnect; // close the port and driver + inherited Destroy; // call inherited destructor +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: IsConnected +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: True or False +// DESCRIPTION: Determines whether or not the CAN driver is connected and active +// +//*************************************************************************************** +function TPCanDriver.IsConnected: boolean; +begin + Result := FCanConnected; +end; //*** end of IsConnected *** + + +//*************************************************************************************** +// NAME: IsThreadRunning +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: True or False +// DESCRIPTION: Determines whether or not the CAN event thread is running +// +//*************************************************************************************** +function TPCanDriver.IsThreadRunning: boolean; +begin + if FThreadRunning = True then + Result := True + else + Result := False; +end; //*** end of IsThreadRunning *** + + +//*************************************************************************************** +// NAME: SetBaudRate +// PRECONDITIONS: none +// PARAMETER: Value : new baudrate value [0 - 1000000 bps] +// RETURN VALUE: none +// DESCRIPTION: Configures the baudrate +// +// |------------------------------------------------------------------------------------ +// | Update baudrate configuration +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TPCanDriver.SetBaudRate( Value: LongInt ); +begin + FBaudRate := Value; // update property +end; //*** end of SetBaudRate *** + + +//*************************************************************************************** +// NAME: SetChannel +// PRECONDITIONS: none +// PARAMETER: Value : channel0 or channel1 +// RETURN VALUE: none +// DESCRIPTION: Configures the used CAN channel +// +// |------------------------------------------------------------------------------------ +// | Update channel configuration +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TPCanDriver.SetChannel( Value: TPCanChannel ); +begin + FChannel := Value; +end; //*** end of SetChannel *** + + +//*************************************************************************************** +// NAME: SetHardware +// PRECONDITIONS: none +// PARAMETER: Value : type of CAN hardware (Virtual, CANcardXL, etc.) +// RETURN VALUE: none +// DESCRIPTION: Configures the used CAN hardware +// +// |------------------------------------------------------------------------------------ +// | Update hardware configuration +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TPCanDriver.SetHardware( Value: TPCanHardware ); +begin + FHardware := Value; +end; //*** end of SetHardware *** + + +//*************************************************************************************** +// NAME: SetPriority +// PRECONDITIONS: none +// PARAMETER: Value : thread priority +// RETURN VALUE: none +// DESCRIPTION: Configures the priority for the CAN event thread +// +// |------------------------------------------------------------------------------------ +// | y\ Is Thread running? /n +// |------------------------------------------------------------------------------------ +// | Stop Thread | +// | Update Thread priority | Update Thread priority +// | Restart Thread | +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TPCanDriver.SetPriority( Value: TThreadPriority ); +begin + if IsThreadRunning then + begin + FCanEventThread.Suspend; // suspend the thread + FPriority := Value; // update the priority + FCanEventThread.Resume; // resume the thread + end + else + begin + FPriority := Value; // update the priority + end; +end; //*** end of SetPriority *** + + +//*************************************************************************************** +// NAME: SetExtendedId +// PRECONDITIONS: none +// PARAMETER: Value : true = support only 29-bit id's, false = support only 11-bit +// RETURN VALUE: none +// DESCRIPTION: Configures the support of extended 29-bit identifiers +// +// |------------------------------------------------------------------------------------ +// | Update extended id support selection +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TPCanDriver.SetExtendedId( Value: Boolean ); +begin + FExtendedId := Value; +end; //*** end of SetExtendedId ***/ + + +//*************************************************************************************** +// NAME: Connect +// PRECONDITIONS: Disconnected from CAN bus +// PARAMETER: none +// RETURN VALUE: True or False for succees or error, respectively +// DESCRIPTION: Initializes the CAN driver and synchronizes the hardware with the CAN +// bus. +// +//*************************************************************************************** +function TPCanDriver.Connect: boolean; +var + Baudcode : Word; + MsgType : Integer; + +begin + Result := False; + FThreadRunning := False; + FCanConnected := False; + + // convert baudrate in bps to supported baudrate code + Baudcode := CAN_BAUD_500K; // init local + case FBaudRate of + 5000 : Baudcode := CAN_BAUD_5K; + 10000 : Baudcode := CAN_BAUD_10K; + 20000 : Baudcode := CAN_BAUD_20K; + 33333 : Baudcode := $1D14; + 50000 : Baudcode := CAN_BAUD_50K; + 83333 : Baudcode := $4B14; + 100000 : Baudcode := CAN_BAUD_100K; + 125000 : Baudcode := CAN_BAUD_125K; + 250000 : Baudcode := CAN_BAUD_250K; + 500000 : Baudcode := CAN_BAUD_500K; + 1000000 : Baudcode := CAN_BAUD_1M; + end; + + // convert extented id info + if FExtendedId then + MsgType := 1 + else + MsgType := 0; + + //-------------------------- open the driver ------------------------------------------ + if CAN_Init(Baudcode, MsgType) <> CAN_ERR_OK then Exit; + + + //-------------------------- open the acceptance filter -------------------------------- + if CAN_ResetFilter <> CAN_ERR_OK then + begin + CAN_Close; + Exit; + end; + + if FExtendedId then + begin + if CAN_MsgFilter($000, $1FFFFFFF, MSGTYPE_EXTENDED) <> CAN_ERR_OK then + begin + CAN_Close; + Exit; + end; + end + else + begin + if CAN_MsgFilter($000, $7FF, MSGTYPE_STANDARD) <> CAN_ERR_OK then + begin + CAN_Close; + Exit; + end; + end; + + //-------------------------- reset message queues ------------------------------------- + if CAN_ResetClient <> CAN_ERR_OK then + begin + CAN_Close; + Exit; + end; + + //-------------------------- start CAN event thread ----------------------------------- + FCanEventThread := TPCanEventThread.Create(True); // create and suspend + FCanEventThread.FreeOnTerminate := True; // auto free on termination + FCanEventThread.Method := ProcessReception; // set method + FCanEventThread.Resume; // start + FThreadRunning := True; + + + //-------------------------- store start time for time stamps ------------------------- + FStartTickCnt := GetTickCount; + + //-------------------------- success -------------------------------------------------- + FCanConnected := True; + Result := True; // successfully initialized the driver +end; //*** end of Connect *** + + +//*************************************************************************************** +// NAME: Disconnect +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Disconnects the CAN driver +// +//*************************************************************************************** +procedure TPCanDriver.Disconnect; +begin + if IsConnected = True then // are we connected? + begin + FCanConnected := False; + // close the channel + CAN_Close; + end; + + if IsThreadRunning then + begin + FCanEventThread.Terminate; // stop + FThreadRunning := False; + end; +end; //*** end of Disconnect *** + + +//*************************************************************************************** +// NAME: Transmit +// PRECONDITIONS: Driver initialized using 'Connect' +// PARAMETER: Message: CAN message that is to be transmitted +// RETURN VALUE: True or False for succees or error, respectively +// DESCRIPTION: Transmits a CAN message. +// +//*************************************************************************************** +function TPCanDriver.Transmit( Message: TPCanMessage): boolean; +var + cnt : Byte; + msg : TPCANMsg; + msgcpy : TPCanMessage; +begin + // make sure the CAN driver is connected + if not IsConnected then + begin + Result := False; // can't transmit it not connected + exit; // no need to continue + end; + + // set the message identifier + msg.ID := Message.id; + if Message.ext then + msg.MSGTYPE := MSGTYPE_EXTENDED + else + msg.MSGTYPE := MSGTYPE_STANDARD; + + // set the data length + msg.LEN := Message.dlc; + + // store the data bytes + for cnt :=0 to Message.dlc do + begin + msg.DATA[cnt] := Message.data[cnt]; + end; + + // submit the transmit request + if CAN_Write(msg) <> CAN_ERR_OK then + begin + Result := False; + exit; + end; + + //---------------- process transmission confirmation -------------------------- + if Assigned( FOnMessage ) then + begin + msgcpy := Message; + msgcpy.time := GetTickCount - FStartTickCnt; + FOnMessage( Self, PCanTx, msgcpy ); // call application's event handler + end; + + Result := True; +end; //*** end of Transmit *** + + +//*************************************************************************************** +// NAME: ProcessReception +// PRECONDITIONS: thread running +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the CAN event tread. This function traps and processes CAN +// events for OnMessage. +// +//*************************************************************************************** +procedure TPCanDriver.ProcessReception; +var + cnt : Byte; + msg : TPCanMessage; + msgraw : TPCANMsg; +begin + //---------------- process reception indication ------------------------------- + // continue only if a new message is present in the queue + if CAN_Read(msgraw) <> CAN_ERR_OK then + Exit; + + // only process CAN messages and not the status messages + if (msgraw.MSGTYPE = MSGTYPE_EXTENDED) or (msgraw.MSGTYPE = MSGTYPE_STANDARD) then + begin + // copy the message info + msg.time := GetTickCount - FStartTickCnt; + msg.id := msgraw.ID; + msg.dlc := msgraw.LEN; + // store the data bytes + for cnt :=0 to msg.dlc do + begin + msg.data[cnt] := msgraw.DATA[cnt]; + end; + + if Assigned( FOnMessage ) then + begin + FOnMessage( Self, PCanRx, msg ); // call application's event handler + end; + end; +end; //*** end of ProcessReception *** + + +//*************************************************************************************** +// NAME: Register +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Registers the TPCanDriver component into Borland Delphi's IDE. +// +//*************************************************************************************** +procedure Register; +begin + RegisterComponents('Feaser', [TPCanDriver]); +end; //*** end of Register *** + + +end. +//********************************** end of PCANdrvD.pas ******************************** + + diff --git a/Host/Source/interfaces/can/peak/Pcan_usb.pas b/Host/Source/interfaces/can/peak/Pcan_usb.pas new file mode 100644 index 00000000..f62f7ef3 --- /dev/null +++ b/Host/Source/interfaces/can/peak/Pcan_usb.pas @@ -0,0 +1,296 @@ +/////////////////////////////////////////////////////////////////////////////// +// PCAN-Light +// PCAN_USB.pas +// +// Version 1.5 +// +// ~~~~~~~~~~ +// +// Basic Idea: +// +// ~~~~~~~~~~ +// +// Definition of the PCAN-Light API. +// The Driver support a Hardware and a Software who want to communicate with CAN-busses +// +// ~~~~~~~~~~~~ +// +// PCAN-Light -API +// +// ~~~~~~~~~~~~ +// +// - CAN_Init(wBTR0BTR1: Word; CANMsgType: Integer) +// - CAN_Close() +// - CAN_Status() +// - CAN_Write(var MsgBuff: TPCANMsg) +// - CAN_Read(var MsgBuff: TPCANMsg) +// - CAN_VersionInfo(lpszTextBuff: PChar) +// - CAN_ResetClient() +// - CAN_MsgFilter(FromID, ToID: LongWord; _Type: Integer) +// - CAN_ResetFilter() +// - SetUSBDeviceNr(DevNum: Longint) +// - GetUSBDeviceNr(var DevNum: Longint) +// +// ------------------------------------------------------------------ +// Author : Hoppe, Wilhelm +// Modified By: Wagner (13.08.2008) +// +// Sprache: PASCAL OO +// ------------------------------------------------------------------ +// +// Copyright (C) 1999-2006 PEAK-System Technik GmbH, Darmstadt +// +unit pcan_usb; + +interface + +const + // Constants definitions - Frame Type + // + CAN_INIT_TYPE_EX = $01; //Extended Frame + CAN_INIT_TYPE_ST = $00; //Standart Frame + + // Constants definitions - ID + // + CAN_MAX_STANDARD_ID = $7ff; + CAN_MAX_EXTENDED_ID = $1fffffff; + + // Constants definitions - CAN message types + // + MSGTYPE_STANDARD = $00; // Standard Data frame (11-bit ID) + MSGTYPE_RTR = $01; // 1, if Remote Request frame + MSGTYPE_EXTENDED = $02; // 1, if Extended Data frame (CAN 2.0B, 29-bit ID) + MSGTYPE_ERROR = $80; // 1, if Status information + + // Baud rate codes = BTR0/BTR1 register values for the CAN controller. + // You can define your own Baudrate with the BTROBTR1 register !! + // take a look at www.peak-system.com for our software BAUDTOOL to + // calculate the BTROBTR1 register for every baudrate and sample point. + // + CAN_BAUD_1M = $0014; // 1 MBit/s + CAN_BAUD_500K = $001C; // 500 kBit/s + CAN_BAUD_250K = $011C; // 250 kBit/s + CAN_BAUD_125K = $031C; // 125 kBit/s + CAN_BAUD_100K = $432F; // 100 kBit/s + CAN_BAUD_50K = $472F; // 50 kBit/s + CAN_BAUD_20K = $532F; // 20 kBit/s + CAN_BAUD_10K = $672F; // 10 kBit/s + CAN_BAUD_5K = $7F7F; // 5 kBit/s + + // Error codes (bit code) + // + CAN_ERR_OK = $0000; // No error + CAN_ERR_XMTFULL = $0001; // Transmit buffer in CAN controller is full + CAN_ERR_OVERRUN = $0002; // CAN controller was read too late + CAN_ERR_BUSLIGHT = $0004; // Bus error: an error counter reached the 'light' limit + CAN_ERR_BUSHEAVY = $0008; // Bus error: an error counter reached the 'heavy' limit + CAN_ERR_BUSOFF = $0010; // Bus error: the CAN controller is in bus-off state + CAN_ERR_QRCVEMPTY = $0020; // Receive queue is empty + CAN_ERR_QOVERRUN = $0040; // Receive queue was read too late + CAN_ERR_QXMTFULL = $0080; // Transmit queue is full + CAN_ERR_REGTEST = $0100; // Test of the CAN controller hardware registers failed (no hardware found) + CAN_ERR_NOVXD = $0200; // Driver not loaded + CAN_ERR_RESOURCE = $2000; // Resource (FIFO, Client, timeout) cannot be created + CAN_ERR_ILLPARAMTYPE = $4000; // Invalid parameter + CAN_ERR_ILLPARAMVAL = $8000; // Invalid parameter value + CAN_ERRMASK_ILLHANDLE = $1C00; // Mask for all handle errors + CAN_ERR_ANYBUSERR = (CAN_ERR_BUSLIGHT or CAN_ERR_BUSHEAVY or CAN_ERR_BUSOFF); + // All further error conditions <> 0 please ask PEAK when required.......internal driver failure ........ + +type + // CAN Message + // + TPCANMsg = record + ID: LongWord; // 11/29 bit identifier + MSGTYPE: Byte; // Bits from MSGTYPE_* + LEN: Byte; // Data Length Code of the Msg (0..8) + DATA: array[0..7] of Byte; // Data 0 .. 7 + end; + +/////////////////////////////////////////////////////////////////////////////// +// CAN_Init() +// This function make the following: +// - Activate a Hardware +// - Make a Register Test of 82C200/SJA1000 +// - Allocate a Send buffer and a Hardware handle +// - Programs the configuration of the transmit/receive driver +// - Set the Baudrate register +// - Set the Controller in RESET condition +// +// If CANMsgType=0 ---> ID 11Bit +// If CANMsgType=1 ---> ID 11/29Bit +// +// Possible Errors: NOVXD ILLHW REGTEST RESOURCE +// +function CAN_Init(wBTR0BTR1: Word; + CANMsgType: Integer): LongWord; stdcall; + +/////////////////////////////////////////////////////////////////////////////// +// CAN_Close() +// This function terminate and release the configured hardware and all +// allocated resources +// +// Possible Errors: NOVXD +// +function CAN_Close: LongWord; stdcall; + +/////////////////////////////////////////////////////////////////////////////// +// CAN_Status() +// This function request the current status of the hardware (b.e. BUS-OFF) +// +// Possible Errors: NOVXD BUSOFF BUSHEAVY OVERRUN +// +function CAN_Status: LongWord; stdcall; + +/////////////////////////////////////////////////////////////////////////////// +// CAN_Write() +// This function Place a CAN message into the Transmit Queue of the CAN Hardware +// +// Possible Errors: NOVXD RESOURCE BUSOFF QXMTFULL +// +function CAN_Write(var MsgBuff: TPCANMsg): LongWord; stdcall; + +/////////////////////////////////////////////////////////////////////////////// +// CAN_Read() +// This function get the next message or the next error from the Receive Queue of +// the CAN Hardware. +// REMARK: +// - Check always the type of the received Message (MSGTYPE_STANDARD,MSGTYPE_RTR, +// MSGTYPE_EXTENDED,MSGTYPE_STATUS) +// - The function will return ERR_OK always that you receive a CAN message successfully +// although if the messages is a MSGTYPE_STATUS message. +// - When a MSGTYPE_STATUS mesasge is got, the ID and Length information of the message +// will be treated as indefined values. Actually information of the received message +// should be interpreted using the first 4 data bytes as follow: +// * Data0 Data1 Data2 Data3 Kind of Error +// 0x00 0x00 0x00 0x02 CAN_ERR_OVERRUN 0x0002 CAN Controller was read to late +// 0x00 0x00 0x00 0x04 CAN_ERR_BUSLIGHT 0x0004 Bus Error: An error counter limit reached (96) +// 0x00 0x00 0x00 0x08 CAN_ERR_BUSHEAVY 0x0008 Bus Error: An error counter limit reached (128) +// 0x00 0x00 0x00 0x10 CAN_ERR_BUSOFF 0x0010 Bus Error: Can Controller went "Bus-Off" +// - If a CAN_ERR_BUSOFF status message is received, the CAN Controller must to be +// initialized again using the Init() function. Otherwise, will be not possible +// to send/receive more messages. +// - The message will be written to 'msgbuff'. +// +// Possible Errors: NOVXD QRCVEMPTY +// +function CAN_Read(var MsgBuff: TPCANMsg): LongWord; stdcall; + +/////////////////////////////////////////////////////////////////////////////// +// CAN_VersionInfo() +// This function get the Version and copyright of the hardware as text +// (max. 255 characters) +// +// Possible Errors: NOVXD +// +function CAN_VersionInfo( + lpszTextBuff: PChar + ): LongWord; stdcall; + +/////////////////////////////////////////////////////////////////////////////// +// CAN_SpecialFunktion() +// This function is an special function to be used "ONLY" for distributors +// Return: 1 - the given parameters and the parameters in the hardware agree +// 0 - otherwise +// +// Possible Errors: NOVXD +// +function CAN_SpecialFunktion( + distributorcode: LongWord; + codenumber: Integer + ): LongWord; stdcall; + +////////////////////////////////////////////////////////////////////////////// +// CAN_ResetClient() +// This function delete the both queues (Transmit,Receive) of the CAN Controller +// using a RESET +// +// Possible Errors: ERR_ILLCLIENT ERR_NOVXD +// +function CAN_ResetClient: LongWord; stdcall; + +/////////////////////////////////////////////////////////////////////////////// +// CAN_MsgFilter(FromID, ToID, int Type) +// This function set the receive message filter of the CAN Controller. +// REMARK: +// - A quick register of all messages is possible using the parameters FromID and ToID = 0 +// - Every call of this function maybe cause an extention of the receive filter of the +// CAN controller, which one can go briefly to RESET +// - New in Ver 2.x: +// * Standard frames will be put it down in the acc_mask/code as Bits 28..13 +// * Hardware driver for 82C200 must to be moved to Bits 10..0 again! +// WARNING: +// It is not guaranteed to receive ONLY the registered messages. +// +// Possible Errors: NOVXD ILLCLIENT ILLNET REGTEST +// +function CAN_MsgFilter(FromID, ToID: LongWord; _Type: Integer): LongWord; stdcall; + +/////////////////////////////////////////////////////////////////////////////// +// CAN_ResetFilter() +// This function close completely the Message Filter of the Hardware. +// They will be no more messages received. +// +// Possible Errors: NOVXD +// +function CAN_ResetFilter: LongWord; stdcall; + +////////////////////////////////////////////////////////////////////////////// +// SetUSBDeviceNr() +// This function set an identification number to the USB CAN hardware +// +// Possible Errors: NOVXD ILLHW ILLPARAMTYPE ILLPARAMVAL REGTEST +// +function SetUSBDeviceNr(DevNum: Longint): LongWord; stdcall; + +////////////////////////////////////////////////////////////////////////////// +// GetUSBDeviceNr() +// This function read the device number of a USB CAN Hardware +// +// Possible Errors: NOVXD ILLHW ILLPARAMTYPE +// +function GetUSBDeviceNr(var DevNum: Longint): LongWord; stdcall; + +implementation + +uses SysUtils; + +const DLL_Name = 'PCAN_USB.dll'; + +function CAN_Init(wBTR0BTR1: Word; CANMsgType: Integer): LongWord; stdcall; +external DLL_Name; + +function CAN_Close: LongWord; stdcall; +external DLL_Name; + +function CAN_Status: LongWord; stdcall; +external DLL_Name; + +function CAN_Write(var MsgBuff: TPCANMsg): LongWord; stdcall; +external DLL_Name; + +function CAN_Read(var MsgBuff: TPCANMsg): LongWord; stdcall; +external DLL_Name; + +function CAN_VersionInfo(lpszTextBuff: PChar): LongWord; stdcall; +external DLL_Name; + +function CAN_SpecialFunktion(distributorcode: LongWord; codenumber: Integer): LongWord; stdcall; +external DLL_Name; + +function CAN_ResetClient: LongWord; stdcall; +external DLL_Name; + +function CAN_MsgFilter(FromID, ToID: LongWord; _Type: Integer): LongWord; stdcall; +external DLL_Name; + +function CAN_ResetFilter: LongWord; stdcall; +external DLL_Name; + +function SetUSBDeviceNr(DevNum: Longint): LongWord; stdcall; +external DLL_Name; + +function GetUSBDeviceNr(var DevNum: Longint): LongWord; stdcall; +external DLL_Name; + +end. diff --git a/Host/Source/interfaces/can/peak/XcpSettings.dfm b/Host/Source/interfaces/can/peak/XcpSettings.dfm new file mode 100644 index 0000000000000000000000000000000000000000..ae3b3a1b2ec321e73c0f8eb4c176581776bfc482 GIT binary patch literal 13359 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 NbsZ;t;@XbQ`X8X6dZ_>a literal 0 HcmV?d00001 diff --git a/Host/Source/interfaces/can/peak/XcpSettings.pas b/Host/Source/interfaces/can/peak/XcpSettings.pas new file mode 100644 index 00000000..5707cbfe --- /dev/null +++ b/Host/Source/interfaces/can/peak/XcpSettings.pas @@ -0,0 +1,289 @@ +unit XcpSettings; +//*************************************************************************************** +// Description: XCP settings interface for CAN +// File Name: XcpSettings.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, ComCtrls, ExtCtrls, IniFiles; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TXcpSettingsForm = class(TForm) + pnlFooter: TPanel; + btnOK: TButton; + btnCancel: TButton; + pageControl: TPageControl; + tabXcp: TTabSheet; + tabCan: TTabSheet; + iconCan: TImage; + lblCan: TLabel; + lblXcp: TLabel; + iconXcp2: TImage; + lblHardware: TLabel; + cmbHardware: TComboBox; + lblChannel: TLabel; + cmbChannel: TComboBox; + lblBaudRate: TLabel; + chbExtendedId: TCheckBox; + edtBaudRate: TEdit; + lblT1: TLabel; + lblT3: TLabel; + lblT4: TLabel; + lblT5: TLabel; + lblT7: TLabel; + edtT1: TEdit; + edtT3: TEdit; + edtT4: TEdit; + edtT5: TEdit; + edtT7: TEdit; + tabProt: TTabSheet; + iconXcp1: TImage; + lblPort: TLabel; + edtSeedKey: TEdit; + btnBrowse: TButton; + lblTransmitId: TLabel; + Label1: TLabel; + edtTransmitId: TEdit; + edtReceiveId: TEdit; + openDialog: TOpenDialog; + procedure btnOKClick(Sender: TObject); + procedure btnCancelClick(Sender: TObject); + procedure btnBrowseClick(Sender: TObject); + private + { Private declarations } + public + { Public declarations } + end; + +type + TXcpSettings = class(TObject) + private + FSettingsForm : TXcpSettingsForm; + FIniFile : string; + public + constructor Create(iniFile : string); + destructor Destroy; override; + function Configure : Boolean; + end; + + +implementation +{$R *.DFM} +//*************************************************************************************** +// NAME: btnOKClick +// PARAMETER: none +// RETURN VALUE: modal result +// DESCRIPTION: Sets the module result to okay. +// +//*************************************************************************************** +procedure TXcpSettingsForm.btnOKClick(Sender: TObject); +begin + ModalResult := mrOK; +end; //*** end of btnOKClick *** + + +//*************************************************************************************** +// NAME: btnCancelClick +// PARAMETER: none +// RETURN VALUE: modal result +// DESCRIPTION: Sets the module result to cancel. +// +//*************************************************************************************** +procedure TXcpSettingsForm.btnCancelClick(Sender: TObject); +begin + ModalResult := mrCancel; +end; //*** end of btnCancelClick *** + + +//*************************************************************************************** +// NAME: btnBrowseClick +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Prompts the user to select the seed/key dll file. +// +//*************************************************************************************** +procedure TXcpSettingsForm.btnBrowseClick(Sender: TObject); +begin + openDialog.InitialDir := ExtractFilePath(ParamStr(0)); + if openDialog.Execute then + begin + edtSeedKey.Text := openDialog.FileName; + end; +end; //*** end of btnBrowseClick *** + + +//*************************************************************************************** +// NAME: Create +// PARAMETER: Name of the INI file where the settings are and will be stored +// RETURN VALUE: none +// DESCRIPTION: Class constructor +// +//*************************************************************************************** +constructor TXcpSettings.Create(iniFile : string); +begin + // call inherited constructor + inherited Create; + + // set the inifile + FIniFile := iniFile; + + // create an instance of the settings form + FSettingsForm := TXcpSettingsForm.Create(nil); +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class destructor +// +//*************************************************************************************** +destructor TXcpSettings.Destroy; +begin + // releaase the settings form object + FSettingsForm.Free; + + // call inherited destructor + inherited; +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: Configure +// PARAMETER: none +// RETURN VALUE: True if configuration was successfully changed, False otherwise +// DESCRIPTION: Allows the user to configure the XCP interface using a GUI. +// +//*************************************************************************************** +function TXcpSettings.Configure : Boolean; +var + settingsIni: TIniFile; +begin + // initialize the return value + result := false; + + // init the form elements using the configuration found in the INI + if FileExists(FIniFile) then + begin + // create ini file object + settingsIni := TIniFile.Create(FIniFile); + + // CAN related elements + FSettingsForm.cmbHardware.ItemIndex := settingsIni.ReadInteger('can', 'hardware', 0); + FSettingsForm.cmbChannel.ItemIndex := settingsIni.ReadInteger('can', 'channel', 0); + FSettingsForm.edtBaudRate.Text := IntToStr(settingsIni.ReadInteger('can', 'baudrate', 500)); + FSettingsForm.chbExtendedId.Checked := settingsIni.ReadBool('can', 'extended', false); + FSettingsForm.edtTransmitId.Text := Format('%x',[settingsIni.ReadInteger('can', 'txid', $667)]); + FSettingsForm.edtReceiveId.Text := Format('%x',[settingsIni.ReadInteger('can', 'rxid', $7e1)]); + + // XCP related elements + FSettingsForm.edtSeedKey.Text := settingsIni.ReadString('xcp', 'seedkey', ''); + FSettingsForm.edtT1.Text := IntToStr(settingsIni.ReadInteger('xcp', 't1', 1000)); + FSettingsForm.edtT3.Text := IntToStr(settingsIni.ReadInteger('xcp', 't3', 2000)); + FSettingsForm.edtT4.Text := IntToStr(settingsIni.ReadInteger('xcp', 't4', 10000)); + FSettingsForm.edtT5.Text := IntToStr(settingsIni.ReadInteger('xcp', 't5', 1000)); + FSettingsForm.edtT7.Text := IntToStr(settingsIni.ReadInteger('xcp', 't7', 2000)); + + // release ini file object + settingsIni.Free; + end + else + begin + // set defaults + // CAN related elements + FSettingsForm.cmbHardware.ItemIndex := 0; + FSettingsForm.cmbChannel.ItemIndex := 0; + FSettingsForm.edtBaudRate.Text := IntToStr(500); + FSettingsForm.chbExtendedId.Checked := false; + FSettingsForm.edtTransmitId.Text := Format('%x',[$667]); + FSettingsForm.edtReceiveId.Text := Format('%x',[$7e1]); + + // XCP related elements + FSettingsForm.edtSeedKey.Text := ''; + FSettingsForm.edtT1.Text := IntToStr(1000); + FSettingsForm.edtT3.Text := IntToStr(2000); + FSettingsForm.edtT4.Text := IntToStr(10000); + FSettingsForm.edtT5.Text := IntToStr(1000); + FSettingsForm.edtT7.Text := IntToStr(2000); + + end; + + // show the form as modal so we can get the result here + if FSettingsForm.ShowModal = mrOK then + begin + if FIniFile <> '' then + begin + // create ini file object + settingsIni := TIniFile.Create(FIniFile); + + // CAN related elements + settingsIni.WriteInteger('can', 'hardware', FSettingsForm.cmbHardware.ItemIndex); + settingsIni.WriteInteger('can', 'channel', FSettingsForm.cmbChannel.ItemIndex); + settingsIni.WriteInteger('can', 'baudrate', StrToInt(FSettingsForm.edtBaudRate.Text)); + settingsIni.WriteBool('can', 'extended', FSettingsForm.chbExtendedId.Checked); + settingsIni.WriteInteger('can', 'txid', StrToInt('$'+FSettingsForm.edtTransmitId.Text)); + settingsIni.WriteInteger('can', 'rxid', StrToInt('$'+FSettingsForm.edtReceiveId.Text)); + + // XCP related elements + settingsIni.WriteString('xcp', 'seedkey', FSettingsForm.edtSeedKey.Text); + settingsIni.WriteInteger('xcp', 't1', StrToInt(FSettingsForm.edtT1.Text)); + settingsIni.WriteInteger('xcp', 't3', StrToInt(FSettingsForm.edtT3.Text)); + settingsIni.WriteInteger('xcp', 't4', StrToInt(FSettingsForm.edtT4.Text)); + settingsIni.WriteInteger('xcp', 't5', StrToInt(FSettingsForm.edtT5.Text)); + settingsIni.WriteInteger('xcp', 't7', StrToInt(FSettingsForm.edtT7.Text)); + + // release ini file object + settingsIni.Free; + + // indicate that the settings where successfully updated + result := true; + end; + end; +end; //*** end of Configure *** + + +end. +//******************************** end of XcpSettings.pas ******************************* + + diff --git a/Host/Source/interfaces/can/peak/XcpTransport.pas b/Host/Source/interfaces/can/peak/XcpTransport.pas new file mode 100644 index 00000000..b8f79f36 --- /dev/null +++ b/Host/Source/interfaces/can/peak/XcpTransport.pas @@ -0,0 +1,362 @@ +unit XcpTransport; +//*************************************************************************************** +// Description: XCP transport layer for CAN. +// File Name: XcpTransport.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Forms, IniFiles, PCANdrvD; + + +//*************************************************************************************** +// Global Constants +//*************************************************************************************** +const kMaxPacketSize = 256; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TXcpTransportInfo = (kNone, kResponse, kError); + + +type + TXcpTransport = class(TObject) + private + comEventInfo : TXcpTransportInfo; + comEvent : THandle; + packetTxId : LongWord; + packetRxId : Longword; + extendedId : Boolean; + procedure OnCanMessage(Sender: TObject; Direction: TPCanDirection; Message: TPCanMessage); + function MsgWaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; + public + packetData : array[0..kMaxPacketSize-1] of Byte; + packetLen : Word; + pcanDriver : TPCanDriver; + constructor Create; + procedure Configure(iniFile : string); + procedure Connect; + function SendPacket(timeOutms: LongWord): Boolean; + procedure Disconnect; + destructor Destroy; override; + end; + + +implementation + +//*************************************************************************************** +// NAME: Create +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class constructore +// +//*************************************************************************************** +constructor TXcpTransport.Create; +begin + // call inherited constructor + inherited Create; + + // reset can event info + comEventInfo := kNone; + + // create the event that requires manual reset + comEvent := CreateEvent(nil, True, False, nil); + + if comEvent = 0 then + Application.MessageBox( 'Could not obtain event placeholder.', + 'Error', MB_OK or MB_ICONERROR ); + + // create a pcan driver instance + pcanDriver := TPCanDriver.Create(nil); + + // set can driver event handlers + pcanDriver.OnMessage := OnCanMessage; + + // reset the packet ids + packetTxId := 0; + packetRxId := 0; + + // use standard id's by default + extendedId := false; + + // reset packet length + packetLen := 0; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class destructor +// +//*************************************************************************************** +destructor TXcpTransport.Destroy; +begin + // release can driver instance + pcanDriver.Free; + + // release event handle + CloseHandle(comEvent); + + // call inherited destructor + inherited; +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: Configure +// PARAMETER: filename of the INI +// RETURN VALUE: none +// DESCRIPTION: Configures both this class from the settings in the INI. +// +//*************************************************************************************** +procedure TXcpTransport.Configure(iniFile : string); +var + settingsIni : TIniFile; + hwIndex : integer; +begin + // read XCP configuration from INI + if FileExists(iniFile) then + begin + // create ini file object + settingsIni := TIniFile.Create(iniFile); + + // set message configuration + packetTxId := settingsIni.ReadInteger('can', 'txid', $667); + packetRxId := settingsIni.ReadInteger('can', 'rxid', $7e1); + extendedId := settingsIni.ReadBool('can', 'extended', false); + + // configure can hardware + hwIndex := settingsIni.ReadInteger('can', 'hardware', 0); + pcanDriver.Hardware := PCAN_USB1CH; // init to PCAN_USB1CH + case hwIndex of + 0 : pcanDriver.Hardware := PCAN_USB1CH; + end; + + // configure baudrate + pcanDriver.BaudRate := settingsIni.ReadInteger('can', 'baudrate', 500) * 1000; + + // only 1 channel on PCAN USB 1CH + pcanDriver.Channel := pcanchannel0; + + // release ini file object + settingsIni.Free; + end; +end; //*** end of Configure *** + + +//*************************************************************************************** +// NAME: Connect +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Connects the transport layer device. +// +//*************************************************************************************** +procedure TXcpTransport.Connect; +begin + if not pcanDriver.Connect then + Application.MessageBox( 'Could not connect to CAN bus.', + 'Error', MB_OK or MB_ICONERROR ); +end; //*** end of Connect *** + + +//*************************************************************************************** +// NAME: SendPacket +// PARAMETER: the time[ms] allowed for the reponse from the slave to come in. +// RETURN VALUE: True if response received from slave, False otherwise +// DESCRIPTION: Sends the XCP packet using the data in 'packetData' and length in +// 'packetLen' and waits for the response to come in. +// +//*************************************************************************************** +function TXcpTransport.SendPacket(timeOutms: LongWord): Boolean; +var + pcanmsg : TPCanMessage; + cnt : byte; + waitResult: Integer; +begin + // prepare the packet + pcanmsg.id := LongInt(PacketTxId); + pcanmsg.dlc := packetLen; + pcanmsg.ext := extendedId; + for cnt := 0 to packetLen-1 do + begin + pcanmsg.data[cnt] := packetData[cnt]; + end; + + // make sure the event is reset + ResetEvent(comEvent); + comEventInfo := kNone; + + // submit the packet transmission request + if not pcanDriver.Transmit(pcanmsg) then + begin + // unable to submit tx request + result := False; + Exit; + end; + + // packet is being transmitted. Now wait for the response to come in + waitResult := MsgWaitForSingleObject(comEvent, timeOutms); + + if waitResult <> WAIT_OBJECT_0 then + begin + // no com event triggered so either a timeout or internal error occurred + result := False; + Exit; + end; + + // com event was triggered. now check if the reponse was correctly received + if comEventInfo <> kResponse then + begin + result := False; + Exit; + end; + + // packet successfully transmitted and response packet received + result := True; +end; //*** end of SendPacket *** + + +//*************************************************************************************** +// NAME: Disconnect +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Disconnects the transport layer device. +// +//*************************************************************************************** +procedure TXcpTransport.Disconnect; +begin + pcanDriver.Disconnect; +end; //*** end of Disconnect *** + + +//*************************************************************************************** +// NAME: OnCanMessage +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Can message event handler +// +//*************************************************************************************** +procedure TXcpTransport.OnCanMessage(Sender: TObject; Direction: TPCanDirection; Message: TPCanMessage); +var + cnt : integer; +begin + // the event we are interested in is the reception of the command response from + // slave. + if Direction = PCanRx then + begin + if Message.id = LongInt(PacketRxId) then + begin + // store response data + for cnt := 0 to Message.dlc-1 do + begin + packetData[cnt] := Message.data[cnt]; + end; + + // store response length + packetLen := Message.dlc; + + // set event flag + comEventInfo := kResponse; + + // trigger the event + SetEvent(comEvent); + end; + end; +end; //*** end of OnCanMessage *** + + +//*************************************************************************************** +// NAME: MsgWaitForSingleObject +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Improved version of WaitForSingleObject. This version actually +// processes messages in the queue instead of blocking them. +// +//*************************************************************************************** +function TXcpTransport.MsgWaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; +var + dwEnd:DWord; +begin + // compute the time when the WaitForSingleObject is supposed to time out + dwEnd := GetTickCount + dwMilliseconds; + + repeat + // wait for an event to happen or a message to be in the queue + result := MsgWaitForMultipleObjects(1, hHandle, False, dwMilliseconds, QS_ALLINPUT); + + // a message was in the queue? + if result = WAIT_OBJECT_0 + 1 then + begin + // process these messages + Application.ProcessMessages; + + // check for timeout manually because if a message in the queue occurred, the + // MsgWaitForMultipleObjects will be called again and the timer will start from + // scratch. we need to make sure the correct timeout time is used. + dwMilliseconds := GetTickCount; + if dwMilliseconds < dwEnd then + begin + dwMilliseconds := dwEnd - dwMilliseconds; + end + else + begin + // timeout occured + result := WAIT_TIMEOUT; + Break; + end; + end + else + // the event occured? + begin + // we can stop + Break; + end; + until True = False; +end; //*** end of MsgWaitForSingleObject *** + + +end. +//******************************** end of XcpTransport.pas ****************************** + diff --git a/Host/Source/interfaces/can/peak/openblt_can_peak.cfg b/Host/Source/interfaces/can/peak/openblt_can_peak.cfg new file mode 100644 index 00000000..b7fa021f --- /dev/null +++ b/Host/Source/interfaces/can/peak/openblt_can_peak.cfg @@ -0,0 +1,35 @@ +-$A+ +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J+ +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-E../../../../ +-LNc:\program files (x86)\borland\delphi4\Lib diff --git a/Host/Source/interfaces/can/peak/openblt_can_peak.dof b/Host/Source/interfaces/can/peak/openblt_can_peak.dof new file mode 100644 index 00000000..0e2c2a16 --- /dev/null +++ b/Host/Source/interfaces/can/peak/openblt_can_peak.dof @@ -0,0 +1,87 @@ +[Compiler] +A=1 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=1 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir=../../../../ +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages=Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40 +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1031 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +$(DELPHI)\Lib\dclusr40.bpl=Borland User +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlOutputDirectorry] +Count=2 +Item0=../../../../ +Item1=../../../ diff --git a/Host/Source/interfaces/can/peak/openblt_can_peak.dpr b/Host/Source/interfaces/can/peak/openblt_can_peak.dpr new file mode 100644 index 00000000..07263dc5 --- /dev/null +++ b/Host/Source/interfaces/can/peak/openblt_can_peak.dpr @@ -0,0 +1,605 @@ +library openblt_can_peak; +//*************************************************************************************** +// Project Name: MicroBoot Interface for Borland Delphi +// Description: XCP - CAN interface for MicroBoot supporting PEAK CAN +// File Name: openblt_can_peak.dpr +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, + Messages, + Graphics, + Controls, + Forms, + Dialogs, + SysUtils, + Classes, + Extctrls, + XcpProtection in '..\..\XcpProtection.pas', + SRecReader in '..\..\SRecReader.pas', + XcpDataFile in '..\..\XcpDataFile.pas', + XcpLoader in '..\..\XcpLoader.pas', + XcpTransport in 'XcpTransport.pas', + XcpSettings in 'XcpSettings.pas' {XcpSettingsForm}, + pcan_usb in 'Pcan_usb.pas', + PCANdrvD in 'PCANdrvD.pas'; + + +//*************************************************************************************** +// Global Constants +//*************************************************************************************** +const kMaxProgLen = 256; // maximum number of bytes to progam at one time + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +// DLL Interface Callbacks - modifications requires potential update of all interfaces! +type + TStartedEvent = procedure(length: Longword) of object; + TProgressEvent = procedure(progress: Longword) of object; + TDoneEvent = procedure of object; + TErrorEvent = procedure(error: ShortString) of object; + TLogEvent = procedure(info: ShortString) of object; + TInfoEvent = procedure(info: ShortString) of object; + +type + TEventHandlers = class // create a dummy class + procedure OnTimeout(Sender: TObject); + end; + +//*************************************************************************************** +// Global Variables +//*************************************************************************************** +var + //--- begin of don't change --- + AppOnStarted : TStartedEvent; + AppOnProgress : TProgressEvent; + AppOnDone : TDoneEvent; + AppOnError : TErrorEvent; + AppOnLog : TLogEvent; + AppOnInfo : TInfoEvent; + //--- end of don't change --- + timer : TTimer; + events : TEventHandlers; + loader : TXcpLoader; + datafile : TXcpDataFile; + progdata : array of Byte; + progfile : string; + stopRequest : boolean; + + +//*************************************************************************************** +// NAME: MbiCallbackOnStarted +// PARAMETER: length of the file that is being downloaded. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnStarted(length: Longword); +begin + if Assigned(AppOnStarted) then + begin + AppOnStarted(length); + end; +end; //** end of MbiCallbackOnStarted *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnProgress +// PARAMETER: progress of the file download. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnProgress(progress: Longword); +begin + if Assigned(AppOnProgress) then + begin + AppOnProgress(progress); + end; +end; //** end of MbiCallbackOnProgress *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnDone +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnDone; +begin + if Assigned(AppOnDone) then + begin + AppOnDone; + end; +end; //** end of MbiCallbackOnDone *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnError +// PARAMETER: info about the error that occured. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnError(error: ShortString); +begin + if Assigned(AppOnError) then + begin + AppOnError(error); + end; +end; //** end of MbiCallbackOnError *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnLog +// PARAMETER: info on the log event. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnLog(info: ShortString); +begin + if Assigned(AppOnLog) then + begin + AppOnLog(info); + end; +end; //** end of MbiCallbackOnLog *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnInfo +// PARAMETER: details on the info event. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnInfo(info: ShortString); +begin + if Assigned(AppOnInfo) then + begin + AppOnInfo(info); + end; +end; //** end of MbiCallbackOnLog *** + + +//*************************************************************************************** +// NAME: LogData +// PARAMETER: pointer to byte array and the data length +// RETURN VALUE: none +// DESCRIPTION: Writes the program data formatted to the logfile +// +//*************************************************************************************** +procedure LogData(data : PByteArray; len : longword); stdcall; +var + currentWriteCnt : byte; + cnt : byte; + logStr : string; + bufferOffset : longword; +begin + bufferOffset := 0; + + while len > 0 do + begin + // set the current write length optimized to log 32 bytes per line + currentWriteCnt := len mod 32; + if currentWriteCnt = 0 then currentWriteCnt := 32; + logStr := ''; + + // prepare the line to add to the log + for cnt := 0 to currentWriteCnt-1 do + begin + logStr := logStr + Format('%2.2x ', [data[bufferOffset+cnt]]); + end; + + // update the log + MbiCallbackOnLog(logStr); + + // update loop variables + len := len - currentWriteCnt; + bufferOffset := bufferOffset + currentWriteCnt; + end; +end; //*** end of LogData *** + + +//*************************************************************************************** +// NAME: OnTimeout +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Timer event handler. A timer is used in this example to simulate the +// progress of a file download. It also demonstrates how to use the +// application callbacks to keep the application informed. +// +//*************************************************************************************** +procedure TEventHandlers.OnTimeout(Sender: TObject); +var + errorInfo : string; + progress : longword; + regionCnt : longword; + currentWriteCnt : word; + bufferOffset : longword; + addr : longword; + len : longword; + dataSizeKB : real; +begin + timer.Enabled := False; + + // connect the transport layer + MbiCallbackOnLog('Connecting the transport layer. t='+TimeToStr(Time)); + loader.Connect; + + //---------------- start the programming session -------------------------------------- + MbiCallbackOnLog('Starting the programming session. t='+TimeToStr(Time)); + if not loader.StartProgrammingSession then + begin + // update the user info + MbiCallbackOnInfo('Could not connect. Please reset your target...'); + MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+TimeToStr(Time)); + Application.ProcessMessages; + end; + + while not loader.StartProgrammingSession do + begin + Application.ProcessMessages; + Sleep(5); + if stopRequest then + begin + MbiCallbackOnError('Programming session cancelled by user.'); + Exit; + end; + end; + + // still here so programming session was started + MbiCallbackOnLog('Programming session started. t='+TimeToStr(Time)); + + // create the datafile object + datafile := TXcpDataFile.Create(progfile); + + // compute the size in kbytes + dataSizeKB := datafile.GetDataCnt / 1024; + + // Call application callback when we start the actual download + MbiCallbackOnStarted(datafile.GetDataCnt); + + // Init progress to 0 progress + progress := 0; + MbiCallbackOnProgress(progress); + + //---------------- next clear the memory regions -------------------------------------- + // update the user info + MbiCallbackOnInfo('Erasing memory...'); + + for regionCnt := 0 to datafile.GetRegionCnt-1 do + begin + // obtain the region info + datafile.GetRegionInfo(regionCnt, addr, len); + + // erase the memory + MbiCallbackOnLog('Clearing Memory '+Format('addr:0x%x,len:0x%x',[addr,len])+'. t='+TimeToStr(Time)); + if not loader.ClearMemory(addr, len) then + begin + loader.GetLastError(errorInfo); + MbiCallbackOnLog('Could not clear memory ('+errorInfo+'). t='+TimeToStr(Time)); + MbiCallbackOnError('Could not clear memory ('+errorInfo+').'); + datafile.Free; + Exit; + end; + MbiCallbackOnLog('Memory cleared. t='+TimeToStr(Time)); + end; + + //---------------- next program the memory regions ------------------------------------ + for regionCnt := 0 to datafile.GetRegionCnt-1 do + begin + // update the user info + MbiCallbackOnInfo('Reading file...'); + + // obtain the region info + datafile.GetRegionInfo(regionCnt, addr, len); + // dynamically allocated buffer memory + SetLength(progdata, len); + // obtain the regiond data + datafile.GetRegionData(regionCnt, progdata); + + bufferOffset := 0; + while len > 0 do + begin + // set the current write length taking into account kMaxProgLen + currentWriteCnt := len mod kMaxProgLen; + if currentWriteCnt = 0 then currentWriteCnt := kMaxProgLen; + + // program the data + MbiCallbackOnLog('Programming Data '+Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt])+'. t='+TimeToStr(Time)); + LogData(@progdata[bufferOffset], currentWriteCnt); + + if not loader.WriteData(addr, currentWriteCnt, @progdata[bufferOffset]) then + begin + loader.GetLastError(errorInfo); + MbiCallbackOnLog('Could not program data ('+errorInfo+'). t='+TimeToStr(Time)); + MbiCallbackOnError('Could not program data ('+errorInfo+').'); + datafile.Free; + Exit; + end; + MbiCallbackOnLog('Data Programmed. t='+TimeToStr(Time)); + + // update progress + progress := progress + currentWriteCnt; + MbiCallbackOnProgress(progress); + + // update loop variables + len := len - currentWriteCnt; + addr := addr + currentWriteCnt; + bufferOffset := bufferOffset + currentWriteCnt; + + // update the user info + MbiCallbackOnInfo('Programming data... ' + Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB])); + + end; + end; + + //---------------- stop the programming session --------------------------------------- + MbiCallbackOnLog('Stopping the programming session. t='+TimeToStr(Time)); + if not loader.StopProgrammingSession then + begin + loader.GetLastError(errorInfo); + MbiCallbackOnLog('Could not stop the programming session ('+errorInfo+'). t='+TimeToStr(Time)); + MbiCallbackOnError('Could not stop the programming session ('+errorInfo+').'); + datafile.Free; + Exit; + end; + MbiCallbackOnLog('Programming session stopped. t='+TimeToStr(Time)); + + // all done so set progress to 100% and finish up + progress := datafile.GetDataCnt; + datafile.Free; + MbiCallbackOnProgress(progress); + MbiCallbackOnLog('File successfully downloaded t='+TimeToStr(Time)); + MbiCallbackOnDone; + +end; //*** end of OnTimeout *** + + +//*************************************************************************************** +// NAME: MbiInit +// PARAMETER: callback function pointers +// RETURN VALUE: none +// DESCRIPTION: Called by the application to initialize the interface library. +// +//*************************************************************************************** +procedure MbiInit(cbStarted: TStartedEvent; cbProgress: TProgressEvent; + cbDone: TDoneEvent; cbError: TErrorEvent; cbLog: TLogEvent; + cbInfo: TInfoEvent); stdcall; +begin + //--- begin of don't change --- + AppOnStarted := cbStarted; + AppOnProgress := cbProgress; + AppOnDone := cbDone; + AppOnLog := cbLog; + AppOnInfo := cbInfo; + AppOnError := cbError; + //--- end of don't change --- + + // create xcp loader object + loader := TXcpLoader.Create; + + // update to the latest configuration + loader.Configure(ExtractFilePath(ParamStr(0))+'openblt_can_peak.ini'); + + // create and init a timer + events := TEventHandlers.Create; + timer := TTimer.Create(nil); + timer.Enabled := False; + timer.Interval := 100; + timer.OnTimer := events.OnTimeout; +end; //*** end of MbiInit *** + + +//*************************************************************************************** +// NAME: MbiStart +// PARAMETER: filename of the file that is to be downloaded. +// RETURN VALUE: none +// DESCRIPTION: Called by the application to request the interface library to download +// the file that is passed as a parameter. +// +//*************************************************************************************** +procedure MbiStart(fileName: ShortString); stdcall; +begin + // update the user info + MbiCallbackOnInfo(''); + + // start the log + MbiCallbackOnLog('--- Downloading "'+fileName+'" ---'); + + // reset stop request + stopRequest := false; + + // start the startup timer which gives microBoot a chance to paint itself + timer.Enabled := True; + + // store the program's filename + progfile := fileName; +end; //*** end of MbiStart *** + + +//*************************************************************************************** +// NAME: MbiStop +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the application to request the interface library to stop +// a download that could be in progress. +// +//*************************************************************************************** +procedure MbiStop; stdcall; +begin + // set stop request + stopRequest := true; + + // disconnect the transport layer + MbiCallbackOnLog('Disconnecting the transport layer. t='+TimeToStr(Time)); + loader.Disconnect; +end; //*** end of MbiStop *** + + +//*************************************************************************************** +// NAME: MbiDeInit +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the application to uninitialize the interface library. +// +//*************************************************************************************** +procedure MbiDeInit; stdcall; +begin + // release xcp loader object + loader.Free; + + // release the timer and events object + timer.Free; + events.Free; + + //--- begin of don't change --- + AppOnStarted := nil; + AppOnProgress := nil; + AppOnDone := nil; + AppOnLog := nil; + AppOnInfo := nil; + AppOnError := nil; + //--- end of don't change --- +end; //*** end of MbiDeInit *** + + +//*************************************************************************************** +// NAME: MbiName +// PARAMETER: none +// RETURN VALUE: name of the interface library +// DESCRIPTION: Called by the application to obtain the name of the interface library. +// +//*************************************************************************************** +function MbiName : ShortString; stdcall; +begin + Result := 'OpenBLT CAN Peak'; +end; //*** end of MbiName *** + + +//*************************************************************************************** +// NAME: MbiDescription +// PARAMETER: none +// RETURN VALUE: description of the interface library +// DESCRIPTION: Called by the application to obtain the description of the interface +// library. +// +//*************************************************************************************** +function MbiDescription : ShortString; stdcall; +begin + Result := 'OpenBLT using Peak CAN Interface'; +end; //*** end of MbiDescription *** + + +//*************************************************************************************** +// NAME: MbiVersion +// PARAMETER: none +// RETURN VALUE: version number +// DESCRIPTION: Called by the application to obtain the version number of the +// interface library. +// +//*************************************************************************************** +function MbiVersion : Longword; stdcall; +begin + Result := 10000; // v1.00.00 +end; //*** end of MbiVersion *** + + +//*************************************************************************************** +// NAME: MbiVInterface +// PARAMETER: none +// RETURN VALUE: version number of the supported interface +// DESCRIPTION: Called by the application to obtain the version number of the +// Mbi interface uBootInterface.pas (not the interface library). This can +// be used by the application for backward compatibility. +// +//*************************************************************************************** +function MbiVInterface : Longword; stdcall; +begin + Result := 10001; // v1.00.01 +end; //*** end of MbiVInterface *** + + +//*************************************************************************************** +// NAME: MbiConfigure +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the application to enable the user to configure the inter- +// face library through the application. +// +//*************************************************************************************** +procedure MbiConfigure; stdcall; +var + settings : TXcpSettings; +begin + // create xcp settings object + settings := TXcpSettings.Create(ExtractFilePath(ParamStr(0))+'openblt_can_peak.ini'); + + // display the modal configuration dialog + settings.Configure; + + // release the xcp settings object + settings.Free; + + // update to the latest configuration + loader.Configure(ExtractFilePath(ParamStr(0))+'openblt_can_peak.ini'); +end; //*** end of MbiConfigure *** + + +//*************************************************************************************** +// External Declarations +//*************************************************************************************** +exports + //--- begin of don't change --- + MbiInit index 1, + MbiStart index 2, + MbiStop index 3, + MbiDeInit index 4, + MbiName index 5, + MbiDescription index 6, + MbiVersion index 7, + MbiConfigure index 8, + MbiVInterface index 9; + //--- end of don't change --- + +end. +//********************************** end of openblt_can_peak.dpr ************************ diff --git a/Host/Source/interfaces/can/vector/CANIcon.bmp b/Host/Source/interfaces/can/vector/CANIcon.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6ca58cdf8ac60d52fbb6ced81fecd8ecad40ba31 GIT binary patch literal 2446 zcmchYJx;?w5QUc#DK$`}az$!O9Dtsl6Zi^gsZvr#@@ael-vJ~JV!r*!_+@MdBN0~4 zYG(6x-pt$a`uXMkHl*>y{K&83chB!8JTQmwTK-Q?nZ7`p`~99-N87f) z#V9`8!^lJIyYsQ#ZkwiI-S(})7+4MAsj4b8A-sh+pA3kVXAMTfn=L$KU&2FmdN!Ml z@+3?h+S&jZ4r8&^5T2APF-DRcgA=nIyWKAIeHi*emB8>Q#=vTHAyTNjrwCN%&CZWfKb zi3cxhOzp_btdPvG2BWz+yNi7Q$*P;+r`y8CRyWl{jZxH#H`^MF26lGhiLGLH+NGQN z?24tk5ZO+^1$ORO&$YfhnK1E?6Ah??3jgX$nt8hNU4Uxo3N!`QU<~YxRF7M`hC2-3 DijuO8 literal 0 HcmV?d00001 diff --git a/Host/Source/interfaces/can/vector/CANdrvD.pas b/Host/Source/interfaces/can/vector/CANdrvD.pas new file mode 100644 index 00000000..52e0b9d8 --- /dev/null +++ b/Host/Source/interfaces/can/vector/CANdrvD.pas @@ -0,0 +1,740 @@ +unit CANdrvD; +//*************************************************************************************** +// Project Name: TCanDriver component for Borland Delphi +// Description: Encapsulates Vector's CANlib v4.3 into a VCL component +// File Name: CANdrvD.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, CANlibD; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TChannel = ( channel0, channel1 ); + THardware = ( Virtual, CANcardX, CANcardXL, CANcaseXL, CANboardXL, + CANboardXL_Compact, CANac2, CANac2Pci, CANpari, CANdongle, + CANcard, CANcardY, CANcard2, EDICcard ); + TDirection = ( Tx, Rx ); + TCanMsg = packed record + id : LongInt; + dlc : Byte; + data : array [0..MAX_MSG_LEN-1] of Byte; + time : LongInt; + ext : Boolean; + end; + +type + TMessageEvent = procedure( Sender: TObject; Direction: TDirection; Message: TCanMsg ) of object; + TErrorFrameEvent = procedure( Sender: TObject; time: LongInt ) of object; + TBusOffEvent = procedure( Sender: TObject; time: LongInt ) of object; + +type + TCanEventThread = class(TThread) + private + { Private declarations } + FMethod: TThreadMethod; + protected + FEventHndl: LongInt; + procedure Execute; override; + public + property Method : TThreadMethod read FMethod write FMethod; + property EventHandle: LongInt read FEventHndl write FEventHndl; + end; + +type + TCanDriver = class(TComponent) + private + { Private declarations } + FPortHandle : VPortHandle; + FChannelMask : Vaccess; + FPermissionMask: Vaccess; + FCanEventThread: TCanEventThread; + FThreadRunning : boolean; + FEventHandle : LongInt; + function IsThreadRunning: boolean; + procedure ProcessEvents; + procedure CopyMessage(event: Vevent; var msg: TCanMsg); + protected + { Protected declarations } + FBaudRate : LongInt; + FChannel : TChannel; + FHardware : THardware; + FFilterMask : LongInt; + FFilterCode : LongInt; + FPriority : TThreadPriority; + FExtendedId : Boolean; + FOnMessage : TMessageEvent; + FOnErrorFrame: TErrorFrameEvent; + FOnBusOff : TBusOffEvent; + procedure SetBaudRate( Value: LongInt ); + procedure SetChannel( Value: TChannel ); + procedure SetHardware( Value: THardware ); + procedure SetFilterMask( Value: LongInt ); + procedure SetFilterCode( Value: LongInt ); + procedure SetPriority( Value: TThreadPriority ); + procedure SetExtendedId( Value: Boolean ); + public + { Public declarations } + constructor Create( AOwner: TComponent ); override; + destructor Destroy; override; + function Connect: boolean; virtual; + procedure Disconnect; virtual; + function Transmit( Message: TCanMsg): boolean; virtual; + function IsConnected: boolean; virtual; + published + { Published declarations } + property BaudRate : LongInt read FBaudRate write SetBaudRate default 500000; + property Channel : TChannel read FChannel write SetChannel default channel0; + property Hardware : THardware read FHardware write SetHardware default Virtual; + property FilterMask : LongInt read FFilterMask write SetFilterMask default 0; + property FilterCode : LongInt read FFilterCode write SetFilterCode default 0; + property Priority : TThreadPriority read FPriority write SetPriority default tpNormal; + property ExtendedId : Boolean read FExtendedId write SetExtendedId default False; + property OnMessage : TMessageEvent read FOnMessage write FOnMessage; + property OnErrorFrame: TErrorFrameEvent read FOnErrorFrame write FOnErrorFrame; + property OnBusOff : TBusOffEvent read FOnBusOff write FOnBusOff; + end; + + +//*************************************************************************************** +// Prototypes +//*************************************************************************************** +procedure Register; + +implementation +//*************************************************************************************** +// Constants +//*************************************************************************************** +const + Channels: array[channel0..channel1] of integer = ( 0, 1 ); + HardwareTypes: array[Virtual..EDICcard] of integer = ( + HWTYPE_VIRTUAL, HWTYPE_CANCARDX, HWTYPE_CANCARDXL, HWTYPE_CANCASEXL, HWTYPE_CANBOARDXL, + HWTYPE_CANBOARDXL_COMPACT, HWTYPE_CANAC2, HWTYPE_CANAC2PCI, HWTYPE_CANPARI, + HWTYPE_CANDONGLE, HWTYPE_CANCARD, HWTYPE_CANCARDY, HWTYPE_CANCARD2, HWTYPE_EDICCARD); + + +//*************************************************************************************** +// NAME: Execute +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Overriden Execute function for the CanEventThread. Calls and synchro- +// nizes with the TCanDriver.ProcessEvents function. +// +//*************************************************************************************** +procedure TCanEventThread.Execute; +begin + while not Terminated do + begin + if FEventHndl <> 0 then // make sure event is configured + begin + // wait for receive event + WaitForSingleObject(FEventHndl, 1000); + + if Assigned(Method) then // make sure TCanDriver.ProcessEvents is set + Synchronize(Method); // call and synchronize + end; + end; +end; //*** end of Execute *** + + +//*************************************************************************************** +// NAME: Create +// PRECONDITIONS: none +// PARAMETER: AOwner : owner of the component +// RETURN VALUE: none +// DESCRIPTION: Component constructor. Calls TComponent's constructor and initializes +// the private property variables to their default values. +// +//*************************************************************************************** +constructor TCanDriver.Create( AOwner: TComponent ); +begin + // call inherited constructor + inherited Create( AOwner ); + + // set defaults for internal variables + FPortHandle := INVALID_PORTHANDLE; + FChannelMask := 0; + FPermissionMask:= 0; + FThreadRunning := False; + FEventHandle := 0; + + // set defaults for properties + FBaudRate := 500000; + FChannel := channel0; + FHardware := Virtual; + FFilterMask := 0; + FFilterCode := 0; + FPriority := tpNormal; + FExtendedId := False; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Component destructor. Calls TComponent's destructor +// +//*************************************************************************************** +destructor TCanDriver.Destroy; +begin + Disconnect; // close the port and driver + inherited Destroy; // call inherited destructor +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: IsConnected +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: True or False +// DESCRIPTION: Determines whether or not the CAN driver is connected and active +// +//*************************************************************************************** +function TCanDriver.IsConnected: boolean; +begin + if FPortHandle <> INVALID_PORTHANDLE then + Result := True + else + Result := False; +end; //*** end of IsConnected *** + + +//*************************************************************************************** +// NAME: IsThreadRunning +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: True or False +// DESCRIPTION: Determines whether or not the CAN event thread is running +// +//*************************************************************************************** +function TCanDriver.IsThreadRunning: boolean; +begin + if FThreadRunning = True then + Result := True + else + Result := False; +end; //*** end of IsThreadRunning *** + + +//*************************************************************************************** +// NAME: CopyMessage +// PRECONDITIONS: none +// PARAMETER: event: msg tx or rx event information (source) +// msg: buffer to copy message to (destination) +// RETURN VALUE: none +// DESCRIPTION: Copies a CAN message from an event type to a TCanMsg type. +// +//*************************************************************************************** +procedure TCanDriver.CopyMessage(event: Vevent; var msg: TCanMsg); +var + cnt: integer; +begin + if (event.msg.id and EXT_MSG) = EXT_MSG then // 29-bit id? + begin + msg.id := (event.msg.id and not EXT_MSG); // reset ext bit + msg.ext := True; // this is an 29-bit id + end + else + begin + msg.id := event.msg.id; // store id + msg.ext := False; // this is an 11-bit id + end; + msg.dlc := event.msg.dlc; + msg.time := event.timeStamp; + + // copy the data bytes + for cnt :=0 to MAX_MSG_LEN-1 do + begin + if cnt < event.msg.dlc then + msg.data[cnt] := event.msg.data[cnt] + else + msg.data[cnt] := 0; + end; +end; //*** end of CopyMessage *** + + +//*************************************************************************************** +// NAME: SetBaudRate +// PRECONDITIONS: none +// PARAMETER: Value : new baudrate value [0 - 1000000 bps] +// RETURN VALUE: none +// DESCRIPTION: Configures the baudrate +// +// |------------------------------------------------------------------------------------ +// | Update baudrate configuration +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TCanDriver.SetBaudRate( Value: LongInt ); +begin + FBaudRate := Value; // update property +end; //*** end of SetBaudRate *** + + +//*************************************************************************************** +// NAME: SetChannel +// PRECONDITIONS: none +// PARAMETER: Value : channel0 or channel1 +// RETURN VALUE: none +// DESCRIPTION: Configures the used CAN channel +// +// |------------------------------------------------------------------------------------ +// | Update channel configuration +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TCanDriver.SetChannel( Value: TChannel ); +begin + FChannel := Value; +end; //*** end of SetChannel *** + + +//*************************************************************************************** +// NAME: SetHardware +// PRECONDITIONS: none +// PARAMETER: Value : type of CAN hardware (Virtual, CANcardXL, etc.) +// RETURN VALUE: none +// DESCRIPTION: Configures the used CAN hardware +// +// |------------------------------------------------------------------------------------ +// | Update hardware configuration +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TCanDriver.SetHardware( Value: THardware ); +begin + FHardware := Value; +end; //*** end of SetHardware *** + + +//*************************************************************************************** +// NAME: SetFilterMask +// PRECONDITIONS: none +// PARAMETER: Value : acceptance filter mask +// RETURN VALUE: none +// DESCRIPTION: Configures the acceptance filter mask for the CAN channel +// +// |------------------------------------------------------------------------------------ +// | Update filter mask value +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TCanDriver.SetFilterMask( Value: LongInt ); +begin + FFilterMask := Value; +end; //*** end of SetFilterMask *** + + +//*************************************************************************************** +// NAME: SetFilterCode +// PRECONDITIONS: none +// PARAMETER: Value : acceptance filter code +// RETURN VALUE: none +// DESCRIPTION: Configures the acceptance filter code for the CAN channel +// +// |------------------------------------------------------------------------------------ +// | Update filter code value +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TCanDriver.SetFilterCode( Value: LongInt ); +begin + FFilterCode := Value; +end; //*** end of SetFilterCode *** + + +//*************************************************************************************** +// NAME: SetPriority +// PRECONDITIONS: none +// PARAMETER: Value : thread priority +// RETURN VALUE: none +// DESCRIPTION: Configures the priority for the CAN event thread +// +// |------------------------------------------------------------------------------------ +// | y\ Is Thread running? /n +// |------------------------------------------------------------------------------------ +// | Stop Thread | +// | Update Thread priority | Update Thread priority +// | Restart Thread | +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TCanDriver.SetPriority( Value: TThreadPriority ); +begin + if IsThreadRunning then + begin + FCanEventThread.Suspend; // suspend the thread + FPriority := Value; // update the priority + FCanEventThread.Resume; // resume the thread + end + else + begin + FPriority := Value; // update the priority + end; +end; //*** end of SetPriority *** + + +//*************************************************************************************** +// NAME: SetExtendedId +// PRECONDITIONS: none +// PARAMETER: Value : true = support only 29-bit id's, false = support only 11-bit +// RETURN VALUE: none +// DESCRIPTION: Configures the support of extended 29-bit identifiers +// +// |------------------------------------------------------------------------------------ +// | Update extended id support selection +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TCanDriver.SetExtendedId( Value: Boolean ); +begin + FExtendedId := Value; +end; //*** end of SetExtendedId ***/ + + +//*************************************************************************************** +// NAME: Connect +// PRECONDITIONS: Disconnected from CAN bus +// PARAMETER: none +// RETURN VALUE: True or False for succees or error, respectively +// DESCRIPTION: Initializes the CAN driver and synchronizes the hardware with the CAN +// bus. +// +// |------------------------------------------------------------------------------------ +// | y\ Connected? /n +// |------------------------------------------------------------------------------------ +// | Open the driver (ncdOpenDriver) +// | Obtain mask to channel (ncdGetChannelMask) +// | Open the port using this mask (ncdOpenPort) +// |------------------------------------------------------------------------------------ +// | y\ Permission to change settings? /n +// |------------------------------------------------------------------------------------ +// | Configure baudrate (ncdSetChannelBitrate) | +// |------------------------------------------------------------------------------------ +// | Configure acceptance filter (ncdSetChannelAcceptance) +// | Enable error frames and chipstate events (ncdSetReceiveMode) +// | Create synchronizatio object (ncdSetNotification) +// | Reset internal clock (ncdResetClock) +// | Sync to the CAN bus (ncdActivateChannel) +// | Empty transmit and receive queue's (ncdFlushXxxQueue) +// |------------------------------------------------------------------------------------ +// | y\ Errors occurred during init? /n +// |------------------------------------------------------------------------------------ +// | y\ Port opened? /n | +// |-------------------------------------------------------------| Start CAN event thread +// | Close port (ncdClosePort) | | Return TRUE +// |-------------------------------------------------------------| +// | Return FALSE | +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +function TCanDriver.Connect: boolean; +var + vErr : Vstatus; + acc : VsetAcceptance; +label + error; +begin + // reset internal variables + FPortHandle := INVALID_PORTHANDLE; + FChannelMask := 0; + FPermissionMask:= 0; + FThreadRunning := False; + FEventHandle := 0; + + //-------------------------- open the driver ------------------------------------------ + vErr := ncdOpenDriver; + if vErr <> VSUCCESS then goto error; + + //-------------------------- select a channel ----------------------------------------- + FChannelMask := ncdGetChannelMask(HardwareTypes[FHardware], 0, Channels[FChannel]); + if FChannelMask=0 then goto error; + + //-------------------------- open a port ---------------------------------------------- + FPermissionMask := FChannelMask; + vErr := ncdOpenPort(FPortHandle, 'TCanDriver0', FChannelMask, FPermissionMask, + FPermissionMask, 1024); + if vErr <> VSUCCESS then goto error; + + //-------------------------- set baudrate --------------------------------------------- + if FPermissionMask<>0 then + begin + vErr := ncdSetChannelBitrate(FPortHandle, FPermissionMask, FBaudRate); + if vErr <> VSUCCESS then goto error; + end; + + //-------------------------- set the acceptance filter -------------------------------- + acc.mask := FFilterMask; + acc.code := FFilterCode; + if FExtendedId = True then // 29-bit id used? + begin + acc.mask := acc.mask or LongInt(EXT_MSG); + acc.code := acc.code or LongInt(EXT_MSG); + end; + vErr := ncdSetChannelAcceptance(FPortHandle, FChannelMask, acc); + if vErr <> VSUCCESS then goto error; + + //-------------------------- enable error frames and chipstate events ----------------- + vErr := ncdSetReceiveMode(FPortHandle, 0, 0); + if vErr <> VSUCCESS then goto error; + + //-------------------------- create synchronisation object ---------------------------- + FEventHandle := CreateEvent(nil, FALSE, FALSE, nil); + if FEventHandle = 0 then goto error; + vErr := ncdSetNotification(FPortHandle, FEventHandle, 1); + if vErr<>VSUCCESS then goto error; + + //-------------------------- reset the clock ------------------------------------------ + vErr := ncdResetClock(FPortHandle); + if vErr <> VSUCCESS then goto error; + + //-------------------------- sync with bus -------------------------------------------- + vErr := ncdActivateChannel(FPortHandle, FChannelMask); + if vErr <> VSUCCESS then goto error; + + //-------------------------- flush queue's -------------------------------------------- + vErr := ncdFlushReceiveQueue(FPortHandle); + if vErr <> VSUCCESS then goto error; + vErr := ncdFlushTransmitQueue(FPortHandle, FChannelMask); + if vErr <> VSUCCESS then goto error; + + //-------------------------- start CAN event thread ----------------------------------- + FCanEventThread := TCanEventThread.Create(True); // create and suspend + FCanEventThread.FreeOnTerminate := True; // auto free on termination + FCanEventThread.Method := ProcessEvents; // set method + FCanEventThread.FEventHndl := FEventHandle; // set event handle + FCanEventThread.Resume; // start + FThreadRunning := True; + + //-------------------------- success -------------------------------------------------- + Result := True; // successfully initialized the driver + exit; // stop here + + //-------------------------- error occurred ------------------------------------------- + error: + if FEventHandle <> 0 then + CloseHandle(FEventHandle); + if FPortHandle <> INVALID_PORTHANDLE then + begin + ncdClosePort(FPortHandle); + FPortHandle := INVALID_PORTHANDLE; + end; + Result := False; +end; //*** end of Connect *** + + +//*************************************************************************************** +// NAME: Disconnect +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Disconnects the CAN driver +// +// |------------------------------------------------------------------------------------ +// | y\ Connected? /n +// |------------------------------------------------------------------------------------ +// | Deactivate the channel (ncdDeactivateChannel) | +// | Close port (ncdClosePort) | +// |------------------------------------------------------------------------------------ +// | Close the driver (ncdCloseDriver) +// |------------------------------------------------------------------------------------ +// | y\ CAN event thread active? /n +// |------------------------------------------------------------------------------------ +// | Stop CAN event thread | +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +procedure TCanDriver.Disconnect; +begin + if IsConnected = True then begin // are we connected? + ncdDeactivateChannel(FPortHandle, FChannelMask); // deactivate channel + if FEventHandle <> 0 then + CloseHandle(FEventHandle); + ncdClosePort(FPortHandle); // close the port + FPortHandle := INVALID_PORTHANDLE; // invalidate handle + end; + ncdCloseDriver; // close the driver + if IsThreadRunning then + begin + FCanEventThread.FEventHndl := 0; // reset event handle + FCanEventThread.Terminate; // stop + FThreadRunning := False; + end; +end; //*** end of Disconnect *** + + +//*************************************************************************************** +// NAME: Transmit +// PRECONDITIONS: Driver initialized using 'Connect' +// PARAMETER: Message: CAN message that is to be transmitted +// RETURN VALUE: True or False for succees or error, respectively +// DESCRIPTION: Transmits a CAN message. +// +// |------------------------------------------------------------------------------------ +// | y\ Connected? /n +// |------------------------------------------------------------------------------------ +// | Transmit message using ncdTransmit | +// |----------------------------------------------| Return FALSE +// | Return TRUE | +// |------------------------------------------------------------------------------------ +//*************************************************************************************** +function TCanDriver.Transmit( Message: TCanMsg): boolean; +var + vErr : Vstatus; + event : Vevent; + cnt : integer; +begin + // make sure the CAN driver is connected + if not IsConnected then + begin + Result := False; // can't transmit it not connected + exit; // no need to continue + end; + + // configure message as tx with acknowledge + event.tag := V_TRANSMIT_MSG; + event.msg.flags := MSGFLAG_TX; + + // set the message identifier + if Message.ext = True then + event.msg.id := Message.id or LongInt(EXT_MSG) + else + event.msg.id := Message.id; + + // set the data length + event.msg.dlc := Message.dlc; + + // store the data bytes + for cnt :=0 to MAX_MSG_LEN-1 do + begin + event.msg.data[cnt] := Message.data[cnt]; + end; + + vErr := ncdTransmit(FPortHandle, FChannelMask, event); + + if vErr <> VSUCCESS then + Result := False + else + Result := True; +end; //*** end of Transmit *** + + +//*************************************************************************************** +// NAME: ProcessEvents +// PRECONDITIONS: thread running +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the CAN event tread. This function traps and processes CAN +// events for OnMessage, OnBusOff, and OnErrorFrame. +// +//*************************************************************************************** +procedure TCanDriver.ProcessEvents; +var + vErr : Vstatus; + pEvent : PVEvent; + msg : TCanMsg; +begin + while True do + begin + vErr := ncdReceive1(FPortHandle, pEvent); + + if (vErr<>VSUCCESS) and (vErr<>VERR_QUEUE_IS_EMPTY) then break; + if vErr=VERR_QUEUE_IS_EMPTY then break; + + case pEvent^.tag of + V_RECEIVE_MSG, V_TRANSMIT_MSG: + begin + if (pEvent^.msg.flags and MSGFLAG_ERROR_FRAME) = MSGFLAG_ERROR_FRAME then + begin + //---------------- process errorframe ----------------------------------------- + if Assigned( FOnErrorFrame ) then + begin + FOnErrorFrame( Self, pEvent^.timeStamp ); // call application's event handler + end; + end + else if pEvent^.msg.flags = 0 then // msg rx indication + begin + //---------------- process reception indication ------------------------------- + CopyMessage(pEvent^, msg); + if Assigned( FOnMessage ) then + begin + FOnMessage( Self, Rx, msg ); // call application's event handler + end; + end + else if (pEvent^.msg.flags and MSGFLAG_TX) = MSGFLAG_TX then // msg tx confirmation + begin + //---------------- process transmission confirmation -------------------------- + CopyMessage(pEvent^, msg); + if Assigned( FOnMessage ) then + begin + FOnMessage( Self, Tx, msg ); // call application's event handler + end; + end; + end; + V_CHIP_STATE: + begin + if (pEvent^.chipState.busStatus and CHIPSTAT_BUSOFF) = CHIPSTAT_BUSOFF then + begin + //---------------- process bus off event -------------------------------------- + if Assigned( FOnBusOff ) then + begin + FOnBusOff( Self, pEvent^.timeStamp ); // call application's event handler + end; + end; + end; + end; + end; +end; //*** end of ProcessEvents *** + + +//*************************************************************************************** +// NAME: Register +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Registers the TCanDriver component into Borland Delphi's IDE. +// +//*************************************************************************************** +procedure Register; +begin + RegisterComponents('Feaser', [TCanDriver]); +end; //*** end of Register *** + + +end. +//********************************** end of CANdrvD.pas ********************************* + + diff --git a/Host/Source/interfaces/can/vector/CANlibD.pas b/Host/Source/interfaces/can/vector/CANlibD.pas new file mode 100644 index 00000000..e6e6a3af --- /dev/null +++ b/Host/Source/interfaces/can/vector/CANlibD.pas @@ -0,0 +1,959 @@ +unit CANlibD; + +(*---------------------------------------------------------------------------- +| File: +| CANlibD.pas +| Project: +| Unit for Delphi32 samples (V2.0) +| +|----------------------------------------------------------------------------- +| Ported from cantrace.c by Torsten Lang +|----------------------------------------------------------------------------- +| Copyright (c) 1998 BSK Datentechnik GmbH, Kiesacker 14, 35418 Buseck / +| 1998 by Vector Informatik GmbH, Friolzheimer Str. 6, 70499 Stuttgart +| All rights reserved. +| +| BSK Datentechnik rumt der Vector Informatik GmbH das nicht ausschlieliche Recht +| ein, CANlibD.pas fr eigene Zwecke zu nutzen. Vector ist es gestattet, die +| Software zu kopieren, abzundern, zu erweitern, weiterzugeben und in Software von +| Vector zu integrieren. Im Quelltext enthaltene Copyright-Hinweise drfen hierbei +| nicht entfernt oder gendert werden. +| Vector darf aus von ihm vorgenommenen Anpassungen und/oder Erweiterungen der +| CANlibD.pas keine Rechte an irgendwelchen Teilen der Software gegenber BSK +| Datentechnik geltend machen. + ----------------------------------------------------------------------------*) + +{ environment switches } +(******************************************************************************* +Attention: +1. All functions that use pointers to structures (either explicitly or by using + var parameters) may change the contents of the structures right after the + funtction returns. +*******************************************************************************) +{$ifdef WIN32} +{$define CanLib4Delphi32} +{$else} +{$ifdef CONSOLE} +{$define CanLib4Delphi32} +{$endif} +{$endif} + +{ public interface } + +interface + +type + ncdStringType = PChar; + Vstatus = Word; + +const + MAX_APPNAME = 32; + + VCAN_WAIT = 0; + VCAN_POLL = 1; + {$ifdef CanLib4Delphi32} + { Attention: This exists only under Win32 } + VCAN_NOTIFY = 2; + {$endif} + + VSUCCESS = 0; + VPENDING = 1; + VERROR = 255; + VERR_QUEUE_IS_EMPTY = 10; + VERR_QUEUE_IS_FULL = 11; + VERR_TX_NOT_POSSIBLE = 12; + VERR_NO_LICENSE = 14; + VERR_WRONG_PARAMETER = 101; + VERR_TWICE_REGISTER = 110; + VERR_INVALID_CHAN_INDEX = 111; + VERR_INVALID_ACCESS = 112; + VERR_PORT_IS_OFFLINE = 113; + VERR_CHAN_IS_ONLINE = 116; + VERR_INVALID_PORT = 118; + VERR_HW_NOT_READY = 120; + VERR_CMD_TIMEOUT = 121; + VERR_HW_NOT_PRESENT = 129; + VERR_NOTIFY_ALREADY_ACTIVE = 131; + VERR_CANNOT_OPEN_DRIVER = 201; + +{ +//------------------------------------------------------------------------------ +// accessmask +} +type + Vaccess = LongInt; { unsigned long doesn't exist for Delphi32 / Borland Pascal 7! } + +{ +//------------------------------------------------------------------------------ +// porthandle +} + +const + INVALID_PORTHANDLE = -1; + +type + VportHandle = LongInt; + +{ +//------------------------------------------------------------------------------ +// acceptance filter +} + +type + VsetAcceptance = packed record + code : LongInt; {unsigned long doesn't exist!} + mask : LongInt; {unsigned long doesn't exist!} + end; + PVsetAcceptance = ^VsetAcceptance; + +{ +//------------------------------------------------------------------------------ +// bit timing +} + +type + VchipParams = packed record + bitRate : LongInt; {unsigned long doesn't exist!} + sjw : Byte; + tseg1 : Byte; + tseg2 : Byte; + sam : Byte; { 1 or 3 } + end; + PVchipParams = ^VchipParams; + +{ +//------------------------------------------------------------------------------ +// definitions for the events and commands used by the driver +} + +const + V_RECEIVE_MSG = 1; + V_CHIP_STATE = 4; + V_CLOCK_OVERFLOW = 5; + V_TRIGGER = 6; + V_TIMER = 8; + V_TRANSCEIVER = 9; + V_TRANSMIT_MSG = 10; + +type + VeventTag = Byte; + +{ +//------------------------------------------------------------------------------ +// events +} + +{ +//------------------------------------------------------------------------------ +// structure for V_RECEIVE_MSG +} + +const + MAX_MSG_LEN = 8; + EXT_MSG = $80000000; { signs an extended identifier } + + MSGFLAG_ERROR_FRAME = $01; { Msg is a bus error } + MSGFLAG_OVERRUN = $02; { Msgs following this has been lost } + MSGFLAG_NERR = $04; { NERR active during this msg } + MSGFLAG_WAKEUP = $08; { Msg rcv'd in wakeup mode } + MSGFLAG_REMOTE_FRAME = $10; { Msg is a remote frame } + MSGFLAG_RESERVED_1 = $20; { Reserved for future usage } + MSGFLAG_TX = $40; { TX acknowledge } + MSGFLAG_TXRQ = $80; { TX request } + +type + _Vmsg = packed record + id : LongInt; {unsigned long doesn't exist!} + flags : Byte; + dlc : Byte; + data : array [0..MAX_MSG_LEN-1] of Byte; + end; { 14 Bytes } + _PVmsg = ^_Vmsg; + +{ +// structure for V_CHIP_STATE +} + +const + CHIPSTAT_BUSOFF = $01; + CHIPSTAT_ERROR_PASSIVE = $02; + CHIPSTAT_ERROR_WARNING = $04; + CHIPSTAT_ERROR_ACTIVE = $08; + +type + _VchipState = packed record + busStatus : Byte; + txErrorCounter : Byte; + rxErrorCounter : Byte; + end; + _PVchipState = ^_VchipState; + +{ +// structure for V_TRANSCEIVER +} + +const + TRANSCEIVER_EVENT_ERROR = 1; + TRANSCEIVER_EVENT_CHANGED = 2; + + TRANSCEIVER_TYPE_NONE = 0; + TRANSCEIVER_TYPE_251 = 1; + TRANSCEIVER_TYPE_252 = 2; + TRANSCEIVER_TYPE_DNOPTO = 3; + TRANSCEIVER_TYPE_W210 = 4; + + TRANSCEIVER_LINEMODE_NA = 0; + TRANSCEIVER_LINEMODE_TWO_LINE = 1; + TRANSCEIVER_LINEMODE_CAN_H = 2; + TRANSCEIVER_LINEMODE_CAN_L = 3; + + TRANSCEIVER_RESNET_NA = 0; + TRANSCEIVER_RESNET_MASTER = 1; + TRANSCEIVER_RESNET_MASTER_STBY = 2; + TRANSCEIVER_RESNET_SLAVE = 3; + +type + _Vtransceiver = packed record + event : Byte; { TRANSCEIVER_EVENT_xxx } + end; + _PVtransceiver = ^_Vtransceiver; + + Vevent = packed record + tag : VeventTag; { 1 } + chanIndex : Byte; { 1 } + _transId : Byte; { 1 not implemented yet !!!! } + portHandle : Byte; { 1 internal use only !!!! } + timeStamp : LongInt; { 4 } { unsigned long doesn't exist! } + case {tagData:}Byte of + 0 : (msg : _Vmsg); + 1 : (chipState : _VchipState); + 2 : (transceiver : _Vtransceiver); + { 14 Bytes (_VMessage) } + end; + { -------- } + { 22 Bytes } + PVevent = ^Vevent; + +{ +//------------------------------------------------------------------------------ +// structure for SET_OUTPUT_MODE +} + +const + OUTPUT_MODE_SILENT = 0; + OUTPUT_MODE_NORMAL = 1; + +{ +//------------------------------------------------------------------------------ +// configuration +} + +{ +// defines for the supported hardware +} +const + HWTYPE_NONE = 0; + HWTYPE_VIRTUAL = 1; + HWTYPE_CANCARDX = 2; + HWTYPE_CANPARI = 3; + HWTYPE_CANDONGLE = 4; + HWTYPE_CANAC2 = 5; + HWTYPE_CANAC2PCI = 6; + HWTYPE_CANCARD = 7; + HWTYPE_CANCARDY = 12; + HWTYPE_CANCARDXL = 15; + HWTYPE_CANCARD2 = 17; + HWTYPE_EDICCARD = 19; + HWTYPE_CANCASEXL = 21; + HWTYPE_CANBOARDXL = 25; + HWTYPE_CANBOARDXL_COMPACT = 27; + MAX_HWTYPE = 27; + +{ +// defines for the tranceiver type +} +const + (* + TRANSCEIVER_TYPE_NONE = 0; + TRANSCEIVER_TYPE_251 = 1; + TRANSCEIVER_TYPE_252 = 2; + TRANSCEIVER_TYPE_DNOPTO = 3; + TRANSCEIVER_TYPE_W210 = 4; + *) { These have already been defined above } + MAX_TRANSCEIVER_TYPE = 4; + + MAX_CHAN_NAME = 31; + MAX_DRIVER_NAME = 31; + +type + VChannelConfig = packed record + name : array [0..MAX_CHAN_NAME] of Char; + hwType : Byte; { HWTYPE_xxxx (see above) } + hwIndex : Byte; { Index of the hardware (same type) (0,1,...) } + hwChannel : Byte; { Index of the channel (same hardware) (0,1,...) } + tranceiverType : Byte; { TRANCEIVER_TYPE_xxxx (see above) } + channelIndex : Byte; { Global channel index (0,1,...) } + channelMask : LongInt; { Global channel mask (=1<PdJbpj z>`vaix%czA@6Mgs``(>g^K(K=s4-eA2z6^#M8geDtGUIc2P!#EXbdkd6m)U)DW1C^pZwtBa%~%NUu|43FotZ%xH3z zaJ*2bi0z0c`wHSFXDRlQv(!z7=`7<-;o07*w4p_%7m=^HQHmL99WAO64blIGkK;T- zwPYw_@^{d#UXAy7TL$0x@GXPyZ1_63J7CXoE#`T0VDA1idi5rJIPNBp07Zc(ub=nr z+0)$IeD0G^^PZhLzpYxe3c~887k_z!c~-1g0X!Y)^#7md+bg5T4qiO@;lRj1o*U`v z(A6)_4h~-$wHrEgdEnSbM-S|O@6bO!xH32dr|jc7e)L$^>#x7Fd-uf)Uo$O^JMfpU zmKOC^x(=_Ndvy07zW8p$WP?WUzOP%#k1yj7uUmX<_|g?nx;lJiM_1R}va+J0BB#^o za=A9W{4(RwlN&~dhVQ-iUhtvA;kfh8JGX7!Iy#IMIqu&dT>^%O1BaJzy_H41zfGO~ zZUkGuf7h1}dV7~}(0@2G_sHPa!_cY7GGGG?&-2r#PoFt+=FaXn7|#YR3A&1++op&S9OjVdr6|zP&OM4u?VIsVASZ@xb}d&kWSx(_7B< z)&+Zn2adn?tFv|`@CGP#@AwnzWR1K$aQ4r;-UOBV@4r8r=k(D_Pd{}0(b5lrs%7bs zo;{g>0as9$zq@xIgJ+GE@)g*Yn5C zr7O(`HaADJgmXz=0gR1ApHSp#?#>>y4doSpX9R_Pp~>AP|6109SJygw|H& z)0bmsAHN-k@QS;7FMcs}WnlQ3#}2~bGIwwCiM}11KN}qyfe@NEZyr#2ypzPP0c;@}g;Nmq)m7D+sz&M~G&sYxwGcNP_e!DP6>XM8>gsju%jbcm@ytn7a4 zEfkM8tZ8_5{rWd|?qqjBb{sH`DR10*Jn&2uB4R6&d9q(dbG*k%j(3}x<1Mptyb_iJ z`{LGy0UAXW$-bm2hcyjyN{YdeY&zheAdnARC}r*{S!!23UQw>r3`0}=)#wEzH>5$; z!?(V$MpKbj5L-#+>Lkfy8pKq0tD!d3Q}9M&pw~38-h!UZ40JZsdumXdn3fHn4b0P^ zLXsYP-s2}=q@7{#L1#!*V@M_}uD_BoI47Xtsd$FL!5F47Fq4HV21m7{5KIDeO%5b8 zZJWcKT&}-d0f)aTW=Jm}tnJ|qu@y)&KBSWln+2Rt0PjT;2pOg@^U91+)tVp}&?dE~ zbrH`8{3NxnQ{!l((_!WN9x0|_M^L+N<%IvlHTyGS%a$!29UZW@Z{6M9*DGU}r|oMQ z9>D%l_BLnEoVK<$=x2J9kzvC2hK;AJtc+{pxJ?}1TMZz#^Grs@4$s;)95a0s+rU0t9x4iC7+4w<)|Ba<8Q zw5r9K>ie6P1hCSG68*HIhc+7Zmtenh9s0=7#Y<6p9hx{0x z9Ixl)$tz>}t-sq0dGb(Ux5XG95YLNk?;KBtxf%pugG1^x&?P)@M12fn2RFmsE_HUO|IMLpgj>WJo# z_mEuu=Vq>6&Y*o{8lb>3v}c+jHsM9|Rq2!g94ue;Sx65vd_OijA*wLrpzuE>@M}%@ zh1Ub`HGwkd*!pTQ9dCk_a|+KBc+G@wxE}aYj09;m3eK-@O{NxPXi9)a&|&Fbk&L=H zC30gT*FiJ?cSac#^TutKO0cdbI6r|l+7RjVt=tZEb^@pwO(=$7N?}Lx2_a2s)vC3P zftb>2d7dIZNxblo=>^TQZI+uBNv6e8HM*9p(K^(Klrl=JgOHY14X58U`uDZ{NSFf z5TxFT{xI)2C-jcbBnmDD`)Sw*%Wa0ix(gVVK(XiHx|PHdt+g8s1hcug6;@A?u-azD z!UpTo&0t|wx;BM^mKp>^Dl=?YGj$8KamfgvxRHHd&@rp#m{kjQRz?}7?o_!1l&#RU z%p&Tp{gzqz^ouP0V$e6^HCz46MCy1cHZv3Uz_hth*9+E^3)0zi+ z@jMu6h30K_D^G-Py_KyS@$)$rbBg>{sC4C{uqox~lrjtDr-j!!2d{@>?7^jg@gyKJ|N1ef%NW@B7 z{gAZce(0vaci5*;u6+#HmN7%d3U5l0Vizt&RqI+uicUjaXJ{$vK{Ma3u=4Fp#mh^@ z7cI(U;Mv6}dfqBVWm02YB!VQDWyZyLNP?swEp4P&c@UfgLiv2OoegEY)dCD?n1I3g zN(xHJ=9^_!hP{LW7cy*iBmCgT&AWqsu!+~DI7Q?Z)K}a}jkuNrSCCHf`mxnbh%i zSY}s5H6Cn2sidaD+O$xfshkif^FI+P2-Fj1N-T|qniVxf-N387?YgKaP;Uqd6**Xy zH1iA-tmjOu=CN3%wYmtltVW8acLs&Z9GImPhE$7OubS)9uC6?(@f_0}3(6cSGJ?X= z9MI(y^bu^EYp1o?{p?udW>%+DoxydY1R#)S>p@{TK+)BAH(q_G&UfvlvxsHpFj*}w zdk$jLqn@_()=Z!Wg$SD-^{S=UHh~_i5)eD78!f$GPoT$26GV@C%G3k5PoM~81&#{{ z4N0WZf9&yVnWp*5AXGzm_rgVSS?0r%4DTiK57u<5q9VnD5lMX>cC9*;lu#--pGYlu riTrt~N|uA5K>HWs-i2;KGN9r#Gm2!WG-OQ`$<=ioBiF>W4V(2p%_OJ^ literal 0 HcmV?d00001 diff --git a/Host/Source/interfaces/can/vector/XcpSettings.pas b/Host/Source/interfaces/can/vector/XcpSettings.pas new file mode 100644 index 00000000..5707cbfe --- /dev/null +++ b/Host/Source/interfaces/can/vector/XcpSettings.pas @@ -0,0 +1,289 @@ +unit XcpSettings; +//*************************************************************************************** +// Description: XCP settings interface for CAN +// File Name: XcpSettings.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, ComCtrls, ExtCtrls, IniFiles; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TXcpSettingsForm = class(TForm) + pnlFooter: TPanel; + btnOK: TButton; + btnCancel: TButton; + pageControl: TPageControl; + tabXcp: TTabSheet; + tabCan: TTabSheet; + iconCan: TImage; + lblCan: TLabel; + lblXcp: TLabel; + iconXcp2: TImage; + lblHardware: TLabel; + cmbHardware: TComboBox; + lblChannel: TLabel; + cmbChannel: TComboBox; + lblBaudRate: TLabel; + chbExtendedId: TCheckBox; + edtBaudRate: TEdit; + lblT1: TLabel; + lblT3: TLabel; + lblT4: TLabel; + lblT5: TLabel; + lblT7: TLabel; + edtT1: TEdit; + edtT3: TEdit; + edtT4: TEdit; + edtT5: TEdit; + edtT7: TEdit; + tabProt: TTabSheet; + iconXcp1: TImage; + lblPort: TLabel; + edtSeedKey: TEdit; + btnBrowse: TButton; + lblTransmitId: TLabel; + Label1: TLabel; + edtTransmitId: TEdit; + edtReceiveId: TEdit; + openDialog: TOpenDialog; + procedure btnOKClick(Sender: TObject); + procedure btnCancelClick(Sender: TObject); + procedure btnBrowseClick(Sender: TObject); + private + { Private declarations } + public + { Public declarations } + end; + +type + TXcpSettings = class(TObject) + private + FSettingsForm : TXcpSettingsForm; + FIniFile : string; + public + constructor Create(iniFile : string); + destructor Destroy; override; + function Configure : Boolean; + end; + + +implementation +{$R *.DFM} +//*************************************************************************************** +// NAME: btnOKClick +// PARAMETER: none +// RETURN VALUE: modal result +// DESCRIPTION: Sets the module result to okay. +// +//*************************************************************************************** +procedure TXcpSettingsForm.btnOKClick(Sender: TObject); +begin + ModalResult := mrOK; +end; //*** end of btnOKClick *** + + +//*************************************************************************************** +// NAME: btnCancelClick +// PARAMETER: none +// RETURN VALUE: modal result +// DESCRIPTION: Sets the module result to cancel. +// +//*************************************************************************************** +procedure TXcpSettingsForm.btnCancelClick(Sender: TObject); +begin + ModalResult := mrCancel; +end; //*** end of btnCancelClick *** + + +//*************************************************************************************** +// NAME: btnBrowseClick +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Prompts the user to select the seed/key dll file. +// +//*************************************************************************************** +procedure TXcpSettingsForm.btnBrowseClick(Sender: TObject); +begin + openDialog.InitialDir := ExtractFilePath(ParamStr(0)); + if openDialog.Execute then + begin + edtSeedKey.Text := openDialog.FileName; + end; +end; //*** end of btnBrowseClick *** + + +//*************************************************************************************** +// NAME: Create +// PARAMETER: Name of the INI file where the settings are and will be stored +// RETURN VALUE: none +// DESCRIPTION: Class constructor +// +//*************************************************************************************** +constructor TXcpSettings.Create(iniFile : string); +begin + // call inherited constructor + inherited Create; + + // set the inifile + FIniFile := iniFile; + + // create an instance of the settings form + FSettingsForm := TXcpSettingsForm.Create(nil); +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class destructor +// +//*************************************************************************************** +destructor TXcpSettings.Destroy; +begin + // releaase the settings form object + FSettingsForm.Free; + + // call inherited destructor + inherited; +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: Configure +// PARAMETER: none +// RETURN VALUE: True if configuration was successfully changed, False otherwise +// DESCRIPTION: Allows the user to configure the XCP interface using a GUI. +// +//*************************************************************************************** +function TXcpSettings.Configure : Boolean; +var + settingsIni: TIniFile; +begin + // initialize the return value + result := false; + + // init the form elements using the configuration found in the INI + if FileExists(FIniFile) then + begin + // create ini file object + settingsIni := TIniFile.Create(FIniFile); + + // CAN related elements + FSettingsForm.cmbHardware.ItemIndex := settingsIni.ReadInteger('can', 'hardware', 0); + FSettingsForm.cmbChannel.ItemIndex := settingsIni.ReadInteger('can', 'channel', 0); + FSettingsForm.edtBaudRate.Text := IntToStr(settingsIni.ReadInteger('can', 'baudrate', 500)); + FSettingsForm.chbExtendedId.Checked := settingsIni.ReadBool('can', 'extended', false); + FSettingsForm.edtTransmitId.Text := Format('%x',[settingsIni.ReadInteger('can', 'txid', $667)]); + FSettingsForm.edtReceiveId.Text := Format('%x',[settingsIni.ReadInteger('can', 'rxid', $7e1)]); + + // XCP related elements + FSettingsForm.edtSeedKey.Text := settingsIni.ReadString('xcp', 'seedkey', ''); + FSettingsForm.edtT1.Text := IntToStr(settingsIni.ReadInteger('xcp', 't1', 1000)); + FSettingsForm.edtT3.Text := IntToStr(settingsIni.ReadInteger('xcp', 't3', 2000)); + FSettingsForm.edtT4.Text := IntToStr(settingsIni.ReadInteger('xcp', 't4', 10000)); + FSettingsForm.edtT5.Text := IntToStr(settingsIni.ReadInteger('xcp', 't5', 1000)); + FSettingsForm.edtT7.Text := IntToStr(settingsIni.ReadInteger('xcp', 't7', 2000)); + + // release ini file object + settingsIni.Free; + end + else + begin + // set defaults + // CAN related elements + FSettingsForm.cmbHardware.ItemIndex := 0; + FSettingsForm.cmbChannel.ItemIndex := 0; + FSettingsForm.edtBaudRate.Text := IntToStr(500); + FSettingsForm.chbExtendedId.Checked := false; + FSettingsForm.edtTransmitId.Text := Format('%x',[$667]); + FSettingsForm.edtReceiveId.Text := Format('%x',[$7e1]); + + // XCP related elements + FSettingsForm.edtSeedKey.Text := ''; + FSettingsForm.edtT1.Text := IntToStr(1000); + FSettingsForm.edtT3.Text := IntToStr(2000); + FSettingsForm.edtT4.Text := IntToStr(10000); + FSettingsForm.edtT5.Text := IntToStr(1000); + FSettingsForm.edtT7.Text := IntToStr(2000); + + end; + + // show the form as modal so we can get the result here + if FSettingsForm.ShowModal = mrOK then + begin + if FIniFile <> '' then + begin + // create ini file object + settingsIni := TIniFile.Create(FIniFile); + + // CAN related elements + settingsIni.WriteInteger('can', 'hardware', FSettingsForm.cmbHardware.ItemIndex); + settingsIni.WriteInteger('can', 'channel', FSettingsForm.cmbChannel.ItemIndex); + settingsIni.WriteInteger('can', 'baudrate', StrToInt(FSettingsForm.edtBaudRate.Text)); + settingsIni.WriteBool('can', 'extended', FSettingsForm.chbExtendedId.Checked); + settingsIni.WriteInteger('can', 'txid', StrToInt('$'+FSettingsForm.edtTransmitId.Text)); + settingsIni.WriteInteger('can', 'rxid', StrToInt('$'+FSettingsForm.edtReceiveId.Text)); + + // XCP related elements + settingsIni.WriteString('xcp', 'seedkey', FSettingsForm.edtSeedKey.Text); + settingsIni.WriteInteger('xcp', 't1', StrToInt(FSettingsForm.edtT1.Text)); + settingsIni.WriteInteger('xcp', 't3', StrToInt(FSettingsForm.edtT3.Text)); + settingsIni.WriteInteger('xcp', 't4', StrToInt(FSettingsForm.edtT4.Text)); + settingsIni.WriteInteger('xcp', 't5', StrToInt(FSettingsForm.edtT5.Text)); + settingsIni.WriteInteger('xcp', 't7', StrToInt(FSettingsForm.edtT7.Text)); + + // release ini file object + settingsIni.Free; + + // indicate that the settings where successfully updated + result := true; + end; + end; +end; //*** end of Configure *** + + +end. +//******************************** end of XcpSettings.pas ******************************* + + diff --git a/Host/Source/interfaces/can/vector/XcpTransport.pas b/Host/Source/interfaces/can/vector/XcpTransport.pas new file mode 100644 index 00000000..5d61293b --- /dev/null +++ b/Host/Source/interfaces/can/vector/XcpTransport.pas @@ -0,0 +1,398 @@ +unit XcpTransport; +//*************************************************************************************** +// Description: XCP transport layer for CAN. +// File Name: XcpTransport.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Forms, CANdrvD, IniFiles; + + +//*************************************************************************************** +// Global Constants +//*************************************************************************************** +const kMaxPacketSize = 256; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TXcpTransportInfo = (kNone, kResponse, kError); + + +type + TXcpTransport = class(TObject) + private + comEventInfo : TXcpTransportInfo; + comEvent : THandle; + packetTxId : LongWord; + packetRxId : Longword; + extendedId : Boolean; + procedure OnCanMessage(Sender: TObject; Direction: TDirection; Message: TCanMsg); + procedure OnBusOff(Sender: TObject; time: LongInt); + function MsgWaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; + public + packetData : array[0..kMaxPacketSize-1] of Byte; + packetLen : Word; + canDriver : TCanDriver; + constructor Create; + procedure Configure(iniFile : string); + procedure Connect; + function SendPacket(timeOutms: LongWord): Boolean; + procedure Disconnect; + destructor Destroy; override; + end; + + +implementation + +//*************************************************************************************** +// NAME: Create +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class constructore +// +//*************************************************************************************** +constructor TXcpTransport.Create; +begin + // call inherited constructor + inherited Create; + + // reset can event info + comEventInfo := kNone; + + // create the event that requires manual reset + comEvent := CreateEvent(nil, True, False, nil); + + if comEvent = 0 then + Application.MessageBox( 'Could not obtain event placeholder.', + 'Error', MB_OK or MB_ICONERROR ); + + // create a can driver instance + canDriver := TCanDriver.Create(nil); + + // set can driver event handlers + canDriver.OnMessage := OnCanMessage; + canDriver.OnBusOff := OnBusOff; + + + // reset the packet ids + packetTxId := 0; + packetRxId := 0; + + // use standard id's by default + extendedId := false; + + // reset packet length + packetLen := 0; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class destructor +// +//*************************************************************************************** +destructor TXcpTransport.Destroy; +begin + // release can driver instances + canDriver.Free; + + // release event handle + CloseHandle(comEvent); + + // call inherited destructor + inherited; +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: Configure +// PARAMETER: filename of the INI +// RETURN VALUE: none +// DESCRIPTION: Configures both this class from the settings in the INI. +// +//*************************************************************************************** +procedure TXcpTransport.Configure(iniFile : string); +var + settingsIni : TIniFile; + hwIndex : integer; +begin + // read XCP configuration from INI + if FileExists(iniFile) then + begin + // create ini file object + settingsIni := TIniFile.Create(iniFile); + + // set message configuration + packetTxId := settingsIni.ReadInteger('can', 'txid', $667); + packetRxId := settingsIni.ReadInteger('can', 'rxid', $7e1); + extendedId := settingsIni.ReadBool('can', 'extended', false); + + // configure can hardware + hwIndex := settingsIni.ReadInteger('can', 'hardware', 0); + canDriver.Hardware := Virtual; // init to virtual channel + case hwIndex of + 0 : canDriver.Hardware := Virtual; + 1 : canDriver.Hardware := CANcardX; + 2 : canDriver.Hardware := CANcardXL; + 3 : canDriver.Hardware := CANcaseXL; + 4 : canDriver.Hardware := CANboardXL; + 5 : canDriver.Hardware := CANboardXL_Compact; + 6 : canDriver.Hardware := CANac2; + 7 : canDriver.Hardware := CANac2Pci; + 8 : canDriver.Hardware := CANpari; + 9 : canDriver.Hardware := CANdongle; + 10: canDriver.Hardware := CANcard; + 11: canDriver.Hardware := CANcardY; + 12: canDriver.Hardware := CANcard2; + 13: canDriver.Hardware := EDICcard; + end; + + // configure baudrate + canDriver.BaudRate := settingsIni.ReadInteger('can', 'baudrate', 500) * 1000; + + if settingsIni.ReadInteger('can', 'channel', 0) = 0 then + canDriver.Channel := channel0 + else + canDriver.Channel := channel1; + + // release ini file object + settingsIni.Free; + end; +end; //*** end of Configure *** + + +//*************************************************************************************** +// NAME: Connect +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Connects the transport layer device. +// +//*************************************************************************************** +procedure TXcpTransport.Connect; +begin + if not canDriver.Connect then + Application.MessageBox( 'Could not connect to CAN bus.', + 'Error', MB_OK or MB_ICONERROR ); +end; //*** end of Connect *** + + +//*************************************************************************************** +// NAME: SendPacket +// PARAMETER: the time[ms] allowed for the reponse from the slave to come in. +// RETURN VALUE: True if response received from slave, False otherwise +// DESCRIPTION: Sends the XCP packet using the data in 'packetData' and length in +// 'packetLen' and waits for the response to come in. +// +//*************************************************************************************** +function TXcpTransport.SendPacket(timeOutms: LongWord): Boolean; +var + msg: TCanMsg; + cnt : byte; + waitResult: Integer; +begin + // prepare the packet + msg.id := LongInt(PacketTxId); + msg.dlc := packetLen; + msg.ext := extendedId; + for cnt := 0 to packetLen-1 do + begin + msg.data[cnt] := packetData[cnt]; + end; + + // make sure the event is reset + ResetEvent(comEvent); + comEventInfo := kNone; + + // submit the packet transmission request + if not canDriver.Transmit(msg) then + begin + // unable to submit tx request + result := False; + Exit; + end; + + // packet is being transmitted. Now wait for the response to come in + waitResult := MsgWaitForSingleObject(comEvent, timeOutms); + + if waitResult <> WAIT_OBJECT_0 then + begin + // no com event triggered so either a timeout or internal error occurred + result := False; + Exit; + end; + + // com event was triggered. now check if the reponse was correctly received + if comEventInfo <> kResponse then + begin + result := False; + Exit; + end; + + // packet successfully transmitted and response packet received + result := True; +end; //*** end of SendPacket *** + + +//*************************************************************************************** +// NAME: Disconnect +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Disconnects the transport layer device. +// +//*************************************************************************************** +procedure TXcpTransport.Disconnect; +begin + canDriver.Disconnect; +end; //*** end of Disconnect *** + + +//*************************************************************************************** +// NAME: OnCanMessage +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Can message event handler +// +//*************************************************************************************** +procedure TXcpTransport.OnCanMessage( Sender: TObject; Direction: TDirection; Message: TCanMsg ); +var + cnt : integer; +begin + // the event we are interested in is the reception of the command response from + // slave. + if Direction = Rx then + begin + if Message.id = LongInt(PacketRxId) then + begin + // store response data + for cnt := 0 to Message.dlc-1 do + begin + packetData[cnt] := Message.data[cnt]; + end; + + // store response length + packetLen := Message.dlc; + + // set event flag + comEventInfo := kResponse; + + // trigger the event + SetEvent(comEvent); + end; + end; +end; //*** end of OnCanMessage *** + + +//*************************************************************************************** +// NAME: OnBusOff +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Bus off event handler +// +//*************************************************************************************** +procedure TXcpTransport.OnBusOff(Sender: TObject; time: LongInt); +begin + // set error event flag + comEventInfo := kError; + + // trigger the event + SetEvent(comEvent); +end; //*** end of OnBusOff *** + + +//*************************************************************************************** +// NAME: MsgWaitForSingleObject +// PRECONDITIONS: none +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Improved version of WaitForSingleObject. This version actually +// processes messages in the queue instead of blocking them. +// +//*************************************************************************************** +function TXcpTransport.MsgWaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; +var + dwEnd:DWord; +begin + // compute the time when the WaitForSingleObject is supposed to time out + dwEnd := GetTickCount + dwMilliseconds; + + repeat + // wait for an event to happen or a message to be in the queue + result := MsgWaitForMultipleObjects(1, hHandle, False, dwMilliseconds, QS_ALLINPUT); + + // a message was in the queue? + if result = WAIT_OBJECT_0 + 1 then + begin + // process these messages + Application.ProcessMessages; + + // check for timeout manually because if a message in the queue occurred, the + // MsgWaitForMultipleObjects will be called again and the timer will start from + // scratch. we need to make sure the correct timeout time is used. + dwMilliseconds := GetTickCount; + if dwMilliseconds < dwEnd then + begin + dwMilliseconds := dwEnd - dwMilliseconds; + end + else + begin + // timeout occured + result := WAIT_TIMEOUT; + Break; + end; + end + else + // the event occured? + begin + // we can stop + Break; + end; + until True = False; +end; //*** end of MsgWaitForSingleObject *** + + +end. +//******************************** end of XcpTransport.pas ****************************** + diff --git a/Host/Source/interfaces/can/vector/openblt_can_vector.cfg b/Host/Source/interfaces/can/vector/openblt_can_vector.cfg new file mode 100644 index 00000000..b7fa021f --- /dev/null +++ b/Host/Source/interfaces/can/vector/openblt_can_vector.cfg @@ -0,0 +1,35 @@ +-$A+ +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J+ +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-E../../../../ +-LNc:\program files (x86)\borland\delphi4\Lib diff --git a/Host/Source/interfaces/can/vector/openblt_can_vector.dof b/Host/Source/interfaces/can/vector/openblt_can_vector.dof new file mode 100644 index 00000000..223c7e52 --- /dev/null +++ b/Host/Source/interfaces/can/vector/openblt_can_vector.dof @@ -0,0 +1,86 @@ +[Compiler] +A=1 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=1 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir=../../../../ +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages=Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40 +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1031 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +$(DELPHI)\Lib\dclusr40.bpl=Borland User +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlOutputDirectorry] +Count=1 +Item0=../../../../ diff --git a/Host/Source/interfaces/can/vector/openblt_can_vector.dpr b/Host/Source/interfaces/can/vector/openblt_can_vector.dpr new file mode 100644 index 00000000..e11e8d5b --- /dev/null +++ b/Host/Source/interfaces/can/vector/openblt_can_vector.dpr @@ -0,0 +1,605 @@ +library openblt_can_vector; +//*************************************************************************************** +// Project Name: MicroBoot Interface for Borland Delphi +// Description: XCP - CAN interface for MicroBoot supporting Vector CAN +// File Name: openblt_can_vector.dpr +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, + Messages, + Graphics, + Controls, + Forms, + Dialogs, + SysUtils, + Classes, + Extctrls, + XcpProtection in '..\..\XcpProtection.pas', + SRecReader in '..\..\SRecReader.pas', + XcpDataFile in '..\..\XcpDataFile.pas', + XcpLoader in '..\..\XcpLoader.pas', + XcpTransport in 'XcpTransport.pas', + CANdrvD in 'CANdrvD.pas', + CANlibD in 'CANlibD.pas', + XcpSettings in 'XcpSettings.pas' {XcpSettingsForm}; + + +//*************************************************************************************** +// Global Constants +//*************************************************************************************** +const kMaxProgLen = 256; // maximum number of bytes to progam at one time + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +// DLL Interface Callbacks - modifications requires potential update of all interfaces! +type + TStartedEvent = procedure(length: Longword) of object; + TProgressEvent = procedure(progress: Longword) of object; + TDoneEvent = procedure of object; + TErrorEvent = procedure(error: ShortString) of object; + TLogEvent = procedure(info: ShortString) of object; + TInfoEvent = procedure(info: ShortString) of object; + +type + TEventHandlers = class // create a dummy class + procedure OnTimeout(Sender: TObject); + end; + +//*************************************************************************************** +// Global Variables +//*************************************************************************************** +var + //--- begin of don't change --- + AppOnStarted : TStartedEvent; + AppOnProgress : TProgressEvent; + AppOnDone : TDoneEvent; + AppOnError : TErrorEvent; + AppOnLog : TLogEvent; + AppOnInfo : TInfoEvent; + //--- end of don't change --- + timer : TTimer; + events : TEventHandlers; + loader : TXcpLoader; + datafile : TXcpDataFile; + progdata : array of Byte; + progfile : string; + stopRequest : boolean; + + +//*************************************************************************************** +// NAME: MbiCallbackOnStarted +// PARAMETER: length of the file that is being downloaded. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnStarted(length: Longword); +begin + if Assigned(AppOnStarted) then + begin + AppOnStarted(length); + end; +end; //** end of MbiCallbackOnStarted *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnProgress +// PARAMETER: progress of the file download. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnProgress(progress: Longword); +begin + if Assigned(AppOnProgress) then + begin + AppOnProgress(progress); + end; +end; //** end of MbiCallbackOnProgress *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnDone +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnDone; +begin + if Assigned(AppOnDone) then + begin + AppOnDone; + end; +end; //** end of MbiCallbackOnDone *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnError +// PARAMETER: info about the error that occured. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnError(error: ShortString); +begin + if Assigned(AppOnError) then + begin + AppOnError(error); + end; +end; //** end of MbiCallbackOnError *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnLog +// PARAMETER: info on the log event. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnLog(info: ShortString); +begin + if Assigned(AppOnLog) then + begin + AppOnLog(info); + end; +end; //** end of MbiCallbackOnLog *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnInfo +// PARAMETER: details on the info event. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnInfo(info: ShortString); +begin + if Assigned(AppOnInfo) then + begin + AppOnInfo(info); + end; +end; //** end of MbiCallbackOnLog *** + + +//*************************************************************************************** +// NAME: LogData +// PARAMETER: pointer to byte array and the data length +// RETURN VALUE: none +// DESCRIPTION: Writes the program data formatted to the logfile +// +//*************************************************************************************** +procedure LogData(data : PByteArray; len : longword); stdcall; +var + currentWriteCnt : byte; + cnt : byte; + logStr : string; + bufferOffset : longword; +begin + bufferOffset := 0; + + while len > 0 do + begin + // set the current write length optimized to log 32 bytes per line + currentWriteCnt := len mod 32; + if currentWriteCnt = 0 then currentWriteCnt := 32; + logStr := ''; + + // prepare the line to add to the log + for cnt := 0 to currentWriteCnt-1 do + begin + logStr := logStr + Format('%2.2x ', [data[bufferOffset+cnt]]); + end; + + // update the log + MbiCallbackOnLog(logStr); + + // update loop variables + len := len - currentWriteCnt; + bufferOffset := bufferOffset + currentWriteCnt; + end; +end; //*** end of LogData *** + + +//*************************************************************************************** +// NAME: OnTimeout +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Timer event handler. A timer is used in this example to simulate the +// progress of a file download. It also demonstrates how to use the +// application callbacks to keep the application informed. +// +//*************************************************************************************** +procedure TEventHandlers.OnTimeout(Sender: TObject); +var + errorInfo : string; + progress : longword; + regionCnt : longword; + currentWriteCnt : word; + bufferOffset : longword; + addr : longword; + len : longword; + dataSizeKB : real; +begin + timer.Enabled := False; + + // connect the transport layer + MbiCallbackOnLog('Connecting the transport layer. t='+TimeToStr(Time)); + loader.Connect; + + //---------------- start the programming session -------------------------------------- + MbiCallbackOnLog('Starting the programming session. t='+TimeToStr(Time)); + if not loader.StartProgrammingSession then + begin + // update the user info + MbiCallbackOnInfo('Could not connect. Please reset your target...'); + MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+TimeToStr(Time)); + Application.ProcessMessages; + end; + + while not loader.StartProgrammingSession do + begin + Application.ProcessMessages; + Sleep(5); + if stopRequest then + begin + MbiCallbackOnError('Programming session cancelled by user.'); + Exit; + end; + end; + + // still here so programming session was started + MbiCallbackOnLog('Programming session started. t='+TimeToStr(Time)); + + // create the datafile object + datafile := TXcpDataFile.Create(progfile); + + // compute the size in kbytes + dataSizeKB := datafile.GetDataCnt / 1024; + + // Call application callback when we start the actual download + MbiCallbackOnStarted(datafile.GetDataCnt); + + // Init progress to 0 progress + progress := 0; + MbiCallbackOnProgress(progress); + + //---------------- next clear the memory regions -------------------------------------- + // update the user info + MbiCallbackOnInfo('Erasing memory...'); + + for regionCnt := 0 to datafile.GetRegionCnt-1 do + begin + // obtain the region info + datafile.GetRegionInfo(regionCnt, addr, len); + + // erase the memory + MbiCallbackOnLog('Clearing Memory '+Format('addr:0x%x,len:0x%x',[addr,len])+'. t='+TimeToStr(Time)); + if not loader.ClearMemory(addr, len) then + begin + loader.GetLastError(errorInfo); + MbiCallbackOnLog('Could not clear memory ('+errorInfo+'). t='+TimeToStr(Time)); + MbiCallbackOnError('Could not clear memory ('+errorInfo+').'); + datafile.Free; + Exit; + end; + MbiCallbackOnLog('Memory cleared. t='+TimeToStr(Time)); + end; + + //---------------- next program the memory regions ------------------------------------ + for regionCnt := 0 to datafile.GetRegionCnt-1 do + begin + // update the user info + MbiCallbackOnInfo('Reading file...'); + + // obtain the region info + datafile.GetRegionInfo(regionCnt, addr, len); + // dynamically allocated buffer memory + SetLength(progdata, len); + // obtain the regiond data + datafile.GetRegionData(regionCnt, progdata); + + bufferOffset := 0; + while len > 0 do + begin + // set the current write length taking into account kMaxProgLen + currentWriteCnt := len mod kMaxProgLen; + if currentWriteCnt = 0 then currentWriteCnt := kMaxProgLen; + + // program the data + MbiCallbackOnLog('Programming Data '+Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt])+'. t='+TimeToStr(Time)); + LogData(@progdata[bufferOffset], currentWriteCnt); + + if not loader.WriteData(addr, currentWriteCnt, @progdata[bufferOffset]) then + begin + loader.GetLastError(errorInfo); + MbiCallbackOnLog('Could not program data ('+errorInfo+'). t='+TimeToStr(Time)); + MbiCallbackOnError('Could not program data ('+errorInfo+').'); + datafile.Free; + Exit; + end; + MbiCallbackOnLog('Data Programmed. t='+TimeToStr(Time)); + + // update progress + progress := progress + currentWriteCnt; + MbiCallbackOnProgress(progress); + + // update loop variables + len := len - currentWriteCnt; + addr := addr + currentWriteCnt; + bufferOffset := bufferOffset + currentWriteCnt; + + // update the user info + MbiCallbackOnInfo('Programming data... ' + Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB])); + + end; + end; + + //---------------- stop the programming session --------------------------------------- + MbiCallbackOnLog('Stopping the programming session. t='+TimeToStr(Time)); + if not loader.StopProgrammingSession then + begin + loader.GetLastError(errorInfo); + MbiCallbackOnLog('Could not stop the programming session ('+errorInfo+'). t='+TimeToStr(Time)); + MbiCallbackOnError('Could not stop the programming session ('+errorInfo+').'); + datafile.Free; + Exit; + end; + MbiCallbackOnLog('Programming session stopped. t='+TimeToStr(Time)); + + // all done so set progress to 100% and finish up + progress := datafile.GetDataCnt; + datafile.Free; + MbiCallbackOnProgress(progress); + MbiCallbackOnLog('File successfully downloaded t='+TimeToStr(Time)); + MbiCallbackOnDone; + +end; //*** end of OnTimeout *** + + +//*************************************************************************************** +// NAME: MbiInit +// PARAMETER: callback function pointers +// RETURN VALUE: none +// DESCRIPTION: Called by the application to initialize the interface library. +// +//*************************************************************************************** +procedure MbiInit(cbStarted: TStartedEvent; cbProgress: TProgressEvent; + cbDone: TDoneEvent; cbError: TErrorEvent; cbLog: TLogEvent; + cbInfo: TInfoEvent); stdcall; +begin + //--- begin of don't change --- + AppOnStarted := cbStarted; + AppOnProgress := cbProgress; + AppOnDone := cbDone; + AppOnLog := cbLog; + AppOnInfo := cbInfo; + AppOnError := cbError; + //--- end of don't change --- + + // create xcp loader object + loader := TXcpLoader.Create; + + // update to the latest configuration + loader.Configure(ExtractFilePath(ParamStr(0))+'openblt_can_vector.ini'); + + // create and init a timer + events := TEventHandlers.Create; + timer := TTimer.Create(nil); + timer.Enabled := False; + timer.Interval := 100; + timer.OnTimer := events.OnTimeout; +end; //*** end of MbiInit *** + + +//*************************************************************************************** +// NAME: MbiStart +// PARAMETER: filename of the file that is to be downloaded. +// RETURN VALUE: none +// DESCRIPTION: Called by the application to request the interface library to download +// the file that is passed as a parameter. +// +//*************************************************************************************** +procedure MbiStart(fileName: ShortString); stdcall; +begin + // update the user info + MbiCallbackOnInfo(''); + + // start the log + MbiCallbackOnLog('--- Downloading "'+fileName+'" ---'); + + // reset stop request + stopRequest := false; + + // start the startup timer which gives microBoot a chance to paint itself + timer.Enabled := True; + + // store the program's filename + progfile := fileName; +end; //*** end of MbiStart *** + + +//*************************************************************************************** +// NAME: MbiStop +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the application to request the interface library to stop +// a download that could be in progress. +// +//*************************************************************************************** +procedure MbiStop; stdcall; +begin + // set stop request + stopRequest := true; + + // disconnect the transport layer + MbiCallbackOnLog('Disconnecting the transport layer. t='+TimeToStr(Time)); + loader.Disconnect; +end; //*** end of MbiStop *** + + +//*************************************************************************************** +// NAME: MbiDeInit +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the application to uninitialize the interface library. +// +//*************************************************************************************** +procedure MbiDeInit; stdcall; +begin + // release xcp loader object + loader.Free; + + // release the timer and events object + timer.Free; + events.Free; + + //--- begin of don't change --- + AppOnStarted := nil; + AppOnProgress := nil; + AppOnDone := nil; + AppOnLog := nil; + AppOnInfo := nil; + AppOnError := nil; + //--- end of don't change --- +end; //*** end of MbiDeInit *** + + +//*************************************************************************************** +// NAME: MbiName +// PARAMETER: none +// RETURN VALUE: name of the interface library +// DESCRIPTION: Called by the application to obtain the name of the interface library. +// +//*************************************************************************************** +function MbiName : ShortString; stdcall; +begin + Result := 'OpenBLT CAN Vector'; +end; //*** end of MbiName *** + + +//*************************************************************************************** +// NAME: MbiDescription +// PARAMETER: none +// RETURN VALUE: description of the interface library +// DESCRIPTION: Called by the application to obtain the description of the interface +// library. +// +//*************************************************************************************** +function MbiDescription : ShortString; stdcall; +begin + Result := 'OpenBLT using Vector CAN Interface'; +end; //*** end of MbiDescription *** + + +//*************************************************************************************** +// NAME: MbiVersion +// PARAMETER: none +// RETURN VALUE: version number +// DESCRIPTION: Called by the application to obtain the version number of the +// interface library. +// +//*************************************************************************************** +function MbiVersion : Longword; stdcall; +begin + Result := 10000; // v1.00.00 +end; //*** end of MbiVersion *** + + +//*************************************************************************************** +// NAME: MbiVInterface +// PARAMETER: none +// RETURN VALUE: version number of the supported interface +// DESCRIPTION: Called by the application to obtain the version number of the +// Mbi interface uBootInterface.pas (not the interface library). This can +// be used by the application for backward compatibility. +// +//*************************************************************************************** +function MbiVInterface : Longword; stdcall; +begin + Result := 10001; // v1.00.01 +end; //*** end of MbiVInterface *** + + +//*************************************************************************************** +// NAME: MbiConfigure +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the application to enable the user to configure the inter- +// face library through the application. +// +//*************************************************************************************** +procedure MbiConfigure; stdcall; +var + settings : TXcpSettings; +begin + // create xcp settings object + settings := TXcpSettings.Create(ExtractFilePath(ParamStr(0))+'openblt_can_vector.ini'); + + // display the modal configuration dialog + settings.Configure; + + // release the xcp settings object + settings.Free; + + // update to the latest configuration + loader.Configure(ExtractFilePath(ParamStr(0))+'openblt_can_vector.ini'); +end; //*** end of MbiConfigure *** + + +//*************************************************************************************** +// External Declarations +//*************************************************************************************** +exports + //--- begin of don't change --- + MbiInit index 1, + MbiStart index 2, + MbiStop index 3, + MbiDeInit index 4, + MbiName index 5, + MbiDescription index 6, + MbiVersion index 7, + MbiConfigure index 8, + MbiVInterface index 9; + //--- end of don't change --- + +end. +//********************************** end of openblt_can_vector.dpr ********************** diff --git a/Host/Source/interfaces/uart/CPDrv.ico b/Host/Source/interfaces/uart/CPDrv.ico new file mode 100644 index 0000000000000000000000000000000000000000..d0125faa54728c4de80964b80d0e38c22aee0ee9 GIT binary patch literal 766 zcmah_Jx{|h5WP^O+*T&mW@JQSU|xg&aneF7Ws9jxdcJCTR>KRiSz-cJTQTpES})&z|oshS63SqfWc z@(io7Sg}Yn@Hlv4=~YvL6`BSSd?9xtGJF=Y2KKC#HrxF86o)WhN_=6}v{O}z#U$prGU?PrMTOb_#E|FyrP>7lmq{G@pQXEx)C32Jdhjusa^6v z 0) + property OnReceivePacket: TReceivePacketEvent read FOnReceivePacket write FOnReceivePacket; + end; + +function BaudRateOf( bRate: TBaudRate ): DWORD; +function DelayForRX( bRate: TBaudRate; DataSize: DWORD ): DWORD; + +implementation + +const + Win32BaudRates: array[br110..br256000] of DWORD = + ( CBR_110, CBR_300, CBR_600, CBR_1200, CBR_2400, CBR_4800, CBR_9600, + CBR_14400, CBR_19200, CBR_38400, CBR_56000, CBR_57600, CBR_115200, + CBR_128000, CBR_256000 ); + +const + dcb_Binary = $00000001; + dcb_ParityCheck = $00000002; + dcb_OutxCtsFlow = $00000004; + dcb_OutxDsrFlow = $00000008; + dcb_DtrControlMask = $00000030; + dcb_DtrControlDisable = $00000000; + dcb_DtrControlEnable = $00000010; + dcb_DtrControlHandshake = $00000020; + dcb_DsrSensivity = $00000040; + dcb_TXContinueOnXoff = $00000080; + dcb_OutX = $00000100; + dcb_InX = $00000200; + dcb_ErrorChar = $00000400; + dcb_NullStrip = $00000800; + dcb_RtsControlMask = $00003000; + dcb_RtsControlDisable = $00000000; + dcb_RtsControlEnable = $00001000; + dcb_RtsControlHandshake = $00002000; + dcb_RtsControlToggle = $00003000; + dcb_AbortOnError = $00004000; + dcb_Reserveds = $FFFF8000; + +function GetWinPlatform: string; +var ov: TOSVERSIONINFO; +begin + ov.dwOSVersionInfoSize := sizeof(ov); + if GetVersionEx( ov ) then + begin + case ov.dwPlatformId of + VER_PLATFORM_WIN32s: // Win32s on Windows 3.1 + Result := 'W32S'; + VER_PLATFORM_WIN32_WINDOWS: // Win32 on Windows 95/98 + Result := 'W95'; + VER_PLATFORM_WIN32_NT: // Windows NT + Result := 'WNT'; + end; + end + else + Result := '??'; +end; + +function GetWinVersion: DWORD; +var ov: TOSVERSIONINFO; +begin + ov.dwOSVersionInfoSize := sizeof(ov); + if GetVersionEx( ov ) then + Result := MAKELONG( ov.dwMinorVersion, ov.dwMajorVersion ) + else + Result := $00000000; +end; + +function BaudRateOf( bRate: TBaudRate ): DWORD; +begin + if bRate = brCustom then + Result := 0 + else + Result := Win32BaudRates[ bRate ]; +end; + +function DelayForRX( bRate: TBaudRate; DataSize: DWORD ): DWORD; +begin + Result := round( DataSize / (BaudRateOf(bRate) / 10) * 1000 ); +end; + +constructor TCommPortDriver.Create( AOwner: TComponent ); +begin + inherited Create( AOwner ); + // Initialize to default values ----------------------- + // not canceled + FCancel := false; + // Not connected + FHandle := INVALID_HANDLE_VALUE; + // COM 2 + FPort := pnCOM2; + FPortName := '\\.\COM2'; + // 9600 bauds + FBaudRate := br9600; + FBaudRateValue := BaudRateOf( br9600 ); + // 8 data bits + FDataBits := db8BITS; + // 1 stop bit + FStopBits := sb1BITS; + // no parity + FParity := ptNONE; + // No hardware flow control but RTS on + FHwFlow := hfNONERTSON; + // No software flow control + FSwFlow := sfNONE; + // Input buffer of 2048 bytes + FInBufSize := 2048; + // Output buffer of 2048 bytes + FOutBufSize := 2048; + // Don't pack data + FPacketSize := -1; + // Packet timeout disabled + FPacketTimeout := -1; + // Discard incomplete packets + FPacketMode := pmDiscard; + // Poll COM port every 50ms + FPollingDelay := 50; + // Output timeout of 500ms + FOutputTimeout := 500; + // Timeout for ReadData(), 200ms + FInputTimeout := 200; + // DTR high on connect + FEnableDTROnOpen := true; + // Time not valid ( used by the packing routines ) + FFirstByteOfPacketTime := DWORD(-1); + // Don't check of off-line devices + FCkLineStatus := false; + // Init number of RX polling timer pauses - not paused + FRXPollingPauses := 0; + // Temporary buffer for received data + FTempInBuffer := AllocMem( FInBufSize ); + // Allocate a window handle to catch timer's notification messages + if not (csDesigning in ComponentState) then + FNotifyWnd := AllocateHWnd( TimerWndProc ); +end; + +destructor TCommPortDriver.Destroy; +begin + // Be sure to release the COM port + Disconnect; + // Free the temporary buffer + FreeMem( FTempInBuffer, FInBufSize ); + // Destroy the timer's window + if not (csDesigning in ComponentState) then + DeallocateHWnd( FNotifyWnd ); + // Call inherited destructor + inherited Destroy; +end; + +// The COM port handle made public and writeable. +// This lets you connect to external opened com port. +// Setting ComPortHandle to INVALID_PORT_HANDLE acts as Disconnect. +procedure TCommPortDriver.SetHandle( Value: HFILE ); +begin + // If same COM port then do nothing + if FHandle = Value then + exit; + // If value is RELEASE_NOCLOSE_PORT then stop controlling the COM port + // without closing in + if Value = RELEASE_NOCLOSE_PORT then + begin + // Stop the timer + if Connected then + KillTimer( FNotifyWnd, 1 ); + // No more connected + FHandle := INVALID_HANDLE_VALUE; + end + else + begin + // Disconnect + Disconnect; + // If Value is INVALID_HANDLE_VALUE then exit now + if Value = INVALID_HANDLE_VALUE then + exit; + // Set COM port handle + FHandle := Value; + // Start the timer ( used for polling ) + SetTimer( FNotifyWnd, 1, FPollingDelay, nil ); + end; +end; + +// Selects the COM port to use +procedure TCommPortDriver.SetPort( Value: TPortNumber ); +begin + // Be sure we are not using any COM port + if Connected then + exit; + // Change COM port + FPort := Value; + // Update the port name + if FPort <> pnCustom then + FPortName := Format( '\\.\COM%d', [ord(FPort)] ); +end; + +// Sets the port name +procedure TCommPortDriver.SetPortName( Value: string ); +begin + // Be sure we are not using any COM port + if Connected then + exit; + // Change COM port + FPort := pnCustom; + // Update the port name + FPortName := Value; +end; + +// Selects the baud rate +procedure TCommPortDriver.SetBaudRate( Value: TBaudRate ); +begin + // Set new COM speed + FBaudRate := Value; + if FBaudRate <> brCustom then + FBaudRateValue := BaudRateOf( FBaudRate ); + // Apply changes + if Connected then + ApplyCOMSettings; +end; + +// Selects the baud rate ( actual baud rate value ) +procedure TCommPortDriver.SetBaudRateValue( Value: DWORD ); +begin + // Set new COM speed + FBaudRate := brCustom; + FBaudRateValue := Value; + // Apply changes + if Connected then + ApplyCOMSettings; +end; + +// Selects the number of data bits +procedure TCommPortDriver.SetDataBits( Value: TDataBits ); +begin + // Set new data bits + FDataBits := Value; + // Apply changes + if Connected then + ApplyCOMSettings; +end; + +// Selects the number of stop bits +procedure TCommPortDriver.SetStopBits( Value: TStopBits ); +begin + // Set new stop bits + FStopBits := Value; + // Apply changes + if Connected then + ApplyCOMSettings; +end; + +// Selects the kind of parity +procedure TCommPortDriver.SetParity( Value: TParity ); +begin + // Set new parity + FParity := Value; + // Apply changes + if Connected then + ApplyCOMSettings; +end; + +// Selects the kind of hardware flow control +procedure TCommPortDriver.SetHwFlowControl( Value: THwFlowControl ); +begin + // Set new hardware flow control + FHwFlow := Value; + // Apply changes + if Connected then + ApplyCOMSettings; +end; + +// Selects the kind of software flow control +procedure TCommPortDriver.SetSwFlowControl( Value: TSwFlowControl ); +begin + // Set new software flow control + FSwFlow := Value; + // Apply changes + if Connected then + ApplyCOMSettings; +end; + +// Sets the RX buffer size +procedure TCommPortDriver.SetInBufSize( Value: DWORD ); +begin + // Do nothing if connected + if Connected then + exit; + // Free the temporary input buffer + FreeMem( FTempInBuffer, FInBufSize ); + // Set new input buffer size + if Value > 8192 then + Value := 8192 + else if Value < 128 then + Value := 128; + FInBufSize := Value; + // Allocate the temporary input buffer + FTempInBuffer := AllocMem( FInBufSize ); + // Adjust the RX packet size + SetPacketSize( FPacketSize ); +end; + +// Sets the TX buffer size +procedure TCommPortDriver.SetOutBufSize( Value: DWORD ); +begin + // Do nothing if connected + if Connected then + exit; + // Set new output buffer size + if Value > 8192 then + Value := 8192 + else if Value < 128 then + Value := 128; + FOutBufSize := Value; +end; + +// Sets the size of incoming packets +procedure TCommPortDriver.SetPacketSize( Value: smallint ); +begin + // PackeSize <= 0 if data isn't to be 'packetized' + if Value <= 0 then + FPacketSize := -1 + // If the PacketSize if greater than then RX buffer size then + // increase the RX buffer size + else if DWORD(Value) > FInBufSize then + begin + FPacketSize := Value; + SetInBufSize( FPacketSize ); + end; +end; + +// Sets the timeout for incoming packets +procedure TCommPortDriver.SetPacketTimeout( Value: integer ); +begin + // PacketTimeout <= 0 if packet timeout is to be disabled + if Value < 1 then + FPacketTimeout := -1 + // PacketTimeout cannot be less than polling delay + some extra ms + else if Value < FPollingDelay then + FPacketTimeout := FPollingDelay + (FPollingDelay*40) div 100; +end; + +// Sets the delay between polling checks +procedure TCommPortDriver.SetPollingDelay( Value: word ); +begin + // Make it greater than 4 ms + if Value < 5 then + Value := 5; + // If new delay is not equal to previous value... + if Value <> FPollingDelay then + begin + // Stop the timer + if Connected then + KillTimer( FNotifyWnd, 1 ); + // Store new delay value + FPollingDelay := Value; + // Restart the timer + if Connected then + SetTimer( FNotifyWnd, 1, FPollingDelay, nil ); + // Adjust the packet timeout + SetPacketTimeout( FPacketTimeout ); + end; +end; + +// Apply COM settings +function TCommPortDriver.ApplyCOMSettings: boolean; +var dcb: TDCB; +begin + // Do nothing if not connected + Result := false; + if not Connected then + exit; + + // ** Setup DCB (Device Control Block) fields ****************************** + + // Clear all + fillchar( dcb, sizeof(dcb), 0 ); + // DCB structure size + dcb.DCBLength := sizeof(dcb); + // Baud rate + dcb.BaudRate := FBaudRateValue; + // Set fBinary: Win32 does not support non binary mode transfers + // (also disable EOF check) + dcb.Flags := dcb_Binary; + // Enables the DTR line when the device is opened and leaves it on + if EnableDTROnOpen then + dcb.Flags := dcb.Flags or dcb_DtrControlEnable; + // Kind of hw flow control to use + case FHwFlow of + // No hw flow control + hfNONE:; + // No hw flow control but set RTS high and leave it high + hfNONERTSON: + dcb.Flags := dcb.Flags or dcb_RtsControlEnable; + // RTS/CTS (request-to-send/clear-to-send) flow control + hfRTSCTS: + dcb.Flags := dcb.Flags or dcb_OutxCtsFlow or dcb_RtsControlHandshake; + end; + // Kind of sw flow control to use + case FSwFlow of + // No sw flow control + sfNONE:; + // XON/XOFF sw flow control + sfXONXOFF: + dcb.Flags := dcb.Flags or dcb_OutX or dcb_InX; + end; + // Set XONLim: specifies the minimum number of bytes allowed in the input + // buffer before the XON character is sent (or CTS is set). + if (GetWinPlatform = 'WNT') and (GetWinVersion >= $00040000) then + begin + // WinNT 4.0 + Service Pack 3 needs XONLim to be less than or + // equal to 4096 bytes. Win95/98 doesn't have such limit. + if FInBufSize div 4 > 4096 then + dcb.XONLim := 4096 + else + dcb.XONLim := FInBufSize div 4; + end + else + dcb.XONLim := FInBufSize div 4; + // Specifies the maximum number of bytes allowed in the input buffer before + // the XOFF character is sent (or CTS is set low). The maximum number of bytes + // allowed is calculated by subtracting this value from the size, in bytes, of + // the input buffer. + dcb.XOFFLim := dcb.XONLim; + // How many data bits to use + dcb.ByteSize := 5 + ord(FDataBits); + // Kind of parity to use + dcb.Parity := ord(FParity); + // How many stop bits to use + dcb.StopBits := ord(FStopbits); + // XON ASCII char - DC1, Ctrl-Q, ASCII 17 + dcb.XONChar := #17; + // XOFF ASCII char - DC3, Ctrl-S, ASCII 19 + dcb.XOFFChar := #19; + + // Apply new settings + Result := SetCommState( FHandle, dcb ); + if not Result then + exit; + // Flush buffers + Result := FlushBuffers( true, true ); + if not Result then + exit; + // Setup buffers size + Result := SetupComm( FHandle, FInBufSize, FOutBufSize ); +end; + +function TCommPortDriver.Connect: boolean; +var tms: TCOMMTIMEOUTS; +begin + // not canceled + FCancel := false; + + // Do nothing if already connected + Result := Connected; + if Result then + exit; + // Open the COM port + FHandle := CreateFile( pchar(FPortName), + GENERIC_READ or GENERIC_WRITE, + 0, // Not shared + nil, // No security attributes + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + 0 // No template + ) ; + Result := Connected; + if not Result then + exit; + // Apply settings + Result := ApplyCOMSettings; + if not Result then + begin + Disconnect; + exit; + end; + // Set ReadIntervalTimeout: Specifies the maximum time, in milliseconds, + // allowed to elapse between the arrival of two characters on the + // communications line. + // We disable timeouts because we are polling the com port! + tms.ReadIntervalTimeout := 1; + // Set ReadTotalTimeoutMultiplier: Specifies the multiplier, in milliseconds, + // used to calculate the total time-out period for read operations. + tms.ReadTotalTimeoutMultiplier := 0; + // Set ReadTotalTimeoutConstant: Specifies the constant, in milliseconds, + // used to calculate the total time-out period for read operations. + tms.ReadTotalTimeoutConstant := 1; + // Set WriteTotalTimeoutMultiplier: Specifies the multiplier, in milliseconds, + // used to calculate the total time-out period for write operations. + tms.WriteTotalTimeoutMultiplier := 0; + // Set WriteTotalTimeoutConstant: Specifies the constant, in milliseconds, + // used to calculate the total time-out period for write operations. + tms.WriteTotalTimeoutConstant := 10; + // Apply timeouts + SetCommTimeOuts( FHandle, tms ); + // Start the timer (used for polling) + SetTimer( FNotifyWnd, 1, FPollingDelay, nil ); +end; + +procedure TCommPortDriver.Disconnect; +begin + // not canceled + FCancel := true; + + + if Connected then + begin + // Stop the timer (used for polling) + KillTimer( FNotifyWnd, 1 ); + // Release the COM port + CloseHandle( FHandle ); + // No more connected + FHandle := INVALID_HANDLE_VALUE; + end; +end; + +// Returns true if connected +function TCommPortDriver.Connected: boolean; +begin + Result := FHandle <> INVALID_HANDLE_VALUE; +end; + +// Returns CTS, DSR, RING and RLSD (CD) signals status +function TCommPortDriver.GetLineStatus: TLineStatusSet; +var dwS: DWORD; +begin + Result := []; + if not Connected then + exit; + // Retrieves modem control-register values. + // The function fails if the hardware does not support the control-register + // values. + if not GetCommModemStatus( FHandle, dwS ) then + exit; + if dwS and MS_CTS_ON <> 0 then Result := Result + [lsCTS]; + if dwS and MS_DSR_ON <> 0 then Result := Result + [lsDSR]; + if dwS and MS_RING_ON <> 0 then Result := Result + [lsRING]; + if dwS and MS_RLSD_ON <> 0 then Result := Result + [lsCD]; +end; + +// Returns true if polling has not been paused +function TCommPortDriver.IsPolling: boolean; +begin + Result := FRXPollingPauses <= 0; +end; + +// Pauses polling +procedure TCommPortDriver.PausePolling; +begin + // Inc. RX polling pauses counter + inc( FRXPollingPauses ); +end; + +// Re-starts polling (after pause) +procedure TCommPortDriver.ContinuePolling; +begin + // Dec. RX polling pauses counter + dec( FRXPollingPauses ); +end; + +// Flush rx/tx buffers +function TCommPortDriver.FlushBuffers( inBuf, outBuf: boolean ): boolean; +var dwAction: DWORD; +begin + // Do nothing if not connected + Result := false; + if not Connected then + exit; + // Flush the RX data buffer + dwAction := 0; + if outBuf then + dwAction := dwAction or PURGE_TXABORT or PURGE_TXCLEAR; + // Flush the TX data buffer + if inBuf then + dwAction := dwAction or PURGE_RXABORT or PURGE_RXCLEAR; + Result := PurgeComm( FHandle, dwAction ); + // Used by the RX packet mechanism + if Result then + FFirstByteOfPacketTime := DWORD(-1); +end; + +// Returns number of received bytes in the RX buffer +function TCommPortDriver.CountRX: integer; +var stat: TCOMSTAT; + errs: DWORD; +begin + // Do nothing if port has not been opened + Result := 65535; + if not Connected then + exit; + // Get count + ClearCommError( FHandle, errs, @stat ); + Result := stat.cbInQue; +end; + +// Returns the output buffer free space or 65535 if not connected +function TCommPortDriver.OutFreeSpace: word; +var stat: TCOMSTAT; + errs: DWORD; +begin + if not Connected then + Result := 65535 + else + begin + ClearCommError( FHandle, errs, @stat ); + Result := FOutBufSize - stat.cbOutQue; + end; +end; + +// Sends binary data. Returns number of bytes sent. Timeout overrides +// the value specifiend in the OutputTimeout property +function TCommPortDriver.SendDataEx( DataPtr: pchar; DataSize, Timeout: DWORD ): DWORD; +var nToSend, nSent, t1: DWORD; +begin + // Do nothing if port has not been opened + Result := 0; + if not Connected then + exit; + // Current time + t1 := GetTickCount; + // Loop until all data sent or timeout occurred + while DataSize > 0 do + begin + // Get TX buffer free space + nToSend := OutFreeSpace; + // If output buffer has some free space... + if nToSend > 0 then + begin + // Check signals + if FCkLineStatus and (GetLineStatus = []) then + exit; + // Don't send more bytes than we actually have to send + if nToSend > DataSize then + nToSend := DataSize; + // Send + WriteFile( FHandle, DataPtr^, nToSend, nSent, nil ); + nSent := abs( nSent ); + if nSent > 0 then + begin + // Update number of bytes sent + Result := Result + nSent; + // Decrease the count of bytes to send + DataSize := DataSize - nSent; + // Inc. data pointer + DataPtr := DataPtr + nSent; + // Get current time + t1 := GetTickCount; + // Continue. This skips the time check below (don't stop + // trasmitting if the Timeout is set too low) + continue; + end; + end; + // Buffer is full. If we are waiting too long then exit + if DWORD(GetTickCount-t1) > Timeout then + exit; + end; +end; + +// Send data (breaks the data in small packets if it doesn't fit in the output +// buffer) +function TCommPortDriver.SendData( DataPtr: pointer; DataSize: DWORD ): DWORD; +begin + Result := SendDataEx( DataPtr, DataSize, FOutputTimeout ); +end; + +// Sends a byte. Returns true if the byte has been sent +function TCommPortDriver.SendByte( Value: byte ): boolean; +begin + Result := SendData( @Value, 1 ) = 1; +end; + +// Sends a char. Returns true if the char has been sent +function TCommPortDriver.SendChar( Value: char ): boolean; +begin + Result := SendData( @Value, 1 ) = 1; +end; + +// Sends a pascal string (NULL terminated if $H+ (default)) +function TCommPortDriver.SendString( s: string ): boolean; +var len: DWORD; +begin + len := length( s ); + {$IFOPT H+} // New syle pascal string (NULL terminated) + Result := SendData( pchar(s), len ) = len; + {$ELSE} // Old style pascal string (s[0] = length) + Result := SendData( pchar(@s[1]), len ) = len; + {$ENDIF} +end; + +// Sends a C-style string (NULL terminated) +function TCommPortDriver.SendZString( s: pchar ): boolean; +var len: DWORD; +begin + len := strlen( s ); + Result := SendData( s, len ) = len; +end; + +// Reads binary data. Returns number of bytes read +function TCommPortDriver.ReadData( DataPtr: pchar; MaxDataSize: DWORD ): DWORD; +var nToRead, nRead, t1: DWORD; +begin + // Do nothing if port has not been opened + Result := 0; + if not Connected then + exit; + // Pause polling + PausePolling; + // Current time + t1 := GetTickCount; + // Loop until all requested data read or timeout occurred + while MaxDataSize > 0 do + begin + Application.ProcessMessages; // ##Vg process these messages + + if FCancel then exit; + + // Get data bytes count in RX buffer + nToRead := CountRX; + // If input buffer has some data... + if nToRead > 0 then + begin + // Don't read more bytes than we actually have to read + if nToRead > MaxDataSize then + nToRead := MaxDataSize; + // Read + ReadFile( FHandle, DataPtr^, nToRead, nRead, nil ); + // Update number of bytes read + Result := Result + nRead; + // Decrease the count of bytes to read + MaxDataSize := MaxDataSize - nRead; + // Inc. data pointer + DataPtr := DataPtr + nRead; + // Get current time + t1 := GetTickCount; + // Continue. This skips the time check below (don't stop + // reading if the FInputTimeout is set too low) + continue; + end; + // Buffer is empty. If we are waiting too long then exit + if (GetTickCount-t1) > FInputTimeout then + break; + end; + // Continue polling + ContinuePolling; +end; + +// Reads a byte. Returns true if the byte has been read +function TCommPortDriver.ReadByte( var Value: byte ): boolean; +begin + Result := ReadData( @Value, 1 ) = 1; +end; + +// Reads a char. Returns true if char has been read +function TCommPortDriver.ReadChar( var Value: char ): boolean; +begin + Result := ReadData( @Value, 1 ) = 1; +end; + +// Set DTR line high (onOff=TRUE) or low (onOff=FALSE). +// You must not use HW handshaking. +procedure TCommPortDriver.ToggleDTR( onOff: boolean ); +const funcs: array[boolean] of integer = (CLRDTR,SETDTR); +begin + if Connected then + EscapeCommFunction( FHandle, funcs[onOff] ); +end; + +// Set RTS line high (onOff=TRUE) or low (onOff=FALSE). +// You must not use HW handshaking. +procedure TCommPortDriver.ToggleRTS( onOff: boolean ); +const funcs: array[boolean] of integer = (CLRRTS,SETRTS); +begin + if Connected then + EscapeCommFunction( FHandle, funcs[onOff] ); +end; + +// COM port polling proc +procedure TCommPortDriver.TimerWndProc( var msg: TMessage ); +var nRead, nToRead, dummy: DWORD; + comStat: TCOMSTAT; +begin + if (msg.Msg = WM_TIMER) and Connected then + begin + // Do nothing if RX polling has been paused + if FRXPollingPauses > 0 then + exit; + // If PacketSize is > 0 then raise the OnReceiveData event only if the RX + // buffer has at least PacketSize bytes in it. + ClearCommError( FHandle, dummy, @comStat ); + if FPacketSize > 0 then + begin + // Complete packet received ? + if DWORD(comStat.cbInQue) >= DWORD(FPacketSize) then + begin + repeat + // Read the packet and pass it to the app + nRead := 0; + if ReadFile( FHandle, FTempInBuffer^, FPacketSize, nRead, nil ) then + if (nRead <> 0) and Assigned(FOnReceivePacket) then + FOnReceivePacket( Self, FTempInBuffer, nRead ); + // Adjust time + //if comStat.cbInQue >= FPacketSize then + FFirstByteOfPacketTime := FFirstByteOfPacketTime + + DelayForRX( FBaudRate, FPacketSize ); + comStat.cbInQue := comStat.cbInQue - WORD(FPacketSize); + if comStat.cbInQue = 0 then + FFirstByteOfPacketTime := DWORD(-1); + until DWORD(comStat.cbInQue) < DWORD(FPacketSize); + // Done + exit; + end; + // Handle packet timeouts + if (FPacketTimeout > 0) and (FFirstByteOfPacketTime <> DWORD(-1)) and + (GetTickCount - FFirstByteOfPacketTime > DWORD(FPacketTimeout)) then + begin + nRead := 0; + // Read the "incomplete" packet + if ReadFile( FHandle, FTempInBuffer^, comStat.cbInQue, nRead, nil ) then + // If PacketMode is not pmDiscard then pass the packet to the app + if (FPacketMode <> pmDiscard) and (nRead <> 0) and Assigned(FOnReceivePacket) then + FOnReceivePacket( Self, FTempInBuffer, nRead ); + // Restart waiting for a packet + FFirstByteOfPacketTime := DWORD(-1); + // Done + exit; + end; + // Start time + if (comStat.cbInQue > 0) and (FFirstByteOfPacketTime = DWORD(-1)) then + FFirstByteOfPacketTime := GetTickCount; + // Done + exit; + end; + + // Standard data handling + nRead := 0; + nToRead := comStat.cbInQue; + if (nToRead > 0) and ReadFile( FHandle, FTempInBuffer^, nToRead, nRead, nil ) then + if (nRead <> 0) and Assigned(FOnReceiveData) then + FOnReceiveData( Self, FTempInBuffer, nRead ); + end + // Let Windows handle other messages + else + Msg.Result := DefWindowProc( FNotifyWnd, Msg.Msg, Msg.wParam, Msg.lParam ) ; +end; + +end. diff --git a/Host/Source/interfaces/uart/XcpSettings.dfm b/Host/Source/interfaces/uart/XcpSettings.dfm new file mode 100644 index 0000000000000000000000000000000000000000..6d833d1d29e3d80efdf01ac36c146cdd751eec6a GIT binary patch literal 11217 zcmeHNeQ*=U6<iF+mtXsN(cpPQw*&!g#^NcBqV@8uub|;|Ky)e_#+eb?d{!3a*Uy! zG@W5|*6!`@+xL5K-|g+aed~k=aU1-#!3vJ6T)jLPs9C!TEzIlsAwpbjU|}A&AruK> zO%vqCXh2b=+)?$cYTTeXp0znRCE~bI5pq{;zDkwwjl)D`!=Z4f1l74PsSj zp!~YhUNo^r4Et5gYq*9Cg<)!ys6e!LPmCzRkczSF2i38fQ!BJ!F*y9p2C#IG$km!h_ffu3L!0~;sxcr#(Q>W zBjo1F1Wn>2uRytM70Jm}3~3Ie>5!&CvY|&IM`(jV*DFT$kKvJT;fK(-AOu8YZKQd{6ChneED*a(;SQa|K;4eIehx)wVo4wLw#es zNFxIyA6@Jpygr<&=)jG>)2F(R9De8cpO4+_9{^J7c+Pa6-u3FM`}gg;cJ)(>3!x*w z|D-6Zv(VACYDV|IUw!oXkRc5UorgZ%;5$?7>RP|>^x*ZIz%(*=^R->OW=x-+m6c_; z+Z_%^+qP|%95u3Kcwlhm%$ZeP69`|u!PMCk9Qu7iXn-mZMqS(w%N%jo&f zhluuv_kO&H>C8va-c>#0WdEmw&?t!_U;~WH<;u;?oiu6Ep4WF&CN9(6jM zz+JbluJ>;}12=Af(Wp|?ZXicT8-`)`U%M`e5{wF1I*uJrSr0}Aht#@Lfc^AC9lzLe z9)?jf`()o$B7y$aaU2LKDJcQtSdFxhD#s$-x;YdG1c2q4jnAaW0s4m*`l^1==|i2B zYzO!FnP30pVk#3@1DIZa?YCB=RTxtaP=B}g4Pco+e}1~0^WE2$)!RTX_)R=X@o(5{cxYP-~Xy?Vx9;Q7QO7up)n!jMXs z69->Un(pPc?ZA|ilk@J8Bct$+{OK@EEtrIRckhA60+`U@!2bPSuNS5Qm>MCNTJ6&N z+d>zYJxr$X^2a)_eKc^hZ}7RNk3zNB*%?{W``Y#oh6jdV3eBE98$>Y-11btlO^U2s zzDN`SY%UlC63qIt(lSMstE;N%h&ILT{0!V5RSR{gLgP^@dg2GczKKb#7SD*tzm(KP_gXfw8f8Ei1 z>5~uoDHF|y`i9=xd1cF*bFCZC^<5?F3;b?;b}jz%c9`Sv?5nG)I*uQ=SYWQ~d-F{k z4%e)%*}Q4f8+-OxZ$SDyusFW)!h&{~gy2;LZO|Ge;;I+DfjGH0i%pJTPiVM==7BO zJ?MlCS5jbFNtaGEFf?Me5qP*vh8>hWZrYG}q8qN`3oVq<^%6I^l5_`r=nD#FnEQ*g<$l3aOE5Ux>JyGM=l4!-sSX2WM*23Vd1(YQg zv=^Yu_*fX$2u!habnJBo_KN=mJJ&>F=hR1{b3sZr2YS~lWlD=DB-N*lVWTc*u^~q> zrG_OlT9HF4(FH+GC2<~`%jvIK#ro(ipWX`St&rY| z=&hLEO6YA7N-m`^=aQ;=K~-}k)FxEd;5VUbmM?$dLRVIPA;}9Dk$iD6$4& z6S}itkzOkT64Z)HNEesSS44;|Uq0}`JzpoM41@S)$!~%iJ|MNKqFK*=B1Fzu(t_bD zlm11pn_mQmd=VgO<{Rsikck1M?N08~>wNHh$@?7m_}wxwpz-Zs#DFp} zpiB%X69dY`fbO=4-cS33_uaPKemA)NWFtVGy!4&Q-Z6G6kEQKYh#MKiIQ*k3+{%_$ zSCc3}MOe^0IINL&Xr{oAruz7fLl*GlG|wB(4E3-N3CfhIN^_L%L>w1rP-c-aE4#wA`3 zvuklQqR3Iqa=v7YUWYRNC$B(}BN>sWaeDi6A>!jhu4vRvUPm?8?}A~24hna7#C#&C_lXQ*RB8AHVy%N30REuo-K z>Y#fJQ2XYuD>tbu7HwtM^8$c?pRKZ72|&?}h!Zv. +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + StdCtrls, ComCtrls, ExtCtrls, IniFiles; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TXcpSettingsForm = class(TForm) + pnlFooter: TPanel; + btnOK: TButton; + btnCancel: TButton; + pageControl: TPageControl; + tabXcp: TTabSheet; + tabSci: TTabSheet; + iconSci: TImage; + lblSci: TLabel; + lblXcp: TLabel; + iconXcp2: TImage; + lblComport: TLabel; + cmbComport: TComboBox; + lblBaudrate: TLabel; + cmbBaudrate: TComboBox; + lblT1: TLabel; + lblT3: TLabel; + lblT4: TLabel; + lblT5: TLabel; + lblT7: TLabel; + edtT1: TEdit; + edtT3: TEdit; + edtT4: TEdit; + edtT5: TEdit; + edtT7: TEdit; + tabProt: TTabSheet; + iconXcp1: TImage; + lblPort: TLabel; + edtSeedKey: TEdit; + btnBrowse: TButton; + openDialog: TOpenDialog; + procedure btnOKClick(Sender: TObject); + procedure btnCancelClick(Sender: TObject); + procedure btnBrowseClick(Sender: TObject); + private + { Private declarations } + public + { Public declarations } + end; + +type + TXcpSettings = class(TObject) + private + FSettingsForm : TXcpSettingsForm; + FIniFile : string; + public + constructor Create(iniFile : string); + destructor Destroy; override; + function Configure : Boolean; + end; + + +implementation +{$R *.DFM} +//*************************************************************************************** +// NAME: btnOKClick +// PARAMETER: none +// RETURN VALUE: modal result +// DESCRIPTION: Sets the module result to okay. +// +//*************************************************************************************** +procedure TXcpSettingsForm.btnOKClick(Sender: TObject); +begin + ModalResult := mrOK; +end; //*** end of btnOKClick *** + + +//*************************************************************************************** +// NAME: btnCancelClick +// PARAMETER: none +// RETURN VALUE: modal result +// DESCRIPTION: Sets the module result to cancel. +// +//*************************************************************************************** +procedure TXcpSettingsForm.btnCancelClick(Sender: TObject); +begin + ModalResult := mrCancel; +end; //*** end of btnCancelClick *** + + +//*************************************************************************************** +// NAME: btnBrowseClick +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Prompts the user to select the seed/key dll file. +// +//*************************************************************************************** +procedure TXcpSettingsForm.btnBrowseClick(Sender: TObject); +begin + openDialog.InitialDir := ExtractFilePath(ParamStr(0)); + if openDialog.Execute then + begin + edtSeedKey.Text := openDialog.FileName; + end; +end; //*** end of btnBrowseClick *** + + +//*************************************************************************************** +// NAME: Create +// PARAMETER: Name of the INI file where the settings are and will be stored +// RETURN VALUE: none +// DESCRIPTION: Class constructor +// +//*************************************************************************************** +constructor TXcpSettings.Create(iniFile : string); +begin + // call inherited constructor + inherited Create; + + // set the inifile + FIniFile := iniFile; + + // create an instance of the settings form + FSettingsForm := TXcpSettingsForm.Create(nil); +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class destructor +// +//*************************************************************************************** +destructor TXcpSettings.Destroy; +begin + // releaase the settings form object + FSettingsForm.Free; + + // call inherited destructor + inherited; +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: Configure +// PARAMETER: none +// RETURN VALUE: True if configuration was successfully changed, False otherwise +// DESCRIPTION: Allows the user to configure the XCP interface using a GUI. +// +//*************************************************************************************** +function TXcpSettings.Configure : Boolean; +var + settingsIni: TIniFile; +begin + // initialize the return value + result := false; + + // init the form elements using the configuration found in the INI + if FileExists(FIniFile) then + begin + // create ini file object + settingsIni := TIniFile.Create(FIniFile); + + // SCI related elements + FSettingsForm.cmbComport.ItemIndex := settingsIni.ReadInteger('sci', 'port', 0); + FSettingsForm.cmbBaudrate.ItemIndex := settingsIni.ReadInteger('sci', 'baudrate', 6); + + // XCP related elements + FSettingsForm.edtSeedKey.Text := settingsIni.ReadString('xcp', 'seedkey', ExtractFilePath(ParamStr(0))+''); + FSettingsForm.edtT1.Text := IntToStr(settingsIni.ReadInteger('xcp', 't1', 1000)); + FSettingsForm.edtT3.Text := IntToStr(settingsIni.ReadInteger('xcp', 't3', 2000)); + FSettingsForm.edtT4.Text := IntToStr(settingsIni.ReadInteger('xcp', 't4', 10000)); + FSettingsForm.edtT5.Text := IntToStr(settingsIni.ReadInteger('xcp', 't5', 1000)); + FSettingsForm.edtT7.Text := IntToStr(settingsIni.ReadInteger('xcp', 't7', 2000)); + + // release ini file object + settingsIni.Free; + end + else + begin + // set defaults + // SCI related elements + FSettingsForm.cmbComport.ItemIndex := 0; + FSettingsForm.cmbBaudrate.ItemIndex := 6; + + // XCP related elements + FSettingsForm.edtSeedKey.Text := ExtractFilePath(ParamStr(0))+''; + FSettingsForm.edtT1.Text := IntToStr(1000); + FSettingsForm.edtT3.Text := IntToStr(2000); + FSettingsForm.edtT4.Text := IntToStr(10000); + FSettingsForm.edtT5.Text := IntToStr(1000); + FSettingsForm.edtT7.Text := IntToStr(2000); + + end; + + // show the form as modal so we can get the result here + if FSettingsForm.ShowModal = mrOK then + begin + if FIniFile <> '' then + begin + // create ini file object + settingsIni := TIniFile.Create(FIniFile); + + // SCI related elements + settingsIni.WriteInteger('sci', 'port', FSettingsForm.cmbComport.ItemIndex); + settingsIni.WriteInteger('sci', 'baudrate', FSettingsForm.cmbBaudrate.ItemIndex); + + // XCP related elements + settingsIni.WriteString('xcp', 'seedkey', FSettingsForm.edtSeedKey.Text); + settingsIni.WriteInteger('xcp', 't1', StrToInt(FSettingsForm.edtT1.Text)); + settingsIni.WriteInteger('xcp', 't3', StrToInt(FSettingsForm.edtT3.Text)); + settingsIni.WriteInteger('xcp', 't4', StrToInt(FSettingsForm.edtT4.Text)); + settingsIni.WriteInteger('xcp', 't5', StrToInt(FSettingsForm.edtT5.Text)); + settingsIni.WriteInteger('xcp', 't7', StrToInt(FSettingsForm.edtT7.Text)); + + // release ini file object + settingsIni.Free; + + // indicate that the settings where successfully updated + result := true; + end; + end; +end; //*** end of Configure *** + + +end. +//******************************** end of XcpSettings.pas ******************************* + + diff --git a/Host/Source/interfaces/uart/XcpTransport.pas b/Host/Source/interfaces/uart/XcpTransport.pas new file mode 100644 index 00000000..dd7ebf6d --- /dev/null +++ b/Host/Source/interfaces/uart/XcpTransport.pas @@ -0,0 +1,267 @@ +unit XcpTransport; +//*************************************************************************************** +// Description: XCP transport layer for SCI. +// File Name: XcpTransport.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Forms, CPDrv, IniFiles; + + +//*************************************************************************************** +// Global Constants +//*************************************************************************************** +const kMaxPacketSize = 256; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +type + TXcpTransport = class(TObject) + private + public + packetData : array[0..kMaxPacketSize-1] of Byte; + packetLen : Word; + sciDriver : TCommPortDriver; + constructor Create; + procedure Configure(iniFile : string); + procedure Connect; + function SendPacket(timeOutms: LongWord): Boolean; + procedure Disconnect; + destructor Destroy; override; + end; + + +implementation + +//*************************************************************************************** +// NAME: Create +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class constructore +// +//*************************************************************************************** +constructor TXcpTransport.Create; +begin + // call inherited constructor + inherited Create; + + // create a sci driver instance + sciDriver := TCommPortDriver.Create(nil); + + // init sci settings + sciDriver.DataBits := db8BITS; + sciDriver.StopBits := sb1BITS; + sciDriver.Parity := ptNONE; + sciDriver.SwFlow := sfNONE; + sciDriver.PollingDelay := 5; + + // reset packet length + packetLen := 0; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Class destructor +// +//*************************************************************************************** +destructor TXcpTransport.Destroy; +begin + // release sci driver instance + sciDriver.Free; + + // call inherited destructor + inherited; +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: Configure +// PARAMETER: filename of the INI +// RETURN VALUE: none +// DESCRIPTION: Configures both this class from the settings in the INI. +// +//*************************************************************************************** +procedure TXcpTransport.Configure(iniFile : string); +var + settingsIni : TIniFile; + configIndex : integer; +begin + // read XCP configuration from INI + if FileExists(iniFile) then + begin + // create ini file object + settingsIni := TIniFile.Create(iniFile); + + // configure baudrate + configIndex := settingsIni.ReadInteger('sci', 'baudrate', 6); + sciDriver.BaudRate := br38400; // init to default value + case configIndex of + 0 : sciDriver.BaudRate := br1200; + 1 : sciDriver.BaudRate := br2400; + 2 : sciDriver.BaudRate := br4800; + 3 : sciDriver.BaudRate := br9600; + 4 : sciDriver.BaudRate := br14400; + 5 : sciDriver.BaudRate := br19200; + 6 : sciDriver.BaudRate := br38400; + 7 : sciDriver.BaudRate := br56000; + 8 : sciDriver.BaudRate := br57600; + 9 : sciDriver.BaudRate := br115200; + 10: sciDriver.BaudRate := br128000; + 11: sciDriver.BaudRate := br256000; + end; + + // configure port + configIndex := settingsIni.ReadInteger('sci', 'port', 0); + sciDriver.Port := pnCOM1; // init to default value + case configIndex of + 0 : sciDriver.Port := pnCOM1; + 1 : sciDriver.Port := pnCOM2; + 2 : sciDriver.Port := pnCOM3; + 3 : sciDriver.Port := pnCOM4; + 4 : sciDriver.Port := pnCOM5; + 5 : sciDriver.Port := pnCOM6; + 6 : sciDriver.Port := pnCOM7; + 7 : sciDriver.Port := pnCOM8; + end; + + // release ini file object + settingsIni.Free; + end; +end; //*** end of Configure *** + + +//*************************************************************************************** +// NAME: Connect +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Connects the transport layer device. +// +//*************************************************************************************** +procedure TXcpTransport.Connect; +begin + if not sciDriver.Connect then + Application.MessageBox( 'Could not connect to COM port.', + 'Error', MB_OK or MB_ICONERROR ); +end; //*** end of Connect *** + + +//*************************************************************************************** +// NAME: SendPacket +// PARAMETER: the time[ms] allowed for the reponse from the slave to come in. +// RETURN VALUE: True if response received from slave, False otherwise +// DESCRIPTION: Sends the XCP packet using the data in 'packetData' and length in +// 'packetLen' and waits for the response to come in. +// +//*************************************************************************************** +function TXcpTransport.SendPacket(timeOutms: LongWord): Boolean; +var + msgData : array of Byte; + resLen : byte; + cnt : byte; + dwEnd :DWord; +begin + // init the return value + result := false; + + // prepare the packet. length goes in the first byte followed by the packet data + SetLength(msgData, packetLen+1); + msgData[0] := packetLen; + for cnt := 0 to packetLen-1 do + begin + msgData[cnt+1] := packetData[cnt]; + end; + + // submit the packet transmission request + if sciDriver.SendData(@msgData[0], packetLen+1) <> (packetLen+1) then + begin + // unable to submit tx request + Exit; + end; + + // compute timeout time + dwEnd := GetTickCount + timeOutms; + + // configure timeout for first byte + sciDriver.InputTimeout := timeOutms; + + // receive the first byte which holds the packet length + if sciDriver.ReadByte(resLen) = true then + begin + timeOutms := GetTickCount; + if timeOutms < dwEnd then + begin + // configure timeout for remaining bytes + sciDriver.InputTimeout := dwEnd - timeOutms; + end + else + begin + Exit; // timed out + end; + + // receive the actual packet data + if sciDriver.ReadData(@packetData[0], resLen) = resLen then + begin + packetLen := resLen; + result := true; + end; + end; +end; //*** end of SendPacket *** + + +//*************************************************************************************** +// NAME: Disconnect +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Disconnects the transport layer device. +// +//*************************************************************************************** +procedure TXcpTransport.Disconnect; +begin + sciDriver.Disconnect; +end; //*** end of Disconnect *** + + +end. +//******************************** end of XcpTransport.pas ****************************** + diff --git a/Host/Source/interfaces/uart/openblt_uart.cfg b/Host/Source/interfaces/uart/openblt_uart.cfg new file mode 100644 index 00000000..c757c9ae --- /dev/null +++ b/Host/Source/interfaces/uart/openblt_uart.cfg @@ -0,0 +1,35 @@ +-$A+ +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J+ +-$K- +-$L+ +-$M- +-$N+ +-$O+ +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-E../../../ +-LNc:\program files (x86)\borland\delphi4\Lib diff --git a/Host/Source/interfaces/uart/openblt_uart.dof b/Host/Source/interfaces/uart/openblt_uart.dof new file mode 100644 index 00000000..09cc9d39 --- /dev/null +++ b/Host/Source/interfaces/uart/openblt_uart.dof @@ -0,0 +1,86 @@ +[Compiler] +A=1 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=1 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir=../../../ +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages=Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40 +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1031 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +$(DELPHI)\Lib\dclusr40.bpl=Borland User +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlOutputDirectorry] +Count=1 +Item0=../../../ diff --git a/Host/Source/interfaces/uart/openblt_uart.dpr b/Host/Source/interfaces/uart/openblt_uart.dpr new file mode 100644 index 00000000..c1a78482 --- /dev/null +++ b/Host/Source/interfaces/uart/openblt_uart.dpr @@ -0,0 +1,605 @@ +library openblt_uart; +//*************************************************************************************** +// Project Name: MicroBoot Interface for Borland Delphi +// Description: XCP - SCI interface for MicroBoot +// File Name: openblt_uart.dpr +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// L I C E N S E +//--------------------------------------------------------------------------------------- +// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with OpenBLT. +// If not, see . +// +// A special exception to the GPL is included to allow you to distribute a combined work +// that includes OpenBLT without being obliged to provide the source code for any +// proprietary components. The exception text is included at the bottom of the license +// file . +// +//*************************************************************************************** + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, + Messages, + Graphics, + Controls, + Forms, + Dialogs, + SysUtils, + Classes, + Extctrls, + XcpProtection in '..\XcpProtection.pas', + SRecReader in '..\SRecReader.pas', + XcpDataFile in '..\XcpDataFile.pas', + XcpLoader in '..\XcpLoader.pas', + XcpTransport in 'XcpTransport.pas', + XcpSettings in 'XcpSettings.pas' {XcpSettingsForm}, + CPDrv in 'CPDrv.pas'; + + +//*************************************************************************************** +// Global Constants +//*************************************************************************************** +const kMaxProgLen = 256; // maximum number of bytes to progam at one time + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +// DLL Interface Callbacks - modifications requires potential update of all interfaces! +type + TStartedEvent = procedure(length: Longword) of object; + TProgressEvent = procedure(progress: Longword) of object; + TDoneEvent = procedure of object; + TErrorEvent = procedure(error: ShortString) of object; + TLogEvent = procedure(info: ShortString) of object; + TInfoEvent = procedure(info: ShortString) of object; + +type + TEventHandlers = class // create a dummy class + procedure OnTimeout(Sender: TObject); + end; + +//*************************************************************************************** +// Global Variables +//*************************************************************************************** +var + //--- begin of don't change --- + AppOnStarted : TStartedEvent; + AppOnProgress : TProgressEvent; + AppOnDone : TDoneEvent; + AppOnError : TErrorEvent; + AppOnLog : TLogEvent; + AppOnInfo : TInfoEvent; + //--- end of don't change --- + timer : TTimer; + events : TEventHandlers; + loader : TXcpLoader; + datafile : TXcpDataFile; + progdata : array of Byte; + progfile : string; + stopRequest : boolean; + + +//*************************************************************************************** +// NAME: MbiCallbackOnStarted +// PARAMETER: length of the file that is being downloaded. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnStarted(length: Longword); +begin + if Assigned(AppOnStarted) then + begin + AppOnStarted(length); + end; +end; //** end of MbiCallbackOnStarted *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnProgress +// PARAMETER: progress of the file download. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnProgress(progress: Longword); +begin + if Assigned(AppOnProgress) then + begin + AppOnProgress(progress); + end; +end; //** end of MbiCallbackOnProgress *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnDone +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnDone; +begin + if Assigned(AppOnDone) then + begin + AppOnDone; + end; +end; //** end of MbiCallbackOnDone *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnError +// PARAMETER: info about the error that occured. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnError(error: ShortString); +begin + if Assigned(AppOnError) then + begin + AppOnError(error); + end; +end; //** end of MbiCallbackOnError *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnLog +// PARAMETER: info on the log event. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnLog(info: ShortString); +begin + if Assigned(AppOnLog) then + begin + AppOnLog(info); + end; +end; //** end of MbiCallbackOnLog *** + + +//*************************************************************************************** +// NAME: MbiCallbackOnInfo +// PARAMETER: details on the info event. +// RETURN VALUE: none +// DESCRIPTION: Wrapper function for safely calling an application callback +// +//*************************************************************************************** +procedure MbiCallbackOnInfo(info: ShortString); +begin + if Assigned(AppOnInfo) then + begin + AppOnInfo(info); + end; +end; //** end of MbiCallbackOnLog *** + + +//*************************************************************************************** +// NAME: LogData +// PARAMETER: pointer to byte array and the data length +// RETURN VALUE: none +// DESCRIPTION: Writes the program data formatted to the logfile +// +//*************************************************************************************** +procedure LogData(data : PByteArray; len : longword); stdcall; +var + currentWriteCnt : byte; + cnt : byte; + logStr : string; + bufferOffset : longword; +begin + bufferOffset := 0; + + while len > 0 do + begin + // set the current write length optimized to log 32 bytes per line + currentWriteCnt := len mod 32; + if currentWriteCnt = 0 then currentWriteCnt := 32; + logStr := ''; + + // prepare the line to add to the log + for cnt := 0 to currentWriteCnt-1 do + begin + logStr := logStr + Format('%2.2x ', [data[bufferOffset+cnt]]); + end; + + // update the log + MbiCallbackOnLog(logStr); + + // update loop variables + len := len - currentWriteCnt; + bufferOffset := bufferOffset + currentWriteCnt; + end; +end; //*** end of LogData *** + + +//*************************************************************************************** +// NAME: OnTimeout +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Timer event handler. A timer is used in this example to simulate the +// progress of a file download. It also demonstrates how to use the +// application callbacks to keep the application informed. +// +//*************************************************************************************** +procedure TEventHandlers.OnTimeout(Sender: TObject); +var + errorInfo : string; + progress : longword; + regionCnt : longword; + currentWriteCnt : word; + bufferOffset : longword; + addr : longword; + len : longword; + dataSizeKB : real; +begin + timer.Enabled := False; + + // connect the transport layer + MbiCallbackOnLog('Connecting the transport layer. t='+TimeToStr(Time)); + loader.Connect; + + //---------------- start the programming session -------------------------------------- + MbiCallbackOnLog('Starting the programming session. t='+TimeToStr(Time)); + + if not loader.StartProgrammingSession then + begin + // update the user info + MbiCallbackOnInfo('Could not connect. Please reset your target...'); + MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+TimeToStr(Time)); + Application.ProcessMessages; + end; + + while not loader.StartProgrammingSession do + begin + Application.ProcessMessages; + Sleep(5); + if stopRequest then + begin + MbiCallbackOnError('Programming session cancelled by user.'); + Exit; + end; + end; + + // still here so programming session was started + MbiCallbackOnLog('Programming session started. t='+TimeToStr(Time)); + + // create the datafile object + datafile := TXcpDataFile.Create(progfile); + + // compute the size in kbytes + dataSizeKB := datafile.GetDataCnt / 1024; + + // Call application callback when we start the actual download + MbiCallbackOnStarted(datafile.GetDataCnt); + + // Init progress to 0 progress + progress := 0; + MbiCallbackOnProgress(progress); + + //---------------- next clear the memory regions -------------------------------------- + // update the user info + MbiCallbackOnInfo('Erasing memory...'); + + for regionCnt := 0 to datafile.GetRegionCnt-1 do + begin + // obtain the region info + datafile.GetRegionInfo(regionCnt, addr, len); + + // erase the memory + MbiCallbackOnLog('Clearing Memory '+Format('addr:0x%x,len:0x%x',[addr,len])+'. t='+TimeToStr(Time)); + if not loader.ClearMemory(addr, len) then + begin + loader.GetLastError(errorInfo); + MbiCallbackOnLog('Could not clear memory ('+errorInfo+'). t='+TimeToStr(Time)); + MbiCallbackOnError('Could not clear memory ('+errorInfo+').'); + datafile.Free; + Exit; + end; + MbiCallbackOnLog('Memory cleared. t='+TimeToStr(Time)); + end; + + //---------------- next program the memory regions ------------------------------------ + for regionCnt := 0 to datafile.GetRegionCnt-1 do + begin + // update the user info + MbiCallbackOnInfo('Reading file...'); + + // obtain the region info + datafile.GetRegionInfo(regionCnt, addr, len); + // dynamically allocated buffer memory + SetLength(progdata, len); + // obtain the regiond data + datafile.GetRegionData(regionCnt, progdata); + + bufferOffset := 0; + while len > 0 do + begin + // set the current write length taking into account kMaxProgLen + currentWriteCnt := len mod kMaxProgLen; + if currentWriteCnt = 0 then currentWriteCnt := kMaxProgLen; + + // program the data + MbiCallbackOnLog('Programming Data '+Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt])+'. t='+TimeToStr(Time)); + LogData(@progdata[bufferOffset], currentWriteCnt); + + if not loader.WriteData(addr, currentWriteCnt, @progdata[bufferOffset]) then + begin + loader.GetLastError(errorInfo); + MbiCallbackOnLog('Could not program data ('+errorInfo+'). t='+TimeToStr(Time)); + MbiCallbackOnError('Could not program data ('+errorInfo+').'); + datafile.Free; + Exit; + end; + MbiCallbackOnLog('Data Programmed. t='+TimeToStr(Time)); + + // update progress + progress := progress + currentWriteCnt; + MbiCallbackOnProgress(progress); + + // update loop variables + len := len - currentWriteCnt; + addr := addr + currentWriteCnt; + bufferOffset := bufferOffset + currentWriteCnt; + + // update the user info + MbiCallbackOnInfo('Programming data... ' + Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB])); + + end; + end; + + //---------------- stop the programming session --------------------------------------- + MbiCallbackOnLog('Stopping the programming session. t='+TimeToStr(Time)); + if not loader.StopProgrammingSession then + begin + loader.GetLastError(errorInfo); + MbiCallbackOnLog('Could not stop the programming session ('+errorInfo+'). t='+TimeToStr(Time)); + MbiCallbackOnError('Could not stop the programming session ('+errorInfo+').'); + datafile.Free; + Exit; + end; + MbiCallbackOnLog('Programming session stopped. t='+TimeToStr(Time)); + + // all done so set progress to 100% and finish up + progress := datafile.GetDataCnt; + datafile.Free; + MbiCallbackOnProgress(progress); + MbiCallbackOnLog('File successfully downloaded t='+TimeToStr(Time)); + MbiCallbackOnDone; + +end; //*** end of OnTimeout *** + + +//*************************************************************************************** +// NAME: MbiInit +// PARAMETER: callback function pointers +// RETURN VALUE: none +// DESCRIPTION: Called by the application to initialize the interface library. +// +//*************************************************************************************** +procedure MbiInit(cbStarted: TStartedEvent; cbProgress: TProgressEvent; + cbDone: TDoneEvent; cbError: TErrorEvent; cbLog: TLogEvent; + cbInfo: TInfoEvent); stdcall; +begin + //--- begin of don't change --- + AppOnStarted := cbStarted; + AppOnProgress := cbProgress; + AppOnDone := cbDone; + AppOnLog := cbLog; + AppOnInfo := cbInfo; + AppOnError := cbError; + //--- end of don't change --- + + // create xcp loader object + loader := TXcpLoader.Create; + + // update to the latest configuration + loader.Configure(ExtractFilePath(ParamStr(0))+'openblt_uart.ini'); + + // create and init a timer + events := TEventHandlers.Create; + timer := TTimer.Create(nil); + timer.Enabled := False; + timer.Interval := 100; + timer.OnTimer := events.OnTimeout; +end; //*** end of MbiInit *** + + +//*************************************************************************************** +// NAME: MbiStart +// PARAMETER: filename of the file that is to be downloaded. +// RETURN VALUE: none +// DESCRIPTION: Called by the application to request the interface library to download +// the file that is passed as a parameter. +// +//*************************************************************************************** +procedure MbiStart(fileName: ShortString); stdcall; +begin + // update the user info + MbiCallbackOnInfo(''); + + // start the log + MbiCallbackOnLog('--- Downloading "'+fileName+'" ---'); + + // reset stop request + stopRequest := false; + + // start the startup timer which gives microBoot a chance to paint itself + timer.Enabled := True; + + // store the program's filename + progfile := fileName; +end; //*** end of MbiStart *** + + +//*************************************************************************************** +// NAME: MbiStop +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the application to request the interface library to stop +// a download that could be in progress. +// +//*************************************************************************************** +procedure MbiStop; stdcall; +begin + // set stop request + stopRequest := true; + + // disconnect the transport layer + MbiCallbackOnLog('Disconnecting the transport layer. t='+TimeToStr(Time)); + loader.Disconnect; +end; //*** end of MbiStop *** + + +//*************************************************************************************** +// NAME: MbiDeInit +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the application to uninitialize the interface library. +// +//*************************************************************************************** +procedure MbiDeInit; stdcall; +begin + // release xcp loader object + loader.Free; + + // release the timer and events object + timer.Free; + events.Free; + + //--- begin of don't change --- + AppOnStarted := nil; + AppOnProgress := nil; + AppOnDone := nil; + AppOnLog := nil; + AppOnInfo := nil; + AppOnError := nil; + //--- end of don't change --- +end; //*** end of MbiDeInit *** + + +//*************************************************************************************** +// NAME: MbiName +// PARAMETER: none +// RETURN VALUE: name of the interface library +// DESCRIPTION: Called by the application to obtain the name of the interface library. +// +//*************************************************************************************** +function MbiName : ShortString; stdcall; +begin + Result := 'OpenBLT UART'; +end; //*** end of MbiName *** + + +//*************************************************************************************** +// NAME: MbiDescription +// PARAMETER: none +// RETURN VALUE: description of the interface library +// DESCRIPTION: Called by the application to obtain the description of the interface +// library. +// +//*************************************************************************************** +function MbiDescription : ShortString; stdcall; +begin + Result := 'OpenBLT using UART'; +end; //*** end of MbiDescription *** + + +//*************************************************************************************** +// NAME: MbiVersion +// PARAMETER: none +// RETURN VALUE: version number +// DESCRIPTION: Called by the application to obtain the version number of the +// interface library. +// +//*************************************************************************************** +function MbiVersion : Longword; stdcall; +begin + Result := 10000; // v1.00.00 +end; //*** end of MbiVersion *** + + +//*************************************************************************************** +// NAME: MbiVInterface +// PARAMETER: none +// RETURN VALUE: version number of the supported interface +// DESCRIPTION: Called by the application to obtain the version number of the +// Mbi interface uBootInterface.pas (not the interface library). This can +// be used by the application for backward compatibility. +// +//*************************************************************************************** +function MbiVInterface : Longword; stdcall; +begin + Result := 10001; // v1.00.01 +end; //*** end of MbiVInterface *** + + +//*************************************************************************************** +// NAME: MbiConfigure +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Called by the application to enable the user to configure the inter- +// face library through the application. +// +//*************************************************************************************** +procedure MbiConfigure; stdcall; +var + settings : TXcpSettings; +begin + // create xcp settings object + settings := TXcpSettings.Create(ExtractFilePath(ParamStr(0))+'openblt_uart.ini'); + + // display the modal configuration dialog + settings.Configure; + + // release the xcp settings object + settings.Free; + + // update to the latest configuration + loader.Configure(ExtractFilePath(ParamStr(0))+'openblt_uart.ini'); +end; //*** end of MbiConfigure *** + + +//*************************************************************************************** +// External Declarations +//*************************************************************************************** +exports + //--- begin of don't change --- + MbiInit index 1, + MbiStart index 2, + MbiStop index 3, + MbiDeInit index 4, + MbiName index 5, + MbiDescription index 6, + MbiVersion index 7, + MbiConfigure index 8, + MbiVInterface index 9; + //--- end of don't change --- + +end. +//********************************** end of openblt_uart.dpr **************************** diff --git a/Host/Source/uBootInterface.pas b/Host/Source/uBootInterface.pas new file mode 100644 index 00000000..0af2e588 --- /dev/null +++ b/Host/Source/uBootInterface.pas @@ -0,0 +1,422 @@ +unit uBootInterface; +//*************************************************************************************** +// Project Name: TMicroBootInterface component for Borland Delphi +// Description: Encapsulates the MicroBoot DLL interface +// File Name: uBootInterface.pas +// +//--------------------------------------------------------------------------------------- +// C O P Y R I G H T +//--------------------------------------------------------------------------------------- +// Copyright (c) by Feaser LLC All rights reserved. +// +// This software has been carefully tested, but is not guaranteed for any particular +// purpose. The author does not offer any warranties and does not guarantee the accuracy, +// adequacy, or completeness of the software and is not responsible for any errors or +// omissions or the results obtained from use of the software. +// +//--------------------------------------------------------------------------------------- +// A U T H O R I D E N T I T Y +//--------------------------------------------------------------------------------------- +// Initials Name Contact +// -------- --------------------- ---------------------- +// Vg Frank Voorburg voorburg@feaser.com +// +//--------------------------------------------------------------------------------------- +// R E V I S I O N H I S T O R Y +//--------------------------------------------------------------------------------------- +// Date Version Author Description +// --------- ------- ------ -------------------------------------------------------- +// 01-Aug-05 1.00.00 Vg - Creation +//*************************************************************************************** +interface + + +//*************************************************************************************** +// Includes +//*************************************************************************************** +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; + + +//*************************************************************************************** +// Type Definitions +//*************************************************************************************** +// DLL Interface Callbacks - modifications requires potential update of all interfaces! +type + TStartedEvent = procedure(length: Longword) of object; + TProgressEvent = procedure(progress: Longword) of object; + TDoneEvent = procedure of object; + TErrorEvent = procedure(error: ShortString) of object; + TLogEvent = procedure(info: ShortString) of object; + TInfoEvent = procedure(info: ShortString) of object; + +// DLL Interface Methods - modifications requires potential update of all interfaces! +type + TDllMbiInit = procedure(cbStarted: TStartedEvent; cbProgress: TProgressEvent; + cbDone: TDoneEvent; cbError: TErrorEvent; + cbLog: TLogEvent; cbInfo: TInfoEvent); stdcall; + TDllMbiStart = procedure(fileName: ShortString); stdcall; + TDllMbiStop = procedure; stdcall; + TDllMbiDeInit = procedure; stdcall; + TDllMbiName = function : ShortString; stdcall; + TDllMbiDescription = function : ShortString; stdcall; + TDllMbiVersion = function : Longword; stdcall; + TDllMbiConfigure = procedure; stdcall; + TDllMbiVInterface = function : Longword; stdcall; + +// Interface Class +type + TMicroBootInterface = class(TComponent) + private + { Private declarations } + DllMbiInit : TDllMbiInit; + DllMbiStart : TDllMbiStart; + DllMbiStop : TDllMbiStop; + DllMbiDeInit : TDllMbiDeInit; + DllMbiName : TDllMbiName; + DllMbiDescription : TDllMbiDescription; + DllMbiVersion : TDllMbiVersion; + DllMbiConfigure : TDllMbiConfigure; + DllMbiVInterface : TDllMbiVInterface; + protected + { Protected declarations } + FLibraryFile : string; + FLibraryHandle : THandle; + FOnStarted : TStartedEvent; + FOnProgress : TProgressEvent; + FOnDone : TDoneEvent; + FOnError : TErrorEvent; + FOnLog : TLogEvent; + FOnInfo : TInfoEvent; + public + { Public declarations } + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function Enable(libraryFile: string; evStarted: TStartedEvent; + evProgress: TProgressEvent; evDone: TDoneEvent; + evError: TErrorEvent; evLog: TLogEvent; + evInfo: TInfoEvent) : Boolean; + procedure Disable; + procedure Download(fileName: ShortString); + procedure Cancel; + function Name : ShortString; + function Description : ShortString; + function Version : Longword; + procedure Configure; + function VInterface : Longword; + published + { Published declarations } + end; + + +implementation +//*************************************************************************************** +// NAME: Create +// PARAMETER: AOwner : owner of the component +// RETURN VALUE: none +// DESCRIPTION: Component constructor. Calls TComponent's constructor and initializes +// the private property variables to their default values. +// +//*************************************************************************************** +constructor TMicroBootInterface.Create(AOwner: TComponent); +begin + // call inherited constructor + inherited Create( AOwner ); + + // initialize the callback pointers + FOnStarted := nil; + FOnProgress := nil; + FOnDone := nil; + FOnError := nil; + FOnLog := nil; + FOnInfo := nil; + + // initialize the properties + FLibraryFile := ''; + FLibraryHandle := 0; +end; //*** end of Create *** + + +//*************************************************************************************** +// NAME: Destroy +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Component destructor. Calls TComponent's destructor +// +//*************************************************************************************** +destructor TMicroBootInterface.Destroy; +begin + if FLibraryHandle = 0 then //##Vg shouldn't this be <> 0? + begin + FreeLibrary(FLibraryHandle); // release the handle + end; + + inherited Destroy; // call inherited destructor +end; //*** end of Destroy *** + + +//*************************************************************************************** +// NAME: Enable +// PARAMETER: name of library file and pointers to the callback functions. +// RETURN VALUE: true: interface library ready, false: error occurred. +// DESCRIPTION: Used to connect the interface library to the application. +// +//*************************************************************************************** +function TMicroBootInterface.Enable(libraryFile: string; evStarted: TStartedEvent; + evProgress: TProgressEvent; evDone: TDoneEvent; + evError: TErrorEvent; evLog: TLogEvent; + evInfo :TInfoEvent) : Boolean; +var + Initialized : Boolean; +begin + Initialized := True; + + // first make sure the interface is disabled + Disable; + + // set the library file + if (FileExists(libraryFile)) and (LowerCase(ExtractFileExt(libraryFile)) = '.dll') then + begin + FLibraryFile := libraryFile; + end; + + // set the callback functions + if Assigned(evStarted) then FOnStarted := evStarted; + if Assigned(evProgress) then FOnProgress := evProgress; + if Assigned(evDone) then FOnDone := evDone; + if Assigned(evError) then FOnError := evError; + if Assigned(evLog) then FOnLog := evLog; + if Assigned(evInfo) then FOnInfo := evInfo; + + // check if callback functions are configured properly + if not Assigned(FOnStarted) then Initialized := False; + if not Assigned(FOnProgress) then Initialized := False; + if not Assigned(FOnDone) then Initialized := False; + if not Assigned(FOnError) then Initialized := False; + if not Assigned(FOnLog) then Initialized := False; + if not Assigned(FOnInfo) then Initialized := False; + + // check if a proper library file is configured + if FLibraryFile = '' then Initialized := False; + + // only continue if everything was okay sofar + if Initialized = True then + begin + // attempt to obtain a handle to the interface library + FLibraryHandle := LoadLibrary(PChar(FLibraryFile)); + if FLibraryHandle = 0 then Initialized := False; + end; + + // only continue if everything was okay sofar + if Initialized = True then + begin + // attempt to obtain the function pointers from the interface library + @DllMbiInit := GetProcAddress(FLibraryHandle, 'MbiInit'); + @DllMbiStart := GetProcAddress(FLibraryHandle, 'MbiStart'); + @DllMbiStop := GetProcAddress(FLibraryHandle, 'MbiStop'); + @DllMbiDeInit := GetProcAddress(FLibraryHandle, 'MbiDeInit'); + @DllMbiName := GetProcAddress(FLibraryHandle, 'MbiName'); + @DllMbiDescription := GetProcAddress(FLibraryHandle, 'MbiDescription'); + @DllMbiVersion := GetProcAddress(FLibraryHandle, 'MbiVersion'); + @DllMbiConfigure := GetProcAddress(FLibraryHandle, 'MbiConfigure'); + @DllMbiVInterface := GetProcAddress(FLibraryHandle, 'MbiVInterface'); + end; + + // check if the functions were found in the interface library + if not Assigned(DllMbiInit) then Initialized := False; + if not Assigned(DllMbiStart) then Initialized := False; + if not Assigned(DllMbiStop) then Initialized := False; + if not Assigned(DllMbiDeInit) then Initialized := False; + if not Assigned(DllMbiName) then Initialized := False; + if not Assigned(DllMbiDescription) then Initialized := False; + if not Assigned(DllMbiVersion) then Initialized := False; + if not Assigned(DllMbiConfigure) then Initialized := False; + if not Assigned(DllMbiVInterface) then Initialized := False; + + // only continue if everything was okay sofar + if Initialized = True then + begin + // pass callback function pointers on to the interface library + DllMbiInit(FOnStarted, FOnProgress, FOnDone, FOnError, FOnLog, FOnInfo); + end + else + begin + // error occured so make sure to reset the handle to the interface library + FLibraryHandle := 0; + end; + + Result := Initialized; +end; //*** end of Enable *** + + +//*************************************************************************************** +// NAME: Download +// PARAMETER: filename with full path +// RETURN VALUE: none +// DESCRIPTION: Requests the interface library to start the download of a file. +// +//*************************************************************************************** +procedure TMicroBootInterface.Download(fileName: ShortString); +begin + // only continue with we have a valid interface library handle + if FLibraryHandle <> 0 then + begin + // pass control for file download to the library + DllMbiStart(fileName); + end; +end; //*** end of Download *** + + +//*************************************************************************************** +// NAME: Cancel +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Cancels a possible active file download. +// +//*************************************************************************************** +procedure TMicroBootInterface.Cancel; +begin + // only continue with we have a valid interface library handle + if FLibraryHandle <> 0 then + begin + DllMbiStop; // let interface library handle the stop request + end; +end; //*** end of Cancel *** + + +//*************************************************************************************** +// NAME: Disable +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Disables the interface library. +// +//*************************************************************************************** +procedure TMicroBootInterface.Disable; +begin + // only continue with we have a valid interface library handle + if FLibraryHandle <> 0 then + begin + DllMbiDeInit; // inform the dll aswell that we're disabling + FreeLibrary(FLibraryHandle); // release the handle + end; + + // initialize the callback pointers + FOnStarted := nil; + FOnProgress := nil; + FOnDone := nil; + FOnError := nil; + FOnLog := nil; + FOnInfo := nil; + + // initialize the properties + FLibraryFile := ''; + FLibraryHandle := 0; +end; //*** end of Disable *** + + +//*************************************************************************************** +// NAME: Name +// PARAMETER: none +// RETURN VALUE: Name of the interface library +// DESCRIPTION: Obtains the name of the interface library. +// +//*************************************************************************************** +function TMicroBootInterface.Name : ShortString; +begin + // only continue with we have a valid interface library handle + if FLibraryHandle <> 0 then + begin + Result := DllMbiName; // obtain the request info from the interface + end + else + begin + Result := ''; + end; +end; //*** end of Name *** + + +//*************************************************************************************** +// NAME: Description +// PARAMETER: none +// RETURN VALUE: Description of the interface library +// DESCRIPTION: Obtains the description of the interface library. +// +//*************************************************************************************** +function TMicroBootInterface.Description : ShortString; +begin + // only continue with we have a valid interface library handle + if FLibraryHandle <> 0 then + begin + Result := DllMbiDescription; // obtain the request info from the interface + end + else + begin + Result := ''; + end; +end; //*** end of Description *** + + +//*************************************************************************************** +// NAME: Version +// PARAMETER: none +// RETURN VALUE: version of the library interface +// DESCRIPTION: Obtains the version of the interface library. +// +//*************************************************************************************** +function TMicroBootInterface.Version : Longword; +begin + // only continue with we have a valid interface library handle + if FLibraryHandle <> 0 then + begin + Result := DllMbiVersion; // obtain the request info from the interface + end + else + begin + Result := 0; + end; +end; //*** end of Version *** + + +//*************************************************************************************** +// NAME: VInterface +// PARAMETER: none +// RETURN VALUE: Version of uBootInterface.pas +// DESCRIPTION: Obtains the version of the uBootInterface that is supported by the +// interface library. +// +//*************************************************************************************** +function TMicroBootInterface.VInterface : Longword; +begin + // only continue with we have a valid interface library handle + if FLibraryHandle <> 0 then + begin + Result := DllMbiVInterface; // obtain the request info from the interface + end + else + begin + Result := 0; + end; +end; //*** end of Version *** + + +//*************************************************************************************** +// NAME: Configure +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Used to request the configuration of the interface library. +// +//*************************************************************************************** +procedure TMicroBootInterface.Configure; +begin + // only continue with we have a valid interface library handle + if FLibraryHandle <> 0 then + begin + DllMbiConfigure; // let interface handle the configuration request + end; +end; //*** end of Configure *** + + +end. +//******************************* end of uBootInterface.pas ***************************** + + diff --git a/Host/openblt_can_peak.dll b/Host/openblt_can_peak.dll new file mode 100644 index 0000000000000000000000000000000000000000..11d0e1ac2a9cdad84b28a3e022ac17b6082c76a4 GIT binary patch literal 396288 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�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