Software and software architecture for a student satellite

Software and software architecture for a student satellite
Software and software
architecture for a student satellite
by
Dan Erik Holmstrøm
December 21, 2012
TDT4501 - Computer Science,
Specialisation Project
Abstract
Modern satellites use computer software to do on-board data
handling and other tasks that are elemental to their successful operation. Design and development of such software poses several
challenges due to factors such as the physical environment, reliability, security as well as cost and power constraints.
This paper addresses the software system of the NTNU test
satellite. The satellite is a 2U CubeSat where the goal is to build a
modular platform that is not specific to any particular payload. We
discuss the requirements for an on-board computer module and
highlight possible challenges and limitations with the current system design. The modules of the satellite communicate with each
other over an I 2 C bus. This means that inter-module communication may be hampered by failure in anything connected to the bus.
Therefore, we discuss possible methods to mitigate the effects of
this kind of interference.
When investigating how to satisfy system requirements, it is
possible to benefit from existing software. We find that a communications library called cubesat space protocol can be used for intermodule communication, and communication between ground and
space segment. In addition, we find that FreeRTOS is a suitable
operating system for the on-board computer module.
Some changes had to be made to make cubesat space protocol and FreeRTOS suitable for use in this project. The necessary
changes and challenges are described, including porting the cubesat space protocol library to Microsoft Windows.
In conclusion, we find that a lot of time can be saved by not
developing all the software from scratch. However, we realise that
there is a lot of software features and challenges that will have to
be solved in the future.
Contents
I Project overview and planning
1
1 Project description
3
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
1.10
Project mandate . . . .
Project background . . .
Stakeholders . . . . . .
Resources . . . . . . . .
Scope . . . . . . . . . .
Previous work (related to
Project status . . . . .
NUTS status . . . . . .
Assignment . . . . . . .
Similar projects . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
software)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2 Planning
11
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3 System description and environment
3.1 System overview . . . . . . . . . . .
3.2 NUTS subsystems . . . . . . . . . .
3.3 Hardware specifications . . . . . . . .
3.4 Software environment . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2.1
2.2
2.3
2.4
Team composition
Method of work .
Tools . . . . . . .
Project phases . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
11
12
12
15
4 Requirements
4.1
4.2
4.3
3
4
4
5
5
5
5
6
6
7
15
16
17
22
25
System requirements . . . . . . . . . . . . . . . . . . . . . . . .
Functional requirements . . . . . . . . . . . . . . . . . . . . . .
Non-functional requirements . . . . . . . . . . . . . . . . . . . .
iii
25
26
27
4.4
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5 Software architecture
5.1 Software . . . . . . . . . . . .
5.2 Functionality mapping . . . . .
5.3 Communications architecture . .
5.4 Quality attributes . . . . . . . .
5.5 Fairness on the data bus . . . .
5.6 Conclusion . . . . . . . . . . .
31
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6 Testing
6.1
6.2
6.3
6.4
Scope . . . . . . . . . . . . .
Testing cubesat space protocol
Testing the OBC . . . . . . .
Conclusion . . . . . . . . . .
30
31
31
32
33
34
35
37
.
.
.
.
37
37
41
43
II NUTS software
45
7 Ground segment software
7.1 Previous work . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.2 Porting Cubesat Space Protocol . . . . . . . . . . . . . . . . . .
47
8 Space segment software
8.1 Previous work . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2 OBC software . . . . . . . . . . . . . . . . . . . . . . . . . . .
51
IIIConclusion and evaluation
53
9 Conclusion and evaluation
9.1 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.2 Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
55
References
59
A Appendix
A.1
A.2
A.3
A.4
A.5
Installing and configuring MinGW . . .
Cubesat space protocol, windows port .
Cubesat space protocol, ground segment
Cubesat space protocol, KISS test . . .
XMEGA A1 Code . . . . . . . . . . .
47
47
51
51
55
57
61
. . . . . . .
. . . . . . .
test code . .
. . . . . . .
. . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
61
67
70
76
90
A.6
A.7
OBC Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
FreeRTOS on the OBC . . . . . . . . . . . . . . . . . . . . . . . 103
List of Figures
1.1
1.2
CubeSTAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
SwissCube . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1
3.2
3.3
3.4
System topology . . . . . . . . . . .
OBC memory topology . . . . . . . .
OBC memory map . . . . . . . . . .
System overview with debug terminals.
have a USB interface connector . . .
5.1
5.2
5.3
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
7
8
15
19
20
Both the radio and the OBC are
. . . . . . . . . . . . . . . . .
21
Nominal mode, module functionality . . . . . . . . . . . . . . . . . .
Reduced mode, module functionality . . . . . . . . . . . . . . . . . .
Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
32
33
List of Tables
4.1
4.2
NUTS system requirements . . . . . . . . . . . . . . . . . . . . . . .
NUTS functional requirements . . . . . . . . . . . . . . . . . . . . .
v
25
26
List of abbreviations
ADCS
Attitude Determination and Control System
Cal Poly
California Polytechnic State University
CDHS
Command and Data Handling
CDMS
Command and Data Monitoring System
COTS
Commercial-off-the-shelf
CSP
Cubesat space protocol
EPS
Electrical Power Supply system
ICE
In-Circuit Emulator
MMU
Memory Management Unit
MPU
Memory Protection Unit
NUTS
NTNU Test Satellite
OBC
On-board Computer
OBDH
On-board Data Handling
OTP
One-Time Programmable
vii
Preface
This paper is one of the deliverables in the course TDT4501 Specialisation Project, given by IDI at the Norwegian University of Science and
Technology, NTNU, in the fall of 2011.
Initially, the assignment described the need to manage the main data
bus in the satellite. However, as the project evolved it was clear that the
focus had to be changed as well as the scope of the project. This was the
first semester in the NUTS project, where an assigment put any focus on
how software could be used to make the satellite function as a whole.
Because of this, the development of the system software for the NUTS
satellite was – and still is – in its infancy.
Given the limited resources available, it means that there is still a lot
to do. And my effort is only a tiny step towards completion. But this
also means that I am in a better position to focus on exactly the tasks
that I find interesting.
Before implementing anything, one has to to decide what to make. The
formalisation of this, is a list of requirements. Thus I had to create
a software requirements specification. This kind of documentation is
a work in progress-document, and is bound to change in the future.
However, what is not possible to avoid, is communication between the
different subsystems as well as the satellite and the ground. Implementation wise, this is also where I have put most of the effort this semester.
I hope that people will find that at least some of the decisions taken
when solving the assignment, were sound. And that they are willing to
continue where I left off.
I would also like to express my appreciation to the people who have
helped me realise this project. This includes my supervisor, Gunnar
Tufte, and the NUTS project leader, Roger Birkeland, for helpful input
and encouragment. Last, but not least, I would like to thank those who
had to endure long workshop sessions with me.
Part I
Project overview and planning
1
Project description
1
Introduction
This chapter presents the project and describes how this specific assignment fits into the NTNU test satellite project as a whole. At last, this
project is compared with similar CubeSat projects.
1.1
Project mandate
The purpose of the project is to specify the software requirements for
a student satellite, and see how inter-module and satellite-ground communication could be implemented. Part of the investigative processs
is to decide whether to use COTS software, design or implementation
issues and see if software developed in the earlier stages of the project
could be used.
While the ultimate goal of the NUTS mission, is to put the payload
into orbit, it is the satellite platform that will make it usable. And for
this to happen, a lot of elements have to play well together. This report describes the beginnings of creating the computer software in this
system and the process of investigating possible implementations using
freely available software.
The name of the specific project addressed in this report is ”Software
and software architecture for a student satellite”. When using the term
”project” throughout this report, it can mean both the project directly
related to this report or the NUTS project as a whole, depending on the
context.
3
1.2
Project background
The Norwegian Student Satellite Project, ANSAT, was launched in 2006
[2] by a collaborative effort between NAROM and Andøya Rocket Range
[17]. The goal of the ANSAT project is to launch three student satellites
by the end of 2014. The common denominator with all of the three
satellites, is that students shall play a significant role in realising the
goal of putting a functioning satellite into earth orbit. The NTNU test
satellite, NUTS, is one of them.
The work on NUTS started in September 2007. It is a 2U CubeSat,
meaning it has twice the volume of a ”1U” CubeSat. A CubeSat has a
volume of 1 litre and measures 10x10x10cm [23] and a mass up to 1.33kg.
One of the design goals is to create a generic and modular satellite platform [9]. At the time of this writing, the payload is an IR camera. The
camera will be used to observe gravity waves in the earth atmosphere.
In addition, the radio and the on-board computer module are fitted with
wireless transceivers that could be used to test the feasibility of using a
wireless bus in space.
The CubeSat standard was created at California Polytechnic State
University. Its purpose is to provide a standard for picosatellites. An
established standard helps to reduce development time and cost. A
lot of firms provide equipment adhering to the CubeSat standard, and
many universities and educational institutions choose to buy complete
modules from these vendors.
When creating CubeSats, it is common to use COTS hardware. However, this would limit the possibilities for students designing the electronics in the NUTS satellite. NUTS has a custom designed backplane,
and this means that it is not possible to buy complete modules and trivially make use of them.
1.3
Stakeholders
The stakeholders in the NUTS project are the people and organisations
that are affected, affects or take an interest in the project. Both NAROM
and Andøya Rocket Range (ARR) are stakeholders, because they both
created the ANSAT program. The other stakeholders are the NUTS
project leader, Roger Birkeland, as well as the students that are working
on the project.
NAROM, the department of electronics and telecommunications as
well as the department of engineering cybernetics finance the project.
1.4
Resources
This semester there are 14 students working on the NUTS project [19].
This is the first semester where software is considered as a distinct entity,
and at this point there is a single person working on this.
1.5
Scope
The abstraction level of the topics in this report are necessarily high. The
main goal is to identify the software requirements for the NUTS space
segment software. This has a higher priority than producing a working
implementation at this point.
This report focuses on the OBC, the On-Board Computer — but in
the context of the whole system.
1.6
Previous work (related to software)
Hardware design-wise, only the on-board computer module, the radio
module and the backplane are more or less completed. There may be
new revisions of each of the those two modules if any problems are
found, but no significant hardware changes are expected.
The designer of the OBC-module developed a couple of drivers to
demonstrate it, as well as demonstrate that the module is able to read
sensor data from the NUTS backplane.
1.7
Project status
This semester there is ongoing work on the attitude determination and
control system (ADCS), antenna design for both the ground station and
the satellite, the external power supply system, the wireless bus and the
payload module. The specific hardware configuration for the payload is
yet to be determined.
Currently, only the radio module and the OBC module are fitted
with 2.4GHz wireless transceivers [24]. Testing of the wireless bus is in
the works this semester, and work on the camera payload module just
started this semester.
There are also proceeding tasks of a more analytical nature: Mission
analysis and design of uplink security.
Currently there is no software that facilitates inter-module communication. That will be a topic for discussion in this report.
1.8
NUTS status
The satellite will consist of multiple modules or sub-systems. The modules in NUTS are:
• OBDH/OBC: Does on-board data handling. The idea is that this
module can provide computing power for at least the payload
module, as well as being able to handle requests from the ground
segment, if a request originating from the ground segment is destined for it.
• EPS: Provides power to the various systems in the satellite.
• ADCS: Stabilises the satellite and provides various means of determining the spatial orientation.
• Radio/COMM: Contains radio transceivers as well as a radio transmitter for a beacon signal. This module processes in- and outgoing
requests from and to the ground segment during the mission.
• Payload: An infrared camera. Details of this module are yet to be
determined.
The modules are realised as circuit boards that fit into slots on a backplane. The NUTS backplane can accommodate any module that adheres
to the backplane specifications. The original backplane design has eight
slots [14], and is responsible for distributing power to all of the modules.
1.9
Assignment
The task is to start work on creating specifications for the systems software on the satellite. This includes a general interface for communication between the satellite and the ground station.
Specific issues related to that are:
• What, if any, Commercial Off-The-Self (COTS) software shall be
used.
• Is it possible to guarantee fairness over the internal data bus?
• Is it possible to use the same, or parts of the same, software on
multiple modules?
• What kind of mechanism or means is used for communication between each subsystem, and between the ground and space segment?
1.10
Similar projects
With the assignment in mind, it is useful to compare this with other
student satellite projects where the necessary information is disclosed.
The level of detail for each project will vary with the amount of available
information.
CubeSTAR
The CubeSTAR uses I 2 C as the bus type
for the internal data bus. It has two separate data buses, where the idea is that
the second bus can be used either for redundancy or in case the ”main” bus has
hung. The bus is used in multi-master
mode, where both the communications
and the OBC module may act as bus masters.
For fault detection and increased system availability, ping/echo-commands
CubeSTAR
are used. The module will be reset if Figure 1.1:
Source:
http://cubestar.no/
it fails to respond to a ping/status request. The system exploits the minimum web_images/picture1.jpg
Hamming distance between commands
to provide error detection. Error prevention may also be possible, by finding the minimum distance from the
received command to a set of possible commands.
The payload module also uses the main data bus. This means that
the system has to rely on short bus transactions if erroneous resets are
to be avoided.
No COTS operating system is used in any of the subsystems.
SwissCube
SwissCube was launched on September
23, 2009 [6][1]. As of today, the satellite continues to be operational![5]. Over
time, the main data bus has become unstable for long frames [16]. At some
point, the data bus also got stuck, but it
was possible to reset the system by draining the batteries.
In the SwissCube project several bus
types were evaluated [21] (p. 24). In the
end I 2 C was found to be the most suitable alternative, and this was the bus type
that was used. The I 2 C bus in SwissCube
Figure 1.2:
SwissCube
operates with a lower clocked ”standard
Source: http://swisscube.
mode”, as opposed to the higher clocked
epfl.ch/images/whatis.jpg
”fast mode” in NUTS.
Several operating systems were evaluated [21] (p. 13), but no ”best” alternative was found. In the end, the
SwissCube did not use a COTS operating system [18]. The evaluated
operating systems are not ported to the main microcontrollers in any of
the NUTS subsystems.
The subsystems in SwissCube are [22] (p. 37):
• COMM
• EPS
• ADCS
• Beacon
• CDMS
The NUTS OBC is most similar to the CDMS in the SwissCube. However, while NUTS has a separate backplane, the CDMS board in SwissCube serves as a ”connector hub”. A separate microcontroller is used
on the CDMS to interface with the I 2 C bus, because the main microcontroller (an Atmel ARM AT91M55800A) in the CDMS has no hardware
support for I 2 C [12] (p. 8). The same microcontroller is used as an
I 2 C bridge in each subsystem. For persistent storage, a combination of
EEPROM and NAND flash memory was used [13] (p. 11).
The main tasks of the CDMS are [13] (p. 11):
• Execute scheduled tasks.
• Serve as a data storage for payload and subsystem statuses. The
CDMS polls for housekeeping data at regular intervals.
• Execute control algorithms for the ADCS.
Ther NUTS OBC has similar responsibilities. But one of the most
significant differences are that the main processor on the CDMS does
processing for the ADCS system. On NUTS the ADCS system will have
to be able to do processing itself and operate autonomously, but be able
to respond to requests from the other modules on the NUTS backplane.
While NUTS is not like SwissCube, there it shares enough similarities
that a lot of the same software design decisions taken for the SwissCube,
also applies to NUTS.
AUSAT
The AUSAT uses a PC/104 compliant frame and circuit boards. The design is based on the concept of a centralised microcontroller that manages each subsystem [10]. The design philosophy is completely different
from that of the NUTS project. AUSAT is a CubeSat that serves a very
specific purpose. While the PC/104 standard gives physical modularity,
the AUSAT is not a modular system in the same sense as NUTS.
The EPS module was COTS hardware. All the other electronics was
grouped into PC/104 compliant circuit boards. In the end, the physical
boards were[10]:
• EPS
• Communication
• CDHS
• ADCS
The Command and Data Handling system is the closest analog to the
OBC in NUTS. Unlike NUTS, the central microcontroller on the CDHS
has full knowledge of each subsystem to the extent that the hardware
permits. They opted not to use an operating system. Instead the central
”controller program” is based around the concept of a state machine
that is able to perform a single task at the time.
The bottom line, is that the design of AUSAT makes it hard to transfer the same software concepts to the NUTS project: The hardware design is different and the design philosophy for the satellite is also completely orthogonal.
2
Planning
Introduction
This chapter presents the NUTS project as it is this semester, the team
composition and what kind of methods and aids the participants use
during project work. Lastly the actual timeline of the assignment described in this report, is presented.
2.1
Team composition
This semester, the NUTS project has a team of 14 students. Their background is either from telematics, cybernetics, electronics, computer science or mechanics. This excludes technical staff.
The following departments are involved in the NUTS project:
Department of Engineering Design and Materials (IPM)
Department of Physics (PHYS)
Department of Electronics and Telecommunications (IET)
Department of Engineering Cybernetics (ITK)
Department of Computer and Information Science (IDI)
Department of Telematics (ITEM)
2.2
Method of work
The team has weekly meetings. Having regular and relative short meetings, makes it easier to know what the other team members are doing.
11
This also makes it easier to know who to ask if any problems or questions arise. Extra meetings were arranged when necessary.
However the members do not work closely together. The main objective for the student is to produce a report resulting from practical work
and background studies.
2.3
Tools
Several general software tools is used to aid in project work.
•
Subversion Centralised VCS. This is used mostly for code, but
some team members use it for documentation as well.
•
Git Distributed VCS. Some team members prefer to use this.
•
Yammer Social network service for projects. The team uses this to
exchange information and progress updates.
•
Google Docs This is used to quickly share documentation.
Other software is used for specific tasks. Details of this can be found
in the appropriate chapters. The NUTS project also has a Subversion
repository. This is the official repository, and all team members who
wants to share code with others have have to use this. But when working individually, a feasible solution is to merge data from an external
repository into the official one.
2.4
Project phases
There were no distinct project phases. This is a natural consequence
of not knowing the specific assignment until the middle of the semester,
some uncertainties regarding the project itself and that there was a single
person working on the software for the space segment.
The project duration was from August 29th to December 21st. In
that time span, the work on the assignment can be broken down into
the following stages:
Phase
Project start
Workshops
Planning
Prestudy
Implementation
Report writing
Activites
Briefing and administrative tasks
Meetings with electronics group
Setting up development environment
NUTS kickoff
Requirements
Commands draft
Background study of bus types
Communication libraries
Getting to know libcsp
OS alternatives
Comparisons with other CubeSats
NUTS backplane & OBC
Porting libcsp
Analysing OBC code
Learning FreeRTOS
Deploying FreeRTOS to OBC
Work on the report
Week no.
35
36–37
38
39–42
41–49
50–51
Note that the table depicts the actual time spent. There was no way to
plan ahead the prestudy and implementation phase because the nature
and extent of them were completely unkown.
3
System description and
environment
Introduction
This chapter gives a detailed insight into the parts of the NUTS project
that are relevant to this report, or to future works related to software.
3.1
System overview
Figure 3.1: System topology
Radio
OBC/
OBDH
EPS
Payload
ADCS
Space segment
Radio
Ground segment
Figure 3.1 shows an overview over the whole system. The funtionality of the NUTS satellite is split into physical modules that are connected
to a common data bus. In addition both the radio and OBC-modules
15
have radio transceivers meant for local data transfer. This functionality
is not tested as of yet, but using this feature as a wireless bus may be
used as a backup bus, used for bulk data transfers or used in the event
that the main data bus fails.
3.2
NUTS subsystems
What follows is a brief description of each subsystem in NUTS.
ADCS
The satellite has to be able to change its orientation and reduce or control
its angular velocity. The ADCS system is responsible for doing this. All
processing is completed within the ADCS module. However the ADCS
system shall be able to respond to high-level requests from either the
OBC or the radio.
OBC
The OBC is responsible for running the flight management software
aboard NUTS. Its primary task is to process data from the payload module, store system status information, execute scheduled commands and
retrieve stored data upon request from the ground segment.
The OBC is one of two masters of the back plane. In this context, it
means that the OBC has access to extra pins on the backplane. These
pins makes it possible for the OBC to perform a partial or a full system
reset
Radio
The radio module has two RF transceivers plus a radio transmitter for a
beacon signal. The beacon signal is controlled by a dedicated microcontroller.
Frame encapsulation and decapsulation for radio transmission or receival is done on the radio module. The packet framing has not been
decided yet, but it is common to use AX.25 framing in CubeSats.
A design goal, is that the radio module shall be able to operate as a
feature reduced OBC in the event that the OBC module fails. However,
the radio module lacks some hardware features that are present on the
OBC module, so it does not have access to the same amount of program
and data memory. In addition, no OTP memory is present on the radio
module.
EPS
The EPS module handles the task of providing regulated power to the
rest of the system and also charges the batteries from solar cells. This
modules provides vital power telemetry data to the rest of the system.
Payload
The payload consists of an IR camera. This module is currently in the
design phase, so the exact specifications are not clear. But its main task
is to respond to commands from the OBC module, and send image data
when requested to do so.
3.3
Hardware specifications
The project is still evolving, and not all hardware specification decisions
are final. What follows is a brief discussion of the hardware features
that are unlikely to undergo substantial changes in the future. The EPS
and payload modules are omitted because exact hardware specifications
are not known at this point.
Backplane
The backplane has eight connectors. The slot configuration is as follows
[14]:
Module 4: OBC
Module 5: EPS
Module 8: Radio
Module connector 1–3 and 6–7 are generic connectors. They can be
used for other subsystems or the payload module. The module connectors used by the OBC and the Radio have special access to the backplane:
They connectors have extra pins for resetting the system, power on or
off a module, reset a module and program a module. Extra address pins
makes it possible to target a specific module. The signals for system reset are different for module connector five and eight. This is to prevent
a module from resetting itself.
This means that the OBC and the radio are masters of the backplane.
They are able to isolate other modules from the backplane, including
the other backplane master.
The backplane is also responsible for distributing power throughout
the system. To do this, the backplane provides duplicate 3.3V and 5V
rails with over-current protection to each module.
For CubeSats, it is not unusual to follow the form factor and data
bus-defining standard, PC/104 [11]. The NUTS backplane does not follow this, but has a different form factor and bus type. The bus type is
I 2 C, operating in ”fast mode”. This gives a theoretical throughput of
400kbps [20].
Radio
• UHF and VHF transceivers
• Main MCU: Atmel AVR32UC3A3256
• Beacon MCU: Atmel ATmega328P
• Nordic Semiconductor nRF24LE1D 2.4GHz RF transceiver chip
(SoC)
The main MCU is connected to the main transceivers used for uplink
and downlink communication with the ground station The beacon MCU
is connected to the beacon transmitter. Testing the radio module is beyond the scope of this project.
OBC
• Atmel AVR32UC3A3256
• Nordic Semiconductor nRF24LE1D 2.4GHz RF transceiver chip
(SoC) connected to main CPU via a SPI interface. The transceiver
chip has two external clock sources: A 32KHz crystal, used for protocol syncronisation, and a 16MHz crystal for inernal clocks[24].
• Micron MT29F16G08DAAWP 16Gb NAND flash
• Atmel AT27LV040A 4Mb EPROM, OTP
• Integrated Silicon Solutions IS61WV102416BLL 16Mb SRAM
The external memories are accessed through the external bus interface (EBI) of the AVR32UC3A3256 microcontroller. With this configuration, the static memory controller and NAND flash controller is used to
interface with them. The memory topology is as depicted in 3.3.
Figure 3.2: OBC memory topology
Atmel AVR32UC3A3256
128KB SRAM
(data memory)
256KB Flash
(program memory)
Volatile memory
Non-volatile memory
16Mb SRAM
16Mb NAND Flash
Aftern configuration, we have the memory map shown in 3.3
From the memory map, we see that the amount of integrated memory is limited. We will see that the current OBC program is very close
to reaching the limits of the integrated program memory.
Both the radio and the OBC have a debug interface for on-ground
testing and diagnostics, as seen in figure 3.4. Neither the radio or the
OBC has a USART-to-USB-bridge. This means that the software on these
modules has to implement a USB stack. The reasons for not having
this, is because a simpler module design was desired. This is a tradeoff
between software and hardware complexity. And the former loses out
on this.
AVR32UC hardware features
The AVR32UC3 is based on the AVR32A micro-architecture [8]. Unlike
the AVR32B architecture, it lacks certain features like register shadowing
in interrupts contexts and dedicated registers for storing return values
and return addresses.
Figure 3.3: OBC memory map
0xFF01 0000
0xFF00 0000
Embedded SRAM0 & SRAM1
0xD800 0000
External static/dynamic RAM area
128MB
0xD000 0000
0xC800 0000
EBI-configured SRAM (16Mb)
EBI-configured NAND flash (16Gb)
AVR32_EBI_CS1_ADDRESS
AVR32_EBI_CS2_ADDRESS
0x8004 0000
0x8000 0000
Embedded flash (256kB)
0x0001 0000
0x0000 0000
Embedded CPU SRAM (64kB)
While the ISA is not binary compatible with the 8-bit AVRs, it still
shares many similarities: The instruction set is that of a load-store architecture, with dedicated instructions for loading and storing data to
memory. The instructions are also variable length, with either a size of
16-bit or 32-bit.
While the architecture lacks backwards compatibility with the AVR8architecture, it is compatible with previous revisions of the same architecture. In this project, source compatibility is not a concern, since we
have access to the source code to all programs that are to be executed
on board the satellite. However, when using frameworks, the intended
architecture may still impact compatibility. For instance, if a library is
designed with a 32-bit architecture in mind, it may not be trivial to compile it into a binary for an 8-bit architecture.
Other notable hardware features are
• 15 general-purpose registers
• 32-bit stack pointer, program counter, link register
Figure 3.4: System overview with debug terminals. Both the radio and
the OBC are have a USB interface connector
>foo
Debugging/
Diagnostics
Radio
OBC/
OBDH
EPS
Payload
I2C bus
ADCS
Radio
• Various DSP-instructions
• An MPU for protecting memory address ranges
• A flat memory model, but with separate program and data memory
• Dedicated flash controller for interfacing with external memories
• Privileged and unprivileged modes
When in unprivileged mode, certain rules apply:
• All memory accesses are checked for violations
• The high half word of the status register is not available. This part
of the register makes it possible to enable and disable interrupts,
mask interrupts etc.
• System registers are placed outside the virtual address space, and
has to be accessed using the privileged instructions mfsr, mtsr. Examples of system registers are the registers that controls the MPU,
configuration registers for the processor, and the EVBA register.
The latter stores the base address of the exceptions routines table.
The AVR32UC3 lacks a MMU, but the MPU is able to protect a limited number of address ranges. The AVR32UC3 MPU can split the address space into eight regions, where each reagion can be further divided into 16 subregions. This means that the main microcontrollers og
the radio and OBC has some hardware features that can be leveraged to
prevent runaway programs from causing trouble. Unfortunately, as described later, there is no support for this in the AVR32 port of FreeRTOS.
3.4
Software environment
Here we describe the existing software for both the ground and the
space segment.
Space segment
There is some code for testing the OBC features, as part of designing the
module. The program demonstrated:
• Controlling the backplane using I 2 C
• Writing and reading to/from NAND flash
• Writing and reading to/from SRAM
• USB communication using Atmel Software Framework Drivers
• Testing of JTAG-programming by bit-banging the JTAG-pins on
the module connector.
This program was only meant for testing, and significant changes
are needed if the code is to be used in a different context. However it
is useful as an example, and is a good basis for writing drivers for the
implicated hardware.
Ground segment
• Operating system: Windows XP
• Hamradio Deluxe
• MixW
• WXTrack
In addition a custom .NET4-program for communicating with the OBC
has been written. The program uses Windows Presentation Foundation,
so it will not run in Mono — a portable implementation of Microsoft
.NET framework.
Summary
Currently the software on the ground station dictates that Windows is
used. This means that any third party library that does not work in
Windows, has to be either discarded or ported.
4
Requirements
Introduction
This chapter presents the system- and software requirements, with a
focus on the space segment. We then discuss desirable architectural
attributes and tactics that will help us achieve them.
4.1
System requirements
The system requirements describes the main features of the system,
without being to specific. They are the basis for requirements that are
more specific. In NUTS, we have the following system requirements:
Table 4.1: NUTS system requirements
ID
S-1
S-2
S-3
S-4
S-5
S-6
Description
Satellite must process commands from the
ground station
Satellite must send a beacon signal
Satellite must be able to send housekeeping data
Satellite must be able to send payload data
Ground station must be able to send commands to satellite
Both ground station and satellite must be
able to detect data corruption or complete
loss of transmitted data
25
4.2
Functional requirements
The system requirements in table 4.1 are further refined into more specific, functional requirements as shown in 4.2:
Table 4.2: NUTS functional requirements
ID
F-1
F-2
F-3
F-4
F-5
F-6
F-7
F-8
F-9
F-10
F-11
F-12
Description
The satellite beacon must continuously
transmit beacon signal
It must be possible to change the beacon
signal pattern after launch
The satellite must execute a one-time initialisation sequence on first boot up
The satellite must accept a ”detumble”
command. The command must be accepted by the ADCS system
The ADCS system must accept other commands from both the ground segment, the
OBC or the radio
The satellite must accept and store commands sent from the ground segment
The satellite must be able to create and
store commands programmatically
The satellite must execute housekeeping
tasks periodically
The satellite must store the results of running the housekeeping tasks
The satellite must be able to send the result
of housekeeping task runs, upon request
from the ground station
The satellite must initiate a single housekeeping task run upon request from the
ground station
The radio and OBC module must be able
to run an arbitrary program
Priority (H/M/L)
H
M/H
H
M/H
M/H
M/G
M
M
H
H
H
L/M
Table 4.2: (continued...)
ID
F-13
F-14
F-15
Description
The satellite must transmit payload data
when ground station requests it to do so
It must be possible to initiate a full or partial satellite system reset from the ground
station
It must be able to set the current time in
the satellite, from the ground station
Priority (H/M/L)
L
M/H
L/M
Comments to table 4.2
F-1 The radio module has a separate microcontroller that controls the
beacon signal.
F-3 The initialisation sequence includes unfolding the atennas, after som
period of time. This program must not be executed more than once.
F-4 The power requirements for a detumbling operation are high. This
action must only be performed when the system is requested to.
F-5 All necessary control algorithms runs within the ADCS system.
However this item indicates that the ADCS system must accept high
level-commands like ”point towards earth”.
F-8 Housekeeping tasks include logging telemetry data like current draw
and actual voltage on the 3.3V and 5V rails for each module, andvalues
from temperature sensors. F-10 This is a more specific requirement than
F-6. F-12 This is a function that is useful to a developer, and the flight
software must make it easy to do this.
The requirements are given priorities ranging from low to high. Intuitively, it would seem better to start implementing the higher priority
items first. However, often lower prioritised items are prerequisites for
those of a higher priority, or they take more time to implement.
4.3
Non-functional requirements
Non-functional requirements describe attributes or properties of the system. This includes business requirements, system requirements, quality
requirements and other requirements. We omit listing business requirements, because we have been unable to identify them yet. 1
Quality requirements
The quality requirements described the desirable properties of the system. We have identified four main quality attributes: Modifiability,
testability, security and reliability.
Modifiability
ID
NF-M1
NF-M2
Description
It shall be possible to compile and run the
same programs on the OBC and the radio,
unless they are dependent upon specific
hardware drivers.
It must be possible to change the output
device for diagnostics prinout without affecting more than a single file in the source
code.
Priority (H/M/L)
H
H
Testability
ID
NF-T1
NF-T2
NF-T3
1
Description
It shall be possible to send a command via
the debug interface on each module, without changing the command format
Commands sent to the debug interface
shall be processed the same way as commands received via the data bus
The OBC and radio shall be able to store
a program execution trace to non-volatile
memory
Priority (H/M/L)
H
H
L
The project schedule is not known yet. Neither is the resources allocated to software.
Table 4.4: (continued...)
ID
NF-T4
Description
It shall be possible to retrieve contents
from non-volatile memory on the OBC,
from the debug interface
Priority (H/M/L)
L
Reliability
ID
NF-R1
NF-R2
NF-R3
NF-R4
Description
Only uncorrupted commands shall be executed
A failing program must not affect the core
functionality of the system
Execution of less-important tasks shall not
affect the timelinss of higher-prioritised
tasks
A frozen system program shall not render
the satellite useless
Priority (H/M/L)
H
Description
Only commands sent from our ground station shall be executed
Data transmitted from the satellite to the
ground station must not be encrypted
Priority (H/M/L)
H
H
M
H
Security
ID
NF-S1
NF-S2
System requirements
H
ID
NF-O1
NF-O2
4.4
Description
The ground station software must run on
Windows Vista, or a more recent version of
Windows
The operating system on the radio and
OBC must both work on an Atmel
AVR32UC3A3256 microcontroller
Priority (H/M/L)
H
H
Conclusion
We have seen the various requirements for the NUTS project. The requirements focus on the satellite, but the ground segment is included
when believed to be relevant. The requirements are work in progress,
and the priorities are bound to change in the future as the project evolves.
5
Software architecture
Introduction
This chapter introduces the software architecture.
5.1
Software
The development environment of choice is AVR Studio 5.0 for the radioand OBC-software. This development tool uses the AVR GNU Toolchain,
and all libraries have to work with this.
5.2
Functionality mapping
The functionality identified in chapter 4 is mapped into modules in the
system. This can be seen in figure 5.1.
Figure 5.1: Nominal mode, module functionality
Radio
Beacon control
Beacon transmit
Radio receive
Radio transmit
Command processing
OBC
System control
Housekeeping
Data storage
Payload processing
Command dispatcher
Command scheduler
Command processing
EPS
Power management
ADCS
Sensors
Actuators
ADCS processing
Command processing
31
Payload
Camera control
Command processing
The radio is a single point of failure. However, we have two backplane masters. If the OBC fails, the system will have to operate in ”reduced” mode as seen in figure 5.2. The radio doesn’t have the same
hardware features as the OBC, so it will not be able to substitute the
OBC completely.
Figure 5.2: Reduced mode, module functionality
5.3
Communications architecture
When using libcsp, we end up with a layered architecture, as seen in
figure 5.3
The libcsp core functionality contains basic functions in the CSP library. These functions include – but are not limited to – buffer management, service handlers, socket management, port management and
packet routing. Above this layer, we have the two protocols which would
belong in the transport layer in the OSI model. UDP is implemented in
CSP, and at least parts of RDP is implemented. On top of the transport
protocols, we find the module commands layer. It is in this layer we will
do module-specific processing and it is here we have the business logic.
Below the libcsp core functionality layer, we find medium specific
code. CSP is not dependent on what is used to transport data, but
it needs code to interface with it. On the bottom layer, we find the
hardware drivers. CSP has to interface with this layer to be able to push
data around. This means that in order to transport CSP packets over the
internal data bus in NUTS, we will have to implement an I 2 C interface
Figure 5.3: Architecture
Application
Transport &
network layer
Module commands
UDP
RDP
libcsp core functionality
Link layer
I2C
framing
KISS
I2C
driver
USB &
USART
driver
AX.25(?) Loopback
Radio
driver
in CSP, and talk to an hardware driver. This driver must work with
FreeRTOS.
5.4
Quality attributes
At this point, it is hard to verify that the architecture (or the implementation) achieves the desired quality attributes. To test this, one could
make quality attribute scenarios. But it must be possible to test the system against these attribute scenarios for them to have any value.
But we can draw some general conclusions for each attribute.
Security
CSP supports both packet encryption and authentication using HMAC.
Both methods are alone sufficient for ensuring that no malicious third
party sends command to the satellite, without the radio or the subsystem knowing that the command is to be discarded. Of course, this is
assuming the implementation does not contain any flaws.
Modifiability
Using an operating system like FreeRTOS, has the same effect as implementing a HAL — an Hardware Abstraction Layer. This makes typical
”user”-programs less specific to the hardware, because the operating
system provides methods for synchronisation, intertask-communication
etc.
Reliability
At this point, the architecture itself does not imply extra reliability. CSP
does checksumming of packets, but tasks running within FreeRTOS are
not restricted to what kind of memory addresses they are allowed to
write to. Currently there is no FreeRTOS port for AVRUC3, that supports the MPU.
Testability
The code, as it is now, is not very testable.
5.5
Fairness on the data bus
I 2 C is a multimaster-bus, and the module that sends the ”lowest” byte is
always going to win arbitration. This means that we will have to impose
extra restrictions if it should be possible to guarantee fairness or any
particular quality of service. In most CubeSat projects this has not been
a problem in practice, because on could rely on loose timing constraints
and sheer bandwidth. NUTS has strict no timing constraints, but the
I 2 C bus is not made for shuffling large amounts of data around.
We do not yet know how much data the payload mdule is going to
transfer over the bus, and this makes it a theoretical issue. There are no
other module in the satellite that has to shuffle around potentially huge
amounts of data.
To reduce the noise on the bus, it has been decided that only the
radio and the OBC are allowed to assume the roles as masters on the
bus. This means that they are the only modules that are allowed to initiate transactions on the internal data bus. No other module is allowed
to start a bus transaction on its own initiative. The result is that the
system has to rely on either periodically polling each module for status
information, or ”know” that we have some data to receive.
It would be possible to impose some kind of bus arbitration scheme.
This will not be discussed in this report, and it would be better to put
a definitive limit to the size of a single picture before deciding whether
this is going to be necessary in practice.
5.6
Conclusion
We have seen how using COTS software can help achieve some qualities.
But there is still a lot to be desired. Methods for achieving reliability
have to be researched, and a policy for writing testable code has to be
developed.
6
Testing
Introduction
This chapter describes how the implementation was tested. We first describe how cubesat space protocol was tested on a development system
representative for the ground station. We then describe how basic functionality in FreeRTOS was tested on the OBC. Last, we describe how
cubesat space protocol was compiled and linked into the OBC firmware
this firmware was tested and verified not to overflow or exceed the
amount of available embedded memory on the main MCU.
6.1
Scope
No test plan has been developed, because it is too early in the software
development. The typical documentation for testing software will follow the IEEE Standard 829-2008 [15], and adopted to the project in question. This will have to be done in the future, when it is possible to test
the requirements described in chapter 4. Instead we choose to describe
how the software evolved, and how it was tested during development to
make sure that the desired features were present and working. We only
describe the parts that are relevant to the implementation described in
this report.
6.2
Testing cubesat space protocol
This section describes how cubesat space protocol was tested in a envitronment similar to that of the ground station. Here, the test system
37
meet the minimum system requirements as described in the system requirements section 4.3.
Software
• Operating system: Windows 7
• IDE/text editor: vim 7.3
• Compiler/Toolchain: MinGW with GCC 4.5.2
• Other: cubesat space protocol
CSP in loopback mode
When running CSP in loopback mode, the server and client are two
threads within the same process. To verify that the windows-port was
working, a simple program was written. All it does is to use various services integrated in CSP as well as send a packet with arbitrary payload.
The former tests that the ”service handler” within CSP is working, and
the latter tests that it works for an arbitrary packet.
The code for the test program can be found in the appendix, in section A.3 or in an archive file enclosed with this report.
Dan [email protected] /C/Repos/Studsat/Software/ground segment/GSE/CSP_Loopback/branches/_danerik
$ make
g++ -g -pedantic -D__STDC_LIMIT_MACROS -Iinclude -Ilib/libcsp/include
-c -o src/main.o s
rc/main.cpp
In file included from include/server.h:5:0,
from src/main.cpp:8:
lib/libcsp/include/csp/csp.h:635:34: warning: anonymous variadic macros were introduced in
C99
lib/libcsp/include/csp/csp.h:141:19: warning: comma at end of enumerator list
lib/libcsp/include/csp/csp.h:203:2: warning: ISO C++ prohibits anonymous structs
lib/libcsp/include/csp/csp.h:263:17: warning: ISO C++ forbids zero-size array ’data’
lib/libcsp/include/csp/csp.h:264:20: warning: ISO C++ forbids zero-size array ’data16’
lib/libcsp/include/csp/csp.h:265:20: warning: ISO C++ forbids zero-size array ’data32’
lib/libcsp/include/csp/csp.h:620:16: warning: comma at end of enumerator list
mv src/main.o obj/
g++ -Llib/libcsp/lib
obj/main.o obj/event.o obj/mutex.o obj/thread.o obj/screenlock.o ob
j/client.o obj/server.o -lcsp -lstdc++ -o obj/main
mv obj/main bin/main
Dan [email protected] /C/Repos/Studsat/Software/ground segment/GSE/CSP_Loopback/branches/_danerik
$ bin/main.exe
Level 0: value 1
Level 1: value 0
Level 2: value 0
Level 3: value 1
Level 4: value 1
Level 5: value 1
Level 6: value 1
1 csp_port.c:90 Binding socket 00542F78 to port 16
?[0mServer listening
Client trying to connect to server...
?[0;33m1 csp_buffer.c:115 BUFFER: Using element 1 at 00543108
?[0mPS node 1: ?[0;32m1 csp_io.c:188 Sending packet size 1 from 1 to 1 port 2 via interfac
e LOOP
?[0m?[0;32m1 csp_route.c:259 Router input: P 0x02, S 0x01, D 0x01, Dp 0x02, Sp 0x15, F 0x0
0
?[0m?[0;32m1 csp_io.c:188 Sending packet size 37 from 1 to 1 port 21 via interface LOOP
?[0m?[0;33m1 csp_buffer.c:147 BUFFER: Free element 1
?[0;32m1 csp_route.c:259 Router input: P 0x02, S 0x01, D 0x01, Dp 0x15, Sp 0x02, F 0x00
?[0m?[0mPS Length 37
Tasklist in not available on windows
?[0;33m1 csp_buffer.c:147 BUFFER: Free element 1
?[0m?[0;33m1 csp_buffer.c:115 BUFFER: Using element 2 at 00543248
?[0m?[0;32m1 csp_io.c:188 Sending packet size 0 from 1 to 1 port 3 via interface LOOP
?[0m?[0;32m1 csp_route.c:259 Router input: P 0x02, S 0x01, D 0x01, Dp 0x03, Sp 0x16, F 0x0
0
?[0m?[0;32m1 csp_io.c:188 Sending packet size 4 from 1 to 1 port 22 via interface LOOP
?[0m?[0;33m1 csp_buffer.c:147 BUFFER: Free element 2
?[0m?[0;32m1 csp_route.c:259 Router input: P 0x02, S 0x01, D 0x01, Dp 0x16, Sp 0x03, F 0x0
0
?[0m?[0;33m1 csp_buffer.c:147 BUFFER: Free element 2
?[0mFree Memory at node 1 is 1834471424 bytes
?[0;33m1 csp_buffer.c:115 BUFFER: Using element 3 at 00543388
?[0m?[0;32m1 csp_io.c:188 Sending packet size 0 from 1 to 1 port 5 via interface LOOP
?[0m?[0;32m1 csp_route.c:259 Router input: P 0x02, S 0x01, D 0x01, Dp 0x05, Sp 0x17, F 0x0
0
?[0m?[0;32m1 csp_io.c:188 Sending packet size 4 from 1 to 1 port 23 via interface LOOP
?[0m?[0;33m1 csp_buffer.c:147 BUFFER: Free element 4
?[0mUptime of node 1 is 155234 s
?[0;33m1 csp_buffer.c:115 BUFFER: Using element 5 at 00543608
?[0m?[0;32m1 csp_io.c:188 Sending packet size 0 from 1 to 1 port 8 via interface LOOP
?[0m?[0;32m1 csp_route.c:259 Router input: P 0x02, S 0x01, D 0x01, Dp 0x08, Sp 0x19, F 0x0
0
?[0mMessage from client: Hello world!
?[0;33m1 csp_buffer.c:147 BUFFER: Free element 5
?[0m
The tested version of CSP use ANSI escape sequences, and they are not
interpreted by the terminal.
CSP in USART/KISS mode
In this mode, packet data is encapsulated in KISS frames and sent via
an USART interface. The test program runs both a server and a client
thread, as when testing CSP in loopback mode. The difference is that the
packet is sent to a different interface. An Atmel XMEGA A-1 Xplained
was used as the ”OBC” in this example. The program on the A-1 does
nothing but ”bounce” any received characters back to the sender. This
tests that CSP is able to use the USART interface, and that KISS encapsulation and decapsulation works.
The test output is:
Dan [email protected] /C/Repos
$ gcc -Wall -pedantic -std=gnu99 -Lcsp_deploy/lib -Icsp_deploy/include kiss.c -lcsp -o ki
ss
In file included from kiss.c:5:0:
csp_deploy/include/csp/csp.h:143:3: warning: ISO C doesn’t support unnamed structs/unions
csp_deploy/include/csp/csp.h:196:11: warning: ISO C forbids zero-size array ’data’
csp_deploy/include/csp/csp.h:197:12: warning: ISO C forbids zero-size array ’data16’
csp_deploy/include/csp/csp.h:198:12: warning: ISO C forbids zero-size array ’data32’
csp_deploy/include/csp/csp.h:199:3: warning: ISO C doesn’t support unnamed structs/unions
Dan [email protected] /C/Repos
$ ./kiss.exe
Level 4: value 1
Level 2: value 1
[01] usart_windows.c:93 Port: COM4, Baudrate: 9600, Data bits: 8, Stop bits: 0, Parity: None
[00 0040F074] S:0, 0 -> 0, 0 -> 0, sock: 00000000
[01 0040F098] S:0, 0 -> 0, 0 -> 0, sock: 00000000
[02 0040F0BC] S:0, 0 -> 0, 0 -> 0, sock: 00000000
[03 0040F0E0] S:0, 0 -> 0, 0 -> 0, sock: 00000000
[04 0040F104] S:0, 0 -> 0, 0 -> 0, sock: 00000000
[05 0040F128] S:0, 0 -> 0, 0 -> 0, sock: 00000000
[06 0040F14C] S:0, 0 -> 0, 0 -> 0, sock: 00000000
[07 0040F170] S:0, 0 -> 0, 0 -> 0, sock: 00000000
[08 0040F194] S:0, 0 -> 0, 0 -> 0, sock: 00000000
[09 0040F1B8] S:0, 0 -> 0, 0 -> 0, sock: 00000000
Node Interface Address
1 KISS
1
* LOOP
255
LOOP
tx: 00000 rx: 00000 txe: 00000 rxe: 00000
drop: 00000 autherr: 00000 frame: 00000
txb: 0 (0.0B) rxb: 0 (0.0B)
KISS
tx: 00000 rx: 00000 txe: 00000 rxe: 00000
drop: 00000 autherr: 00000 frame: 00000
txb: 0 (0.0B) rxb: 0 (0.0B)
[01]
[01]
[01]
[01]
[01]
[01]
Ping
[01]
[01]
[01]
[01]
[01]
Ping
[01]
[01]
[01]
[01]
[01]
Ping
[01]
[01]
[01]
[01]
[01]
Ping
csp_port.c:90 Binding socket 0040F098 to port 32
csp_io.c:234 Sending packet size 100 from 1 to 1 port
csp_route.c:254 Router input: P 0x02, S 0x01, D 0x01,
csp_service_handler.c:94 SERVICE: Ping received
csp_io.c:234 Sending packet size 100 from 1 to 1 port
csp_route.c:254 Router input: P 0x02, S 0x01, D 0x01,
with payload of 50 bytes, took 1092 ms
csp_io.c:234 Sending packet size 100 from 1 to 1 port
csp_route.c:254 Router input: P 0x02, S 0x01, D 0x01,
csp_service_handler.c:94 SERVICE: Ping received
csp_io.c:234 Sending packet size 100 from 1 to 1 port
csp_route.c:254 Router input: P 0x02, S 0x01, D 0x01,
with payload of 100 bytes, took 998 ms
csp_io.c:234 Sending packet size 100 from 1 to 1 port
csp_route.c:254 Router input: P 0x02, S 0x01, D 0x01,
csp_service_handler.c:94 SERVICE: Ping received
csp_io.c:234 Sending packet size 100 from 1 to 1 port
csp_route.c:254 Router input: P 0x02, S 0x01, D 0x01,
with payload of 150 bytes, took 1311 ms
csp_io.c:234 Sending packet size 100 from 1 to 1 port
csp_route.c:254 Router input: P 0x02, S 0x01, D 0x01,
csp_service_handler.c:94 SERVICE: Ping received
csp_io.c:234 Sending packet size 100 from 1 to 1 port
csp_route.c:254 Router input: P 0x02, S 0x01, D 0x01,
with payload of 200 bytes, took 999 ms
1 via interface KISS
Dp 0x01, Sp 0x25, F 0x00
37 via interface KISS
Dp 0x25, Sp 0x01, F 0x00
1 via interface KISS
Dp 0x01, Sp 0x26, F 0x00
38 via interface KISS
Dp 0x26, Sp 0x01, F 0x00
1 via interface KISS
Dp 0x01, Sp 0x27, F 0x00
39 via interface KISS
Dp 0x27, Sp 0x01, F 0x00
1 via interface KISS
Dp 0x01, Sp 0x28, F 0x00
40 via interface KISS
Dp 0x28, Sp 0x01, F 0x00
The output is different because this uses a more recent version of CSP,
where ANSI escape sequences are not printed when the library is compiled for Windows.
The code for the A1 and relevant code snippets for this test can also
be found in the appendix, in sections A.5 and A.4.
6.3
Testing the OBC
There were some technical difficulties when testing CSP on the OBC. To
test CSP on the OBC, the goal was to make it work in loopback mode,
while printing the result to a host computer over USB.
To do this, libcsp was compiled for FreeRTOS and our project with
the command from within the libcsp root folder:
JOBS=1 CFLAGS=”−mpart=uc3a3256 −DBOARD=USER BOARD −
DFREERTOS USED” . / waf d i s t c l e a n c o n f i g u r e −− t o o l c h a i n =avr32 −
−− p r e f i x = . . / obc deploy −−with−os= f r e e r t o s −−with− f r e e r t o s
= . . / obc/OBC System SW/ s r c / a s f / t h i r d p a r t y / f r e e r t o s /source/ −−
i n c l u d e s = . . / obc/OBC System SW/ s r c , . . / obc/OBC System SW , . . /
obc/OBC System SW/ s r c / c o n f i g , . . / obc/OBC System SW/ s r c / a s f /
t h i r d p a r t y / f r e e r t o s /source/ p o r t a b l e /gcc/avr32 uc3 , . . / obc/
OBC System SW/ s r c / a s f / t h i r d p a r t y / f r e e r t o s /source , . . obc/ a s f /
t h i r d p a r t y /newlib addons/ l i b c s /i n c lu d e , . . / obc/OBC System SW/
s r c / a s f /common/boards , . . / obc/OBC System SW/ s r c / a s f /common/
boards/user board , . . / obc/OBC System SW/ s r c / a s f /common/
s e r v i c e s / f i f o , . . / obc/OBC System SW/ s r c / a s f /common/ u t i l s / , . . /
obc/OBC System SW/ s r c / a s f /commonutils/ i n t e r r u p t , . . / obc/
OBC System SW/ s r c / a s f /avr32/ u t i l s , . . / obc/OBC System SW/ s r c /
a s f /avr32/ u t i l s / p r e p r o c e s s o r , . . / obc/OBC System SW/ s r c / a s f /
avr32/ d r i v e r s /pm, . . / obc/OBC System SW/ s r c / a s f /avr32/ d r i v e r s /
i n t c build i n s t a l l
While both the server and the client were able to run, the server program
quickly ran out of buffers. The test result was that both the server and
the client were running and printing their output to the host computer.
However, there was a bug that prevented it from functioning correctly.
The files under ../csp deploy/{include,lib} were copied into the
AVR Studio project for the OBC. The linker was configured to link with
the library, and the CSP include folder was added to the include paths
in the project properties.
To verify that the code would work with the internal OBC memory,
the avr32-nm was used to generate a list of symbols with adresses. Extracts from the output can be seen below:
avr32 −nm −s −n obc firmware . e l f
w Jv R e g i s t e r C l a s s e s
00000008
00000008
0000000 c
00000010
00000014
00000018
00000018
0000001 c
(...)
00000 b3c
00000 b40
00000 b44
00000 b45
00000 b48
00000 b50
00000 b54
00000 b58
00000 c60
00000 c64
00000 c68
00000 c70
00000 c70
00001000
00001000
0000 f 0 0 0
0000 f 0 0 0
00010000
80000000
80002000
80002004
80002020
(...)
ffffffff
ffffffff
w cpu r e s e t
w cpu s e t r e s e t cause
w csp r o u t e in pu t hook
CTOR LIST
d
B data
CTOR END
d
d
DTOR LIST
D
DTOR END
d
JCR END
d
JCR LIST
D GLOBAL OFFSET TABLE
B
B
B
B
B
B
B
B
B
B
B
A
A
A
A
A
B
B
T
t
T
T
A
A
s t d i o u s a r t base
prvScreenMutex
b rx new
b t x new
l i n e coding
my address
interfaces
routes
routes lock
handle r o u t e r
errno
heap s t a r t
end
stack size
stack size
heap end
stack
estack
trampoline
program s t a r t
init
stext
heap s i z e
max heap s i z e
We see that the heap begins at the end of the .data segment, and ends
at the beginning of the stack. The heap size is 0xF000-0x0C70, which is
about 56kB. The same method can be used to find the size of the stack.
The .text segment begins at 0x8000 0000. The standard linker script
puts a special ”trampoline” routine. Normally, this routine does nothing but transfer control to the user code. We also see a special symbol
called init. This symbol denotes a special initialisation function. This
function is defined by FreeRTOS, and it does early hardware initialisation. This includes configuring the interrupt controller, setting the stack
register to point at stack and configuring the exception vectors.
A linker script tells the linker how to lay out the final, linked binary. By looking at the OBC memory map in table 3.3, we see that it is
very important that data and code are put on the correct load memory
address.
If external memories are to be used, the linker script has to be modified to put the heap in external RAM, and the initialisation code has
to initialize the memory controller before anything is allocated from the
heap!
6.4
Conclusion
While the OBC code is not functioning properly, the Windows port of
CSP does. We also have working USART support in CSP, which means
that we have a very solid basis for developing ground station software
for NUTS. FreeRTOS is also working on the OBC, so it is easy to create
new tasks.
The vast majority of the features implied by the requirements specification are still lacking, so a more formal test could not be performed
at this point.
Part II
NUTS software
45
Ground segment software
7
Introduction
This chapter describes the existing software for the ground segment.
Software that is not directly relevant to the assignment will not be described. The rest of the chapter is about the porting of Cubesat Space
Protocol for Windows. Testing of the implementation is detailed in chapter 6
7.1
Previous work
Currently, there is a single ground segment program for the OBC. This
program uses an USART to communicate with the OBC firmware, and
gives a graphical presentation of the results. This program works with
the firmware developed as part of the task of designing the OBC module. The plan is that this program will evolve into a fuilly featured
ground station program for controlling NUTS after launch. The program is written in C# and makes use of the .NET 4-framework, so we
have to keep this in mind when choosing third party libraries.
The use of this program, and other software, basically dictates that
we use Windows on the ground station.
7.2
Porting Cubesat Space Protocol
Prior to this project, libcsp was working on GNU/Linux and FreeRTOS.
Looking at the features and testing the library in loopback mode in
GNU/Linux, lead to the conclusion that trying to port it to Windows,
was well worth the effort. This section describes the process of porting
47
core libcsp to Windows, and creating a USART interface for it. Source
code listings can be found in A.2.
Porting libcsp to Windows
The code of libcsp is quite modular. Almost all of the platform specific
code is located in subfolders under src/arch/ in the root folder of the
project. The first step in developing a port, was to have a look at the
”POSIX” port. This was an obvious choice, because the author was
already familiar with parts of the API dictated by the POSIX standard.
Now there was two ways of solving this: The first is to try to find
an Windows-implementation of the POSIX API, and the other is to use
native API functions. Both strategies were tried in parallell.
Because the author was not familiar with the Windows API, the obvious first step was to map the POSIX port into a set of ”How do I...”:
• Create a thread
• Get the amount of available heap memory
• Create a concurrent queue using the Windows API
• Get the current time
• Allocate memory? What is the difference between GlobalAlloc and
LocalAlloc? Can I use malloc?
Each of those items were explored separately. In addition a suitable
compiler had to be found; libcsp is littered with compiler-specific directives. The conclusion is that it would not be possible to use Microsoft’s
own C compiler. Viable alternatives was to use MinGW or MinGW-w64
when developing a native port. The other option was to use GCC from
within Cygwin.
In the end, a native port of libcsp was developed. There are mainly
three reasons for this:
1. The POSIX implementation in Cygwin was lacking at least a function to get the time from a monotonically increasing clock source.
2. The resulting binary would have been dependent on a cygwin.dll
3. The upstream project developers did not want to use Cygwin
The native port of libcsp was first compiled using MinGW. We found
that the Windows API headers part of the MinGW environment were
lacking support for ”condition variables”. Support for this was introduced with Windows Vista, and apparently the MinGW-developers
haven’t noticed.
Before investigating further, a another development environment was
tried: MinGW-w64. This is more than a compiler: It is also a combination of runtime libraries and headers. To be on the safe side, we tried
to install a completely new development toolchain for MinGW-w64. Because we could not find any working binaries, the whole toolchain plus
compiler had to be compiled. Details on how that was done is described
in the appendix, in section A.1.
Unfortunately, this turned out to be a waste of time. It did work, but
was not necessary to make use of condition variables. Instead, it was
enough to create appropriate declarations for the implicated functions.
These declaration can be found in the file src/arch/windows/windows glue.h,
in the Cubesat Space Protocol port.
Merging Cubesat Space Protocol
We did make an effort at merging the port with the upstream project.
This is an advantage for both parties. For GomSpace, it is nice to have
support for another platform. This increases the value of their product.
For us it is also an advantage: It is easier to keep track of the changes in
the Cubesat Space Protocol library, and stay updated.
Because of the collaboration with the upstream developers, it was
feasible to use our own Subversion repository when working with Cubesat Space Protocol. Instead, Git was found to be a better alternative.
Result
libcsp has been ported to Windows, and the changes have been merged
with the upstream project. However it is still not possible to use the
libcsp headers with MSVC. This is not a significant limitation at this
point. But we will have to figure out how to make use of this library
from a program written in C#.
Space segment software
8
Introduction
This chapter described the current state of the NUTS space segment
software.
8.1
Previous work
A test program has been developed for the OBC. This test program takes
commands via a USART-like interface where the OBC acts like a USB
CDC devic, implementing the ”Abstract Control Model”. The program
is able to control the backplane, and includes code snippets for writing
to external memories.
8.2
OBC software
In this section we describe the software and the toolchain for the OBC.
Operating system
Because Cubesat Space Protocol is ported to FreeRTOS, and a FreeRTOS
port existsis for the MCU on the OBC, the choice of OS on the OBC
is quite clear. But compiling the FreeRTOS port found on http://www.
freertos.org/ would not work with the current version of the Atmel
GNU toolchain. Instead, it was found that it was easier to start with an
example project targeting one of Atmel’s evaluation board. More details
on how this example project was customised to our needs, can be found
in the appendix in section A.7
51
C library
AVR 32-bit GNU Toolchain uses Newlib as the C standard library. The
Newlib project on the official project website at http://sourceware.
org/newlib, does not support AVR 32s. Instead Atmel, have created
ther own set of patches to Newlib. These patches targets version 1.16.0
of Newlib [7].
In addition, Atmel have produced their own AVR32-port for GCC.
These patches have not been merged with the upstream project, are part
of the default installation of the AVR GNU toolchain.
Memory requirements
The combination of FreeRTOS, cubesat space protocol and Newlib resulted in quite high memory use. In FreeRTOS, the task context is stored
on the top of the stack for each task and the stack for each task is allocated from the heap. This means that the task stacks and ”ordinary”
dynamically allocated memory compete fo the same memory area.
The task stack has to be large enough for the most ”stack-consuming”
function used by each task. In one case, we had problems with a stack
overflow. It turned out that the printf function in Newlib was the culprit.
Result
FreeRTOS is working on the OBC, but there are some problems with
using CSP in loopback mode. This is the first step in using CSP on the
OBC, so this problem has to be solved before proceeding with building
more elaborate services on top of the CSP library.
We have also seen that the memory requirements of the OBC firmware
are quite high. A more long-term solution is to move the heap to external SRAM. But on the other hand, Atmel recommends that the stack is
kept in embedded data memory because the access time is lower. This
warrants more investigation.
Part III
Conclusion and evaluation
53
Conclusion and evaluation
9
Introduction
This chapter summarises this project. First we summarise the results of
the project work, and then we evaluate the results and how externalities
have affected the outcome.
9.1
Conclusion
Here we summarise the results of the project, and the decisions taken.
Overall system
Cubesat space protocol is used both on the OBC and the ground station.
libcsp has not been tested for interoperability with the existing software
on the ground station.
FreeRTOS is the chosen operating system on the OBC. In addition
to libcsp, we use a USB stack implementing the device part of the USB
CDC device class. The OBC still lacks a lot of drivers. The drivers
developed during the design of the OBC have not been integrated into
the current OBC firmware.
Testing
It is difficult to test embedded systems. The strategy for testing the
Cubesat space protocol when porting this to windows, have been to try
to isolate as much of the library as possible, and start working with the
most trivial parts first.
55
Testing the OBC firmware was difficult at best. For instance, a stack
overflow caused a lot of headache during development. The only visible
behavior, was that the OBC ended up in an seemingly arbitrary exception handling routine. It was not possible to deduce why or what caused
this to happen. In the end, the problem was a stack overflow when calling printf. The lessons learned here, is that concurrency makes both
testing and debugging difficult.
Unit-testing has not been considered in this project. It would be interesting to research what kind of options we have. But it is important to
note that unit-testing would most likely not reveal the problems enountered during testing of FreeRTOS and Cubesat Space Protocol on the
OBC.
Summary
Cubesat space protocol, libcsp, was found to be a capable communications library. By using libcsp, and using our own services on top of that,
we can take advantage of the fact that libcsp is a tried and testet product. Another option would be to develop a solution from scratch. This
has been done in many other CubeSat projects. But we would still need
at least the following features:
• Packet routing
• Packet checksumming
• Packet authentication or encryption
• Services for getting system status
• Be relative hardware independent
Each of those features themselves, would probably not take a tremendous effort to implement ourselves. Especially because we only have to
implement exactly what we need. But we would still have to spend a lot
of time designing, implementing and testing the system.
FreeRTOS was found to be the only viable OS alternative. There are
other operating systems, but unless we are willing to do the porting
ourselves, there is no other cost-effective option. libcsp is also ported to
FreeRTOS.
It would be possible to implement operating system-like features
ourselves. And while that would certainly be an interesting task, i would
also just as certain be extremely time consuming.
9.2
Evaluation
Here I summarise the experiences from the project, and evaluate the
work done in the project.
NUTS project
One of the main problems with developing software in this project, is to
get an idea of what we are trying to do. The project is a typical example
of bottom-up design. When it is not clear exactly what the satellite
is supposed to do, this kind of strategy makes it difficult to develop
software. While the project work described in this report mainly focuses
on a single module, namely the OBC, the software still has to be design
for the whole system. This means that developing software for the OBC,
involves a huge integration problem.
For a software developer, it would be easier to do it in the opposite
direction:
1. Decide what the system should do
2. Create a requirements specification for this
3. Design an architecture
4. Design a system architecture
5. Decide what kind of hardware is necessary to implement the architecture, with the required properties
Risks
It seems that one of the problems in this project is sharing of knowledge.
Because this is a last-year project for most students, we are always being
drained for knowledge.
Also, the hardware is a variation point. As it is now, we depend
on the fact that both the radio and the OBC are using the same processor. Depending on what kind of hardware is used in the other modules, it may be challenging to use cubesat space protocol throughout the
system. It may even be necessary to either port FreeRTOS to another
architecture or develop a minimal operating system.
Resources devoted to software design
Having a single persion work on software is way too little
Issues
There are a couple of issues with the current implementation:
• libcsp must be integrated with the existing ground station software
• We are very close to reaching the limits of the internal OBC memory
• Input from the OBC code is not working as expected ( scanf)
• The current write-implementation depends on FreeRTOS queues.
Maybe it should go through a gateway task, instead of communicating (in)directly with the device cdc task.
Future work
Software-wise, the current implementation is sorely lacking features and
testing. Suggestions for future work are:
1. Improve the I/O-facilities.
2. Develop a test plan for the software
3. Create integration tests
4. Develop services for peristent storage on the OBC, possibly using
a file system
5. Write hardware drivers
6. Test the OBC firmware on the radio module
References
[1] Swisscube launch schedule, 2009.
[2] Ansat project. www.ANSAT.no, 2011. Last read: 17 December 2011.
[3] Built-in functions specific to particular target machines. http:
//gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Target-Builtins.
html#Target-Builtins, 2011. Last read: December 17 2011.
[4] Other built-in functions provided by gcc.
http://gcc.
gnu.org/onlinedocs/gcc-4.1.1/gcc/Other-Builtins.html#
Other-Builtins, 2011. Last read: December 17 2011.
[5] Swiss cube — the first swiss satellite. http://swisscube.epfl.ch/,
2011. Last read: 17 December 2011.
[6] Swisscube — gunter’s space page. http://space.skyrocket.de/
doc_sdat/swisscube.htm, 2011. Last read: 17 december 2011.
[7] Atmel. AVR 32-bit GNU Toolchain: Release 3.3.0.275.
[8] Atmel. AVR32UC Technical Reference Manual, 2010.
[9] Roger Birkeland.
NTNU, 2011.
Nuts-1 mission statement.
Technical report,
[10] Callum Chartier, Michael Mackay, Drew Ravalico, Sonja Russell,
and Andrew Wallis. Ausat final report. Master’s thesis, The University of Adelaide, 2010.
[11] PC/104 Consortium. Pc/104 specifications. http://www.pc104.
org/specifications.php, 2011. Last read: 17 December 2011.
[12] Benoit Cosandier, Florian George, and Ted Choueiri. Swisscube
flight software architecture. Master’s thesis, EPFL, 2007.
59
[13] David Crettaz. Phase c: Cdms control & data management system.
Master’s thesis, HES-SO, 2007.
[14] Dewald de Bruyn. Power distribution and conditioning for a small
student satellite - design of the nuts backplane & eps module. Master’s thesis, NTNU, 2011.
[15] IEEE Standard for Software and System Test Documentation 8292008. IEEE Standard for Software and System Test Documentation 8292008, 2008.
[16] Anton Ivanov Muriel Noca. SwissCube status may 2 2010, 2010.
Last read: December 17 2011.
[17] NAROM. Nasjonalt studentsatellittprogram, ANSAT, 2011. Last
read: 17 December 2011.
[18] Muriel Nocaa, Fabien Jordan, Nicolas Steiner, Ted Choueiri, Florian George, Guillaume Roethlisberger, Noemy Scheidegger, Herve
Peter-Contesse, Maurice Borgeaud, Renato Krpoun, and Herbert
Shea. Lessons learned from the first swiss pico-satellite: Swisscube.
In Small Satellite Conference, 2009.
[19] NTNU. NUTS - NTNU Test Satellite. A Norwegian CubeSat Project
- Current activities, 2011. Last read: 17 December 2011.
[20] Philips. UM10204 I2C bus specification and user manual, 2007.
[21] Tapparel Pierre-Andre. Cdms. Master’s thesis, HEVs, 2007.
[22] Guillaume Roethlisberger. Swisscube structural design and flight
system configuration. Master’s thesis, EPFL, 2007.
[23] California Polytechnic State University. Cubesat design specification, rev. 12, 2009.
[24] Marius Voldstad. Internal data bus of a small student satellite.
Master’s thesis, NTNU, 2011.
A
Appendix
A.1
Installing and configuring MinGW
Introduction
This section describes how to set up MinGW for compiling programs in
Windows.
Installing MinGW
An installer for MSYS and MinGW can be obtained by navigating to the
project page on http://sourceforge.net/projects/mingw/files/ and
downloading the latest version of mingw-get-inst.
mingw-get-inst is a graphical installation program that installs both
MinGW and MSYS. This installer will actually download mingw-get,
and it is this program that will actually perform the installation. After
installation, mingw-get can be used to download both updates and new
programs available in the package repository.
When installing using mingw-get-inst, remember that
• Choose to use the ”pre-packaged repository catalogue”
• The installation path should not contain any whitespaces. The
default of using C:\MinGW is good.
Setting up MinGW
Move the home directory
As default, MSYS will create a home directory derived from the Windows user name. If this name does *not* contain a whitespace, this
61
section can be skipped.
First, open the MinGW-shell. Next, open /etc/profile within an text
editor. At around line 30, the home directory is created if it doesn’t
already exist. If you are running MinGW shell, the home directory does
exist, unless we rename it. So change the text from this:
# Set up USER’s home directory
if [ -z "$HOME" ]; then
HOME="/home/$LOGNAME"
fi
into something like this:
LOGNAME=${LOGNAME// /_}
# Set up USER’s home directory
if [ -z "$HOME" ]; then
HOME="/home/$LOGNAME"
fi
Save the file and exit the text editor, and navigate to the home directory by executing:
cd ~ && cd .. && mv My\ User\ Name My_User_Name
Open a new MinGW shell, to verify that everything is working. Because we changed the format of the LOGNAME variable, and renamed
the home directory to follow the same formatting, we should end up in
the same directory. The only difference should be the name of the home
directory.
Create a programs folder within the home folder (and set
up bash)
We are going to create a folder hierarchy within the home folder, similar
to /usr/local. Within this hierarchy, we can install things like subversion
– without affecting the ”global” environment.
First, we need to to make /etc/profile ”source” per-user settings.
At the end of /etc/profile, add the logic for doing that. So the last line
would look something like this:
if [ -e ~/.bashrc ]; then
. ~/.bashrc
fi
Next, create the file ‘.bashrc‘ in the home directory. In this file, add
the following statements:
alias g=’grep -r --exclude="*\.svn*" --color=always’
alias vi=vim
export PATH=$PATH:~/local/bin
This will also add useful aliases for vi and grep. The alias for grep is
useful, because it makes grep use colorised output and makes it exclude
subversion ”control” directories.
Next, create the folder that we just added to path:
mkdir -pv ~/local/bin
Installing Subversion
It is useful to be able to use subversion within the MSYS environment. A
viable option is to use Subversion for Windows. The most recent version
as of this writing, is 1.16.17. I prefer to simply download an archive file
- as opposed to using an installer. Both would work, but when using the
installer, the location of the binaries will have to be added to the path.
Assuming we are going to download and extract Subversion 1.6.17
(http://sourceforge.net/projects/win32svn/files/1.6.17/svn-win32-1.
6.17.zip/download) from within MSYS:
cd ~
mingw-get install msys-wget msys-unzip
wget \
http://sourceforge.net/projects/win32svn/files/1.6.17/svn-win32-1.6.17.zip/downloa
unzip svn-win32-1.6.17.zip
cd svn-win32-1.6.17
mv bin/* ~/local/bin
Installing dependencies for compiling GCC
GCC has several build-time dependencies, and some of them are not
part of a ”standard” installation of MinGW. I found the following libraries to be missing:
• Mpc
• MPFR
• GMP
They can be installed by executing: mingw-get install mpc mpfr
gmp
Notes about MinGW, MinGW-w32 & MinGW-w64
MinGW was formerly known as mingw32. The project was renamed to
MinGW, to remove any impressions that it was limited to 32 bit archiectures only. It provides a set of runtime headers, but does not contain a
C runtime library. The C runtime library is provided by Microsoft, and
distributed with Windows. More specifically, MinGW does not provide
a CRT because GCC does not provide it. However, GCC comes with
some basic runtime support routines for things like exception handling
(but then you must link with -lgcc instead of the often implicit -lc). In
addition it comes with an implementation of STL – libstdc++. On a
typical Linux system, the C library is glibc.
MinGW-w64 began as a spinoff project from mingw32, providing
support for creating 64-bit binaries. It provides both headers and a runtime library, in addition to supporting both x86-32 and x86-64. When
compiling for x86-32, the toolchain binaries are prefixed with mingww32. MinGW-w64 also provides a C interface to msvcrt.dll, and more
up-to-date headers than MinGW. The C interface allows GCC to build
for Windows.
What’s a cross compiler?
In the context of compilers, the concepts about a ”target”, ”host” and
the ”build machine” are common. In short:
• build: The machine you are building on
• host: The machine that you are building for
• target: The machine that you will produce code for. E.g. GCC will
produce code for x86-64
If all of these three are equal, we build a native toolchain. If build
and host are the same, but target is different, you are building a cross
toolchain.
Get the sources of GCC and MinGW-w64
I’ve chosen to use the 4.6 branch of GCC. There is no particular reason
for this. Using the source from trunk would probably also work, but I
don’t know much about the development process to say anything about
the stability of the ”HEAD” of the 4.6 branch or trunk.
mkdir ~/repos
cd repos
svn co \
svn://http://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch gcc46x
For MinGW-w64, you can fetch the code either from the subversion
repository, or download a snapshot from http://sourceforge.net/projects/
mingw-w64/files/. If you choose to do the latter download the latest
”headers and CRT source” into the /repos folder.
Compile and install binutils
Download and extract binutils to /repos. Then:
mkdir -pv ~/repos/build/binutils
cd ~/repos/build/binutils
../../binutils-2.22.51/configure --prefix=/usr/local \
--target=i686-w64-mingw32 --disable-multilib
make
make install
The build directory can be removed after installing. Also, the bin folder
will have to be added to path, in order for it to be detected during
configuration of gcc.
It is important to specify the target. Otherwise the ”guessed” target
would be i686-pc-mingw32, and linking would fail when compiling with
make.
Compile and install the headers for MinGW-w64
Here, we assume that the sources are located in /repos/mingw-w64-2.0.
We are going to build the sources in a separate directory:
mkdir -pv ~/repos/build/mingw-w64-headers
cd ~/repos/build/mingw-w64-headers
../../mingw-w64-v2.0/mingw-w64-headers/configure \
--prefix=/usr/local --host=i686-w64-mingw32 --disable-multilib
make install
Compiling GCC core
Again, we are going to configure and compile the sources from outside
the project folder
mkdir -pv ~/repos/build/gcc
cd ~/repos/build/gcc
../../gcc-4.6/configure --prefix=/usr/local --target=i686-w64-mingw32
make all-gcc
make install-gcc
These steps will build and install GCC core. That is, only the C-compiler.
Compiling the C runtime library
mkdir -pv ~/repos/build/mingw-w64-crt
cd ~/repos/build/mingw-w64-crt
../../mingw-w64-v2.0/mingw-w64-crt/configure \
--prefix=/usr/local --target=i686-w64-mingw32
make
make install
Compiling and installing the rest of GCC
cd ~/repos/build/gcc
make
make install
The C runtime library is necessary for using condition variables from the
Windows API. But in order to build the C runtime library, we also have
to install both mingw-w64 headers and GCC. Otherwise the configurescript for the mingw-64 crt will fail because it is missing a header provided by GCC core.
A.2
Cubesat space protocol, windows port
Introduction
This section contains the source code for the most relevant files in the
windows port, developed as part of this project. CSP have most of the
architecture-specific files in the folder src/arch/windows. Headers in
src/src include the headers for the architecture that is the build target.
In addition various small changes had to be made. When creating a
thread, a pointer to the thread function has to be passed to the threading API. However, the calling conventions are different for each platform. This had to be changed in src/csp route.c. This files contains
the definitions for the CSP router task, plus additional helper functions.
Also, the service handler had to be changed: The service handler has to
be able to process a ”get available memory”-request. This is platform
dependent.
After merging with the upstream project, the libcsp developers have
made some restructuring changes to their source code. This means that
the code listed here have evolved over time, and it is not unlikely that the
code structure will change again. The original upstream project can be
found at https://github.com/danerik/libcsp while the git repo used
during porting is at the following URL https://github.com/danerik/
libcsp
There are two main examples of code restructuring done since the
merge with upstream libcsp: An abstraction for threads (that addresses
the issue with the router task), and the service handler. I have taken the
liberty to list the windows-specific service handler, because this file contains the code that was originally part of the src/src/csp service handler.c
file.
main
# include <s t d i o . h>
# include <p r o c e s s . h>
# include <Windows . h>
#undef i n t e r f a c e
# include <csp/csp . h>
# include <csp/ i n t e r f a c e s / c s p i f k i s s . h>
# include <csp/ d r i v e r s / u s a r t . h>
# define PORT 10
# define MY ADDRESS 1
# define SERVER TIDX 0
# define CLIENT TIDX 1
# define USART HANDLE 0
unsigned WINAPI s e r v e r T a s k ( void ∗params ) ;
unsigned WINAPI c l i e n t T a s k ( void ∗params ) ;
s t a t i c HANDLE t h r e a d s [ 2 ] ;
i n t main ( i n t argc , char ∗ argv [ ] ) {
c s p d e b u g t o g g l e l e v e l ( CSP PACKET ) ;
c s p d e b u g t o g g l e l e v e l ( CSP INFO ) ;
struct usart conf settings ;
s e t t i n g s . d e v i c e = a r g c ! = 2 ? ”COM4” : argv [ 1 ] ;
s e t t i n g s . baudrate = CBR 9600 ;
settings . databits = 8;
s e t t i n g s . p a r i t y s e t t i n g = NOPARITY ;
s e t t i n g s . s t o p b i t s = ONESTOPBIT ;
s e t t i n g s . c h e c k p a r i t y = FALSE ;
c s p b u f f e r i n i t (10 , 300) ;
c s p i n i t (MY ADDRESS) ;
u s a r t i n i t (& s e t t i n g s ) ;
csp kiss init ( usart putstr , usart insert ) ;
usart set callback ( csp kiss rx ) ;
c s p r o u t e s e t (MY ADDRESS, &c s p i f k i s s , CSP NODE MAC) ;
cs p ro ute st art ta sk (0 , 0) ;
csp conn print table () ;
csp route print table () ;
csp route print interfaces () ;
t h r e a d s [ SERVER
serverTask ,
t h r e a d s [ CLIENT
clientTask ,
TIDX ]
NULL,
TIDX ]
NULL,
= (HANDLE) b e g i n t h r e a d e x (NULL, 0 , &
0 , NULL) ;
= (HANDLE) b e g i n t h r e a d e x (NULL, 0 , &
0 , NULL) ;
W a i t F o r M u l t i p l e O b j e c t s ( 2 , threads , TRUE, INFINITE ) ;
return 0 ;
}
unsigned WINAPI s e r v e r T a s k ( void ∗params ) {
i n t running = 1 ;
csp
csp
csp
csp
socket
conn t
packet
packet
t ∗ s o c k e t = c s p s o c k e t ( CSP SO NONE ) ;
∗conn ;
t ∗ pack et ;
t ∗ response ;
response = c s p b u f f e r g e t ( s i z e o f ( c s p p a c k e t t ) + 2 ) ;
i f ( response == NULL ) {
f p r i n t f ( s t d e r r , ”Could not a l l o c a t e memory f o r response
pack et ! \ n” ) ;
return 1 ;
}
response −>data [ 0 ] = ’O ’ ;
response −>data [ 1 ] = ’K ’ ;
response −>l e n g t h = 2 ;
c s p b i n d ( s o c k e t , CSP ANY) ;
c s p l i s t e n ( socket , 5) ;
while ( running ) {
i f ( ( conn = c s p a c c e p t ( s o c k e t , 1 0 0 0 0 ) ) == NULL ) {
continue ;
}
while ( ( packet = c s p r e a d ( conn , 1 0 0 ) ) ! = NULL ) {
switch ( c s p c o n n d p o r t ( conn ) ) {
c a s e PORT :
i f ( packet −>data [ 0 ] == ’ q ’ )
running = 0 ;
c s p b u f f e r f r e e ( p acket ) ;
csp send ( conn , response , 1 0 0 0 ) ;
break ;
default :
c s p s e r v i c e h a n d l e r ( conn , pac ket ) ;
break ;
}
}
c s p c l o s e ( conn ) ;
}
c s p b u f f e r f r e e ( response ) ;
return 0 ;
}
unsigned WINAPI c l i e n t T a s k ( void ∗params ) {
char outbuf = ’ q ’ ;
char i n b u f [ 3 ] = { 0 } ;
int pingResult ;
f o r ( i n t i = 5 0 ; i <= 2 0 0 ; i += 5 0 ) {
p i n g R e s u l t = c s p p i n g (MY ADDRESS, 1 0 0 0 , 1 0 0 , CSP O NONE
);
p r i n t f ( ” Ping with payload o f %d bytes , took %d ms\n” , i
, pingResult ) ;
Sleep (1000) ;
}
c s p p s (MY ADDRESS, 1 0 0 0 ) ;
Sleep (1000) ;
csp memfree (MY ADDRESS, 1 0 0 0 ) ;
Sleep (1000) ;
c s p b u f f r e e (MY ADDRESS, 1 0 0 0 ) ;
Sleep (1000) ;
csp uptime (MY ADDRESS, 1 0 0 0 ) ;
Sleep (1000) ;
c s p t r a n s a c t i o n ( 0 , MY ADDRESS, PORT, 1 0 0 0 , &outbuf , 1 ,
inbuf , 2 ) ;
p r i n t f ( ” Quit response from s e r v e r : %s \n” , i n b u f ) ;
return 0 ;
}
A.3
Cubesat space protocol, ground segment
test code
Introduction
This section contains code listings fort the most relevant parts of the
ground segment tests for libcsp. Note that the listed code relies on a
more elaborate program that wraps the Windows API behind classes
for events and threads.
main
The ScreenLock is a singleton instance. However, we cannot rely on
thread safe static initialisation, so the main thread acquires and releases
the thread once before starting the server and client.
# include
# include
# include
# include
# include
<iostream >
<p r o c e s s . h>
<Windows . h>
” t h r e a d . h”
”mutex . h”
# include ” event . h”
# include < c l i e n t . h>
# include <s e r v e r . h>
# include <csp/csp . h>
# include <common . h>
# include <s c r e e n l o c k . h>
# define DEBUG
using namespace s t d ;
Mutex screenMutex ;
Event readyEvent ;
void configureDebugging ( ) ;
void i n i t S c r e e n M u t e x S i n g l e t o n ( ) ;
i n t main ( ) {
initScreenMutexSingleton ( ) ;
/ / S e t up t h e c s p b u f f e r t h e same way , a s i t would ’ v e b e e n
with s t a t i c a l l o c
c s p b u f f e r i n i t ( CSP BUFFER COUNT , CSP BUFFER SIZE ) ;
c s p i n i t (ADDRESS) ;
cs p ro ute st art ta sk (4096 , 1) ;
# i f d e f DEBUG
configureDebugging ( ) ;
# endif
C l i e n t c ( readyEvent )
S e r v e r s ( readyEvent )
try {
c . Resume ( ) ;
s . Resume ( ) ;
c . Join ( ) ;
s . Join ( ) ;
} catch ( exception e )
cout << e . what ( )
}
;
;
{
<< endl ;
return 0 ;
}
void i n i t S c r e e n M u t e x S i n g l e t o n ( ) {
ScreenLock : : I n s t a n c e ( ) . Acquire ( ) ;
ScreenLock : : I n s t a n c e ( ) . R e l e a s e ( ) ;
}
void configureDebugging ( ) {
c s p d e b u g t o g g l e l e v e l ( CSP INFO ) ;
csp
csp
csp
csp
csp
csp
debug
debug
debug
debug
debug
debug
toggle
toggle
toggle
toggle
toggle
toggle
l e v e l ( CSP ERROR ) ;
l e v e l (CSP WARN) ;
l e v e l ( CSP BUFFER ) ;
l e v e l ( CSP PACKET ) ;
l e v e l (CSP PROTOCOL) ;
l e v e l ( CSP LOCK ) ;
}
server
# i f n d e f GUARD SERVER H
# define GUARD SERVER H
# include <s i g n a l a b l e t h r e a d . h>
# include <event . h>
# include <csp/csp . h>
# include <s t d i n t . h>
# include <s t r i n g >
c l a s s S e r v e r : public S i g n a l a b l e T h r e a d {
public :
S e r v e r ( Event& e v t ) : S i g n a l a b l e T h r e a d ( e v t ) {}
protected :
void Work ( ) ;
private :
c s p s o c k e t t ∗ i n i t S o c k e t ( ) const ;
void p r i n t S t r i n g ( c o n s t u i n t 8 t ∗ s t r ) c o n s t ;
void p r o c e s s R e q u e s t ( c s p c o n n t ∗conn , c s p p a c k e t t ∗
pack et ) c o n s t ;
char getRequestCode ( c s p p a c k e t t ∗ pack et ) c o n s t ;
s t a t i c s t d : : s t r i n g m help ;
};
# endif
# include
# include
# include
# include
# include
# include
# include
# include
# include
<s e r v e r . h>
<s c r e e n l o c k . h>
<common . h>
<iostream >
<event . h>
<csp/csp . h>
<s t d i n t . h>
<s t d d e f . h>
<s t d e x c e p t >
using namespace s t d ;
s t d : : s t r i n g S e r v e r : : m help = ”Help s t r i n g from s e r v e r ” ;
c s p s o c k e t t ∗ Server : : i n i t S o c k e t ( ) const {
s t a t i c s i z e t backlog = 1 0 ;
s t a t i c u i n t 3 2 t options = 0 ;
c s p s o c k e t t ∗ socket = csp socket ( options ) ;
c s p b i n d ( s o c k e t , CSP ANY) ;
c s p l i s t e n ( s o c k e t , backlog ) ;
return socket ;
}
void S e r v e r : : p r i n t S t r i n g ( c o n s t u i n t 8 t ∗ d a t a p t r ) c o n s t {
c o n s t char ∗ s t r = ( c o n s t char ∗ ) d a t a p t r ;
P r i n t ( ”Message from c l i e n t : ” << s t r ) ;
}
void S e r v e r : : p r o c e s s R e q u e s t ( c s p c o n n t ∗conn , c s p p a c k e t t ∗
pack et ) c o n s t {
c o n s t char code = getRequestCode ( pa cket ) ;
i f ( code == ’ h ’ )
P r i n t ( m help ) ;
}
char S e r v e r : : getRequestCode ( c s p p a c k e t t ∗ pack et ) c o n s t {
i f ( packet −>l e n g t h < 1 ) {
throw r u n t i m e e r r o r ( ” Request pack et was empty ! ” ) ;
}
char code = ( char ) packet −>data [ 0 ] ;
r e t u r n code ;
}
void S e r v e r : : Work ( ) {
csp socket t ∗ socket = initSocket ( ) ;
m signal −>S i g n a l ( ) ;
csp conn t ∗ connection ;
c s p p a c k e t t ∗ pack et ;
Print ( ” Server l i s t e n i n g ” ) ;
while ( t r u e ) {
c o n n e c t i o n = c s p a c c e p t ( s o c k e t , CSP MAX DELAY) ;
i f ( c o n n e c t i o n == NULL) continue ; / / T i m e o u t
while ( ( packet = c s p r e a d ( connection , 1 0 0 1 ) ) ! = NULL )
{
switch ( c s p c o n n d p o r t ( c o n n e c t i o n ) ) {
c a s e PAYLOAD PORT :
p r i n t S t r i n g ( packet −>data ) ;
break ;
c a s e CONTROL PORT :
p r o c e s s R e q u e s t ( connection , pac ket ) ;
break ;
default :
c s p s e r v i c e h a n d l e r ( connection , pa cket ) ;
break ;
}
c s p b u f f e r f r e e ( p acket ) ;
pack et = NULL;
csp close ( connection ) ;
}
}
}
client
# i f n d e f GUARD CLIENT H
# define GUARD CLIENT H
# include <s i g n a l a b l e t h r e a d . h>
# include <s t d i n t . h>
# include <common . h>
c l a s s C l i e n t : public S i g n a l a b l e T h r e a d {
public :
C l i e n t ( Event& e v t ) :
SignalableThread ( evt ) ,
m server addr (ADDRESS) ,
m timeout ( 6 0 0 0 0 0 ) {}
protected :
void Work ( ) ;
private :
void ping ( ) ;
void ps ( ) ;
void freemem ( ) ;
void f r e e b u f f e r s ( ) ;
void uptime ( ) ;
u i n t 8 t m server addr ;
unsigned i n t m timeout ;
};
# endif
# include
# include
# include
# include
<iostream >
< c l i e n t . h>
<mutex . h>
<s c r e e n l o c k . h>
# include
# include
# include
# include
# include
# include
<event . h>
<csp/csp . h>
<s t d e x c e p t >
<common . h>
<c s t r i n g >
<Windows . h>
using namespace s t d ;
void C l i e n t : : Work ( ) {
m signal −>Wait ( ) ;
P r i n t ( ” C l i e n t t r y i n g t o c on n ec t t o s e r v e r . . . ” ) ;
Sleep (1000)
ps ( ) ;
Sleep (1000)
freemem ( ) ;
Sleep (1000)
freebuffers
Sleep (1000)
uptime ( ) ;
Sleep (1000)
;
;
;
() ;
;
;
c o n s t char ∗ message = ” Hello world ! ” ;
c s p p a c k e t t ∗ pack et = ( c s p p a c k e t t ∗ ) c s p b u f f e r g e t (
s i z e o f ( c s p p a c k e t t ) + s t r l e n ( message ) + 1 ) ;
i f ( packet == NULL) {
throw r u n t i m e e r r o r ( ” F a i l e d t o a l l o c a t e memory f o r
pack et ! ” ) ;
}
c s p c o n n t ∗ c o n n e c t i o n = c s p c o n n e c t ( CSP PRIO NORM , ADDRESS
, PAYLOAD PORT, 1 0 0 0 , CSP O NONE) ;
i f ( c o n n e c t i o n == NULL) {
c s p b u f f e r f r e e ( p acket ) ;
throw r u n t i m e e r r o r ( ” Connection f a i l e d ! ” ) ;
}
s t r c p y ( ( char ∗ ) packet −>data , message ) ;
i f ( ! csp send ( connection , packet , 1 0 0 0 ) ) {
c s p b u f f e r f r e e ( p acket ) ;
throw r u n t i m e e r r o r ( ”Send f a i l e d ! ” ) ;
}
csp close ( connection ) ;
}
void C l i e n t : : ping ( ) {
i n t p i n g R e s u l t = c s p p i n g ( m server addr , m timeout , 1 0 0 ,
CSP O NONE) ;
P r i n t ( ” Ping r e s u l t : ” << p i n g R e s u l t ) ;
}
void C l i e n t : : ps ( ) {
c s p p s ( m server addr , m timeout ) ;
}
void C l i e n t : : freemem ( ) {
csp memfree ( m server addr , m timeout ) ;
}
void C l i e n t : : f r e e b u f f e r s ( ) {
c s p b u f f r e e ( m server addr , m timeout ) ;
}
void C l i e n t : : uptime ( ) {
csp uptime ( m server addr , m timeout ) ;
}
A.4
Cubesat space protocol, KISS test
Introduction
This section contains the source code for the test of the KISS functionality in CSP.
The code was compiled with:
./waf distclean configure --prefix=../csp_deploy --enable-if-kiss \
--with-driver-usart=windows --with-os=windows --enable-examples build insta
csp malloc.c
Listing A.1: src/arch/windows/csp malloc.c
# include ” . . / c s p m a l l o c . h”
# include <s t d l i b . h>
void ∗ c s p m a l l o c ( s i z e t s i z e ) {
r e t u r n malloc ( s i z e ) ;
}
void c s p f r e e ( void ∗ p t r ) {
free ( ptr ) ;
}
csp queue.c
Listing A.2: src/arch/windows/csp queue.c
# include
# include
# include
# include
<s t d i n t . h>
<csp/csp . h>
” . . / csp queue . h”
”windows queue . h”
c s p q u e u e h a n d l e t c s p q u e u e c r e a t e ( i n t length , s i z e t
item size ) {
r e t u r n windows queue create ( length , i t e m s i z e ) ;
}
void csp queue remove ( c s p q u e u e h a n d l e t queue ) {
windows queue delete ( queue ) ;
}
i n t csp queue enqueue ( c s p q u e u e h a n d l e t handle , void ∗ value ,
u i n t 3 2 t timeout ) {
r e t u r n windows queue enqueue ( handle , value , timeout ) ;
}
i n t c s p q u e u e e n q u e u e i s r ( c s p q u e u e h a n d l e t handle , void ∗
value , CSP BASE TYPE ∗ task woken ) {
i f ( task woken ! = NULL )
∗ task woken = 0 ;
r e t u r n windows queue enqueue ( handle , value , 0 ) ;
}
i n t csp queue dequeue ( c s p q u e u e h a n d l e t handle , void ∗ buf ,
u i n t 3 2 t timeout ) {
r e t u r n windows queue dequeue ( handle , buf , timeout ) ;
}
i n t c s p q u e u e d e q u e u e i s r ( c s p q u e u e h a n d l e t handle , void ∗ buf
, CSP BASE TYPE ∗ task woken ) {
i f ( task woken ! = NULL )
∗ task woken = 0 ;
r e t u r n windows queue dequeue ( handle , buf , 0 ) ;
}
i n t c s p q u e u e s i z e ( c s p q u e u e h a n d l e t handle ) {
r e t u r n windows queue items ( handle ) ;
}
i n t c s p q u e u e s i z e i s r ( c s p q u e u e h a n d l e t handle ) {
r e t u r n windows queue items ( handle ) ;
}
csp semaphore.c
Listing A.3: src/arch/windows/csp semaphore.c
# include <Windows . h>
# include <csp/csp . h>
# include ” . . / csp semaphore . h”
i n t c s p m u t e x c r e a t e ( c s p m u t e x t ∗ mutex ) {
HANDLE mutexHandle = CreateMutex (NULL, FALSE , FALSE ) ;
i f ( mutexHandle == NULL ) {
r e t u r n CSP MUTEX ERROR ;
}
∗mutex = mutexHandle ;
r e t u r n CSP MUTEX OK ;
}
i n t csp mutex remove ( c s p m u t e x t ∗ mutex ) {
i f ( ! CloseHandle ( ∗ mutex ) ) {
r e t u r n CSP MUTEX ERROR ;
}
r e t u r n CSP MUTEX OK ;
}
i n t c s p m u t e x l o c k ( c s p m u t e x t ∗ mutex , u i n t 3 2 t timeout ) {
i f ( W a i t F o r S i n g l e O b j e c t ( ∗ mutex , timeout ) == WAIT OBJECT 0 ) {
r e t u r n CSP MUTEX OK ;
}
r e t u r n CSP MUTEX ERROR ;
}
i n t csp mutex unlock ( c s p m u t e x t ∗ mutex ) {
i f ( ! ReleaseMutex ( ∗ mutex ) ) {
r e t u r n CSP MUTEX ERROR ;
}
r e t u r n CSP MUTEX OK ;
}
i n t c s p b i n s e m c r e a t e ( c s p b i n s e m h a n d l e t ∗ sem ) {
HANDLE semHandle = CreateSemaphore (NULL, 1 , 1 , NULL) ;
i f ( semHandle == NULL ) {
r e t u r n CSP SEMAPHORE ERROR ;
}
∗sem = semHandle ;
r e t u r n CSP SEMAPHORE OK ;
}
i n t csp bin sem remove ( c s p b i n s e m h a n d l e t ∗ sem ) {
i f ( ! CloseHandle ( ∗ sem ) ) {
r e t u r n CSP SEMAPHORE ERROR ;
}
r e t u r n CSP SEMAPHORE OK ;
}
i n t c s p b i n s e m w a i t ( c s p b i n s e m h a n d l e t ∗ sem , u i n t 3 2 t
timeout ) {
i f ( W a i t F o r S i n g l e O b j e c t ( ∗ sem , timeout ) == WAIT OBJECT 0 ) {
r e t u r n CSP SEMAPHORE OK ;
}
r e t u r n CSP SEMAPHORE ERROR ;
}
i n t c s p b i n s e m p o s t ( c s p b i n s e m h a n d l e t ∗ sem ) {
i f ( ! ReleaseSemaphore ( ∗ sem , 1 , NULL) ) {
r e t u r n CSP SEMAPHORE ERROR ;
}
r e t u r n CSP SEMAPHORE OK ;
}
i n t c s p b i n s e m p o s t i s r ( c s p b i n s e m h a n d l e t ∗ sem ,
CSP BASE TYPE ∗ task woken ) {
i f ( task woken ! = NULL ) {
∗ task woken = 0 ;
}
r e t u r n c s p b i n s e m p o s t ( sem ) ;
}
csp system.c
This code was moved from its original location in src/csp service handler.c.
Listing A.4: src/arch/windows/csp system.c
/∗
C u b e s a t S p a c e P r o t o c o l − A s m a l l n e t w o r k −l a y e r p r o t o c o l
designed f o r Cubesats
C o p y r i g h t ( C ) 2011 Gomspace ApS ( h t t p : / / www. g o m s p a c e . com )
C o p y r i g h t ( C ) 2011 AAUSAT3 P r o j e c t ( h t t p : / / a a u s a t 3 . s p a c e . aau . dk
)
T h i s l i b r a r y i s f r e e s o f t w a r e ; you can r e d i s t r i b u t e i t and / o r
m o d i f y i t u n d e r t h e t e r m s o f t h e GNU L e s s e r G e n e r a l P u b l i c
L i c e n s e a s p u b l i s h e d by t h e F r e e S o f t w a r e F o u n d a t i o n ; e i t h e r
v e r s i o n 2 . 1 o f t h e L i c e n s e , o r ( a t y o u r o p t i o n ) any l a t e r
version .
This l i b r a r y i s d i s t r i b u t e d in the hope t h a t i t w i l l be useful ,
b u t WITHOUT ANY WARRANTY; w i t h o u t e v e n t h e i m p l i e d w a r r a n t y o f
MERCHANTABILITY o r FITNESS FOR A PARTICULAR PURPOSE . S e e t h e
GNU
L e s s e r G e n e r a l P u b l i c L i c e n s e f o r more d e t a i l s .
You s h o u l d h a v e r e c e i v e d a c o p y o f t h e GNU L e s s e r G e n e r a l
Public
L i c e n s e a l o n g w i t h t h i s l i b r a r y ; i f not , w r i t e t o t h e F r e e
Software
F o u n d a t i o n , I n c . , 51 F r a n k l i n S t r e e t , F i f t h F l o o r , B o s t o n , MA
02110 − 1301 USA
∗/
# include <s t d i n t . h>
# include <s t r i n g . h>
# include <Windows . h>
# include <csp/csp . h>
# include <csp/ c s p e r r o r . h>
# include ” . . / csp system . h”
i n t c s p s y s t a s k l i s t ( char ∗ out ) {
s t r c p y ( out , ” T a s k l i s t not a v a i l a b l e on Windows” ) ;
r e t u r n CSP ERR NONE ;
}
u i n t 3 2 t csp sys memfree ( void ) {
MEMORYSTATUSEX s t a t e x ;
s t a t e x . dwLength = s i z e o f ( s t a t e x ) ;
GlobalMemoryStatusEx(& s t a t e x ) ;
DWORDLONG freePhysicalMem = s t a t e x . u l l A v a i l P h y s ;
s i z e t t o t a l = ( s i z e t ) freePhysicalMem ;
return ( u i n t 3 2 t ) t o t a l ;
}
i n t c s p s y s r e b o o t ( void ) {
/ ∗ TODO: F i x r e b o o t on Windows ∗ /
c s p l o g e r r o r ( ” F a i l e d t o r e b o o t \ r \n” ) ;
r e t u r n CSP ERR INVAL ;
}
void c s p s y s s e t c o l o r ( c s p c o l o r t c o l o r ) {
/ ∗ TODO: Add Windows c o l o r o u t p u t h e r e ∗ /
}
csp time.c
Listing A.5: src/arch/windows/csp time.c
# include <Windows . h>
# include <s t d i n t . h>
# include ” . . / c s p t i m e . h”
u i n t 3 2 t c s p g e t m s ( void ) {
r e t u r n ( u i n t 3 2 t ) GetTickCount ( ) ;
}
u i n t 3 2 t c s p g e t m s i s r ( void ) {
return csp get ms ( ) ;
}
u i n t 3 2 t c s p g e t s ( void ) {
u i n t 3 2 t time ms = c s p g e t m s ( ) ;
r e t u r n time ms / 1 0 0 0 ;
}
u i n t 3 2 t c s p g e t s i s r ( void ) {
return c s p g e t s ( ) ;
}
windows glue.h
This files contains definintions for condition variables. Without this
”glue-header”, it would not be possible to build libcsp under the current
version of MinGW.
Listing A.6: src/arch/windows/windows glue.h
# i f n d e f WINDOWS GLUE H
# define WINDOWS GLUE H
# include <Windows . h>
#undef i n t e r f a c e
# i f ( WIN32 WINNT >= 0 x0600 )
# define RTL CONDITION VARIABLE INIT 0
# define RTL CONDITION VARIABLE LOCKMODE SHARED 1
# define CONDITION VARIABLE INIT RTL CONDITION VARIABLE INIT
# define CONDITION VARIABLE LOCKMODE SHARED
RTL CONDITION VARIABLE LOCKMODE SHARED
typedef PVOID RTL CONDITION VARIABLE ;
typedef RTL CONDITION VARIABLE CONDITION VARIABLE , ∗
PCONDITION VARIABLE ;
WINBASEAPI VOID WINAPI I n i t i a l i z e C o n d i t i o n V a r i a b l e (
PCONDITION VARIABLE C o n d i t i o n V a r i a b l e ) ;
WINBASEAPI WINBOOL WINAPI S l e e p C o n d i t i o n V a r i a b l e C S (
PCONDITION VARIABLE C o n d i t i o n V a r i a b l e , PCRITICAL SECTION
C r i t i c a l S e c t i o n , DWORD dwMilliseconds ) ;
WINBASEAPI VOID WINAPI WakeAllConditionVariable (
PCONDITION VARIABLE C o n d i t i o n V a r i a b l e ) ;
WINBASEAPI VOID WINAPI WakeConditionVariable (
PCONDITION VARIABLE C o n d i t i o n V a r i a b l e ) ;
# endif / /
# endif
WIN#” WINNT
windows queue
Listing A.7: src/arch/windows/windows queue.h
# i f n d e f WINDOWS QUEUE H
# define WINDOWS QUEUE H
# ifdef
cplusplus
e x t e r n ”C” {
# endif
# include <Windows . h>
# include ” windows glue . h”
#undef i n t e r f a c e
# include ” . . / csp queue . h”
# define
# define
# define
# define
WINDOWS QUEUE ERROR CSP QUEUE ERROR
WINDOWS QUEUE EMPTY CSP QUEUE ERROR
WINDOWS QUEUE FULL CSP QUEUE ERROR
WINDOWS QUEUE OK CSP QUEUE OK
typedef s t r u c t windows queue s {
void ∗ b u f f e r ;
int size ;
int item size ;
i n t i te ms ;
i n t head idx ;
CRITICAL SECTION mutex ;
CONDITION VARIABLE c o n d f u l l ;
CONDITION VARIABLE cond empty ;
} windows queue t ;
windows queue t ∗ windows queue create ( i n t length , s i z e t
item size ) ;
void windows queue delete ( windows queue t ∗ q ) ;
i n t windows queue enqueue ( windows queue t ∗ queue , void ∗ value
, i n t timeout ) ;
i n t windows queue dequeue ( windows queue t ∗ queue , void ∗ buf ,
i n t timeout ) ;
i n t windows queue items ( windows queue t ∗ queue ) ;
# ifdef
cplusplus
} / ∗ e x t e r n ”C” ∗ /
# endif
# endif / /
WINDOWS QUEUE H
Listing A.8: src/arch/windows/windows queue.c
# include ”windows queue . h”
# include ” windows glue . h”
# include <Windows . h>
s t a t i c i n t queueFull ( windows queue t ∗ queue ) {
r e t u r n queue−>i te ms == queue−>s i z e ;
}
s t a t i c i n t queueEmpty ( windows queue t ∗ queue ) {
r e t u r n queue−>i te ms == 0 ;
}
windows queue t ∗ windows queue create ( i n t length , s i z e t
item size ) {
windows queue t ∗queue = ( windows queue t ∗ ) malloc (
s i z e o f ( windows queue t ) ) ;
i f ( queue == NULL)
goto q u e u e m a l l o c f a i l e d ;
queue−>b u f f e r = malloc ( l e n g t h ∗ i t e m s i z e ) ;
i f ( queue−>b u f f e r == NULL)
goto b u f f e r m a l l o c f a i l e d ;
queue−>s i z e = l e n g t h ;
queue−>i t e m s i z e = i t e m s i z e ;
queue−>i te ms = 0 ;
queue−>head idx = 0 ;
I n i t i a l i z e C r i t i c a l S e c t i o n (&( queue−>mutex ) ) ;
I n i t i a l i z e C o n d i t i o n V a r i a b l e (&( queue−>c o n d f u l l ) ) ;
I n i t i a l i z e C o n d i t i o n V a r i a b l e (&( queue−>cond empty ) ) ;
goto q u e u e i n i t s u c c e s s ;
buffer malloc failed :
f r e e ( queue ) ;
queue = NULL;
queue malloc failed :
queue init success :
r e t u r n queue ;
}
void windows queue delete ( windows queue t ∗ q ) {
i f ( q==NULL) r e t u r n ;
D e l e t e C r i t i c a l S e c t i o n (&( q−>mutex ) ) ;
f r e e ( q−>b u f f e r ) ;
free (q) ;
}
i n t windows queue enqueue ( windows queue t ∗ queue , void ∗ value
, i n t timeout ) {
int offset ;
E n t e r C r i t i c a l S e c t i o n (&( queue−>mutex ) ) ;
while ( queueFull ( queue ) ) {
i n t r e t = S l e e p C o n d i t i o n V a r i a b l e C S (&( queue−>
c o n d f u l l ) , &(queue−>mutex ) , timeout ) ;
if ( ! ret ) {
L e a v e C r i t i c a l S e c t i o n (&( queue−>mutex ) ) ;
r e t u r n r e t == WAIT TIMEOUT ?
WINDOWS QUEUE FULL :
WINDOWS QUEUE ERROR;
}
}
o f f s e t = ( ( queue−>head idx+queue−>i te ms ) % queue−>s i z e )
∗ queue−>i t e m s i z e ;
memcpy ( ( unsigned char ∗ ) queue−>b u f f e r + o f f s e t , value ,
queue−>i t e m s i z e ) ;
queue−>it e ms ++;
L e a v e C r i t i c a l S e c t i o n (&( queue−>mutex ) ) ;
WakeAllConditionVariable (&( queue−>cond empty ) ) ;
r e t u r n WINDOWS QUEUE OK;
}
i n t windows queue dequeue ( windows queue t ∗ queue , void ∗ buf ,
i n t timeout ) {
E n t e r C r i t i c a l S e c t i o n (&( queue−>mutex ) ) ;
while ( queueEmpty ( queue ) ) {
i n t r e t = S l e e p C o n d i t i o n V a r i a b l e C S (&( queue−>
cond empty ) , &(queue−>mutex ) , timeout ) ;
if ( ! ret ) {
L e a v e C r i t i c a l S e c t i o n (&( queue−>mutex ) ) ;
r e t u r n r e t == WAIT TIMEOUT ?
WINDOWS QUEUE EMPTY :
WINDOWS QUEUE ERROR;
}
}
memcpy( buf , ( unsigned char ∗ ) queue−>b u f f e r +( queue−>
head idx%queue−>s i z e ∗queue−>i t e m s i z e ) , queue−>
item size ) ;
queue−>items −−;
queue−>head idx = ( queue−>head idx + 1 ) % queue−>s i z e ;
L e a v e C r i t i c a l S e c t i o n (&( queue−>mutex ) ) ;
WakeAllConditionVariable (&( queue−>c o n d f u l l ) ) ;
r e t u r n WINDOWS QUEUE OK;
}
i n t windows queue items ( windows queue t ∗ queue ) {
i n t i te ms ;
E n t e r C r i t i c a l S e c t i o n (&( queue−>mutex ) ) ;
it e ms = queue−>it em s ;
L e a v e C r i t i c a l S e c t i o n (&( queue−>mutex ) ) ;
r e t u r n i te ms ;
}
usart windows
This file contains the USART driver for the windows port of CSP.
Listing A.9: src/drivers/usart/usart windows.c
# include <s t d i o . h>
# include <Windows . h>
# include <p r o c e s s . h>
# include <csp/csp . h>
# include <csp/ d r i v e r s / u s a r t . h>
static
static
static
static
static
HANDLE portHandle = INVALID HANDLE VALUE ;
HANDLE rxThread = INVALID HANDLE VALUE ;
CRITICAL SECTION t x S e c t i o n ;
LONG i s L i s t e n i n g = 0 ;
u s a r t c a l l b a c k t u s a r t c a l l b a c k = NULL;
s t a t i c void prvSendData ( char ∗ buf , i n t bufsz ) ;
s t a t i c i n t prvTryOpenPort ( c o n s t char ∗ i n t f ) ;
s t a t i c i n t prvTryConfigurePort ( c o n s t s t r u c t u s a r t c o n f ∗ ) ;
s t a t i c i n t prvTrySetPortTimeouts ( void ) ;
s t a t i c c o n s t char ∗ p r v P a r i t y T o S t r ( BYTE p a r i t y S e t t i n g ) ;
# i f d e f CSP DEBUG
s t a t i c void p r v P r i n t E r r o r ( void ) {
char ∗ messageBuffer = NULL;
DWORD errorCode = G e t L a s t E r r o r ( ) ;
DWORD formatMessageRet ;
formatMessageRet = FormatMessageA (
FORMAT MESSAGE ALLOCATE BUFFER |
FORMAT MESSAGE FROM SYSTEM,
NULL,
errorCode ,
MAKELANGID(LANG NEUTRAL, SUBLANG DEFAULT) ,
( char ∗ )&messageBuffer ,
0,
NULL) ;
i f ( ! formatMessageRet ) {
c s p l o g e r r o r ( ” FormatMessage e r r o r , code : %l u \n” ,
GetLastError ( ) ) ;
return ;
}
c s p l o g e r r o r ( ”%s \n” , messageBuffer ) ;
L o c a l F r e e ( messageBuffer ) ;
}
# endif
# i f d e f CSP DEBUG
# define p r i n t E r r o r ( ) p r v P r i n t E r r o r ( )
# else
# define p r i n t E r r o r ( ) do {} while ( 0 )
# endif
s t a t i c i n t prvTryOpenPort ( c o n s t char ∗ i n t f ) {
portHandle = C r e a t e F i l e A (
intf ,
GENERIC READ | GENERIC WRITE ,
0,
NULL,
OPEN EXISTING ,
0,
NULL) ;
i f ( portHandle == INVALID HANDLE VALUE ) {
DWORD errorCode = G e t L a s t E r r o r ( ) ;
i f ( errorCode == ERROR FILE NOT FOUND ) {
c s p l o g e r r o r ( ”Could not open s e r i a l port , because
i t didn ’ t e x i s t ! \ n” ) ;
}
else
c s p l o g e r r o r ( ” F a i l u r e opening s e r i a l p o r t ! Code : %
l u ” , errorCode ) ;
return 1 ;
}
return 0 ;
}
s t a t i c i n t prvTryConfigurePort ( c o n s t s t r u c t u s a r t c o n f ∗ conf )
{
DCB p o r t S e t t i n g s = { 0 } ;
p o r t S e t t i n g s . DCBlength = s i z e o f (DCB) ;
i f ( ! GetCommState ( portHandle , &p o r t S e t t i n g s ) ) {
c s p l o g e r r o r ( ”Could not g e t d e f a u l t s e t t i n g s f o r open
COM p o r t ! Code : %l u \n” , G e t L a s t E r r o r ( ) ) ;
r e t u r n − 1;
}
p o r t S e t t i n g s . BaudRate = conf −>baudrate ;
p o r t S e t t i n g s . P a r i t y = conf −>p a r i t y s e t t i n g ;
p o r t S e t t i n g s . S t o p B i t s = conf −>s t o p b i t s ;
p o r t S e t t i n g s . f P a r i t y = conf −>c h e c k p a r i t y ;
p o r t S e t t i n g s . f B i n a r y = TRUE ;
p o r t S e t t i n g s . B y t e S i z e = conf −>d a t a b i t s ;
i f ( ! SetCommState ( portHandle , &p o r t S e t t i n g s ) ) {
c s p l o g e r r o r ( ” E r r o r when s e t t i n g COM p o r t s e t t i n g s !
Code:% l u \n” , G e t L a s t E r r o r ( ) ) ;
return 1 ;
}
GetCommState ( portHandle , &p o r t S e t t i n g s ) ;
c s p l o g i n f o ( ” P o r t : %s , Baudrate : %lu , Data b i t s : %d , Stop
b i t s : %d , P a r i t y : %s \ r \n” ,
conf −>device , conf −>baudrate , conf −>d a t a b i t s , conf
−>s t o p b i t s , p r v P a r i t y T o S t r ( conf −>p a r i t y s e t t i n g ) )
;
return 0 ;
}
s t a t i c c o n s t char ∗ p r v P a r i t y T o S t r ( BYTE p a r i t y S e t t i n g ) {
s t a t i c c o n s t char ∗ p a r i t y S t r [ ] = {
”None” ,
”Odd” ,
”Even” ,
”N/A”
};
char c o n s t ∗ r e s u l t S t r = NULL;
switch ( p a r i t y S e t t i n g ) {
c a s e NOPARITY :
resultStr = parityStr
break ;
c a s e ODDPARITY :
resultStr = parityStr
break ;
c a s e EVENPARITY :
resultStr = parityStr
break ;
default :
resultStr = parityStr
};
return r e s u l t S t r ;
[0];
[1];
[2];
[3];
}
s t a t i c i n t prvTrySetPortTimeouts ( void ) {
COMMTIMEOUTS t i m e o u t s = { 0 } ;
i f ( ! GetCommTimeouts ( portHandle , &t i m e o u t s ) ) {
c s p l o g e r r o r ( ” E r r o r g e t t i n g s c u r r e n t timeout s e t t i n g s \
n” ) ;
return 1 ;
}
t i m e o u t s . ReadIntervalTimeout = 5 ;
timeouts . ReadTotalTimeoutMultiplier = 1 ;
t i m e o u t s . ReadTotalTimeoutConstant = 5 ;
timeouts . WriteTotalTimeoutMultiplier = 1 ;
t i m e o u t s . WriteTotalTimeoutConstant = 5 ;
i f ( ! SetCommTimeouts ( portHandle , &t i m e o u t s ) ) {
c s p l o g e r r o r ( ” Error s e t t i n g timeouts ! ” ) ;
return 1 ;
}
return 0 ;
}
unsigned WINAPI prvRxTask ( void ∗ params ) {
DWORD bytesRead ;
DWORD e v e n t S t a t u s ;
uint8 t recvBuffer [ 2 4 ] ;
SetCommMask ( portHandle , EV RXCHAR) ;
while ( i s L i s t e n i n g ) {
WaitCommEvent ( portHandle , &e v e n t S t a t u s , NULL) ;
i f ( ! ( e v e n t S t a t u s & EV RXCHAR) ) {
continue ;
}
i f ( ! R e a d F i l e ( portHandle , r e c v B u f f e r , 2 4 , &bytesRead ,
NULL) ) {
c s p l o g w a r n ( ” E r r o r r e c e i v i n g data ! Code : %l u \n” ,
GetLastError ( ) ) ;
continue ;
}
i f ( u s a r t c a l l b a c k ! = NULL )
u s a r t c a l l b a c k ( r e c v B u f f e r , ( s i z e t ) bytesRead , NULL)
;
}
return 0 ;
}
s t a t i c void prvSendData ( char ∗ buf , i n t bufsz ) {
DWORD b y t e s T o t a l = 0 ;
DWORD b y t e s A c t u a l ;
i f ( ! W r i t e F i l e ( portHandle , buf , bufsz −b y t e s T o t a l , &
b y t e s A c t u a l , NULL) ) {
c s p l o g e r r o r ( ”Could not w r i t e data . Code : %l u \n” ,
GetLastError ( ) ) ;
return ;
}
i f ( ! F l u s h F i l e B u f f e r s ( portHandle ) ) {
c s p l o g w a r n ( ”Could not f l u s h w r i t e b u f f e r . Code : %l u \n
” , GetLastError ( ) ) ;
}
}
void usart shutdown ( void ) {
I n t e r l o c k e d E x c h a n g e (& i s L i s t e n i n g , 0 ) ;
CloseHandle ( portHandle ) ;
portHandle = INVALID HANDLE VALUE ;
i f ( rxThread ! = INVALID HANDLE VALUE ) {
W a i t F o r S i n g l e O b j e c t ( rxThread , INFINITE ) ;
rxThread = INVALID HANDLE VALUE ;
}
D e l e t e C r i t i c a l S e c t i o n (& t x S e c t i o n ) ;
}
void u s a r t l i s t e n ( void ) {
I n t e r l o c k e d E x c h a n g e (& i s L i s t e n i n g , 1 ) ;
rxThread = (HANDLE) b e g i n t h r e a d e x (NULL, 0 , &prvRxTask , NULL
, 0 , NULL) ;
}
void u s a r t p u t s t r ( char ∗ buf , i n t bufsz ) {
E n t e r C r i t i c a l S e c t i o n (& t x S e c t i o n ) ;
prvSendData ( buf , bufsz ) ;
L e a v e C r i t i c a l S e c t i o n (& t x S e c t i o n ) ;
}
void u s a r t i n s e r t ( char c , void ∗pxTaskWoken ) {
/ ∗ r e d i r e c t debug o u t p u t t o s t d o u t ∗ /
p r i n t f ( ”%c ” , c ) ;
}
void u s a r t s e t c a l l b a c k ( u s a r t c a l l b a c k t c a l l b a c k ) {
usart callback = callback ;
}
void u s a r t i n i t ( s t r u c t u s a r t c o n f ∗ conf ) {
i f ( prvTryOpenPort ( conf −>d e v i c e ) ) {
printError ( ) ;
return ;
}
i f ( prvTryConfigurePort ( conf ) ) {
printError ( ) ;
return ;
}
i f ( prvTrySetPortTimeouts ( ) ) {
printError ( ) ;
return ;
}
I n i t i a l i z e C r i t i c a l S e c t i o n (& t x S e c t i o n ) ;
/∗ Start r e c e i v e r thread ∗/
usart listen () ;
}
A.5
XMEGA A1 Code
Introduction
This section contains the code for the XMEGA A1 Code.. This evaluation
kit was used as a ”character bouncer”, when testing and porting the
USART-driver and KISS-encapsulation and -decapsulation in CSP.
main
Listing A.10: xmega/main.c
/∗ ∗
∗ \file
∗
∗ \ b r i e f Empty u s e r a p p l i c a t i o n t e m p l a t e
∗
∗/
/∗
∗ I n c l u d e header f i l e s f o r a l l d r i v e r s t h a t have been imported
from
∗ AVR S o f t w a r e Framework ( ASF ) .
∗/
# include <a s f . h>
/ / Define th e Usart used in t a s k
# define USART USARTC0
# define USARTPORT PORTC
# define LEDPORT PORTE
# define SWITCHPORTL PORTD
# define SWITCHPORTLMASK 0 x3F
# define SWITCHPORTH PORTR
# define SWITCHPORTHMASK 0 x3
void SetupUsart ( void )
{
/ / P l a c e a j u m p e r t o c o n n e c t Pin3 and Pin2
/ / PD3 (TXD0) a s o u t p u t
USARTPORT . DIRSET
= PIN3 bm ; / / (TXD0) a s o u t p u t .
/ / PD2 (RXD0) a s i n p u t
USARTPORT . DIRCLR
= PIN2 bm ; / / (RXD0) a s i n p u t .
/ / USARTD0 ; 8 Data b i t s , No P a r i t y , 1 S t o p b i t
USART . CTRLC = ( u i n t 8 t ) USART CHSIZE 8BIT gc |
USART PMODE DISABLED gc | f a l s e ;
/ / E n a b l e b o t h TX on PORTC and RX on PORTD
USART . CTRLB | = USART TXEN bm | USART RXEN bm ;
/ / T a r g e t : I n t e r n a l RC 2MHz ( d e f a u l t ) , 9600 baud
USART .BAUDCTRLA = 1 2 ;
}
v o l a t i l e u i n t 8 t recvcounter = 0 ;
u i n t 8 t recvByte ( ) {
while ( (USART . STATUS & USART RXCIF bm ) == 0 ) ;
u i n t 8 t data = USART .DATA;
USART . STATUS | = USART RXCIF bm ;
r e t u r n data ;
}
void sendByte ( u i n t 8 t data ) {
while ( (USART . STATUS & USART DREIF bm ) == 0 ) ;
USART .DATA = data ;
}
void i n i t L e d s ( void ) ;
void i n i t B u t t o n s ( void ) ;
void updateLeds ( void ) ;
i n t main ( void )
{
board init () ;
initLeds ( ) ;
initButtons () ;
SetupUsart ( ) ;
PMIC . CTRL | = PMIC LOLVLEN bm ;
sei () ;
while ( 1 ) {
u i n t 8 t data = r e c v B y t e ( ) ;
cli () ;
recvcounter = ( recvcounter + 1) & 255;
updateLeds ( ) ;
sei () ;
sendByte ( data ) ;
}
}
void updateLeds ( void ) {
LEDPORT .OUT = r e c v c o u n t e r ;
}
void i n i t L e d s ( void ) {
LEDPORT . DIR = 0xFF ;
PORTCFG .MPCMASK = 0xFF ;
LEDPORT . PIN0CTRL | = PORT INVEN bm ;
LEDPORT .OUT = 0 x00 ;
}
ISR ( PORTD INT0 vect ) {
i f ( SWITCHPORTL . IN & PIN0 bm ) {
recvcounter = 0 ;
updateLeds ( ) ;
}
}
ISR ( PORTR INT0 vect ) {
}
void i n i t B u t t o n s ( void ) {
SWITCHPORTL . DIRCLR = SWITCHPORTLMASK;
PORTCFG .MPCMASK = SWITCHPORTLMASK;
SWITCHPORTL . PIN0CTRL | = (SWITCHPORTL . PIN0CTRL & ˜ (
PORT OPC gm | PORT ISC gm ) ) | PORT INVEN bm |
PORT OPC PULLUP gc | PORT ISC RISING gc ;
SWITCHPORTL . INT0MASK | = SWITCHPORTLMASK;
SWITCHPORTL . INTCTRL = (SWITCHPORTL . INTCTRL & ˜
PORT INT0LVL gm ) | PORT INT0LVL LO gc ;
SWITCHPORTH. DIRCLR = SWITCHPORTHMASK;
PORTCFG .MPCMASK = SWITCHPORTHMASK;
SWITCHPORTH. PIN0CTRL = (SWITCHPORTH. PIN0CTRL & ˜ (
PORT OPC gm | PORT ISC gm ) ) | PORT INVEN bm |
PORT OPC PULLUP gc | PORT ISC RISING gc ;
SWITCHPORTH. INT0MASK | = SWITCHPORTHMASK;
SWITCHPORTH. INTCTRL = (SWITCHPORTH. INTCTRL & ˜
PORT INT0LVL gm ) | PORT INT0LVL LO gc ;
}
A.6
OBC Code
Introduction
This section contains the OBC code. The FreeRTOS port is taken from
an example project for an evaluation board that uses the same microcontroller as the OBC and the radio.
The example project provided a USB stack, implemented both for
a host and a device. The source code was modified so that it would
work in device mode only, and the USB CDC task was changed into
something appropriate for the OBC.
In addition to that, a couple of small I/O-functions were added. They
handle writing output to USB.
The list of changed file should be (more or less):
• src/main.c
• src/device cdc task.c
• src/config/conf board.h
• src/config/conf io.h
• src/config/FreeRTOSConfig.h
• src/lib/*
• Compiled CSP was put in src/thirdparty/libcsp
• src/common/boards/*
In this section, we only list the most relevant parts. Consult the
enclosed source code for the full listings.
main
This file contains the definitions for the CSP server and client. The code
for this is basically a verbatim copy of the loopback example bundlet
with the CSP library.. This is the code in the clientTask and serverTask
functions.
Listing A.11: src/main.c
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
<s t d i o . h>
<u n i s t d . h>
” compiler . h”
” board . h”
” i n t c . h”
” p o w e r c l o c k s l i b . h”
”main . h”
”FreeRTOS . h”
” t a s k . h”
”semphr . h”
” c o n f b o a r d . h”
” c o n f u s b . h”
” u s b t a s k . h”
” d e v i c e c d c t a s k . h”
<i o / i o . h>
<csp/csp . h>
# define MY ADDRESS 1
# define MY PORT 10
# define USE CSP 1
pcl freq param t pcl freq param =
{
. cpu f
. pba f
. osc0 f
. osc0 startup
=
=
=
=
APPLI CPU SPEED ,
APPLI PBA SPEED ,
FOSC0 ,
OSC0 STARTUP
};
s t a t i c xSemaphoreHandle prvScreenMutex ;
s t a t i c void p r i n t T a s k ( void ∗ pvParameters ) ;
s t a t i c void readTask ( void ∗ pvParameters ) ;
s t a t i c void diagTask ( void ∗ pvParameters ) ;
# i f d e f USE CSP
s t a t i c void p r v S t a r t C s p ( void ) ;
void s e r v e r T a s k ( void ∗ pvParams ) ;
void c l i e n t T a s k ( void ∗ pvParams ) ;
# endif
void p r i n t D i a g ( char cmd) ;
/ ∗ ! \ b r i e f Main f u n c t i o n . E x e c u t i o n s t a r t s h e r e .
∗
∗ \ r e t v a l 42 F a t a l e r r o r .
∗/
i n t main ( void )
{
prvScreenMutex = xSemaphoreCreateMutex ( ) ;
xTaskCreate (& p r i n t T a s k , ( c o n s t signed portCHAR ∗ ) ” P r i n t
t a s k ” , 1 2 8 , NULL, tskIDLE PRIORITY , NULL) ;
xTaskCreate (& diagTask , ( c o n s t signed portCHAR ∗ ) ” Diag
t a s k ” , configMINIMAL STACK SIZE +128 , NULL,
tskIDLE PRIORITY , NULL) ;
/ / Configure system c l o c k s .
i f ( p c l c o n f i g u r e c l o c k s (& p c l f r e q p a r a m ) ! = PASS )
return 42;
/ / I n i t i a l i z e USB c l o c k .
pcl configure usb clock () ;
/ / I n i t i a l i z e USB t a s k
usb task init () ;
io init () ;
/ / I n i t i a l i z e d e v i c e CDC USB t a s k
device cdc task init () ;
# i f d e f USE CSP
prvStartCsp ( ) ;
# endif
/ / S t a r t OS s c h e d u l e r
vTaskStartScheduler ( ) ;
portDBG TRACE ( ”FreeRTOS r e t u r n e d . ” ) ;
return 42;
}
void diagTask ( void ∗ pvParameters ) {
i n t in p ut ;
portTickType xLastWakeTime ;
xLastWakeTime = xTaskGetTickCount ( ) ;
while ( 1 ) {
i np ut = g e t c h a r ( ) ;
xSemaphoreTake ( prvScreenMutex , portMAX DELAY ) ;
p r i n t f ( ”Got %c \n” , in pu t ) ;
xSemaphoreGive ( prvScreenMutex ) ;
vTaskDelayUntil (&xLastWakeTime , 5 0 0 ) ;
}
while ( 1 ) {
i np ut = g e t c h a r ( ) ;
i f ( i np ut ! = ’ d ’ ) {
p r i n t f ( ”Got %c \n” , i n pu t ) ;
continue ;
}
xSemaphoreTake ( prvScreenMutex , portMAX DELAY ) ;
p r i n t D i a g ( i np ut ) ;
xSemaphoreGive ( prvScreenMutex ) ;
}
}
void p r i n t D i a g ( char cmd) {
extern u i n t 8 t
executable start ;
unsigned portBASE TYPE tasksCount =
uxTaskGetNumberOfTasks ( ) ;
signed char ∗ b u f f e r = NULL; / / p v P o r t M a l l o c ( t a s k s C o u n t ∗
(40+10) ) ;
p r i n t f ( ”\ n E x e c u t a b l e data s t a r t s a t %p\n” , &
executable start ) ;
p r i n t f ( ”Number o f t a s k s i s %l u \n” , tasksCount ) ;
i f ( b u f f e r ! = NULL ) {
vTaskList ( buffer ) ;
p r i n t f ( ”%s \n” , b u f f e r ) ;
vPortFree ( buffer ) ;
}
}
# i f d e f USE CSP
void p r v S t a r t C s p ( void ) {
c s p b u f f e r i n i t (2 , 300) ;
/ ∗ I n i t CSP w i t h a d d r e s s MY ADDRESS ∗ /
c s p i n i t (MY ADDRESS) ;
/ ∗ S t a r t r o u t e r t a s k w i t h 500 word s t a c k , OS t a s k
p r i o r i t y 1 ∗/
c s p r o u t e s t a r t t a s k ( 5 0 0 , tskIDLE PRIORITY ) ;
//
xTaskCreate (& serverTask , ( c o n s t signed portCHAR ∗ ) ”
S e r v e r t a s k ” , 2 5 6 , NULL, tskIDLE PRIORITY , NULL) ;
xSemaphoreTake ( prvScreenMutex , portMAX DELAY ) ;
p r i n t f ( ” Created s e r v e r t a s k ! \ n” ) ;
xSemaphoreGive ( prvScreenMutex ) ;
xTaskCreate (& c l i e n t T a s k , ( c o n s t signed portCHAR ∗ ) ”
C l i e n t t a s k ” , 4 0 9 6 , NULL, tskIDLE PRIORITY , NULL) ;
}
void s e r v e r T a s k ( void ∗ pvParams ) {
/ ∗ C r e a t e s o c k e t w i t h o u t any s o c k e t o p t i o n s ∗ /
c s p s o c k e t t ∗ sock = c s p s o c k e t ( CSP SO NONE ) ;
/ ∗ Bind a l l p o r t s t o s o c k e t ∗ /
c s p b i n d ( sock , CSP ANY) ;
/ ∗ C r e a t e 10 c o n n e c t i o n s b a c k l o g q u e u e ∗ /
c s p l i s t e n ( sock , 1 0 ) ;
/ ∗ P o i n t e r t o c u r r e n t c o n n e c t i o n and p a c k e t ∗ /
c s p c o n n t ∗conn ;
c s p p a c k e t t ∗ pack et ;
/∗ P r o c e s s incoming c o n n e c t i o n s ∗/
while ( 1 ) {
/ ∗ Wait f o r c o n n e c t i o n , 10000 ms t i m e o u t ∗ /
i f ( ( conn = c s p a c c e p t ( sock , 1 0 0 0 0 ) ) == NULL) {
p r i n t f ( ” Timeout ! ” ) ;
continue ;
}
/ ∗ Read p a c k e t s . Timout i s 100 ms ∗ /
while ( ( pac ket = c s p r e a d ( conn , 1 0 0 ) ) ! = NULL)
{
switch ( c s p c o n n d p o r t ( conn ) ) {
c a s e MY PORT :
/∗ Process packet here ∗/
p r i n t f ( ” Packet r e c e i v e d on MY PORT : %s \ r \n” , (
char ∗ ) packet −>data ) ;
c s p b u f f e r f r e e ( p acket ) ;
default :
/∗ Let the s e r v i c e handler
r e p l y p i n g s , b u f f e r use , e t c
. ∗/
c s p s e r v i c e h a n d l e r ( conn ,
pack et ) ;
break ;
}
}
/ ∗ C l o s e c u r r e n t c o n n e c t i o n , and h a n d l e n e x t ∗ /
c s p c l o s e ( conn ) ;
}
}
void c l i e n t T a s k ( void ∗ pvParams ) {
c s p p a c k e t t ∗ pack et ;
c s p c o n n t ∗ conn ;
while ( 1 ) {
/∗ ∗
∗ Try p i n g
∗/
i n t r e s u l t = c s p p i n g (MY ADDRESS, 1 0 0 , 1 0 0 ,
CSP O NONE) ;
p r i n t f ( ” Ping r e s u l t %d [ms] \ r \n” , r e s u l t ) ;
/∗ ∗
∗ Try d a t a p a c k e t t o s e r v e r
∗/
/ ∗ Get p a c k e t b u f f e r f o r d a t a ∗ /
pack et = c s p b u f f e r g e t ( 1 0 0 ) ;
i f ( packet == NULL) {
/ ∗ Could n o t g e t b u f f e r e l e m e n t ∗ /
p r i n t f ( ” F a i l e d t o g e t b u f f e r element \n” ) ;
return ;
}
/ ∗ C o n n e c t t o h o s t HOST, p o r t PORT w i t h r e g u l a r
UDP− l i k e p r o t o c o l and 1000 ms t i m e o u t ∗ /
conn = c s p c o n n e c t ( CSP PRIO NORM , MY ADDRESS,
MY PORT, 1 0 0 0 , CSP O NONE) ;
i f ( conn == NULL) {
/∗ Connect f a i l e d ∗/
p r i n t f ( ” Connection f a i l e d \n” ) ;
/ ∗ Remember t o f r e e p a c k e t b u f f e r ∗ /
c s p b u f f e r f r e e ( p acket ) ;
return ;
}
/ ∗ Copy dummy d a t a t o p a c k e t ∗ /
char ∗msg = ” Hello World” ;
s t r c p y ( ( char ∗ ) packet −>data , msg ) ;
/∗ Set packet length ∗/
packet −>l e n g t h = s t r l e n ( msg ) ;
/ ∗ Send p a c k e t ∗ /
i f ( ! csp send ( conn , packet , 1 0 0 0 ) ) {
/ ∗ Send f a i l e d ∗ /
p r i n t f ( ”Send f a i l e d \n” ) ;
c s p b u f f e r f r e e ( p acket ) ;
}
/∗ Close connection ∗/
c s p c l o s e ( conn ) ;
}
}
# endif
void p r i n t T a s k ( void ∗ pvParameters ) {
portTickType xLastWakeTime ;
xLastWakeTime = xTaskGetTickCount ( ) ;
int counter = 0 ;
while ( 1 ) {
xSemaphoreTake ( prvScreenMutex , portMAX DELAY ) ;
p r i n t f ( ” Hello , world ! %d\ r \n” , c o u n t e r ++) ;
xSemaphoreGive ( prvScreenMutex ) ;
vTaskDelayUntil (&xLastWakeTime , 1 0 0 0 0 ) ;
}
}
void readTask ( void ∗ pvParameters ) {
portTickType xLastWakeTime ;
xLastWakeTime = xTaskGetTickCount ( ) ;
while ( 1 ) {
xSemaphoreTake ( prvScreenMutex , portMAX DELAY ) ;
p r i n t f ( ” Hello , o t h e r world ! \ r \n” ) ;
xSemaphoreGive ( prvScreenMutex ) ;
vTaskDelayUntil (&xLastWakeTime , 9 0 0 ) ;
}
}
device cdc task
This file contains a FreeRTOS task. This task handles input and output
specific to the USB CDC device class (but not the actual USB request
handling). This snippet contains an ugly hack that basically waits until
ten seconds have passed before consuming data from the output buffer.
This makes it possible for the host computer to connect to the OBC and
still be able to read the first messages that was printed.
Listing A.12: src/device cdcs task.c
# include
# include
# include
# include
# include
# include
# include
”FreeRTOS . h”
” c o n f u s b . h”
” u s b s t a n d a r d r e q u e s t . h”
” d e v i c e c d c t a s k . h”
” u a r t u s b l i b . h”
” t a s k . h”
<i o / i o . h>
static volatile uint16 t
sof cnt ;
s t a t i c void prvFlushData ( void ) ;
s t a t i c void prvReadInput ( void ) ;
s t a t i c void prvWriteOutput ( void ) ;
void d e v i c e c d c t a s k i n i t ( )
{
sof cnt = 0 ;
uart usb init () ;
xTaskCreate ( d e v i c e c d c t a s k ,
configTSK USB DCDC NAME ,
configTSK USB DCDC STACK SIZE ,
NULL,
configTSK USB DCDC PRIORITY ,
NULL) ;
}
s t a t i c portTickType t i c k s S i n c e E n u m e r a t e d = 0 ;
void d e v i c e c d c t a s k ( void ∗ pvParameters )
{
portTickType xLastWakeTime ;
xLastWakeTime = xTaskGetTickCount ( ) ;
while ( t r u e )
{
vTaskDelayUntil (&xLastWakeTime , configTSK USB DCDC PERIOD ) ;
i f ( ! I s d e v i c e e n u m e r a t e d ( ) ) continue ;
i f ( t i c k s S i n c e E n u m e r a t e d == 0 ) {
t i c k s S i n c e E n u m e r a t e d = xTaskGetTickCount ( ) ;
} else {
portTickType d i f f = xTaskGetTickCount ( ) −
ticksSinceEnumerated ;
i f ( ( d i f f /portTICK RATE MS ) > 10000 ) {
prvFlushData ( ) ;
prvWriteOutput ( ) ;
prvReadInput ( ) ;
}
}
}
}
s t a t i c void prvFlushData ( void ) {
i f ( s o f c n t >=NB MS BEFORE FLUSH )
Timeout
{
s o f c n t =0;
uart usb flush ( ) ;
}
}
s t a t i c void prvWriteOutput ( void ) {
s t a t i c portCHAR queueValue ;
i f ( writeQueueHandle == NULL) {
/ / Flush b u f f e r in
return ;
}
while ( xQueueReceive ( writeQueueHandle , &queueValue , (
portTickType ) 0 ) == pdTRUE )
{
u a r t u s b p u t c h a r ( queueValue ) ;
}
}
s t a t i c void prvReadInput ( void ) {
static uint8 t c ;
i f ( readQueueHandle == NULL ) {
return ;
}
if ( uart usb test hit () )
r e c e i v e d f r o m t h e USB ?
/ / Something
{
c = uart usb getchar ( ) ;
i f ( xQueueSendToBack ( readQueueHandle , ( void ∗ ) &
c , 0 ) ! = pdTRUE ) {
return ;
}
}
}
//
//
//
//
//
!
! @brief usb sof action
!
! This function increments the s o f c n t counter each time
! t h e USB S t a r t −o f −Frame i n t e r r u p t s u b r o u t i n e i s e x e c u t e d ( 1
ms ) .
/ / ! U s e f u l t o manage t i m e d e l a y s
// !
void u s b s o f a c t i o n ( void )
{
s o f c n t ++;
}
write
The C library calls the write function when writing data to a file descriptor. In this case, we only support the file descriptors for standard
output and standard error.
Listing A.13: src/lib/io/read.c
/∗
∗ read . c
∗
∗ Created : 05.12.2011 11:17:18
∗ Author : Dan E r i k
∗/
# include <FreeRTOS . h>
# include <queue . h>
# include <u n i s t d . h>
# include <i o / i o . h>
# include <c o n f i g / c o n f i o . h>
int
r e a d ( i n t f i l e , char ∗ ptr , i n t l e n ) ;
int
{
r e a d ( i n t f i l e , char ∗ ptr , i n t l e n )
i n t nChars = 0 ;
i f ( f i l e ! = STDIN FILENO )
r e t u r n − 1;
i f ( readQueueHandle == NULL )
r e t u r n − 1;
f o r ( ; l e n > 0 ; −− l e n )
{
portCHAR c ;
i f ( xQueueReceive ( readQueueHandle , &c , ( portTickType
) IO READ TIMEOUT ) ! = pdTRUE )
break ;
∗ p t r ++ = c ;
++nChars ;
}
r e t u r n nChars ;
}
A.7
FreeRTOS on the OBC
Introduction
This section describes the AVR Studio 5 project setup for the OBC.
Starting from an example project
Create new example project from AVR Studio 5. The example chosen
was ”USB CDC Example (from ASF v1) - EVK1104 - AT32UC3A3256”.
In the example project, a USB interface is set up as either host, device
or both. When in device mode, both the USART and the USB interface
is used. Traffic sent to one of them, is forwarded to the other.
The example is designed for the evaluation board called EVK1104.
This won’t work directly with the OBC design, but is a good basis for
writing the logic in a USB CDC device. In addition, the example can use
FreeRTOS. And it is this use-case, that is most interesting. In addition,
the example project comes bundled with drivers for the USB interface.
By using them we don’t have to:
• Write a USB stack as implemented on a USB device
• Implement USB CDC Device class specific logic
• Write USB drivers for FreeRTOS
Now, do the following:
• Remove src/host cdc task.c & src/host cdc task.h. These files implement host specific logic for USB CDC Device class.
• Remove src/asf/avr32/drivers/intc/exception.S. FreeRTOS defines
its own exception vector, and defining them twice is going to become a problem when linking the binary.
• Remove src/asf/avr32/boards & src/asf/avr32/components. These
folders contain initialisation code and defines for EVK1104, as well
as a joystick driver. These folders are also removed from the include directories
• Change -DBOARD=EVK1104 to -DBOARD=USER BOARD and add
-DFREERTOS USED in project settings.
Then adjust the rest of the project according to preference.
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement