diff --git a/boards/LICENSE b/boards/LICENSE new file mode 100644 index 0000000000..f99be76ab3 --- /dev/null +++ b/boards/LICENSE @@ -0,0 +1,454 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/boards/Makefile b/boards/Makefile new file mode 100644 index 0000000000..7a3c9d345b --- /dev/null +++ b/boards/Makefile @@ -0,0 +1,5 @@ +all: + "$(MAKE)" -C $(BOARD) + +clean: + "$(MAKE)" -C $(BOARD) clean diff --git a/boards/Makefile.base b/boards/Makefile.base new file mode 100644 index 0000000000..0b860294f9 --- /dev/null +++ b/boards/Makefile.base @@ -0,0 +1,30 @@ +ifeq ($(BOARD),msba2) + INCLUDES += -I$(RIOTBOARD)/msba2/include/ + INCLUDES += -I$(RIOTBOARD)/msba2-common/include/ + INCLUDES += -I$(RIOTBOARD)/msba2-common/drivers/include/ +endif +ifeq ($(BOARD),msb-430) + INCLUDES += -I$(RIOTBOARD)/msb-430/include/ + INCLUDES += -I$(RIOTBOARD)/msb-430-common/include/ + INCLUDES += -I$(RIOTBOARD)/msb-430-common/drivers/include/ +endif +ifeq ($(BOARD),msb-430h) + INCLUDES += -I$(RIOTBOARD)/msb-430h/include/ + INCLUDES += -I$(RIOTBOARD)/msb-430-common/include/ + INCLUDES += -I$(RIOTBOARD)/msb-430-common/drivers/include/ +endif +ifeq ($(BOARD),wsn430-v1_3b) + INCLUDES += -I$(RIOTBOARD)/wsn430-v1_3b/include/ + INCLUDES += -I$(RIOTBOARD)/wsn430-common/include/ +endif +ifeq ($(BOARD),wsn430-v1_4) + INCLUDES += -I$(RIOTBOARD)/wsn430-v1_4/include/ + INCLUDES += -I$(RIOTBOARD)/wsn430-common/include/ +endif +ifeq ($(BOARD),chronos) + INCLUDES += -I$(RIOTBOARD)/chronos/include/ + INCLUDES += -I$(RIOTBOARD)/chronos/drivers/include/ +endif +ifeq ($(BOARD),native) + INCLUDES += -I$(RIOTBOARD)/native/include/ +endif diff --git a/boards/README.md b/boards/README.md new file mode 100644 index 0000000000..cda1a563ea --- /dev/null +++ b/boards/README.md @@ -0,0 +1,6 @@ +Platform configurations for RIOT-OS +==================================== +This repository contains existing configuration and initialization files for platforms supported by RIOT-OS. + +RIOT's kernel, system libraries, and drivers can be found here: +https://github.com/RIOT-OS/RIOT diff --git a/boards/avsextrem/Makefile b/boards/avsextrem/Makefile new file mode 100644 index 0000000000..3597e18c73 --- /dev/null +++ b/boards/avsextrem/Makefile @@ -0,0 +1,38 @@ +SRC = $(wildcard *.c) +BINDIR = bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +export ARCH = avsextrem_base.a + +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBOARD)/msba2-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/arm_common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/lpc2387/include/ +INCLUDES += -I$(RIOTBASE)/drivers/cc110x + +all: $(BINDIR)$(ARCH) + "$(MAKE)" -C ../msba2-common + "$(MAKE)" -C drivers + +$(BINDIR)$(ARCH): $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + mkdir -p $(BINDIR) + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + "$(MAKE)" -C ../msba2-common clean + "$(MAKE)" -C drivers clean + rm -f $(BINDIR)$(ARCH) $(OBJ) $(DEP) + @if [ -d $(BINDIR) ] ; \ + then rmdir $(BINDIR) ; \ + fi + diff --git a/boards/avsextrem/Makefile.include b/boards/avsextrem/Makefile.include new file mode 100644 index 0000000000..741b952a92 --- /dev/null +++ b/boards/avsextrem/Makefile.include @@ -0,0 +1,3 @@ +export INCLUDES += -I$(RIOTBOARD)/msba2-common/include + +include $(RIOTBOARD)/msba2-common/Makefile.include diff --git a/boards/avsextrem/board_init.c b/boards/avsextrem/board_init.c new file mode 100644 index 0000000000..419198da9a --- /dev/null +++ b/boards/avsextrem/board_init.c @@ -0,0 +1,202 @@ +/* +* board_init.c - initialization of the AVSEXTREM-BOARD. +* Copyright (C) 2013 Heiko Will +* +* This source code is licensed under the LGPLv2 license, +* See the file LICENSE for more details. +* +*/ + + +/** + * @file + * @brief avsextrem board initialization + * + * @author Freie Universität Berlin, Computer Systems & Telematics + * @author Heiko Will + * @author Kaspar Schleise + * @author Michael Baar + * @author Zakaria Kasmi + * @author Marco Ziegert + * @author Stefan Pfeiffer + * + * @note $Id: board_init.c 1071 2013-09-19 16:50:56 kasmi $ + */ +#include "lpc23xx.h" +#include "VIC.h" +#include "cpu.h" +#include "gpioint.h" + +#define PCRTC BIT9 +#define CL_CPU_DIV 4 + + +/*---------------------------------------------------------------------------*/ +static inline void +pllfeed(void) +{ + PLLFEED = 0xAA; + PLLFEED = 0x55; +} + +/*---------------------------------------------------------------------------*/ +void init_clks1(void) +{ + // Disconnect PLL + PLLCON &= ~0x0002; + pllfeed(); + + while (PLLSTAT & BIT25); /* wait until PLL is disconnected before + * disabling - deadlock otherwise */ + + // Disable PLL + PLLCON &= ~0x0001; + pllfeed(); + + while (PLLSTAT & BIT24); // wait until PLL is disabled + + SCS |= 0x10; // main OSC between 15MHz and 24MHz (more stable in tests) + SCS |= 0x20; // Enable main OSC + + while (!(SCS & 0x40)); // Wait until main OSC is usable + + /* select main OSC, 16MHz, as the PLL clock source */ + CLKSRCSEL = 0x0001; + + // Setting Multiplier and Divider values + PLLCFG = 0x0008; // M=9 N=1 Fcco = 288 MHz + pllfeed(); + + // Enabling the PLL */ + PLLCON = 0x0001; + pllfeed(); + + /* Set clock divider to 4 (value+1) */ + CCLKCFG = CL_CPU_DIV - 1; // Fcpu = 72 MHz + +#if USE_USB + USBCLKCFG = USBCLKDivValue; /* usbclk = 288 MHz/6 = 48 MHz */ +#endif +} + +/*---------------------------------------------------------------------------*/ +void bl_init_ports(void) +{ + SCS |= BIT0; // Set IO Ports to fast switching mode + + /* UART0 */ + PINSEL0 |= BIT4 + BIT6; // RxD0 and TxD0 + PINSEL0 &= ~(BIT5 + BIT7); + + //PTTU: + + /*Turn Board on*/ + // PINMODE0 |= BIT1; + // FIO0DIR |= BIT27; + // FIO0CLR = BIT27; + // 0.27 + + /* 5V*/ + // FIO1DIR |= BIT28; // Synch + // FIO1SET = BIT28; // No Powersave + // 1.28 + + // FIO1DIR |= BIT27; // 5V off + // FIO1CLR = BIT27; + // 1.27 + + /* Disable Resistors on Buttons */ + // PINMODE4 |= BIT9 + BIT11; + // + + /* Disable Resistors on LED - and Ports to output*/ + PINMODE7 |= BIT19 + BIT21; //3.25 + 3.26 + PINMODE2 |= BIT1; //1.0 + FIO1DIR |= BIT0; + FIO3DIR |= BIT25 + BIT26; + FIO1SET = BIT0; //all off + FIO3SET = BIT25 + BIT26; + + // Config and Disable PA + // FIO1DIR |= BIT25 + BIT26 + BIT22; + // FIO1SET = BIT26; + // FIO1CLR = BIT25; + // FIO1CLR = BIT22; // PA /Shutdown + // Important: First put this Port as DA 2.0V and then turn on PA!! + // FIO0DIR |= BIT26; + // FIO0SET = BIT26; + // 1.22 + 1.25 + 1.26 + + // Configure GPS + PINMODE3 |= BIT3 + BIT7; // No Pullup on 1.17 & 1.19 + PINMODE9 |= BIT27 + BIT25; // No Pullup for Uart + FIO1DIR |= BIT17; + FIO1CLR = BIT17; // Turn off GPS + FIO1DIR |= BIT19; + FIO1CLR = BIT19; // Hold in Reset + PINSEL9 |= BIT24 + BIT25 + BIT26 + BIT27; //4.28 & 4.29 as Uart3 + + // Nanotron + FIO2DIR &= ~BIT8; // nanotron uC IRQ as input + FIO1DIR |= BIT15; // nanotron power on reset + FIO1DIR &= ~BIT14; // nanotron uC RESET as input + FIO1DIR &= ~BIT10; // nanotron uC Vcc as input + FIO1DIR |= BIT9; // nanotron ENABLE as output + FIO1DIR &= ~BIT4; // nanotron Rx/Tx as input + + FIO1CLR = BIT15; + FIO1CLR = BIT9; // Enable power + + PINMODE1 |= BIT1; // No Pullup for CS + FIO0DIR |= BIT16; // CS as output + FIO0SET = BIT16; // drive cs inactive + FIO0DIR |= BIT18 + BIT15; // SPi Output + + // RFID + // FIO1DIR |= BIT1; // RFID Power + // FIO1CLR = BIT1; + // + // FIO0DIR |= BIT1; // RFID Reset + // FIO0SET = BIT1; // Hold in Reset + // + // FIO0DIR &= ~BIT10; // LED as INPUT + // FIO0DIR &= ~BIT11; // DATA as INPUT + // PINMODE0 |= BIT19 + BIT21; // No Pullups + // 1.1 + 0.1 + 0.10 + 0.11 + + // LTC4150 ARM + FIO0DIR |= BIT5; + FIO0CLR = BIT5; + + // LTC4150 System + // FIO0DIR |= BIT24; + // FIO0CLR = BIT24; + // 0.23 + 0.24 + + // Battery Voltage (AD) + PINMODE1 |= BIT19; //0.25 + PINSEL1 &= ~BIT19; + PINSEL1 |= BIT18; + + //cc1100 + FIO0DIR |= BIT6 + BIT7 + BIT9; + FIO0SET = BIT6; + FIO0SET = BIT7 + BIT9; + + //SMB380 + FIO1DIR |= BIT20 + BIT21 + BIT24; //SCK + CSB + SDI + FIO1SET = BIT21; + FIO1SET = BIT20 + 24; + + //SHT11 + FIO1DIR |= BIT25; //1.25 + PINSEL3 &= ~(BIT12 | BIT13 | BIT18 | BIT19); + + //SD + FIO0DIR &= ~(BIT19 | BIT20 | BIT21 | BIT22) ; //0.19 0.20 0.21 0.22 as input + PINMODE1 |= (BIT7) | (BIT9) | (BIT11) | (BIT13); // no resistors + FIO2DIR &= ~(BIT11 + BIT12 + BIT13); //2.11 2.12 2.13 as input + PINMODE4 |= (BIT23) | (BIT25) | (BIT27); // no resistors + +} + diff --git a/boards/avsextrem/drivers/Makefile b/boards/avsextrem/drivers/Makefile new file mode 100644 index 0000000000..71736befcc --- /dev/null +++ b/boards/avsextrem/drivers/Makefile @@ -0,0 +1,24 @@ +SRC = $(wildcard *.c) +BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o) +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBASE)/sys/include/ -I$(RIOTBASE)/drivers/cc110x_ng/include/ -I$(RIOTBOARD)/$(BOARD)/include + +$(BINDIR)avsextrem_base.a: $(OBJ) + $(AR) rcs $(BINDIR)${ARCH} $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)" | cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products + +clean: + rm -f $(BINDIR)$(MODULE).a $(OBJ) $(DEP) $(ASMOBJ) + diff --git a/boards/avsextrem/drivers/avsextrem-cc1100.c b/boards/avsextrem/drivers/avsextrem-cc1100.c new file mode 100644 index 0000000000..ee83ebbd90 --- /dev/null +++ b/boards/avsextrem/drivers/avsextrem-cc1100.c @@ -0,0 +1,257 @@ +/* +* avsextrem-cc1100.c - CC100 Transceiver Driver for the AVSEXTREM-BOARD. +* Copyright (C) 2013 Heiko Will +* +* This source code is licensed under the LGPLv2 license, +* See the file LICENSE for more details. +* +*/ + + +/** + * @file + * @ingroup LPC2387 + * @brief CC1100 LPC2387 dependend functions + * + * @author Freie Universität Berlin, Computer Systems & Telematics + * @author Heiko Will + * @author Thomas Hillebrandt + * @author Zakaria Kasmi + * + * @version $Revision: 1781 $ + * + * @note $Id: avsextrem-cc1100.c 1781 2013-08-14 13:39:36Z kasmi $ + */ + +#include +#include +// cpu +#include "cpu.h" +// sys +#include "cc1100.h" +#include "arch_cc1100.h" +#include "cc1100_spi.h" +#include "gpioint.h" + +#define CC1100_GDO0 (FIO2PIN & BIT6) // read serial I/O (GDO0) +#define CC1100_GDO1 (FIO0PIN & BIT8) // read serial I/O (GDO1) +#define CC1100_GDO2 (FIO0PIN & BIT28) // read serial I/O (GDO2) + +#define SPI_TX_EMPTY (SSP1SR & SSPSR_TFE) +#define SPI_BUSY (SSP1SR & SSPSR_BSY) +#define SPI_RX_AVAIL (SSP1SR & SSPSR_RNE) + +#define CC1100_GDO1_LOW_RETRY (100) // max. retries for GDO1 to go low +#define CC1100_GDO1_LOW_COUNT (2700) // loop count (timeout ~ 500 us) to wait +// for GDO1 to go low when CS low + +//#define DEBUG +#ifdef DEBUG + +#include "stdio.h" + +static unsigned long time_value; + +static void set_time(void) +{ + time_value = 0; +} + +static int test_time(int code) +{ + time_value++; + + if (time_value > 10000000) { + printf("CC1100 SPI alarm: %u!\n", code); + time_value = 0; + return 1; + } + + return 0; +} +#endif + +int cc1100_get_gdo0(void) +{ + return CC1100_GDO0; +} + +int cc1100_get_gdo1(void) +{ + return CC1100_GDO1; +} + +int cc1100_get_gdo2(void) +{ + return CC1100_GDO2; +} + +void cc1100_spi_init(void) +{ + // configure chip-select + FIO0DIR |= BIT6; + FIO0SET = BIT6; + + // Power + PCONP |= PCSSP1; // Enable power for SSP1 (default is on) + + // PIN Setup + PINSEL0 |= BIT15; // Set CLK function to SSP1 + PINSEL0 &= ~BIT14; + PINSEL0 |= BIT17 ; // Set MISO function to SSP1 + PINSEL0 &= ~BIT16; + PINSEL0 |= BIT19; // Set MOSI function to SSP1 + PINSEL0 &= ~BIT18; + // Interface Setup + SSP1CR0 = 7; + + // Clock Setup + uint32_t pclksel; + uint32_t cpsr; + lpc2387_pclk_scale(F_CPU / 1000, 6000, &pclksel, &cpsr); + PCLKSEL0 &= ~(BIT21 | BIT20); // CCLK to PCLK divider + PCLKSEL0 |= pclksel << 20; + SSP1CPSR = cpsr; + + // Enable + SSP1CR1 |= BIT1; // SSP-Enable + int dummy; + + // Clear RxFIFO: + while (SPI_RX_AVAIL) { // while RNE (Receive FIFO Not Empty)... + dummy = SSP1DR; // read data + } +} + +uint8_t +cc1100_txrx(uint8_t c) +{ + uint8_t result; + SSP1DR = c; +#ifdef DEBUG + set_time(); +#endif + + while (!SPI_TX_EMPTY) { +#ifdef DEBUG + test_time(0); +#endif + } + +#ifdef DEBUG + set_time(); +#endif + + while (SPI_BUSY) { +#ifdef DEBUG + test_time(1); +#endif + } + +#ifdef DEBUG + set_time(); +#endif + + while (!SPI_RX_AVAIL) { +#ifdef DEBUG + test_time(2); +#endif + } + + result = (uint8_t)SSP1DR; + return result; +} + +void cc1100_spi_cs(void) +{ + FIO0CLR = BIT6; +} + +void +cc1100_spi_select(void) +{ + volatile int retry_count = 0; + volatile int abort_count; + // Switch to GDO mode input + PINSEL0 &= ~(BIT17 + BIT16); // Set MISO function to GPIO + FIO0DIR &= ~BIT8; +cs_low: + // CS to low + abort_count = 0; + FIO0CLR = BIT6; + // Wait for SO to go low (voltage regulator + // has stabilized and the crystal is running) +loop: + asm volatile("nop"); + + if (CC1100_GDO1) { + abort_count++; + + if (abort_count > CC1100_GDO1_LOW_COUNT) { + retry_count++; + + if (retry_count > CC1100_GDO1_LOW_RETRY) { + puts("[CC1100 SPI] fatal error\n"); + goto final; + } + + FIO0SET = BIT6; // CS to high + goto cs_low; // try again + } + + goto loop; + } + +final: + // Switch to SPI mode + PINSEL0 |= BIT17; // Set MISO function to SSP1 + PINSEL0 &= ~BIT16; +} + +void +cc1100_spi_unselect(void) +{ + FIO0SET = BIT6; +} + +void cc1100_gdo2_disable(void) +{ + gpioint_set(0, BIT28, GPIOINT_DISABLE, NULL); +} + +void cc1100_gdo2_enable(void) +{ + gpioint_set(0, BIT28, GPIOINT_FALLING_EDGE, &cc1100_gdo2_irq); +} + +void cc1100_before_send(void) +{ + // Disable GDO2 interrupt before sending packet + cc1100_gdo2_disable(); +} + +void cc1100_after_send(void) +{ + // Enable GDO2 interrupt after sending packet + cc1100_gdo2_enable(); +} + +void cc1100_gdo0_enable(void) +{ + gpioint_set(2, BIT6, GPIOINT_RISING_EDGE, &cc1100_gdo0_irq); +} + +void cc1100_gdo0_disable(void) +{ + gpioint_set(2, BIT6, GPIOINT_DISABLE, NULL); +} + +void cc1100_init_interrupts(void) +{ + // Enable external interrupt on low edge (for GDO2) + FIO0DIR &= ~BIT28; + cc1100_gdo2_enable(); + // Enable external interrupt on low edge (for GDO0) + FIO2DIR &= ~BIT6; +} + diff --git a/boards/avsextrem/drivers/avsextrem-smb380.c b/boards/avsextrem/drivers/avsextrem-smb380.c new file mode 100644 index 0000000000..5cc084f73d --- /dev/null +++ b/boards/avsextrem/drivers/avsextrem-smb380.c @@ -0,0 +1,1338 @@ +/* + * msba2acc-smb380.c - implementation of the Driver for the SMB380 acceleration + * sensor on the AVSEXTREM board. + * Copyright (C) 2013 Freie Universität Berlin + * + * This source code is licensed under the LGPLv2 license, + * See the file LICENSE for more details. + * + */ + +/** + * @file + * @internal + * @brief SMB380 acceleration sensor driver for the LPC2387 on the + * AVSEXTREM board. + * + * @author Freie Universität Berlin, Computer Systems & Telematics + * @author Marco Ziegert + * @author Zakaria Kasmi + * @version $Revision: 3854 $ + * + * @note $Id: msba2acc-smb380.c 3854 2010-01-18 15:27:01Z zkasmi $ + */ + + +#include "lpc23xx.h" /* LPC23XX/24xx Peripheral Registers */ +#include "cpu.h" +#include "lpm.h" +//#include "PatrecInit.h" +#include "VIC.h" +#include "kernel.h" +#include "ssp0-board.h" +#include "smb380-board.h" +#include "hwtimer.h" +#include +#include +// for fk_thread: +#include "sched.h" +#include "msg.h" +#include "irq.h" + +//#include "hal-board.h" +#include "gpioint.h" +#include "stdlib.h" +#include "math.h" +#include "lpc2387.h" + + +uint8_t simple_pid; +int16_t simple_buffer[4]; + +volatile int16_t *ringBuff_X = NULL; +volatile int16_t *ringBuff_Y = NULL; +volatile int16_t *ringBuff_Z = NULL; +volatile int16_t *ringBuff_T = NULL; +uint16_t readPointerPos[SMB380_RING_BUFF_MAX_THREADS]; +u_char PointerList[SMB380_RING_BUFF_MAX_THREADS]; +static msg_t wakeupmessage; + +/* + * pointer to a user-defined function which is called during a writepointer + * action + */ +uint8_t (*smb380function)(int16_t *); +uint16_t sampleRateSMB380; // condition if range-check should be done +bool dynRange = false; +uint8_t counter_Decreasing = 0; + +volatile uint16_t interruptTicksSMB380; + +typedef struct { + u_int writePointerPos; //Writepointer position + /* + * check value for updated range settings (only needed for multiplication + * in Float-mode + */ + uint8_t countRange; + uint8_t range; //current range +} settingsSMB380; + +settingsSMB380 settings; + +// measuring temperature dependent internal sample rate of SMB380 +static volatile uint32_t tickStart = 0; +static volatile uint32_t tickLastSample = 0; +static volatile uint32_t tickCurrentSamples = 0; + +uint8_t initRingReadPointerforCurrentThread(void); +uint8_t getRingReadPointerforCurrentThread(void); +void wakeUpRegisteredProcesses(void); +uint8_t smb380emptyfunction(int16_t *); +static void SMB380_extIntHandler(void); + +extern unsigned long ktimer_now(void); + +float SMB380_getSampleRatio(void) +{ + return ((1.0 / ((float)(tickLastSample - tickStart) / tickCurrentSamples)) * + 100000); +} + +uint8_t smb380emptyfunction(int16_t *value) +{ + return 1; +} + +uint8_t SMB380_HystereseFunctionSample(int16_t *value) +{ + static int16_t x = 0, y = 0, z = 0; + static uint8_t counter = 0; + int16_t delta = abs(value[0] - x) + abs(value[1] - y) + abs(value[2] - z); + + if (delta < 40) { //TODO: delta and counter are constant values, change it! + counter++; + } + else { + counter = 0; + } + + x = value[0]; + y = value[1]; + z = value[2]; + + if (smb380_mode == SMB380_THRESHOLD) { + SMB380_disableAnyMotionLimit(); + SMB380_enableNewDataInt(); + smb380_mode = SMB380_CONTINOUS; + printf("Threshold: x=%i, y=%i, z=%i\n\r", value[0], value[1], value[2]); + } + + if ((counter == 100) && (smb380_mode == SMB380_POLL)) { + //MZ SMB380_disableNewDataInt(); + //SMB380_setAnyMotionLimit(100,0); + SMB380_enableAnyMotionLimit(); + smb380_mode = SMB380_THRESHOLD; + counter = 0; + } + else if (counter == 100) { + SMB380_disableNewDataInt(); + //SMB380_setAnyMotionLimit(100,0); + SMB380_enableAnyMotionLimit(); + smb380_mode = SMB380_FALSEALERT; + counter = 0; + return 0; + } + + + return 1; +} + +static void SMB380_simple_interrupthandler(void) +{ + lpm_awake(); + + SMB380_getAcceleration(SMB380_X_AXIS, NULL, &simple_buffer[0]); + SMB380_getAcceleration(SMB380_Y_AXIS, NULL, &simple_buffer[1]); + SMB380_getAcceleration(SMB380_Z_AXIS, NULL, &simple_buffer[2]); + simple_buffer[3] = SMB380_getTemperature(); + + if (interruptTicksSMB380 >= sampleRateSMB380 - 1) { + interruptTicksSMB380 = 0; + wakeupmessage.type = MSG_TYPE_SMB380_WAKEUP; + msg_send(&wakeupmessage, simple_pid, 0); + } + else { + interruptTicksSMB380++; + } + + return; +} + +// enables simple Interrupt driven Mode +uint8_t SMB380_init_simple(uint16_t samplerate, uint8_t bandwidth, uint8_t + range) +{ + SSP0Init(); + interruptTicksSMB380 = 0; + simple_pid = active_thread->pid; + gpioint_set(0, BIT1, GPIOINT_RISING_EDGE, &SMB380_simple_interrupthandler); + SMB380_softReset(); + hwtimer_wait(HWTIMER_TICKS(100000)); + SMB380_disableUpperLimit(); + SMB380_disableLowerLimit(); + SMB380_setSampleRate(samplerate); + SMB380_setBandWidth(bandwidth); + SMB380_setRange(range); + + return 0; +} + +uint8_t SMB380_init(uint8_t (*func)(int16_t *)) +{ + SSP0Init(); + +#if SMB380_EXTINT_MODE + + if (gpioint_set(0, BIT1, GPIOINT_RISING_EDGE, &SMB380_extIntHandler)); + +#endif + + interruptTicksSMB380 = 0; + + if (func != NULL) { + smb380function = func; + } + else { + smb380function = smb380emptyfunction; + } + + //smb380function = SMB380_HystereseFunctionSample; //placeholder + + SMB380_softReset(); + hwtimer_wait(HWTIMER_TICKS(100000)); + SMB380_disableUpperLimit(); + SMB380_disableLowerLimit(); + + smb380_mode = SMB380_POLL; + SMB380_setSampleRate(SMB380_SAMPLE_RATE_MAX); //set output to 3000 Hz + + settings.writePointerPos = 0; + settings.range = 0; + settings.countRange = 0; + + for (int i = 0; i < SMB380_RING_BUFF_MAX_THREADS; i++) { + readPointerPos[i] = 0; + PointerList[i] = 0; + } + + ringBuff_X = (int16_t *)malloc(SMB380_RING_BUFF_SIZE * sizeof(int16_t)); + ringBuff_Y = (int16_t *)malloc(SMB380_RING_BUFF_SIZE * sizeof(int16_t)); + ringBuff_Z = (int16_t *)malloc(SMB380_RING_BUFF_SIZE * sizeof(int16_t)); + ringBuff_T = (int16_t *)malloc(SMB380_RING_BUFF_SIZE * sizeof(int16_t)); + + if ((ringBuff_X == NULL) | (ringBuff_Y == NULL) | (ringBuff_Z == NULL) | + (ringBuff_T == NULL)) { + if (ringBuff_X != NULL) { + free((int16_t *)ringBuff_X); + } + + if (ringBuff_Y != NULL) { + free((int16_t *)ringBuff_Y); + } + + if (ringBuff_Z != NULL) { + free((int16_t *)ringBuff_Z); + } + + if (ringBuff_T != NULL) { + free((int16_t *)ringBuff_T); + } + + return 0; + } + + return 1; +} + +static void SMB380_extIntHandler(void) +{ + int16_t accInt[4]; + + lpm_awake(); //initializes clock + + SMB380_getAcceleration(SMB380_X_AXIS, NULL, &accInt[0]); + SMB380_getAcceleration(SMB380_Y_AXIS, NULL, &accInt[1]); + SMB380_getAcceleration(SMB380_Z_AXIS, NULL, &accInt[2]); + accInt[3] = SMB380_getTemperature(); + + + writeRingBuff(accInt); + + // printf("SMB380 acc x,y,z: [%i|%i|%i|%2.3f]\r\n", accInt[0], accInt[1], + // accInt[2], acc[3]); + // printf("SMB380 acc x,y,z: [%2.3f|%2.3f|%2.3f|%2.3f]\r\n\n\n", acc[0], + // acc[1], acc[2], acc[3]); + // printf("Nach Interrupt Reset:\n"); + // SMB380_ShowMemory(); +} + +void SMB380_setSampleRate(uint16_t rate) +{ + if (rate > 0 && rate <= SMB380_SAMPLE_RATE_MAX) { + sampleRateSMB380 = SMB380_SAMPLE_RATE_MAX / rate; + } + else { + sampleRateSMB380 = 1; + } +} + +uint16_t SMB380_getSampleRate(void) +{ + return SMB380_SAMPLE_RATE_MAX / sampleRateSMB380; +} + +uint8_t SMB380_Prepare(void) +{ + return SSP0Prepare(SMB380_ACC, 16, 1, 1, 8000); +} + +uint8_t SMB380_Unprepare(void) +{ + return SSP0Unprepare(SMB380_ACC); +} + +// return the pointerNo related with the current thread +uint8_t getRingReadPointerforCurrentThread(void) +{ + uint8_t pointerNo = 0; + + while ((PointerList[pointerNo] != active_thread->pid) && + (pointerNo < SMB380_RING_BUFF_MAX_THREADS)) { + pointerNo++; + } + + return pointerNo; +} + +uint8_t initRingReadPointerforCurrentThread(void) +{ + //TODO: make it Threadsafe + uint8_t pointerNo = 0; + + while ((PointerList[pointerNo] > 0) && + (pointerNo < SMB380_RING_BUFF_MAX_THREADS)) { + pointerNo++; + } + + if (pointerNo == SMB380_RING_BUFF_MAX_THREADS) { + return 0; + } + else { + PointerList[pointerNo] = active_thread->pid; + readPointerPos[pointerNo] = settings.writePointerPos; + return 1; + } +} + +void freeRingReadPointer(void) +{ + //Should be Threadsafe + uint8_t pointerNo = getRingReadPointerforCurrentThread(); + + if (pointerNo != SMB380_RING_BUFF_MAX_THREADS) { + PointerList[pointerNo] = 0; + } +} + +void actualizeRingReadPointer(void) +{ + uint8_t pointerNo = getRingReadPointerforCurrentThread(); + + if (pointerNo != SMB380_RING_BUFF_MAX_THREADS) { + readPointerPos[pointerNo] = settings.writePointerPos; + } +} + +//TODO: more read-pointer +uint8_t readRingBuff(int16_t *value) +{ + + uint8_t pointerNo = getRingReadPointerforCurrentThread(); + + /* + * If thread is not known to read on the ringbuffer, try adding him to the + * list of known threads, otherwise exit with error + */ + + if (pointerNo == SMB380_RING_BUFF_MAX_THREADS) { + if (!initRingReadPointerforCurrentThread()) { + //printf("%sNo Readpointer left, maximum of %u is reached!\n\r", + // SMB380_DEBUG_MESSAGE, SMB380_RING_BUFF_MAX_THREADS); + return 0; + } + else { + pointerNo = getRingReadPointerforCurrentThread(); + } + } + + if (readPointerPos[pointerNo] == settings.writePointerPos) { + value[0] = 0; + value[1] = 0; + value[2] = 0; + value[3] = 0; + return 0; + } + + value[0] = ringBuff_X[readPointerPos[pointerNo]]; + value[1] = ringBuff_Y[readPointerPos[pointerNo]]; + value[2] = ringBuff_Z[readPointerPos[pointerNo]]; + value[3] = ringBuff_T[readPointerPos[pointerNo]]; + readPointerPos[pointerNo] += 1; + + if (readPointerPos[pointerNo] == SMB380_RING_BUFF_SIZE) { + readPointerPos[pointerNo] = 0; + } + + return 1; +} + +//TODO: more read-pointer +uint8_t writeRingBuff(int16_t *value) +{ + if (smb380_mode == SMB380_FALSEALERT) { + smb380_mode = SMB380_THRESHOLD; + return 0; + } + + if ((interruptTicksSMB380 >= sampleRateSMB380 - 1) || + (smb380_mode == SMB380_THRESHOLD)) { + interruptTicksSMB380 = 0; + + /* measuring temperature dependent internal sample rate of SMB380 */ + if (smb380_mode == SMB380_CONTINOUS) { + tickLastSample = ktimer_now(); + tickCurrentSamples++; + } + + ringBuff_X[settings.writePointerPos] = value[0]; + ringBuff_Y[settings.writePointerPos] = value[1]; + ringBuff_Z[settings.writePointerPos] = value[2]; + ringBuff_T[settings.writePointerPos] = value[3]; + + /* check for increasing range if dynRange is true */ + if (dynRange) { + smb380function = checkRange; + } + else { + smb380function = smb380emptyfunction; + } + + smb380function(value); + + //printf("Werte: x=%i, y=%i, z=%i\n\r",value[0], value[1], value[2]); + //vgpio_toggle(&gpio_led_green); + + settings.writePointerPos += 1; + + if (settings.writePointerPos == SMB380_RING_BUFF_SIZE) { + settings.writePointerPos = 0; + } + + wakeUpRegisteredProcesses(); + return 1; + } + else { + interruptTicksSMB380++; + return 0; + } +} + +void SMB380_activateDynRangeSet(uint8_t activate) +{ + switch (activate) { + case 0: + dynRange = false ; + break; + + case 1: + dynRange = true ; + break; + } +} + +/* + * checking for in-/decreasing range + */ +uint8_t checkRange(int16_t *value) +{ + bool increased = false; + + // printf("CurrentValues: %i %i %i \r\n", xyzTMP[0], xyzTMP[1], xyzTMP[2]); + + // determination of max and min value + int16_t maxValue = value[0]; // max(xValue, max(yValue, zValue)); + int16_t minValue = value[0]; // min(xValue, min(yValue, zValue)); + + for (int i = 1; i < 3; i++) { + if (value[i] > maxValue) { + maxValue = value[i]; + } + + if (value[i] < minValue) { + minValue = value[i]; + } + } + + int8_t isRange = SMB380_getRange(); + + //increase range immediately + switch (isRange) { + case 2: + if ((maxValue > 1800) || (minValue < -1800)) { + SMB380_setRange(SMB380_RANGE_4G); + increased = true; + printf("=== Set range from 2 g to 4 g ===\r\n"); + } + + break; + + case 4: + if ((maxValue > 3800) || (minValue < -3800)) { + SMB380_setRange(SMB380_RANGE_8G); + increased = true; + printf("=== Set range from 4 g to 8 g ===\r\n"); + } + + break; + + case 8: + break; + } + + /* check for decreasing range */ + if (increased) { + counter_Decreasing = 0; + } + else { + //decrease range after 10 consecutive relevant values + switch (isRange) { + case 2: + break; + + case 4: + if ((maxValue < 2000) && (minValue > -2000)) { + if (counter_Decreasing >= 9) { + SMB380_setRange(SMB380_RANGE_2G); + printf("=== Set range from 4 g to 2 g ===\r\n"); + counter_Decreasing = 0; + } + else { + counter_Decreasing++; + } + } + else { + counter_Decreasing = 0; + } + + break; + + case 8: + if ((maxValue < 4000) && (minValue > -4000)) { + if (counter_Decreasing >= 9) { + SMB380_setRange(SMB380_RANGE_4G); + printf("=== Set range from 8 g to 4 g ===\r\n"); + counter_Decreasing = 0; + } + else { + counter_Decreasing++; + } + } + else { + counter_Decreasing = 0; + } + + break; + } + } + + return 0; +} + + +void wakeUpRegisteredProcesses(void) +{ + uint8_t pointerNo = 0; + //wake up waiting processes + wakeupmessage.type = MSG_TYPE_SMB380_WAKEUP; + + while ((PointerList[pointerNo] > 0) && + (pointerNo < SMB380_RING_BUFF_MAX_THREADS)) { + msg_send(&wakeupmessage, PointerList[pointerNo], false); + pointerNo++; + } +} + +int16_t SMB380_getTemperature(void) +{ + int16_t t = 0; + + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_TEMP, 0, SMB380_READ_REGISTER); + + // t = (SMB380_ssp_read() & 0xFF) / 2.0 + SMB380_TEMP_OFFSET; + t = (SMB380_ssp_read() & 0xFF); + t = (t >> 1) + SMB380_TEMP_OFFSET; + SMB380_Unprepare(); + restoreIRQ(cpsr); + + return t; +} + +void SMB380_getAcceleration(unsigned char axis, int16_t *pAbs, int16_t *pMg) +{ + unsigned short ur; + + if (!settings.countRange && (pMg != NULL)) { + settings.countRange = 1; + settings.range = SMB380_getRange(); + } + + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + + switch (axis) { + case SMB380_X_AXIS: + SMB380_ssp_write(SMB380_ACC_X_MSB, 0, SMB380_READ_REGISTER); + SMB380_ssp_write(SMB380_ACC_X_LSB_NEWDATA, 0, SMB380_READ_REGISTER); + break; + + case SMB380_Y_AXIS: + SMB380_ssp_write(SMB380_ACC_Y_MSB, 0, SMB380_READ_REGISTER); + SMB380_ssp_write(SMB380_ACC_Y_LSB_NEWDATA, 0, SMB380_READ_REGISTER); + break; + + default: + SMB380_ssp_write(SMB380_ACC_Z_MSB, 0, SMB380_READ_REGISTER); + SMB380_ssp_write(SMB380_ACC_Z_LSB_NEWDATA, 0, SMB380_READ_REGISTER); + } + + ur = (SMB380_ssp_read() & SMB380_ACC_MSB_MASK) << 2; + ur |= (SMB380_ssp_read() & SMB380_ACC_LSB_MASK) >> 6; + SMB380_Unprepare(); + restoreIRQ(cpsr); + + if (pAbs != NULL) { + if (ur & BIT9) { //ur<0 + *pAbs = ur | 0xFC00; + } + else { + *pAbs = ur & 0x03FF; + } + } + + if (pMg != NULL) { + if (ur & BIT9) { //ur<0 + *pMg = -(((settings.range * (512 - (ur & 0x1FF))) * 2000) / 1024); + } + else { + *pMg = ((settings.range * ur) * 2000) / 1024; + } + } + +} + +unsigned char SMB380_getChipID(void) +{ + unsigned char ur = 0; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CHIP_ID, 0, 0); + ur = (unsigned char)(SMB380_ssp_read() & SMB380_CHIP_ID_MASK); + restoreIRQ(cpsr); + return ur; +} + +void SMB380_setWakeUpPause(unsigned char duration) +{ + unsigned char utemp; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL4, 0, SMB380_READ_REGISTER); + utemp = SMB380_ssp_read(); + utemp &= ~SMB380_CONTROL4_WAKEUP_PAUSE_MASK; + utemp |= (duration & (0x3) << 1);//+1; + SMB380_ssp_write(SMB380_CONTROL4, utemp, SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +unsigned char SMB380_getWakeUpPause(void) +{ + unsigned char up; + + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL4, 0, SMB380_READ_REGISTER); + up = (unsigned char)SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); + up &= SMB380_CONTROL4_WAKEUP_PAUSE_MASK; + up = up >> 1; + + return up; +} + +void SMB380_setBandWidth(unsigned char bandWidth) +{ + unsigned char utemp; + + if ((bandWidth == SMB380_BAND_WIDTH_100HZ) | + (bandWidth == SMB380_BAND_WIDTH_1500HZ) | + (bandWidth == SMB380_BAND_WIDTH_190HZ) | + (bandWidth == SMB380_BAND_WIDTH_25HZ) | + (bandWidth == SMB380_BAND_WIDTH_375HZ) | + (bandWidth == SMB380_BAND_WIDTH_50HZ) | + (bandWidth == SMB380_BAND_WIDTH_750HZ)) { + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL3, 0, SMB380_READ_REGISTER); + utemp = SMB380_ssp_read(); + utemp &= ~SMB380_CONTROL3_BANDWITH_MASK; + utemp |= (bandWidth & 0x7); + SMB380_ssp_write(SMB380_CONTROL3, utemp, SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); + } +} + +void SMB380_setRange(unsigned char range) +{ + unsigned char utemp = 0; + + if (range != 0x3) { + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL3, 0, SMB380_READ_REGISTER); + utemp = (unsigned char)SMB380_ssp_read(); + utemp &= ~SMB380_CONTROL3_RANGE_MASK; + utemp |= (range & 0x3) << 3; + SMB380_ssp_write(SMB380_CONTROL3, utemp, SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); + settings.countRange = 0; + } + +} + +unsigned char SMB380_getRange(void) +{ + unsigned char ur; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL3, 0, SMB380_READ_REGISTER); + ur = (SMB380_ssp_read() & SMB380_CONTROL3_RANGE_MASK) >> 3; + SMB380_Unprepare(); + restoreIRQ(cpsr); + + switch (ur) { + case SMB380_RANGE_2G: + return 2; + + case SMB380_RANGE_4G: + return 4; + + case SMB380_RANGE_8G: + return 8; + + default: + return 4; + } +} + +unsigned char SMB380_getBandWidth(void) +{ + unsigned char uBand; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL3, 0, SMB380_READ_REGISTER); + uBand = SMB380_ssp_read() & SMB380_CONTROL3_BANDWITH_MASK; + SMB380_Unprepare(); + restoreIRQ(cpsr); + return uBand; +} + +int16_t SMB380_getBandWidthAbs(void) +{ + unsigned char uBand; + uBand = SMB380_getBandWidth(); + + switch (uBand) { + case SMB380_BAND_WIDTH_25HZ: + return 25; + + case SMB380_BAND_WIDTH_50HZ: + return 50; + + case SMB380_BAND_WIDTH_100HZ: + return 100; + + case SMB380_BAND_WIDTH_190HZ: + return 190; + + case SMB380_BAND_WIDTH_375HZ: + return 375; + + case SMB380_BAND_WIDTH_750HZ: + return 750; + + case SMB380_BAND_WIDTH_1500HZ: + return 1500; + + default: + return uBand; + } +} + +void SMB380_softReset(void) +{ + unsigned char ur; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL1, SMB380_CONTROL1_SOFT_RESET_MASK, + SMB380_WRITE_REGISTER); + ur = ((unsigned char)SMB380_ssp_read()) & SMB380_CONTROL1_SOFT_RESET_MASK; + SMB380_Unprepare(); + restoreIRQ(cpsr); + ur = ur >> 1; +} + +void SMB380_setCustomerReg(unsigned char data) +{ + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CUST1, data, SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +unsigned char SMB380_getCustomerReg(void) +{ + unsigned uReg = 0; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CUST1, 0, SMB380_READ_REGISTER); + uReg = (unsigned char)SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); + return uReg; +} + +// Selftest +void SMB380_Selftest_1(void) +{ + unsigned char uReg = 0; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_LG_THRES, 6, SMB380_WRITE_REGISTER); + //SSP0Init(); + SMB380_ssp_read(); + SMB380_ssp_write(SMB380_LG_DUR, 0, SMB380_WRITE_REGISTER); + //SSP0Init(); + SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL1, 0, SMB380_READ_REGISTER); + + uReg = (unsigned char)SMB380_ssp_read(); + uReg &= ~SMB380_CONTROL1_SELF_TEST_1_MASK; + uReg |= 0x01 << 3; + SMB380_ssp_write(SMB380_CONTROL1, uReg, SMB380_WRITE_REGISTER); + // SSP0Init(); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +void SMB380_ShowMemory(void) +{ + uint16_t uReg = 0; + uint8_t bitMask[16]; + printf("SMB380 Speicher\n\r"); + unsigned long cpsr; + + for (unsigned char regAd = 0x16; regAd > 0; regAd--) { + cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(regAd - 1, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); + printf("Register: = %X: 0x%X = ", regAd - 1, uReg); + + for (int pos = 0; pos < 16; pos++) { //uReg != 0) + bitMask[15 - pos] = uReg % 2; + + uReg = uReg / 2; + } + + for (int pos = 8; pos < 16; pos++) { //uReg != 0) + printf("%d", bitMask[pos]); + + if ((pos % 4) == 0) { + printf(" "); + } + } + + printf("\n"); + } +} + +void SMB380_setUpperLimit(void) +{ + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_HG_THRES, 128, SMB380_WRITE_REGISTER); //1g + SMB380_ssp_read(); + SMB380_ssp_write(SMB380_HG_DUR, 0, SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +void SMB380_enableUpperLimit(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL2, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL2, uReg | SMB380_CONTROL2_ENABLE_HG_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +void SMB380_disableUpperLimit(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL2, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL2, uReg & ~SMB380_CONTROL2_ENABLE_HG_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +void SMB380_enableLowerLimit(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL2, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL2, uReg | SMB380_CONTROL2_ENABLE_LG_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +void SMB380_disableLowerLimit(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL2, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL2, uReg & ~SMB380_CONTROL2_ENABLE_LG_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +/* @param gvaluefloat - value is in mg + * @param gvalueint - value in range of 0 to 512 + * Choose one of them, set the other to zero + */ +uint8_t SMB380_setAnyMotionLimit(uint16_t mg, uint16_t gvalueint) +{ + + uint8_t threshold = 0; + + if (mg != 0) { + threshold = mg / (15.6 * (SMB380_getRange() / 2)); + } + else if (gvalueint != 0) { + /* Scaling for different gRanges is not needed */ + threshold = ceil(((gvalueint * 2000) / 512.0) / 15.6); + } + else { + return 0; + } + + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + /* 0,3g = 300 / 15,6mg = 19 */ + SMB380_ssp_write(SMB380_ANY_MOTION_THRES, threshold, SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + //Set duration at this point + SMB380_ssp_write(SMB380_ANY_MOTION_DUR_HYST, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); + return 1; +} + +void SMB380_enableAnyMotionLimit(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL4, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL4, uReg | SMB380_CONTROL4_ENABLE_ADV_INT_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL2, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL2, uReg | SMB380_CONTROL2_ANY_MOTION_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +void SMB380_disableAnyMotionLimit(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL2, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL2, + uReg & ~SMB380_CONTROL2_ANY_MOTION_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL4, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL4, + uReg & ~SMB380_CONTROL4_ENABLE_ADV_INT_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +void SMB380_enableNewDataInt(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + /* + * prevent deep sleep, reason: 400 µs wake-up time is to long for 3kHz + * interrupts + */ + SETBIT(lpm_prevent_sleep, LPM_PREVENT_SLEEP_ACCSENSOR); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL4, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL4, uReg | SMB380_CONTROL4_NEW_DATA_INT_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + // measuring temperature dependent internal sample rate of SMB380 + tickStart = ktimer_now(); + tickCurrentSamples = 0; + restoreIRQ(cpsr); +} + +void SMB380_disableNewDataInt(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL4, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL4, uReg & ~SMB380_CONTROL4_NEW_DATA_INT_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + /* + * enable deep sleep, reason: 400 µs wake-up time was to long for 3kHz + * interrupts + */ + CLRBIT(lpm_prevent_sleep, LPM_PREVENT_SLEEP_ACCSENSOR); + restoreIRQ(cpsr); +} + +void SMB380_resetInterruptFlags(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL1, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL1, uReg | SMB380_CONTROL1_RESET_INT_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +void SMB380_enableEEPROM(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL1, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL1, uReg | SMB380_CONTROL1_EE_W_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +void SMB380_disableEEPROM(void) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + SMB380_ssp_write(SMB380_CONTROL1, 0, SMB380_READ_REGISTER); + uReg = SMB380_ssp_read(); + SMB380_ssp_write(SMB380_CONTROL1, uReg & ~SMB380_CONTROL1_EE_W_MASK, + SMB380_WRITE_REGISTER); + SMB380_ssp_read(); + SMB380_Unprepare(); + restoreIRQ(cpsr); +} + +/* + * Return offsets from offset registers, + * remove xyz afterwards because it is useless + */ +unsigned char SMB380_readOffset(uint16_t *offset) +{ + if (sizeof(offset) < 3) { + return false; + } + + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_X, 0, SMB380_READ_REGISTER); + uReg = ((SMB380_ssp_read() & SMB380_ACC_LSB_MASK) >> 6); + SMB380_ssp_write(SMB380_OFFSET_MSB_X, 0, SMB380_READ_REGISTER); + uReg |= (SMB380_ssp_read() & SMB380_ACC_MSB_MASK) << 2; + + + offset[0] = uReg; + printf("Offset X: %u ", uReg); + + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_Y, 0, SMB380_READ_REGISTER); + uReg = (SMB380_ssp_read() & SMB380_ACC_LSB_MASK) >> 6; + SMB380_ssp_write(SMB380_OFFSET_MSB_Y, 0, SMB380_READ_REGISTER); + uReg |= (SMB380_ssp_read() & SMB380_ACC_MSB_MASK) << 2; + + offset[1] = uReg; + printf("Offset Y: %u ", uReg); + + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_Z, 0, SMB380_READ_REGISTER); + uReg = (SMB380_ssp_read() & SMB380_ACC_LSB_MASK) >> 6; + SMB380_ssp_write(SMB380_OFFSET_MSB_Z, 0, SMB380_READ_REGISTER); + uReg |= (SMB380_ssp_read() & SMB380_ACC_MSB_MASK) << 2; + + offset[2] = uReg; + printf("Offset Z: %u \r\n", uReg); + + SMB380_Unprepare(); + restoreIRQ(cpsr); + + return true; +} + +unsigned char SMB380_readOffsetTemp(uint16_t *offset) +{ + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_T, 0, SMB380_READ_REGISTER); + uReg = ((SMB380_ssp_read() & SMB380_ACC_LSB_MASK) >> 6); + SMB380_ssp_write(SMB380_OFFSET_MSB_T, 0, SMB380_READ_REGISTER); + uReg |= (SMB380_ssp_read() & SMB380_ACC_MSB_MASK) << 2; + + + offset[0] = uReg; + printf("Offset T: %u ", uReg); + + SMB380_Unprepare(); + restoreIRQ(cpsr); + + return true; +} + +/* + * EEPROM = 1 if data has to be written in EEPROM and not only in image + */ +void SMB380_writeOffset(uint16_t *offset, uint8_t EEPROM) +{ + printf("Writing Offset X: %u Y: %u Z: %u\r\n", offset[0], offset[1], offset[2]); + + if (sizeof(offset) >= 3) { + uint16_t eeoffset = 0; + + if (EEPROM) { + //create offset if saving to EEPROM is needed + eeoffset = SMB380_EEPROM_OFFSET; + } + + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + + //x-Axis + uReg = (offset[0] & 0x03) << 6; //get both LSB Bits + //write them to image or eeprom + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_X, 0, SMB380_READ_REGISTER); + uReg |= (SMB380_ssp_read() & 0x3F); //saves gain from same register + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_X + eeoffset, (uint8_t)uReg, + SMB380_WRITE_REGISTER); //write them to image or eeprom + SMB380_ssp_read(); + hwtimer_wait(HWTIMER_TICKS(50000)); + + uReg = (offset[0] & 0x3FC) >> 2; //get MSB Bits + SMB380_ssp_write(SMB380_OFFSET_MSB_X + eeoffset, (uint8_t)uReg, + SMB380_WRITE_REGISTER); //write them to image or eeprom + SMB380_ssp_read(); + hwtimer_wait(HWTIMER_TICKS(50000)); + + //y-Axis + uReg = (offset[1] & 0x03) << 6; //get both LSB Bits + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_Y, 0, SMB380_READ_REGISTER); + uReg |= (SMB380_ssp_read() & 0x3F); //saves gain from same register + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_Y + eeoffset, (uint8_t)uReg, + SMB380_WRITE_REGISTER); //write them to image or eeprom + SMB380_ssp_read(); + hwtimer_wait(HWTIMER_TICKS(50000)); + + uReg = (offset[1] & 0x3FC) >> 2; //get MSB Bits + SMB380_ssp_write(SMB380_OFFSET_MSB_Y + eeoffset, (uint8_t)uReg, + SMB380_WRITE_REGISTER); //write them to image or eeprom + SMB380_ssp_read(); + hwtimer_wait(HWTIMER_TICKS(50000)); + + //z-Axis + uReg = (offset[2] & 0x03) << 6; //get both LSB Bits + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_Z, 0, + SMB380_READ_REGISTER); //write them to image or eeprom + uReg |= (SMB380_ssp_read() & 0x3F); //saves gain from same register + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_Z + eeoffset, (uint8_t)uReg, + SMB380_WRITE_REGISTER); //write them to image or eeprom + SMB380_ssp_read(); + hwtimer_wait(HWTIMER_TICKS(50000)); + + uReg = (offset[2] & 0x3FC) >> 2; //get MSB Bits + SMB380_ssp_write(SMB380_OFFSET_MSB_Z + eeoffset, (uint8_t)uReg, + SMB380_WRITE_REGISTER); //write them to image or eeprom + SMB380_ssp_read(); + hwtimer_wait(HWTIMER_TICKS(50000)); + + SMB380_Unprepare(); + restoreIRQ(cpsr); + + } +} + +void SMB380_writeOffsetTemp(uint16_t *offset, uint8_t EEPROM) +{ + printf("Writing Offset Temp: %u\r\n", offset[0]); + + if (sizeof(offset) >= 1) { + uint16_t eeoffset = 0; + + if (EEPROM) { + //create offset if saving to EEPROM is needed + eeoffset = SMB380_EEPROM_OFFSET; + } + + unsigned short uReg; + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + + //T-Axis + uReg = (offset[0] & 0x03) << 6; //get both LSB Bits + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_T, 0, + SMB380_READ_REGISTER); //write them to image or eeprom + uReg |= (SMB380_ssp_read() & 0x3F); //saves gain from same register + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_T + eeoffset, (uint8_t)uReg, + SMB380_WRITE_REGISTER); //write them to image or eeprom + SMB380_ssp_read(); + hwtimer_wait(HWTIMER_TICKS(50000)); + + uReg = (offset[0] & 0x3FC) >> 2; //get MSB Bits + SMB380_ssp_write(SMB380_OFFSET_MSB_T + eeoffset, (uint8_t)uReg, + SMB380_WRITE_REGISTER); //write them to image or eeprom + SMB380_ssp_read(); + hwtimer_wait(HWTIMER_TICKS(50000)); + + SMB380_Unprepare(); + restoreIRQ(cpsr); + } +} + +unsigned char SMB380_readGain(uint16_t *gain) +{ + if (sizeof(gain) < 3) { + return false; + } + + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + + //x-gain + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_X, 0, SMB380_READ_REGISTER); + gain[0] = (SMB380_ssp_read() & SMB380_OFFSET_GAIN_MASK); + //y-gain + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_Y, 0, SMB380_READ_REGISTER); + gain[1] = (SMB380_ssp_read() & SMB380_OFFSET_GAIN_MASK); + //z-gain + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_Z, 0, SMB380_READ_REGISTER); + gain[2] = (SMB380_ssp_read() & SMB380_OFFSET_GAIN_MASK); + + SMB380_Unprepare(); + restoreIRQ(cpsr); + + return true; +} + +unsigned char SMB380_readGainTemp(uint16_t *gain) +{ + if (sizeof(gain) < 1) { + return false; + } + + unsigned long cpsr = disableIRQ(); + SMB380_Prepare(); + + //T-gain + SMB380_ssp_write(SMB380_OFFSET_LSB_GAIN_T, 0, SMB380_READ_REGISTER); + gain[0] = (SMB380_ssp_read() & SMB380_OFFSET_GAIN_MASK); + + SMB380_Unprepare(); + restoreIRQ(cpsr); + + return true; +} + + diff --git a/boards/avsextrem/drivers/avsextrem-ssp0.c b/boards/avsextrem/drivers/avsextrem-ssp0.c new file mode 100644 index 0000000000..e396e5dddb --- /dev/null +++ b/boards/avsextrem/drivers/avsextrem-ssp0.c @@ -0,0 +1,425 @@ +/* + * avsextrem-ssp0.c - implementation of the SPI0 interface for the LPC2387, + * and the AVSESTREM board. + * Copyright (C) 2013 Freie Universität Berlin + * + * This source code is licensed under the LGPLv2 license, + * See the file LICENSE for more details. + */ + +/** + * @file + * @internal + * @brief Implements the SPI0 interface for the LPC2387 + * + * @author Freie Universität Berlin, Computer Systems & Telematics + * @author Marco Ziegert + * @author Zakaria Kasmi + * @version $Revision: 3854 $ + * + * @note $Id: avsextrem-ssp0.c 3854 2013-08-14 15:27:01Z zkasmi $ + */ + +#include "lpc23xx.h" /* LPC23XX/24xx Peripheral Registers */ +#include "cpu.h" +#include "VIC.h" +#include "ssp0-board.h" +#include "smb380-board.h" +//#include "mma7455l-board.h" +#include "gpioint.h" +#include "hwtimer.h" +#include +#include "lpm.h" + +//uint16_t sampleRateMMA7455L; +//uint16_t interruptTicksMMA7455L; +// +//static void MMA7455L_extIntHandler(void); + +uint32_t SSP0Init(void) +{ + + /* + * enable clock to SSP0 for security reason. + * By default, it's enabled already + */ + PCONP |= PCSSP0; + //TODO: configure CLK, MISO, MOSI by default as GPIOs. +#if USE_CS + // P1.20 1.21 1.23 1.24 + // PINSEL3 |= BIT8 | BIT9 | BIT10 | BIT11 | BIT14 | BIT15 | BIT16 | BIT17; +#else + // No SSEL0 + // PINSEL3 |= BIT8 | BIT9 | BIT14 | BIT15 | BIT16 | BIT17; //1.20 1.23 1.24 +#endif + +#if SSP1_INTERRUPT_MODE + + if (install_irq(SSP1_INT, (void *)SSP0Handler, HIGHEST_PRIORITY) == FALSE) { + return (FALSE); + } + + /* + * Set SSPINMS registers to enable interrupts, + * enable all error related interrupts + */ + + SSP1IMSC = SSPIMSC_RORIM | SSPIMSC_RTIM; +#endif + + return (1); +} + +/* + * datasize (wordsize) in decimal (4-16), cpol&cpha =(0/1) and frequency divided + * by 1000 (e.g. 8 MHz = 8000) + */ +uint8_t SSP0Prepare(uint8_t chip, uint8_t datasize, uint8_t cpol, uint8_t cpha, + uint16_t freq) +{ + switch (chip) { + case BMA180_INTERN: + case SMB380_ACC: { +#if USE_CS + PINSEL3 |= BIT8 | BIT9 | BIT10 | BIT11 | BIT14 | BIT15 | BIT16 | + BIT17; //P1.20 1.21 1.23 1.24 +#else + // 1.20 1.23 1.24 are not configured as SSEL0 + PINSEL3 |= BIT8 | BIT9 | BIT14 | BIT15 | BIT16 | BIT17; +#endif + break; + } + + case BMA180_EXTERN: + case L3G_EXTERN: + case NANOPAN: + case ACAMDMS: { +#if USE_CS + PINSEL0 |= BIT31; + PINSEL1 |= BIT1 | BIT3 | BIT5; // P0.15 0.16 0.17 0.18 +#else + // Turn on NanoPAN + PINSEL0 |= BIT31; + // 0.15 0.17 0.18 are not configured as SSEL0 + PINSEL1 |= BIT3 | BIT5; +#endif + break; + } + + case NORDIC: { + PINSEL0 |= BIT31; + PINSEL1 |= BIT3 | BIT5; // 0.15 0.17 0.18 SSEL0 (No) + break; + } + + default: { + printf("wrong CHIP selected\n"); + return 0; + } + } + + uint32_t SSP0CR0tmp = 0; + + switch (datasize) { + case 4: + SSP0CR0tmp = BIT0 | BIT1; + break; + + case 5: + SSP0CR0tmp = BIT2; + break; + + case 6: + SSP0CR0tmp = BIT0 | BIT2; + break; + + case 7: + SSP0CR0tmp = BIT1 | BIT2; + break; + + case 8: + SSP0CR0tmp = BIT0 | BIT1 | BIT2; + break; + + case 9: + SSP0CR0tmp = BIT3; + break; + + case 10: + SSP0CR0tmp = BIT0 | BIT3; + break; + + case 11: + SSP0CR0tmp = BIT1 | BIT3; + break; + + case 12: + SSP0CR0tmp = BIT0 | BIT1 | BIT3; + break; + + case 13: + SSP0CR0tmp = BIT2 | BIT3; + break; + + case 14: + SSP0CR0tmp = BIT0 | BIT2 | BIT3; + break; + + case 15: + SSP0CR0tmp = BIT1 | BIT2 | BIT3; + break; + + case 16: + SSP0CR0tmp = BIT0 | BIT1 | BIT2 | BIT3; + break; + + default: + return 0; + } + + if (cpol) { + SSP0CR0tmp |= BIT6; + } + + if (cpha) { + SSP0CR0tmp |= BIT7; + } + + SSP0CR1 = 0x00; // SSP0 disabled + + // Setting xx-Bit Datasize, CPOL and CPHA + SSP0CR0 = SSP0CR0tmp; + + // Clock Setup + uint32_t pclksel; + uint32_t cpsr; + lpc2387_pclk_scale(F_CPU / 1000, freq, &pclksel, &cpsr); + PCLKSEL1 &= ~(BIT10 | BIT11); // CCLK to PCLK divider ??? + PCLKSEL1 |= pclksel << 10; + SSP0CPSR = cpsr; + + // Enable + SSP0CR1 |= BIT1; // SSP0 enabled + + uint32_t Dummy; + + for (uint32_t i = 0; i < FIFOSIZE; i++) { + Dummy = SSP0DR; // clear the RxFIFO + } + + return 1; +} + +uint8_t SSP0Unprepare(uint8_t chip) +{ + switch (chip) { + case BMA180_INTERN: + case SMB380_ACC: { + // Turn off Acceleration Sensor + PINSEL3 &= ~(BIT8 | BIT9 | BIT10 | BIT11 | BIT14 | BIT15 | BIT16 | + BIT17); + FIO1DIR |= BIT20 | BIT21 | BIT24; + FIO1DIR &= ~BIT23; // MISO as Input + FIO1SET = BIT20 | BIT24; /* + * CLK + SSEL + MOSI GPIO as Output + * TODO: depends on CPOL+CPHA Settings + */ + FIO1CLR = BIT21; + break; + } + + case BMA180_EXTERN: + case L3G_EXTERN: + case NORDIC: + case NANOPAN: + case ACAMDMS: { + // Turn off Nanopan (Pins to GPIO) + PINSEL0 &= ~(BIT30 | BIT31); //CLK to GPIO + PINSEL1 &= ~(BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5); + FIO0DIR |= BIT15 | BIT16 | BIT18; //CLK + SSEL + MOSI GPIO as Output + FIO0DIR &= ~BIT17; // MISO as Input + FIO0SET = BIT15 | BIT16; /* + * CLK + SSEL + MOSI GPIO as Output + * TODO: depends on CPOL+CPHA Settings + */ + FIO0CLR = BIT18; + break; + } + + default: { + printf("wrong CHIP selected\n"); + return 0; + } + } + + return 1; +} + +unsigned char SMB380_ssp_write(const unsigned char regAddr, + const unsigned char data, unsigned char flag) +{ + + uint16_t temp = 0; + + if (flag) { + temp = (unsigned int)(((regAddr & 0xFF7F) << 8) | data); + + } + else { + temp = (((unsigned int)(regAddr | 0x80) << 8) | 0xFF); + } + + return SSP0_write(temp, SMB380_ACC); +} + +unsigned char SSP0_write(const uint16_t data, uint8_t device) +{ + unsigned char ret = 1; + + while ((SSP0SR & (SSPSR_TNF | SSPSR_BSY)) != SSPSR_TNF) + ; + + if (!USE_CS) { + switch (device) { + case BMA180_INTERN: + case SMB380_ACC: { + FIO1CLR = SSP0_SEL; + break; + } + + case BMA180_EXTERN: + case L3G_EXTERN: + case NANOPAN: { + printf("[%s] line: %d\n", __FUNCTION__, __LINE__); + FIO0CLR = SSP0_SELN; + break; + } + + case ACAMDMS: + case NORDIC: + // Chip Select is done in Nordic driver + break; + + default: + ret = 0; + goto ret; + } + } + + SSP0DR = data; + + if (!USE_CS) { + while (SSP0SR & SSPSR_BSY) + ; + + switch (device) { + case BMA180_INTERN: + case SMB380_ACC: { + FIO1SET = SSP0_SEL; + break; + } + + case BMA180_EXTERN: + case L3G_EXTERN: + case NANOPAN: { + FIO0SET = SSP0_SELN; + break; + } + + case ACAMDMS: + case NORDIC: + // Chip Select is done in Nordic driver + break; + + default: + ret = 0; + goto ret; + } + } + +ret: + return ret; +} + +unsigned short SSP0_read(uint8_t device) +{ + uint16_t data; + + while (!(SSP0SR & SSPSR_RNE)) + ; + + if (!USE_CS) { + switch (device) { + case BMA180_INTERN: + case SMB380_ACC: { + FIO1CLR = SSP0_SEL; + break; + } + + case BMA180_EXTERN: + case L3G_EXTERN: + case NANOPAN: { + FIO0CLR = SSP0_SELN; + break; + } + + case NORDIC: + case ACAMDMS: + // Chip Select is done in Nordic driver + break; + + default: + data = 0xFFFF; + goto ret; + } + } + + data = SSP0DR; + + if (!USE_CS) { + switch (device) { + case BMA180_INTERN: + case SMB380_ACC: { + FIO1SET = SSP0_SEL; + break; + } + + case BMA180_EXTERN: + case L3G_EXTERN: + case NANOPAN: { + FIO0SET = SSP0_SELN; + break; + } + + case ACAMDMS: + case NORDIC: + // Chip Select is done in Nordic driver + break; + + default: + data = 0xFFFF; + goto ret; + } + } + +ret: + return data; +} + +unsigned short SMB380_ssp_read(void) +{ + return SSP0_read(SMB380_ACC); +} + +unsigned short nrf24l01_ssp_read_write(const uint8_t data) +{ + SSP0_write(data, NORDIC); + return SSP0_read(NORDIC); +} + +unsigned short acam_trx(const uint8_t data) +{ + SSP0_write(data, ACAMDMS); + return SSP0_read(ACAMDMS); +} + diff --git a/boards/avsextrem/include/board.h b/boards/avsextrem/include/board.h new file mode 100644 index 0000000000..4370382942 --- /dev/null +++ b/boards/avsextrem/include/board.h @@ -0,0 +1,66 @@ +/* +* board.h - Definitions for the AVSEXTREM board configuration. +* Copyright (C) 2013 Zakaria Kasmi +* +* This source code is licensed under the LGPLv2 license, +* See the file LICENSE for more details. +* +*/ + + +/** + * @file + * @brief avsextrem board configuration + * + * @author Freie Universität Berlin, Computer Systems & Telematics + * @author Heiko Will + * @author Zakaria Kasmi + * @version $Revision: 1127 $ + * + * @note $Id: board-conf.h 1127 2013-06-13 08:48:29Z kasmi$ + */ + + +#ifndef BOARDCONF_H_ +#define BOARDCONF_H_ +#include +#include "msba2_common.h" + +#define FEUERWARE_CONF_BOARD_NAME "FU Berlin AVSEXTREM BOARD" + +#define LED_RED_PIN (BIT25) +#define LED_GREEN_PIN (BIT26) + +#define LED_GREEN_OFF (FIO3SET = LED_GREEN_PIN) +#define LED_GREEN_ON (FIO3CLR = LED_GREEN_PIN) +#define LED_GREEN_TOGGLE (FIO3PIN ^= LED_GREEN_PIN) + +#define LED_RED_OFF (FIO3SET = LED_RED_PIN) +#define LED_RED_ON (FIO3CLR = LED_RED_PIN) +#define LED_RED_TOGGLE (FIO3PIN ^= LED_RED_PIN) + + + +#ifdef MODULE_CC110X +#define FEUERWARE_CONF_NUM_RADIOS 1 +#else +#define FEUERWARE_CONF_NUM_RADIOS 0 +#endif + +// if FAT is enabled this board supports files +#define FEUERWARE_CONF_CORE_SUPPORTS_FILES defined(MODULE_FAT) + +#ifdef MODULE_FAT +#define CFG_CONF_MEM_SIZE 0x7FFFFFFF +#define SYSLOG_CONF_NUM_INTERFACES 2 +#else +#define SYSLOG_CONF_NUM_INTERFACES 1 +#endif + +void init_clks1(void); + +typedef uint8_t radio_packet_length_t; + +/** @} */ +#endif /* BOARDCONF_H_ */ + diff --git a/boards/avsextrem/include/configure.h b/boards/avsextrem/include/configure.h new file mode 100644 index 0000000000..5ca52843a1 --- /dev/null +++ b/boards/avsextrem/include/configure.h @@ -0,0 +1,77 @@ +/* +* configure.h - Configuration file for the avsextrem board. +* Copyright (C) 2013 Zakaria Kasmi +* +* This source code is licensed under the LGPLv2 license, +* See the file LICENSE for more details. +* +*/ + +/** + * @file + * @brief definitions for the avsextrem board configuration + * + * @author Freie Universität Berlin, Computer Systems & Telematics + * @author baar + * @author Zakaria Kasmi + * @version $Revision: 1127 $ + * + * @note $Id: board-conf.h 1127 2013-08-20 17:15:29 kasmi $ + */ + +#ifndef CONFIGURE_H_ +#define CONFIGURE_H_ + +/** + * + * The offline configuration file "configure.h" is automatically + * included in every file by the build system and allows to configure + * all neccessary defines on cpu, board and project level. + * + * The configuration is built of + * \li a project specific file (project-conf.h) + * \li a board specific file (board-conf.h) and + * \li a cpu specific file (cpu-conf.h). + * All of which are chosen by the build system depending on your arguments. + * + * @{ + */ + +//#include "project-conf.h" +//#include "board-conf.h" +#include "cpu-conf.h" + +#ifdef MODULE_SYSMON +#ifndef TRACELOG_CONF_NUM_ENTRIES +#define TRACELOG_CONF_NUM_ENTRIES 10 +#endif +#else +#undef TRACELOG_CONF_NUM_ENTRIES +#endif + + +/* ------------------------------------------------------------------------- */ +/* + * documentation of defines that do not belong to a specific module: + */ + +/** + * @def FEUERWARE_CONF_BOARD_NAME + * @brief Defines the name of the board as a string + */ + +/** + * @def FEUERWARE_CONF_CPU_NAME + * @brief Defines the name of the cpu as a string + */ + +/** + * @def FEUERWARE_CONF_SUPPORTS_FILES + * @brief Defines if standard library file functions are available + */ +#ifndef FEUERWARE_CONF_SUPPORTS_FILES +#define FEUERWARE_CONF_SUPPORTS_FILES 0 +#endif + +/** @} */ +#endif /* CONFIGURE_H_ */ diff --git a/boards/avsextrem/include/smb380-board.h b/boards/avsextrem/include/smb380-board.h new file mode 100644 index 0000000000..218f724f49 --- /dev/null +++ b/boards/avsextrem/include/smb380-board.h @@ -0,0 +1,254 @@ +/* + * msba2acc-smb380.h - Definitions of the Driver for the SMB380 acceleration + * sensor. + * Copyright (C) 2013 Freie Universität Berlin + * + * This source code is licensed under the LGPLv2 license, + * See the file LICENSE for more details. + **/ + +/** + * @file + * @internal + * @brief SMB380 acceleration sensor definitions for the LPC2387 + * + * @author Freie Universität Berlin, Computer Systems & Telematics + * @author Marco Ziegert + * @author Zakaria Kasmi + * @version $Revision: 3854 $ + * + * @note $Id: msba2acc-smb380.h 3854 2010-01-18 15:27:01 kasmi $ + * + */ + +#ifndef SMB380_H_ +#define SMB380_H_ +#include +#include + +#define SMB380_DEBUG_MESSAGE "SMB380 Driver Error: " + +#define MSG_TYPE_SMB380_WAKEUP 814 + +#define SMB380_X_AXIS 0 //X Axis-Name +#define SMB380_Y_AXIS 1 //Y Axis-Name +#define SMB380_Z_AXIS 2 //Z Axis-Name + +#define LPM_PREVENT_SLEEP_ACCSENSOR BIT2 + +enum SMB380_MODE { + SMB380_POLL, + SMB380_POLL_AFTER_CONTINOUS, + SMB380_CONTINOUS, + SMB380_THRESHOLD, + SMB380_FALSEALERT +}; +//volatile enum SMB380_MODE +volatile enum SMB380_MODE smb380_mode;// = SMB380_POLL; + +/* Writeable values to EEPROM: from 0x0A (control1) to 0x1D (offset_T). + For writing enable ... flag and add eeprom_offset_address. + + Generally it is a good idea to read out shared register addresses before writing, + registers 0x14 and 34h are especially critical. +*/ + +#define SMB380_EEPROM_OFFSET 0x20 +//Chip-ID Bit0-2, default: 010b +#define SMB380_CHIP_ID 0x00 +//Chip-ID mask +#define SMB380_CHIP_ID_MASK 0x07 +//ml_version Bit0-3 ; al_version Bit4-7 +#define SMB380_AL_ML_VERSION 0x01 +#define SMB380_AL_MASK 0xF0 +#define SMB380_ML_MASK 0x0F +//LSB_acc_x Bit6-7; new_data_x Bit0 +#define SMB380_ACC_X_LSB_NEWDATA 0x02 +//MSB_acc_x Bit0-7 +#define SMB380_ACC_X_MSB 0x03 +//LSB_acc_y Bit6-7; new_data_y Bit0 +#define SMB380_ACC_Y_LSB_NEWDATA 0x04 +//MSB_acc_y Bit0-7 +#define SMB380_ACC_Y_MSB 0x05 +//LSB_acc_z Bit6-7; new_data_z Bit0 +#define SMB380_ACC_Z_LSB_NEWDATA 0x06 +//MSB_acc_z Bit0-7 +#define SMB380_ACC_Z_MSB 0x07 +#define SMB380_ACC_LSB_MASK 0xC0 +#define SMB380_ACC_MSB_MASK 0xFF +#define SMB380_ACC_NEWDATA_MASK 0x01 +//Temperature Bit0-7 +#define SMB380_TEMP 0x08 +//Status register, contains six flags +#define SMB380_STATUS 0x09 +#define SMB380_STATUS_ST_RESULT_MASK 0x80 +#define SMB380_STATUS_ALERT_PHASE_MASK 0x10 +#define SMB380_STATUS_LG_LATCHED_MASK 0x08 +#define SMB380_STATUS_HG_LATCHED_MASK 0x04 +#define SMB380_STATUS_STATUS_LG_MASK 0x02 +#define SMB380_STATUS_STATUS_HG_MASK 0x01 +//Control register - contains seven values, default: x000 0000b +#define SMB380_CONTROL1 0x0A +#define SMB380_CONTROL1_RESET_INT_MASK 0x40 +#define SMB380_CONTROL1_UPDATE_MASK 0x20 +#define SMB380_CONTROL1_EE_W_MASK 0x10 +#define SMB380_CONTROL1_SELF_TEST_1_MASK 0x08 +#define SMB380_CONTROL1_SELF_TEST_0_MASK 0x04 +#define SMB380_CONTROL1_SOFT_RESET_MASK 0x02 +#define SMB380_CONTROL1_SLEEP_MASK 0x01 +//Control register - contains six values, default: x000 0011b +#define SMB380_CONTROL2 0x0B +#define SMB380_CONTROL2_ALERT_MASK 0x80 +#define SMB380_CONTROL2_ANY_MOTION_MASK 0x40 +#define SMB380_CONTROL2_COUNTER_HG_MASK 0x30 +#define SMB380_CONTROL2_COUNTER_LG_MASK 0x0C +#define SMB380_CONTROL2_ENABLE_HG_MASK 0x02 +#define SMB380_CONTROL2_ENABLE_LG_MASK 0x01 +//default: 20 +#define SMB380_LG_THRES 0x0C +//default: 150 +#define SMB380_LG_DUR 0x0D +//default: 160 +#define SMB380_HG_THRES 0x0E +//default: 150 +#define SMB380_HG_DUR 0x0F +//default: 0 +#define SMB380_ANY_MOTION_THRES 0x10 +//default: 0000 0000b +#define SMB380_ANY_MOTION_DUR_HYST 0x1 +#define SMB380_ANY_MOTION_DUR_MASK 0xC0 +#define SMB380_ANY_MOTION_DUR_HG_HYST_MASK 0x38 +#define SMB380_ANY_MOTION_DUR_LG_HYST_MASK 0x07 +//default: 162 +#define SMB380_CUST1 0x12 +//default: 13 +#define SMB380_CUST2 0x13 +//default: xxx0 1110b +#define SMB380_CONTROL3 0x14 +#define SMB380_CONTROL3_RANGE_MASK 0x18 +#define SMB380_CONTROL3_BANDWITH_MASK 0x07 +//default: 1000 0000b +#define SMB380_CONTROL4 0x15 +#define SMB380_CONTROL4_SPI4_MASK 0x80 +#define SMB380_CONTROL4_ENABLE_ADV_INT_MASK 0x40 +#define SMB380_CONTROL4_NEW_DATA_INT_MASK 0x20 +#define SMB380_CONTROL4_LATCH_INT_MASK 0x10 +#define SMB380_CONTROL4_SHADOW_DIS_MASK 0x08 +#define SMB380_CONTROL4_WAKEUP_PAUSE_MASK 0x06 +#define SMB380_CONTROL4_WAKEUP_MASK 0x01 + +#define SMB380_OFFSET_LSB_GAIN_X 0x16 +#define SMB380_OFFSET_LSB_GAIN_Y 0x17 +#define SMB380_OFFSET_LSB_GAIN_Z 0x18 +#define SMB380_OFFSET_LSB_GAIN_T 0x19 +#define SMB380_OFFSET_LSB_MASK 0xC0 +#define SMB380_OFFSET_GAIN_MASK 0x3F + +#define SMB380_OFFSET_MSB_X 0x1A +#define SMB380_OFFSET_MSB_Y 0x1B +#define SMB380_OFFSET_MSB_Z 0x1C +#define SMB380_OFFSET_MSB_T 0x1D + +#define SMB380_TEMP_OFFSET -30 +#define SMB380_DEFAULT_MAXG 4.0f +#define SMB380_READ_REGISTER 0x00 +#define SMB380_WRITE_REGISTER 0x01 +#define SMB380_WAKE_UP_PAUSE_20MS 0x00 +#define SMB380_WAKE_UP_PAUSE_80MS 0x01 +#define SMB380_WAKE_UP_PAUSE_320MS 0x02 +#define SMB380_WAKE_UP_PAUSE_2560MS 0x03 +#define SMB380_RANGE_2G 0x00 +#define SMB380_RANGE_4G 0x01 +#define SMB380_RANGE_8G 0x02 +#define SMB380_BAND_WIDTH_25HZ 0x00 +#define SMB380_BAND_WIDTH_50HZ 0x01 +#define SMB380_BAND_WIDTH_100HZ 0x02 +#define SMB380_BAND_WIDTH_190HZ 0x03 +#define SMB380_BAND_WIDTH_375HZ 0x04 +#define SMB380_BAND_WIDTH_750HZ 0x05 +#define SMB380_BAND_WIDTH_1500HZ 0x06 +//SMB380_RING_BUFF_SIZE * int16_t (2Byte) * 4 (x,y,z,Temp) = 512 Byte (for 64) +#define SMB380_RING_BUFF_SIZE 256 +//TODO chsnge size to 2048 +#define SMB380_RING_BUFF_MAX_THREADS 10 +#define SMB380_SAMPLE_RATE_MAX 3000 + +/* + * change from Header (public) to internal use (private) + * (use it after every write to EEPROM). + * set update_image Bit in control1 to + * copie content from EEPROM (0x2B to 0x3D) to Image (0x0B to 0x1D) + **/ +void SMB380_update_image(void); + +/* + * change from Header (public) to internal use (private) + * set ee_w Bit in control1 to + * enable read to 0x16 to 0x22 and + * enable write to 0x16 to 0x3D + **/ +void SMB380_enable_eeprom_default(void); +//Example Hysterese function +uint8_t SMB380_HystereseFunctionSample(int16_t *value); + +//Simple api for single-sample, single thread interrupt mode +uint8_t SMB380_init_simple(uint16_t samplerate, uint8_t bandwidth, + uint8_t range); + + +//Enables Interrupts (normally only once called) +uint8_t SMB380_init(uint8_t (*func)(int16_t *)); +void SMB380_setSampleRate(uint16_t rate); +uint16_t SMB380_getSampleRate(void); +void freeRingReadPointer(void); +void actualizeRingReadPointer(void); +uint8_t readRingBuff(int16_t *value); +uint8_t writeRingBuff(int16_t *value); +void SMB380_activateDynRangeSet(uint8_t activate); +uint8_t checkRange(int16_t *value); + +void SMB380_enableEEPROM(void); +void SMB380_disableEEPROM(void); + +// getter +float SMB380_getSampleRatio(void); +void SMB380_getAcceleration(unsigned char axis, int16_t *pAbs, int16_t *pMg); +int16_t SMB380_getTemperature(void); +unsigned char SMB380_getChipID(void); +unsigned char SMB380_getWakeUpPause(void); +unsigned char SMB380_getBandWidth(void); +int16_t SMB380_getBandWidthAbs(void); +unsigned char SMB380_getRange(void); +unsigned char SMB380_getCustomerReg(void); +unsigned char SMB380_readOffset(uint16_t *offset); +unsigned char SMB380_readOffsetTemp(uint16_t *offset); +unsigned char SMB380_readGain(uint16_t *gain); +unsigned char SMB380_readGainTemp(uint16_t *gain); + +// setter +void SMB380_setTempOffset(uint16_t offset, uint8_t EEPROM); +void SMB380_setWakeUpPause(unsigned char duration); +void SMB380_setBandWidth(unsigned char bandWidth); +void SMB380_setRange(unsigned char range); +void SMB380_softReset(void); +void SMB380_setCustomerReg(unsigned char data); +void SMB380_setUpperLimit(void); +void SMB380_enableUpperLimit(void); +void SMB380_disableUpperLimit(void); +void SMB380_enableLowerLimit(void); +void SMB380_disableLowerLimit(void); +uint8_t SMB380_setAnyMotionLimit(uint16_t mg, uint16_t gvalueint); +void SMB380_enableAnyMotionLimit(void); +void SMB380_disableAnyMotionLimit(void); +void SMB380_enableNewDataInt(void); +void SMB380_disableNewDataInt(void); +void SMB380_resetInterruptFlags(void); +void SMB380_writeOffset(uint16_t *offset, uint8_t EEPROM); +void SMB380_writeOffsetTemp(uint16_t *offset, uint8_t EEPROM); + +// stats +void SMB380_ShowMemory(void); +void SMB380_Selftest_1(void); + + +#endif /* SMB380_H_ */ diff --git a/boards/avsextrem/include/ssp0-board.h b/boards/avsextrem/include/ssp0-board.h new file mode 100644 index 0000000000..ffcc5356ee --- /dev/null +++ b/boards/avsextrem/include/ssp0-board.h @@ -0,0 +1,118 @@ +/* + * ssp0-borad.h - header file of the SPI interface for the LPC2387. + * Copyright (C) 2013 Freie Universität Berlin + * + * This source code is licensed under the LGPLv2 license, + * See the file LICENSE for more details. + * + */ + +/** + * @file + * @internal + * @brief SPI interface definitions for the LPC2387 + * + * @author Freie Universität Berlin, Computer Systems & Telematics + * @author Marco Ziegert + * @author Zakaria Kasmi + * @version $Revision: 3854 $ + * + * @note $Id: avsextrem-ssp0.c 3854 2010-01-18 15:27:01Z zkasmi $ + */ +#ifndef __SSP_H__ +#define __SSP_H__ + +#include "stdint.h" + +#define DMA_ENABLED 0 + +/* + * if USE_CS is zero, set SSEL as GPIO that you have total control of the + * sequence + **/ +#define USE_CS 0 + +/* + * if 1, use driver for onboard BMA180, otherwise for external BMA180 utilizing + * Nanopan Connector + **/ +#define BMA180_ONBOARD 1 + +#define SMB380_ACC 0 +#define NANOPAN 1 +#define NORDIC 2 +#define BMA180_EXTERN 3 +#define BMA180_INTERN 4 +#define L3G_EXTERN 5 +#define L3G_INTERN 6 +#define ACAMDMS 7 + +/* SPI read and write buffer size */ +#define BUFSIZE 256 +#define FIFOSIZE 8 + +/* SSP select pin */ +#define SSP0_SEL 1 << 21 //P1.21 SMB380 + +#define SSP0_SELN 1 << 16 //P0.16 Nanotron + +/* SSP1 external interrupt Pin (SMB380 specific) */ +#define SMB380_INT1 1 << 1 //P0.1 +#define BMA180_INT1 1 << 8 //P2.8 + + + +/* SSP1 CR0 register */ +#define SSPCR0_DSS 1 << 0 +#define SSPCR0_FRF 1 << 4 +#define SSPCR0_SPO 1 << 6 +#define SSPCR0_SPH 1 << 7 +#define SSPCR0_SCR 1 << 8 + +/* SSP1 CR1 register */ +#define SSPCR1_LBM 1 << 0 +#define SSPCR1_SSE 1 << 1 +#define SSPCR1_MS 1 << 2 +#define SSPCR1_SOD 1 << 3 + +/* SSP1 Interrupt Mask Set/Clear register */ +#define SSPIMSC_RORIM 1 << 0 +#define SSPIMSC_RTIM 1 << 1 +#define SSPIMSC_RXIM 1 << 2 +#define SSPIMSC_TXIM 1 << 3 + +/* SSP1 Interrupt Status register */ +#define SSPRIS_RORRIS 1 << 0 +#define SSPRIS_RTRIS 1 << 1 +#define SSPRIS_RXRIS 1 << 2 +#define SSPRIS_TXRIS 1 << 3 + +/* SSP1 Masked Interrupt register */ +#define SSPMIS_RORMIS 1 << 0 +#define SSPMIS_RTMIS 1 << 1 +#define SSPMIS_RXMIS 1 << 2 +#define SSPMIS_TXMIS 1 << 3 + +/* SSP1 Interrupt clear register */ +#define SSPICR_RORIC 1 << 0 +#define SSPICR_RTIC 1 << 1 + +#define SSP1_INTERRUPT_MODE 0 +#define SMB380_EXTINT_MODE 1 +#define BMA180_EXTINT_MODE 1 + +uint32_t SSP0Init(void); +uint8_t SSP0Prepare(uint8_t chip, uint8_t datasize, uint8_t cpol, uint8_t cpha, + uint16_t freq); +uint8_t SSP0Unprepare(uint8_t chip); +unsigned char SSP0_write(const uint16_t data, uint8_t device); +unsigned short SSP0_read(uint8_t device); +unsigned char SMB380_ssp_write(const unsigned char regAddr, + const unsigned char data, unsigned char flag); +unsigned short SMB380_ssp_read(void); +unsigned short nrf24l01_ssp_read_write(const uint8_t data); +unsigned short acam_trx(const uint8_t data); +void SSP0Handler(void); + +#endif /* __SSP_H__ */ + diff --git a/boards/chronos/Makefile b/boards/chronos/Makefile new file mode 100644 index 0000000000..1b8144cb49 --- /dev/null +++ b/boards/chronos/Makefile @@ -0,0 +1,35 @@ +SRC = $(wildcard *.c) +BINDIR = bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines + +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -Iinclude -I$(RIOTBASE)/sys/lib -I$(RIOTBASE)/sys/drivers/include +INCLUDES += -I$(RIOTBASE)/sys/drivers/cc110x_ng/include +INCLUDES += -I$(RIOTBASE)/core/include +INCLUDES += -I$(RIOTBASE)/cpu/msp430-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/cc430/include/ +#INCLUDES += -I/usr/msp430/include/ + +all: $(BINDIR)chronos_base.a + $(MAKE) -C drivers + +$(BINDIR)chronos_base.a: $(OBJ) + $(AR) rcs $(BINDIR)chronos_base.a $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/fw_out && mv /tmp/fw_out $(BINDIR)$*.d + +# remove compilation products +clean: + rm -f $(BINDIR)chronos_base.a $(OBJ) $(DEP) + $(MAKE) -C drivers clean + + + diff --git a/boards/chronos/Makefile.include b/boards/chronos/Makefile.include new file mode 100644 index 0000000000..04b77c5d4c --- /dev/null +++ b/boards/chronos/Makefile.include @@ -0,0 +1,22 @@ +## the cpu to build for +export CPU = cc430 +export MCU = cc430f6137 + +# toolchain config +export PREFIX = @msp430- +export CC = @$(PREFIX)gcc +export AR = @$(PREFIX)ar +export CFLAGS += -std=gnu99 -Wstrict-prototypes -gdwarf-2 -Os -Wall -mmcu=$(MCU) -D CC430 +export ASFLAGS += -mmcu=$(MCU) --defsym $(MCU)=1 --gdwarf-2 +export AS = $(PREFIX)as +export LINK = $(PREFIX)gcc +export SIZE = $(PREFIX)size +export OBJCOPY = $(PREFIX)objcopy +export LINKFLAGS = -mmcu=$(MCU) -lgcc $(RIOTBASE)/bin/startup.o +export FLASHER = mspdebug +ifeq ($(strip $(PORT)),) + export PORT = /dev/ttyUSB0 +endif +export HEXFILE = bin/$(PROJECT).hex +export FFLAGS = -d $(PORT) -j uif "prog $(HEXFILE)" +export OFLAGS = -O ihex diff --git a/boards/chronos/board_init.c b/boards/chronos/board_init.c new file mode 100644 index 0000000000..db2326701f --- /dev/null +++ b/boards/chronos/board_init.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include + +void cc430_cpu_init(void) +{ + volatile uint16_t i; + volatile unsigned char *ptr; + + /* disable watchdog */ + WDTCTL = WDTPW + WDTHOLD; + + // --------------------------------------------------------------------- + // Enable 32kHz ACLK + P5SEL |= 0x03; // Select XIN, XOUT on P5.0 and P5.1 + UCSCTL6 &= ~XT1OFF; // XT1 On, Highest drive strength + UCSCTL6 |= XCAP_3; // Internal load cap + + UCSCTL3 = SELA__XT1CLK; // Select XT1 as FLL reference + UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV; + + // --------------------------------------------------------------------- + // Configure CPU clock for 12MHz + _BIS_SR(SCG0); // Disable the FLL control loop + UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx + UCSCTL1 = DCORSEL_5; // Select suitable range + UCSCTL2 = FLLD_1 + 0x16E; // Set DCO Multiplier + _BIC_SR(SCG0); // Enable the FLL control loop + + // Worst-case settling time for the DCO when the DCO range bits have been + // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx + // UG for optimization. + // 32 x 32 x 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle + for (i = 0xFF; i > 0; i--); // Time for flag to set + + // Loop until XT1 & DCO stabilizes, use do-while to insure that + // body is executed at least once + do { + UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); + SFRIFG1 &= ~OFIFG; // Clear fault flags + } + while ((SFRIFG1 & OFIFG)); + + // Disable all interrupts + __disable_interrupt(); + // Get write-access to port mapping registers: + PMAPPWD = 0x02D52; + // Allow reconfiguration during runtime: + PMAPCTL = PMAPRECFG; + + // P2.7 = TA0CCR1A or TA1CCR0A output (buzzer output) + ptr = &P2MAP0; + *(ptr + 7) = PM_TA1CCR0A; + P2OUT &= ~BIT7; + P2DIR |= BIT7; + + // P1.5 = SPI MISO input + ptr = &P1MAP0; + *(ptr + 5) = PM_UCA0SOMI; + // P1.6 = SPI MOSI output + *(ptr + 6) = PM_UCA0SIMO; + // P1.7 = SPI CLK output + *(ptr + 7) = PM_UCA0CLK; + + // Disable write-access to port mapping registers: + PMAPPWD = 0; + // Re-enable all interrupts + enableIRQ(); + +} + +void board_init(void) +{ + cc430_cpu_init(); +} diff --git a/boards/chronos/drivers/Makefile b/boards/chronos/drivers/Makefile new file mode 100644 index 0000000000..bf355bf8e2 --- /dev/null +++ b/boards/chronos/drivers/Makefile @@ -0,0 +1,24 @@ +SRC = $(wildcard *.c) +BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o) +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBASE)/sys/include/ -I$(RIOTBASE)/drivers/cc110x_ng/include/ + +$(BINDIR)chronos_drivers.a: $(OBJ) + $(AR) rcs $(BINDIR)chronos_base.a $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)" | cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products + +clean: + rm -f $(OBJ) $(DEP) + diff --git a/boards/chronos/drivers/battery.c b/boards/chronos/drivers/battery.c new file mode 100644 index 0000000000..13e50dc102 --- /dev/null +++ b/boards/chronos/drivers/battery.c @@ -0,0 +1,14 @@ +#include +#include +#include + +uint32_t battery_get_voltage(void) +{ + uint32_t voltage; + voltage = adc12_single_conversion(REFVSEL_1, ADC12SHT0_10, ADC12INCH_11); + + /* Ideally we have A11=0->AVCC=0V ... A11=4095(2^12-1)->AVCC=4V + * --> (A11/4095)*4V=AVCC --> AVCC=(A11*4)/4095 */ + voltage = (voltage * 2 * 2 * 1000) / 4095; + return voltage; +} diff --git a/boards/chronos/drivers/buzzer.c b/boards/chronos/drivers/buzzer.c new file mode 100644 index 0000000000..3d4d15061d --- /dev/null +++ b/boards/chronos/drivers/buzzer.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +void buzzer_beep(uint8_t pitch, uint16_t duration) +{ + // Reset TA1R, set up mode, TA1 runs from 32768Hz ACLK + TA1CTL = TACLR | MC_1 | TASSEL__ACLK; + + // Set PWM frequency + TA1CCR0 = pitch; + + // Enable IRQ, set output mode "toggle" + TA1CCTL0 = OUTMOD_4; + + // Allow buzzer PWM output on P2.7 + P2SEL |= BIT7; + + hwtimer_wait(duration); + + // Stop PWM timer + TA1CTL &= ~(BIT4 | BIT5); + + // Reset and disable buzzer PWM output + P2OUT &= ~BIT7; + P2SEL &= ~BIT7; + TA1CCTL0 &= ~CCIE; +} diff --git a/boards/chronos/drivers/cc430-cc110x.c b/boards/chronos/drivers/cc430-cc110x.c new file mode 100644 index 0000000000..d606d5bfd5 --- /dev/null +++ b/boards/chronos/drivers/cc430-cc110x.c @@ -0,0 +1,94 @@ +#include + +#include +#include +#include +#include + +//#include +#include +//#include + +#define CC1100_GDO0 (RF1AIN & BIT0) +#define CC1100_GDO1 (RF1AIN & BIT1) +#define CC1100_GDO2 (RF1AIN & BIT2) + +int cc110x_get_gdo0(void) +{ + return CC1100_GDO0; +} + +int cc110x_get_gdo1(void) +{ + return CC1100_GDO1; +} + +int cc110x_get_gdo2(void) +{ + return CC1100_GDO2; +} + +void cc110x_before_send(void) +{ + // Disable GDO2 interrupt before sending packet + cc110x_gdo2_disable(); +} + +void cc110x_after_send(void) +{ + // Enable GDO2 interrupt after sending packet + cc110x_gdo2_enable(); +} + +void cc110x_gdo0_enable(void) +{ + RF1AIFG &= ~BIT0; + RF1AIE |= BIT0; +} + +void cc110x_gdo0_disable(void) +{ + RF1AIE &= ~BIT0; + RF1AIFG &= ~BIT0; +} + +void cc110x_gdo2_disable(void) +{ + RF1AIFG &= ~BIT2; // Clear a pending interrupt + RF1AIE &= ~BIT2; // Disable the interrupt +} + +void cc110x_gdo2_enable(void) +{ + RF1AIFG &= ~BIT2; // Clear a pending interrupt + RF1AIE |= BIT2; // Enable the interrupt +} + +void cc110x_init_interrupts(void) +{ + uint8_t state = disableIRQ(); /* Disable all interrupts */ + cc110x_gdo2_enable(); + cc110x_gdo0_disable(); + restoreIRQ(state); /* Enable all interrupts */ +} + +interrupt(CC1101_VECTOR) __attribute__((naked)) cc110x_isr(void) +{ + __enter_isr(); + + /* Check IFG */ + if (RF1AIV == RF1AIV_RFIFG2) { + while (RF1AIN & BIT2); + + /* discard all further interrupts */ + RF1AIV = 0; + cc110x_gdo2_irq(); + } + + if (RF1AIV == RF1AIV_RFIFG0) { + cc110x_gdo0_irq(); + RF1AIE &= ~BIT0; + } + + __exit_isr(); +} diff --git a/boards/chronos/drivers/display.c b/boards/chronos/drivers/display.c new file mode 100644 index 0000000000..b93c820e1e --- /dev/null +++ b/boards/chronos/drivers/display.c @@ -0,0 +1,418 @@ +/* ************************************************************************************************* + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ************************************************************************************************* + * Basic display functions. + * ************************************************************************************************/ + +/* ************************************************************************************************* + * Include section + */ + +/* system */ +#include + +/* driver */ +#include +#include + + +/************************************************************************************************** + * Prototypes section */ +void write_lcd_mem(uint8_t *lcdmem, uint8_t bits, uint8_t bitmask, uint8_t state); +void clear_line(uint8_t line); +void display_symbol(uint8_t symbol, uint8_t mode); + +/* ************************************************************************************************* + * Global Variable section */ + +/* Display flags */ +volatile s_display_flags_t display; + +/* Global return string for itoa function */ +char itoa_str[8]; + +void lcd_init(void) +{ + /* Clear entire display memory */ + LCDBMEMCTL |= LCDCLRBM + LCDCLRM; + + /* LCD_FREQ = ACLK/16/8 = 256Hz */ + /* Frame frequency = 256Hz/4 = 64Hz, LCD mux 4, LCD on */ + LCDBCTL0 = (LCDDIV0 + LCDDIV1 + LCDDIV2 + LCDDIV3) | (LCDPRE0 + LCDPRE1) | LCD4MUX | LCDON; + + /* LCB_BLK_FREQ = ACLK/8/4096 = 1Hz */ + LCDBBLKCTL = LCDBLKPRE0 | LCDBLKPRE1 | LCDBLKDIV0 | LCDBLKDIV1 | LCDBLKDIV2 | LCDBLKMOD0; + + /* I/O to COM outputs */ + P5SEL |= (BIT5 | BIT6 | BIT7); + P5DIR |= (BIT5 | BIT6 | BIT7); + + /* Activate LCD output */ + LCDBPCTL0 = 0xFFFF; /* Select LCD segments S0-S15 */ + LCDBPCTL1 = 0x00FF; /* Select LCD segments S16-S22 */ + +#ifdef USE_LCD_CHARGE_PUMP + /* Charge pump voltage generated internally, internal bias (V2-V4) generation */ + LCDBVCTL = LCDCPEN | VLCD_2_72; +#endif +} + +void clear_display_all(void) +{ + // Clear generic content + clear_line(LINE1); + clear_line(LINE2); +} + +void clear_display(void) +{ + clear_line(LINE1); + clear_line(LINE2); +} + +void clear_line(uint8_t line) +{ + display_chars(switch_seg(line, LCD_SEG_L1_3_0, LCD_SEG_L2_5_0), NULL, SEG_OFF); + + if (line == LINE1) { + display_symbol(LCD_SEG_L1_DP1, SEG_OFF); + display_symbol(LCD_SEG_L1_DP0, SEG_OFF); + display_symbol(LCD_SEG_L1_COL, SEG_OFF); + } + /* line == LINE2 */ + else { + display_symbol(LCD_SEG_L2_DP, SEG_OFF); + display_symbol(LCD_SEG_L2_COL1, SEG_OFF); + display_symbol(LCD_SEG_L2_COL0, SEG_OFF); + } +} + +void write_lcd_mem(uint8_t *lcdmem, uint8_t bits, uint8_t bitmask, uint8_t state) +{ + if (state == SEG_ON) { + /* Clear segments before writing */ + *lcdmem = (uint8_t)(*lcdmem & ~bitmask); + + /* Set visible segments */ + *lcdmem = (uint8_t)(*lcdmem | bits); + } + else if (state == SEG_OFF) { + /* Clear segments */ + *lcdmem = (uint8_t)(*lcdmem & ~bitmask); + } + else if (state == SEG_ON_BLINK_ON) { + /* Clear visible / blink segments before writing */ + *lcdmem = (uint8_t)(*lcdmem & ~bitmask); + *(lcdmem + 0x20) = (uint8_t)(*(lcdmem + 0x20) & ~bitmask); + + /* Set visible / blink segments */ + *lcdmem = (uint8_t)(*lcdmem | bits); + *(lcdmem + 0x20) = (uint8_t)(*(lcdmem + 0x20) | bits); + } + else if (state == SEG_ON_BLINK_OFF) { + /* Clear visible segments before writing */ + *lcdmem = (uint8_t)(*lcdmem & ~bitmask); + + /* Set visible segments */ + *lcdmem = (uint8_t)(*lcdmem | bits); + + /* Clear blink segments */ + *(lcdmem + 0x20) = (uint8_t)(*(lcdmem + 0x20) & ~bitmask); + } + else if (state == SEG_OFF_BLINK_OFF) { + /* Clear segments */ + *lcdmem = (uint8_t)(*lcdmem & ~bitmask); + + /* Clear blink segments */ + *(lcdmem + 0x20) = (uint8_t)(*(lcdmem + 0x20) & ~bitmask); + } +} + +char *itoa(uint32_t n, uint8_t digits, uint8_t blanks) +{ + uint8_t i; + uint8_t digits1 = digits; + + /* Preset result string */ + memcpy(itoa_str, "0000000", 7); + + /* Return empty string if number of digits is invalid (valid range for digits: 1-7) */ + if ((digits == 0) || (digits > 7)) { + return (itoa_str); + } + + /* Numbers 0 .. 180 can be copied from itoa_conversion_table without conversion */ + if (n <= 180) { + if (digits >= 3) { + memcpy(itoa_str + (digits - 3), itoa_conversion_table[n], 3); + } + /* digits == 1 || 2 */ + else { + memcpy(itoa_str, itoa_conversion_table[n] + (3 - digits), digits); + } + } + /* For n > 180 need to calculate string content */ + else { + /* Calculate digits from least to most significant number */ + do { + itoa_str[digits - 1] = n % 10 + '0'; + n /= 10; + } + while (--digits > 0); + } + + /* Remove specified number of leading '0', always keep last one */ + i = 0; + + while ((itoa_str[i] == '0') && (i < digits1 - 1)) { + if (blanks > 0) { + /* Convert only specified number of leading '0' */ + itoa_str[i] = ' '; + blanks--; + } + + i++; + } + + return (itoa_str); +} + +void display_value1(uint8_t segments, uint32_t value, uint8_t digits, uint8_t blanks, uint8_t disp_mode) +{ + char *str; + + str = itoa(value, digits, blanks); + + /* Display string in blink mode */ + display_chars(segments, str, disp_mode); +} + +void display_symbol(uint8_t symbol, uint8_t mode) +{ + uint8_t *lcdmem; + uint8_t bits; + uint8_t bitmask; + + if (symbol <= LCD_SEG_L2_DP) { + /* Get LCD memory address for symbol from table */ + lcdmem = (uint8_t *)segments_lcdmem[symbol]; + + /* Get bits for symbol from table */ + bits = segments_bitmask[symbol]; + + /* Bitmask for symbols equals bits */ + bitmask = bits; + + /* Write LCD memory */ + write_lcd_mem(lcdmem, bits, bitmask, mode); + } +} + +void display_char(uint8_t segment, char chr, uint8_t mode) +{ + uint8_t *lcdmem; /* Pointer to LCD memory */ + uint8_t bitmask; /* Bitmask for character */ + uint8_t bits, bits1; /* Bits to write */ + + /* Write to single 7-segment character */ + if ((segment >= LCD_SEG_L1_3) && (segment <= LCD_SEG_L2_DP)) { + /* Get LCD memory address for segment from table */ + lcdmem = (uint8_t *)segments_lcdmem[segment]; + + /* Get bitmask for character from table */ + bitmask = segments_bitmask[segment]; + + /* Get bits from font set */ + if ((chr >= 0x30) && (chr <= 0x5A)) { + /* Use font set */ + bits = lcd_font[chr - 0x30]; + } + else if (chr == 0x2D) { + /* '-' not in font set */ + bits = BIT1; + } + else { + /* Other characters map to ' ' (blank) */ + bits = 0; + } + + /* When addressing LINE2 7-segment characters need to swap high- and low-nibble, */ + /* because LCD COM/SEG assignment is mirrored against LINE1 */ + if (segment >= LCD_SEG_L2_5) { + bits1 = ((bits << 4) & 0xF0) | ((bits >> 4) & 0x0F); + bits = bits1; + + /* When addressing LCD_SEG_L2_5, need to convert ASCII '1' and 'L' to 1 bit, */ + /* because LCD COM/SEG assignment is special for this incomplete character */ + if (segment == LCD_SEG_L2_5) { + if ((chr == '1') || (chr == 'L')) { + bits = BIT7; + } + } + } + + /* Physically write to LCD memory */ + write_lcd_mem(lcdmem, bits, bitmask, mode); + } +} + +void display_chars(uint8_t segments, char *str, uint8_t mode) +{ + uint8_t i; + uint8_t length = 0; /* Write length */ + uint8_t char_start = 0; /* Starting point for consecutive write */ + + switch (segments) { + /* LINE1 */ + case LCD_SEG_L1_3_0: + length = 4; + char_start = LCD_SEG_L1_3; + break; + + case LCD_SEG_L1_2_0: + length = 3; + char_start = LCD_SEG_L1_2; + break; + + case LCD_SEG_L1_1_0: + length = 2; + char_start = LCD_SEG_L1_1; + break; + + case LCD_SEG_L1_3_1: + length = 3; + char_start = LCD_SEG_L1_3; + break; + + case LCD_SEG_L1_3_2: + length = 2; + char_start = LCD_SEG_L1_3; + break; + + /* LINE2 */ + case LCD_SEG_L2_5_0: + length = 6; + char_start = LCD_SEG_L2_5; + break; + + case LCD_SEG_L2_4_0: + length = 5; + char_start = LCD_SEG_L2_4; + break; + + case LCD_SEG_L2_3_0: + length = 4; + char_start = LCD_SEG_L2_3; + break; + + case LCD_SEG_L2_2_0: + length = 3; + char_start = LCD_SEG_L2_2; + break; + + case LCD_SEG_L2_1_0: + length = 2; + char_start = LCD_SEG_L2_1; + break; + + case LCD_SEG_L2_5_4: + length = 2; + char_start = LCD_SEG_L2_5; + break; + + case LCD_SEG_L2_5_2: + length = 4; + char_start = LCD_SEG_L2_5; + break; + + case LCD_SEG_L2_3_2: + length = 2; + char_start = LCD_SEG_L2_3; + break; + + case LCD_SEG_L2_4_2: + length = 3; + char_start = LCD_SEG_L2_4; + break; + } + + /* Write to consecutive digits */ + for (i = 0; i < length; i++) { + /* Use single character routine to write display memory */ + display_char(char_start + i, *(str + i), mode); + } +} + +uint8_t switch_seg(uint8_t line, uint8_t index1, uint8_t index2) +{ + if (line == LINE1) { + return index1; + } + /* line == LINE2 */ + else { + return index2; + } +} + +void start_blink(void) +{ + LCDBBLKCTL |= LCDBLKMOD0; +} + +void stop_blink(void) +{ + LCDBBLKCTL &= ~LCDBLKMOD0; +} + +void clear_blink_mem(void) +{ + LCDBMEMCTL |= LCDCLRBM; +} + +void set_blink_rate(uint8_t bits) +{ + LCDBBLKCTL &= ~(BIT7 | BIT6 | BIT5); + LCDBBLKCTL |= bits; +} + +void display_all_off(void) +{ + uint8_t *lcdptr = (uint8_t *)0x0A20; + uint8_t i; + + for (i = 1; i <= 12; i++) { + *lcdptr = 0x00; + lcdptr++; + } +} diff --git a/boards/chronos/drivers/display1.c b/boards/chronos/drivers/display1.c new file mode 100644 index 0000000000..461c0c0097 --- /dev/null +++ b/boards/chronos/drivers/display1.c @@ -0,0 +1,208 @@ +/* ************************************************************************************************* + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ************************************************************************************************/ + +/* Basic display functions. */ +/* ************************************************************************************************* */ + +/* ************************************************************************************************* */ +/* Include section */ +#include +#include +#include + +/* ************************************************************************************************* */ +/* Global Variable section */ + +/* Table with memory bit assignment for digits "0" to "9" and characters "A" to "Z" */ +/* A */ +/* F B */ +/* G */ +/* E C */ +/* D */ +const uint8_t lcd_font[] = { + SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F, /* Displays "0" */ + SEG_B + SEG_C, /* Displays "1" */ + SEG_A + SEG_B + SEG_D + SEG_E + SEG_G, /* Displays "2" */ + SEG_A + SEG_B + SEG_C + SEG_D + SEG_G, /* Displays "3" */ + SEG_B + SEG_C + SEG_F + SEG_G, /* Displays "4" */ + SEG_A + SEG_C + SEG_D + SEG_F + SEG_G, /* Displays "5" */ + SEG_A + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G, /* Displays "6" */ + SEG_A + SEG_B + SEG_C, /* Displays "7" */ + SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G, /* Displays "8" */ + SEG_A + SEG_B + SEG_C + SEG_D + SEG_F + SEG_G, /* Displays "9" */ + 0, /* Displays " " (:) */ + 0, /* Displays " " (;) */ + SEG_A + SEG_F + SEG_G, /* Displays "<" as high c */ + SEG_D + SEG_G, /* Displays "=" */ + 0, /* Displays " " (>) */ + SEG_A + SEG_B + SEG_E + SEG_G, /* Displays "?" */ + 0, /* Displays " " (@) */ + SEG_A + SEG_B + SEG_C + SEG_E + SEG_F + SEG_G, /* Displays "A" */ + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G, /* Displays "b" */ + SEG_D + SEG_E + SEG_G, /* Displays "c" */ + SEG_B + SEG_C + SEG_D + SEG_E + SEG_G, /* Displays "d" */ + SEG_A + SEG_D + SEG_E + SEG_F + SEG_G, /* Displays "E" */ + SEG_A + SEG_E + SEG_F + SEG_G, /* Displays "f" */ + SEG_A + SEG_B + SEG_C + SEG_D + SEG_F + SEG_G, /* Displays "g" same as 9 */ + SEG_C + SEG_E + SEG_F + SEG_G, /* Displays "h" */ + SEG_E, /* Displays "i" */ + SEG_A + SEG_B + SEG_C + SEG_D, /* Displays "J" */ + SEG_D + SEG_F + SEG_G, /* Displays "k" */ + SEG_D + SEG_E + SEG_F, /* Displays "L" */ + SEG_A + SEG_B + SEG_C + SEG_E + SEG_F, /* Displays "M" */ + SEG_C + SEG_E + SEG_G, /* Displays "n" */ + SEG_C + SEG_D + SEG_E + SEG_G, /* Displays "o" */ + SEG_A + SEG_B + SEG_E + SEG_F + SEG_G, /* Displays "P" */ + SEG_A + SEG_B + SEG_C + SEG_F + SEG_G, /* Displays "q" */ + SEG_E + SEG_G, /* Displays "r" */ + SEG_A + SEG_C + SEG_D + SEG_F + SEG_G, /* Displays "S" same as 5 */ + SEG_D + SEG_E + SEG_F + SEG_G, /* Displays "t" */ + SEG_C + SEG_D + SEG_E, /* Displays "u" */ + SEG_C + SEG_D + SEG_E, /* Displays "v" same as u */ + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G, /* Displays "W" */ + SEG_B + SEG_C + SEG_E + SEG_F + SEG_G, /* Displays "X" as H */ + SEG_B + SEG_C + SEG_D + SEG_F + SEG_G, /* Displays "Y" */ + SEG_A + SEG_B + SEG_D + SEG_E + SEG_G, /* Displays "Z" same as 2 */ +}; + +/* Table with memory address for each display element */ +const uint8_t *segments_lcdmem[] = { + LCD_SYMB_AM_MEM, + LCD_SYMB_PM_MEM, + LCD_SYMB_ARROW_UP_MEM, + LCD_SYMB_ARROW_DOWN_MEM, + LCD_SYMB_PERCENT_MEM, + LCD_SYMB_TOTAL_MEM, + LCD_SYMB_AVERAGE_MEM, + LCD_SYMB_MAX_MEM, + LCD_SYMB_BATTERY_MEM, + LCD_UNIT_L1_FT_MEM, + LCD_UNIT_L1_K_MEM, + LCD_UNIT_L1_M_MEM, + LCD_UNIT_L1_I_MEM, + LCD_UNIT_L1_PER_S_MEM, + LCD_UNIT_L1_PER_H_MEM, + LCD_UNIT_L1_DEGREE_MEM, + LCD_UNIT_L2_KCAL_MEM, + LCD_UNIT_L2_KM_MEM, + LCD_UNIT_L2_MI_MEM, + LCD_ICON_HEART_MEM, + LCD_ICON_STOPWATCH_MEM, + LCD_ICON_RECORD_MEM, + LCD_ICON_ALARM_MEM, + LCD_ICON_BEEPER1_MEM, + LCD_ICON_BEEPER2_MEM, + LCD_ICON_BEEPER3_MEM, + LCD_SEG_L1_3_MEM, + LCD_SEG_L1_2_MEM, + LCD_SEG_L1_1_MEM, + LCD_SEG_L1_0_MEM, + LCD_SEG_L1_COL_MEM, + LCD_SEG_L1_DP1_MEM, + LCD_SEG_L1_DP0_MEM, + LCD_SEG_L2_5_MEM, + LCD_SEG_L2_4_MEM, + LCD_SEG_L2_3_MEM, + LCD_SEG_L2_2_MEM, + LCD_SEG_L2_1_MEM, + LCD_SEG_L2_0_MEM, + LCD_SEG_L2_COL1_MEM, + LCD_SEG_L2_COL0_MEM, + LCD_SEG_L2_DP_MEM, +}; + +/* Table with bit mask for each display element */ +const uint8_t segments_bitmask[] = { + LCD_SYMB_AM_MASK, + LCD_SYMB_PM_MASK, + LCD_SYMB_ARROW_UP_MASK, + LCD_SYMB_ARROW_DOWN_MASK, + LCD_SYMB_PERCENT_MASK, + LCD_SYMB_TOTAL_MASK, + LCD_SYMB_AVERAGE_MASK, + LCD_SYMB_MAX_MASK, + LCD_SYMB_BATTERY_MASK, + LCD_UNIT_L1_FT_MASK, + LCD_UNIT_L1_K_MASK, + LCD_UNIT_L1_M_MASK, + LCD_UNIT_L1_I_MASK, + LCD_UNIT_L1_PER_S_MASK, + LCD_UNIT_L1_PER_H_MASK, + LCD_UNIT_L1_DEGREE_MASK, + LCD_UNIT_L2_KCAL_MASK, + LCD_UNIT_L2_KM_MASK, + LCD_UNIT_L2_MI_MASK, + LCD_ICON_HEART_MASK, + LCD_ICON_STOPWATCH_MASK, + LCD_ICON_RECORD_MASK, + LCD_ICON_ALARM_MASK, + LCD_ICON_BEEPER1_MASK, + LCD_ICON_BEEPER2_MASK, + LCD_ICON_BEEPER3_MASK, + LCD_SEG_L1_3_MASK, + LCD_SEG_L1_2_MASK, + LCD_SEG_L1_1_MASK, + LCD_SEG_L1_0_MASK, + LCD_SEG_L1_COL_MASK, + LCD_SEG_L1_DP1_MASK, + LCD_SEG_L1_DP0_MASK, + LCD_SEG_L2_5_MASK, + LCD_SEG_L2_4_MASK, + LCD_SEG_L2_3_MASK, + LCD_SEG_L2_2_MASK, + LCD_SEG_L2_1_MASK, + LCD_SEG_L2_0_MASK, + LCD_SEG_L2_COL1_MASK, + LCD_SEG_L2_COL0_MASK, + LCD_SEG_L2_DP_MASK, +}; + +/* Quick integer to array conversion table for most common integer values + * discarding this would save aprox. 600 bytes codespace but increase cpu time + * for displaying values */ +const uint8_t itoa_conversion_table[][3] = { + "000", "001", "002", "003", "004", "005", "006", "007", "008", "009", "010", "011", "012", "013", "014", "015", + "016", "017", "018", "019", "020", "021", "022", "023", "024", "025", "026", "027", "028", "029", "030", "031", + "032", "033", "034", "035", "036", "037", "038", "039", "040", "041", "042", "043", "044", "045", "046", "047", + "048", "049", "050", "051", "052", "053", "054", "055", "056", "057", "058", "059", "060", "061", "062", "063", + "064", "065", "066", "067", "068", "069", "070", "071", "072", "073", "074", "075", "076", "077", "078", "079", + "080", "081", "082", "083", "084", "085", "086", "087", "088", "089", "090", "091", "092", "093", "094", "095", + "096", "097", "098", "099", "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", "110", "111", + "112", "113", "114", "115", "116", "117", "118", "119", "120", "121", "122", "123", "124", "125", "126", "127", + "128", "129", "130", "131", "132", "133", "134", "135", "136", "137", "138", "139", "140", "141", "142", "143", + "144", "145", "146", "147", "148", "149", "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", + "160", "161", "162", "163", "164", "165", "166", "167", "168", "169", "170", "171", "172", "173", "174", "175", + "176", "177", "178", "179", "180", +}; diff --git a/boards/chronos/drivers/display_putchar.c b/boards/chronos/drivers/display_putchar.c new file mode 100644 index 0000000000..95498ea8e0 --- /dev/null +++ b/boards/chronos/drivers/display_putchar.c @@ -0,0 +1,45 @@ +#include +#include +#include + +extern int toupper(int c); +extern void (*_putchar)(int c); + +static char display_buf[11]; + +void putchar_to_display(int c); + +void init_display_putchar(void) +{ + memset(display_buf, '\0', 11); + _putchar = putchar_to_display; +} + +void putchar_to_display(int c) +{ + if (c == '\n') { + display_buf[4] = 1; + return; + } + + if (display_buf[4]) { + memset(display_buf, '\0', 11); + } + else { + display_buf[0] = display_buf[1]; + display_buf[1] = display_buf[2]; + display_buf[2] = display_buf[3]; + display_buf[3] = display_buf[5]; + display_buf[5] = display_buf[6]; + display_buf[6] = display_buf[7]; + display_buf[7] = display_buf[8]; + display_buf[8] = display_buf[9]; + } + + display_buf[9] = toupper(c); + + clear_display_all(); + + display_chars(LCD_SEG_L1_3_0, display_buf, SEG_ON); + display_chars(LCD_SEG_L2_5_0, display_buf + 4, SEG_ON); +} diff --git a/boards/chronos/drivers/include/battery.h b/boards/chronos/drivers/include/battery.h new file mode 100644 index 0000000000..e1f1569799 --- /dev/null +++ b/boards/chronos/drivers/include/battery.h @@ -0,0 +1,6 @@ +#ifndef BATTERY_H +#define BATTERY_H + +uint32_t battery_get_voltage(void); + +#endif /* BATTERY_H */ diff --git a/boards/chronos/drivers/include/buzzer.h b/boards/chronos/drivers/include/buzzer.h new file mode 100644 index 0000000000..47ccb81112 --- /dev/null +++ b/boards/chronos/drivers/include/buzzer.h @@ -0,0 +1,6 @@ +#ifndef BUZZER_H +#define BUZZER_H + +void buzzer_beep(uint8_t pitch, uint16_t duration); + +#endif /* BUZZER_H */ diff --git a/boards/chronos/drivers/include/display.h b/boards/chronos/drivers/include/display.h new file mode 100644 index 0000000000..533ce1e1db --- /dev/null +++ b/boards/chronos/drivers/include/display.h @@ -0,0 +1,458 @@ +/* ************************************************************************************************* + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ************************************************************************************************* + * Basic display functions. + * ************************************************************************************************/ + +#ifndef __DISPLAY_H +#define __DISPLAY_H + +#define CLOCK_24HR (0) +#define CLOCK_AM_PM (1) +#define CLOCK_DISPLAY_SELECT (2) + + +/* ************************************************************************************************* + * Global Variable section */ + +/* Set of display flags */ +typedef union { + struct { + /* Line1 + Line2 + Icons*/ + uint16_t full_update : 1; /* 1 = Redraw all content */ + uint16_t partial_update : 1; /* 1 = Update changes */ + + /* Line only */ + uint16_t line1_full_update : 1; /* 1 = Redraw Line1 content */ + uint16_t line2_full_update : 1; /* 1 = Redraw Line2 content */ + + /* Logic module data update flags */ + uint16_t update_time : 1; /* 1 = Time was updated */ + uint16_t update_stopwatch : 1; /* 1 = Stopwatch was updated */ + uint16_t update_temperature : 1; /* 1 = Temperature was updated */ + uint16_t update_battery_voltage : 1; /* 1 = Battery voltage was updated */ + uint16_t update_date : 1; /* 1 = Date was updated */ + uint16_t update_alarm : 1; /* 1 = Alarm time was updated */ + uint16_t update_acceleration : 1; /* 1 = Acceleration data was updated */ + } flag; + uint16_t all_flags; /* Shortcut to all display flags (for reset) */ +} s_display_flags_t; + +extern volatile s_display_flags_t display; + +/* Constants defined in library */ +extern const uint8_t lcd_font[]; +extern const uint8_t *segments_lcdmem[]; +extern const uint8_t segments_bitmask[]; +extern const uint8_t itoa_conversion_table[][3]; + +/* ************************************************************************************************* */ +/* Defines section */ + +/* Display function modes */ +#define DISPLAY_LINE_UPDATE_FULL (BIT0) +#define DISPLAY_LINE_UPDATE_PARTIAL (BIT1) +#define DISPLAY_LINE_CLEAR (BIT2) + +/* Definitions for line view style */ +#define DISPLAY_DEFAULT_VIEW (0u) +#define DISPLAY_ALTERNATIVE_VIEW (1u) +#define DISPLAY_ALTERNATIVE2_VIEW (2u) + +/* Definitions for line access */ +#define LINE1 (1u) +#define LINE2 (2u) + +/* LCD display modes */ +#define SEG_OFF (0u) +#define SEG_ON (1u) +#define SEG_ON_BLINK_ON (2u) +#define SEG_ON_BLINK_OFF (3u) +#define SEG_OFF_BLINK_OFF (4u) + +/* 7-segment character bit assignments */ +#define SEG_A (BIT4) +#define SEG_B (BIT5) +#define SEG_C (BIT6) +#define SEG_D (BIT7) +#define SEG_E (BIT2) +#define SEG_F (BIT0) +#define SEG_G (BIT1) + +/* ------------------------------------------ + * LCD symbols for easier access + * + * xxx_SEG_xxx = Seven-segment character (sequence 5-4-3-2-1-0) + * xxx_SYMB_xxx = Display symbol, e.g. "AM" for ante meridiem + * xxx_UNIT_xxx = Display unit, e.g. "km/h" for kilometers per hour + * xxx_ICON_xxx = Display icon, e.g. heart to indicate reception of heart rate data + * xxx_L1_xxx = Item is part of Line1 information + * xxx_L2_xxx = Item is part of Line2 information + */ + +//* Symbols for Line1 */ +#define LCD_SYMB_AM 0 +#define LCD_SYMB_PM 1 +#define LCD_SYMB_ARROW_UP 2 +#define LCD_SYMB_ARROW_DOWN 3 +#define LCD_SYMB_PERCENT 4 + +/* Symbols for Line2 */ +#define LCD_SYMB_TOTAL 5 +#define LCD_SYMB_AVERAGE 6 +#define LCD_SYMB_MAX 7 +#define LCD_SYMB_BATTERY 8 + +/* Units for Line1 */ +#define LCD_UNIT_L1_FT 9 +#define LCD_UNIT_L1_K 10 +#define LCD_UNIT_L1_M 11 +#define LCD_UNIT_L1_I 12 +#define LCD_UNIT_L1_PER_S 13 +#define LCD_UNIT_L1_PER_H 14 +#define LCD_UNIT_L1_DEGREE 15 + +/* Units for Line2 */ +#define LCD_UNIT_L2_KCAL 16 +#define LCD_UNIT_L2_KM 17 +#define LCD_UNIT_L2_MI 18 + +/* Icons */ +#define LCD_ICON_HEART 19 +#define LCD_ICON_STOPWATCH 20 +#define LCD_ICON_RECORD 21 +#define LCD_ICON_ALARM 22 +#define LCD_ICON_BEEPER1 23 +#define LCD_ICON_BEEPER2 24 +#define LCD_ICON_BEEPER3 25 + +/* Line1 7-segments */ +#define LCD_SEG_L1_3 26 +#define LCD_SEG_L1_2 27 +#define LCD_SEG_L1_1 28 +#define LCD_SEG_L1_0 29 +#define LCD_SEG_L1_COL 30 +#define LCD_SEG_L1_DP1 31 +#define LCD_SEG_L1_DP0 32 + +/* Line2 7-segments */ +#define LCD_SEG_L2_5 33 +#define LCD_SEG_L2_4 34 +#define LCD_SEG_L2_3 35 +#define LCD_SEG_L2_2 36 +#define LCD_SEG_L2_1 37 +#define LCD_SEG_L2_0 38 +#define LCD_SEG_L2_COL1 39 +#define LCD_SEG_L2_COL0 40 +#define LCD_SEG_L2_DP 41 + +/* Line1 7-segment arrays */ +#define LCD_SEG_L1_3_0 70 +#define LCD_SEG_L1_2_0 71 +#define LCD_SEG_L1_1_0 72 +#define LCD_SEG_L1_3_1 73 +#define LCD_SEG_L1_3_2 74 + +/* Line2 7-segment arrays */ +#define LCD_SEG_L2_5_0 90 +#define LCD_SEG_L2_4_0 91 +#define LCD_SEG_L2_3_0 92 +#define LCD_SEG_L2_2_0 93 +#define LCD_SEG_L2_1_0 94 +#define LCD_SEG_L2_5_2 95 +#define LCD_SEG_L2_3_2 96 +#define LCD_SEG_L2_5_4 97 +#define LCD_SEG_L2_4_2 98 + +/* LCD controller memory map */ +#define LCD_MEM_1 ((uint8_t*)0x0A20) +#define LCD_MEM_2 ((uint8_t*)0x0A21) +#define LCD_MEM_3 ((uint8_t*)0x0A22) +#define LCD_MEM_4 ((uint8_t*)0x0A23) +#define LCD_MEM_5 ((uint8_t*)0x0A24) +#define LCD_MEM_6 ((uint8_t*)0x0A25) +#define LCD_MEM_7 ((uint8_t*)0x0A26) +#define LCD_MEM_8 ((uint8_t*)0x0A27) +#define LCD_MEM_9 ((uint8_t*)0x0A28) +#define LCD_MEM_10 ((uint8_t*)0x0A29) +#define LCD_MEM_11 ((uint8_t*)0x0A2A) +#define LCD_MEM_12 ((uint8_t*)0x0A2B) + +/* Memory assignment */ +#define LCD_SEG_L1_0_MEM (LCD_MEM_6) +#define LCD_SEG_L1_1_MEM (LCD_MEM_4) +#define LCD_SEG_L1_2_MEM (LCD_MEM_3) +#define LCD_SEG_L1_3_MEM (LCD_MEM_2) +#define LCD_SEG_L1_COL_MEM (LCD_MEM_1) +#define LCD_SEG_L1_DP1_MEM (LCD_MEM_1) +#define LCD_SEG_L1_DP0_MEM (LCD_MEM_5) +#define LCD_SEG_L2_0_MEM (LCD_MEM_8) +#define LCD_SEG_L2_1_MEM (LCD_MEM_9) +#define LCD_SEG_L2_2_MEM (LCD_MEM_10) +#define LCD_SEG_L2_3_MEM (LCD_MEM_11) +#define LCD_SEG_L2_4_MEM (LCD_MEM_12) +#define LCD_SEG_L2_5_MEM (LCD_MEM_12) +#define LCD_SEG_L2_COL1_MEM (LCD_MEM_1) +#define LCD_SEG_L2_COL0_MEM (LCD_MEM_5) +#define LCD_SEG_L2_DP_MEM (LCD_MEM_9) +#define LCD_SYMB_AM_MEM (LCD_MEM_1) +#define LCD_SYMB_PM_MEM (LCD_MEM_1) +#define LCD_SYMB_ARROW_UP_MEM (LCD_MEM_1) +#define LCD_SYMB_ARROW_DOWN_MEM (LCD_MEM_1) +#define LCD_SYMB_PERCENT_MEM (LCD_MEM_5) +#define LCD_SYMB_TOTAL_MEM (LCD_MEM_11) +#define LCD_SYMB_AVERAGE_MEM (LCD_MEM_10) +#define LCD_SYMB_MAX_MEM (LCD_MEM_8) +#define LCD_SYMB_BATTERY_MEM (LCD_MEM_7) +#define LCD_UNIT_L1_FT_MEM (LCD_MEM_5) +#define LCD_UNIT_L1_K_MEM (LCD_MEM_5) +#define LCD_UNIT_L1_M_MEM (LCD_MEM_7) +#define LCD_UNIT_L1_I_MEM (LCD_MEM_7) +#define LCD_UNIT_L1_PER_S_MEM (LCD_MEM_5) +#define LCD_UNIT_L1_PER_H_MEM (LCD_MEM_7) +#define LCD_UNIT_L1_DEGREE_MEM (LCD_MEM_5) +#define LCD_UNIT_L2_KCAL_MEM (LCD_MEM_7) +#define LCD_UNIT_L2_KM_MEM (LCD_MEM_7) +#define LCD_UNIT_L2_MI_MEM (LCD_MEM_7) +#define LCD_ICON_HEART_MEM (LCD_MEM_2) +#define LCD_ICON_STOPWATCH_MEM (LCD_MEM_3) +#define LCD_ICON_RECORD_MEM (LCD_MEM_1) +#define LCD_ICON_ALARM_MEM (LCD_MEM_4) +#define LCD_ICON_BEEPER1_MEM (LCD_MEM_5) +#define LCD_ICON_BEEPER2_MEM (LCD_MEM_6) +#define LCD_ICON_BEEPER3_MEM (LCD_MEM_7) + +/* Bit masks for write access */ +#define LCD_SEG_L1_0_MASK (BIT2+BIT1+BIT0+BIT7+BIT6+BIT5+BIT4) +#define LCD_SEG_L1_1_MASK (BIT2+BIT1+BIT0+BIT7+BIT6+BIT5+BIT4) +#define LCD_SEG_L1_2_MASK (BIT2+BIT1+BIT0+BIT7+BIT6+BIT5+BIT4) +#define LCD_SEG_L1_3_MASK (BIT2+BIT1+BIT0+BIT7+BIT6+BIT5+BIT4) +#define LCD_SEG_L1_COL_MASK (BIT5) +#define LCD_SEG_L1_DP1_MASK (BIT6) +#define LCD_SEG_L1_DP0_MASK (BIT2) +#define LCD_SEG_L2_0_MASK (BIT3+BIT2+BIT1+BIT0+BIT6+BIT5+BIT4) +#define LCD_SEG_L2_1_MASK (BIT3+BIT2+BIT1+BIT0+BIT6+BIT5+BIT4) +#define LCD_SEG_L2_2_MASK (BIT3+BIT2+BIT1+BIT0+BIT6+BIT5+BIT4) +#define LCD_SEG_L2_3_MASK (BIT3+BIT2+BIT1+BIT0+BIT6+BIT5+BIT4) +#define LCD_SEG_L2_4_MASK (BIT3+BIT2+BIT1+BIT0+BIT6+BIT5+BIT4) +#define LCD_SEG_L2_5_MASK (BIT7) +#define LCD_SEG_L2_COL1_MASK (BIT4) +#define LCD_SEG_L2_COL0_MASK (BIT0) +#define LCD_SEG_L2_DP_MASK (BIT7) +#define LCD_SYMB_AM_MASK (BIT1+BIT0) +#define LCD_SYMB_PM_MASK (BIT0) +#define LCD_SYMB_ARROW_UP_MASK (BIT2) +#define LCD_SYMB_ARROW_DOWN_MASK (BIT3) +#define LCD_SYMB_PERCENT_MASK (BIT4) +#define LCD_SYMB_TOTAL_MASK (BIT7) +#define LCD_SYMB_AVERAGE_MASK (BIT7) +#define LCD_SYMB_MAX_MASK (BIT7) +#define LCD_SYMB_BATTERY_MASK (BIT7) +#define LCD_UNIT_L1_FT_MASK (BIT5) +#define LCD_UNIT_L1_K_MASK (BIT6) +#define LCD_UNIT_L1_M_MASK (BIT1) +#define LCD_UNIT_L1_I_MASK (BIT0) +#define LCD_UNIT_L1_PER_S_MASK (BIT7) +#define LCD_UNIT_L1_PER_H_MASK (BIT2) +#define LCD_UNIT_L1_DEGREE_MASK (BIT1) +#define LCD_UNIT_L2_KCAL_MASK (BIT4) +#define LCD_UNIT_L2_KM_MASK (BIT5) +#define LCD_UNIT_L2_MI_MASK (BIT6) +#define LCD_ICON_HEART_MASK (BIT3) +#define LCD_ICON_STOPWATCH_MASK (BIT3) +#define LCD_ICON_RECORD_MASK (BIT7) +#define LCD_ICON_ALARM_MASK (BIT3) +#define LCD_ICON_BEEPER1_MASK (BIT3) +#define LCD_ICON_BEEPER2_MASK (BIT3) +#define LCD_ICON_BEEPER3_MASK (BIT3) + + +/* ************************************************************************************************* + * API section + */ + +/* Physical LCD memory write */ +/* ************************************************************************************************* + * @fn write_segment + * @brief Write to one or multiple LCD segments + * @param lcdmem Pointer to LCD byte memory + * bits Segments to address + * bitmask Bitmask for particular display item + * mode On, off or blink segments + * @return + * ************************************************************************************************/ +void write_lcd_mem(uint8_t *lcdmem, uint8_t bits, uint8_t bitmask, uint8_t state); + +/* Display init / clear */ +/* ************************************************************************************************* + * @fn lcd_init + * @brief Erase LCD memory. Init LCD peripheral. + * @param none + * @return none + * ************************************************************************************************/ +void lcd_init(void); + +/* ************************************************************************************************* + * @fn clear_display + * @brief Erase LINE1 and LINE2 segments. Keep icons. + * @param none + * @return none + * ************************************************************************************************/ +void clear_display(void); + +/* ************************************************************************************************* + * @fn clear_display_all + * @brief Erase LINE1 and LINE2 segments. Clear also function-specific content. + * @param none + * @return none + * ************************************************************************************************/ +void clear_display_all(void); + +/* ************************************************************************************************* + * @fn clear_line + * @brief Erase segments of a given line. + * @param uint8_t line LINE1, LINE2 + * @return none + * ************************************************************************************************/ +void clear_line(uint8_t line); + +/* Blinking function */ +/* ************************************************************************************************* + * @fn start_blink + * @brief Start blinking. + * @param none + * @return none + * ************************************************************************************************/ +void start_blink(void); + +/* ************************************************************************************************* + * @fn stop_blink + * @brief Stop blinking. + * @param none + * @return none + * ************************************************************************************************/ +void stop_blink(void); + +/* ************************************************************************************************* + * @fn stop_blink + * @brief Clear blinking memory. + * @param none + * @return none + * ************************************************************************************************/ +void clear_blink_mem(void); + +/* ************************************************************************************************* + * @fn set_blink_rate + * @brief Set blink rate register bits. + * @param none + * @return none + * ************************************************************************************************/ +void set_blink_rate(uint8_t bits); + +/* Character / symbol draw functions */ +/* ************************************************************************************************* + * @fn display_char + * @brief Write to 7-segment characters. + * @param uint8_t segment A valid LCD segment + * uint8_t chr Character to display + * uint8_t mode SEG_ON, SEG_OFF, SEG_BLINK + * @return none + * ************************************************************************************************/ +void display_char(uint8_t segment, char chr, uint8_t mode); + +/* ************************************************************************************************* + * @FN display_chars + * @brief Write to consecutive 7-segment characters. + * @param uint8_t segments LCD segment array + * uint8_t * str Pointer to a string + * uint8_t mode SEG_ON, SEG_OFF, SEG_BLINK + * @return none + * ************************************************************************************************/ +void display_chars(uint8_t segments, char *str, uint8_t mode); + +/* ************************************************************************************************* + * @fn display_symbol + * @brief Switch symbol on or off on LCD. + * @param uint8_t symbol A valid LCD symbol (index 0..42) + * uint8_t state SEG_ON, SEG_OFF, SEG_BLINK + * @return none + * ************************************************************************************************/ +void display_symbol(uint8_t symbol, uint8_t mode); + +/* Set_value display functions */ +/* ************************************************************************************************* + * @fn display_value1 + * @brief Generic decimal display routine. Used exclusively by set_value function. + * @param uint8_t segments LCD segments where value is displayed + * uint32_t value Integer value to be displayed + * uint8_t digits Number of digits to convert + * uint8_t blanks Number of leadings blanks in itoa result string + * @return none + * ************************************************************************************************/ +void display_value1(uint8_t segments, uint32_t value, uint8_t digits, uint8_t blanks, uint8_t disp_mode); + +/* Integer to string conversion */ +/* ************************************************************************************************* + * @fn itoa + * @brief Generic integer to array routine. Converts integer n to string. + * Default conversion result has leading zeros, e.g. "00123" + * Option to convert leading '0' into whitespace (blanks) + * @param uint32_t n integer to convert + * uint8_t digits number of digits + * uint8_t blanks fill up result string with number of whitespaces instead of leading zeros + * @return uint8_t string + * ************************************************************************************************/ +char *itoa(uint32_t n, uint8_t digits, uint8_t blanks); + +/* Segment index helper function */ +/* ************************************************************************************************* + * @fn switch_seg + * @brief Returns index of 7-segment character. Required for display routines that can draw + * information on both lines. + * @param uint8_t line LINE1, LINE2 + * uint8_t index1 Index of LINE1 + * uint8_t index2 Index of LINE2 + * @return uint8 + * ************************************************************************************************/ +uint8_t switch_seg(uint8_t line, uint8_t index1, uint8_t index2); + +/* ************************************************************************************************* + * @fn display_all_off + * @brief Sets everything of on the display + * @param none + * @return none + * ************************************************************************************************/ +void display_all_off(void); + +#endif /* __DISPLAY_ */ diff --git a/boards/chronos/drivers/include/display_putchar.h b/boards/chronos/drivers/include/display_putchar.h new file mode 100644 index 0000000000..b903fc1db9 --- /dev/null +++ b/boards/chronos/drivers/include/display_putchar.h @@ -0,0 +1,6 @@ +#ifndef __DISPLAY_PUTCHAR_H +#define __DISPLAY_PUTCHAR_H + +void init_display_putchar(void); + +#endif /* __DISPLAY_PUTCHAR_H */ diff --git a/boards/chronos/include/board.h b/boards/chronos/include/board.h new file mode 100644 index 0000000000..c07dd4f00e --- /dev/null +++ b/boards/chronos/include/board.h @@ -0,0 +1,13 @@ +#ifndef _MSB_BOARD_H +#define _MSB_BOARD_H + +#include +#include + +#define MSP430_INITIAL_CPU_SPEED 7372800uL +#define MSP430_HAS_DCOR 1 +#define MSP430_HAS_EXTERNAL_CRYSTAL 1 + +typedef uint8_t radio_packet_length_t; + +#endif // _MSB_BOARD_H diff --git a/boards/chronos/include/buttons.h b/boards/chronos/include/buttons.h new file mode 100644 index 0000000000..4e7ab28dca --- /dev/null +++ b/boards/chronos/include/buttons.h @@ -0,0 +1,11 @@ +#ifndef BUTTONS_H +#define BUTTONS_H + +// Button ports +#define BUTTON_STAR_PIN (BIT2) +#define BUTTON_NUM_PIN (BIT1) +#define BUTTON_UP_PIN (BIT4) +#define BUTTON_DOWN_PIN (BIT0) +#define BUTTON_BACKLIGHT_PIN (BIT3) + +#endif diff --git a/boards/chronos/putchar.c b/boards/chronos/putchar.c new file mode 100644 index 0000000000..cefcb3281b --- /dev/null +++ b/boards/chronos/putchar.c @@ -0,0 +1,12 @@ +static void _dummy(int c) +{ +} + +void (*_putchar)(int c) = _dummy; + +int putchar(int c) +{ + _putchar(c); + return c; +} + diff --git a/boards/msb-430-common/Makefile b/boards/msb-430-common/Makefile new file mode 100644 index 0000000000..4ca6a9248b --- /dev/null +++ b/boards/msb-430-common/Makefile @@ -0,0 +1,33 @@ +SRC = $(wildcard *.c) +BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBOARD)/msb-430-common/include/ -I${RIOTBOARD}/${BOARD}/include/ +INCLUDES += -I$(RIOTBASE)/cpu/msp430-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/mspx16x/include/ +INCLUDES += -I$(RIOTBASE)/drivers/include/ + +.PHONY: $(BINDIR)$(ARCH) + +all: $(BINDIR)$(ARCH) + $(MAKE) -C drivers + +$(BINDIR)$(ARCH): $(OBJ) + echo $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + $(MAKE) -C drivers clean + rm -f $(OBJ) $(DEP) + rm -f $(BINDIR)$(ARCH) diff --git a/boards/msb-430-common/Makefile.include b/boards/msb-430-common/Makefile.include new file mode 100644 index 0000000000..b7dd9ef3d9 --- /dev/null +++ b/boards/msb-430-common/Makefile.include @@ -0,0 +1,27 @@ +## the cpu to build for +export CPU = msp430x16x +export MCU = msp430f1612 + +# toolchain config +export PREFIX = @msp430- +export CC = @$(PREFIX)gcc +export AR = @$(PREFIX)ar +export CFLAGS += -std=gnu99 -Wstrict-prototypes -gdwarf-2 -Os -Wall -mmcu=$(MCU) +export ASFLAGS += -mmcu=$(MCU) --defsym $(MCU)=1 --gdwarf-2 +export AS = $(PREFIX)as +export LINK = $(PREFIX)gcc +export SIZE = $(PREFIX)size +export OBJCOPY = $(PREFIX)objcopy +export LINKFLAGS = -mmcu=$(MCU) -lgcc $(RIOTBASE)/bin/startup.o +TERMPROG = $(RIOTBASE)/dist/tools/pyterm/pyterm.py +export FLASHER = mspdebug +ifeq ($(strip $(PORT)),) + export PORT = /dev/ttyUSB0 +endif +export HEXFILE = bin/$(PROJECT).hex +#export FFLAGS = -d $(PORT) -j uif "prog $(HEXFILE)" +export FFLAGS = -j olimex "prog $(HEXFILE)" + +export USEMODULE += msp430_common +export INCLUDES += -I $(RIOTCPU)/msp430-common/include/ +export OFLAGS = -O ihex diff --git a/boards/msb-430-common/board_config.c b/boards/msb-430-common/board_config.c new file mode 100644 index 0000000000..14b8d00e31 --- /dev/null +++ b/boards/msb-430-common/board_config.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include + +void config_load(void) +{ + if (*((uint16_t *) INFOMEM) == CONFIG_KEY) { + memcpy(&sysconfig, (char *)(INFOMEM + sizeof(CONFIG_KEY)), sizeof(sysconfig)); + } + else { + config_save(); + } +} + +uint8_t config_save(void) +{ + configmem_t mem = { CONFIG_KEY, sysconfig }; + return (flashrom_erase((uint8_t *) INFOMEM) && flashrom_write((uint8_t *) INFOMEM, (char *) &mem, sizeof(mem))); +} diff --git a/boards/msb-430-common/board_init.c b/boards/msb-430-common/board_init.c new file mode 100644 index 0000000000..e7d4284baa --- /dev/null +++ b/boards/msb-430-common/board_init.c @@ -0,0 +1,228 @@ +#include "cpu.h" +#include "board.h" +#include "kernel_internal.h" +#include "msp430.h" +#include "debug.h" + +static volatile uint32_t __msp430_cpu_speed = MSP430_INITIAL_CPU_SPEED; + +void msp430_init_dco(void); + +/*---------------------------------------------------------------------------*/ +static uint8_t calc_umctl(uint16_t br) +{ + /* from TI slaa049 */ + register uint8_t CMOD = 256 * br - 256 * (br + 1) / 2; + register uint8_t c = 0; + register int i = 0; + register uint8_t a = CMOD; + a <<= 1; + + do { + if (a & 0x80) { /* Overflow to integer? */ + a = a - 128 + CMOD; /* Yes, subtract 1.000000 */ + c |= 0x80; + } + else { + a += CMOD; /* No, add fraction */ + } + + if (i == 7) { + return c; + } + + i++; + c >>= 1; + } + while (1); +} + +static void msb_ports_init(void) +{ + /* Port 1: Free port, for energy saving all outputs are set to zero. */ + P1SEL = 0x00; /* Port1 I/O Function */ + P1OUT = 0x00; /* Port1 Ausgangsregister: 00000000 = 0x00 */ + P1DIR = 0xFF; /* Port1 Direction: 11111111 = 0xFF */ + + P2SEL = 0x20; /* Port2 I/O Function */ + P2OUT = 0x00; /* Port2 Output register: 00000000 = 0x00 */ + P2DIR = 0x1C; /* Port2 Direction: 00011010 = 0x1C */ + /* 0 - P2.0 [IN ] - */ + /* 0 - P2.1 [OUT] - */ + /* 1 - P2.2 [IN ] - */ + /* 1 - P2.3 [OUT] - */ + /* 1 - P2.4 [OUT] - */ + /* 0 - P2.5 [IN ] - */ + /* 0 - P2.6 [IN ] - SDC Protect */ + /* 0 - P2.7 [IN ] - SDC Detect */ + + P3SEL = 0xC0; /* Port3 Pins 6 & 7 for USART */ + P3OUT = 0x49; /* Port3 Output register: 01001001: 0x49 */ + P3DIR = 0xAB; /* Port3 Direction: 10101011: 0xAB */ + /* 1 - P3.0 */ + /* 1 - P3.1 */ + /* 0 - P3.2 */ + /* 1 - P3.3 */ + /* 0 - P3.4 [IN ] - SHT 11 DATA (OUT/IN) */ + /* 1 - P3.5 [OUT] - SHT 11 CLK */ + /* 0 - P3.6 [2-Funktion] - RS232_RxD */ + /* 1 - P3.7 [2-Funktion] - RS232_TxD */ + + /* Port 4: Free port, for energy saving all outputs are set to zero. */ + P4SEL = 0x00; /* Port4 I/O Function */ + P4OUT = 0x00; /* Port4 Output register: 00000000 = 0x00 */ + P4DIR = 0xFF; /* Port4 Direction: 11111111 = 0xFF */ + /* 1 - P4.0 [OUT] - unused */ + /* 1 - P4.1 [OUT] - unused */ + /* 1 - P4.2 [OUT] - unused */ + /* 1 - P4.3 [OUT] - unused */ + /* 1 - P4.4 [OUT] - unused */ + /* 1 - P4.5 [OUT] - unused */ + /* 1 - P4.6 [OUT] - unused */ + /* 1 - P4.7 [OUT] - unused */ + + P5SEL = 0x00; /* Port5 I/O Function: 00000000 = 0x00 */ + P5OUT = 0x80; /* Port5 Output register: 00001001 = 0x09 */ + P5DIR = 0xFF; /* Port5 Direction: 11111011 = 0xFB */ + /* 1 - P5.0 [OUT] - SDC /CS */ + /* 1 - P5.1 [OUT] - SDC DI */ + /* 0 - P5.2 [IN ] - SDC DO */ + /* 1 - P5.3 [OUT] - SDC DCLK */ + /* 1 - P5.4 [OUT] - MMA GS1 */ + /* 1 - P5.5 [OUT] - MMA GS2 */ + /* 1 - P5.6 [OUT] - MMA /SLEEP */ + /* 1 - P5.7 [OUT] - LED_RED 0-on, 1-off */ + + P6SEL = 0x00; /* Port6 I/O Function = 0x07 */ + P6OUT = 0x00; /* Port6 Output register: 00000000 = 0x00 */ + P6DIR = 0xFF; /* Port6 Direction: 11111000 = 0xF8 */ + /* 0 - P6.0 [AD-IN] - MMA X-Axis */ + /* 0 - P6.1 [AD-IN] - MMA Y-Axis */ + /* 0 - P6.2 [AD-IN] - MMA Z-Axis */ + /* 1 - P6.3 [OUT] - unused */ + /* 1 - P6.4 [OUT] - unused */ + /* 1 - P6.5 [OUT] - unused */ + /* 1 - P6.6 [OUT] - unused */ + /* 1 - P6.7 [OUT] - unused */ +} + +void msp430_set_cpu_speed(uint32_t speed) +{ + dint(); + __msp430_cpu_speed = speed; + msp430_init_dco(); + uint16_t br; + UCTL1 = SWRST | CHAR; /* 8-bit character */ + UTCTL1 |= SSEL1 | URXSE; /* UCLK = MCLK */ + /* activate */ + U1ME |= UTXE1 | URXE1; /* Enable USART1 TXD/RXD */ + br = (uint16_t)(__msp430_cpu_speed / 115200uL); + UBR01 = br; /* set baudrate */ + UBR11 = br >> 8; + UMCTL1 = calc_umctl(br); /* set modulation */ + + ME2 |= (UTXE1 | URXE1); + UCTL1 &= ~SWRST; + + IE2 |= URXIE1; + //clock_init(); + eint(); +} + +/*---------------------------------------------------------------------------*/ +void msp430_init_dco(void) +{ +#if MSP430_HAS_EXTERNAL_CRYSTAL + /*------------------ use external oszillator -----------------------*/ + uint16_t i; + + /* Stop watchdog */ + WDTCTL = WDTPW + WDTHOLD; + + //Init crystal for mclk + //XT2 = HF XTAL + BCSCTL1 = RSEL2; + + /* Wait for xtal to stabilize */ + do { + IFG1 &= ~OFIFG; /* Clear oscillator fault flag */ + + for (i = 0xFF; i > 0; i--); /* Time for flag to set */ + } + while ((IFG1 & OFIFG) != 0); /* Oscillator fault flag still set? */ + + BCSCTL2 = SELM_2 + SELS; /* MCLK und SMCLK = XT2 (safe) */ +#else + /* Thdeltais code taken from the FU Berlin sources and reformatted. */ + int delta = __msp430_cpu_speed >> 12; + //#define DELTA 600 + + unsigned int compare, oldcapture = 0; + unsigned int i; + + + BCSCTL1 = 0xa4; /* ACLK is devided by 4. RSEL=6 no division for MCLK + and SSMCLK. XT2 is off. */ + + /* Init FLL to desired frequency using the 32762Hz crystal */ +#if MSP430_HAS_DCOR + BCSCTL2 = 0x01; +#else + BCSCTL2 = 0x00; +#endif + + WDTCTL = WDTPW + WDTHOLD; /* Stop WDT */ + BCSCTL1 |= DIVA1 + DIVA0; /* ACLK = LFXT1CLK/8 */ + + for (i = 0xffff; i > 0; i--); /* Delay for XTAL to settle */ + + CCTL2 = CCIS0 + CM0 + CAP; /* Define CCR2, CAP, ACLK */ + TACTL = TASSEL1 + TACLR + MC1; /* SMCLK, continous mode */ + + + while (1) { + + while ((CCTL2 & CCIFG) != CCIFG); /* Wait until capture occured! */ + + CCTL2 &= ~CCIFG; /* Capture occured, clear flag */ + compare = CCR2; /* Get current captured SMCLK */ + compare = compare - oldcapture; /* SMCLK difference */ + oldcapture = CCR2; /* Save current captured SMCLK */ + + if (delta == compare) { + break; /* if equal, leave "while(1)" */ + } + else if (delta < compare) { /* DCO is too fast, slow it down */ + DCOCTL--; + + if (DCOCTL == 0xFF) { /* Did DCO role under? */ + BCSCTL1--; + } + } + else { /* -> Select next lower RSEL */ + DCOCTL++; + + if (DCOCTL == 0x00) { /* Did DCO role over? */ + BCSCTL1++; + } + + /* -> Select next higher RSEL */ + } + } + + CCTL2 = 0; /* Stop CCR2 function */ + TACTL = 0; /* Stop Timer_A */ + + BCSCTL1 &= ~(DIVA1 + DIVA0); /* remove /8 divisor from ACLK again */ +#endif +} + +void board_init() +{ + msp430_cpu_init(); + msb_ports_init(); + + LED_RED_ON; + + msp430_set_cpu_speed(7372800uL); +} diff --git a/boards/msb-430-common/drivers/Makefile b/boards/msb-430-common/drivers/Makefile new file mode 100644 index 0000000000..d4b65dc031 --- /dev/null +++ b/boards/msb-430-common/drivers/Makefile @@ -0,0 +1,24 @@ +SRC = $(wildcard *.c) +BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o) +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBASE)/sys/include/ -I$(RIOTBASE)/drivers/cc110x_ng/include/ + +$(BINDIR)msb-430_common_drivers.a: $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)" | cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products + +clean: + rm -f $(OBJ) $(DEP) + diff --git a/boards/msb-430-common/drivers/include/sht11-board.h b/boards/msb-430-common/drivers/include/sht11-board.h new file mode 100644 index 0000000000..13aeb89968 --- /dev/null +++ b/boards/msb-430-common/drivers/include/sht11-board.h @@ -0,0 +1,59 @@ +/****************************************************************************** +Copyright 2013, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef SHT11BOARD_H_ +#define SHT11BOARD_H_ + +/** + * @ingroup msb_430h + * @{ + */ + +/** + * @file + * @brief SHT11 Device Driver Configuration For MSB-430 Platform + * + * @author Freie Universität Berlin, Computer Systems & Telematics, RIOT + * + */ +#include +#include + +/* SCK = P3B5 + * DATA = P3B4 + */ + +#define SHT11_SCK_LOW P3OUT &= ~(BIT5); /**< serial clock line low */ +#define SHT11_SCK_HIGH P3OUT |= BIT5; /**< serial clock line high */ +#define SHT11_DATA (P3IN & BIT5) /**< read serial I/O */ +#define SHT11_DATA_LOW P3OUT &= ~(BIT5); /**< serial I/O line low */ +#define SHT11_DATA_HIGH P3OUT |= BIT5; /**< serial I/O line high */ +#define SHT11_DATA_IN P3DIR &= ~(BIT5); /**< serial I/O as input */ +#define SHT11_DATA_OUT P3DIR |= BIT5; /**< serial I/O as output */ +#define SHT11_INIT P3DIR |= BIT5; /* FIO1DIR |= BIT25; PINSEL3 &= ~(BIT14|BIT15 | BIT16|BIT17); */ + +/** @} */ +#endif /* SHT11BOARD_H_ */ diff --git a/boards/msb-430-common/include/board-conf.h b/boards/msb-430-common/include/board-conf.h new file mode 100644 index 0000000000..5a9d5b1dd0 --- /dev/null +++ b/boards/msb-430-common/include/board-conf.h @@ -0,0 +1,8 @@ +#ifndef BOARD_CONF_H +#define BOARD_CONF_H + +#include + +#define INFOMEM (0x1000) + +#endif /* BOARD-CONF_H */ diff --git a/boards/msb-430-common/uart1.c b/boards/msb-430-common/uart1.c new file mode 100644 index 0000000000..025d09dc6e --- /dev/null +++ b/boards/msb-430-common/uart1.c @@ -0,0 +1,57 @@ +#include "board.h" + +#define UART1_TX TXBUF1 +#define UART1_WAIT_TXDONE() while( (UTCTL1 & TXEPT) == 0 ) { _NOP(); } + +#include +#include + +#include + +int putchar(int c) +{ + UART1_TX = c; + UART1_WAIT_TXDONE(); + + if (c == 10) { + UART1_WAIT_TXDONE(); + } + + return c; +} + +void usart0irq(void); +/** + * \brief the interrupt function + */ +interrupt(USART1RX_VECTOR) usart0irq(void) +{ + U1TCTL &= ~URXSE; /* Clear the URXS signal */ + U1TCTL |= URXSE; /* Re-enable URXS - needed here?*/ + int c = 0; + /* Check status register for receive errors. */ + if(U1RCTL & RXERR) { + if (U1RCTL & FE) { + puts("rx framing error"); + } + if (U1RCTL & OE) { + puts("rx overrun error"); + } + if (U1RCTL & PE) { + puts("rx parity error"); + } + if (U1RCTL & BRK) { + puts("rx break error"); + } + /* Clear error flags by forcing a dummy read. */ + c = U1RXBUF; + } +#ifdef MODULE_UART0 + else if (uart0_handler_pid) { + c = U1RXBUF; + uart0_handle_incoming(c); + uart0_notify_thread(); + } +#endif +} + diff --git a/boards/msb-430/Makefile b/boards/msb-430/Makefile new file mode 100644 index 0000000000..66dcd277d1 --- /dev/null +++ b/boards/msb-430/Makefile @@ -0,0 +1,37 @@ +SRC = $(wildcard *.c) +BINDIR = bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +export ARCH = msb-430_base.a + +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBOARD)/msb-430-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/msp430-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/msp430x16x/include/ + +all: $(BINDIR)$(ARCH) + $(MAKE) -C ../msb-430-common + +$(BINDIR)$(ARCH): $(OBJ) + mkdir -p $(BINDIR) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + $(MAKE) -C ../msb-430-common clean + rm -f $(BINDIR)$(ARCH) $(OBJ) $(DEP) + @if [ -d $(BINDIR) ] ; \ + then rmdir $(BINDIR) ; \ + fi + + + diff --git a/boards/msb-430/Makefile.include b/boards/msb-430/Makefile.include new file mode 100644 index 0000000000..e2a5fb3e39 --- /dev/null +++ b/boards/msb-430/Makefile.include @@ -0,0 +1,2 @@ +export INCLUDES += -I$(RIOTBOARD)/msb-430h/include -I$(RIOTBOARD)/msb-430-common/include +include $(RIOTBOARD)/msb-430-common/Makefile.include diff --git a/boards/msb-430/include/board.h b/boards/msb-430/include/board.h new file mode 100644 index 0000000000..e7968f4499 --- /dev/null +++ b/boards/msb-430/include/board.h @@ -0,0 +1,74 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef _MSB_BOARD_H +#define _MSB_BOARD_H + +/** + * @defgroup msb_430h ScatterWeb MSB-430H + * @ingroup msp430 + * +

Compontents

+\li MSP430 +\li CC1100 + +* @{ +*/ + +/** + * @file + * @brief MSB-430H Board + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * @note $Id$ + */ + +#include "board-conf.h" + +//MSB430 core +#define MSP430_INITIAL_CPU_SPEED 2457600uL +#define MSP430_HAS_DCOR 1 +#define MSP430_HAS_EXTERNAL_CRYSTAL 0 + +/* LEDs ports MSB430 */ +#define LEDS_PxDIR P5DIR +#define LEDS_PxOUT P5OUT +#define LEDS_CONF_RED 0x80 +#define LEDS_CONF_GREEN 0x00 +#define LEDS_CONF_YELLOW 0x00 + +#define LED_RED_ON LEDS_PxOUT &=~LEDS_CONF_RED +#define LED_RED_OFF LEDS_PxOUT |= LEDS_CONF_RED +#define LED_RED_TOGGLE LEDS_PxOUT ^= LEDS_CONF_RED + +#include + +typedef uint8_t radio_packet_length_t; + +/** @} */ +#endif // _MSB_BOARD_H diff --git a/boards/msb-430h/Makefile b/boards/msb-430h/Makefile new file mode 100644 index 0000000000..2bd0f63c26 --- /dev/null +++ b/boards/msb-430h/Makefile @@ -0,0 +1,37 @@ +SRC = $(wildcard *.c) +BINDIR = bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +export ARCH = msb-430h_base.a + +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I${RIOTBASE}/core/include/ +INCLUDES += -Iinclude/ -I$(RIOTBOARD)/msb-430-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/msp430-common/include/ -I$(RIOTBASE)/cpu/msp430x16x/include/ +INCLUDES += -I$(RIOTBASE)/drivers/cc110x_ng/include/ -I$(RIOTBASE)/sys/include + +all: $(BINDIR)$(ARCH) + $(MAKE) -C ../msb-430-common + +$(BINDIR)$(ARCH): $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + mkdir -p $(BINDIR) + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + $(MAKE) -C ../msb-430-common clean + rm -f $(BINDIR)$(ARCH) $(OBJ) $(DEP) + @if [ -d $(BINDIR) ] ; \ + then rmdir $(BINDIR) ; \ + fi + + diff --git a/boards/msb-430h/Makefile.dep b/boards/msb-430h/Makefile.dep new file mode 100644 index 0000000000..de1d7e692c --- /dev/null +++ b/boards/msb-430h/Makefile.dep @@ -0,0 +1,6 @@ +ifneq (,$(findstring cc110x_ng,$(USEMODULE))) + ifeq (,$(findstring cc110x_spi,$(USEMODULE))) + USEMODULE += cc110x_spi + endif +endif + diff --git a/boards/msb-430h/Makefile.include b/boards/msb-430h/Makefile.include new file mode 100644 index 0000000000..166060e36f --- /dev/null +++ b/boards/msb-430h/Makefile.include @@ -0,0 +1,4 @@ +export INCLUDES += -I$(RIOTBOARD)/msb-430h/include -I$(RIOTBOARD)/msb-430-common/include +include $(RIOTBOARD)/$(BOARD)/Makefile.dep + +include $(RIOTBOARD)/msb-430-common/Makefile.include diff --git a/boards/msb-430h/driver_cc110x.c b/boards/msb-430h/driver_cc110x.c new file mode 100644 index 0000000000..857bfcf1d4 --- /dev/null +++ b/boards/msb-430h/driver_cc110x.c @@ -0,0 +1,359 @@ +/* Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + +This file is part of the Micro-mesh SensorWeb Firmware. + +Micro-Mesh 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, or (at your option) +any later version. + +Micro-Mesh 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 Micro-Mesh; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include + +#include +#include +#include + +#include +#include + +#define CC1100_GDO0 (P2IN & 0x02) // read serial I/O (GDO0) +#define CC1100_GDO1 (P3IN & 0x04) // read serial I/O (GDO1) +#define CC1100_GDO2 (P2IN & 0x01) // read serial I/O (GDO2) + +#define CC1100_CS_LOW (P3OUT &= ~0x01) +#define CC1100_CS_HIGH (P3OUT |= 0x01) + +#define CC1100_GDO1_LOW_COUNT (2700) // loop count (timeout ~ 500 us) to wait +#define CC1100_GDO1_LOW_RETRY (100) // max. retries for GDO1 to go low + +volatile int abort_count; +volatile int retry_count = 0; + +void cc110x_gdo0_enable(void) +{ + P2IFG &= ~0x02; /* Clear IFG for GDO0 */ + P2IE |= 0x02; /* Enable interrupt for GDO0 */ +} + +void cc110x_gdo0_disable(void) +{ + P2IE &= ~0x02; /* Disable interrupt for GDO0 */ + P2IFG &= ~0x02; /* Clear IFG for GDO0 */ +} + +void cc110x_gdo2_enable(void) +{ + P2IFG &= ~0x01; /* Clear IFG for GDO2 */ + P2IE |= 0x01; /* Enable interrupt for GDO2 */ +} + +void cc110x_gdo2_disable(void) +{ + P2IE &= ~0x01; /* Disable interrupt for GDO2 */ + P2IFG &= ~0x01; /* Clear IFG for GDO2 */ +} + +void cc110x_before_send(void) +{ + // Disable GDO2 interrupt before sending packet + cc110x_gdo2_disable(); +} + +void cc110x_after_send(void) +{ + // Enable GDO2 interrupt after sending packet + cc110x_gdo2_enable(); +} + + +int cc110x_get_gdo0(void) +{ + return CC1100_GDO0; +} + +int cc110x_get_gdo1(void) +{ + return CC1100_GDO1; +} + +int cc110x_get_gdo2(void) +{ + return CC1100_GDO2; +} + +void cc110x_spi_cs(void) +{ + CC1100_CS_LOW; +} + +uint8_t cc110x_txrx(uint8_t data) +{ + /* Ensure TX Buf is empty */ + long c = 0; + IFG1 &= ~UTXIFG0; + IFG1 &= ~URXIFG0; + TXBUF0 = data; + + while (!(IFG1 & UTXIFG0)) { + if (c++ == 1000000) { + puts("cc110x_txrx alarm()"); + } + } + + /* Wait for Byte received */ + c = 0; + + while (!(IFG1 & URXIFG0)) { + if (c++ == 1000000) { + puts("cc110x_txrx alarm()"); + } + } + + return RXBUF0; +} + + +void cc110x_spi_select(void) +{ + // Switch to GDO mode + P3SEL &= ~0x04; + P3DIR &= ~0x04; +cs_low: + // CS to low + abort_count = 0; + CC1100_CS_LOW; + // Wait for SO to go low (voltage regulator + // has stabilized and the crystal is running) +loop: + + // asm volatile ("nop"); + if (CC1100_GDO1) { + abort_count++; + + if (abort_count > CC1100_GDO1_LOW_COUNT) { + retry_count++; + + if (retry_count > CC1100_GDO1_LOW_RETRY) { + puts("[CC1100 SPI] fatal error\n"); + goto final; + } + + CC1100_CS_HIGH; + goto cs_low; // try again + } + + goto loop; + } + +final: + /* Switch to SPI mode */ + P3SEL |= 0x04; +} + +void cc110x_spi_unselect(void) +{ + CC1100_CS_HIGH; +} + +void cc110x_init_interrupts(void) +{ + unsigned int state = disableIRQ(); /* Disable all interrupts */ + P2SEL = 0x00; /* must be <> 1 to use interrupts */ + P2IES |= 0x01; /* Enables external interrupt on low edge (for GDO2) */ + P2IE |= 0x01; /* Enable interrupt */ + P2IFG &= ~0x01; /* Clears the interrupt flag */ + P2IE &= ~0x02; /* Disable interrupt for GDO0 */ + P2IFG &= ~0x02; /* Clear IFG for GDO0 */ + restoreIRQ(state); /* Enable all interrupts */ +} + +void cc110x_spi_init(uint8_t clockrate) +{ + // Switch off async UART + while (!(UTCTL0 & TXEPT)); // Wait for empty UxTXBUF register + + IE1 &= ~(URXIE0 + UTXIE0); // Disable USART0 receive&transmit interrupt + ME1 &= ~(UTXE0 + URXE0); + P3SEL |= 0x0E; // Set pin as SPI + + // Keep peripheral in reset state + UCTL0 = SWRST; + + // 8-bit SPI Master 3-pin mode, with SMCLK as clock source + // CKPL works also, but not CKPH+CKPL or none of them!! + UCTL0 |= CHAR + SYNC + MM; + UTCTL0 = CKPH + SSEL1 + SSEL0 + STC; + + // Ignore clockrate argument for now, just use clock source/2 + // SMCLK = 7,3728 MHz + UBR00 = 0x02; // Ensure baud rate >= 2 + UBR10 = 0x00; + UMCTL0 = 0x00; // No modulation + URCTL0 = 0x00; // Reset Receive Control Register + + // Enable SPI mode + ME1 |= USPIE0; + + // Release for operation + UCTL0 &= ~SWRST; +} + + +// #include +// #include +// #include "type.h" +// #include "cc110x_defines.h" +// #include "driver_cc110x.h" +// #include "driver_system.h" +// #include "spi0.h" +// +// static callback_t _paket_cb; +// static callback_t _cs_cb; +// +// //------------------------------------------------------------------------------------------------------- +// // Public CC1100 communication functions (SPI) +// //------------------------------------------------------------------------------------------------------- +// +// //------------------------------------------------------------------------------------------------------- +// // void spiInitTrx(void) +// // +// // DESCRIPTION: +// // This function puts the cc110x into spi mode. You have to call this bevore every spi transaction. +// // +// //------------------------------------------------------------------------------------------------------- +// +// +// void drivercc110x_spiwriteburstreg(uint8_t addr, unsigned char *buffer, uint8_t count) +// { +// uint8_t i; +// long c; +// drivercc110x_spiinittrx(); +// drivercc110x_trxspi(addr | CC1100_WRITE_BURST); +// for (i = 0; i < count; i++) +// { +// c = 0; +// IFG1 &= ~UTXIFG0; +// IFG1 &= ~URXIFG0; +// TXBUF0 = buffer[i]; +// /* Wait for TX to finish */ +// while(!(IFG1 & UTXIFG0)) +// { +// if (c++ == 1000000) +// alarm(); +// } +// } +// /* Wait for Byte received */ +// c = 0; +// while(!(IFG1 & URXIFG0)) +// { +// if (c++ == 1000000) +// alarm(); +// } +// CC1100_CS_HIGH; +// } +// +// void drivercc110x_spireadburstreg(uint8_t addr, char *buffer, uint8_t count) +// { +// uint8_t i; +// drivercc110x_spiinittrx(); +// drivercc110x_trxspi(addr | CC1100_READ_BURST); +// for (i = 0; i < count; i++) +// { +// long c = 0; +// IFG1 &= ~UTXIFG0; +// IFG1 &= ~URXIFG0; +// TXBUF0 = NOBYTE; +// while(!(IFG1 & UTXIFG0)) +// { +// if (c++ == 1000000) +// alarm(); +// } +// /* Wait for Byte received */ +// c = 0; +// while(!(IFG1 & URXIFG0)) +// { +// if (c++ == 1000000) +// alarm(); +// } +// buffer[i] = RXBUF0; +// } +// CC1100_CS_HIGH; +// } +// +// void drivercc110x_load(callback_t cs_cb,callback_t paket_cb) +// { +// _paket_cb = paket_cb; +// _cs_cb = cs_cb; +// spi0_init(0); +// } +// +// void drivercc110x_aftersend(void) +// { +// CLEAR(P2IFG, 0x01); +// SET(P2IE, 0x01); /* Enable interrupts on port 2 pin 0 */ +// CLEAR(P4OUT, 0x08); /* Turn off Sending Led*/ +// } +// +// void drivercc110x_initinterrupts(void) +// { +// _DINT(); /* Disable all interrupts */ +// P2SEL = 0x00; /* must be <> 1 to use interrupts */ +// SET(P2IES, 0x01); /* Enables external interrupt on low edge (for GDO2) */ +// SET(P2IE, 0x01); /* Enable interrupt */ +// CLEAR(P2IFG, 0x01); /* Clears the interrupt flag */ +// CLEAR(P2IE, 0x02); /* Disable interrupt for GDO0 */ +// CLEAR(P2IFG, 0x02); /* Clear IFG for GDO0 */ +// _EINT(); /* Enable all interrupts */ +// } +// +// void drivercc110x_beforesend(void) +// { +// /* Turn on Led while sending paket for debug reasons */ +// SET(P4OUT, 0x08); +// /* Disable interrupts on port 2 pin 0 */ +// CLEAR(P2IE, 0x01); +// } +// +// +// /* +// * Private functions +// */ +// +// + +/* + * CC1100 receive interrupt + */ +interrupt(PORT2_VECTOR) __attribute__((naked)) cc110x_isr(void) +{ + __enter_isr(); + // if (system_state.POWERDOWN) SPI_INIT; /* Initialize SPI after wakeup */ + /* Check IFG */ + if ((P2IFG & 0x01) != 0) { + P2IFG &= ~0x01; + cc110x_gdo2_irq(); + } + else if ((P2IFG & 0x02) != 0) { + cc110x_gdo0_irq(); + P2IE &= ~0x02; // Disable interrupt for GDO0 + P2IFG &= ~0x02; // Clear IFG for GDO0 + } + else { + puts("cc110x_isr(): unexpected IFG!"); + /* Should not occur - only Port 2 Pin 0 interrupts are enabled */ + // CLEAR(P2IFG, 0xFF); /* Clear all flags */ + } + + // if (system_state.POWERDOWN != 0) END_LPM3; + __exit_isr(); +} diff --git a/boards/msb-430h/include/board.h b/boards/msb-430h/include/board.h new file mode 100644 index 0000000000..fc086d53cb --- /dev/null +++ b/boards/msb-430h/include/board.h @@ -0,0 +1,73 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef _MSB_BOARD_H +#define _MSB_BOARD_H + +/** + * @defgroup msb_430h ScatterWeb MSB-430H + * @ingroup msp430 + * +

Compontents

+\li MSP430 +\li CC1100 + +* @{ +*/ + +/** + * @file + * @brief MSB-430H Board + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * @note $Id$ + */ + +//MSB430 core +#define MSP430_INITIAL_CPU_SPEED 7372800uL +#define MSP430_HAS_DCOR 1 +#define MSP430_HAS_EXTERNAL_CRYSTAL 1 + +/* LEDs ports MSB430 */ +#define LEDS_PxDIR P5DIR +#define LEDS_PxOUT P5OUT +#define LEDS_CONF_RED 0x80 +#define LEDS_CONF_GREEN 0x00 +#define LEDS_CONF_YELLOW 0x00 + +#define LED_RED_ON LEDS_PxOUT &=~LEDS_CONF_RED +#define LED_RED_OFF LEDS_PxOUT |= LEDS_CONF_RED +#define LED_RED_TOGGLE LEDS_PxOUT ^= LEDS_CONF_RED + +#include +#include "board-conf.h" + +typedef uint8_t radio_packet_length_t; + +/** @} */ +#endif // _MSB_BOARD_H diff --git a/boards/msba2-common/Makefile b/boards/msba2-common/Makefile new file mode 100644 index 0000000000..29f64c8ecb --- /dev/null +++ b/boards/msba2-common/Makefile @@ -0,0 +1,33 @@ +SRC = $(wildcard *.c) +BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBOARD)/msba2-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/arm_common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/lpc2387/include/ +INCLUDES += -I$(RIOTBASE)/drivers/include/ +INCLUDES += -I$(RIOTBOARD)/$(BOARD)/include + +.PHONY: $(BINDIR)msba2_common_base.a + +all: $(BINDIR)msba2_common_base.a + "$(MAKE)" -C drivers + +$(BINDIR)msba2_common_base.a: $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + "$(MAKE)" -C drivers clean + rm -f $(OBJ) $(DEP) + diff --git a/boards/msba2-common/Makefile.dep b/boards/msba2-common/Makefile.dep new file mode 100644 index 0000000000..bffa6c72d7 --- /dev/null +++ b/boards/msba2-common/Makefile.dep @@ -0,0 +1,14 @@ +ifneq (,$(findstring cc110x,$(USEMODULE))) + ifeq (,$(findstring gpioint,$(USEMODULE))) + USEMODULE += gpioint + endif +endif + +ifneq (,$(findstring cc110x_ng,$(USEMODULE))) + ifeq (,$(findstring cc110x_spi,$(USEMODULE))) + USEMODULE += cc110x_spi + endif + ifeq (,$(findstring gpioint,$(USEMODULE))) + USEMODULE += gpioint + endif +endif diff --git a/boards/msba2-common/Makefile.include b/boards/msba2-common/Makefile.include new file mode 100644 index 0000000000..5d3ba0fb0d --- /dev/null +++ b/boards/msba2-common/Makefile.include @@ -0,0 +1,27 @@ +## the cpu to build for +export CPU = lpc2387 + +# toolchain config +export PREFIX = @arm-none-eabi- +#export PREFIX = @arm-elf- +export CC = @$(PREFIX)gcc +export AR = @$(PREFIX)ar +export CFLAGS += -std=gnu99 -O2 -Wall -Wstrict-prototypes -mcpu=arm7tdmi-s -gdwarf-2 +export ASFLAGS = -gdwarf-2 -mcpu=arm7tdmi-s +export AS = $(PREFIX)as +export LINK = $(PREFIX)gcc +export SIZE = $(PREFIX)size +export OBJCOPY = $(PREFIX)objcopy +FLASHER = lpc2k_pgm +TERMPROG = $(RIOTBASE)/dist/tools/pyterm/pyterm.py +LINKFLAGS = -gdwarf-2 -mcpu=arm7tdmi-s -static -lgcc -nostartfiles -T$(RIOTBASE)/cpu/$(CPU)/linkerscript.x + +ifeq ($(strip $(PORT)),) + export PORT = /dev/ttyUSB0 +endif +export HEXFILE = bin/$(PROJECT).hex +export FFLAGS = $(PORT) $(PROJBINDIR)/$(PROJECT).hex +include $(RIOTBOARD)/msba2-common/Makefile.dep + +export INCLUDES += -I$(RIOTCPU)/lpc2387/include +export OFLAGS = -O ihex diff --git a/boards/msba2-common/board_common_init.c b/boards/msba2-common/board_common_init.c new file mode 100644 index 0000000000..4096caa944 --- /dev/null +++ b/boards/msba2-common/board_common_init.c @@ -0,0 +1,96 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup msba2 + * @{ + */ + +/** + * @file + * @brief MSB-A2 board initialization + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Kaspar Schleiser + * @author Michael Baar + * @author Zakaria Kasmi + * @note $Id$ + */ +#include +#include +#include +#include +#include +#include +#include + +#define PCRTC BIT9 +#define CL_CPU_DIV 4 + +/*---------------------------------------------------------------------------*/ +/** + * @brief Enabling MAM and setting number of clocks used for Flash memory fetch + * @internal + */ +static void +init_mam(void) +{ + MAMCR = 0x0000; + MAMTIM = 0x0003; + MAMCR = 0x0002; +} +/*---------------------------------------------------------------------------*/ +static inline void +pllfeed(void) +{ + PLLFEED = 0xAA; + PLLFEED = 0x55; +} + + +void init_clks2(void) +{ + // Wait for the PLL to lock to set frequency + while (!(PLLSTAT & BIT26)); + + // Connect the PLL as the clock source + PLLCON = 0x0003; + pllfeed(); + + /* Check connect bit status */ + while (!(PLLSTAT & BIT25)); +} + +void bl_init_clks(void) +{ + PCONP = PCRTC; // switch off everything except RTC + init_clks1(); + init_clks2(); + init_mam(); +} + +/*---------------------------------------------------------------------------*/ diff --git a/boards/msba2-common/board_config.c b/boards/msba2-common/board_config.c new file mode 100644 index 0000000000..496a077961 --- /dev/null +++ b/boards/msba2-common/board_config.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +void config_load(void) { + extern char configmem[]; + /* cast it here for strict-aliasing */ + uint16_t* tmp = (uint16_t*) configmem; + if (*tmp == CONFIG_KEY) { + memcpy(&sysconfig, (configmem + sizeof(CONFIG_KEY)), sizeof(sysconfig)); + } + else { + config_save(); + } +} + +uint8_t config_save(void) { + configmem_t mem = { CONFIG_KEY, sysconfig }; + return (flashrom_erase((uint8_t*) &configmem) && flashrom_write((uint8_t*) &configmem, (char*) &mem, sizeof(mem))); +} diff --git a/boards/msba2-common/drivers/Makefile b/boards/msba2-common/drivers/Makefile new file mode 100644 index 0000000000..c2ec597162 --- /dev/null +++ b/boards/msba2-common/drivers/Makefile @@ -0,0 +1,24 @@ +SRC = $(wildcard *.c) +BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o) +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBASE)/sys/include/ -I$(RIOTBASE)/drivers/cc110x_ng/include/ + +$(BINDIR)msba2_common_drivers.a: $(OBJ) + $(AR) rcs $(BINDIR)${ARCH} $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)" | cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products + +clean: + rm -f $(OBJ) $(DEP) + diff --git a/boards/msba2-common/drivers/include/sht11-board.h b/boards/msba2-common/drivers/include/sht11-board.h new file mode 100644 index 0000000000..c35fb00788 --- /dev/null +++ b/boards/msba2-common/drivers/include/sht11-board.h @@ -0,0 +1,58 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef SHT11BOARD_H_ +#define SHT11BOARD_H_ + +/** + * @ingroup lpc2387 + * @{ + */ + +/** + * @file + * @brief LPC2387 SHT11 Device Driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * @note $Id$ + */ + +#include +#include + +#define SHT11_SCK_LOW FIO1CLR = BIT25; // serial clock line low +#define SHT11_SCK_HIGH FIO1SET = BIT25; // serial clock line high +#define SHT11_DATA ((FIO1PIN & BIT26) != 0) // read serial I/O +#define SHT11_DATA_LOW (FIO1CLR = BIT26); // serial I/O line low +#define SHT11_DATA_HIGH (FIO1SET = BIT26); // serial I/O line high +#define SHT11_DATA_IN (FIO1DIR &= ~BIT26) // serial I/O as input +#define SHT11_DATA_OUT (FIO1DIR |= BIT26) // serial I/O as output +#define SHT11_INIT FIO1DIR |= BIT25; PINSEL3 &= ~(BIT14|BIT15 | BIT16|BIT17); + +/** @} */ +#endif /* SHT11BOARD_H_ */ diff --git a/boards/msba2-common/drivers/include/uart0.h b/boards/msba2-common/drivers/include/uart0.h new file mode 100644 index 0000000000..b0861b2b15 --- /dev/null +++ b/boards/msba2-common/drivers/include/uart0.h @@ -0,0 +1,8 @@ +#ifndef __UART0_H +#define __UART0_H + +#define UART0_BUFSIZE 32 + +extern int uart0_handler_pid; + +#endif /* __UART0_H */ diff --git a/boards/msba2-common/drivers/msba2-cc110x.c b/boards/msba2-common/drivers/msba2-cc110x.c new file mode 100644 index 0000000000..b5bde7cbfc --- /dev/null +++ b/boards/msba2-common/drivers/msba2-cc110x.c @@ -0,0 +1,270 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @file + * @ingroup LPC2387 + * @brief CC1100 LPC2387 dependend functions + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Thomas Hillebrandt + * @version $Revision: 1781 $ + * + * @note $Id: msba2-cc110x.c 1781 2010-01-26 13:39:36Z hillebra $ + */ + +#include +#include +// core +#include +#include +// sys +#include +#include +#include +#include + +#define CC1100_GDO0 (FIO0PIN & BIT27) // read serial I/O (GDO0) +#define CC1100_GDO1 (FIO1PIN & BIT23) // read serial I/O (GDO1) +#define CC1100_GDO2 (FIO0PIN & BIT28) // read serial I/O (GDO2) + +#define SPI_TX_EMPTY (SSP0SR & SSPSR_TFE) +#define SPI_BUSY (SSP0SR & SSPSR_BSY) +#define SPI_RX_AVAIL (SSP0SR & SSPSR_RNE) + +#define CC1100_GDO1_LOW_RETRY (100) // max. retries for GDO1 to go low +#define CC1100_GDO1_LOW_COUNT (2700) // loop count (timeout ~ 500 us) to wait +// for GDO1 to go low when CS low + +//#define DEBUG +#ifdef DEBUG + +#include "stdio.h" + +static unsigned long time_value; + +static void set_time(void) +{ + time_value = 0; +} + +static int test_time(int code) +{ + time_value++; + + if (time_value > 10000000) { + printf("CC1100 SPI alarm: %u!\n", code); + time_value = 0; + return 1; + } + + return 0; +} +#endif + +int cc110x_get_gdo0(void) +{ + return CC1100_GDO0; +} + +int cc110x_get_gdo1(void) +{ + return CC1100_GDO1; +} + +int cc110x_get_gdo2(void) +{ + return CC1100_GDO2; +} + +void cc110x_spi_init(void) +{ + // configure chip-select + FIO1DIR |= BIT21; + FIO1SET = BIT21; + + // Power + PCONP |= PCSSP0; // Enable power for SSP0 (default is on) + + // PIN Setup + PINSEL3 |= BIT8 + BIT9; // Set CLK function to SPI + PINSEL3 |= BIT14 + BIT15; // Set MISO function to SPI + PINSEL3 |= BIT16 + BIT17; // Set MOSI function to SPI + + // Interface Setup + SSP0CR0 = 7; + + // Clock Setup + uint32_t pclksel; + uint32_t cpsr; + lpc2387_pclk_scale(F_CPU / 1000, 6000, &pclksel, &cpsr); + PCLKSEL1 &= ~(BIT10 | BIT11); // CCLK to PCLK divider + PCLKSEL1 |= pclksel << 10; + SSP0CPSR = cpsr; + + // Enable + SSP0CR1 |= BIT1; // SSP-Enable + int dummy; + + // Clear RxFIFO: + while (SPI_RX_AVAIL) { // while RNE (Receive FIFO Not Empty)... + dummy = SSP0DR; // read data + } + + /* to suppress unused-but-set-variable */ + (void) dummy; +} + +uint8_t cc110x_txrx(uint8_t c) +{ + uint8_t result; + SSP0DR = c; +#ifdef DEBUG + set_time(); +#endif + + while (!SPI_TX_EMPTY) { +#ifdef DEBUG + test_time(0); +#endif + } + +#ifdef DEBUG + set_time(); +#endif + + while (SPI_BUSY) { +#ifdef DEBUG + test_time(1); +#endif + } + +#ifdef DEBUG + set_time(); +#endif + + while (!SPI_RX_AVAIL) { +#ifdef DEBUG + test_time(2); +#endif + } + + result = (uint8_t)SSP0DR; + return result; +} + +void cc110x_spi_cs(void) +{ + FIO1CLR = BIT21; +} + +void +cc110x_spi_select(void) +{ + volatile int retry_count = 0; + volatile int abort_count; + // Switch to GDO mode input + PINSEL3 &= ~(BIT14 + BIT15);// Set MISO function to GPIO + FIO1DIR &= ~BIT23; +cs_low: + // CS to low + abort_count = 0; + FIO1CLR = BIT21; + // Wait for SO to go low (voltage regulator + // has stabilized and the crystal is running) +loop: + asm volatile("nop"); + + if (CC1100_GDO1) { + abort_count++; + + if (abort_count > CC1100_GDO1_LOW_COUNT) { + retry_count++; + + if (retry_count > CC1100_GDO1_LOW_RETRY) { + puts("[CC1100 SPI] fatal error\n"); + goto final; + } + + FIO1SET = BIT21; // CS to high + goto cs_low; // try again + } + + goto loop; + } + +final: + // Switch to SPI mode + PINSEL3 |= (BIT14 + BIT15); // Set MISO function to SPI +} + +void +cc110x_spi_unselect(void) +{ + FIO1SET = BIT21; +} + +void cc110x_before_send(void) +{ + // Disable GDO2 interrupt before sending packet + cc110x_gdo2_disable(); +} + +void cc110x_after_send(void) +{ + // Enable GDO2 interrupt after sending packet + cc110x_gdo2_enable(); +} + +void cc110x_gdo0_enable(void) +{ + gpioint_set(0, BIT27, GPIOINT_RISING_EDGE, &cc110x_gdo0_irq); +} + +void cc110x_gdo0_disable(void) +{ + gpioint_set(0, BIT27, GPIOINT_DISABLE, NULL); +} + +void cc110x_gdo2_disable(void) +{ + gpioint_set(0, BIT28, GPIOINT_DISABLE, NULL); +} + +void cc110x_gdo2_enable(void) +{ + gpioint_set(0, BIT28, GPIOINT_FALLING_EDGE, &cc110x_gdo2_irq); +} + +void cc110x_init_interrupts(void) +{ + // Enable external interrupt on low edge (for GDO2) + FIO0DIR &= ~BIT28; + cc110x_gdo2_enable(); + // Enable external interrupt on low edge (for GDO0) + FIO0DIR &= ~BIT27; +} diff --git a/boards/msba2-common/drivers/msba2-ltc4150.c b/boards/msba2-common/drivers/msba2-ltc4150.c new file mode 100644 index 0000000000..aba9085189 --- /dev/null +++ b/boards/msba2-common/drivers/msba2-ltc4150.c @@ -0,0 +1,69 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup msba2 + * @ingroup ltc4150 + * @{ + */ + +/** + * @file + * @brief LTC4150 MSB-A2 specific implemetation + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Michael Baar + * @author Kaspar Schleiser + */ + +#include +#include "lpc2387.h" +#include "ltc4150_arch.h" +#include "gpioint.h" + +void __attribute__((__no_instrument_function__)) ltc4150_disable_int(void) +{ + gpioint_set(0, BIT4, GPIOINT_DISABLE, NULL); +} + +void __attribute__((__no_instrument_function__)) ltc4150_enable_int(void) +{ + gpioint_set(0, BIT4, GPIOINT_FALLING_EDGE, <c4150_interrupt); +} + +void __attribute__((__no_instrument_function__)) ltc4150_sync_blocking(void) +{ + while (!(FIO0PIN & BIT4)) {}; +} + +void __attribute__((__no_instrument_function__)) ltc4150_arch_init() +{ + FIO0DIR |= BIT5; + FIO0SET = BIT5; +} + +/** @} */ diff --git a/boards/msba2-common/drivers/msba2-uart0.c b/boards/msba2-common/drivers/msba2-uart0.c new file mode 100644 index 0000000000..5db2ca0da9 --- /dev/null +++ b/boards/msba2-common/drivers/msba2-uart0.c @@ -0,0 +1,230 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/* + * debug_uart.c: provides initial serial debug output + * + * Copyright (C) 2008, 2009 Kaspar Schleiser + * Heiko Will + */ +#include +#include +#include +#include "lpc23xx.h" +#include "VIC.h" +#include + +#include + +/** + * @file + * @ingroup lpc2387 + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * @note $Id$ + */ + +typedef struct toprint_t { + unsigned int len; + char content[]; +} toprint_t; + +#define QUEUESIZE 255 +static volatile toprint_t *queue[QUEUESIZE]; +static volatile unsigned char queue_head = 0; +static volatile unsigned char queue_tail = 0; +static volatile unsigned char queue_items = 0; + +static volatile unsigned int actual_pos = 0; +static volatile unsigned int running = 0; +static volatile unsigned int fifo = 0; + +static volatile toprint_t *actual = NULL; + +static inline void enqueue(void) +{ + queue_items++; + queue_tail++; +} + +static inline void dequeue(void) +{ + actual = (queue[queue_head]); + queue_items--; + queue_head++; +} + +static void push_queue(void) +{ + running = 1; + lpm_prevent_sleep |= LPM_PREVENT_SLEEP_UART; +start: + + if (!actual) { + if (queue_items) { + dequeue(); + } + else { + running = 0; + lpm_prevent_sleep &= ~LPM_PREVENT_SLEEP_UART; + + if (!fifo) + while (!(U0LSR & BIT6)) {}; + + return; + } + } + + while ((actual_pos < actual->len) && (fifo++ < 16)) { + U0THR = actual->content[actual_pos++]; + } + + if (actual_pos == actual->len) { + free((void *)actual); + actual = NULL; + actual_pos = 0; + goto start; + } +} + +int uart_active(void) +{ + return (running || fifo); +} + +void stdio_flush(void) +{ + U0IER &= ~BIT1; // disable THRE interrupt + + while (running) { + while (!(U0LSR & (BIT5 | BIT6))) {}; // transmit fifo + + fifo = 0; + + push_queue(); // dequeue to fifo + } + + U0IER |= BIT1; // enable THRE interrupt +} + +void UART0_IRQHandler(void) __attribute__((interrupt("IRQ"))); +void UART0_IRQHandler(void) +{ + int iir; + iir = U0IIR; + + switch (iir & UIIR_ID_MASK) { + case UIIR_THRE_INT: // Transmit Holding Register Empty + fifo = 0; + push_queue(); + break; + + case UIIR_CTI_INT: // Character Timeout Indicator + case UIIR_RDA_INT: // Receive Data Available +#ifdef MODULE_UART0 + if (uart0_handler_pid) { + do { + int c = U0RBR; + uart0_handle_incoming(c); + } + while (U0LSR & ULSR_RDR); + + uart0_notify_thread(); + } + +#endif + break; + + default: + U0LSR; + U0RBR; + break; + } // switch + + VICVectAddr = 0; // Acknowledge Interrupt +} + +static inline int uart0_puts(char *astring, int length) +{ + /* while (queue_items == (QUEUESIZE-1)) {} ; + U0IER = 0; + queue[queue_tail] = malloc(length+sizeof(unsigned int)); + queue[queue_tail]->len = length; + memcpy(&queue[queue_tail]->content,astring,length); + enqueue(); + if (!running) + push_queue(); + U0IER |= BIT0 | BIT1; // enable RX irq + */ + /* alternative without queue:*/ + int i; + + for (i = 0; i < length; i++) { + while (!(U0LSR & BIT5)); + + U0THR = astring[i]; + } + + /* */ + + return length; +} + +int fw_puts(char *astring, int length) +{ + return uart0_puts(astring, length); +} + +int +bl_uart_init(void) +{ + PCONP |= PCUART0; // power on + + // UART0 clock divider is CCLK/8 + PCLKSEL0 |= BIT6 + BIT7; + + U0LCR = 0x83; // 8 bits, no Parity, 1 Stop bit + + // TODO: UART Baudrate calculation using uart->config->speed + /* + * Baudrate calculation + * BR = PCLK (9 MHz) / (16 x 256 x DLM + DLL) x (1/(DIVADDVAL/MULVAL)) + */ + U0FDR = 0x92; // DIVADDVAL = 0010 = 2, MULVAL = 1001 = 9 + U0DLM = 0x00; + U0DLL = 0x04; + + U0LCR = 0x03; // DLAB = 0 + U0FCR = 0x07; // Enable and reset TX and RX FIFO + + /* irq */ + install_irq(UART0_INT, UART0_IRQHandler, 6); + U0IER |= BIT0; // enable only RX irq + return 1; +} + diff --git a/boards/msba2-common/include/msba2_common.h b/boards/msba2-common/include/msba2_common.h new file mode 100644 index 0000000000..4e56c82ab7 --- /dev/null +++ b/boards/msba2-common/include/msba2_common.h @@ -0,0 +1,52 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef __MSBA2_COMMON_H +#define __MSBA2_COMMON_H + +/** + * @ingroup msb_a2 + * @{ + */ + +/** + * @file + * @brief MSB-A2 Common Board Definitions + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + * @version $Revision$ + * + * @note $Id$ + */ + +#include +#include "lpc2387.h" + +#define VICIntEnClear VICIntEnClr + +/** @} */ +#endif // __MSBA2_COMMON_H diff --git a/boards/msba2-common/lpc2387-timer3.c b/boards/msba2-common/lpc2387-timer3.c new file mode 100644 index 0000000000..3b404edd94 --- /dev/null +++ b/boards/msba2-common/lpc2387-timer3.c @@ -0,0 +1,36 @@ +/* + * lpc2387_timer0.c + * + * Created on: 13.01.2009 + * Author: heiko + */ + +#include +#include +#include "lpc2387.h" + +void benchmark_init(void) +{ + PCLKSEL1 = (PCLKSEL1 & ~(BIT14|BIT15)) | (1 << 14); // CCLK to PCLK divider + PCONP |= PCTIM3; + T3TCR = 0; // disable timer + T3MCR = 0; // disable interrupt + T3CCR = 0; // capture is disabled. + T3EMR = 0; // no external match output. + T3PR = 0; // set prescaler + T3TC = 0; // reset counter +} + +void benchmark_reset_start(void) +{ + T3TCR = 0; // disable timer + T3TC = 0; // reset counter + T3TCR = BIT0; +} + +unsigned int benchmark_read_stop(void) +{ + T3TCR = 0; // disable timer + return T3TC; +} + diff --git a/boards/msba2-common/tools/CHANGES b/boards/msba2-common/tools/CHANGES new file mode 100644 index 0000000000..dd9e6ec1ea --- /dev/null +++ b/boards/msba2-common/tools/CHANGES @@ -0,0 +1,23 @@ +(heavily hacked by Heiko Will & Kaspar Schleiser since then) + +1.05 (9-Apr-2007) +----------------- +Added boot jump code specific to 2378 (and similar chips) to +disable the PLL before jumping to the user's code. + +1.04 (19-Dec-2006) +------------------ +Added 2364, 2366, 2368, 2378 & 2468 to list. Untested. + +1.03 (2-Jun-2006) +----------------- +Added 2103 chip to chip list. ID numbers for 2101 and 2102 unknown + +1.02 (31-Jul-2005) +------------------ +Added support for other chips +Added soft boot code +Added user configurable crystal value (for baud sync protocol) + + + diff --git a/boards/msba2-common/tools/COPYING b/boards/msba2-common/tools/COPYING new file mode 100644 index 0000000000..a43ea2126f --- /dev/null +++ b/boards/msba2-common/tools/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/boards/msba2-common/tools/Makefile b/boards/msba2-common/tools/Makefile new file mode 100644 index 0000000000..8dbdcc242a --- /dev/null +++ b/boards/msba2-common/tools/Makefile @@ -0,0 +1,51 @@ +CFLAGS = -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" +CC = gcc +prefix=/usr/local + +all: lpc2k_pgm pseudoterm + +SRC = lpc2k_pgm.c download.c uuencode.c ihex.c serial.c chipinfo.c boot_2xxx.c boot_23xx.c control_2xxx.c +OBJS = ${addprefix obj/,${patsubst %.c,%.o,$(SRC)}} + +PSEUDOTERM_SRC = pseudoterm.c serial.c control_2xxx.c +PSEUDOTERM_OBJS = ${addprefix obj/,${patsubst %.c,%.o,$(PSEUDOTERM_SRC)}} + +TARGETDIR = bin + +lpc2k_pgm: $(OBJS) + mkdir -p $(TARGETDIR) + $(CC) -o $(TARGETDIR)/lpc2k_pgm $(OBJS) + +pseudoterm: $(PSEUDOTERM_OBJS) + mkdir -p $(TARGETDIR) + $(CC) -o $(TARGETDIR)/pseudoterm $(PSEUDOTERM_OBJS) -lpthread + +chipinfo.o: boot_2xxx.h boot_23xx.h + +static: $(OBJS) mkstaticlist + $(CC) -o $(TARGETDIR)/lpc2k_pgm $(OBJS) `./mkstaticlist` + +obj/%.o : src/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +cksum_test: cksum_test.c uuencode.o cksum_test.o + $(CC) $(CFLAGS) -o $(TARGETDIR)/cksum_test obj/cksum_test.o obj/uuencode.o + +boot_2xxx.c boot_2xxx.h: boot_2xxx.armasm mkbootc + arm-none-eabi-as -o boot_2xxx.armobj boot_2xxx.armasm + arm-none-eabi-objdump -d boot_2xxx.armobj | ./mkbootc boot_2xxx + +boot_23xx.c boot_23xx.h: src/boot_23xx.armasm mkbootc + arm-none-eabi-as -o obj/boot_23xx.armobj src/boot_23xx.armasm + arm-none-eabi-objdump -d obj/boot_23xx.armobj | ./mkbootc boot_23xx + +clean: + rm -f bin/lpc2k_pgm cksum_test obj/*.o core core.* obj/*.armobj bin/pseudoterm + +install: + install -m 0755 bin/lpc2k_pgm $(prefix)/bin + +.PHONY: install + +obj/gui.o: src/gui.c + $(CC) $(CFLAGS) `gtk-config --cflags` -c src/gui.c -o obj/gui.o diff --git a/boards/msba2-common/tools/README.txt b/boards/msba2-common/tools/README.txt new file mode 100644 index 0000000000..8fd6adb012 --- /dev/null +++ b/boards/msba2-common/tools/README.txt @@ -0,0 +1,144 @@ +This utility downloads code to Philip LPC 2000 series chips, using the +bootloader communication protocol documented in the LPC2106/2105/2104 +User Manual, Sept 2003 revision, pages 177 to 192. This code has also +been tested with LPC2131 and LPC2138 chips (thanks to New Micros for +providing eval boards). It may work with other Philips ARM LPC parts. + + + +Usage: +----- + +When you start the program, it's small control window appears, and a +xterm terminal window is launched. The Xterm window allows you to +simply leave lpc2k_pgm running and interface with the LPC uart using +that window. Most people configure "printf" on in their code to print +to UART0, which will appear in this window. + +This program has 4 settings: + +Firmware: The intel-hex file with your LPC firmware to program. +Port: Which serial device to use. +Baud: The baud rate to communicate. +Crystal: The speed of the crystal on your LPC board. + +Once you have set up these values, simply press the "Program Now" +button to write your firmware to the LPC flash memory, and automatically +run it. If your firmware communicates on UART0, its messages will appear +in the xterm window, and anything you type in that window will be +transmitted to your board. + +The "Reboot" button may be used to reboot your code (assuming you have +connected DTR appropriately). The "Bootloader" button may be used to +stop your code by rebooting into the bootloader, rather than your program. + + + +Hardware Requirements: +--------------------- + +You must have a compatible Philips LPC chip with its UART0 interfaced +to a serial port on your PC. + +You must be able to reset the chip and cause it to enter bootloader mode. +Normally, this is done by connecting the (TTL level translated) DTR signal +to the LPC reset, so that when DTR is high (the TTL version is low), the +Philips chip is in reset mode. Alternately, a pushbutton may be used, +but you will need to manually press the button every time you want to get +back into bootloader mode (while this program attempts to sync baud rates), +rather than letting DTR do it automatically. A few minutes spent wiring +up your circuit so DTR can reset the board will save you much trouble as +you develop code. + +P0.14 must be connected low shortly after reset. Normally, this pin +is just shorted to ground using a jumper. Starting with version 1.02, +you can simply leave this shorted to ground. If your design needs to +use this pin, you may also build a simple circuit that forces this pin +to ground when RTS is high. + + + +Software Requirements: +--------------------- + +You must have a Linux-based system running X Windows. This code has +been tested with Linux kernel 2.4.20 and 2.6.8, and should work with +almost any linux system. + +You must have the "xterm" program installed. Nearly all linux +distrubtions provide this, and it is often installed by default. If +you do not have it, simply install from your linux distribution. + +Your serial port device file (usually /dev/ttyS0 or /dev/ttyS1) must +allow permission for you to use the serial port. + +GTK 1.2 is used for the GUI. Many newer systems only have GTK version +2 (or higher). If you have one of these systems, perhaps you can +install GTK 1.2 (including the development libraries) to allow you to +compile this code. Alternately, you may be able to use the semi-static +build, which includes a copy of this code built into the program. + + + +Building and Installation: +------------------------- + +This software is only provided semi-static binary and source code form. + +To use the semi-static binary, simply copy it to a location where you +can run it, and change the permissions if necessary: + + cp lpc2k_pgm /usr/local/bin + chmod 755 /usr/local/bin/lpc2k_pgm + +The semi-static binary has all of the GTK and X11 libraries statically +linked into it, for maximum compatibility with all linux distributions. +The only disadvantage is, of course, that this uses an extra 1.4 megs +of RAM, with (might) otherwise be shared with other programs. If you +simply want to run this program with minimal work, using the semi-static +binary may be the easiest way. + +If you compile from the source code, the result should be a small +binary that is optimal for your system. + +To build from source, you must have GTK+ 1.2 development libraries +and GCC properly installed. Nearly all linux distributions provide +these as packages, but you may need to install them before you can +compile the code. + +TODO: specific instructions for Debian stable +TODO: specific instructions for Debian testing/unstable +TODO: specific instructions for Fedora +TODO: specific instructions for Suse + +Simply type "make" to build the code. The resulting "lpc2k_pgm" +program can be run from any location. Simply copy to /usr/local/bin, +or where ever you like. + + + +Contact Info: +------------ + +Paul Stoffregen +paul@pjrc.com +http://www.pjrc.com/arm/lpc2k_pgm + +If you discover a bug, you want to request a new feature, or you have +a new Philips LPC chip which is not recognized, please attempt to +provide COMPLETE information in your message. + +If you have problems building from source, please contact me with ALL +of the following: + +1: Complete copy of all messages during the build. +2: Output of "gtk-config --version" +3: Output of "gtk-config --libs" +4: Output of "gtk-config --cflags" +5: Output of "uname -a" +6: Other info... which linux distribution, version, other software + +If you get "Command not found" when trying to run "gtk-config", this +is a sure sign that you do not have GTK+ 1.2 installed. + + diff --git a/boards/msba2-common/tools/armtools.txt b/boards/msba2-common/tools/armtools.txt new file mode 100644 index 0000000000..c91a4853f7 --- /dev/null +++ b/boards/msba2-common/tools/armtools.txt @@ -0,0 +1,15 @@ +This directory contains flash & terminal-utilities for use with +the msb_av2 platform used by the FeuerWhere-Project. + +Usage: +Running "./pseudoterm /dev/ttyUSB1" will start the terminal-emulator, +open the specified port and reset the connected msb_av2-board. +If it receives a SIGUSR2, the terminal closes the port an waits. +On reception of a SIGUSR1, it reopens the port and resets the ARM. + +"./lpc2k_pgm /dev/ttyUSB1 /path/to/firmware.ihex" will do what you +expect, but it will additionally run "killall -SIGUSR2 pseudoterm" before +anѕ "killall -SIGUSR1 pseudoterm" after flashing. + +Together, the tools enable you to have a terminal connected to the board +at all times, but let you flash whenever you feel like. diff --git a/boards/msba2-common/tools/flash.cmd b/boards/msba2-common/tools/flash.cmd new file mode 100755 index 0000000000..e957ca2b65 --- /dev/null +++ b/boards/msba2-common/tools/flash.cmd @@ -0,0 +1,2 @@ +fm.exe "COM(%1, 230400) DEVICE(LPC2387, 16.000000) HARDWARE(BOOTEXEC, 50, 100) HIGHSPEED(0, 230400) ERASEUSED(%2, PROTECTISP) HEXFILE(%2, NOCHECKSUMS, NOFILL, PROTECTISP) RESET" +sleep 2 diff --git a/boards/msba2-common/tools/flashutil.sh b/boards/msba2-common/tools/flashutil.sh new file mode 100755 index 0000000000..c97d7c9a63 --- /dev/null +++ b/boards/msba2-common/tools/flashutil.sh @@ -0,0 +1,113 @@ +#/bin/bash + +linux_checkid() { + udevinfo -a -n ${1} | grep -q "ATTRS{product}==\"${2}\"" +} + +windows_flash_fm() { + echo "Checking FTDI device on COM${1}" + PORTINFO=`${BASEDIR}/../../../tools/windows/ftdiinfo/bin/Debug/ftdiinfo.exe /l COM${1}` + PORTCHECK=`echo ${PORTINFO} | awk '{ print $1 }'` + BOARDCHECK=`echo ${PORTINFO} | awk '{ print $3 }'` + SERIAL=`echo ${PORTINFO} | awk '{ print $2 }'` + if [ "${PORTCHECK}" != "COM${1}" ]; then + echo " port mismatch / ftdiinfo failed" + exit 1 + fi + if [ "${BOARDCHECK}" != "\"${FTDI_ID}\"" ]; then + echo " target mismatch: target board is \"${FTDI_ID}\", connected is ${BOARDCHECK}" + exit 1 + fi + + echo "Flashing ${HEXFILE} to COM${1} (${BOARDCHECK} serial ${SERIAL})" + # Using FlashMagic on Windows (in separate window) + cmd /C start "FlashMagic ${HEXFILE} to ${BOARDCHECK} on COM${1}" fm.exe "COM(${1}, 230400) DEVICE(LPC2387, 16.000000) HARDWARE(BOOTEXEC, 50, 100) HIGHSPEED(0, 230400) ERASEUSED(${HEXFILE}, PROTECTISP) HEXFILE(${HEXFILE}, NOCHECKSUMS, NOFILL, PROTECTISP) RESET" +} + +windows_flash_openocd() { + echo "Flashing ${HEXFILE} through JTAG" + # Using OpenOcd on Windows + #cmd /C start "OpenOCD ${HEXFILE} to ${BOARDCHECK}" + bash -x ${OPENOCD} ${OPENOCD_IF} "mt_flash ${HEXFILE}; reset run; shutdown" +} + +TEMP=`getopt -a -o b:i:p:f:: --long basedir:,id:,ports:,file:,openocd:,openocd-if:,xxx:: \ + -n 'flashutil.sh' -- "$@"` + +if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi + +# Note the quotes around `$TEMP': they are essential! +eval set -- "$TEMP" + +while true ; do + echo $1: $2 + case "$1" in + -b|--basedir) BASEDIR=$2 ; shift 2 ;; + -i|--id) FTDI_ID=$2; shift 2 ;; + -p|--ports) PORTS=`echo $2 | sed -e 's:,: :g'`; shift 2 ;; + --openocd) OPENOCD=$2; shift 2 ;; + --openocd-if) OPENOCD_IF=$2; shift 2 ;; + + --) HEXFILE=$2 ; shift ; break ;; + *) echo "Internal error!" ; exit 1 ;; + esac +done + +if [ "${OS}" = "Windows_NT" ]; then + WINDOWS=1 +fi + +FLASHUTIL_SHELL=${FLASHUTIL_SHELL:-"xterm -e"} + +if [ "x${WINDOWS}x" = "xx" ]; then + echo Pausing terminal + ${BASEDIR}/termctrl.sh pause +else + HEXFILE=`echo ${HEXFILE} | sed -e 's:/:\\\\:g'` + BASEDIRWIN=`echo ${BASEDIR} | sed -e 's:/:\\\\:g'` +fi + +pids="" + +# +# for OpenOCD let the user verify, that the correct board is connected +# +if [ ${PORTS} = "openocd" ]; then + [ "$OPENOCD" != "" ] || exit 1 + [ "$OPENOCD_IF" != "" ] || exit 1 +# echo -n "Is the board connected to the JTAG a '${FTDI_ID}' (y/n)? " +# read REPLY +# [ "$REPLY" = "y" ] || exit 1 +fi +# +# start a flasher for each port +# +for PORT in $PORTS; do + if [ "x${WINDOWS}x" != "xx" ]; then + if [ "${PORT}" = "openocd" ]; then + windows_flash_openocd + else + windows_flash_fm ${PORT} + fi + else + if [ "${PORT}" = "openocd" ]; then + ${OPENOCD} ${OPENOCD_IF} "mt_flash ${HEXFILE}; reset run; shutdown" + else + echo Flashing ${HEXFILE} to ${PORT} + # using homemade lpc2k_pgm else + ${FLASHUTIL_SHELL} "${BASEDIR}/bin/lpc2k_pgm ${PORT} ${HEXFILE}; sleep 2" & + pids="${pids} $!" + fi + fi +done + +### wait for all flasher processes to finish +echo Waiting until all devices have been programmed... +for pid in "${pids}"; do + wait ${pid} +done + +if [ "x${WINDOWS}x" = "xx" ]; then + echo Resuming terminal + ${BASEDIR}/termctrl.sh continue +fi diff --git a/boards/msba2-common/tools/mkbootc b/boards/msba2-common/tools/mkbootc new file mode 100644 index 0000000000..4c0d9554dc --- /dev/null +++ b/boards/msba2-common/tools/mkbootc @@ -0,0 +1,28 @@ +#! /usr/bin/perl + +$h = '[0-9A-Fa-f]'; +$n = 1; +while () { + next unless /^\s*$h+:\s+($h{8})/; + $data[$n++] = "0x$1"; +} +$data[0] = $n; +#$size = $ARGV[0]; +#$size =~ tr/a-z/A-Z/; +#$size .= '_SIZE'; + +open H, ">$ARGV[0].h" or die "unable to write boot.h\n"; +print H "/* automatically generated from $ARGV[0].armasm */\n"; +#print H "#define $size $n\n"; +print H "extern const unsigned int ${ARGV[0]}[];\n"; +close H; + +open C, ">$ARGV[0].c" or die "unable to write boot.c\n"; +print C "/* automatically generated from $ARGV[0].armasm */\n"; +print C "#include \"$ARGV[0].h\"\n"; +print C "const unsigned int ${ARGV[0]}[] = {\n"; +print C "\t", join(', ', @data), "\n"; +print C "};\n"; +close C; + + diff --git a/boards/msba2-common/tools/mkstaticlist b/boards/msba2-common/tools/mkstaticlist new file mode 100644 index 0000000000..4ad31030ca --- /dev/null +++ b/boards/msba2-common/tools/mkstaticlist @@ -0,0 +1,47 @@ +#! /usr/bin/perl + +@arg = split(/\s+/, `gtk-config --libs`); + +%liblist = ( + 'libgtk.a', '/usr/lib/libgtk.a', + 'libgdk.a', '/usr/lib/libgdk.a', + 'libgmodule.a', '/usr/lib/libgmodule.a', + 'libglib.a', '/usr/lib/libglib.a', + 'libXi.a', '/usr/X11R6/lib/libXi.a', + 'libXext.a', '/usr/X11R6/lib/libXext.a', + 'libX11.a', '/usr/X11R6/lib/libX11.a' +); + + +for ($i=0; $i<@arg; $i++) { + $a = $arg[$i]; + next if $a eq '-rdynamic'; # always delete -rdynamic + if (($a eq '-lm') || ($a eq '-ldl') || ($a =~ /^-L/)) { + # a few things we never change + print "$a "; + next; + } + if ($a =~ /^-l/) { + $lib = $'; + $lib = 'lib' . $lib . '.a'; + # first check if it's in the known location + if (-f $liblist{$lib}) { + print $liblist{$lib}, " "; + next; + } + # resort to trying whereis to find it + @source = split(/\s+/, `whereis $lib`); + undef($static); + for ($j=0; $j<@source; $j++) { + $static = $source[$j] if $source[$j] =~ /$lib$/; + } + # if we found a static lib, use it. + if ($static) { + print $static, " "; + } else { + print $a, " "; + } + } +} +print "\n"; + diff --git a/boards/msba2-common/tools/obj/boot_23xx.d b/boards/msba2-common/tools/obj/boot_23xx.d new file mode 100644 index 0000000000..e45338d651 --- /dev/null +++ b/boards/msba2-common/tools/obj/boot_23xx.d @@ -0,0 +1,3 @@ +obj/boot_23xx.d: src/boot_23xx.c src/boot_23xx.h + +src/boot_23xx.h: diff --git a/boards/msba2-common/tools/obj/boot_2xxx.d b/boards/msba2-common/tools/obj/boot_2xxx.d new file mode 100644 index 0000000000..e0e9fb40da --- /dev/null +++ b/boards/msba2-common/tools/obj/boot_2xxx.d @@ -0,0 +1,3 @@ +obj/boot_2xxx.d: src/boot_2xxx.c src/boot_2xxx.h + +src/boot_2xxx.h: diff --git a/boards/msba2-common/tools/obj/chipinfo.d b/boards/msba2-common/tools/obj/chipinfo.d new file mode 100644 index 0000000000..b695e68c42 --- /dev/null +++ b/boards/msba2-common/tools/obj/chipinfo.d @@ -0,0 +1,8 @@ +obj/chipinfo.d: src/chipinfo.c src/chipinfo.h src/boot_2xxx.h \ + src/boot_23xx.h + +src/chipinfo.h: + +src/boot_2xxx.h: + +src/boot_23xx.h: diff --git a/boards/msba2-common/tools/obj/control_2xxx.d b/boards/msba2-common/tools/obj/control_2xxx.d new file mode 100644 index 0000000000..e9ed3f7b1b --- /dev/null +++ b/boards/msba2-common/tools/obj/control_2xxx.d @@ -0,0 +1,5 @@ +obj/control_2xxx.d: src/control_2xxx.c src/control_2xxx.h src/serial.h + +src/control_2xxx.h: + +src/serial.h: diff --git a/boards/msba2-common/tools/obj/download.d b/boards/msba2-common/tools/obj/download.d new file mode 100644 index 0000000000..94c10a80c5 --- /dev/null +++ b/boards/msba2-common/tools/obj/download.d @@ -0,0 +1,19 @@ +obj/download.d: src/download.c src/lpc2k_pgm.h src/download.h \ + src/serial.h src/ihex.h src/uuencode.h src/chipinfo.h src/boot.h \ + src/control_2xxx.h + +src/lpc2k_pgm.h: + +src/download.h: + +src/serial.h: + +src/ihex.h: + +src/uuencode.h: + +src/chipinfo.h: + +src/boot.h: + +src/control_2xxx.h: diff --git a/boards/msba2-common/tools/obj/ihex.d b/boards/msba2-common/tools/obj/ihex.d new file mode 100644 index 0000000000..89b506056a --- /dev/null +++ b/boards/msba2-common/tools/obj/ihex.d @@ -0,0 +1,3 @@ +obj/ihex.d: src/ihex.c src/ihex.h + +src/ihex.h: diff --git a/boards/msba2-common/tools/obj/lpc2k_pgm.d b/boards/msba2-common/tools/obj/lpc2k_pgm.d new file mode 100644 index 0000000000..98c82eb328 --- /dev/null +++ b/boards/msba2-common/tools/obj/lpc2k_pgm.d @@ -0,0 +1,8 @@ +obj/lpc2k_pgm.d: src/lpc2k_pgm.c src/lpc2k_pgm.h src/serial.h \ + src/download.h + +src/lpc2k_pgm.h: + +src/serial.h: + +src/download.h: diff --git a/boards/msba2-common/tools/obj/pseudoterm.d b/boards/msba2-common/tools/obj/pseudoterm.d new file mode 100644 index 0000000000..858fa2cba7 --- /dev/null +++ b/boards/msba2-common/tools/obj/pseudoterm.d @@ -0,0 +1,5 @@ +obj/pseudoterm.d: src/pseudoterm.c src/serial.h src/download.h + +src/serial.h: + +src/download.h: diff --git a/boards/msba2-common/tools/obj/serial.d b/boards/msba2-common/tools/obj/serial.d new file mode 100644 index 0000000000..ebabf01ecf --- /dev/null +++ b/boards/msba2-common/tools/obj/serial.d @@ -0,0 +1,3 @@ +obj/serial.d: src/serial.c src/serial.h + +src/serial.h: diff --git a/boards/msba2-common/tools/obj/uuencode.d b/boards/msba2-common/tools/obj/uuencode.d new file mode 100644 index 0000000000..548a00f642 --- /dev/null +++ b/boards/msba2-common/tools/obj/uuencode.d @@ -0,0 +1,3 @@ +obj/uuencode.d: src/uuencode.c src/uuencode.h + +src/uuencode.h: diff --git a/boards/msba2-common/tools/src/boot.h b/boards/msba2-common/tools/src/boot.h new file mode 100644 index 0000000000..ebca675db1 --- /dev/null +++ b/boards/msba2-common/tools/src/boot.h @@ -0,0 +1,9 @@ + +typedef struct { + int size; + const int *prog; +} boot_t; + + + + diff --git a/boards/msba2-common/tools/src/boot_23xx.armasm b/boards/msba2-common/tools/src/boot_23xx.armasm new file mode 100644 index 0000000000..50e29957ff --- /dev/null +++ b/boards/msba2-common/tools/src/boot_23xx.armasm @@ -0,0 +1,32 @@ + /* ARM code to run user code */ + /* on the LPC23xx chips, the bootloader defaults to using the RC */ + /* osciallator and it activates the PLL to create 14.78 MHz, even */ + /* if there is no crystal. However, when we use try to jump to */ + /* the user's code, their startup routine may (incorrectly) assume */ + /* the PLL is not enabled and crash if it is. So in addition to */ + /* remapping the reset vector to flash, we have to shut off the */ + /* PLL so the user's startup code sees the same conditions as it */ + /* would following a hard reset */ +begin: + adr r0, const + ldr r1, [r0] /* r1 points to MEMMAP register */ + ldr r2, [r0,#4] /* r2 points to PLLCON */ + ldr r3, [r0,#8] /* r3 points to PLLFEED */ + mov r0, #1 + str r0, [r1] /* remap interrupt vectors to flash */ + mov r4, #0xAA + mov r5, #0x55 + str r0, [r2] /* disconnect the PLL, PLLCON = 1 */ + str r4, [r3] + str r5, [r3] + mov r0, #0 + str r0, [r2] /* disable the PLL, PLLCON = 0 */ + str r4, [r3] + str r5, [r3] + mov pc, #0 /* and then jump to the user's code */ +const: + .int 0xE01FC040 /* MEMMAP register */ + .int 0xE01FC080 /* PLLCON */ + .int 0xE01FC08C /* PLLFEED */ + + diff --git a/boards/msba2-common/tools/src/boot_23xx.c b/boards/msba2-common/tools/src/boot_23xx.c new file mode 100644 index 0000000000..80fcb399d0 --- /dev/null +++ b/boards/msba2-common/tools/src/boot_23xx.c @@ -0,0 +1,5 @@ +/* automatically generated from boot_23xx.armasm */ +#include "boot_23xx.h" +const unsigned int boot_23xx[] = { + 20, 0xe28f0038, 0xe5901000, 0xe5902004, 0xe5903008, 0xe3a00001, 0xe5810000, 0xe3a040aa, 0xe3a05055, 0xe5820000, 0xe5834000, 0xe5835000, 0xe3a00000, 0xe5820000, 0xe5834000, 0xe5835000, 0xe3a0f000, 0xe01fc040, 0xe01fc080, 0xe01fc08c +}; diff --git a/boards/msba2-common/tools/src/boot_23xx.h b/boards/msba2-common/tools/src/boot_23xx.h new file mode 100644 index 0000000000..0696a29312 --- /dev/null +++ b/boards/msba2-common/tools/src/boot_23xx.h @@ -0,0 +1,2 @@ +/* automatically generated from boot_23xx.armasm */ +extern const unsigned int boot_23xx[]; diff --git a/boards/msba2-common/tools/src/boot_2xxx.armasm b/boards/msba2-common/tools/src/boot_2xxx.armasm new file mode 100644 index 0000000000..38e171520a --- /dev/null +++ b/boards/msba2-common/tools/src/boot_2xxx.armasm @@ -0,0 +1,15 @@ + /* ARM code to run user code */ + /* This allows us to jump to the user's code in flash. We have */ + /* to remap the flash before jumping. */ +begin: + adr r0, const + ldr r1, [r0] /* r1 points to MEMMAP register */ + mov r0, #1 + str r0, [r1] /* remap interrupt vectors to flash */ + mov pc, #0 /* and then jump to the user's code */ +const: + .int 0xE01FC040 /* MEMMAP register */ + + + + diff --git a/boards/msba2-common/tools/src/boot_2xxx.c b/boards/msba2-common/tools/src/boot_2xxx.c new file mode 100644 index 0000000000..060db40354 --- /dev/null +++ b/boards/msba2-common/tools/src/boot_2xxx.c @@ -0,0 +1,5 @@ +/* automatically generated from boot_2xxx.armasm */ +#include "boot_2xxx.h" +const unsigned int boot_2xxx[] = { + 7, 0xe28f000c, 0xe5901000, 0xe3a00001, 0xe5810000, 0xe3a0f000, 0xe01fc040 +}; diff --git a/boards/msba2-common/tools/src/boot_2xxx.h b/boards/msba2-common/tools/src/boot_2xxx.h new file mode 100644 index 0000000000..333188def2 --- /dev/null +++ b/boards/msba2-common/tools/src/boot_2xxx.h @@ -0,0 +1,2 @@ +/* automatically generated from boot_2xxx.armasm */ +extern const unsigned int boot_2xxx[]; diff --git a/boards/msba2-common/tools/src/chipinfo.c b/boards/msba2-common/tools/src/chipinfo.c new file mode 100644 index 0000000000..4c418379b8 --- /dev/null +++ b/boards/msba2-common/tools/src/chipinfo.c @@ -0,0 +1,156 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program 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 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include "chipinfo.h" +#include "boot_2xxx.h" +#include "boot_23xx.h" + + +struct sector_info_struct lpc2106_layout[] = { + {0x00000000, 0x2000}, + {0x00002000, 0x2000}, + {0x00004000, 0x2000}, + {0x00006000, 0x2000}, + {0x00008000, 0x2000}, + {0x0000A000, 0x2000}, + {0x0000C000, 0x2000}, + {0x0000E000, 0x2000}, + {0x00010000, 0x2000}, + {0x00012000, 0x2000}, + {0x00014000, 0x2000}, + {0x00016000, 0x2000}, + {0x00018000, 0x2000}, + {0x0001A000, 0x2000}, + {0x0001C000, 0x2000} +}; + +struct sector_info_struct lpc2214_layout[] = { + {0x00000000, 0x2000}, + {0x00002000, 0x2000}, + {0x00004000, 0x2000}, + {0x00006000, 0x2000}, + {0x00008000, 0x2000}, + {0x0000A000, 0x2000}, + {0x0000C000, 0x2000}, + {0x0000E000, 0x2000}, + {0x00010000, 0x10000}, + {0x00020000, 0x10000}, + {0x00030000, 0x2000}, + {0x00032000, 0x2000}, + {0x00034000, 0x2000}, + {0x00036000, 0x2000}, + {0x00038000, 0x2000}, + {0x0003A000, 0x2000}, + {0x0003C000, 0x2000} +}; + +struct sector_info_struct lpc2138_layout[] = { + {0x00000000, 0x1000}, + {0x00001000, 0x1000}, + {0x00002000, 0x1000}, + {0x00003000, 0x1000}, + {0x00004000, 0x1000}, + {0x00005000, 0x1000}, + {0x00006000, 0x1000}, + {0x00007000, 0x1000}, + {0x00008000, 0x8000}, + {0x00010000, 0x8000}, + {0x00018000, 0x8000}, + {0x00020000, 0x8000}, + {0x00028000, 0x8000}, + {0x00030000, 0x8000}, + {0x00038000, 0x8000}, + {0x00040000, 0x8000}, + {0x00048000, 0x8000}, + {0x00050000, 0x8000}, + {0x00058000, 0x8000}, + {0x00060000, 0x8000}, + {0x00068000, 0x8000}, + {0x00070000, 0x8000}, + {0x00078000, 0x1000}, + {0x00079000, 0x1000}, + {0x0007A000, 0x1000}, + {0x0007B000, 0x1000}, + {0x0007C000, 0x1000} +}; + + + +/* chunk_size is the number of bytes that will be sent with each */ +/* "C" (Copy RAM to Flash) command. This must be one of the sizes */ +/* supported by that command. Beware that different chips support */ +/* different sets of sizes, so check the user manual specific to */ +/* the chip. You must choose a chunk_size which is an an integer */ +/* multiple of all the sector sizes, and it must be able to fit */ +/* entirely within the RAM (allowing for the bootloader memory and */ +/* stack usage). Currently, all available chunk sizes meet these */ +/* requirements, but who knows what Philips will do in the future? */ +// +/* ram_addr is the location in RAM where the chunks are sent by the */ +/* "W" (Write to RAM) command. */ + + +struct chip_info_struct chip_info[] = { + /* part_number id_string ram_addr _size sec sector layout boot code */ + {"LPC2104 (120k)", "4293984018", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, + {"LPC2105 (120k)", "4293984034", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, + {"LPC2106 (120k)", "4293984050", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, + {"LPC2114 (120k)", "16908050", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, + {"LPC2119 (120k)", "33685266", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, + {"LPC2124 (120k)", "16908051", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, + {"LPC2129 (248k)", "33685267", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, + {"LPC2131 (32k)", "196353", 0x40000200, 0x1000, 8, lpc2138_layout, boot_2xxx}, + {"LPC2132 (64k)", "196369", 0x40000200, 0x1000, 9, lpc2138_layout, boot_2xxx}, + {"LPC2134 (128k)", "196370", 0x40000200, 0x1000, 11, lpc2138_layout, boot_2xxx}, + {"LPC2136 (256k)", "196387", 0x40000200, 0x1000, 15, lpc2138_layout, boot_2xxx}, + {"LPC2138 (500k)", "196389", 0x40000200, 0x1000, 27, lpc2138_layout, boot_2xxx}, + {"LPC2141 (32k)", "67305217", 0x40000200, 0x1000, 8, lpc2138_layout, boot_2xxx}, + {"LPC2142 (64k)", "67305233", 0x40000200, 0x1000, 9, lpc2138_layout, boot_2xxx}, + {"LPC2144 (128k)", "67305234", 0x40000200, 0x1000, 11, lpc2138_layout, boot_2xxx}, + {"LPC2146 (256k)", "67305251", 0x40000200, 0x1000, 15, lpc2138_layout, boot_2xxx}, + {"LPC2148 (500k)", "67305253", 0x40000200, 0x1000, 27, lpc2138_layout, boot_2xxx}, + {"LPC2194 (248k)", "50462483", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, + {"LPC2212 (248k)", "67239698", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, + {"LPC2214 (248k)", "100794131", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, + {"LPC2292 (248k)", "67239699", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, + {"LPC2294 (248k)", "84016915", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, + {"LPC2103 (32k)", "327441", 0x40000200, 0x1000, 8, lpc2138_layout, boot_2xxx}, + {"LPC2364 (128k)", "100924162", 0x40000200, 0x1000, 11, lpc2138_layout, boot_23xx}, + {"LPC2366 (256k)", "100924195", 0x40000200, 0x1000, 15, lpc2138_layout, boot_23xx}, + {"LPC2368 (500k)", "100924197", 0x40000200, 0x1000, 27, lpc2138_layout, boot_23xx}, + {"LPC2378 (500k)", "117702437", 0x40000200, 0x1000, 27, lpc2138_layout, boot_23xx}, + {"LPC2387 (500k)", "402716981", 0x40000200, 0x1000, 27, lpc2138_layout, boot_23xx}, + {"LPC2387 (500k)", "385941301", 0x40000200, 0x1000, 27, lpc2138_layout, boot_23xx}, + {"LPC2468 (500k)", "100925237", 0x40000200, 0x1000, 27, lpc2138_layout, boot_23xx}, + {NULL, NULL, 0, 0, 0, NULL} +}; + + + +char *lpc_return_strings[] = { + "CMD_SUCCESS", "INVALID_COMMAND", "SRC_ADDR_ERROR", "DST_ADDR_ERROR", + "SRC_ADDR_NOT_MAPPED", "DST_ADDR_NOT_MAPPED", "COUNT_ERROR", "INVALID_SECTOR", + "SECTOR_NOT_BLANK", "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION", "COMPARE_ERROR", + "BUSY", "PARAM_ERROR", "ADDR_ERROR", "ADDR_NOT_MAPPED", "CMD_LOCKED", + "INVALID_CODE", "INVALID_BAUD_RATE", "INVALID_STOP_BIT", + "CODE_READ_PROTECTION_ENABLED" +}; + diff --git a/boards/msba2-common/tools/src/chipinfo.h b/boards/msba2-common/tools/src/chipinfo.h new file mode 100644 index 0000000000..8c49593296 --- /dev/null +++ b/boards/msba2-common/tools/src/chipinfo.h @@ -0,0 +1,20 @@ +extern char *lpc_return_strings[]; + +struct sector_info_struct { // an array of + int address; // where each sector is located + int size; // and how big it is +}; + +struct chip_info_struct { + char *part_number; // human readable part number + char *id_string; // id string sent by "J" command + unsigned int ram_addr; // where to download into RAM + int chunk_size; // download to ram chunk size + int num_sector; // number of flash sectors + struct sector_info_struct *layout; // layout of sectors + const unsigned int *bootprog; // code that boots into user program (NULL = DTR/RTS only) +}; + +extern struct chip_info_struct chip_info[]; + + diff --git a/boards/msba2-common/tools/src/cksum_test.c b/boards/msba2-common/tools/src/cksum_test.c new file mode 100644 index 0000000000..facd6a1f3a --- /dev/null +++ b/boards/msba2-common/tools/src/cksum_test.c @@ -0,0 +1,85 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program 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 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + + +#include +#include +#include + +#include "uuencode.h" + + +unsigned int sum = 0; + + + +void cksum(const char *str) +{ + int num, i; + unsigned char data[256]; + + if (str == NULL) { + return; + } + + num = uudecode(str, data, sizeof(data)); + + for (i = 0; i < num; i++) { + sum += data[i]; + } + +} + + +int main() +{ + char buf[4096]; + + while (!feof(stdin)) { + fgets(buf, sizeof(buf), stdin); + + if (strcmp(buf, "\n") == 0) { + break; + } + + cksum(buf); + } + + printf("sum = %u\n", sum); + + return 0; +} + + + + + diff --git a/boards/msba2-common/tools/src/control_2xxx.c b/boards/msba2-common/tools/src/control_2xxx.c new file mode 100644 index 0000000000..581dd8e202 --- /dev/null +++ b/boards/msba2-common/tools/src/control_2xxx.c @@ -0,0 +1,40 @@ +#include "control_2xxx.h" + +#include +#include +#include + +#include "serial.h" + +void hard_reset_to_bootloader(void) +{ + /* Use this lines for flashing a node with interrupted DTR line */ + /* printf("Press Reset - confirm with anykey\n"); + getchar(); + */ + printf("Reset CPU (into bootloader)\r\n"); + set_rts(1); // RTS (ttl level) connects to P0.14 + /* the next two lines should be commented for the prepared node */ + set_dtr(1); // DTR (ttl level) connects to RST + send_break_signal(); // or break detect circuit to RST + usleep(75000); + /* Use this lines for flashing a node with interrupted DTR line */ + /* printf("Release Reset - confirm with anykey\n"); + getchar(); + */ + set_dtr(0); // allow the CPU to run: + set_baud(baud_rate); + set_rts(1); // set RTS again (as it has been reset by set_baudrate) + usleep(40000); +} + +void hard_reset_to_user_code(void) +{ + printf("Reset CPU (into user code)\r\n"); + set_rts(0); // RTS (ttl level) connects to P0.14 + set_dtr(1); // DTR (ttl level) connects to RST + send_break_signal(); // or break detect circuit to RST + usleep(75000); + set_dtr(0); // allow the CPU to run + usleep(40000); +} diff --git a/boards/msba2-common/tools/src/control_2xxx.h b/boards/msba2-common/tools/src/control_2xxx.h new file mode 100644 index 0000000000..e37e2e29d5 --- /dev/null +++ b/boards/msba2-common/tools/src/control_2xxx.h @@ -0,0 +1,8 @@ +#ifndef CONTROL_2XXXX_H +#define CONTROL_2XXXX_H + +void hard_reset_to_bootloader(void); +void hard_reset_to_user_code(void); + +#endif // ..._H + diff --git a/boards/msba2-common/tools/src/download.c b/boards/msba2-common/tools/src/download.c new file mode 100644 index 0000000000..c7aab543a8 --- /dev/null +++ b/boards/msba2-common/tools/src/download.c @@ -0,0 +1,1193 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program 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 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + +#include +#include +#include +#include +#include +#include + +#include "lpc2k_pgm.h" +#include "download.h" +#include "serial.h" +#include "ihex.h" +#include "uuencode.h" +//#include "gui.h" +#include "chipinfo.h" +#include "boot.h" +#include "control_2xxx.h" + + +// This will cause all bytes send and received to be printed as hex. +// It's a LOT of extra output, but useful for difficult debugging +// of what's _really_ being sent and received. +//#define PRINT_TX_RX_BYTES + + +static void download_main(int event); +static void xmit_cmd(const char *cmd, int max_time); +static void mk_valid_code_vector(void); +static unsigned int sum(unsigned char *data, int num); + + +static int state = 0; +static int reboot_only = 0; +static char expected_echo_buf[4096]; +static char *expected_echo_ptr = NULL; +static char parsed_response_buf[4096]; +static char *parsed_response_ptr = NULL; +static int response_timer = 0; + +extern int programming_done; +extern int done_program(int); + + +char *port_name = "/dev/ttyUSB1"; +char *file_name = ""; +char *crystal = "16"; + +/****************************************************************/ +/* */ +/* Main Download Section */ +/* */ +/****************************************************************/ + +// possible states +#define SYNC_1 1 +#define SYNC_2 2 +#define SYNC_3 3 +#define CHIP_ID 4 +#define UNLOCK 5 +#define BLANK_CHECK_SECTOR 6 +#define ERASE_PREPARE 7 +#define ERASE_SECTOR 8 +#define DOWNLOAD_CODE 9 +#define XMIT_DATA 10 +#define XMIT_CKSUM 11 +#define WRITE_PREPARE 12 +#define WRITE_SECTOR 13 +#define BOOT_HARD 14 +#define BOOT_SOFT 15 +#define BOOT_XMIT_DATA 16 +#define BOOT_XMIT_CKSUM 17 +#define BOOT_RUN_CODE 18 + + +// possible input values for "event" +#define BEGIN 1 +#define RESPONSE 2 +#define TIMEOUT 3 +#define RETRY 4 + + + + +int download_begin(char *file) +{ + int r; + + file_name = file; + + printf("\r\nEntering Bootloader Mode\r\n"); + hard_reset_to_bootloader(); + printf("Read \"%s\"", file_name); + r = read_intel_hex(file_name); + + if (r < 0) { + /* abort on ioerror */ + return 0; + } + + printf(": %d bytes\r\n", r); + mk_valid_code_vector(); + state = SYNC_1; + reboot_only = 0; + download_main(BEGIN); + return 1; +} + + +void soft_reboot_begin(void) +{ + printf("\r\nEntering Bootloader Mode\r\n"); + hard_reset_to_bootloader(); + state = SYNC_1; + reboot_only = 1; + download_main(BEGIN); +} + +static void mk_valid_code_vector(void) +{ + unsigned char b[4]; + unsigned int sum = 0; + int addr; + + for (addr = 0; addr < 0x20; addr += 4) { + if (addr != 0x14) { + get_ihex_data(addr, 4, b); + sum += (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)); + } + } + + sum ^= 0xFFFFFFFF; + sum++; + b[0] = (sum >> 0) & 255; + b[1] = (sum >> 8) & 255; + b[2] = (sum >> 16) & 255; + b[3] = (sum >> 24) & 255; + put_ihex_data(0x14, 4, b); +} + + +static unsigned int sum(unsigned char *data, int num) +{ + unsigned int sum = 0; + + while (num > 0) { + sum += *data++; + num--; + } + + return sum; +} + + +static int num_lines(const char *buf) +{ + const char *p; + int count = 0; + + p = buf; + + while (p != NULL) { + p = strstr(p, "\r\n"); + + if (p != NULL) { + count++; + p += 2; + } + } + + return count; +} + +void trim_crlf(char *str) +{ + char *p; + p = strstr(str, "\r\n"); + + if (p != NULL) { + *p = '\0'; + } +} + +void copy_boot_code_to_memory(struct chip_info_struct *chip) +{ + int i; + unsigned char c[4]; + + for (i = 0; i < chip->bootprog[0]; i++) { + c[3] = (chip->bootprog[i + 1] >> 24) & 255; + c[2] = (chip->bootprog[i + 1] >> 16) & 255; + c[1] = (chip->bootprog[i + 1] >> 8) & 255; + c[0] = (chip->bootprog[i + 1]) & 255; + put_ihex_data(i * 4, 4, c); + } +} + + +#define NO_SYNC_ERR "\r\n\ +ERROR: Unable to sync to baud rate.\r\n\ +This probably means the LPC2xxx chip is not connected\r\n\ +or it is not being reset, or P0.14 is not low after\r\n\ +reset to cause it to enter the bootloader mode.\r\n\r\n\ +Please check the serial port connection, make sure\r\n\ +pin P0.14 is low (or tied to RTS via RS-232 level\r\n\ +translator), and the chip has been reset (or reset\r\n\ +is tied to DTR via RS-232 level translator).\r\n" + +#define UNKNOWN_CHIP_ERROR "\r\n\ +Unknown chip ID: \"%s\".\r\n\r\n\ +Perhaps you have a new Philips LPC chip which does not\r\n\ +have its ID string and sector map defined in this program?\r\n\ +Please contact paul@pjrc.com. Please include an exact copy\r\n\ +of this message and any info about the chip and other\r\n\ +hardware you may be using. Thanks :-)\r\n" + + +static void download_main(int event) +{ + char buf[4096]; + unsigned char bytes[256]; + double xtal; + int n; + static unsigned int cksum; + static int retry = 0; + static int sector; // current sector we're doing + static int sector_offset; + static struct chip_info_struct *chip; // which chip + static int current_addr, num_to_xmit, linecount; + + + while (1) { + switch (state) { + case SYNC_1: + switch (event) { + case BEGIN: + printf("Attempting baud sync"); + retry = 0; + + case RETRY: + printf("."); + fflush(stdout); + xmit_cmd("?", 2); + return; + + case RESPONSE: + if (strcmp(parsed_response_buf, "Synchronized\r\n") == 0) { + //printf("response: sync'd\n"); + state = SYNC_2; + event = BEGIN; + break; + } + + if (strcmp(parsed_response_buf, "?") == 0) { + //printf("response: echo only\n"); + retry++; + + if (retry > 150) { + download_cancel(NO_SYNC_ERR); + return; + } + + event = RETRY; + usleep(30000); + break; + } + + snprintf(buf, sizeof(buf), "Unexpected response to sync, \"%s\"", + parsed_response_buf); + download_cancel(buf); + return; + + case TIMEOUT: + if (retry < 100) { + retry++; + event = RETRY; + break; + } + + download_cancel(NO_SYNC_ERR); + return; + } + + break; + + + case SYNC_2: + switch (event) { + case BEGIN: + xmit_cmd("Synchronized\r\n", 3); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "OK\r\n") == 0) { + state = SYNC_3; + event = BEGIN; + break; + } + else { + snprintf(buf, sizeof(buf), "Unable to complete baud sync, %s", + parsed_response_buf); + download_cancel(buf); + return; + } + + return; + + case TIMEOUT: + download_cancel("No response to complete baud sync"); + return; + } + + break; + + + case SYNC_3: + switch (event) { + case BEGIN: + if (sscanf(crystal, "%lf", &xtal) != 1) { + printf("\r\n"); + download_cancel("Crystal frequency is required for 3rd step of baud rate sync"); + return; + } + + if (xtal < 10.0 || xtal > 25.0) { + printf("\r\n"); + printf("Warning: crystal frequency out of range (10.0 to 25.0), continuing anyway! (hope you know what you're doing)\r\n"); + } + + snprintf(buf, sizeof(buf), "%d\r\n", (int)(xtal * 1000.0 + 0.5)); + xmit_cmd(buf, 3); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "OK\r\n") == 0) { + printf("Baud sync sucessful\r\n"); + state = CHIP_ID; + event = BEGIN; + break; + } + else { + snprintf(buf, sizeof(buf), "wrong response to crystal: %s", + parsed_response_buf); + download_cancel(buf); + return; + } + + return; + + case TIMEOUT: + download_cancel("No response to crystal speed"); + return; + } + + break; + + + case CHIP_ID: + switch (event) { + case BEGIN: + xmit_cmd("J\r\n", 3); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) < 2) { + return; + } + + if (strncmp(parsed_response_buf, "0\r\n", 3) == 0) { + trim_crlf(parsed_response_buf + 3); + + for (chip = chip_info; chip->part_number != NULL; chip++) { + if (strcmp(parsed_response_buf + 3, chip->id_string) == 0) { + break; + } + } + + if (chip->part_number == NULL) { + snprintf(buf, sizeof(buf), UNKNOWN_CHIP_ERROR, + parsed_response_buf + 3); + download_cancel(buf); + break; + } + + printf("Found chip: \"%s\"\r\n", chip->part_number); + //download_cancel("stop here, remove this later"); + state = UNLOCK; + event = BEGIN; + break; + } + else { + snprintf(buf, sizeof(buf), "wrong response to ID: %s", + parsed_response_buf); + download_cancel(buf); + return; + } + + return; + + case TIMEOUT: + download_cancel("No response to unlock command"); + return; + } + + break; + + + case UNLOCK: + switch (event) { + case BEGIN: + xmit_cmd("U 23130\r\n", 3); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + printf("Device Unlocked\r\n"); + + if (reboot_only) { + state = BOOT_SOFT; + } + else { + state = BLANK_CHECK_SECTOR; + printf("Erasing....\r\n"); + sector = 0; + } + + event = BEGIN; + break; + } + else { + snprintf(buf, sizeof(buf), "wrong response unlock: %s", + parsed_response_buf); + download_cancel(buf); + return; + } + + return; + + case TIMEOUT: + download_cancel("No response to unlock command"); + return; + } + + break; + + + case BLANK_CHECK_SECTOR: + switch (event) { + case BEGIN: + if (sector >= chip->num_sector) { + printf("Programming....\r\n"); + state = DOWNLOAD_CODE; + sector = sector_offset = 0; + event = BEGIN; + break; + } + + printf(" Sector %2d: ", sector); + fflush(stdout); + + if (!bytes_within_range(chip->layout[sector].address, + chip->layout[sector].address + chip->layout[sector].size - 1)) { + printf("not used\r\n"); + sector++; + break; + } + + if (sector == 0) { + // can't blank check sector 0, so always erase it + state = ERASE_PREPARE; + break; + } + + snprintf(buf, sizeof(buf), "I %d %d\r\n", sector, sector); + xmit_cmd(buf, 5); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) == 1 && + strcmp(parsed_response_buf, "0\r\n") == 0) { + printf("already blank\r\n"); + sector++; + event = BEGIN; + break; + } + else { + if (num_lines(parsed_response_buf) < 3) { + return; + } + + state = ERASE_PREPARE; + event = BEGIN; + break; + } + + case TIMEOUT: + download_cancel("No response to blank check"); + return; + } + + break; + + + + case ERASE_PREPARE: + switch (event) { + case BEGIN: + printf("prep, "); + fflush(stdout); + snprintf(buf, sizeof(buf), "P %d %d\r\n", sector, sector); + xmit_cmd(buf, 8); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + state = ERASE_SECTOR; + event = BEGIN; + break; + } + else { + download_cancel("Unable to prep for write"); + return; + } + + case TIMEOUT: + download_cancel("No response"); + return; + } + + break; + + + + case ERASE_SECTOR: + switch (event) { + case BEGIN: + printf("erase... "); + fflush(stdout); + snprintf(buf, sizeof(buf), "E %d %d\r\n", sector, sector); + xmit_cmd(buf, 25); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) < 1) { + return; + } + + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + printf("Ok\r\n"); + sector++; + state = BLANK_CHECK_SECTOR; + event = BEGIN; + break; + } + else { + printf("Error\r\n"); + download_cancel("Unable to erase flash"); + return; + } + + case TIMEOUT: + download_cancel("No response"); + return; + } + + break; + + + + case DOWNLOAD_CODE: + switch (event) { + case BEGIN: + if (sector >= chip->num_sector) { + state = BOOT_HARD; + sector = 0; + event = BEGIN; + break; + } + + printf(" Sector %2d (0x%08X-0x%08X): ", sector, + chip->layout[sector].address + sector_offset, + chip->layout[sector].address + sector_offset + chip->chunk_size - 1); + fflush(stdout); + + if (!bytes_within_range(chip->layout[sector].address + sector_offset, + chip->layout[sector].address + sector_offset + chip->chunk_size - 1)) { + printf("not used\r\n"); + sector_offset += chip->chunk_size; + + if (sector_offset >= chip->layout[sector].size) { + sector_offset = 0; + sector++; + } + + break; + } + + snprintf(buf, sizeof(buf), "W %d %d\r\n", chip->ram_addr, chip->chunk_size); + xmit_cmd(buf, 4); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + state = XMIT_DATA; + printf("xmit"); + current_addr = chip->layout[sector].address + sector_offset; + num_to_xmit = chip->chunk_size; + linecount = 0; + cksum = 0; + event = BEGIN; + break; + } + else { + download_cancel("can't xmit to ram"); + return; + } + + case TIMEOUT: + download_cancel("No response"); + return; + } + + break; + + + case XMIT_DATA: + switch (event) { + case BEGIN: + n = num_to_xmit; + + if (n > 45) { + n = 45; + } + + get_ihex_data(current_addr, n, bytes); + cksum += sum(bytes, n); + uuencode(buf, bytes, n); + current_addr += n; + num_to_xmit -= n; + linecount++; + xmit_cmd(buf, 5); + write_serial_port("\r\n", 2); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "\r\n") == 0) { + if (linecount >= 20 || num_to_xmit <= 0) { + state = XMIT_CKSUM; + } + + event = BEGIN; + break; + } + else { + download_cancel("data xmit did not echo"); + return; + } + + case TIMEOUT: + download_cancel("No response"); + return; + } + + break; + + + case XMIT_CKSUM: + switch (event) { + case BEGIN: + snprintf(buf, sizeof(buf), "%d\r\n", cksum); + xmit_cmd(buf, 3); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "OK\r\n") == 0) { + if (num_to_xmit > 0) { + printf("."); + fflush(stdout); + state = XMIT_DATA; + event = BEGIN; + linecount = 0; + cksum = 0; + break; + } + + state = WRITE_PREPARE; + event = BEGIN; + break; + } + else { + download_cancel("bad checksum"); + return; + } + + case TIMEOUT: + download_cancel("No response"); + return; + } + + break; + + + case WRITE_PREPARE: + switch (event) { + case BEGIN: + printf("prep, "); + fflush(stdout); + snprintf(buf, sizeof(buf), "P %d %d\r\n", sector, sector); + xmit_cmd(buf, 5); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + state = WRITE_SECTOR; + event = BEGIN; + break; + } + else { + download_cancel("Unable to prep for write"); + return; + } + + case TIMEOUT: + download_cancel("No response"); + return; + } + + break; + + + case WRITE_SECTOR: + switch (event) { + case BEGIN: + printf("write, "); + fflush(stdout); + snprintf(buf, sizeof(buf), "C %d %d %d\r\n", + chip->layout[sector].address + sector_offset, + chip->ram_addr, chip->chunk_size); + xmit_cmd(buf, 5); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + printf("Ok\r\n"); + sector_offset += chip->chunk_size; + + if (sector_offset >= chip->layout[sector].size) { + sector_offset = 0; + sector++; + } + + state = DOWNLOAD_CODE; + event = BEGIN; + } + else { + download_cancel("Unable to prep for write"); + return; + } + + break; + + case TIMEOUT: + download_cancel("No response"); + return; + } + + break; + + + case BOOT_HARD: + // if (chip->bootprog) { + // state = BOOT_SOFT; + // break; + // } else { + printf("Booting (hardware reset)...\r\n\r\n"); + hard_reset_to_user_code(); + done_program(0); + return; + // } + + case BOOT_SOFT: + switch (event) { + case BEGIN: + printf("Booting (soft jump)...\r\n"); + printf("loading jump code\r\n"); + // would be nice if we could simply jump to the user's code, but + // Philips didn't think of that. The interrupt vector table stays + // mapped to the bootloader, so jumping to zero only runs the + // bootloader again. Intead, we need to download a tiny ARM + // program that reconfigures the hardware and then jumps to zero. + //snprintf(buf, sizeof(buf), "G %d A\r\n", 0); + snprintf(buf, sizeof(buf), "W %d %d\r\n", chip->ram_addr, chip->bootprog[0] * 4); + xmit_cmd(buf, 4); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) < 1) { + return; + } + + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + current_addr = 0; + num_to_xmit = chip->bootprog[0] * 4; + copy_boot_code_to_memory(chip); + linecount = 0; + cksum = 0; + state = BOOT_XMIT_DATA; + event = BEGIN; + } + else { + download_cancel("can't xmit to ram"); + return; + } + + break; + + case TIMEOUT: + download_cancel("No response"); + return; + } + + break; + + + case BOOT_XMIT_DATA: + switch (event) { + case BEGIN: + n = num_to_xmit; + + if (n > 45) { + n = 45; + } + + get_ihex_data(current_addr, n, bytes); + cksum += sum(bytes, n); + uuencode(buf, bytes, n); + current_addr += n; + num_to_xmit -= n; + linecount++; + //printf("send: %s\r\n", buf); + xmit_cmd(buf, 5); + write_serial_port("\r\n", 2); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "\r\n") == 0) { + if (linecount >= 20 || num_to_xmit <= 0) { + state = BOOT_XMIT_CKSUM; + } + + event = BEGIN; + break; + } + else { + download_cancel("data xmit did not echo"); + return; + } + + case TIMEOUT: + download_cancel("No response"); + return; + } + + break; + + + case BOOT_XMIT_CKSUM: + switch (event) { + case BEGIN: + snprintf(buf, sizeof(buf), "%d\r\n", cksum); + //printf("send: %s", buf); + xmit_cmd(buf, 3); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) { + return; + } + + if (strcmp(parsed_response_buf, "OK\r\n") == 0) { + if (num_to_xmit > 0) { + printf("."); + fflush(stdout); + state = BOOT_XMIT_DATA; + event = BEGIN; + linecount = 0; + cksum = 0; + break; + } + + state = BOOT_RUN_CODE; + event = BEGIN; + break; + } + else { + download_cancel("bad checksum"); + return; + } + + case TIMEOUT: + download_cancel("No response"); + return; + } + + break; + + + case BOOT_RUN_CODE: + switch (event) { + case BEGIN: + printf("jumping now!\r\n"); + snprintf(buf, sizeof(buf), "G %d A\r\n", chip->ram_addr); + xmit_cmd(buf, 4); + return; + + case RESPONSE: + if (num_lines(parsed_response_buf) < 1) { + return; + } + + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + done_program(0); + return; + } + else { + printf("response = %s", parsed_response_buf); + download_cancel("couldn't run program"); + return; + } + + break; + + case TIMEOUT: + done_program(0); + return; + // Philips user name says it responds, but it does not. + // It seems to just immediately jump to the code without + // any "0" response. + //download_cancel("No response"); return; + } + + break; + + + + default: + snprintf(buf, sizeof(buf), "unknown state %d\r\n", state); + download_cancel(buf); + return; + } + } +} + + +void download_cancel(const char *mesg) +{ + printf("\r\nDownload Canceled"); + + if (mesg && *mesg) { + printf(": %s", mesg); + } + + printf("\r\n"); + // need to do some cleanup for various states??? + done_program(1); +} + + +/****************************************************************/ +/* */ +/* Transmit Commands to Bootloader */ +/* */ +/****************************************************************/ + + + +static void xmit_cmd(const char *cmd, int max_time) +{ + int len; + + if (cmd == NULL || *cmd == '\0') { + return; + } + + len = strlen(cmd); + +#ifdef PRINT_TX_RX_BYTES + printf("tx %d bytes: %s\n", len, cmd); +#endif + + input_flush_serial_port(); + + write_serial_port(cmd, len); + + snprintf(expected_echo_buf, sizeof(expected_echo_buf), "%s", cmd); + + if (state == SYNC_1) { + // special case, baud sync doesn't echo + expected_echo_buf[0] = '\0'; + } + + expected_echo_ptr = expected_echo_buf; + parsed_response_ptr = parsed_response_buf; + + response_timer = max_time; +} + + + +/****************************************************************/ +/* */ +/* Handlers that respond to input */ +/* */ +/****************************************************************/ + + +/* +Whenever the main gtk event loop detects more input has arrived from the +serial port, and we're in the process of a download, it calls here to +hand off the data. We're supposed to match it up to the echo buffer, +and then store it into the parsed response buffer and if it looks like +this might be a complete response, call download_main with a response +event. +*/ +void download_rx_port(const unsigned char *buf, int num) +{ + int i = 0; + + if (num <= 0) { + return; + } + + // echo the data + //write(term_fd, buf, num); + +#ifdef PRINT_TX_RX_BYTES + printf("rx %d bytes:", num); + + for (i = 0; i < num; i++) { + printf(" %02X", *(buf + i)); + } + + printf("\r\n"); +#endif + + // ignore extra incoming garbage we didn't expect + if (expected_echo_ptr == NULL) { + return; + } + + // special case, echo of '?' during unsuccessful sync + if (state == SYNC_1 && num == 1 && buf[0] == '?') { + *parsed_response_ptr++ = '?'; + *parsed_response_ptr = '\0'; + response_timer = 0; + download_main(RESPONSE); + return; + } + + // parse it + for (i = 0; i < num; i++) { + // if we're still expecting the echo, gobble it up + if (*expected_echo_ptr) { + if (buf[i] != *expected_echo_ptr) { +#ifdef PRINT_TX_RX_BYTES + printf(" "); +#endif + // ignore incorrect echo (will timeout) + expected_echo_ptr = NULL; + return; + } + + expected_echo_ptr++; + continue; + } + + // store this into a parsed response buffer + *parsed_response_ptr++ = buf[i]; + } + + // if the last two characters of the response are "\r\n", + // then it's likely we've got a complete response. + *parsed_response_ptr = '\0'; + + if (parsed_response_ptr > parsed_response_buf + 1 + && *(parsed_response_ptr - 2) == '\r' + && *(parsed_response_ptr - 1) == '\n') { + //response_timer = 0; + download_main(RESPONSE); + } +} + + + +/* +During a download, this is supposed to get called at 100 Hz. Whenever +something is transmitted and we expect a response, the response_timer +is initialized to the maximum time we will wait. +*/ +void download_timer(void) +{ + if (response_timer > 0) { + response_timer--; + + if (response_timer == 0) { + expected_echo_ptr = NULL; + download_main(TIMEOUT); + } + } +} + +/* +During a download, all input the user types into the terminal is sent +to this function, instead of passing it to xterm for display +*/ +void download_rx_term(const unsigned char *buf, int num) +{ + // discard anything the user types into the terminal + // while we are in the middle of downloading. Maybe + // we should look for CTRL-C and abort?? +} + + diff --git a/boards/msba2-common/tools/src/download.h b/boards/msba2-common/tools/src/download.h new file mode 100644 index 0000000000..b6b961049f --- /dev/null +++ b/boards/msba2-common/tools/src/download.h @@ -0,0 +1,8 @@ +extern int download_begin(char *file); +extern void soft_reboot_begin(void); +extern void hard_reset_to_bootloader(void); +extern void hard_reset_to_user_code(void); +extern void download_cancel(const char *mesg); +extern void download_rx_term(const unsigned char *buf, int num); +extern void download_rx_port(const unsigned char *buf, int num); +extern void download_timer(void); diff --git a/boards/msba2-common/tools/src/gui.c b/boards/msba2-common/tools/src/gui.c new file mode 100644 index 0000000000..0d4b18d8da --- /dev/null +++ b/boards/msba2-common/tools/src/gui.c @@ -0,0 +1,422 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program 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 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gui.h" +#include "settings.h" +#include "serial.h" +#include "lpc2k_pgm.h" +#include "download.h" + + +static GtkWidget *firmware_label, *firmware_entry, *program_button; +static GtkWidget *port_label, *port_entry, *baud_label, *baud_combo; +static GtkWidget *crystal_label, *crystal_entry, *mhz_label; +static GtkWidget *reboot_button, *bootloader_button, *quit_button; +static GtkWidget *line1_hbox, *line2_hbox, *line3_hbox, *line4_hbox; +static GtkWidget *main_vbox, *main_window; + +static int port_timeout = 0; +static int baud_timeout = 0; +static int download_in_progress = 0; + +gint do_quit(GtkWidget *widget, gpointer *data) +{ + gtk_main_quit(); + return FALSE; +} + +gint do_program(GtkWidget *widget, gpointer *data) +{ + if (download_in_progress) { + // error... not supposed to get here + gtk_widget_set_sensitive(program_button, FALSE); + return FALSE; + } + + download_in_progress = 1; + gtk_widget_set_sensitive(program_button, FALSE); + gtk_widget_set_sensitive(reboot_button, FALSE); + gtk_widget_set_sensitive(bootloader_button, TRUE); + download_begin(); + return FALSE; +} + +int file_exists(const char *filename) +{ + struct stat file_stats; + int r; + + r = stat(filename, &file_stats); + + if (r != 0) { + return 0; + } + + if (!S_ISREG(file_stats.st_mode)) { + return 0; + } + + return 1; +} + +void done_program(int still_in_bootloader) +{ + download_in_progress = 0; + + if (file_exists(gtk_entry_get_text(GTK_ENTRY(firmware_entry)))) { + gtk_widget_set_sensitive(program_button, TRUE); + } + else { + gtk_widget_set_sensitive(program_button, FALSE); + } + + gtk_widget_set_sensitive(bootloader_button, TRUE); + gtk_widget_set_sensitive(reboot_button, TRUE); +} + +gint do_reboot(GtkWidget *widget, gpointer *data) +{ + if (download_in_progress) { + download_cancel(NULL); + gtk_widget_set_sensitive(program_button, FALSE); + gtk_widget_set_sensitive(reboot_button, FALSE); + gtk_widget_set_sensitive(bootloader_button, FALSE); + } + + gtk_widget_set_sensitive(program_button, FALSE); + gtk_widget_set_sensitive(reboot_button, FALSE); + gtk_widget_set_sensitive(bootloader_button, FALSE); + + hard_reset_to_user_code(); + +#if 0 + download_in_progress = 1; + soft_reboot_begin(); +#endif + + if (file_exists(gtk_entry_get_text(GTK_ENTRY(firmware_entry)))) { + gtk_widget_set_sensitive(program_button, TRUE); + } + else { + gtk_widget_set_sensitive(program_button, FALSE); + } + + gtk_widget_set_sensitive(bootloader_button, TRUE); + return FALSE; +} + +gint do_bootloader(GtkWidget *widget, gpointer *data) +{ + if (download_in_progress) { + download_cancel(NULL); + gtk_widget_set_sensitive(program_button, FALSE); + gtk_widget_set_sensitive(reboot_button, FALSE); + gtk_widget_set_sensitive(bootloader_button, FALSE); + } + + hard_reset_to_bootloader(); + + if (file_exists(gtk_entry_get_text(GTK_ENTRY(firmware_entry)))) { + gtk_widget_set_sensitive(program_button, TRUE); + } + else { + gtk_widget_set_sensitive(program_button, FALSE); + } + + gtk_widget_set_sensitive(reboot_button, TRUE); + gtk_widget_set_sensitive(bootloader_button, TRUE); + return FALSE; +} + +gint do_new_port(GtkWidget *widget, gpointer *data) +{ + port_timeout = 12; + return FALSE; +} + +gint do_new_baud(GtkWidget *widget, gpointer *data) +{ + baud_timeout = 7; + return FALSE; +} + +gint do_new_file(GtkWidget *widget, gpointer *data) +{ + const char *filename; + + filename = gtk_entry_get_text(GTK_ENTRY(firmware_entry)); + + if (file_exists(filename)) { + new_file_setting(filename); + + if (download_in_progress) { + gtk_widget_set_sensitive(program_button, FALSE); + } + else { + gtk_widget_set_sensitive(program_button, TRUE); + } + } + else { + gtk_widget_set_sensitive(program_button, FALSE); + } + + return FALSE; +} + +gint do_new_crystal(GtkWidget *widget, gpointer *data) +{ + const char *xtal; + + xtal = gtk_entry_get_text(GTK_ENTRY(crystal_entry)); + new_crystal_setting(xtal); + return FALSE; +} + + +gint do_timer(gpointer data) +{ + if (port_timeout && --port_timeout == 0) { + open_serial_port(gtk_entry_get_text(GTK_ENTRY(port_entry))); + } + + if (baud_timeout && --baud_timeout == 0) { + change_baud(gtk_entry_get_text(GTK_ENTRY( + GTK_COMBO(baud_combo)->entry))); + } + + if (download_in_progress) { + download_timer(); + } + + return TRUE; +} + +void do_term_input(gpointer data, int fd, GdkInputCondition cond) +{ + char buf[256]; + int num, flags; + + flags = fcntl(term_fd, F_GETFL); + fcntl(term_fd, F_SETFL, flags | O_NONBLOCK); + num = read(term_fd, buf, sizeof(buf)); + fcntl(term_fd, F_SETFL, flags); + + if (num > 0) { + if (download_in_progress) { + download_rx_term(buf, num); + } + else { + write_serial_port(buf, num); + } + } +} + +void do_port_input(gpointer data, int fd, GdkInputCondition cond) +{ + char buf[256]; + int num; + + num = read_serial_port_nb((unsigned char *)buf, sizeof(buf)); + + if (num > 0) { + if (download_in_progress) { + download_rx_port(buf, num); + } + else { + write(term_fd, buf, num); + } + } +} + + +void run_gui(void) +{ + gtk_signal_connect(GTK_OBJECT(main_window), "delete_event", + GTK_SIGNAL_FUNC(do_quit), NULL); + gtk_signal_connect(GTK_OBJECT(quit_button), "pressed", + GTK_SIGNAL_FUNC(do_quit), NULL); + gtk_signal_connect(GTK_OBJECT(port_entry), "changed", + GTK_SIGNAL_FUNC(do_new_port), NULL); + gtk_signal_connect(GTK_OBJECT(GTK_COMBO(baud_combo)->entry), "changed", + GTK_SIGNAL_FUNC(do_new_baud), NULL); + gtk_signal_connect(GTK_OBJECT(firmware_entry), "changed", + GTK_SIGNAL_FUNC(do_new_file), NULL); + gtk_signal_connect(GTK_OBJECT(crystal_entry), "changed", + GTK_SIGNAL_FUNC(do_new_crystal), NULL); + gtk_signal_connect(GTK_OBJECT(program_button), "pressed", + GTK_SIGNAL_FUNC(do_program), NULL); + gtk_signal_connect(GTK_OBJECT(reboot_button), "pressed", + GTK_SIGNAL_FUNC(do_reboot), NULL); + gtk_signal_connect(GTK_OBJECT(bootloader_button), "pressed", + GTK_SIGNAL_FUNC(do_bootloader), NULL); + + gtk_timeout_add(100, do_timer, NULL); + gdk_input_add(term_fd, GDK_INPUT_READ, do_term_input, NULL); + gdk_input_add(serial_port_fd(), GDK_INPUT_READ, do_port_input, NULL); + + gtk_main(); +} + + +void create_window(int *argc, char ***argv) +{ + GList *gtk_baud_list = NULL; + int i; + + gtk_init(argc, argv); + + firmware_label = gtk_label_new("Firmware:"); + gtk_label_set_justify(GTK_LABEL(firmware_label), GTK_JUSTIFY_RIGHT); + gtk_widget_show(firmware_label); + + firmware_entry = gtk_entry_new(); + gtk_widget_set_usize(firmware_entry, 110, 0); + gtk_entry_set_text(GTK_ENTRY(firmware_entry), file_setting()); + gtk_widget_show(firmware_entry); + + program_button = gtk_button_new_with_label("Program Now"); + + if (file_exists(file_setting())) { + gtk_widget_set_sensitive(program_button, TRUE); + } + else { + gtk_widget_set_sensitive(program_button, FALSE); + } + + gtk_widget_show(program_button); + + line1_hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(line1_hbox), firmware_label, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(line1_hbox), firmware_entry, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(line1_hbox), program_button, FALSE, FALSE, 2); + gtk_widget_show(line1_hbox); + + + port_label = gtk_label_new("Port:"); + gtk_label_set_justify(GTK_LABEL(port_label), GTK_JUSTIFY_RIGHT); + gtk_widget_show(port_label); + + port_entry = gtk_entry_new(); + gtk_widget_set_usize(port_entry, 80, 0); + gtk_entry_set_text(GTK_ENTRY(port_entry), port_setting()); + open_serial_port(port_setting()); + gtk_widget_show(port_entry); + + baud_label = gtk_label_new("Baud:"); + gtk_label_set_justify(GTK_LABEL(baud_label), GTK_JUSTIFY_RIGHT); + gtk_widget_show(baud_label); + + baud_combo = gtk_combo_new(); + + for (i = 0; baud_list[i] != NULL; i++) { + gtk_baud_list = g_list_append(gtk_baud_list, baud_list[i]); + } + + gtk_combo_set_popdown_strings(GTK_COMBO(baud_combo), gtk_baud_list); + gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(baud_combo)->entry), FALSE); + gtk_widget_set_usize(baud_combo, 75, 0); + + for (i = 0; baud_list[i] != NULL; i++) { + if (strcmp(baud_list[i], baud_setting()) == 0) { + gtk_list_select_item(GTK_LIST(GTK_COMBO(baud_combo)->list), i); + break; + } + } + + gtk_widget_show(baud_combo); + + line2_hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(line2_hbox), port_label, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(line2_hbox), port_entry, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(line2_hbox), baud_label, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(line2_hbox), baud_combo, FALSE, FALSE, 2); + gtk_widget_show(line2_hbox); + + + crystal_label = gtk_label_new("Crystal:"); + gtk_label_set_justify(GTK_LABEL(crystal_label), GTK_JUSTIFY_RIGHT); + gtk_widget_show(crystal_label); + + crystal_entry = gtk_entry_new(); + gtk_widget_set_usize(crystal_entry, 80, 0); + gtk_entry_set_text(GTK_ENTRY(crystal_entry), crystal_setting()); + gtk_widget_show(crystal_entry); + + mhz_label = gtk_label_new("(MHz)"); + gtk_label_set_justify(GTK_LABEL(mhz_label), GTK_JUSTIFY_LEFT); + gtk_widget_show(mhz_label); + + line3_hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(line3_hbox), crystal_label, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(line3_hbox), crystal_entry, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(line3_hbox), mhz_label, FALSE, FALSE, 2); + gtk_widget_show(line3_hbox); + + + reboot_button = gtk_button_new_with_label("Reboot"); + gtk_widget_set_sensitive(reboot_button, TRUE); + gtk_widget_show(reboot_button); + + bootloader_button = gtk_button_new_with_label("Booloader"); + gtk_widget_show(bootloader_button); + + quit_button = gtk_button_new_with_label("Quit"); + gtk_widget_show(quit_button); + + line4_hbox = gtk_hbox_new(TRUE, 2); + gtk_box_pack_start(GTK_BOX(line4_hbox), reboot_button, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(line4_hbox), bootloader_button, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(line4_hbox), quit_button, TRUE, TRUE, 2); + gtk_widget_show(line4_hbox); + + main_vbox = gtk_vbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(main_vbox), line1_hbox, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(main_vbox), line2_hbox, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(main_vbox), line3_hbox, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(main_vbox), line4_hbox, TRUE, TRUE, 2); + gtk_widget_show(main_vbox); + + main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_add(GTK_CONTAINER(main_window), main_vbox); + gtk_widget_show(main_window); +} diff --git a/boards/msba2-common/tools/src/gui.h b/boards/msba2-common/tools/src/gui.h new file mode 100644 index 0000000000..fadde6db6d --- /dev/null +++ b/boards/msba2-common/tools/src/gui.h @@ -0,0 +1,3 @@ +extern void create_window(int *argc, char ***argv); +extern void run_gui(void); +extern void done_program(int still_in_bootloader); diff --git a/boards/msba2-common/tools/src/ihex.c b/boards/msba2-common/tools/src/ihex.c new file mode 100644 index 0000000000..d5865a569a --- /dev/null +++ b/boards/msba2-common/tools/src/ihex.c @@ -0,0 +1,314 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program 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 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + +#include +#include + + +// the maximum flash image size we can support +// chips with larger memory may be used, but only this +// much intel-hex data can be loaded into memory! +#define MAX_MEMORY_SIZE 0x80000 + + +#include "ihex.h" + + +static unsigned char firmware_image[MAX_MEMORY_SIZE]; +static unsigned char firmware_mask[MAX_MEMORY_SIZE]; +static int end_record_seen = 0; +static int byte_count; +static unsigned int extended_addr = 0; + + +static int parse_hex_line(char *line); + + +/****************************************************************/ +/* */ +/* Read Intel Hex File */ +/* */ +/****************************************************************/ + + + +int read_intel_hex(const char *filename) +{ + FILE *fp; + int i, lineno = 0; + char buf[1024]; + + byte_count = 0; + end_record_seen = 0; + + for (i = 0; i < MAX_MEMORY_SIZE; i++) { + firmware_image[i] = 0xFF; + firmware_mask[i] = 0; + } + + extended_addr = 0; + + fp = fopen(filename, "r"); + + if (fp == NULL) { + printf("Unable to read file %s\n", filename); + return -1; + } + + while (!feof(fp)) { + *buf = '\0'; + fgets(buf, sizeof(buf), fp); + lineno++; + + if (*buf) { + if (parse_hex_line(buf) == 0) { + printf("Warning, parse error line %d\n", lineno); + return -2; + } + } + + if (end_record_seen) { + break; + } + + if (feof(stdin)) { + break; + } + } + + fclose(fp); + return byte_count; +} + + +/* from ihex.c, at http://www.pjrc.com/tech/8051/pm2_docs/intel-hex.html */ + +/* parses a line of intel hex code, stores the data in bytes[] */ +/* and the beginning address in addr, and returns a 1 if the */ +/* line was valid, or a 0 if an error occured. The variable */ +/* num gets the number of bytes that were stored into bytes[] */ + + +int +parse_hex_line(char *line) +{ + int addr, code, num; + int sum, len, cksum, i; + char *ptr; + + num = 0; + + if (line[0] != ':') { + return 0; + } + + if (strlen(line) < 11) { + return 0; + } + + ptr = line + 1; + + if (!sscanf(ptr, "%02x", &len)) { + return 0; + } + + ptr += 2; + + if (strlen(line) < (11 + (len * 2))) { + return 0; + } + + if (!sscanf(ptr, "%04x", &addr)) { + return 0; + } + + ptr += 4; + + /* printf("Line: length=%d Addr=%d\n", len, addr); */ + if (!sscanf(ptr, "%02x", &code)) { + return 0; + } + + if (addr + extended_addr + len >= MAX_MEMORY_SIZE) { + return 0; + } + + ptr += 2; + sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255); + + if (code != 0) { + if (code == 1) { + end_record_seen = 1; + return 1; + } + + if (code == 2 && len == 2) { + if (!sscanf(ptr, "%04x", &i)) { + return 1; + } + + ptr += 4; + sum += ((i >> 8) & 255) + (i & 255); + + if (!sscanf(ptr, "%02x", &cksum)) { + return 1; + } + + if (((sum & 255) + (cksum & 255)) & 255) { + return 1; + } + + extended_addr = i << 4; + //printf("ext addr = %05X\n", extended_addr); + } + + if (code == 4 && len == 2) { + if (!sscanf(ptr, "%04x", &i)) { + return 1; + } + + ptr += 4; + sum += ((i >> 8) & 255) + (i & 255); + + if (!sscanf(ptr, "%02x", &cksum)) { + return 1; + } + + if (((sum & 255) + (cksum & 255)) & 255) { + return 1; + } + + extended_addr = i << 16; + //printf("ext addr = %08X\n", extended_addr); + } + + return 1; // non-data line + } + + byte_count += len; + + while (num != len) { + if (sscanf(ptr, "%02x", &i) != 1) { + return 0; + } + + i &= 255; + firmware_image[addr + extended_addr + num] = i; + firmware_mask[addr + extended_addr + num] = 1; + ptr += 2; + sum += i; + (num)++; + + if (num >= 256) { + return 0; + } + } + + if (!sscanf(ptr, "%02x", &cksum)) { + return 0; + } + + if (((sum & 255) + (cksum & 255)) & 255) { + return 0; /* checksum error */ + } + + return 1; +} + + +int bytes_within_range(int begin, int end) +{ + int i; + + if (begin < 0 || begin >= MAX_MEMORY_SIZE || + end < 0 || end >= MAX_MEMORY_SIZE) { + return 0; + } + + for (i = begin; i <= end; i++) { + if (firmware_mask[i]) { + return 1; + } + } + + return 0; +} + +void get_ihex_data(int addr, int len, unsigned char *bytes) +{ + int i; + + if (addr < 0 || len < 0 || addr + len >= MAX_MEMORY_SIZE) { + for (i = 0; i < len; i++) { + bytes[i] = 255; + } + + return; + } + + for (i = 0; i < len; i++) { + if (firmware_mask[addr]) { + bytes[i] = firmware_image[addr]; + } + else { + bytes[i] = 255; + } + + addr++; + } +} + +void put_ihex_data(int addr, int len, const unsigned char *bytes) +{ + int i; + + if (addr < 0 || len < 0 || addr + len >= MAX_MEMORY_SIZE) { + return; + } + + for (i = 0; i < len; i++) { + firmware_image[addr] = bytes[i]; + firmware_mask[addr] = 1; + addr++; + } +} + + + + + + + + + + + diff --git a/boards/msba2-common/tools/src/ihex.h b/boards/msba2-common/tools/src/ihex.h new file mode 100644 index 0000000000..f6892381f5 --- /dev/null +++ b/boards/msba2-common/tools/src/ihex.h @@ -0,0 +1,7 @@ +extern int read_intel_hex(const char *filename); +extern int bytes_within_range(int begin, int end); +extern void get_ihex_data(int addr, int len, unsigned char *bytes); +extern void put_ihex_data(int addr, int len, const unsigned char *bytes); + + + diff --git a/boards/msba2-common/tools/src/lpc2k_pgm.c b/boards/msba2-common/tools/src/lpc2k_pgm.c new file mode 100644 index 0000000000..8c74429887 --- /dev/null +++ b/boards/msba2-common/tools/src/lpc2k_pgm.c @@ -0,0 +1,101 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program 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 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lpc2k_pgm.h" +#include "serial.h" +#include "download.h" + +int programming_done = 0; + +int done_program(int i) +{ + printf("Programming done.\n"); + programming_done = 1; + return 0; +} + +void handle_port_input() +{ + unsigned char buf[256]; + int num; + + num = read_serial_port(buf, sizeof(buf)); + + if (num > 0) { + download_rx_port(buf, num); + } +} + +void usage() +{ + printf("usage: lpc2k_pgm \n"); +} + +int main(int argc, char **argv) +{ + if (argc < 3) { + usage(); + exit(1); + } + + char *port_name = argv[1]; + char *file_name = argv[2]; + + if (open_serial_port(port_name) < 0) { + return (1); + } + + if (!download_begin(file_name)) { + return 1; + } + + while (!programming_done) { + handle_port_input(); + } + + close_serial_port(); + + return 0; +} + diff --git a/boards/msba2-common/tools/src/lpc2k_pgm.h b/boards/msba2-common/tools/src/lpc2k_pgm.h new file mode 100644 index 0000000000..0a5f5a7eeb --- /dev/null +++ b/boards/msba2-common/tools/src/lpc2k_pgm.h @@ -0,0 +1,12 @@ +#ifndef LPC2K_PGM +#define LPC2K_PGM + +/* gets a name like "115200", sets baudrate accordingly. */ +void change_baud(const char *baud_name); + +/* called before/after using serial device, used to have terminal + * close the device. +*/ +void signal_terminal(); + +#endif // LPC2K_PGM diff --git a/boards/msba2-common/tools/src/pseudoterm.c b/boards/msba2-common/tools/src/pseudoterm.c new file mode 100644 index 0000000000..24b2d33cb0 --- /dev/null +++ b/boards/msba2-common/tools/src/pseudoterm.c @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "pthread.h" +#include "download.h" + +int tty_fd; +int stopped = 0; +char *port_name = "/dev/ttyUSB1"; +pthread_t serial_reader; + +void *serial_reader_func(void *arg) +{ + unsigned char buf[255]; + + while (1) { + int n = read_serial_port(buf, sizeof(buf)); + + if (n > 0) { + write(tty_fd, buf, n); + } + } +} + +int init() +{ + int result = open_serial_port(port_name); + pthread_create(&serial_reader, NULL, serial_reader_func, NULL); + hard_reset_to_user_code(); + return result; +} + +struct termios old_term_setting; + +void close_tty() +{ + tcsetattr(tty_fd, TCSANOW, &old_term_setting); +} + +void sig_handler(int signal) +{ + if (signal == SIGUSR1) { + if (stopped) { + stopped = 0; + printf("\nSignal received, opening port.\r\n"); + + if (init() < 0) { + printf("Cannot open port.\r\n"); + close_tty(); + exit(1); + } + } + } + else if (signal == SIGUSR2) { + if (!stopped) { + stopped = 1; + printf("\nSignal received, closing port. \r\n"); + pthread_cancel(serial_reader); + close_serial_port(); + } + } + else if (signal == SIGINT) { + printf("SIGINT received, exiting...\n"); + pthread_cancel(serial_reader); + close_serial_port(); + close_tty(); + exit(0); + } +} + +int open_tty(void) +{ + int r, fd; + struct termios term_setting; + + fd = open("/dev/tty", O_RDWR); + + if (fd < 0) { + return -1; + } + + r = tcgetattr(fd, &term_setting); + + if (r != 0) { + return -2; + } + + old_term_setting = term_setting; + + term_setting.c_oflag |= (ONLRET); + term_setting.c_iflag |= (/*IGNBRK |*/ BRKINT | IGNPAR); + term_setting.c_iflag &= ~(ISTRIP); + term_setting.c_lflag &= ~(ICANON |/* ISIG |*/ ECHO); + term_setting.c_lflag |= (ISIG); + term_setting.c_cflag |= CREAD; + term_setting.c_cc[VMIN] = 1; + term_setting.c_cc[VTIME] = 1; + r = tcsetattr(fd, TCSANOW, &term_setting); + + if (r != 0) { + return -3; + } + + return fd; +} + +void install_sighandler() +{ + struct sigaction action; + sigemptyset(&action.sa_mask); + sigaddset(&action.sa_mask, SIGINT); + sigaddset(&action.sa_mask, SIGUSR1); + sigaddset(&action.sa_mask, SIGUSR2); + action.sa_flags = 0; + action.sa_handler = sig_handler; + sigaction(SIGINT, &action, NULL); + sigaction(SIGUSR1, &action, NULL); + sigaction(SIGUSR2, &action, NULL); +} + +int main(int argc, char **argv) +{ + if (argc == 2) { + port_name = argv[1]; + } + + printf("Using %s as serial device.\n", port_name); + + char ttybuf[255]; + tty_fd = open_tty(); + + if (tty_fd < 0) { + printf("Error opening terminal.\n"); + return (1); + } + + install_sighandler(); + + if (init() < 0) { + printf("Cannot open port.\r\n"); + exit(1); + } + + while (1) { + int n = read(tty_fd, ttybuf, sizeof(ttybuf)); + int i; + + /* check for 0x3 (ctrl-c), clean exit */ + for (i = 0; i < n; i++) { + if (ttybuf[i] == 0x3) { + if (i > 0) { + write_serial_port(ttybuf, i); + } + + close_serial_port(); + close_tty(); + system("tset -c"); + return 0; + } + + } + + write_serial_port(ttybuf, n); + } + + close_tty(); + close_serial_port(); + return 0; +} + + diff --git a/boards/msba2-common/tools/src/serial.c b/boards/msba2-common/tools/src/serial.c new file mode 100644 index 0000000000..9e7fee25f8 --- /dev/null +++ b/boards/msba2-common/tools/src/serial.c @@ -0,0 +1,452 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program 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 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef LINUX +#include +#endif + +#include "serial.h" + +static int port_fd = -1; + +static tcflag_t baud_name_to_flags(const char *baud_name); +static void report_open_error(const char *filename, int err); + +char *baud_rate = "115200"; + +int open_serial_port(const char *port_name) +{ + int r; + struct termios term_setting; + + if (port_fd >= 0) { + close(port_fd); + } + + port_fd = open(port_name, O_RDWR); + + if (port_fd < 0) { + report_open_error(port_name, errno); + return -1; + } + + bzero(&term_setting, sizeof(term_setting)); + term_setting.c_cflag = (CS8 | CREAD); + term_setting.c_cc[VMIN] = 1; + term_setting.c_cc[VTIME] = 1; + r = tcsetattr(port_fd, TCSANOW, &term_setting); + + if (r != 0) { + return -1; + } + + r = set_baud(baud_rate); + + if (r == 0) { + printf("Port \"%s\" opened at %s baud\r\n", + port_name, baud_rate); + } + else { + printf("Port \"%s\" opened, unable to set baud to %s\r\n", + port_name, baud_rate); + } + +#ifdef LINUX + { + struct serial_struct kernel_serial_settings; + /* attempt to set low latency mode, but don't worry if we can't */ + r = ioctl(port_fd, TIOCGSERIAL, &kernel_serial_settings); + + if (r < 0) { + return 0; + } + + kernel_serial_settings.flags |= ASYNC_LOW_LATENCY; + ioctl(port_fd, TIOCSSERIAL, &kernel_serial_settings); + } +#endif + return 0; +} + + +/* if the port can't be opened, try to print as much info as + * possible, so the problem can be resolved (usually permissions) + */ +static void report_open_error(const char *filename, int err) +{ + struct stat info; + uid_t my_uid; + gid_t my_gid; + char my_uname[64], my_gname[64], file_uname[64], file_gname[64]; + struct passwd *p; + struct group *g; + mode_t perm; + int r, perm_ok = 0; + + printf("\r\n"); + printf("Unable to open \"%s\"\r\n", filename); + + if (err == EACCES) { + printf("You don't have permission to access %s\r\n", filename); + } + + //printf("Attemping to find more information about %s....\r\n", filename); + r = stat(filename, &info); + + if (r < 0) { + if (errno == ENOENT) { + printf("file %s does not exist\r\n", filename); + } + else if (errno == ELOOP) { + printf("too many symbolic links\r\n"); + } + else if (errno == EACCES) { + printf("permission denied to get file status\r\n"); + } + else { + printf("Unable to get file status, err%d\r\n", errno); + } + + return; + } + + my_uid = getuid(); + my_gid = getgid(); + + p = getpwuid(my_uid); + + if (p) { + snprintf(my_uname, sizeof(my_uname), + "\"%s\" (gid=%d)", p->pw_name, (int)my_uid); + } + else { + snprintf(my_uname, sizeof(my_uname), + "(gid=%d)", (int)my_uid); + } + + p = getpwuid(info.st_uid); + + if (p) { + snprintf(file_uname, sizeof(file_uname), + "\"%s\" (uid=%d)", p->pw_name, (int)info.st_uid); + } + else { + snprintf(file_uname, sizeof(file_uname), + "(uid=%d)", (int)info.st_uid); + } + + g = getgrgid(my_gid); + + if (g) { + snprintf(my_gname, sizeof(my_gname), + "\"%s\" (gid=%d)", g->gr_name, (int)my_gid); + } + else { + snprintf(my_gname, sizeof(my_gname), + "(gid=%d)", (int)my_gid); + } + + g = getgrgid(info.st_gid); + + if (g) { + snprintf(file_gname, sizeof(file_gname), + "\"%s\" (uid=%d)", g->gr_name, (int)info.st_gid); + } + else { + snprintf(file_gname, sizeof(file_gname), + "(uid=%d)", (int)info.st_gid); + } + + /* printf("%s is owned by: user %s, group %s\r\n", + filename, file_uname, file_gname); */ + + perm = info.st_mode; + + if ((perm & S_IROTH) && (perm & S_IWOTH)) { + printf("%s has read/write permission for everybody\r\n", + filename); + } + else { + printf("%s is not read/write for everybody, so\r\n", filename); + printf(" you must match either user or group permission\r\n"); + + if ((perm & S_IRUSR) && (perm & S_IWUSR)) { + printf("%s has read/write permission for user %s\r\n", + filename, file_uname); + perm_ok = 1; + } + + if ((perm & S_IRGRP) && (perm & S_IWGRP)) { + printf("%s has read/write permission for group %s\r\n", + filename, file_gname); + perm_ok = 1; + } + + if (perm_ok == 0) { + printf("%s does not read/write permission for user or group!\r\n", + filename); + } + else { + printf("Your access privs: user %s, group %s\r\n", + my_uname, my_gname); + } + } + + printf("\r\n"); +} + + + +int write_serial_port(const void *buf, int num) +{ + return (write(port_fd, buf, num)); +} + + +void input_flush_serial_port(void) +{ + tcflush(port_fd, TCIFLUSH); +} + + +int read_serial_port_nb(unsigned char *buf, int bufsize) +{ + int num, flags; + + flags = fcntl(port_fd, F_GETFL); + fcntl(port_fd, F_SETFL, flags | O_NONBLOCK); + num = read(port_fd, buf, bufsize); + fcntl(port_fd, F_SETFL, flags); + return num; +} + +int read_serial_port(unsigned char *buf, int bufsize) +{ + int num; + + num = read(port_fd, buf, bufsize); + + return num; +} + + +void send_break_signal(void) +{ + tcsendbreak(port_fd, 0); +} + + +void close_serial_port(void) +{ + if (port_fd >= 0) { + close(port_fd); + port_fd = -1; + } +} + + +tcflag_t baud_name_to_flags(const char *baud_name) +{ + if (strcmp(baud_name, "230400") == 0) { + return B230400; + } + + if (strcmp(baud_name, "115200") == 0) { + return B115200; + } + + if (strcmp(baud_name, "57600") == 0) { + return B57600; + } + + if (strcmp(baud_name, "38400") == 0) { + return B38400; + } + + if (strcmp(baud_name, "19200") == 0) { + return B19200; + } + + if (strcmp(baud_name, "9600") == 0) { + return B9600; + } + + if (strcmp(baud_name, "4800") == 0) { + return B4800; + } + + if (strcmp(baud_name, "2400") == 0) { + return B2400; + } + + if (strcmp(baud_name, "1200") == 0) { + return B1200; + } + + if (strcmp(baud_name, "300") == 0) { + return B300; + } + + return B0; +} + + +int set_baud(const char *baud_name) +{ + struct termios port_setting; + tcflag_t baud; + int r; + + if (port_fd < 0) { + return -1; + } + + baud = baud_name_to_flags(baud_name); + + if (baud == B0) { + return -2; + } + + r = tcgetattr(port_fd, &port_setting); + + if (r != 0) { + return -3; + } + +#ifdef __APPLE__ + cfsetspeed(&port_setting, baud); + port_setting.c_iflag = IGNBRK | IGNPAR; + port_setting.c_cflag = CS8 | CREAD | HUPCL | CLOCAL; +#else + port_setting.c_iflag = IGNBRK | IGNPAR; + port_setting.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL; +#endif + + port_setting.c_oflag = 0; + port_setting.c_lflag = 0; + r = tcsetattr(port_fd, TCSAFLUSH, &port_setting); + + if (r != 0) { + return -4; + } + + return 0; +} + + +// Normally this should never be used... except to pass the port +// file descriptor to the GTK event monitoring loop. All other +// use of the serial port is supposed to happen in the file. +int serial_port_fd(void) +{ + return port_fd; +} + + + +void set_rts(int val) +{ + int flags; + int result; + + result = ioctl(port_fd, TIOCMGET, &flags); + + if (result == -1) { + printf("Error %i while reading port io flags\n", errno); + return; + } + + if (val) { + flags |= TIOCM_RTS; + } + else { + flags &= ~(TIOCM_RTS); + } + + result = ioctl(port_fd, TIOCMSET, &flags); + + if (result == -1) { + printf("Error %i while setting port io flags\n", errno); + } +} + + + + + + + +void set_dtr(int val) +{ + int flags; + int result; + + result = ioctl(port_fd, TIOCMGET, &flags); + + if (result == -1) { + printf("Error %i while reading port io flags\n", errno); + return; + } + + if (val) { + flags |= TIOCM_DTR; + } + else { + flags &= ~(TIOCM_DTR); + } + + result = ioctl(port_fd, TIOCMSET, &flags); + + if (result == -1) { + printf("Error %i while setting port io flags\n", errno); + } +} + + + + + + diff --git a/boards/msba2-common/tools/src/serial.h b/boards/msba2-common/tools/src/serial.h new file mode 100644 index 0000000000..3887a18947 --- /dev/null +++ b/boards/msba2-common/tools/src/serial.h @@ -0,0 +1,19 @@ +#ifndef SERIAL_H +#define SERIAL_H + +extern char *baud_rate; + +int open_serial_port(const char *port_name); +int write_serial_port(const void *buf, int num); +void input_flush_serial_port(void); +int read_serial_port_nb(unsigned char *buf, int bufsize); +int read_serial_port(unsigned char *buf, int bufsize); +void close_serial_port(void); +void send_break_signal(void); +int set_baud(const char *baud_name); +int serial_port_fd(void); +void set_rts(int val); +void set_dtr(int val); +void change_baud(const char *baud_name); + +#endif // SERIAL_H diff --git a/boards/msba2-common/tools/src/settings.c b/boards/msba2-common/tools/src/settings.c new file mode 100644 index 0000000000..405d648e1a --- /dev/null +++ b/boards/msba2-common/tools/src/settings.c @@ -0,0 +1,209 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program 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 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + + +#include +#include +#include +#include + +#include "settings.h" + +#define DEFAULT_FILE "" +#define DEFAULT_PORT "/dev/ttyS0" +#define DEFAULT_BAUD "115200" +#define DEFAULT_CRYSTAL "16" + +char *baud_list[] = {"115200", "57600", "38400", + "19200", "9600", "4800", "2400", "1200", "300", NULL + }; + +static char file[128] = {DEFAULT_FILE}; +static char port[64] = {DEFAULT_PORT}; +static char baud[64] = {DEFAULT_BAUD}; +static char crystal[64] = {DEFAULT_CRYSTAL}; + +static char settings_file[256] = {'\0'}; + + +void init_settings(void) +{ + const char *home_dir; + FILE *fp; + char buf[1024], *p, *q; + + home_dir = getenv("HOME"); + + if (home_dir && *home_dir) { + snprintf(settings_file, sizeof(settings_file), + "%s/.lpc2k_pgm", home_dir); + fp = fopen(settings_file, "r"); + + if (fp == NULL) { + return; + } + + while (!feof(fp)) { + buf[0] = '\0'; + fgets(buf, sizeof(buf), fp); + + if (strncmp(buf, "file:", 5) == 0) { + for (p = buf + 5; isspace(*p); p++); + q = rindex(p, '\n'); + if (q) { + *q = '\0'; + } + q = rindex(p, '\r'); + if (q) { + *q = '\0'; + } + snprintf(file, sizeof(file), "%s", p); + } + + if (strncmp(buf, "port:", 5) == 0) { + for (p = buf + 5; isspace(*p); p++); + q = rindex(p, '\n'); + if (q) { + *q = '\0'; + } + q = rindex(p, '\r'); + if (q) { + *q = '\0'; + } + snprintf(port, sizeof(port), "%s", p); + } + + if (strncmp(buf, "baud:", 5) == 0) { + for (p = buf + 5; isspace(*p); p++); + q = rindex(p, '\n'); + if (q) { + *q = '\0'; + } + q = rindex(p, '\r'); + if (q) { + *q = '\0'; + } + snprintf(baud, sizeof(baud), "%s", p); + } + + if (strncmp(buf, "xtal:", 5) == 0) { + for (p = buf + 5; isspace(*p); p++) ; + q = rindex(p, '\n'); + if (q) { + *q = '\0'; + } + q = rindex(p, '\r'); + if (q) { + *q = '\0'; + } + snprintf(crystal, sizeof(crystal), "%s", p); + } + } + + fclose(fp); + } +} + +void write_settings_file(void) +{ + FILE *fp; + + if (settings_file[0] == '\0') { + return; + } + + fp = fopen(settings_file, "w"); + + if (fp == NULL) { + return; + } + + fprintf(fp, "file: %s\n", file); + fprintf(fp, "port: %s\n", port); + fprintf(fp, "baud: %s\n", baud); + fprintf(fp, "xtal: %s\n", crystal); + fflush(fp); + fclose(fp); +} + +const char *file_setting(void) +{ + return file; +} + +const char *port_setting(void) +{ + return port; +} + +const char *baud_setting(void) +{ + return baud; +} + +const char *crystal_setting(void) +{ + return crystal; +} + +void new_file_setting(const char *new_file) +{ + if (strcmp(file, new_file)) { + snprintf(file, sizeof(file), "%s", new_file); + write_settings_file(); + } +} + +void new_port_setting(const char *new_port) +{ + if (strcmp(port, new_port)) { + snprintf(port, sizeof(port), "%s", new_port); + write_settings_file(); + } +} + +void new_baud_setting(const char *new_baud) +{ + if (strcmp(baud, new_baud)) { + snprintf(baud, sizeof(baud), "%s", new_baud); + write_settings_file(); + } +} + +void new_crystal_setting(const char *new_xtal) +{ + if (strcmp(crystal, new_xtal)) { + snprintf(crystal, sizeof(crystal), "%s", new_xtal); + write_settings_file(); + } +} + diff --git a/boards/msba2-common/tools/src/settings.h b/boards/msba2-common/tools/src/settings.h new file mode 100644 index 0000000000..47356be96c --- /dev/null +++ b/boards/msba2-common/tools/src/settings.h @@ -0,0 +1,12 @@ + +extern void init_settings(void); +extern const char *file_setting(void); +extern const char *port_setting(void); +extern const char *baud_setting(void); +extern const char *crystal_setting(void); +extern void new_file_setting(const char *new_file); +extern void new_port_setting(const char *new_port); +extern void new_baud_setting(const char *new_baud); +extern void new_crystal_setting(const char *new_xtal); + +extern char *baud_list[]; diff --git a/boards/msba2-common/tools/src/uuencode.c b/boards/msba2-common/tools/src/uuencode.c new file mode 100644 index 0000000000..7b6856ab64 --- /dev/null +++ b/boards/msba2-common/tools/src/uuencode.c @@ -0,0 +1,123 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program 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 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + +#include "uuencode.h" + +static char uuchar(unsigned int val); + + +void uuencode(char *str, const unsigned char *data, int num) +{ + int i, n; + unsigned int val; + + *str++ = uuchar(num); + + n = (num + 2) / 3; + + for (i = 0; i < n; i++) { + val = ((data[0] & 0xFF) << 16) + | ((data[1] & 0xFF) << 8) + | ((data[2] & 0xFF) << 0); + *str++ = uuchar(val >> 18); + *str++ = uuchar(val >> 12); + *str++ = uuchar(val >> 6); + *str++ = uuchar(val >> 0); + data += 3; + } + + *str = '\0'; +} + +int uudecode(const char *str, unsigned char *data, int max) +{ + int num = 0; + int i, n; + unsigned int val; + + if (*str == '\0') { + return 0; + } + + num = *str++ - 32; + + if (num < 1 || num > 45) { + return 0; + } + + n = (num + 2) / 3; + + for (i = 0; i < n; i++) { + if (str[0] < 32 || str[0] > 96) { + return 0; + } + + if (str[1] < 32 || str[1] > 96) { + return 0; + } + + if (str[2] < 32 || str[2] > 96) { + return 0; + } + + if (str[3] < 32 || str[3] > 96) { + return 0; + } + + val = (((str[0] - 32) & 0x3F) << 18) + | (((str[1] - 32) & 0x3F) << 12) + | (((str[2] - 32) & 0x3F) << 6) + | (((str[3] - 32) & 0x3F) << 0); + *data++ = (val >> 16) & 0xFF; + *data++ = (val >> 8) & 0xFF; + *data++ = (val >> 0) & 0xFF; + str += 4; + } + + return num; +} + + +static char uuchar(unsigned int val) +{ + val &= 0x3F; + val += 0x20; + + if (val == 0x20) { + val = 0x60; + } + + return val; +} + + + diff --git a/boards/msba2-common/tools/src/uuencode.h b/boards/msba2-common/tools/src/uuencode.h new file mode 100644 index 0000000000..92fecb7d33 --- /dev/null +++ b/boards/msba2-common/tools/src/uuencode.h @@ -0,0 +1,3 @@ +extern void uuencode(char *str, const unsigned char *data, int num); +extern int uudecode(const char *str, unsigned char *data, int max); + diff --git a/boards/msba2-common/tools/termctrl.sh b/boards/msba2-common/tools/termctrl.sh new file mode 100755 index 0000000000..75e87ab21e --- /dev/null +++ b/boards/msba2-common/tools/termctrl.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +pid=`pgrep pseudoterm` + +if test "$pid" = "" ; then + + echo " Pseudoterm not running." + +else + + if test "$1" = "continue" ; then + kill -s USR1 $pid; + elif test "$1" = "pause" ; then + kill -s USR2 $pid ; + elif test "$1" = "stop" ; then + kill $pid ; + else + echo "Usage:"; + echo "termctrl.sh continue/pause/stop"; + fi + +fi diff --git a/boards/msba2/Makefile b/boards/msba2/Makefile new file mode 100644 index 0000000000..0aff0df0b1 --- /dev/null +++ b/boards/msba2/Makefile @@ -0,0 +1,37 @@ +SRC = $(wildcard *.c) +BINDIR = bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +export ARCH = msba2_base.a + +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBOARD)/msba2/include/ +INCLUDES += -I$(RIOTBOARD)/msba2-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/arm_common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/lpc2387/include/ + +all: $(BINDIR)$(ARCH) + $(MAKE) -C ../msba2-common + +$(BINDIR)$(ARCH): $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + mkdir -p $(BINDIR) + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + $(MAKE) -C ../msba2-common clean + rm -f $(BINDIR)$(ARCH) $(OBJ) $(DEP) + @if [ -d $(BINDIR) ] ; \ + then rmdir $(BINDIR) ; \ + fi + + diff --git a/boards/msba2/Makefile.include b/boards/msba2/Makefile.include new file mode 100644 index 0000000000..80751c020a --- /dev/null +++ b/boards/msba2/Makefile.include @@ -0,0 +1,3 @@ +export INCLUDES += -I$(RIOTBOARD)/msba2/include -I$(RIOTBOARD)/msba2-common/include + +include $(RIOTBOARD)/msba2-common/Makefile.include diff --git a/boards/msba2/board_init.c b/boards/msba2/board_init.c new file mode 100644 index 0000000000..427d563e1b --- /dev/null +++ b/boards/msba2/board_init.c @@ -0,0 +1,109 @@ +/* + * main.c - Main function of the SRF02 ultrasonic sensor project. + * Copyright (C) 2013 Zakaria Kasmi + * + * The source code is licensed under the LGPLv2 license, + * See the file LICENSE for more details. + */ + +/** + * @ingroup msba2 + * @{ + */ + +/** + * @file + * @brief MSB-A2 board initialization + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Kaspar Schleiser + * @author Michael Baar + * @author Zakaria Kasmi + * + * @note $Id$ + */ + + +#include +#include + +void loop_delay(void) +{ + volatile uint16_t i, j; + + for (i = 1; i < 30; i++) { + for (j = 1; j != 0; j++) { + asm volatile(" nop "); + } + } +} + +void bl_blink(void) +{ + LED_RED_ON; + LED_GREEN_ON; + + loop_delay(); + + LED_RED_OFF; + LED_GREEN_OFF; +} + +void bl_init_ports(void) +{ + SCS |= BIT0; // Set IO Ports to fast switching mode + + /* UART0 */ + PINSEL0 |= BIT4 + BIT6; // RxD0 and TxD0 + PINSEL0 &= ~(BIT5 + BIT7); + + /* LEDS */ + FIO3DIR |= LED_RED_PIN; + FIO3DIR |= LED_GREEN_PIN; + LED_RED_OFF; + LED_GREEN_OFF; + + /* short blinking of both of the LEDs on startup */ + bl_blink(); +} + +static inline void +pllfeed(void) +{ + PLLFEED = 0xAA; + PLLFEED = 0x55; +} + +void init_clks1(void) +{ + // Disconnect PLL + PLLCON &= ~0x0002; + pllfeed(); + + // Disable PLL + PLLCON &= ~0x0001; + pllfeed(); + + SCS |= 0x20; // Enable main OSC + + while (!(SCS & 0x40)); // Wait until main OSC is usable + + /* select main OSC, 16MHz, as the PLL clock source */ + CLKSRCSEL = 0x0001; + + // Setting Multiplier and Divider values + PLLCFG = 0x0008; // M=9 N=1 Fcco = 288 MHz + pllfeed(); + + // Enabling the PLL */ + PLLCON = 0x0001; + pllfeed(); + + /* Set clock divider to 4 (value+1) */ + CCLKCFG = CL_CPU_DIV - 1; // Fcpu = 72 MHz + +#if USE_USB + USBCLKCFG = USBCLKDivValue; /* usbclk = 288 MHz/6 = 48 MHz */ +#endif +} diff --git a/boards/msba2/include/board.h b/boards/msba2/include/board.h new file mode 100644 index 0000000000..829715b3c2 --- /dev/null +++ b/boards/msba2/include/board.h @@ -0,0 +1,22 @@ +#ifndef __BOARD_H +#define __BOARD_H + +#include "msba2_common.h" +#include "bitarithm.h" + +#define LED_RED_PIN (BIT25) +#define LED_GREEN_PIN (BIT26) + +#define LED_GREEN_OFF (FIO3SET = LED_GREEN_PIN) +#define LED_GREEN_ON (FIO3CLR = LED_GREEN_PIN) +#define LED_GREEN_TOGGLE (FIO3PIN ^= LED_GREEN_PIN) + +#define LED_RED_OFF (FIO3SET = LED_RED_PIN) +#define LED_RED_ON (FIO3CLR = LED_RED_PIN) +#define LED_RED_TOGGLE (FIO3PIN ^= LED_RED_PIN) + +void init_clks1(void); + +typedef uint8_t radio_packet_length_t; + +#endif /* __BOARD_H */ diff --git a/boards/native/Makefile b/boards/native/Makefile new file mode 100644 index 0000000000..ded96b6cf2 --- /dev/null +++ b/boards/native/Makefile @@ -0,0 +1,31 @@ +SRC = $(wildcard *.c) +BINDIR = bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +DEP = $(SRC:%.c=$(BINDIR)%.d) +export ARCH = native_base.a + +INCLUDES += -I$(RIOTBASE)/cpu/native/include/ +INCLUDES += -I$(RIOTBOARD)/native/include/ + +all: $(BINDIR)$(ARCH) + $(MAKE) -C drivers + +$(BINDIR)$(ARCH): $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + -mkdir -p $(BINDIR) + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + ${MAKE} -C drivers clean + rm -f $(BINDIR)$(ARCH) $(OBJ) $(DEP) + -rmdir -p $(BINDIR) + diff --git a/boards/native/Makefile.dep b/boards/native/Makefile.dep new file mode 100644 index 0000000000..fdd8ec4d90 --- /dev/null +++ b/boards/native/Makefile.dep @@ -0,0 +1,6 @@ +ifneq (,$(findstring ltc4150,$(USEMODULE))) + ifeq (,$(findstring hwtimer,$(USEMODULE))) + USEMODULE += hwtimer + endif +endif + diff --git a/boards/native/Makefile.include b/boards/native/Makefile.include new file mode 100644 index 0000000000..1a5b2e4d2d --- /dev/null +++ b/boards/native/Makefile.include @@ -0,0 +1,23 @@ +export INCLUDES += -I$(RIOTBOARD)/native/include +export CPU = native + +# toolchain config +export PREFIX = +#export CC = @$(PREFIX)gcc +export AR = @$(PREFIX)ar +export CFLAGS += -std=gnu99 -Wall -m32 +export ASFLAGS = +export AS = $(PREFIX)as +export LINK = $(PREFIX)gcc +export SIZE = $(PREFIX)size +export OBJCOPY = $(PREFIX)objcopy +FLASHER = lpc2k_pgm +TERM = pyterm.py + +LINKFLAGS += -m32 -gc + +ifeq ($(strip $(PORT)),) + export PORT = /dev/ttyUSB0 +endif + +include $(RIOTBOARD)/$(BOARD)/Makefile.dep diff --git a/boards/native/board_config.c b/boards/native/board_config.c new file mode 100644 index 0000000000..dafdf747aa --- /dev/null +++ b/boards/native/board_config.c @@ -0,0 +1,39 @@ +/** + * Native Board config.h implementation + * + * No functionality implemented at the moment. + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup native_board + * @{ + * @file + * @author Ludwig Ortmann + * @} + */ + +#include +#include + +#include + +/** + * XXX: loading not implemented + */ +void config_load(void) +{ + printf("XXX: config_load(): not implemented\n"); + return; +} + +/** + * XXX: storing not implemented + */ +uint8_t config_save(void) +{ + printf("XXX: config_save(): not implemented - your config will vanish on process termination\n"); + return 1; +} diff --git a/boards/native/board_init.c b/boards/native/board_init.c new file mode 100644 index 0000000000..0abc01573c --- /dev/null +++ b/boards/native/board_init.c @@ -0,0 +1,32 @@ +/** + * Native Board board_init implementation + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup native_board + * @{ + * @file + * @author Ludwig Ortmann + * @} + */ +#include +#include "board.h" + +#include "board_internal.h" + +/** + * Nothing to initialize at the moment. + * Turns the red LED on and the green LED off. + */ +void board_init() +{ +#ifdef MODULE_UART0 + _native_init_uart0(); +#endif + LED_GREEN_OFF; + LED_RED_ON; + puts("RIOT native board initialized."); +} diff --git a/boards/native/drivers/Makefile b/boards/native/drivers/Makefile new file mode 100644 index 0000000000..f0516a8530 --- /dev/null +++ b/boards/native/drivers/Makefile @@ -0,0 +1,30 @@ +SRC = $(wildcard *.c) +BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ +OBJ = $(BINDIR)native-led.o +ifneq (,$(findstring ltc4150,$(USEMODULE))) + OBJ += $(BINDIR)native-ltc4150.o +endif +ifneq (,$(findstring uart0,$(USEMODULE))) + OBJ += $(BINDIR)native-uart0.o +endif +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBOARD)/native/include/ + +$(BINDIR)native_drivers.a: $(OBJ) + @$(AR) rcs $(BINDIR)${ARCH} $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + @$(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)" | cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products + +clean: + rm -f $(OBJ) $(DEP) + diff --git a/boards/native/drivers/native-led.c b/boards/native/drivers/native-led.c new file mode 100644 index 0000000000..7f9296d7c3 --- /dev/null +++ b/boards/native/drivers/native-led.c @@ -0,0 +1,51 @@ +/** + * Native Board LED implementation + * + * Only prints function calls at the moment. + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup native_board + * @{ + * @file + * @author Ludwig Ortmann + * @} + */ + +#include + +#include "board.h" + +void _native_LED_GREEN_OFF(void) +{ + printf("LED_GREEN_OFF\n"); +} + +void _native_LED_GREEN_ON(void) +{ + printf("LED_GREEN_ON\n"); +} + +void _native_LED_GREEN_TOGGLE(void) +{ + printf("LED_GREEN_TOGGLE\n"); +} + +void _native_LED_RED_OFF(void) +{ + printf("LED_RED_OFF\n"); +} + +void _native_LED_RED_ON(void) +{ + printf("LED_RED_ON\n"); +} + +void _native_LED_RED_TOGGLE(void) +{ + printf("LED_RED_TOGGLE\n"); +} + diff --git a/boards/native/drivers/native-ltc4150.c b/boards/native/drivers/native-ltc4150.c new file mode 100644 index 0000000000..babe801616 --- /dev/null +++ b/boards/native/drivers/native-ltc4150.c @@ -0,0 +1,89 @@ +/** + * Native Board ltc4150_arch.h implementation + * + * Only measures time at the moment. Uses POSIX real-time extension + * timer to generate periodic signal/interrupt. + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup native_board + * @ingroup ltc4150 + * @{ + * @file + * @author Ludwig Ortmann + */ + +#include +#include +#include +#include + +#include "ltc4150_arch.h" +#include "debug.h" + +#include "cpu.h" +#include "cpu-conf.h" +#include "hwtimer.h" + +#define native_ltc4150_startup_delay 10 + +static int _int_enabled; + +/** + * native ltc4150 hwtimer - interrupt handler proxy + */ +static void _int_handler() +{ + DEBUG("ltc4150 _int_handler()\n"); + ltc4150_interrupt(); + if (_int_enabled == 1) { + if (hwtimer_set(100000, _int_handler, NULL) == -1) { + errx(1, "_int_handler: hwtimer_set"); + }; + } +} + +/** + * unregister signal handler + */ +void ltc4150_disable_int(void) +{ + DEBUG("ltc4150_disable_int()\n"); + _int_enabled = 0; +} + +/** + * register signal handler + */ +void ltc4150_enable_int(void) +{ + DEBUG("ltc4150_enable_int()\n"); + _int_enabled = 1; + if (hwtimer_set(100000, _int_handler, NULL) == -1) { + errx(1, "ltc4150_enable_int: hwtimer_set"); + }; +} + +/** + * elaborate nop + */ +void ltc4150_sync_blocking(void) +{ + DEBUG("ltc4150_sync_blocking()\n"); + + for (int i = native_ltc4150_startup_delay; i > 0; i--); +} + +/** + * set up posix real-time timer to simulate coloumb counter ticks + */ +void ltc4150_arch_init(void) +{ + ltc4150_disable_int(); + + puts("Native LTC4150 initialized."); +} +/** @} */ diff --git a/boards/native/drivers/native-uart0.c b/boards/native/drivers/native-uart0.c new file mode 100644 index 0000000000..b9d8b041d3 --- /dev/null +++ b/boards/native/drivers/native-uart0.c @@ -0,0 +1,98 @@ +/* + * native uart0 implementation + */ + +#include +#include +#include +#include + +#include + +#include "cpu.h" +#include "debug.h" +#include "board_uart0.h" + +int _native_uart_in; +int _native_uart_out; + +fd_set _native_uart_rfds; + +inline int uart0_puts(char *astring, int length) +{ + int nwritten, offset; + + nwritten = 0; + offset = 0; + + _native_in_syscall = 1; + + while ((length > 0) &&(nwritten = write(_native_uart_out, astring+offset, length-offset)) > 0) { + offset += nwritten; + } + if (nwritten == -1) { + err(EXIT_FAILURE, "uart0_puts: write"); + } + else if ((length > 0) && (nwritten == 0)) { + /* XXX: handle properly */ + errx(EXIT_FAILURE, "uart0_puts: Could not write to stdout. I don't know what to do now."); + } + + _native_in_syscall = 0; + + return length; +} + +void _native_handle_uart0_input() +{ + char buf[42]; + int nread; + + if (!FD_ISSET(_native_uart_in, &_native_rfds)) { + DEBUG("_native_handle_uart0_input - nothing to do\n"); + return; + } + DEBUG("_native_handle_uart0_input\n"); + _native_in_syscall = 0; + _native_in_isr = 1; + + nread = read(_native_uart_in, buf, sizeof(buf)); + if (nread == -1) { + err(1, "_native_handle_uart0_input(): read()"); + } + else if (nread == 0) { + /* XXX: + * preliminary resolution for this situation, will be coped + * with properly in #161 */ + close(_native_uart_in); + _native_uart_in = -1; + warnx("stdin closed"); + } + for(int pos = 0; pos < nread; pos++) { + uart0_handle_incoming(buf[pos]); + } + uart0_notify_thread(); + + _native_in_isr = 0; + thread_yield(); +} + +int _native_set_uart_fds(void) +{ + DEBUG("_native_set_uart_fds"); + FD_SET(_native_uart_in, &_native_rfds); + return _native_uart_in; +} + +void _native_init_uart0() +{ + _native_uart_out = STDOUT_FILENO; + _native_uart_in = STDIN_FILENO; + + puts("RIOT native uart0 initialized."); +} + +int putchar(int c) { + write(_native_uart_out, &c, 1); + return 0; +} diff --git a/boards/native/include/board.h b/boards/native/include/board.h new file mode 100644 index 0000000000..f1dca63e6a --- /dev/null +++ b/boards/native/include/board.h @@ -0,0 +1,37 @@ +#ifndef BOARD_H +#define BOARD_H + +/** + * Native Board interface + * + * The native board uses call level hardware simulation. + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @defgroup native_board + * @{ + * @file + * @author Ludwig Ortmann + * @} + */ + +#include + +void _native_LED_GREEN_OFF(void); +#define LED_GREEN_OFF (_native_LED_GREEN_OFF()) +void _native_LED_GREEN_ON(void); +#define LED_GREEN_ON (_native_LED_GREEN_ON()) +void _native_LED_GREEN_TOGGLE(void); +#define LED_GREEN_TOGGLE (_native_LED_GREEN_TOGGLE()) +void _native_LED_RED_OFF(void); +#define LED_RED_OFF (_native_LED_RED_OFF()) +void _native_LED_RED_ON(void); +#define LED_RED_ON (_native_LED_RED_ON()) +void _native_LED_RED_TOGGLE(void); +#define LED_RED_TOGGLE (_native_LED_RED_TOGGLE()) + +typedef uint16_t radio_packet_length_t; +#endif /* BOARD_H */ diff --git a/boards/native/include/board_internal.h b/boards/native/include/board_internal.h new file mode 100644 index 0000000000..368d5287de --- /dev/null +++ b/boards/native/include/board_internal.h @@ -0,0 +1,6 @@ +#ifdef MODULE_UART0 +#include +void _native_handle_uart0_input(void); +void _native_init_uart0(void); +int _native_set_uart_fds(void); +#endif diff --git a/boards/olimex_lpc2148/board_init.c b/boards/olimex_lpc2148/board_init.c new file mode 100644 index 0000000000..1d1746be4d --- /dev/null +++ b/boards/olimex_lpc2148/board_init.c @@ -0,0 +1,88 @@ +/* + * bl_board_init.c + * + * Created on: 19.08.2008 + * Author: heiko, kaspar + */ + +#include "cpu.h" +#include "bits.h" +#include "VIC.h" + +#define PLOCK 0x400 + +static void feed(void) +{ + PLL0FEED = 0xAA; + PLL0FEED = 0x55; +} + +void bl_init_clks(void) +{ + + // Setting the Phased Lock Loop (PLL) + // ---------------------------------- + // + // Olimex LPC-P2148 has a 12.0000 mhz crystal + // + // We'd like the LPC2148 to run at 60 mhz (has to be an even multiple of crystal) + // + // According to the Philips LPC2148 manual: M = cclk / Fosc where: M = PLL multiplier (bits 0-4 of PLLCFG) + // cclk = 60000000 hz + // Fosc = 12000000 hz + // + // Solving: M = 60000000 / 12000000 = 5 + // + // Note: M - 1 must be entered into bits 0-4 of PLLCFG (assign 4 to these bits) + // + // + // The Current Controlled Oscilator (CCO) must operate in the range 156 mhz to 320 mhz + // + // According to the Philips LPC2148 manual: Fcco = cclk * 2 * P where: Fcco = CCO frequency + // cclk = 60000000 hz + // P = PLL divisor (bits 5-6 of PLLCFG) + // + // Solving: Fcco = 60000000 * 2 * P + // P = 2 (trial value) + // Fcco = 60000000 * 2 * 2 + // Fcc0 = 240000000 hz (good choice for P since it's within the 156 mhz to 320 mhz range) + // + // From Table 22 (page 34) of Philips LPC2148 manual P = 2, PLLCFG bits 5-6 = 1 (assign 1 to these bits) + // + // Finally: PLLCFG = 0 01 00100 = 0x24 + // + // Final note: to load PLLCFG register, we must use the 0xAA followed 0x55 write sequence to the PLLFEED register + // this is done in the short function feed() below + // + + // Setting Multiplier and Divider values + PLL0CFG = 0x24; + feed(); + + // Enabling the PLL */ + PLL0CON = 0x1; + feed(); + + // Wait for the PLL to lock to set frequency + while (!(PLL0STAT & PLOCK)) ; + + // Connect the PLL as the clock source + PLL0CON = 0x3; + feed(); + + // Enabling MAM and setting number of clocks used for Flash memory fetch + MAMTIM = 0x3; + MAMCR = 0x2; + + // Setting peripheral Clock (pclk) to 1/2 System Clock (cclk) + VPBDIV = PCLK_DIV; +} + + + + +void bl_init_ports(void) +{ + +} + diff --git a/boards/olimex_lpc2148/debug_uart.c b/boards/olimex_lpc2148/debug_uart.c new file mode 100644 index 0000000000..90f5144dfe --- /dev/null +++ b/boards/olimex_lpc2148/debug_uart.c @@ -0,0 +1,14 @@ +#include "lpc214x.h" +#include "bits.h" + +#include "rs232.h" + +void debug_putchar(int character) +{ + UART1WriteChar(character); +} + +void bl_uart_init(void) +{ + UART1Initialize(115200U); +} diff --git a/boards/olimex_lpc2148/include/board.h b/boards/olimex_lpc2148/include/board.h new file mode 100644 index 0000000000..ff961ea366 --- /dev/null +++ b/boards/olimex_lpc2148/include/board.h @@ -0,0 +1,4 @@ +#include +#include "lpc2148.h" + +typedef uint8_t radio_packet_length_t; diff --git a/boards/olimex_lpc2148/include/rs232.h b/boards/olimex_lpc2148/include/rs232.h new file mode 100644 index 0000000000..9fe0bf2c87 --- /dev/null +++ b/boards/olimex_lpc2148/include/rs232.h @@ -0,0 +1,40 @@ +//rs232.h +//#include + +#include "lpc214x.h" + +//#define OSCILLATOR_CLOCK_FREQUENCY 14745600 //in MHz +#define OSCILLATOR_CLOCK_FREQUENCY 12000000 //in MHz + +//get real processor clock frequency +unsigned int processorClockFrequency(void); +//get peripheral clock frequency +unsigned int peripheralClockFrequency(void); + +/**** UART0 ****/ +//initialize UART0 interface +void UART0Initialize(unsigned int baud); +//write char to UART0 (RS232); +void UART0WriteChar(int ch0); +//read char from RS232 +unsigned char UART0ReadChar(void); + +//this function read/write char from RS232, +//but they not wait to read/write +unsigned char UART0ReadChar_nostop(void); +void UART0WriteChar_nostop(unsigned char ch0); + + +/**** UART1 ****/ +//initialize UART0 interface +void UART1Initialize(unsigned int baud); +//write char to UART0 (RS232); +void UART1WriteChar(int ch0); +//read char from RS232 +unsigned char UART0ReadChar(void); + +//this function read/write char from RS232, +//but they not wait to read/write +unsigned char UART1ReadChar_nostop(void); +void UART1WriteChar_nostop(unsigned char ch0); + diff --git a/boards/olimex_lpc2148/rs232.c b/boards/olimex_lpc2148/rs232.c new file mode 100644 index 0000000000..ac885b877f --- /dev/null +++ b/boards/olimex_lpc2148/rs232.c @@ -0,0 +1,75 @@ +//rs232.c +#include "rs232.h" + +unsigned int processorClockFrequency(void) +{ + //return real processor clock speed + return OSCILLATOR_CLOCK_FREQUENCY * (PLL0CON & 1 ? (PLL0CFG & 0xF) + 1 : 1); +} + +unsigned int peripheralClockFrequency(void) +{ + //VPBDIV - determines the relationship between the processor clock (cclk) + //and the clock used by peripheral devices (pclk). + unsigned int divider = 0; + + switch (VPBDIV & 3) { + case 0: + divider = 4; + break; + + case 1: + divider = 1; + break; + + case 2: + divider = 2; + break; + } + + return processorClockFrequency() / divider; +} + +/**** UART0 ****/ +void UART1Initialize(unsigned int baud) +{ + unsigned int divisor = peripheralClockFrequency() / (16 * baud); + + //set Line Control Register (8 bit, 1 stop bit, no parity, enable DLAB) + // U0LCR_bit.WLS = 0x3; //8 bit + // U0LCR_bit.SBS = 0x0; //1 stop bit + // U0LCR_bit.PE = 0x0; //no parity + // U0LCR_bit.DLAB = 0x1; //enable DLAB + //with one row + U1LCR = 0x83; + + + //devisor + U1DLL = divisor & 0xFF; + U1DLM = (divisor >> 8) & 0xFF; + U1LCR &= ~0x80; + + //set functionalite to pins: port0.0 -> TX0, port0.1 -> RXD0 + // PINSEL0_bit.P0_0 = 0x1; + // PINSEL0_bit.P0_1 = 0x1; + //with one row + PINSEL0 |= BIT16; + PINSEL0 &= ~BIT17; + +} + +void UART1WriteChar(int ch0) +{ + while (!(U1LSR & BIT5)); + + U1THR = ch0; +} + +unsigned char UART0ReadChar(void) +{ + //when U0LSR_bit.DR is 1 - U0RBR contains valid data + // while (U0LSR_bit.DR == 0); + return U0RBR; +} + + diff --git a/boards/olimex_lpc2148/tick.c b/boards/olimex_lpc2148/tick.c new file mode 100644 index 0000000000..0d62706943 --- /dev/null +++ b/boards/olimex_lpc2148/tick.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + +This file is part of the Micro-mesh SensorWeb Firmware. + +Micro-Mesh 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, or (at your option) +any later version. + +Micro-Mesh 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 Micro-Mesh; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "lpc214x.h" +#include "bits.h" +//#include "tick.h" +#include "minimal_dbg_console.h" +#include "VIC.h" + +void Timer0_IRQHandler(void) __attribute__((interrupt("IRQ"))); + +extern void eINT(); +extern void dINT(); + + +void driver_timer_load(void) +{ + T0TCR = 0; // Disable timer 0. + T0PR = 3000; // Prescaler is set to relevant pclk , counter is incremented every T0PR tact. + T0CCR = 0; // Capture is disabled. + T0EMR = 0; // No external match output. + T0TC = 0; + T0MR0 = 1000; + T0MCR |= BIT0 + BIT1; + T0TCR = BIT0; // Enable timer 0. + + dINT(); // Disable all interrupts + VICIntEnable = BIT4; // Enable Interrupthandling for Timer0 + VICVectCntl3 = 4 + BIT5; // Assign Timer0 to IRQ Slot 3 + VICVectAddr3 = (unsigned int)Timer0_IRQHandler; // Assign Isr Address + eINT(); +} + +int counter = 0; + +void Timer0_IRQHandler(void) +{ + extern unsigned int sched_context_switch_request; + counter++; + T0IR |= 0xff; // reset timer1 interrupt flag + sl_printf("#"); + + sched_context_switch_request = 1; + + VICVectAddr = 0; // acknowledge interrupt (if using VIC IRQ) +} + diff --git a/boards/olimex_lpc2148/tools/lpc2148_flash.gdb b/boards/olimex_lpc2148/tools/lpc2148_flash.gdb new file mode 100644 index 0000000000..cb308752ae --- /dev/null +++ b/boards/olimex_lpc2148/tools/lpc2148_flash.gdb @@ -0,0 +1,22 @@ +#winheight regs 11 +set history save on +set history size 1000 +target remote localhost:3333 +monitor reset +monitor sleep 100 +monitor halt +monitor poll +#monitor arm7_9 sw_bkpts disable +#monitor arm7_9 force_hw_bkpts enable +monitor mww 0xE01FC040 0x0001 +monitor mdw 0xE01FC040 +monitor flash erase_sector 0 0 14 +#monitor flash auto_erase on +monitor flash erase_check 0 +#monitor flash write_image /home/kaspar/FeuerWhere/src/x/bin/arm.elf +set remote hardware-watchpoint-limit 2 +load +break bootloader +mon soft_reset_halt +continue +d b 1 diff --git a/boards/pttu/board_init.c b/boards/pttu/board_init.c new file mode 100644 index 0000000000..18ba75d850 --- /dev/null +++ b/boards/pttu/board_init.c @@ -0,0 +1,163 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup pttu + * @{ + */ + +/** + * @file + * @brief PTTU board initialization + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Kaspar Schleiser + * + */ +#include +#include +#include + +#define PCRTC BIT9 +#define CL_CPU_DIV 4 + +void bl_init_ports(void) +{ + SCS |= BIT0; // Set IO Ports to fast switching mode + + /* UART0 */ + PINSEL0 |= BIT4 + BIT6; // RxD0 and TxD0 + PINSEL0 &= ~(BIT5 + BIT7); + + /*Turn Board on*/ + PINMODE0 |= BIT1; + FIO0DIR |= BIT27; + FIO0CLR = BIT27; + + /* 5V*/ + FIO1DIR |= BIT28; // Synch + FIO1SET = BIT28; // No Powersave + + FIO1DIR |= BIT27; // 5V off + FIO1CLR = BIT27; + + /* Disable Resistors on Buttons */ + PINMODE4 |= BIT9 + BIT11; + + /* Disable Resistors on LED - and Ports to output*/ + PINMODE7 |= BIT19 + BIT21; + PINMODE2 |= BIT1; + FIO1DIR |= BIT0; + FIO3DIR |= BIT25 + BIT26; + FIO1SET = BIT0; + FIO3SET = BIT25 + BIT26; + + // Config and Disable PA + FIO1DIR |= BIT25 + BIT26 + BIT22; + FIO1SET = BIT26; + FIO1CLR = BIT25; + FIO1CLR = BIT22; // PA /Shutdown + FIO0DIR |= BIT26; // ** // Important: First put this Port as DA 2.0V and then turn on PA!! + FIO0SET = BIT26; // ** + + // Configure GPS + PINMODE3 |= BIT3 + BIT7; // No Pullup on 1.17 & 1.19 + PINMODE9 |= BIT27 + BIT25; // No Pullup for Uart + FIO1DIR |= BIT17; + FIO1CLR = BIT17; // Turn off GPS + FIO1DIR |= BIT19; + FIO1CLR = BIT19; // Hold in Reset + PINSEL9 |= BIT24 + BIT25 + BIT26 + BIT27; //4.28 & 4.29 as Uart3 + + // Nanotron + FIO2DIR &= ~BIT8; // nanotron uC IRQ as input + FIO1DIR |= BIT15; // nanotron power on reset + FIO1DIR &= ~BIT14; // nanotron uC RESET as input + FIO1DIR &= ~BIT10; // nanotron uC Vcc as input + FIO1DIR |= BIT9; // nanotron ENABLE as output + FIO1DIR &= ~BIT4; // nanotron Rx/Tx as input + + FIO1CLR = BIT15; + FIO1CLR = BIT9; // Enable power + + PINMODE1 |= BIT1; // No Pullup for CS + FIO0DIR |= BIT16; // CS as output + FIO0SET = BIT16; // drive cs inactive + FIO0DIR |= BIT18 + BIT15; // SPi Output + + // RFID + FIO1DIR |= BIT1; // RFID Power + FIO1CLR = BIT1; // + + FIO0DIR |= BIT1; // RFID Reset + FIO0SET = BIT1; // Hold in Reset + + FIO0DIR &= ~BIT10; // LED as INPUT + FIO0DIR &= ~BIT11; // DATA as INPUT + PINMODE0 |= BIT19 + BIT21; // No Pullups + + // LTC4150 ARM + FIO0DIR |= BIT5; + FIO0CLR = BIT5; + + // LTC4150 System + FIO0DIR |= BIT24; + FIO0CLR = BIT24; + + // Battery Voltage (AD) + PINMODE1 |= BIT19; + PINSEL1 &= ~BIT19; + PINSEL1 |= BIT18; + + //cc1100 + FIO0DIR |= BIT6 + BIT7 + BIT9; + FIO0SET = BIT6; + FIO0SET = BIT7 + BIT9; + + //SD + FIO2DIR |= BIT12 + BIT13 + BIT11; + FIO0DIR |= BIT20 + BIT22 + BIT21; + + //Tetra + FIO2DIR |= BIT0 + BIT7; + + + // No Pullups on any port + int nopullup = BIT1 + BIT3 + BIT5 + BIT7 + BIT9 + BIT11 + BIT13 + BIT15 + BIT17 + BIT19 + BIT21 + BIT23 + BIT25 + BIT27 + BIT29 + BIT31; + PINMODE0 = nopullup - BIT13 - BIT15 - BIT17 - BIT19; + PINMODE1 = BIT1 + BIT3 + BIT5 + BIT7 + BIT9 + BIT11 + BIT13 + BIT15 + BIT17 + BIT19 + BIT21; + PINMODE2 = nopullup; + PINMODE3 = nopullup; + PINMODE4 = nopullup; + PINMODE5 = nopullup; + PINMODE6 = nopullup; + PINMODE7 = nopullup; + PINMODE8 = nopullup; + PINMODE9 = nopullup; +} + +/** @} */ diff --git a/boards/pttu/include/board.h b/boards/pttu/include/board.h new file mode 100644 index 0000000000..ba7b3f42bf --- /dev/null +++ b/boards/pttu/include/board.h @@ -0,0 +1,58 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program 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. + +FeuerWare 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 +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef __BOARD_H +#define __BOARD_H + +/** + * @ingroup pttu + * @{ + */ + +/** + * @file + * @brief PTTU Board + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + * @version $Revision$ + * + * @note $Id: board.h 664 2009-02-19 10:54:44Z baar $ + */ + +#include +#include + +#define VICIntEnClear VICIntEnClr + +void init_clks1(void); +void init_clks2(void); +void bl_init_clks(void); + +typedef uint8_t radio_packet_length_t; + +/** @} */ +#endif // __BOARD_H diff --git a/boards/pttu/tools/jtag.txt b/boards/pttu/tools/jtag.txt new file mode 100644 index 0000000000..586eea6745 --- /dev/null +++ b/boards/pttu/tools/jtag.txt @@ -0,0 +1,14 @@ +compile openocd release v0.1: +[extract to somewhere] +./configure --prefix=CHANGEMEtowhatever --enable-ft2232_libftdi +make +make install + +to flash run from within board/pttu/tools: +./openocd-pttu.sh olimex-usb-jtag-tiny-a "mt_flash CHANGEME/absolute/path/to/hexfile/pttu.hex;shutdown" + + +to debug, first start the following from within board/pttu/tools: +./openocd-pttu.sh olimex-usb-jtag-tiny-a + +then just run "jam debug". this will flash bin/pttu.hex, run it and stop at the bootloader. diff --git a/boards/pttu/tools/olimex-arm-usb-ocd.cfg b/boards/pttu/tools/olimex-arm-usb-ocd.cfg new file mode 100644 index 0000000000..0aaba1d2bb --- /dev/null +++ b/boards/pttu/tools/olimex-arm-usb-ocd.cfg @@ -0,0 +1,9 @@ +# +set CPUTAPID 0x4f1f0f0f + +jtag_speed 100 + +source [find interface/olimex-arm-usb-ocd.cfg] +#source [find target/lpc2148.cfg] +source lpc2378.cfg + diff --git a/boards/pttu/tools/openocd-pttu.cfg b/boards/pttu/tools/openocd-pttu.cfg new file mode 100644 index 0000000000..b58392f1ee --- /dev/null +++ b/boards/pttu/tools/openocd-pttu.cfg @@ -0,0 +1,75 @@ +###### +# parts taken from Martin Thomas +# http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/openocd_intro/index.html +# + +set CPUTAPID 0x4f1f0f0f +jtag_speed 100 + +source [find cpu/lpc2387/tools/openocd-lpc2387.cfg] + +fast disable + +# +# scipts/macros/user commands - this is TCL (variant JIM): +# +proc mt_internal_rc {} { + jtag_khz 100 + reset run + sleep 100 + reset + halt + wait_halt 2 + # PLL disconnect PLLCON + mww 0xE01FC080 0x01 + mww 0xE01FC08C 0xAA + mww 0xE01FC08C 0x55 + # PLL disable PLLCON + mww 0xE01FC080 0x00 + mww 0xE01FC08C 0xAA + mww 0xE01FC08C 0x55 + # no prescaler CCLKCFG + mww 0xE01FC104 0x00 + # internal RC CLKSRCSEL + mww 0xE01FC10C 0x00 + #### main oscil. CLKSRCSEL + #### mww 0xE01FC10C 0x01 + # remap to internal flash + mww 0xE01FC040 0x01 + sleep 100 + jtag_khz 500 + flash probe 0 +} + +proc mt_flash_bin {IMGFILE OFFSET} { + mt_internal_rc + flash write_image erase $IMGFILE $OFFSET + sleep 100 + verify_image $IMGFILE $OFFSET + sleep 100 +} + +proc mt_flash_v {IMGFILE} { + mt_internal_rc + flash write_image erase $IMGFILE + sleep 100 + verify_image $IMGFILE + sleep 100 +} + +proc mt_flash {IMGFILE} { + mt_internal_rc + flash write_image erase $IMGFILE +} + +flash bank lpc2000 0x0 0x7d000 0 0 0 lpc2000_v2 4000 calc_checksum + +arm7_9 dcc_downloads enable + +gdb_flash_program enable + +init + +fast enable +jtag_khz 500 +debug_level 1 diff --git a/boards/pttu/tools/openocd-pttu.sh b/boards/pttu/tools/openocd-pttu.sh new file mode 100755 index 0000000000..95f11fa148 --- /dev/null +++ b/boards/pttu/tools/openocd-pttu.sh @@ -0,0 +1,30 @@ +#/bin/bash + +if [ $# -le 0 ]; then + echo "usage: $0 [openocd interface name] [openocd args]" >&2 + echo " common interfaces: olimex-arm-usb-ocd olimex-jtag-tiny olimex-jtag-tiny-a" + echo "" + echo "using default olimex-jtag-tiny-a" + INTERFACE=olimex-jtag-tiny-a +else + INTERFACE=$1 + shift +fi + +if [ $# -ge 1 ]; then + COMMAND=$@ +else + COMMAND="debug_level 1" +fi + +if [ "${OS}" = "Windows_NT" ]; then + WINDOWS=1 +fi + +if [ "x${WINDOWS}x" = "xx" ]; then + xterm -e "openocd -s ../../.. -f interface/${INTERFACE}.cfg -f board/pttu/tools/openocd-pttu.cfg -c \"${COMMAND}\"|| read" & +else + echo ${COMMAND} + #cmd /C start "OpenOCD PTTU using ${INTERFACE}" + openocd-ftd2xx.exe -s ../../.. -f interface/${INTERFACE}.cfg -f board/pttu/tools/openocd-pttu.cfg -c "${COMMAND}" +fi diff --git a/boards/pttu/tools/pttu_debug.gdb b/boards/pttu/tools/pttu_debug.gdb new file mode 100644 index 0000000000..2c8ec0df14 --- /dev/null +++ b/boards/pttu/tools/pttu_debug.gdb @@ -0,0 +1,15 @@ +#winheight regs 11 +set history save on +set history size 1000 +target remote localhost:3333 +monitor mt_internal_rc +load +compare-sections +monitor soft_reset_halt +set mem inaccessible-by-default off +monitor debug_level 0 + +break bootloader +continue +d b 1 + diff --git a/boards/redbee-econotag/Makefile b/boards/redbee-econotag/Makefile new file mode 100644 index 0000000000..8b1d55d8b4 --- /dev/null +++ b/boards/redbee-econotag/Makefile @@ -0,0 +1,32 @@ +SRC = $(wildcard *.c) +BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +DEP = $(SRC:%.c=$(BINDIR)%.d) +export ARCH = redbee-econotag_base.a + +INCLUDES += -I$(RIOTBOARD)/redbee-econotag/drivers/include +INCLUDES += -I$(RIOTBASE)/cpu/arm_common/include +INCLUDES += -I$(RIOTBASE)/cpu/mc1322x/include + +.PHONY: $(BINDIR)/$(ARCH) + +all: $(BINDIR)$(ARCH) + $(MAKE) -C drivers + +$(BINDIR)$(ARCH): $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(CFLAGS_MTHUMB) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(CFLAGS_MTHUMB) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + ${MAKE} -C drivers clean + rm -f $(OBJ) $(DEP) + diff --git a/boards/redbee-econotag/Makefile.dep b/boards/redbee-econotag/Makefile.dep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/boards/redbee-econotag/Makefile.include b/boards/redbee-econotag/Makefile.include new file mode 100644 index 0000000000..19179c3c2d --- /dev/null +++ b/boards/redbee-econotag/Makefile.include @@ -0,0 +1,29 @@ +## the cpu to build for +export CPU = mc1322x + +# toolchain config +export PREFIX = @arm-none-eabi- +export CC = @$(PREFIX)gcc +export AR = @$(PREFIX)ar +export CFLAGS = -std=gnu99 -march=armv4t -mtune=arm7tdmi-s -mlong-calls \ + -msoft-float -mthumb-interwork -fno-strict-aliasing -fno-common \ + -ffixed-r8 -ffunction-sections -ffreestanding -fno-builtin \ + -nodefaultlibs -Wcast-align -Wall -Wstrict-prototypes -Wextra \ + -Os -pipe +export CFLAGS_MTHUMB ?= -mthumb +$(warning TODO add -mthumb) +export AFLAGS = -Wa,-gstabs $(CFLAGS) +export AS = $(PREFIX)as +export LINK = $(PREFIX)gcc +export SIZE = $(PREFIX)size +export OBJCOPY = $(PREFIX)objcopy +FLASHER = mc1322x-load.pl +TERM = pyterm.py +LINKFLAGS = -mcpu=arm7tdmi-s -static -lgcc -nostartfiles -T$(RIOTBASE)/cpu/$(CPU)/mc1322x.lds + +ifeq ($(strip $(PORT)),) + export PORT = /dev/ttyUSB0 +endif +export HEXFILE = bin/$(PROJECT).hex +export FFLAGS = -t $(PORT) -f $(HEXFILE) -c 'bbmc -l redbee-econotag reset' +export OFLAGS = -O binary --gap-fill=0xff diff --git a/boards/redbee-econotag/README b/boards/redbee-econotag/README new file mode 100644 index 0000000000..7cce0fdd05 --- /dev/null +++ b/boards/redbee-econotag/README @@ -0,0 +1,11 @@ +Flashing: +tools/mc1322x-load.pl -f -t /dev/ + +more information: https://github.com/malvira/libmc1322x/wiki/libmc1322x#loading-images-to-ram-with-mc1322x-loadpl + +Erase: +cd tools/ftditools/ +make +./bbmc -l redbee-econotag erase + +more information: https://github.com/malvira/libmc1322x/wiki/bbmc \ No newline at end of file diff --git a/boards/redbee-econotag/board_init.c b/boards/redbee-econotag/board_init.c new file mode 100644 index 0000000000..18ac6c376c --- /dev/null +++ b/boards/redbee-econotag/board_init.c @@ -0,0 +1,22 @@ +/* + * board_init.c - redbee-econotag initialization code + * Copyright (C) 2013 Oliver Hahm + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +void board_init(void) +{ + asm("nop"); +} + +void bl_init_clks(void) +{ + // dummy to compile +} + +void bl_init_ports(void) +{ + // dummy to compile +} diff --git a/boards/redbee-econotag/drivers/Makefile b/boards/redbee-econotag/drivers/Makefile new file mode 100644 index 0000000000..cec1080b64 --- /dev/null +++ b/boards/redbee-econotag/drivers/Makefile @@ -0,0 +1,26 @@ +SRC = $(wildcard *.c) +BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o) +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBASE)/sys/include/ + +.PHONY: redbee-econotag_drivers.a + +$(BINDIR)redbee-econotag_common_drivers.a: $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(CFLAGS_MTHUMB) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(CFLAGS_MTHUMB) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)" | cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products + +clean: + rm -f $(OBJ) $(DEP) + diff --git a/boards/redbee-econotag/drivers/include/nvm.h b/boards/redbee-econotag/drivers/include/nvm.h new file mode 100644 index 0000000000..2a8c72bfeb --- /dev/null +++ b/boards/redbee-econotag/drivers/include/nvm.h @@ -0,0 +1,58 @@ +/* + * nvm.h - non-volatile memory specific definitions + * Copyright (C) 2013 Thomas Eichinger + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#ifndef NVM_H +#define NVM_H + +#include + +typedef enum +{ + g_nvm_type_no_nvm_c = 0, + g_nvm_type_SST_c, + g_nvm_type_ST_c, + g_nvm_type_ATM_c, + g_nvm_type_Max_c +} nvm_type_t; + + +typedef enum +{ + g_nvm_err_no_error_c = 0, + g_nvm_err_invalid_interface_c, + g_nvm_err_onvalid_nvm_type_c, + g_nvm_err_invalid_pointer_c, + g_nvm_err_write_protect_c, + g_nvm_err_verify_error_c, + g_nvm_err_address_space_overflow_c, + g_nvm_err_blank_check_error_c, + g_nvm_err_restricted_area_c, + g_nvm_err_max_error_c +} nvm_err_t; + +typedef enum +{ + g_nvm_internal_interface_c = 0, + g_nvm_external_interface_c, + g_nvm_interface_max_c +} nvm_interface_t; + +/* ROM code seems to be THUMB */ +/* need to be in a THUMB block before calling them */ +extern nvm_err_t (*nvm_detect)(nvm_interface_t nvm_interface,nvm_type_t* p_nvm_type); +extern nvm_err_t (*nvm_read)(nvm_interface_t nvm_interface , nvm_type_t nvm_type , void *p_dest, uint32_t address, uint32_t num_bytes); +extern nvm_err_t (*nvm_write)(nvm_interface_t nvm_interface, nvm_type_t nvm_type ,void *p_src, uint32_t address, uint32_t num_bytes); +/* sector bit field selects which sector to erase */ +/* SST flash has 32 sectors 4096 bytes each */ +/* bit 0 is the first sector, bit 31 is the last */ +extern nvm_err_t (*nvm_erase)(nvm_interface_t nvm_interface, nvm_type_t nvm_type ,uint32_t sector_bitfield); +extern void(*nvm_setsvar)(uint32_t zero_for_awesome); + +#endif //NVM_H diff --git a/boards/redbee-econotag/drivers/include/uart.h b/boards/redbee-econotag/drivers/include/uart.h new file mode 100644 index 0000000000..252bca811b --- /dev/null +++ b/boards/redbee-econotag/drivers/include/uart.h @@ -0,0 +1,105 @@ +/* + * uart.h - UART driver for redbee + * Copyright (C) 2013 Thomas Eichinger + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#ifndef UART_H +#define UART_H + +#include + +/*-----------------------------------------------------------------*/ +/* UART */ +#define UART1_BASE (0x80005000) +#define UART2_BASE (0x8000B000) + +struct UART_struct { + union { + uint32_t CON; + struct UART_CON { + uint32_t TXE: 1; /*< Tx Enable */ + uint32_t RXE: 1; /*< Rx Enable */ + uint32_t PEN: 1; /*< Parity Enable */ + uint32_t EP: 1; /*< Even Parity (1=Odd, 0=Even) */ + uint32_t ST2: 1; /*< Enable 2 Stop Bits */ + uint32_t SB: 1; /*< Send Break */ + uint32_t CONTX: 1; /*< Continuous Tx (Test Mode) */ + uint32_t TXOENB: 1; /*< TXD Outbut Disable */ + uint32_t : 2; /*< reserved */ + uint32_t XTIM: 1; /*< Times of Oversampling */ + uint32_t FCP: 1; /*< Flow Control Polarity */ + uint32_t FCE: 1; /*< Flow Control Enable */ + uint32_t MTXR: 1; /*< enable/disable TxRDY Interrupts */ + uint32_t MRXR: 1; /*< enable/disable RxRDY Interrupts */ + uint32_t TST: 1; /*< Test Loop-Back */ + uint32_t : 16; /*< reserved */ + } CONbits; + }; + union { + uint32_t STAT; + struct UART_STAT { + uint32_t SE: 1; /*< Start Bit Error */ + uint32_t PE: 1; /*< Parity Bit Error */ + uint32_t FE: 1; /*< Frame/Stop Bit Error */ + uint32_t TOE: 1; /*< Tx FIFO Overrun Error */ + uint32_t ROE: 1; /*< Rx FIFO Overrun Error */ + uint32_t RUE: 1; /*< Rx FIFO Underrun Error */ + uint32_t RXRDY: 1; /*< Receiver is causing Interrupts */ + uint32_t TXRDY: 1; /*< Transmitter is causing Interrupts */ + uint32_t : 24; + } USTATbits; + }; + union { + uint32_t DATA; + struct UART_DATA { + uint32_t DATA: 8; + uint32_t : 24; + } DATAbits; + }; + union { + uint32_t RXCON; + struct UART_URXCON { + uint32_t LVL: 6; + uint32_t : 26; + } RXCONbits; + }; + union { + uint32_t TXCON; + struct UART_TXCON { + uint32_t LVL: 6; + uint32_t : 26; + } TXCONbits; + }; + union { + uint32_t CTS; + struct UART_CTS { + uint32_t LVL: 5; + uint32_t : 27; + } CTSbits; + }; + + uint32_t BR; /*< BR is 32bit access only */ +}; + +static volatile struct UART_struct *const UART1 = (void *)(UART1_BASE); +static volatile struct UART_struct *const UART2 = (void *)(UART2_BASE); + +void uart_init(volatile struct UART_struct *uart, uint32_t baud); +void uart_set_baudrate(volatile struct UART_struct *uart, uint32_t baud); +void uart_flow_ctl(volatile struct UART_struct *uart, uint8_t on); + + +#define UART0_BUFSIZE (32) + +void uart1_putc(uint8_t c); +uint8_t uart1_getc(void); + +void uart2_putc(uint8_t c); +uint8_t uart2_getc(void); + +#endif \ No newline at end of file diff --git a/boards/redbee-econotag/drivers/nvm.c b/boards/redbee-econotag/drivers/nvm.c new file mode 100644 index 0000000000..5d4538ef26 --- /dev/null +++ b/boards/redbee-econotag/drivers/nvm.c @@ -0,0 +1,22 @@ +/* + * nvm.c - non-volatile memory implementations + * Copyright (C) 2013 Thomas Eichinger + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "nvm.h" + +nvm_err_t (*nvm_detect) (nvm_interface_t nvm_interface, nvm_type_t* p_nvm_type) + = (void*) 0x00006cb9; +nvm_err_t (*nvm_read) (nvm_interface_t nvm_interface, nvm_type_t nvm_type, void *p_dest, uint32_t address, uint32_t num_bytes) + = (void*) 0x00006d69; +nvm_err_t (*nvm_write) (nvm_interface_t nvm_interface, nvm_type_t nvm_type, void *p_src, uint32_t address, uint32_t numb_bytes) + = (void*) 0x00006ec5; +nvm_err_t (*nvm_erase) (nvm_interface_t nvm_interface, nvm_type_t nvm_type, uint32_t sector_bitfield) + = (void*) 0x00006e05; +void (*nvm_sets_var) (uint32_t zero_is_for_winners) + = (void*) 0x00007085; \ No newline at end of file diff --git a/boards/redbee-econotag/drivers/redbee_uart.c b/boards/redbee-econotag/drivers/redbee_uart.c new file mode 100644 index 0000000000..cdeb62bc98 --- /dev/null +++ b/boards/redbee-econotag/drivers/redbee_uart.c @@ -0,0 +1,185 @@ +/* + * redbee_uart.c - UART driver for redbee + * Copyright (C) 2013 Thomas Eichinger + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "mc1322x.h" +#include "uart.h" +#include "gpio.h" + +#define MOD_ 9999 +#define CLK_ 24000000 +#define DIV_ 16 /* uart->CON.XTIM = 0 is 16x oversample (datasheet is incorrect) */ +#define BAUTRATE_UART1 115200 +#define BAUTRATE_UART2 115200 + +void uart_set_baudrate(volatile struct UART_struct *uart, uint32_t baudrate) +{ + uint64_t inc = 0; + + /* calculate inc following equation 13-1 from datasheet */ + /* multiply by another 10 to get a fixed point*/ + inc = ((uint64_t) baudrate * DIV_ * MOD_ * 10 / CLK_) - 10; + /* add 5 and div by 10 to get a proper rounding */ + inc = (inc + 5) / 10; + + /* disable UARTx to set baudrate */ + uart->CONbits.TXE = 0; + uart->CONbits.RXE = 0; + + /* set baudrate */ + /* BR register is 32bit access only */ + uart->BR = (((uint16_t) inc << 16) | MOD_); + + /* reenable UARTx again */ + /* uart->CON.XTIM = 0 is 16x oversample (datasheet is incorrect) */ + uart->CONbits.XTIM = 0; + uart->CONbits.TXE = 1; + uart->CONbits.RXE = 1; +} + +void uart_flow_ctl(volatile struct UART_struct *uart, uint8_t on) +{ + if (on) { + /* enable flow control */ + if (uart == UART1) { + /* CTS and RTS directions */ + GPIO->PAD_DIR_SET.U1CTS = 1; + GPIO->PAD_DIR_RESET.U1RTS = 1; + /* function select to uart */ + GPIO->FUNC_SEL.U1CTS = 1; + GPIO->FUNC_SEL.U1RTS = 1; + } + else { + /* UART2 */ + /* CTS and RTS directions */ + GPIO->PAD_DIR_SET.U2CTS = 1; + GPIO->PAD_DIR_RESET.U2RTS = 1; + /* function select to uart */ + GPIO->FUNC_SEL.U2CTS = 1; + GPIO->FUNC_SEL.U2RTS = 1; + } + + /* enable flow control */ + uart->CONbits.FCE = 1; + } + else { + /* disable flow control */ + uart->CONbits.FCE = 0; + + if (uart == UART1) { + /* CTS and RTS directions */ + GPIO->PAD_DIR_RESET.U1CTS = 1; + GPIO->PAD_DIR_RESET.U1RTS = 1; + /* function select to GPIO */ + GPIO->FUNC_SEL.U1CTS = 3; + GPIO->FUNC_SEL.U1RTS = 3; + } + else { + /* CTS and RTS directions */ + GPIO->PAD_DIR_RESET.U2CTS = 1; + GPIO->PAD_DIR_RESET.U2RTS = 1; + /* function select to GPIO */ + GPIO->FUNC_SEL.U2CTS = 3; + GPIO->FUNC_SEL.U2RTS = 3; + } + } +} + +void uart_init(volatile struct UART_struct *uart, uint32_t baudrate) +{ + /* enable the uart so we can set the gpio mode */ + /* has to be enabled before setting the function with GPIO->FUNC_SEL */ + uart->CONbits.TXE = 1; + uart->CONbits.RXE = 1; + + if (uart == UART1) { + /* TX and RX direction */ + GPIO->PAD_DIR_SET.U1TX = 1; + GPIO->PAD_DIR_RESET.U1RX = 1; + + /* set function selection to UART */ + GPIO->FUNC_SEL.U1TX = 1; + GPIO->FUNC_SEL.U1RX = 1; + + UART1->CONbits.TXE = 1; /*< enable transmit */ + UART1->CONbits.RXE = 1; /*< enable receive */ + + UART1->CONbits.FCE = 1; /*< enable flowcontrol */ + UART1->CONbits.MRXR = 1; /*< disable Rx interrupt */ + UART1->CTSbits.LVL = 31; /*< drop cts when tx buffer at trigger level */ + GPIO->FUNC_SEL.U1CTS = 1; /*< set GPIO 16 to UART1 CTS */ + GPIO->FUNC_SEL.U1RTS = 1; /*< set GPIO 17 to UART1 RTS */ + + ITC->INTENABLEbits.UART1 = 1; + + } + else { + /* UART2 */ + /* TX and RX direction */ + GPIO->PAD_DIR_SET.U2TX = 1; + GPIO->PAD_DIR_RESET.U2RX = 1; + + /* set function selection to UART */ + GPIO->FUNC_SEL.U2TX = 1; + GPIO->FUNC_SEL.U2RX = 1; + + UART2->CONbits.TXE = 1; /*< enable transmit */ + UART2->CONbits.RXE = 1; /*< enable receive */ + + UART2->CONbits.FCE = 1; /*< enable flowcontrol */ + UART2->CONbits.MRXR = 1; /*< disable Rx interrupt */ + UART2->CTSbits.LVL = 31; /*< drop cts when tx buffer at trigger level */ + GPIO->FUNC_SEL.U2CTS = 1; /*< set GPIO 20 to UART2 CTS */ + GPIO->FUNC_SEL.U2RTS = 1; /*< set GPIO 21 to UART2 RTS */ + + ITC->INTENABLEbits.UART2 = 1; + } + + uart_set_baudrate(uart, baudrate); + +} + +static inline uint32_t uart0_puts(uint8_t *astring, uint32_t length) +{ + uint32_t i = 0; + + for (; i < length; i++) { + uart1_putc(astring[i]); + } + + return i; +} + +void stdio_flush(void) +{ + ITC->INTENABLEbits.UART1 = 0; + ITC->INTENABLEbits.UART2 = 0; + + while (UART1->RXCON != 0 || UART2->RXCON != 0) { + UART1->DATA; + UART2->DATA; + } + while (UART1->TXCON != 0 || UART2->TXCON != 0) { + /* wait */ + } + + ITC->INTENABLEbits.UART1 = 1; + ITC->INTENABLEbits.UART2 = 1; +} + + +int fw_puts(char *astring, int length) +{ + return uart0_puts((uint8_t *) astring, (uint32_t) length); +} + +int bl_uart_init(void) +{ + uart_init(UART1, BAUTRATE_UART1); +} \ No newline at end of file diff --git a/boards/redbee-econotag/drivers/redbee_uart1.c b/boards/redbee-econotag/drivers/redbee_uart1.c new file mode 100644 index 0000000000..690d13d381 --- /dev/null +++ b/boards/redbee-econotag/drivers/redbee_uart1.c @@ -0,0 +1,58 @@ +/* + * uart1.c - UART1 driver for redbee + * Copyright (C) 2013 Oliver Hahm + * 2013 Thomas Eichinger + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "mc1322x.h" +#include "board_uart0.h" +#include "uart.h" + +void uart1_isr(void) +{ + uint32_t i = 0; + + if (UART1->USTATbits.RXRDY == 1) { +#ifdef MODULE_UART0 + + if (uart0_handler_pid) { + while (UART1->RXCON != 0) { + uart0_handle_incoming(UART1->DATA); + + if (++i >= UART0_BUFSIZE) { + uart0_notify_thread(); + i = 0; + } + } + + uart0_notify_thread(); + } + +#endif + } +} + +void uart1_putc(uint8_t c) +{ + /* while uart fifo is full */ + while (UART1->TXCON == 0) { + /* wait */ + } + + UART1->DATA = c; +} + +uint8_t uart1_getc(void) +{ + /* while uart fifo is empty */ + while (UART1->RXCON == 0) { + /* wait */ + } + + return UART1->DATA; +} \ No newline at end of file diff --git a/boards/redbee-econotag/drivers/redbee_uart2.c b/boards/redbee-econotag/drivers/redbee_uart2.c new file mode 100644 index 0000000000..013d424159 --- /dev/null +++ b/boards/redbee-econotag/drivers/redbee_uart2.c @@ -0,0 +1,58 @@ +/* + * uart1.c - UART1 driver for redbee + * Copyright (C) 2013 Oliver Hahm + * 2013 Thomas Eichinger + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "mc1322x.h" +#include "board_uart0.h" +#include "uart.h" + +void uart2_isr(void) +{ + uint32_t i = 0; + + if (UART2->USTATbits.RXRDY == 1) { +#ifdef MODULE_UART0 + + if (uart0_handler_pid) { + while (UART2->RXCON != 0) { + uart0_handle_incoming(UART2->DATA); + + if (++i >= UART0_BUFSIZE) { + uart0_notify_thread(); + i = 0; + } + } + + uart0_notify_thread(); + } + +#endif + } +} + +void uart2_putc(uint8_t c) +{ + /* while uart fifo is full */ + while (UART2->TXCON == 0) { + /* wait */ + } + + UART2->DATA = c; +} + +uint8_t uart2_getc(void) +{ + /* while uart fifo is empty */ + while (UART2->RXCON == 0) { + /* wait */ + } + + return UART2->DATA; +} \ No newline at end of file diff --git a/boards/redbee-econotag/include/board.h b/boards/redbee-econotag/include/board.h new file mode 100644 index 0000000000..bbcb2b07d3 --- /dev/null +++ b/boards/redbee-econotag/include/board.h @@ -0,0 +1,17 @@ +/** + * board.h - redbee-econotag Board. + * Copyright (C) 2013 Thomas Eichinger + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#ifndef REDBEE_ECONOTAG_BOARD_H +#define REDBEE_ECONOTAG_BOARD_H + +#define CTUNE 0xb +#define IBIAS 0x1f +#define FTUNE 0x7 + +#endif + diff --git a/boards/redbee-econotag/tools/ftditools/Makefile b/boards/redbee-econotag/tools/ftditools/Makefile new file mode 100644 index 0000000000..521d7d14ff --- /dev/null +++ b/boards/redbee-econotag/tools/ftditools/Makefile @@ -0,0 +1,17 @@ +INSTALL= /usr/local/bin + +################ + +LDLIBS = -lftdi + +TARGETS = bbmc + +CFLAGS = -Wall -Wextra #-Werror + +all: $(TARGETS) + +clean: + -rm -f $(TARGETS) + +install: all + cp bbmc $(INSTALL) \ No newline at end of file diff --git a/boards/redbee-econotag/tools/ftditools/bbmc.c b/boards/redbee-econotag/tools/ftditools/bbmc.c new file mode 100644 index 0000000000..f211f52eee --- /dev/null +++ b/boards/redbee-econotag/tools/ftditools/bbmc.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2010, Mariano Alvira and other contributors + * to the MC1322x project (http://mc1322x.devl.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of libmc1322x: see http://mc1322x.devl.org + * for details. + * + * + */ + +/* control reset and VREF2 lines */ + +#include +#include +#include +#include +#include + +#define DEBUG 0 + +#define low(x) (1 << x) +#define high(x) (1 << (x + 8)) + +#define REDBEE_ECONOTAG_RESET high(2) +#define REDBEE_ECONOTAG_VREF2L high(7) +#define REDBEE_ECONOTAG_VREF2H high(6) +#define REDBEE_ECONOTAG_INTERFACE INTERFACE_A + +#define REDBEE_USB_RESET high(2) +#define REDBEE_USB_VREF2L low(5) +#define REDBEE_USB_VREF2H low(6) +#define REDBEE_USB_INTERFACE INTERFACE_B + +#define FLEXIBITY_USB_RESET high(2) +#define FLEXIBITY_USB_VREF2L high(7) +#define FLEXIBITY_USB_VREF2H high(6) +#define FLEXIBITY_USB_INTERFACE INTERFACE_A + +#define BOARD REDBEE_USB + +#define STR(x) #x +#define STR2(x) STR(x) +#define CAT(x,y) x##y +#define CAT2(x, y, z) x##y##z + +#define dir(x) ( CAT(x,_RESET) | CAT(x,_VREF2L) | CAT(x,_VREF2H)) +#define interface(x) ( CAT(x,_INTERFACE) ) +#define reset_release(x) ( CAT(x,_RESET) ) +#define reset_set(x) ( 0 ) +#define vref2_normal(x) ( CAT(x,_VREF2H) ) +#define vref2_erase(x) ( CAT(x,_VREF2L) ) + +/* fgets input buffer length: for prompts and such */ +#define BUF_LEN 32 + +struct layout { + char *name; + char *desc; + enum ftdi_interface interface; + uint16_t dir; + uint16_t reset_release; + uint16_t reset_set; + uint16_t vref2_normal; + uint16_t vref2_erase; +}; + +int print_and_prompt(struct ftdi_device_list *devlist); +int bb_mpsee(struct ftdi_context *ftdic, uint16_t dir, uint16_t val); +void reset(struct ftdi_context *ftdic, const struct layout *l); +void erase(struct ftdi_context *ftdic, const struct layout *l); +void usage(void); + +#define std_layout(x) \ + .interface = interface(x), \ + .dir = dir(x), \ + .reset_release = reset_release(x), \ + .reset_set = reset_set(x), \ + .vref2_normal = vref2_normal(x), \ + .vref2_erase = vref2_erase(x), + +static struct layout layouts[] = { + { + .name = "redbee-econotag", + .desc = "Redbee Econotag", + std_layout(REDBEE_ECONOTAG) + }, + { + .name = "redbee-usb", + .desc = "Redbee USB stick", + std_layout(REDBEE_USB) + }, + { + .name = "flexibity", + .desc = "Flexibity USB Interface", + std_layout(FLEXIBITY_USB) + }, + { .name = NULL, /* end of table */ }, +}; + +struct command { + char *name; + char *desc; + void (*cmd)(struct ftdi_context *ftdic, const struct layout *l); +}; + +static const struct command commands[] = { + { + .name = "reset", + .desc = "Toggles reset pin", + .cmd = reset, + }, + { + .name = "erase", + .desc = "Sets VREF2 erase mode; toggles reset; waits 2 sec.; sets normal; toggles reset again", + .cmd = erase, + }, + { .name = NULL, /* end of table */ }, +}; + +struct layout *find_layout(char *str) +{ + uint32_t i = 0; + + while (layouts[i].name != NULL) { + if (strcmp(layouts[i].name, str) == 0) { + return &layouts[i]; + } + + i++; + } + + return NULL; +} + +static uint32_t vendid = 0x0403; +uint32_t prodid = 0x6010; + +#if __APPLE__ +static void restore_ftdi_kext(void) +{ + system("sudo kextload /System/Library/Extensions/FTDIUSBSerialDriver.kext"); +} +#endif + +int main(int argc, char **argv) +{ + struct ftdi_context ftdic; + struct ftdi_device_list *devlist; + int dev_index = -1; + int num_devs; + char layout_str[BUF_LEN]; + struct layout layout; + struct layout *l = NULL; + int i, ret; + + /* overrides for layout parameters */ + int interface = -1; + int dir = -1; + int reset_release = -1; + int reset_set = -1; + int vref2_normal = -1; + int vref2_erase = -1; + + layout.name = NULL; + + while (1) { + int c; + int option_index = 0; + static struct option long_options[] = { + {"layout", required_argument, 0, 'l'}, + {"index", required_argument, 0, 'i'}, + {"vendor", required_argument, 0, 'v'}, + {"product", required_argument, 0, 'p'}, + {"dir", required_argument, 0, 0 }, + {"reset_release", required_argument, 0, 0 }, + {"reset_set", required_argument, 0, 0 }, + {"vref2_normal", required_argument, 0, 0 }, + {"vref2_erase", required_argument, 0, 0 }, + {"interface", required_argument, 0, 0 }, + {"help", no_argument, 0, '?'}, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, argv, "i:l:v:p:", + long_options, &option_index); + + if (c == -1) { + break; + } + + switch (c) { + /* process long opts */ + case 0: + if (strcmp(long_options[option_index].name, "interface") == 0) { + sscanf(optarg, "%i", &interface); + } + + if (strcmp(long_options[option_index].name, "dir") == 0) { + sscanf(optarg, "%i", &dir); + } + + if (strcmp(long_options[option_index].name, "reset_release") == 0) { + sscanf(optarg, "%i", &reset_release); + } + + if (strcmp(long_options[option_index].name, "reset_set") == 0) { + sscanf(optarg, "%i", &reset_set); + } + + if (strcmp(long_options[option_index].name, "vref2_normal") == 0) { + sscanf(optarg, "%i", &vref2_normal); + } + + if (strcmp(long_options[option_index].name, "vref2_erase") == 0) { + sscanf(optarg, "%i", &vref2_erase); + } + + break; + + case 'l': + strncpy(layout_str, optarg, BUF_LEN); + break; + + case 'i': + dev_index = atoi(optarg); + break; + + case 'v': + sscanf(optarg, "%i", &vendid); + break; + + case 'p': + sscanf(optarg, "%i", &prodid); + break; + + default: + usage(); + break; + } + } + + if (!(l = find_layout(layout_str)) && + !((interface >= 0) && + (dir >= 0) && + (reset_release >= 0) && + (reset_set >= 0) && + (vref2_normal >= 0) && + (vref2_erase >= 0)) + ) { + + printf("*** You must specify a layout or a complete set of overrides\n"); + return EXIT_FAILURE; + } + + if (l) { + memcpy(&layout, l, sizeof(struct layout)); + } + +#define override(x) if(x > 0) { layout.x = x; } + override(interface); + override(dir); + override(reset_release); + override(reset_set); + override(vref2_normal); + override(vref2_erase); + + if ((num_devs = ftdi_usb_find_all(&ftdic, &devlist, vendid, prodid)) < 0) { + fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", + num_devs, + ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + + if (ftdi_init(&ftdic) < 0) { + fprintf(stderr, "ftdi_init failed\n"); + return EXIT_FAILURE; + } + + if ((ret = ftdi_set_interface(&ftdic, layout.interface)) < 0) { + fprintf(stderr, "couldn't set interface %d, err %d (%s)\n", layout.interface, ret, ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + + printf("Found %d devices with vendor id 0x%04x product id 0x%04x\n", + num_devs, vendid, prodid); + + if (num_devs == 0) { + return EXIT_SUCCESS; + } + + if (num_devs == 1) { + dev_index = 0; + } + + while ((dev_index < 0) || (dev_index >= num_devs)) { + dev_index = print_and_prompt(devlist); + } + + if (layout.name != NULL) { + printf("Opening device %d interface %d using layout %s\n", + dev_index, layout.interface, layout.name); + } + else { + printf("Opening device %d interface %d without a layout.\n", + dev_index, layout.interface); + } + + if ((ret = ftdi_usb_open_desc_index( + &ftdic, + vendid, + prodid, + NULL, + NULL, + dev_index)) < 0) { +#if __APPLE__ + + if ((ret == -5) && (0 == system("sudo kextunload /System/Library/Extensions/FTDIUSBSerialDriver.kext"))) { + // Try again without the FTDI kext loaded this time + atexit(&restore_ftdi_kext); + ret = ftdi_usb_open_desc_index( + &ftdic, + vendid, + prodid, + NULL, + NULL, + dev_index + ); + } + + if (ret) +#endif // __APPLE__ + { + fprintf(stderr, "couldn't open dev_index %d, err %d (%s)\n", dev_index, ret, ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + } + + + for (i = 0; commands[i].name != NULL; i++) { + if ((argv[optind] != NULL) && + (strcmp(commands[i].name, argv[optind]) == 0)) { + break; + } + } + + if (commands[i].name != NULL) { + commands[i].cmd(&ftdic, &layout); + } + else { + printf("invalid command\n"); + + ftdi_list_free(&devlist); + ftdi_deinit(&ftdic); + + return EXIT_FAILURE; + } + + printf("done.\n"); + + ftdi_list_free(&devlist); + ftdi_deinit(&ftdic); + + return EXIT_SUCCESS; +} + +void usage(void) +{ + int i; + printf("Usage: bbmc [options|overrides] -l|--layout layout command \n"); + printf("Commands:\n"); + + for (i = 0; commands[i].name != NULL; i++) { + printf(" %s: %s\n", commands[i].name, commands[i].desc); + } + + printf("\n"); + printf("Required options:\n"); + printf(" -l|--layout\t specifiy which board layout to use\n"); + printf(" \t layout is not necessary with a full\n"); + printf(" \t set of overrides\n"); + printf("\nLayout overrides:\n"); + printf(" --interface\t\t FTDI interface to use\n"); + printf(" --dir\t\t direction (1 is output)\n"); + printf(" --reset_release\t reset release command\n"); + printf(" --reset_set\t\t reset set command\n"); + printf(" --vref2_normal\t vref2 normal\n"); + printf(" --vref2_erase\t vref2 erase\n"); + printf("\n"); + printf("Layouts:\n"); + + for (i = 0; layouts[i].name != NULL; i++) { + printf("\t%s: %s\n", layouts[i].name, layouts[i].desc); + printf("\n"); + printf("\t\tinterface: \t0x%04x\n", layouts[i].interface); + printf("\t\tdir: \t\t0x%04x\n", layouts[i].dir); + printf("\t\treset release: \t0x%04x\n", layouts[i].reset_release); + printf("\t\treset hold: \t0x%04x\n", layouts[i].reset_set); + printf("\t\tvref2 normal: \t0x%04x\n", layouts[i].vref2_normal); + printf("\t\tvref2 erase: \t0x%04x\n", layouts[i].vref2_erase); + printf("\n"); + } + + printf("\n"); + printf("Options:\n"); + printf(" -i|--index specifiy which device to use (default 0)\n"); + printf(" -v|--vendor set vendor id (default 0x0403)\n"); + printf(" -p|--product set vendor id (default 0x6010)\n"); +} + +int print_and_prompt(struct ftdi_device_list *devlist) +{ + int i, ret; + struct ftdi_context ftdic; + struct ftdi_device_list *curdev; + char manufacturer[128], description[128], serial[128]; + char input[BUF_LEN]; + char *s; + int sel = -1; + + printf("\n"); + + i = 0; + + for (curdev = devlist; curdev != NULL; i++) { + printf(" [%d] ", i); + + if (0 > (ret = ftdi_usb_get_strings(&ftdic, + curdev->dev, + manufacturer, 128, + description, 128, + serial, 128))) { + fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", + ret, ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + + printf("Manufacturer: %s, Description: %s, Serial %s\n", + manufacturer, description, serial); + curdev = curdev->next; + } + + printf("\nUse which device? "); + + s = fgets(input, BUF_LEN, stdin); + + if (s != NULL) { + size_t last = strlen(input) - 1; + + if (input[last] == '\n') { + input[last] = '\0'; + } + } + + sscanf(s, "%i", &sel); + + return sel; +} + +void reset(struct ftdi_context *ftdic, const struct layout *l) +{ + + /* using MPSSE since it give access to high GPIO*/ + /* set as inputs for now */ + ftdi_set_bitmode(ftdic, 0 , BITMODE_MPSSE); + + printf("toggle reset\n"); + + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); + bb_mpsee(ftdic, l->dir, (l->reset_set | l->vref2_normal)); + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); + + return; + +} + + +void erase(struct ftdi_context *ftdic, const struct layout *l) +{ + printf("setting VREF2 erase\n"); + + /* using MPSSE since it give access to high GPIO*/ + /* set as inputs for now */ + ftdi_set_bitmode(ftdic, 0 , BITMODE_MPSSE); + + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_erase)); + + printf("toggle reset\n"); + + bb_mpsee(ftdic, l->dir, (l->reset_set | l->vref2_erase)); + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_erase)); + + printf("waiting for erase\n"); + + sleep(2); + + printf("setting VREF2 normal\n"); + + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); + + reset(ftdic, l); + + return; + +} + + +int bb_mpsee(struct ftdi_context *ftdic, uint16_t dir, uint16_t val) +{ + uint8_t buf[3]; + int ret; + + /* command "set data bits low byte" */ + buf[0] = 0x80; + buf[1] = (val & 0xff); + buf[2] = dir & 0xff; +#if DEBUG + fprintf(stderr, "write %x %x %x\n", buf[0], buf[1], buf[2]); +#endif + + if ((ret = (ftdi_write_data(ftdic, buf, 3))) < 0) { + perror("ft2232_write error"); + fprintf(stderr, "ft2232_write command %x\n", buf[0]); + return EXIT_FAILURE; + } + + + /* command "set data bits high byte" */ + buf[0] = 0x82; + buf[1] = (val >> 8); + buf[2] = dir >> 8; +#if DEBUG + fprintf(stderr, "write %x %x %x\n", buf[0], buf[1], buf[2]); +#endif + + if ((ret = (ftdi_write_data(ftdic, buf, 3))) < 0) { + perror("ft2232_write error"); + fprintf(stderr, "ft2232_write command %x\n", buf[0]); + return EXIT_FAILURE; + } + + return 0; + +} diff --git a/boards/redbee-econotag/tools/mc1322x-load.c b/boards/redbee-econotag/tools/mc1322x-load.c new file mode 100644 index 0000000000..82c59520b9 --- /dev/null +++ b/boards/redbee-econotag/tools/mc1322x-load.c @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2012, Maxim Osipov + * Copyright (c) 2010, Mariano Alvira and other contributors + * to the MC1322x project (http://mc1322x.devl.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +char *filename; +char *second; +char *term = "/dev/ttyUSB0"; +int baud = B115200; +int verbose = 0; +char *rts = "rts"; +char *command; +int first_delay = 50; +int second_delay = 100; +int do_exit = 0; +int zerolen = 0; +char *args = NULL; + +struct stat sbuf; +struct termios options; +char buf[256]; +int pfd; +int ffd; +int sfd; + +void help(void); + +int main(int argc, char **argv) +{ + int c = 0; + int r = 0; + int i = 0; + uint32_t s = 0; + opterr = 0; + + /* Parse options */ + while ((c = getopt(argc, argv, "f:s:zt:vu:r:c:a:b:eh")) != -1) { + switch (c) { + case 'f': + filename = optarg; + break; + + case 's': + second = optarg; + break; + + case 'z': + zerolen = 1; + break; + + case 't': + term = optarg; + break; + + case 'v': + verbose = 1; + break; + + case 'u': + if (strcmp(optarg, "115200")) { + baud = B115200; + } + else if (strcmp(optarg, "57600")) { + baud = B115200; + } + else if (strcmp(optarg, "19200")) { + baud = B19200; + } + else if (strcmp(optarg, "9600")) { + baud = B9600; + } + else { + printf("Unknown baud rate %s!\n", optarg); + return -1; + } + + break; + + case 'r': + rts = optarg; + break; + + case 'c': + command = optarg; + break; + + case 'a': + first_delay = atoi(optarg); + break; + + case 'b': + second_delay = atoi(optarg); + break; + + case 'e': + do_exit = 1; + break; + + case 'h': + case '?': + help(); + return 0; + + default: + abort(); + } + } + + /* Get other arguments */ + if (optind < argc) { + args = argv[optind]; + } + + /* Print settings */ + if (verbose) { + printf("Primary file (RAM): %s\n", filename); + printf("Secondary file (Flash): %s\n", second); + printf("Zero secondary file: %s\n", zerolen == 1 ? "Yes" : "No"); + printf("Port: %s\n", term); + printf("Baud rate: %i\n", baud); + printf("Flow control: %s\n", rts); + printf("Reset command: %s\n", command); + printf("Exit after load: %s\n", do_exit == 1 ? "Yes" : "No"); + printf("Delay 1: %i\n", first_delay); + printf("Delay 2: %i\n", second_delay); + } + + /* Open and configure serial port */ + pfd = open(term, O_RDWR | O_NOCTTY | O_NDELAY); + + if (pfd == -1) { + printf("Cannot open serial port %s!\n", term); + return -1; + } + + fcntl(pfd, F_SETFL, FNDELAY); + tcgetattr(pfd, &options); + cfsetispeed(&options, baud); + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + + if (strcmp(rts, "rts")) { + options.c_cflag &= ~CRTSCTS; + } + else { + options.c_cflag |= CRTSCTS; + } + + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_oflag &= ~OPOST; + tcsetattr(pfd, TCSANOW, &options); + + /* Reset the board if we can */ + printf("Reset the board to enter bootloader (waiting for CONNECT)...\n"); + + if (command) { + printf("Performing reset: %s\n", command); + system(command); + } + + /* Primary bootloader wait loop */ + i = 0; + + while (1) { + /* Wait for CONNECT */ + r = write(pfd, (const void *)"\0", 1); + sleep(1); + r = read(pfd, &buf[i], sizeof(buf) - 1 - i); + + if (r > 0) { + buf[i + r] = '\0'; + printf("%s", &buf[i]); + fflush(stdout); + + if (strstr(&buf[i], "CONNECT")) { + printf("\n"); + break; + } + + i += r; + + if (i >= sizeof(buf) - 1) { + i = 0; + } + } + else { + printf("."); + fflush(stdout); + } + } + + /* Send primary file */ + if (!filename) { + printf("Please specify firmware file name (-f option)!\n"); + return -1; + } + + if (stat(filename, &sbuf)) { + printf("Cannot open firmware file %s!\n", filename); + return -1; + } + + ffd = open(filename, O_RDONLY); + + if (ffd == -1) { + printf("Cannot open firmware file %s!\n", filename); + return -1; + } + + s = sbuf.st_size; + printf("Sending %s (%i bytes)...\n", filename, s); + r = write(pfd, (const void *)&s, 4); + i = 0; + r = read(ffd, buf, 1); + + while (r > 0) { + do { + usleep(first_delay); + c = write(pfd, (const void *)buf, r); + } + while (c < r); + + i += r; + printf("Written %i\r", i); + fflush(stdout); + r = read(ffd, buf, 1); + } + + printf("\n"); + + /* Secondary loader wait loop */ + if (second || zerolen) { + /* Wait for ready */ + printf("Sending secondary file (waiting for ready)...\n"); + i = 0; + + while (1) { + sleep(1); + r = read(pfd, &buf[i], sizeof(buf) - 1 - i); + + if (r > 0) { + buf[i + r] = '\0'; + printf("%s", &buf[i]); + fflush(stdout); + + if (strstr(buf, "ready")) { + printf("\n"); + break; + } + + i += r; + + if (i >= sizeof(buf) - 1) { + i = 0; + } + } + else { + printf("."); + fflush(stdout); + } + } + + /* Send secondary file */ + if (second) { + if (stat(second, &sbuf)) { + printf("Cannot open secondary file %s!\n", second); + return -1; + } + + sfd = open(second, O_RDONLY); + + if (sfd == -1) { + printf("Cannot open secondary file %s!\n", second); + return -1; + } + + s = sbuf.st_size; + printf("Sending %s (%i bytes)...\n", second, s); + r = write(pfd, (const void *)&s, 4); + i = 0; + r = read(sfd, buf, 1); + + while (r > 0) { + do { + usleep(second_delay); + c = write(pfd, (const void *)buf, r); + } + while (c < r); + + i += r; + printf("Written %i\r", i); + fflush(stdout); + r = read(sfd, buf, 1); + } + + printf("\n"); + } + else if (zerolen) { + s = 0; + printf("Sending %i...\n", s); + write(pfd, (const void *)&s, 4); + } + } + + /* Send the remaining arguments */ + if (args) { + printf("Sending %s\n", args); + r = write(pfd, (const void *)args, strlen(args)); + r = write(pfd, (const void *)",", 1); + } + + /* Drop in echo mode */ + if (!do_exit) { + while (1) { + r = read(pfd, buf, sizeof(buf)); + + if (r > 0) { + buf[r] = '\0'; + printf("%s", buf); + fflush(stdout); + } + } + } +} + + +void help(void) +{ + printf("Example usage: mc1322x-load -f foo.bin -t /dev/ttyS0 -b 9600\n"); + printf(" or : mc1322x-load -f flasher.bin -s flashme.bin 0x1e000,0x11223344,0x55667788\n"); + printf(" or : mc1322x-load -f flasher.bin -z 0x1e000,0x11223344,0x55667788\n"); + printf(" -f required: binary file to load\n"); + printf(" -s optional: secondary binary file to send\n"); + printf(" -z optional: send a zero length file as secondary\n"); + printf(" -t, terminal default: /dev/ttyUSB0\n"); + printf(" -u, baud rate default: 115200\n"); + printf(" -r [none|rts] flow control default: rts\n"); + printf(" -c command to run for autoreset: \n"); + printf(" e.g. -c 'bbmc -l redbee-econotag -i 0 reset'\n"); + printf(" -e exit instead of dropping to terminal display\n"); + printf(" -a first intercharacter delay, passed to usleep\n"); + printf(" -b second intercharacter delay, passed to usleep\n"); + printf("\n"); + printf("Anything on the command line is sent after all of the files.\n\n"); +} diff --git a/boards/redbee-econotag/tools/mc1322x-load.pl b/boards/redbee-econotag/tools/mc1322x-load.pl new file mode 100755 index 0000000000..bfc1d1ffcd --- /dev/null +++ b/boards/redbee-econotag/tools/mc1322x-load.pl @@ -0,0 +1,171 @@ +#!/usr/bin/perl -w + +use Device::SerialPort; +use Term::ReadKey; +use Getopt::Long; +use Time::HiRes qw(usleep); + +use strict; + +my $filename = ''; +my $second = ''; +my $term = '/dev/ttyUSB0'; +my $baud = '115200'; +my $verbose; +my $rts = 'rts'; +my $command = ''; +my $first_delay = 50; +my $second_delay = 100; +my $do_exit; +my $zerolen; + +GetOptions ('file=s' => \$filename, + 'secondfile=s' => \$second, + 'zerolen' => \$zerolen, + 'terminal=s' => \$term, + 'verbose' => \$verbose, + 'u|baud=s' => \$baud, + 'rts=s' => \$rts, + 'command=s' => \$command, + 'a=s' => \$first_delay, + 'b=s' => \$second_delay, + 'exit' => \$do_exit, + ) or die 'bad options'; + +$| = 1; + +if($filename eq '') { + print "Example usage: mc1322x-load.pl -f foo.bin -t /dev/ttyS0 -b 9600\n"; + print " or : mc1322x-load.pl -f flasher.bin -s flashme.bin 0x1e000,0x11223344,0x55667788\n"; + print " or : mc1322x-load.pl -f flasher.bin -z 0x1e000,0x11223344,0x55667788\n"; + print " -f required: binary file to load\n"; + print " -s optional: secondary binary file to send\n"; + print " -z optional: send a zero length file as secondary\n"; + print " -t, terminal default: /dev/ttyUSB0\n"; + print " -u, --baud baud rate default: 115200\n"; + print " -r [none|rts] flow control default: rts\n"; + print " -c command to run for autoreset: \n"; + print " e.g. -c 'bbmc -l redbee-econotag -i 0 reset'\n"; + print " -e exit instead of dropping to terminal display\n"; + print " -a first intercharacter delay, passed to usleep\n"; + print " -b second intercharacter delay, passed to usleep\n"; + print "\n"; + print "anything on the command line is sent\n"; + print "after all of the files.\n\n"; + exit; +} + +if (!(-e $filename)) { die "file $filename not found\n"; } +if (($second ne '') && !(-e $second)) { die "secondary file $second not found\n"; } + +my $ob = Device::SerialPort->new ($term) or die "Can't start $term\n"; + # next test will die at runtime unless $ob + +$ob->baudrate($baud); +$ob->parity('none'); +$ob->databits(8); +$ob->stopbits(1); +if($rts eq 'rts') { + $ob->handshake('rts'); +} else { + $ob->handshake('none'); +} +$ob->read_const_time(1000); # 1 second per unfulfilled "read" call +$ob->rts_active(1); + +my $s = 0; +my $reset = 0; +my $size = 0; + +while(1) { + + my $c; my $count; my $ret = ''; my $test=''; + + if($s == 1) { print "secondary send...\n"; } + + $ob->write(pack('C','0')); + + if(($command ne '') && + ($reset eq 0)) { + $reset++; + system($command); + } + + if($s == 1) { + $test = 'ready'; + } else { + $test = 'CONNECT'; + } + + until($ret =~ /$test$/) { + ($count,$c) = $ob->read(1); + if ($count == 0) { + print '.'; + $ob->write(pack('C','0')); + next; + } + $ret .= $c; + } + print $ret . "\n"; + + if (-e $filename || (defined($zerolen) && ($s == 1))) { + + if(defined($zerolen) && ($s == 1)) { + $size = 0; + } else { + $size = -s $filename; + } + + print ("Size: $size bytes\n"); + $ob->write(pack('V',$size)); + + if(($s == 0) || + ((!defined($zerolen)) && ($s == 1))) { + open(FILE, $filename) or die($!); + print "Sending $filename\n"; + + my $i = 1; + while(read(FILE, $c, 1)) { + $i++; + usleep($first_delay) if ( $s == 0 ) && ($first_delay != 0); + usleep($second_delay) if ( $s == 1 ) && ($second_delay != 0); + $ob->write($c); + } + } + } + + last if ($s==1); + if((-e $second) || defined($zerolen)) { + $s=1; $filename = $second; + } else { + last; + } + +} + +print "done sending files.\n"; + +if(scalar(@ARGV)!=0) { + print "sending " ; + print @ARGV; + print ",\n"; + + $ob->write(@ARGV); + $ob->write(','); +} + +if(defined($do_exit)) { + exit; +} + +my $c; my $count; +while(1) { + ($count, $c) = $ob->read(1); + print $c if (defined($count) && ($count != 0)); +} + +$ob -> close or die "Close failed: $!\n"; +ReadMode 0; +undef $ob; # closes port AND frees memory in perl +exit; + diff --git a/boards/telosb/Makefile b/boards/telosb/Makefile new file mode 100644 index 0000000000..c5eb97b3bc --- /dev/null +++ b/boards/telosb/Makefile @@ -0,0 +1,34 @@ +SRC = $(wildcard *.c) +BINDIR = bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +export ARCH = telosb_base.a + +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I${RIOTBOARD}/${BOARD}/include/ +INCLUDES += -I${RIOTBASE}/core/include/ +INCLUDES += -I$(RIOTBASE)/cpu/msp430-common/include/ -I$(RIOTBASE)/cpu/msp430x16x/include/ +INCLUDES += -I$(RIOTBASE)/drivers/cc2420/include/ -I$(RIOTBASE)/sys/include +INCLUDES += -I$(RIOTBASE)/sys/net/include + +all: $(BINDIR)$(ARCH) + +$(BINDIR)$(ARCH): $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + mkdir -p $(BINDIR) + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + rm -f $(BINDIR)$(ARCH) $(OBJ) $(DEP) + @if [ -d $(BINDIR) ] ; \ + then rmdir $(BINDIR) ; \ + fi diff --git a/boards/telosb/Makefile.dep b/boards/telosb/Makefile.dep new file mode 100644 index 0000000000..4392a18adb --- /dev/null +++ b/boards/telosb/Makefile.dep @@ -0,0 +1,2 @@ +USEMODULE += msp430_common + diff --git a/boards/telosb/Makefile.include b/boards/telosb/Makefile.include new file mode 100644 index 0000000000..e07ce0f5da --- /dev/null +++ b/boards/telosb/Makefile.include @@ -0,0 +1,25 @@ +include $(RIOTBOARD)/$(BOARD)/Makefile.dep +## the cpu to build for +export CPU = msp430x16x +export MCU = msp430f1611 + +# toolchain config +export PREFIX = @msp430- +export CC = @$(PREFIX)gcc +export AR = @$(PREFIX)ar +export CFLAGS += -std=gnu99 -Wstrict-prototypes -gdwarf-2 -Os -Wall -mmcu=$(MCU) +export ASFLAGS += -mmcu=$(MCU) --defsym $(MCU)=1 --gdwarf-2 +export AS = $(PREFIX)as +export LINK = $(PREFIX)gcc +export SIZE = $(PREFIX)size +export OBJCOPY = $(PREFIX)objcopy +export LINKFLAGS = -mmcu=$(MCU) -lgcc $(RIOTBASE)/bin/startup.o +export TERMPROG = $(RIOTBASE)/dist/tools/pyterm/pyterm.py +export FLASHER = goodfet.bsl +ifeq ($(strip $(PORT)),) + export PORT = /dev/ttyUSB0 +endif +export HEXFILE = bin/$(PROJECT).hex +export FFLAGS = --telosb -c $(PORT) -r -e -I -p $(HEXFILE) + +export INCLUDES += -I $(RIOTCPU)/msp430-common/include/ diff --git a/boards/telosb/board.c b/boards/telosb/board.c new file mode 100644 index 0000000000..37b21b4caa --- /dev/null +++ b/boards/telosb/board.c @@ -0,0 +1,127 @@ + /* + * board.c - Board initiazilation for the TelosB + * Copyright (C) 2013 Oliver Hahm + * + * This file subject to the terms and conditions of the LGPLv2. See the file + * LICENSE in the top level directory for more details. + */ + +#include "cpu.h" +#include "board.h" + +void uart_init(void); + +static void telosb_ports_init(void) +{ + /* Port 1: GDO, Flash, BSL TX */ + P1SEL = 0x02; /* Port1 Select: 00000010 = 0x02 */ + P1OUT = 0x00; /* Port1 Output: 00000000 = 0x00 */ + P1DIR = 0x87; /* Port1 Direction: 10000111 = 0x87 */ + + /* Port 2: GPIO, BSL RX, 1wire */ + P2SEL = 0x04; /* Port2 Select: 00000100 = 0x04 */ + P2OUT = 0x00; /* Port2 Output: 00000000 = 0x00 */ + P2DIR = 0xFF; /* Port2 Direction: 11111111 = 0xFF */ + + /* Port 3: UART and SPI */ + P3SEL = 0xCE; /* Port3 Select: 11001110 = 0xCE */ + P3OUT = 0x00; /* Port3 Output: 00000000 = 0x00 */ + P3DIR = 0x4E; /* Port3 Direction: 01001110 = 0x4E */ + + /* Port 4: CS */ + P4SEL = 0x02; /* Port4 Select: 00000010 = 0x02 */ + P4OUT = 0x04; /* Port4 Output: 00000100 = 0x04 */ + P4DIR = 0x64; /* Port4 Direction: 01100100 = 0x64 */ + + /* Port 5: SPI, LED */ + P5SEL = 0x00; /* Port5 Select: 00000000 = 0x00 */ + P5OUT = 0x70; /* Port5 Output: 01110000 = 0x70 */ + P5DIR = 0x70; /* Port5 Direction: 01110000 = 0x70 */ + + + P6SEL = 0xFF; /* Port6 Select: 11111111 = 0xFF */ + P6OUT = 0x00; /* Port6 Output: 00000000 = 0x00 */ + P6DIR = 0xFF; /* Port6 Direction: 11111000 = 0xFF */ + +} + +/*---------------------------------------------------------------------------*/ +/* taken from Contiki code */ +void msp430_init_dco(void) +{ + /* This code taken from the FU Berlin sources and reformatted. */ +#define DELTA (F_CPU / (F_RC_OSCILLATOR / 8)) + + unsigned int compare, oldcapture = 0; + unsigned int i; + + /* 10100100 = XT2 is off, ACLK divided by 4, RSELx=4 */ + BCSCTL1 = XT2OFF | DIVA_2 | RSEL2; + + /* Init undivided DCO with internal resistor for MCLK and SMCLK + * DCO = 32762Hz -> FLL = 2,4576 MHz */ + BCSCTL2 = 0x00; + + BCSCTL1 |= DIVA1 + DIVA0; /* ACLK = LFXT1CLK/8 */ + + for (i = 0xFFFF; i > 0; i--) { /* Delay for XTAL to settle */ + asm("nop"); + } + + CCTL2 = CCIS0 + CM0 + CAP; /* Define CCR2, CAP, ACLK */ + TACTL = TASSEL1 + TACLR + MC1; /* SMCLK, continous mode */ + + while (1) { + while ((CCTL2 & CCIFG) != CCIFG); /* Wait until capture occured!*/ + + CCTL2 &= ~CCIFG; /* Capture occured, clear flag */ + compare = CCR2; /* Get current captured SMCLK */ + compare = compare - oldcapture; /* SMCLK difference */ + oldcapture = CCR2; /* Save current captured SMCLK */ + + if (DELTA == compare) { + break; /* if equal, leave "while (1)" */ + } + else if (DELTA < compare) { /* DCO is too fast, slow it down */ + DCOCTL--; + + if (DCOCTL == 0xFF) { /* Did DCO role under? */ + BCSCTL1--; + } + } + else { /* -> Select next lower RSEL */ + DCOCTL++; + + if (DCOCTL == 0x00) { /* Did DCO role over? */ + BCSCTL1++; + } + + /* -> Select next higher RSEL */ + } + } + + CCTL2 = 0; /* Stop CCR2 function */ + TACTL = 0; /* Stop Timer_A */ + + BCSCTL1 &= ~(DIVA1 + DIVA0); /* remove /8 divisor from ACLK again */ +} + + +//=========================== public ========================================== + +void board_init(void) +{ + msp430_cpu_init(); + /* disable watchdog timer */ + WDTCTL = WDTPW + WDTHOLD; + + telosb_ports_init(); + + msp430_init_dco(); + + /* initialize bsp modules */ + uart_init(); + + /* enable interrupts */ + __bis_SR_register(GIE); +} diff --git a/boards/telosb/driver_cc2420.c b/boards/telosb/driver_cc2420.c new file mode 100644 index 0000000000..4ee7ce9d1d --- /dev/null +++ b/boards/telosb/driver_cc2420.c @@ -0,0 +1,222 @@ + /* + * driver_cc2420.c - Implementation of the board dependent cc2420 functions. + * Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + * Copyright (C) 2013 Oliver Hahm + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include + +#include +#include +#include +#include + +#include + +#define ENABLE_DEBUG (1) +#include "debug.h" + +#define CC2420_RESETn_PIN 0x40 +#define CC2420_VREGEN_PIN 0x20 + +#define CC2420_FIFOP_PIN 0x01 +#define CC2420_GIO0_PIN 0x08 +#define CC2420_GIO1_PIN 0x10 +#define CC2420_CCA_PIN 0x40 +#define CC2420_SFD_PIN 0x02 + +#define CC2420_FIFOP (P1IN & CC2420_FIFOP_PIN) /* FIFOP <-> packet interrupt (P1.0) */ +#define CC2420_GIO0 (P1IN & CC2420_GIO0_PIN) /* FIFO <-> GIO0 - RX data available (P1.3) */ +#define CC2420_GIO1 (P1IN & CC2420_GIO1_PIN) /* CCA <-> GIO1 - clear channel (P1.4) */ +#define CC2420_SFD (P4IN & CC2420_SFD_PIN) /* SFD <-> TBL - start frame delimiter (P4.1) */ + +#define CC2420_CS_LOW (P4OUT &= ~0x04) /* P4.2 */ +#define CC2420_CS_HIGH (P4OUT |= 0x04) + +volatile int abort_count; +volatile int retry_count = 0; + +void cc2420_reset(void) +{ + P4OUT |= CC2420_VREGEN_PIN; + P4OUT &= ~CC2420_RESETn_PIN; + hwtimer_wait(500); + P4OUT |= CC2420_RESETn_PIN; +} + +void cc2420_gio0_enable(void) +{ + P1IFG &= ~CC2420_GIO0_PIN; /* Clear IFG for GIO0 */ + P1IE |= CC2420_GIO0_PIN; /* Enable interrupt for GIO0 */ +} + +void cc2420_gio0_disable(void) +{ + P1IE &= ~CC2420_GIO0_PIN; /* Disable interrupt for GIO0 */ + P1IFG &= ~CC2420_GIO0_PIN; /* Clear IFG for GIO0 */ +} + +void cc2420_gio1_enable(void) +{ + P1IFG &= ~CC2420_GIO1_PIN; /* Clear IFG for GIO1 */ + P1IE |= CC2420_GIO1_PIN; /* Enable interrupt for GIO1 */ +} + +void cc2420_gio1_disable(void) +{ + P1IE &= ~CC2420_GIO1_PIN; /* Disable interrupt for GIO1 */ + P1IFG &= ~CC2420_GIO1_PIN; /* Clear IFG for GIO1 */ +} + +void cc2420_before_send(void) +{ + /* Disable SFD interrupt before sending packet */ + /* However this is not used atm */ +} + +void cc2420_after_send(void) +{ + /* Enable SFD interrupt after sending packet */ + /* However this is not used atm */ +} + + +int cc2420_get_gio0(void) +{ + return CC2420_GIO0; +} + +int cc2420_get_gio1(void) +{ + return CC2420_GIO1; +} + +int cc2420_get_fifop(void) +{ + return CC2420_FIFOP; +} + +int cc2420_get_sfd(void) +{ + return CC2420_SFD; +} + +void cc2420_spi_cs(void) +{ + CC2420_CS_LOW; +} + +uint8_t cc2420_txrx(uint8_t data) +{ + /* Ensure TX Buf is empty */ + long c = 0; + IFG1 &= ~UTXIFG0; + IFG1 &= ~URXIFG0; + U0TXBUF = data; + while(!(IFG1 & UTXIFG0)) { + if (c++ == 1000000) { + puts("cc2420_txrx alarm()"); + } + } + /* Wait for Byte received */ + c = 0; + while(!(IFG1 & URXIFG0)) { + if (c++ == 1000000) { + puts("cc2420_txrx alarm()"); + } + } + return U0RXBUF; +} + + +void cc2420_spi_select(void) +{ + CC2420_CS_LOW; +} + +void cc2420_spi_unselect(void) { + CC2420_CS_HIGH; +} + +void cc2420_init_interrupts(void) +{ + unsigned int state = disableIRQ(); /* Disable all interrupts */ + P1SEL &= ~CC2420_FIFOP_PIN; /* must be <> 1 to use interrupts */ + P1SEL &= ~CC2420_GIO0_PIN; /* must be <> 1 to use interrupts */ + + /* FIFO <-> GIO0 interrupt */ + P1IES |= CC2420_GIO0_PIN; /* Enables external interrupt on falling edge (for GIO0/FIFO) */ + P1IE |= CC2420_GIO0_PIN; /* Enable interrupt */ + P1IFG &= ~CC2420_GIO0_PIN; /* Clears the interrupt flag */ + + /* FIFOP <-> Packet interrupt */ + P1IE |= CC2420_FIFOP_PIN; /* Enable interrupt for FIFOP */ + P1IFG &= ~CC2420_FIFOP_PIN; /* Clear IFG for FIFOP */ + restoreIRQ(state); /* Enable all interrupts */ +} + +void cc2420_spi_init(void) +{ + /* Switch off async UART */ + while(!(U0TCTL & TXEPT)); /* Wait for empty UxTXBUF register */ + IE1 &= ~(URXIE0 + UTXIE0); /* Disable USART0 receive&transmit interrupt */ + ME1 &= ~(UTXE0 + URXE0); + + /* configure SPI-related pins */ + P3SEL |= 0x0E; /* P3.1 - SIMO mode, P3.2 - SOMI mode, P3.3 - SCL mode */ + P3DIR |= 0x0A; /* P3.1 and P3.3 as output */ + P3DIR &= ~(0x04); /* P3.2 as input for SOMI */ + P4OUT |= 0x04; /* P4.2 radio CS, hold high */ + P4DIR |= 0x04; /* P4.2 radio CS, output */ + + /* Keep peripheral in reset state */ + U0CTL = SWRST; + + /* 8-bit SPI Master 3-pin mode, with SMCLK as clock source */ + /* CKPL works also, but not CKPH+CKPL or none of them!! */ + U0CTL |= CHAR + SYNC + MM; + U0TCTL = CKPH + SSEL1 + SSEL0 + STC + TXEPT;; + + /* Ignore clockrate argument for now, just use clock source/2 */ + /* SMCLK = 8 MHz */ + U0BR0 = 0x02; /* Ensure baud rate >= 2 */ + U0BR1 = 0x00; + U0MCTL = 0x00; /* No modulation */ + U0RCTL = 0x00; /* Reset Receive Control Register */ + + /* Enable SPI mode */ + ME1 |= USPIE0; + + /* Release for operation */ + U0CTL &= ~SWRST; +} + +/* + * CC1100 receive interrupt + */ +interrupt (PORT1_VECTOR) __attribute__ ((naked)) cc2420_isr(void) +{ + __enter_isr(); + /* Check IFG */ + if ((P1IFG & CC2420_FIFOP_PIN) != 0) { + P1IFG &= ~CC2420_FIFOP_PIN; + cc2420_rx_irq(); + DEBUG("rx interrupt"); + } + /* GIO0 is falling => check if FIFOP is high, indicating an RXFIFO overflow */ + else if ((P1IFG & CC2420_GIO0) != 0) { + P1IFG &= ~CC2420_GIO0_PIN; + if (cc2420_get_fifop()) { + cc2420_rxoverflow_irq(); + DEBUG("[CC2420] rxfifo overflow"); + } + } + else { + puts("cc2420_isr(): unexpected IFG!"); + /* Should not occur - only GDO1 and GIO1 interrupts are enabled */ + } + __exit_isr(); +} diff --git a/boards/telosb/include/board-conf.h b/boards/telosb/include/board-conf.h new file mode 100644 index 0000000000..f65074da9d --- /dev/null +++ b/boards/telosb/include/board-conf.h @@ -0,0 +1,13 @@ +/** + * board-conf.h. + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#ifndef BOARD_CONF_H +#define BOARD_CONF_H + +#define INFOMEM (0x1000) + +#endif /* BOARD-CONF_H */ diff --git a/boards/telosb/include/board.h b/boards/telosb/include/board.h new file mode 100644 index 0000000000..55fd2a35b4 --- /dev/null +++ b/boards/telosb/include/board.h @@ -0,0 +1,61 @@ +/** + * board.h - TelosB Board. + * Copyright (C) 2013 INRIA + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#ifndef _TELOSB_BOARD_H +#define _TELOSB_BOARD_H + +/** + * @defgroup TelosB + * @ingroup TelosB + * +

Compontents

+\li MSP430 +\li CC2420 + +* @{ +*/ + +/** + * @file + * @brief TelosB Board + * + * @author Oliver Hahm + * + */ + +//MSB430 core +#define MSP430_INITIAL_CPU_SPEED 8000000uL +#define MSP430_HAS_DCOR 0 +#define MSP430_HAS_EXTERNAL_CRYSTAL 1 + +/* LEDs ports MSB430 */ +#define LEDS_PxDIR P5DIR +#define LEDS_PxOUT P5OUT +#define LEDS_CONF_RED 0x10 +#define LEDS_CONF_GREEN 0x20 +#define LEDS_CONF_BLUE 0x40 + +#define LED_RED_ON LEDS_PxOUT &=~LEDS_CONF_RED +#define LED_RED_OFF LEDS_PxOUT |= LEDS_CONF_RED +#define LED_RED_TOGGLE LEDS_PxOUT ^= LEDS_CONF_RED + +#define LED_GREEN_ON LEDS_PxOUT &=~LEDS_CONF_GREEN +#define LED_GREEN_OFF LEDS_PxOUT |= LEDS_CONF_GREEN +#define LED_GREEN_TOGGLE LEDS_PxOUT ^= LEDS_CONF_GREEN + +#define LED_BLUE_ON LEDS_PxOUT &=~LEDS_CONF_BLUE +#define LED_BLUE_OFF LEDS_PxOUT |= LEDS_CONF_BLUE +#define LED_BLUE_TOGGLE LEDS_PxOUT ^= LEDS_CONF_BLUE + +#include +#include + +typedef uint8_t radio_packet_length_t; + +/** @} */ +#endif // _TELOSB_BOARD_H diff --git a/boards/telosb/uart.c b/boards/telosb/uart.c new file mode 100644 index 0000000000..1e97bfb569 --- /dev/null +++ b/boards/telosb/uart.c @@ -0,0 +1,118 @@ +/* + * uart.c - Implementation for the TelosB UART + * Copyright (C) 2013 Oliver Hahm + * + * This file subject to the terms and conditions of the LGPLv2. See the file + * LICENSE in the top level directory for more details. + */ + +#include +#include +#include "cpu.h" +#include "board.h" +#include "kernel.h" +#include "board_uart0.h" + +#define UART1_TX U1TXBUF +#define UART1_WAIT_TXDONE() while ( (U1TCTL & TXEPT) == 0 ) { _NOP(); } + +#define BAUDRATE (115200ul) + +static uint8_t calc_umctl(uint16_t br) +{ + /* from TI slaa049 */ + register uint8_t CMOD = 256 * br - 256 * (br + 1) / 2; + register uint8_t c = 0; + register int i = 0; + register uint8_t a = CMOD; + a <<= 1; + + do { + if (a & 0x80) { /* Overflow to integer? */ + a = a - 128 + CMOD; /* Yes, subtract 1.000000 */ + c |= 0x80; + } + else { + a += CMOD; /* No, add fraction */ + } + + if (i == 7) { + return c; + } + + i++; + c >>= 1; + } + while (1); +} + +void uart_init(void) +{ + UCTL1 = SWRST; /* hold UART1 module in reset */ + UCTL1 |= CHAR; /* 8-bit character */ + + /* 115200 baud, clocked from 4.8MHz SMCLK */ + UTCTL1 |= SSEL1; /* UCLK = SCLK */ + UBR01 = F_CPU / BAUDRATE; + UBR11 = (F_CPU / BAUDRATE) >> 8; + UMCTL1 = calc_umctl(F_CPU / BAUDRATE); /* set modulation */ + + ME2 |= UTXE1 + URXE1; /* enable UART1 TX/RX */ + UCTL1 &= ~SWRST; /* clear UART1 reset bit */ + + IE2 |= URXIE1; /* enable rx interrupt */ + IFG1 &= ~UTXIFG1; +} + +int putchar(int c) +{ + UART1_TX = c; + UART1_WAIT_TXDONE(); + return c; +} + +uint8_t uart_readByte(void) +{ + return U1RXBUF; +} + +void usart1irq(void); +/** + * \brief the interrupt function + */ +interrupt(USART1RX_VECTOR) usart1irq(void) +{ + int c = 0; + + /* Check status register for receive errors. */ + if (U1RCTL & RXERR) { + if (U1RCTL & FE) { + puts("rx framing error"); + } + + if (U1RCTL & OE) { + puts("rx overrun error"); + } + + if (U1RCTL & PE) { + puts("rx parity error"); + } + + if (U1RCTL & BRK) { + puts("rx break error"); + } + + /* Clear error flags by forcing a dummy read. */ + c = U1RXBUF; + } + +#ifdef MODULE_UART0 + else if (uart0_handler_pid) { + c = U1RXBUF; + uart0_handle_incoming(c); + uart0_notify_thread(); + } + +#endif +} + diff --git a/boards/wsn430-common/Makefile b/boards/wsn430-common/Makefile new file mode 100644 index 0000000000..8f8f23add9 --- /dev/null +++ b/boards/wsn430-common/Makefile @@ -0,0 +1,33 @@ +SRC = $(wildcard *.c) +BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I$(RIOTBOARD)/wsn430-common/include/ -I${RIOTBOARD}/${BOARD}/include/ +INCLUDES += -I$(RIOTBASE)/cpu/msp430-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/mspx16x/include/ +INCLUDES += -I$(RIOTBASE)/drivers/include/ + +.PHONY: $(BINDIR)$(ARCH) + +all: $(BINDIR)$(ARCH) + #$(MAKE) -C drivers + +$(BINDIR)$(ARCH): $(OBJ) + echo $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + #$(MAKE) -C drivers clean + rm -f $(OBJ) $(DEP) + rm -f $(BINDIR)$(ARCH) diff --git a/boards/wsn430-common/Makefile.include b/boards/wsn430-common/Makefile.include new file mode 100644 index 0000000000..346044a309 --- /dev/null +++ b/boards/wsn430-common/Makefile.include @@ -0,0 +1,25 @@ +## the cpu to build for +export CPU = msp430x16x +export MCU = msp430f1611 + +# toolchain config +export PREFIX = @msp430- +export CC = @$(PREFIX)gcc +export AR = @$(PREFIX)ar +export CFLAGS += -std=gnu99 -Wstrict-prototypes -gdwarf-2 -Os -Wall -mmcu=$(MCU) +export ASFLAGS += -mmcu=$(MCU) --defsym $(MCU)=1 --gdwarf-2 +export AS = $(PREFIX)as +export LINK = $(PREFIX)gcc +export SIZE = $(PREFIX)size +export OBJCOPY = $(PREFIX)objcopy +export LINKFLAGS = -mmcu=$(MCU) -lgcc $(RIOTBASE)/bin/startup.o +export FLASHER = mspdebug +ifeq ($(strip $(PORT)),) + export PORT = /dev/ttyUSB0 +endif +export HEXFILE = bin/$(PROJECT).hex +export FFLAGS = -d $(PORT) -j uif "prog $(HEXFILE)" + +export INCLUDES += -I $(RIOTCPU)/msp430-common/include/ -I$(RIOTBASE)/sys/net/include/ +export OFLAGS = -O ihex + diff --git a/boards/wsn430-common/board_config.c b/boards/wsn430-common/board_config.c new file mode 100644 index 0000000000..4e9bc0b69c --- /dev/null +++ b/boards/wsn430-common/board_config.c @@ -0,0 +1,26 @@ +/** + * board-config.c. + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include +#include +#include +#include +#include + +void config_load(void) { + if (*((uint16_t*) INFOMEM) == CONFIG_KEY) { + memcpy(&sysconfig, (char*) (INFOMEM + sizeof(CONFIG_KEY)), sizeof(sysconfig)); + } + else { + config_save(); + } +} + +uint8_t config_save(void) { + configmem_t mem = { CONFIG_KEY, sysconfig }; + return (flashrom_erase((uint8_t*) INFOMEM) && flashrom_write((uint8_t*) INFOMEM, (char*) &mem, sizeof(mem))); +} diff --git a/boards/wsn430-common/board_init.c b/boards/wsn430-common/board_init.c new file mode 100644 index 0000000000..9b84c699bc --- /dev/null +++ b/boards/wsn430-common/board_init.c @@ -0,0 +1,152 @@ + /* + * board_init.c - Implementation of functions to init board. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include "cpu.h" +#include "board.h" +#include "kernel_internal.h" +#include "msp430.h" +#include "debug.h" + +volatile static uint32_t __msp430_cpu_speed = MSP430_INITIAL_CPU_SPEED; + +void msp430_init_dco(void); + +typedef enum { + MCLK_2MHZ_SCLK_1MHZ = 1000002uL, + MCLK_4MHZ_SCLK_1MHZ = 1000004uL, + MCLK_8MHZ_SCLK_1MHZ = 1000008uL, + MCLK_8MHZ_SCLK_8MHZ = 8000000uL +}speed_t; + +/*---------------------------------------------------------------------------*/ +static uint8_t calc_umctl(uint16_t br) { + // from TI slaa049 + register uint8_t CMOD = 256 * br - 256 * (br + 1) / 2; + register uint8_t c = 0; + register int i = 0; + register uint8_t a = CMOD; + a <<= 1; + do { + if( a & 0x80 ) { // Overflow to integer? + a = a - 128 + CMOD; // Yes, subtract 1.000000 + c |= 0x80; + } else { + a += CMOD; // No, add fraction + } + if( i == 7 ) { + return c; + } + i++; + c >>= 1; + } while(1); +} + +static void msb_ports_init(void) +{ + // Port 1: GDO, Flash, BSL TX + P1SEL = 0x02; // Port1 Select: 00000010 = 0x02 + P1OUT = 0x00; // Port1 Output: 00000000 = 0x00 + P1DIR = 0x87; // Port1 Direction: 10000111 = 0x87 + + // Port 2: GPIO, BSL RX, 1wire + P2SEL = 0x04; // Port2 Select: 00000100 = 0x04 + P2OUT = 0x00; // Port2 Output: 00000000 = 0x00 + P2DIR = 0xFF; // Port2 Direction: 11111111 = 0xFF + + + // Port 3: UART + P3SEL = 0xFE; // Port3 Select: 11111110 = 0xFE + P3OUT = 0x00; // Port3 Output: 00000000 = 0x00 + P3DIR = 0xFF; // Port3 Direction: 11111111 = 0xFF + + + // Port 4: CS + P4SEL = 0x00; // Port4 Select: 00000000 = 0x00 + P4OUT = 0x14; // Port4 Output: 00010100 = 0x14 + P4DIR = 0xFF; // Port4 Direction: 11111111 = 0xFF + + // Port 5: SPI, LED + P5SEL = 0x0E; // Port5 Select: 00001110 = 0x0E + P5OUT = 0x70; // Port5 Output: 01110000 = 0x70 + P5DIR = 0x70; // Port5 Direction: 01110000 = 0x70 + + + P6SEL = 0xFF; // Port6 Select: 11111111 = 0xFF + P6OUT = 0x00; // Port6 Output: 00000000 = 0x00 + P6DIR = 0xFF; // Port6 Direction: 11111000 = 0xF8 + +} + +void msp430_set_cpu_speed(uint32_t speed) +{ + + dint(); + __msp430_cpu_speed = speed; + msp430_init_dco(); + uint16_t br; + + U0CTL = SWRST; + U0CTL = SWRST | CHAR; // 8-bit character + U0TCTL = SSEL1 | TXEPT; // UCLK = SCLK + U0RCTL = 0; + // activate + ME1 |= UTXE0 + URXE0; // Enable USART0 TXD/RXD + br = (uint16_t)((__msp430_cpu_speed & 0xFFFFF0) / 115200uL); + UBR00 = br; // set baudrate + UBR10 = br>>8; + UMCTL0 = calc_umctl(br); // set modulation + + U0CTL &= ~SWRST; + + //URCTL0 |= URXEIE; // allow chars to interrupt + IE1 |= URXIE0; // enable rx interrupt + IFG1 &= ~UTXIFG0; + eint(); +} + +/*---------------------------------------------------------------------------*/ +void msp430_init_dco(void) +{ + /*----------------------- use external oszillator -------------------------*/ + uint16_t i; + + // Stop watchdog + WDTCTL = WDTPW + WDTHOLD; + + BCSCTL1 = RSEL2; + + // Wait for xtal to stabilize + do { + IFG1 &= ~OFIFG; // Clear oscillator fault flag + for (i = 0xFF; i > 0; i--); // Time for flag to set + } + while ((IFG1 & OFIFG) != 0); // Oscillator fault flag still set? + switch (__msp430_cpu_speed) { + case MCLK_2MHZ_SCLK_1MHZ: + BCSCTL2 = (SELM_2 | DIVM_2) | (SELS | DIVS_3); + break; + case MCLK_4MHZ_SCLK_1MHZ: + BCSCTL2 = (SELM_2 | DIVM_1) | (SELS | DIVS_3); + break; + case MCLK_8MHZ_SCLK_1MHZ: + BCSCTL2 = SELM_2 | (SELS | DIVS_3); + break; + default: + BCSCTL2 = SELM_2 + SELS; // MCLK and SMCLK = XT2 (safe) + break; + } +} + +void board_init() { + msp430_cpu_init(); + msb_ports_init(); + + LED_RED_ON; + + msp430_set_cpu_speed(MCLK_8MHZ_SCLK_8MHZ); +} diff --git a/boards/wsn430-common/drivers/Makefile b/boards/wsn430-common/drivers/Makefile new file mode 100644 index 0000000000..e69de29bb2 diff --git a/boards/wsn430-common/include/board-conf.h b/boards/wsn430-common/include/board-conf.h new file mode 100644 index 0000000000..e54b3d58eb --- /dev/null +++ b/boards/wsn430-common/include/board-conf.h @@ -0,0 +1,15 @@ +/** + * board-conf.h. + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#ifndef BOARD_CONF_H +#define BOARD_CONF_H + +#include + +#define INFOMEM (0x1000) + +#endif /* BOARD-CONF_H */ diff --git a/boards/wsn430-common/uart0.c b/boards/wsn430-common/uart0.c new file mode 100644 index 0000000000..f743335ec4 --- /dev/null +++ b/boards/wsn430-common/uart0.c @@ -0,0 +1,63 @@ + /* + * uart0.c - Implementation of the uart. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + */ + +#include "board.h" + +#define UART0_TX U0TXBUF +#define UART0_WAIT_TXDONE() while( (U0TCTL & TXEPT) == 0 ) { _NOP(); } + +#include +#include + +#include + +int putchar(int c) +{ + UART0_TX = c; + UART0_WAIT_TXDONE(); + + if (c == 10) { + UART0_TX = 13; + UART0_WAIT_TXDONE(); + } + + return c; +} + +void usart0irq(void); +/** + * \brief the interrupt function + */ +interrupt(USART0RX_VECTOR) usart0irq(void) { + int dummy = 0; + /* Check status register for receive errors. */ + if(U0RCTL & RXERR) { + if (U0RCTL & FE) { + puts("rx framing error"); + } + if (U0RCTL & OE) { + puts("rx overrun error"); + } + if (U0RCTL & PE) { + puts("rx parity error"); + } + if (U0RCTL & BRK) { + puts("rx break error"); + } + /* Clear error flags by forcing a dummy read. */ + dummy = U0RXBUF; + } +#ifdef MODULE_UART0 + else if (uart0_handler_pid) { + dummy = U0RXBUF; + uart0_handle_incoming(dummy); + uart0_notify_thread(); + } +#endif +} + diff --git a/boards/wsn430-v1_3b/Makefile b/boards/wsn430-v1_3b/Makefile new file mode 100644 index 0000000000..e19884c6b1 --- /dev/null +++ b/boards/wsn430-v1_3b/Makefile @@ -0,0 +1,36 @@ +SRC = $(wildcard *.c) +BINDIR = bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +export ARCH = wsn430-v1_3b_base.a + +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I${RIOTBASE}/core/include/ +INCLUDES += -Iinclude/ -I$(RIOTBOARD)/wsn430-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/msp430-common/include/ -I$(RIOTBASE)/cpu/msp430x16x/include/ +INCLUDES += -I$(RIOTBASE)/drivers/cc110x_ng/include/ -I$(RIOTBASE)/sys/include +#INCLUDES += -I/usr/msp430/include/ + +all: $(BINDIR)$(ARCH) + $(MAKE) -C ../wsn430-common + +$(BINDIR)$(ARCH): $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + mkdir -p $(BINDIR) + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + $(MAKE) -C ../wsn430-common clean + rm -f $(BINDIR)$(ARCH) $(OBJ) $(DEP) + @if [ -d $(BINDIR) ] ; \ + then rmdir $(BINDIR) ; \ + fi \ No newline at end of file diff --git a/boards/wsn430-v1_3b/Makefile.dep b/boards/wsn430-v1_3b/Makefile.dep new file mode 100644 index 0000000000..5463317289 --- /dev/null +++ b/boards/wsn430-v1_3b/Makefile.dep @@ -0,0 +1,7 @@ +ifneq (,$(findstring cc110x_ng,$(USEMODULE))) + ifeq (,$(findstring cc110x_spi,$(USEMODULE))) + USEMODULE += cc110x_spi + endif +endif + +USEMODULE += msp430_common \ No newline at end of file diff --git a/boards/wsn430-v1_3b/Makefile.include b/boards/wsn430-v1_3b/Makefile.include new file mode 100644 index 0000000000..267a2fb9cd --- /dev/null +++ b/boards/wsn430-v1_3b/Makefile.include @@ -0,0 +1,4 @@ +export INCLUDES += -I$(RIOTBOARD)/wsn430-common/include +include $(RIOTBOARD)/$(BOARD)/Makefile.dep + +include $(RIOTBOARD)/wsn430-common/Makefile.include diff --git a/boards/wsn430-v1_3b/driver_cc110x.c b/boards/wsn430-v1_3b/driver_cc110x.c new file mode 100644 index 0000000000..89669e64f7 --- /dev/null +++ b/boards/wsn430-v1_3b/driver_cc110x.c @@ -0,0 +1,207 @@ + /* + * driver_cc110x.c - Implementation of the board dependent cc1100 functions. + * Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include + +#include +#include +#include + +#include +#include + +#define CC1100_GDO0 (P1IN & 0x08) // read serial I/O (GDO0) +#define CC1100_GDO1 (P5IN & 0x04) // read serial I/O (GDO1) +#define CC1100_GDO2 (P1IN & 0x10) // read serial I/O (GDO2) + +#define CC1100_CS_LOW (P4OUT &= ~0x04) +#define CC1100_CS_HIGH (P4OUT |= 0x04) + +#define CC1100_GDO1_LOW_COUNT (2700) // loop count (timeout ~ 500 us) to wait +#define CC1100_GDO1_LOW_RETRY (100) // max. retries for GDO1 to go low + +volatile int abort_count; +volatile int retry_count = 0; + +void cc110x_gdo0_enable(void) +{ + P1IFG &= ~0x08; /* Clear IFG for GDO0 */ + P1IE |= 0x08; /* Enable interrupt for GDO0 */ +} + +void cc110x_gdo0_disable(void) +{ + P1IE &= ~0x08; /* Disable interrupt for GDO0 */ + P1IFG &= ~0x08; /* Clear IFG for GDO0 */ +} + +void cc110x_gdo2_enable(void) +{ + P1IFG &= ~0x10; /* Clear IFG for GDO2 */ + P1IE |= 0x10; /* Enable interrupt for GDO2 */ +} + +void cc110x_gdo2_disable(void) +{ + P1IE &= ~0x10; /* Disable interrupt for GDO2 */ + P1IFG &= ~0x10; /* Clear IFG for GDO2 */ +} + +void cc110x_before_send(void) +{ + // Disable GDO2 interrupt before sending packet + cc110x_gdo2_disable(); +} + +void cc110x_after_send(void) +{ + // Enable GDO2 interrupt after sending packet + cc110x_gdo2_enable(); +} + + +int cc110x_get_gdo0(void) { + return CC1100_GDO0; +} + +int cc110x_get_gdo1(void) { + return CC1100_GDO1; +} + +int cc110x_get_gdo2(void) { + return CC1100_GDO2; +} + +void cc110x_spi_cs(void) +{ + CC1100_CS_LOW; +} + +uint8_t cc110x_txrx(uint8_t data) +{ + /* Ensure TX Buf is empty */ + long c = 0; + IFG2 &= ~UTXIFG1; + IFG2 &= ~URXIFG1; + U1TXBUF = data; + while(!(IFG2 & UTXIFG1)) { + if (c++ == 1000000) { + puts("cc110x_txrx alarm()"); + } + } + /* Wait for Byte received */ + c = 0; + while(!(IFG2 & URXIFG1)) { + if (c++ == 1000000) { + puts("cc110x_txrx alarm()"); + } + } + return U1RXBUF; +} + + +void cc110x_spi_select(void) +{ + // Switch to GDO mode + P5SEL &= ~0x04; + P5DIR &= ~0x04; + cs_low: + // CS to low + abort_count = 0; + CC1100_CS_LOW; + // Wait for SO to go low (voltage regulator + // has stabilized and the crystal is running) + loop: +// asm volatile ("nop"); + if (CC1100_GDO1) { + abort_count++; + if (abort_count > CC1100_GDO1_LOW_COUNT) { + retry_count++; + if (retry_count > CC1100_GDO1_LOW_RETRY) { + puts("[CC1100 SPI] fatal error\n"); + goto final; + } + CC1100_CS_HIGH; + goto cs_low; // try again + } + goto loop; + } + final: + /* Switch to SPI mode */ + P5SEL |= 0x04; +} + +void cc110x_spi_unselect(void) { + CC1100_CS_HIGH; +} + +void cc110x_init_interrupts(void) +{ + unsigned int state = disableIRQ(); /* Disable all interrupts */ + P1SEL = 0x00; /* must be <> 1 to use interrupts */ + P1IES |= 0x10; /* Enables external interrupt on low edge (for GDO2) */ + P1IE |= 0x10; /* Enable interrupt */ + P1IFG &= ~0x10; /* Clears the interrupt flag */ + P1IE &= ~0x08; /* Disable interrupt for GDO0 */ + P1IFG &= ~0x08; /* Clear IFG for GDO0 */ + restoreIRQ(state); /* Enable all interrupts */ +} + +void cc110x_spi_init(uint8_t clockrate) +{ + // Switch off async UART + while(!(U1TCTL & TXEPT)); // Wait for empty UxTXBUF register + IE2 &= ~(URXIE1 + UTXIE1); // Disable USART1 receive&transmit interrupt + ME2 &= ~(UTXE1 + URXE1); + P5DIR |= 0x0A; // output for CLK and SIMO + P5DIR &= ~(0x04); // input for SOMI + P5SEL |= 0x0E; // Set pins as SPI + + // Keep peripheral in reset state + U1CTL = SWRST; + + // 8-bit SPI Master 3-pin mode, with SMCLK as clock source + // CKPL works also, but not CKPH+CKPL or none of them!! + U1CTL |= CHAR + SYNC + MM; + U1TCTL = CKPH + SSEL1 + SSEL0 + STC; + + // Ignore clockrate argument for now, just use clock source/2 + // SMCLK = 8 MHz + U1BR0 = 0x02; // Ensure baud rate >= 2 + U1BR1 = 0x00; + U1MCTL = 0x00; // No modulation + U1RCTL = 0x00; // Reset Receive Control Register + + // Enable SPI mode + ME2 |= USPIE1; + + // Release for operation + U1CTL &= ~SWRST; +} + +/* + * CC1100 receive interrupt + */ +interrupt (PORT1_VECTOR) __attribute__ ((naked)) cc110x_isr(void){ + __enter_isr(); + /* Check IFG */ + if ((P1IFG & 0x10) != 0) { + P1IFG &= ~0x10; + cc110x_gdo2_irq(); + } + else if ((P2IFG & 0x08) != 0) { + cc110x_gdo0_irq(); + P1IE &= ~0x08; // Disable interrupt for GDO0 + P1IFG &= ~0x08; // Clear IFG for GDO0 + } else { + puts("cc110x_isr(): unexpected IFG!"); + /* Should not occur - only GDO1 and GDO2 interrupts are enabled */ + } + __exit_isr(); +} diff --git a/boards/wsn430-v1_3b/include/board.h b/boards/wsn430-v1_3b/include/board.h new file mode 100644 index 0000000000..9a23fdf8d7 --- /dev/null +++ b/boards/wsn430-v1_3b/include/board.h @@ -0,0 +1,65 @@ +/** + * board.h - wsn430-v1_3b Board. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#ifndef _WSN_BOARD_H +#define _WSN_BOARD_H + +/** + * @defgroup wsn430-v1_3b Senslab WSN430 v1.3b + * @ingroup wsn430 + * +

Compontents

+\li MSP430 +\li CC1100 + +* @{ +*/ + +/** + * @file + * @brief wsn430-v1_3b Board + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Milan Babel + * @version $Revision$ + * + * @note $Id$ + */ + +#include "board-conf.h" + +//MSB430 core +#define MSP430_INITIAL_CPU_SPEED 800000uL +#define MSP430_HAS_DCOR 0 +#define MSP430_HAS_EXTERNAL_CRYSTAL 1 + +/* LEDs ports MSB430 */ +#define LEDS_PxDIR P5DIR +#define LEDS_PxOUT P5OUT +#define LEDS_CONF_RED 0x04 +#define LEDS_CONF_GREEN 0x05 +#define LEDS_CONF_BLUE 0x06 + +#define LED_RED_ON LEDS_PxOUT &=~LEDS_CONF_RED +#define LED_RED_OFF LEDS_PxOUT |= LEDS_CONF_RED +#define LED_RED_TOGGLE LEDS_PxOUT ^= LEDS_CONF_RED + +#define LED_GREEN_ON LEDS_PxOUT &=~LEDS_CONF_GREEN +#define LED_GREEN_OFF LEDS_PxOUT |= LEDS_CONF_GREEN +#define LED_GREEN_TOGGLE LEDS_PxOUT ^= LEDS_CONF_GREEN + +#define LED_BLUE_ON LEDS_PxOUT &=~LEDS_CONF_BLUE +#define LED_BLUE_OFF LEDS_PxOUT |= LEDS_CONF_BLUE +#define LED_BLUE_TOGGLE LEDS_PxOUT ^= LEDS_CONF_BLUE + +#include + +typedef uint8_t radio_packet_length_t; + +/** @} */ +#endif // _WSN_BOARD_H diff --git a/boards/wsn430-v1_4/Makefile b/boards/wsn430-v1_4/Makefile new file mode 100644 index 0000000000..5e426ffbd9 --- /dev/null +++ b/boards/wsn430-v1_4/Makefile @@ -0,0 +1,35 @@ +SRC = $(wildcard *.c) +BINDIR = bin/ +OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines +export ARCH = wsn430-v1_4_base.a + +DEP = $(SRC:%.c=$(BINDIR)%.d) + +INCLUDES += -I${RIOTBASE}/core/include/ +INCLUDES += -Iinclude/ -I$(RIOTBOARD)/wsn430-common/include/ +INCLUDES += -I$(RIOTBASE)/cpu/msp430-common/include/ -I$(RIOTBASE)/cpu/msp430x16x/include/ +INCLUDES += -I$(RIOTBASE)/drivers/cc2420/include/ -I$(RIOTBASE)/sys/include + +all: $(BINDIR)$(ARCH) + $(MAKE) -C ../wsn430-common + +$(BINDIR)$(ARCH): $(OBJ) + $(AR) rcs $(BINDIR)$(ARCH) $(OBJ) + +# pull in dependency info for *existing* .o files +-include $(OBJ:.o=.d) + +# compile and generate dependency info +$(BINDIR)%.o: %.c + mkdir -p $(BINDIR) + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o + $(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d + @printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d + +# remove compilation products +clean: + $(MAKE) -C ../wsn430-common clean + rm -f $(BINDIR)$(ARCH) $(OBJ) $(DEP) + @if [ -d $(BINDIR) ] ; \ + then rmdir $(BINDIR) ; \ + fi diff --git a/boards/wsn430-v1_4/Makefile.dep b/boards/wsn430-v1_4/Makefile.dep new file mode 100644 index 0000000000..52516208bc --- /dev/null +++ b/boards/wsn430-v1_4/Makefile.dep @@ -0,0 +1 @@ +USEMODULE += msp430_common \ No newline at end of file diff --git a/boards/wsn430-v1_4/Makefile.include b/boards/wsn430-v1_4/Makefile.include new file mode 100644 index 0000000000..267a2fb9cd --- /dev/null +++ b/boards/wsn430-v1_4/Makefile.include @@ -0,0 +1,4 @@ +export INCLUDES += -I$(RIOTBOARD)/wsn430-common/include +include $(RIOTBOARD)/$(BOARD)/Makefile.dep + +include $(RIOTBOARD)/wsn430-common/Makefile.include diff --git a/boards/wsn430-v1_4/driver_cc2420.c b/boards/wsn430-v1_4/driver_cc2420.c new file mode 100644 index 0000000000..c653c9ba3a --- /dev/null +++ b/boards/wsn430-v1_4/driver_cc2420.c @@ -0,0 +1,213 @@ + /* + * driver_cc2420.c - Implementation of the board dependent cc2420 functions. + * Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include + +#include +#include +#include +#include + +#include + +#define CC2420_RESETn_PIN 0x80 +#define CC2420_VREGEN_PIN 0x01 + +#define CC2420_GDO0_PIN 0x08 +#define CC2420_GDO2_PIN 0x10 +#define CC2420_SFD_PIN 0x20 +#define CC2420_CCA_PIN 0x40 + +#define CC2420_GDO0 (P1IN & CC2420_GDO0_PIN) // read serial I/O (GDO0) +#define CC2420_GDO2 (P1IN & CC2420_GDO2_PIN) // read serial I/O (GDO2) +#define CC2420_SFD (P1IN & CC2420_SFD_PIN) // read serial I/0 (SFD) +#define CC2420_CCA (P1IN & CC2420_CCA_PIN) // read serial I/O (CCA) + + +#define CC2420_CS_LOW (P4OUT &= ~0x04) +#define CC2420_CS_HIGH (P4OUT |= 0x04) + +#define CC2420_GDO1_LOW_COUNT (2700) // loop count (timeout ~ 500 us) to wait +#define CC2420_GDO1_LOW_RETRY (100) // max. retries for GDO1 to go low + +volatile int abort_count; +volatile int retry_count = 0; + +void cc2420_reset(void) +{ + P3OUT |= CC2420_VREGEN_PIN; + P1OUT &= ~CC2420_RESETn_PIN; + hwtimer_wait(500); + P1OUT |= CC2420_RESETn_PIN; +} + +void cc2420_gdo0_enable(void) +{ + P1IFG &= ~CC2420_GDO0_PIN; /* Clear IFG for GDO0 */ + P1IE |= CC2420_GDO0_PIN; /* Enable interrupt for GDO0 */ +} + +void cc2420_gdo0_disable(void) +{ + P1IE &= ~CC2420_GDO0_PIN; /* Disable interrupt for GDO0 */ + P1IFG &= ~CC2420_GDO0_PIN; /* Clear IFG for GDO0 */ +} + +void cc2420_gdo2_enable(void) +{ + P1IFG &= ~CC2420_GDO2_PIN; /* Clear IFG for GDO2 */ + P1IE |= CC2420_GDO2_PIN; /* Enable interrupt for GDO2 */ +} + +void cc2420_gdo2_disable(void) +{ + P1IE &= ~CC2420_GDO2_PIN; /* Disable interrupt for GDO2 */ + P1IFG &= ~CC2420_GDO2_PIN; /* Clear IFG for GDO2 */ +} + +void cc2420_before_send(void) +{ + // Disable SFD interrupt before sending packet + // However this is not used atm +} + +void cc2420_after_send(void) +{ + // Enable SFD interrupt after sending packet + // However this is not used atm +} + + +int cc2420_get_gdo0(void) +{ + return CC2420_GDO0; +} + +int cc2420_get_gdo2(void) +{ + return CC2420_GDO2; +} + +int cc2420_get_sfd(void) +{ + return CC2420_SFD; +} + +void cc2420_spi_cs(void) +{ + CC2420_CS_LOW; +} + +uint8_t cc2420_txrx(uint8_t data) +{ + /* Ensure TX Buf is empty */ + long c = 0; + IFG2 &= ~UTXIFG1; + IFG2 &= ~URXIFG1; + U1TXBUF = data; + while(!(IFG2 & UTXIFG1)) { + if (c++ == 1000000) { + puts("cc2420_txrx alarm()"); + } + } + /* Wait for Byte received */ + c = 0; + while(!(IFG2 & URXIFG1)) { + if (c++ == 1000000) { + puts("cc2420_txrx alarm()"); + } + } + return U1RXBUF; +} + + +void cc2420_spi_select(void) +{ + CC2420_CS_LOW; +} + +void cc2420_spi_unselect(void) { + CC2420_CS_HIGH; +} + +void cc2420_init_interrupts(void) +{ + unsigned int state = disableIRQ(); /* Disable all interrupts */ + P1SEL = 0x00; /* must be <> 1 to use interrupts */ + P1IES |= CC2420_GDO2_PIN; /* Enables external interrupt on falling edge (for GDO2) */ + P1IE |= CC2420_GDO2_PIN; /* Enable interrupt */ + P1IFG &= ~CC2420_GDO2_PIN; /* Clears the interrupt flag */ + P1IES |= CC2420_SFD_PIN; /* Enables external interrupt on falling edge (for GDO2) */ + P1IE |= CC2420_SFD_PIN; /* Enable interrupt */ + P1IFG &= ~CC2420_SFD_PIN; /* Clears the interrupt flag */ + P1IE &= ~CC2420_GDO0_PIN; /* Disable interrupt for GDO0 */ + P1IFG &= ~CC2420_GDO0_PIN; /* Clear IFG for GDO0 */ + restoreIRQ(state); /* Enable all interrupts */ +} + +void cc2420_spi_init(void) +{ + // Switch off async UART + while(!(U1TCTL & TXEPT)); // Wait for empty UxTXBUF register + IE2 &= ~(URXIE1 + UTXIE1); // Disable USART1 receive&transmit interrupt + ME2 &= ~(UTXE1 + URXE1); + P5DIR |= 0x0A; // output for CLK and SIMO + P5DIR &= ~(0x04); // input for SOMI + P5SEL |= 0x0E; // Set pins as SPI + + // Keep peripheral in reset state + U1CTL = SWRST; + + // 8-bit SPI Master 3-pin mode, with SMCLK as clock source + // CKPL works also, but not CKPH+CKPL or none of them!! + U1CTL |= CHAR + SYNC + MM; + U1TCTL = CKPH + SSEL1 + SSEL0 + STC; + + // Ignore clockrate argument for now, just use clock source/2 + // SMCLK = 8 MHz + U1BR0 = 0x02; // Ensure baud rate >= 2 + U1BR1 = 0x00; + U1MCTL = 0x00; // No modulation + U1RCTL = 0x00; // Reset Receive Control Register + + // Enable SPI mode + ME2 |= USPIE1; + + // Release for operation + U1CTL &= ~SWRST; +} + +/* + * CC1100 receive interrupt + */ +interrupt (PORT1_VECTOR) __attribute__ ((naked)) cc2420_isr(void){ + __enter_isr(); + /* Check IFG */ + if ((P1IFG & CC2420_GDO2_PIN) != 0) { + puts("rx interrupt"); + P1IFG &= ~CC2420_GDO2_PIN; + cc2420_rx_irq(); + } + else if ((P1IFG & CC2420_GDO0_PIN) != 0) { + cc2420_rxoverflow_irq(); + puts("[CC2420] rxfifo overflow"); + //P1IE &= ~CC2420_GDO0_PIN; // Disable interrupt for GDO0 + P1IFG &= ~CC2420_GDO0_PIN; // Clear IFG for GDO0 + } else if ((P1IFG & CC2420_SFD_PIN) != 0) { + puts("sfd interrupt"); + P1IFG &= ~CC2420_SFD_PIN; + cc2420_switch_to_rx(); + } + + else { + puts("cc2420_isr(): unexpected IFG!"); + /* Should not occur - only GDO1 and GDO2 interrupts are enabled */ + } + __exit_isr(); +} diff --git a/boards/wsn430-v1_4/include/board.h b/boards/wsn430-v1_4/include/board.h new file mode 100644 index 0000000000..092bc76998 --- /dev/null +++ b/boards/wsn430-v1_4/include/board.h @@ -0,0 +1,65 @@ +/** + * board.h - wsn430-v1_4 Board. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#ifndef _WSN_BOARD_H +#define _WSN_BOARD_H + +/** + * @defgroup wsn430-v1_4 Senslab WSN430 v1.4 + * @ingroup wsn430 + * +

Compontents

+\li MSP430 +\li CC2420 + +* @{ +*/ + +/** + * @file + * @brief wsn430-v1_4 Board + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Milan Babel + * @version $Revision$ + * + * @note $Id$ + */ + +#include "board-conf.h" + +//MSB430 core +#define MSP430_INITIAL_CPU_SPEED 800000uL +#define MSP430_HAS_DCOR 0 +#define MSP430_HAS_EXTERNAL_CRYSTAL 1 + +/* LEDs ports MSB430 */ +#define LEDS_PxDIR P5DIR +#define LEDS_PxOUT P5OUT +#define LEDS_CONF_RED 0x04 +#define LEDS_CONF_GREEN 0x05 +#define LEDS_CONF_BLUE 0x06 + +#define LED_RED_ON LEDS_PxOUT &=~LEDS_CONF_RED +#define LED_RED_OFF LEDS_PxOUT |= LEDS_CONF_RED +#define LED_RED_TOGGLE LEDS_PxOUT ^= LEDS_CONF_RED + +#define LED_GREEN_ON LEDS_PxOUT &=~LEDS_CONF_GREEN +#define LED_GREEN_OFF LEDS_PxOUT |= LEDS_CONF_GREEN +#define LED_GREEN_TOGGLE LEDS_PxOUT ^= LEDS_CONF_GREEN + +#define LED_BLUE_ON LEDS_PxOUT &=~LEDS_CONF_BLUE +#define LED_BLUE_OFF LEDS_PxOUT |= LEDS_CONF_BLUE +#define LED_BLUE_TOGGLE LEDS_PxOUT ^= LEDS_CONF_BLUE + +#include + +typedef uint8_t radio_packet_length_t; + +/** @} */ +#endif // _WSN_BOARD_H