358 Commits

Author SHA1 Message Date
Oliver Smith
5b5785af7a Bump version: 0.8.1 → 0.8.2
Change-Id: I4f0510da6135fcd4d0b86d4fdfc114c27c82420c
2023-09-15 11:19:51 +02:00
Oliver Smith
ecafd5abab firmware/Makefile: don't use distribution's CFLAGS
Set CFLAGS on top of the Makefile, to avoid using the distribution's
default CFLAGS. In debian testing and unstable, -fcf-protection was
recently added to the default CFLAGS, but it cannot be used with the
cross compiler:

  [COMPILING libosmocore/source/backtrace.c]
  cc1: error: '-fcf-protection=full' is not supported for this target
  make[2]: *** [Makefile:270: obj/simtrace/flash_backtrace.o] Error 1

Change-Id: I5f7cd0402f9bb85dd600204fdf8855773ddbeb70
(cherry picked from commit e6e77399d6)
2023-09-15 11:16:38 +02:00
Oliver Smith
afd23660b3 Bump version: 0.8.0.1-8281 → 0.8.1
Change-Id: I6bcc798db9f4ab2b91711daebeba98abebd55e92
2021-12-10 10:04:28 +01:00
Oliver Smith
24a9ee8ae6 host/contrib/simtrace2.spec.in: fix soname
Adjust the soname in the rpm recipe too, to fix:
  error: File not found: /home/abuild/rpmbuild/BUILDROOT/simtrace2-0.8.0.202112100026-1.1.x86_64/usr/lib64/libosmo-simtrace2.so.0*

Change-Id: I748f44409ac736abbd5c18e31ae02d025dee2c77
2021-12-10 10:04:13 +01:00
Harald Welte
45a8f2beee Bump version: 0.7.0.166-61b4-dirty → 0.8.0
Change-Id: I1650f7181cf514ba00e6f70e8133ee88780ebf41
2021-12-09 08:12:56 +01:00
Harald Welte
155c237504 host: Upgrade libosmocore dependency to 1.4.0
1.4.0 contains the most recent changes to libosmousb, so let's use
that as a minimum basis.

Change-Id: Ia44377cd6a8d7998c6995a3f89adb22cdc675601
2021-12-09 08:05:58 +01:00
Eric Wild
61b4aad46f firmware: remove dfu-dfu default target
It's useless, since blupdate does the same thing, just much faster and
easier.

Change-Id: I86dddfacea2e35f4d5a7f23ee4b3d12e3f1d35f1
2021-11-24 17:22:01 +00:00
Eric Wild
23125d05f7 jenkins: build bootloader updater
Change-Id: I8b2023921a67b0e8945d8f24e4c8076de3e12acf
2021-11-02 10:50:36 +00:00
Eric Wild
7ac85188f4 firmware: add missing usb strings to blupdate that prevented building it
Change-Id: I8d0d9bf98748d475427d9b0c78f2e0532ee4bca1
2021-11-02 09:54:55 +00:00
Eric Wild
23eb56319c add our default clang-format file
Change-Id: I77aab70400bdbb46cbdd83e428e2a28ebf29b8dd
2021-11-01 14:35:14 +01:00
Eric Wild
c85f52d5d5 firmware: drop cref printing
No one reads this, no one wants to know this.

Change-Id: Ie2281e207164f82d8ee29bd596a5593c22aaf198
2021-11-01 14:35:14 +01:00
Eric Wild
a079e2b4ee firmware: increase reset delay before usb reattach
The previous value was way too low and led to reenumeration issues when
switching from app to bl because the hosts are fairly lenient and
feature long delays until they accept disappearing devices as gone for
good instead of ignoring a presuambly flaky usb cable or connection.

Related: SYS5061
Change-Id: I9b8c8bf794ad5b94fc7ea2a01d1ebf4e36862c36
2021-11-01 14:35:14 +01:00
Eric Wild
f83d42ce51 firmware: remove usb pullup that dates back to simtrace1
All the parts are DNP and never existed on the simtrace2 with sam3; the
sam3 has internal pullups that are part of the usb peripheral.

Change-Id: I04a703a2eba6ff1dc64692c089213389d0c1066d
2021-11-01 14:35:14 +01:00
Eric Wild
a7e306f745 firmware: add bootloader update "app"
This bl updater can be flashed as app and will update the bootloader and
then
delete itself before resetting the sam3, so the device will end up in
the newly
updated dfu bootloader afterwards, without having to press the
bootloader button
or requring any other manual interaction, ready to receive a new
application image.

Building the blupdater requires a previously built dfu-flash bootloader
bin file that
will then be embedded into the app during building.

Related: OS#1704
Related: SYS5061
Change-Id: I53dea57bba790a2ab3245d9483e0ff1c8d19d5e3
2021-11-01 12:03:38 +00:00
Harald Welte
020edca678 cardem-pcsc: Fix return of uninitialized variable
Fixes: CID#240740
Change-Id: I97431f491f60e2a6537502ef88042907723b7de6
2021-10-25 08:12:08 +02:00
Eric Wild
17bfa5273f fix bootloader led config crash
This led to occasional crashes for targets with leds since it was
introduced 3 years ago
The interesting thing is that most of the time it didn't crash...

Change-Id: Ia6a1b1fc0e44a301b4fb1d9c9fdbc27d61dcab97
2021-10-20 20:03:06 +02:00
Eric Wild
a65fb1e319 clang build support
Supposed to be used with https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm
+ distro provided binutils-arm-none-eabi package, might provide better and more reliable
binary sizes, especially for the bootloader.

Just run USE_CLANG=1 make

Change-Id: I1a19f40d44797efad5c46121e73115ed738a095b
2021-10-20 20:03:06 +02:00
Eric Wild
af6ae8b8dd drop unused exidx sections when linking
clang might emit those even though they are neither needed or wanted,
so just get rid of them.

Change-Id: I159b4405cebe72af4d98b27f876c48835ffd6e2d
2021-10-20 20:03:06 +02:00
Eric Wild
90784220a5 add the ngff cardem to default build targets
Change-Id: Icec4966fe419eee9f7ace67e46e3d88738812b38
2021-10-20 20:03:06 +02:00
Harald Welte
651050922a simtrace2-tool: Initialize logging to avoid error on first log output
This avoids
 ERROR: osmo_log_info == NULL! You must call log_init() before using logging in log_check_level()

Change-Id: Id355ef33e10164f8e8eb40c2fd0b606bc8e9b6f7
2021-10-06 21:10:44 +02:00
Harald Welte
5b7a608277 simtrace2-cardem-pcsc: Remove double libusb initialization
This code already calls osmo_libusb_init further above in the top
of the main() function, so there's no use of calling libusb_init()
directly in the same function lines below.

Change-Id: I2e0c7446aaa644c5aae1059ce91ff9f729903cbc
2021-10-06 21:06:21 +02:00
Harald Welte
e304015b3c Use osmo_libusb_{init,exit}() instead of libusb_{init,exit}()
We use other osmo_libusb_* functions later in the code, so it is best
to initialize the library via libosmousb, and not directly.

Change-Id: I2fd981935e1420e529f5dd8a98edd347c317284c
2021-10-06 21:06:06 +02:00
Harald Welte
19ccc209c1 jenkins.sh: Build 'trace' firmware for ngff_cardem
Let's create and publish binary builds for 'trace' on BOARD=ngff_carde.

According to SYS#5525 this is verified working since two months ago, so
there's no reason to withhold the binary builds for it.

Change-Id: I8a98002ef5aa58e5a3d49627323fe11505508bc8
Related: SYS#5525
2021-10-06 21:01:14 +02:00
Eric Wild
5e82a2a1c6 Revert "firmware: data sections"
This reverts commit e6a76c7bf4.

Might or might not cause weird issues depending on gcc and binutils
versions, let's see if this helps.

Change-Id: I2f593fd5e0f1494aae6b9fcfb2160a6c9168f5b8
2021-10-04 18:05:45 +02:00
Eric Wild
301aec51f7 contrib/jenkins.sh: lower trace to make bl fit
We keep running out of rom space, so reduce tracing to nothing for alle
dfu targets, and let's hope newer gcc versions stop producing more
code...

Change-Id: I7d2947c84097035bed00ad489a175d614b4c388e
2021-10-04 15:07:44 +00:00
Eric Wild
1f75e3881c contrib: allow manually forcing bulk simtrace dissection
Change-Id: I5fcfe3c221b87b02e21c857ac51d0392c3b4de3c
2021-08-09 15:18:59 +02:00
Eric Wild
5beffa5d91 contrib/jenkins.sh: build ngff_Cardem dfu bootloader
It does fit with some compiler versions, while others overflow the bl region,
so just reduce the trace level a bit to make it fits all the time.

Change-Id: I168a847da8dfc585aaeef0030f95fc225a713147
2021-08-09 12:45:13 +02:00
Harald Welte
3092721729 contrib/jenkins.sh: Build APP=cardem for BOARD=ngff_cardem
This makes sure downloads.osmocom.org will get cardem images
for the new ngff_cardem board.

The dfu loader was not enabled as it currently overflows the ROM
region by 200 bytes, see OS#5210.

Change-Id: Id2b7925c823fb19f880e06a205764d2b19de4ad4
Related: OS#5210
2021-08-08 21:31:03 +02:00
Eric Wild
7ca68359f3 cardem: fix spurious NULL bytes during transfers
The "wait time extension timer" was apparently not being reset during
normal tx operations, which led to occasional NULL (0x60) bytes getting
injected into transfers, which in turn led to more tx bytes than what
the reader side expects...

The odd thing is that this was only noticeable with high baud rates,
probably due to the very long default WT of 9600 ETU, and even then only
because it led to weird ngff modem resets after benign transfers.

Change-Id: I15b0b83b7d93b8e5589f3640bd6eb2fc82f93394
Related: SYS#5553
2021-08-08 04:14:38 +02:00
Harald Welte
a951c4ae02 simtrace2.spec: Add simtrace2-tool binary to package
This fixes RPM build issues reported as

[   59s] error: Installed (but unpackaged) file(s) found:
[   59s]    /usr/bin/simtrace2-tool

Change-Id: I1fd5980a686652afb47cd1c30e12919de626aec7
2021-08-03 09:02:34 +02:00
Eric Wild
d1d504bfa5 firmware: trace for ngff
Change-Id: Iee1eedd93d72c02880fd59fb8588abe14d05e77b
2021-08-02 15:10:21 +00:00
Eric Wild
23a9771467 contrib: more cardem dissection
Change-Id: Ia74d3674f854b390c9745a1cb8d5756bd5d39540
2021-08-02 09:23:19 +00:00
Eric Wild
a755b53768 simtrace2-cardem: use local sim on exit
There is no obvious reason why the st should be stuck in cardem mode
without a working running util on the host side since there is no state
that is being kept, so switch back to using the local sim upon reset.

Change-Id: Ib622af0027d40b4e8afbb0fa0d3689f0dbfcac92
2021-08-02 09:23:19 +00:00
Eric Wild
1ad205e682 firmware: make the ngff beakout blink
..but only if the cardem sim is active

Change-Id: I65f1fbeb06690a143ef4c792728c9cb917a4ffde
2021-08-02 09:22:46 +00:00
Eric Wild
34317c1f32 firmware: proper makefile deps
Single threaded evaluation is (assumed to be!) left to right, depth
first - but with concurrent make using -j this breaks, because the
actual usb string header is generated after the attempt to concurrently
compile the code that needs it, since there is no explicit order among
the all: dependencies.

This is fixed by properly adding a dependency on that header.

Change-Id: I0bdf915deabeda861f6398e654764918e58a64c2
2021-08-02 09:22:46 +00:00
Eric Wild
e6a76c7bf4 firmware: data sections
Might or might not be compiler default, but why guess?

Change-Id: Id3da816611afea0858466949dcc47db5e5d5493a
2021-08-02 09:22:46 +00:00
Harald Welte
4fe93be725 introduce support for new ngff_cardem board
This adds support for the new ngff_cardem board, a board that
basically combines a ngff breakout board with a built-in SIMtrace2.

Cardem works, but depending on the modem it might need a adjusted ATR to
ensure a lower baud  rate is used by the modem, high rates might lead
to weird power cycling of the card after a few transfers.

Trace was also tested and appears to work as expected.

Change-Id: Ia96124fbe8a752c98e7fd4096d542a3b2b9bc255
2021-08-02 09:22:46 +00:00
Harald Welte
51d87fbb66 Introduce simtrace2-tool
The simtrace-tool is a command line tool which can be used to e.g.
manually request a modem reset.

Change-Id: I3a8896ac2b3caef7590b51118359e5caed820a40
2021-08-02 09:22:46 +00:00
Oliver Smith
c7490b46cd gitreview: new file
Change-Id: I650fe7c930392d24042e65295fa49400478ffab9
2021-07-30 10:32:35 +02:00
Harald Welte
c85f39078c contrib/flash.py: Add OCTSIMTEST support
Change-Id: Id906d955f45a204ac0b00f56d8f5149c64c62f32
2021-07-09 11:46:16 +00:00
Harald Welte
06fe3b8295 99-simtrace2.rules: Add OCTSIMTEST
Change-Id: I226ee21e0937f851428578578f81075fa703dd54
2021-07-09 11:46:11 +00:00
Harald Welte
d0c420055d board_gpio.gnumeric: Add ngff-cardem pin-out
Change-Id: Ie1a7be85200e331232ad52aa0468c748ff053142
2021-07-01 23:28:52 +02:00
Harald Welte
3ef40d1ca6 simtrace2-list: Use osmo_st2_compatible_dev_ids[]
we shouldn't use a local copy of the device id list, which is already
outdated now that OCTSIMTEST support has been added to libosmo-st2

Change-Id: I2231006b94c33fe3b28ce37b0d54c67206751058
2021-06-30 08:17:58 +00:00
Harald Welte
dcfea28a4f don't printf() directly from library code, go via libosmocore logging
This allows us to use different log levels, and permits the user to use
other log targets.

Change-Id: I08ef7cfa5d8734882746a11ccd5f059d757401ae
2021-06-30 08:17:58 +00:00
Eric Wild
264f615b65 cardemu: support 1v8 for the tester
The tester has shifters, while the original simtrace relies upon the
reader restarting the powerup attempt with > 1v8 after not respondig due
to a lack of shifters and therefore 1v8 support.

Change-Id: I520aa26c6e0fb34568a4f632943efa59a0da831c
2021-06-26 02:54:20 +02:00
Eric Wild
017e10e9ef cardem: free the buf
This leak was probably hard to notice since config commands are usually
rarely sent.

Change-Id: I21411ef78a32a5258a7008272774cdb83119b413
2021-06-21 23:46:38 +02:00
Eric Wild
f0653533cc contrib: add a basic simtrace lua dissector for wireshark
See Help->About Wireshark->Folders tab,the usual place this should go is
~/.local/lib/wireshark/plugins
Hot reload possible after editing using Analyze->Reload Lua Plugins

Change-Id: I360ab522dabc3a378969df36efd3b48fc4cade3c
2021-06-21 17:38:53 +02:00
Harald Welte
f2e924c4aa firmware: octsimtest: ensure all card_insert GPIO are 0 after reset
Change-Id: I3c3744673ba53750cb66aa5023c8228edb006bfc
2021-06-06 11:46:49 +02:00
Harald Welte
efb47b3fae firmware: octsimtest: Add i/I command for setting card-insert via I2C GPIO
Change-Id: Ie1483ccf8465df0d640d55e50421fda910dced4a
2021-06-06 11:46:49 +02:00
Harald Welte
2b1d1e6d92 firmware: octsimtest: Fix disabling the card_insert signal
Back in I8c9b0c3d862a967832134b24252577739182da62 we added support
for enabling the card_insert signal, but not for explicit disable
of it.  Let's fix that.

Change-Id: I6f32bde60674119c9912e51059a53b5ee74d074a
2021-06-03 15:06:58 +02:00
Harald Welte
e2971dee2a firmware: octsimtest: use TRACE_* macros instead of direct printf
Change-Id: I41864bc2f64905a4f2ccb50769b1840e8a490c76
2021-06-03 14:37:45 +02:00
Harald Welte
731e199fc4 firmware: octsimtest: Support SIMTRACE_MSGT_DT_CEMU_CARDINSERT
The octsimtest board can control the card-insert contact of the OCTSIM
under test via an external I2C gpio multiplexer; let's add support for
that.

Change-Id: I8c9b0c3d862a967832134b24252577739182da62
2021-06-03 14:37:45 +02:00
Harald Welte
f69a60f255 firmware: cardem: re-factor CARDINSERT command processing
move it out of the general command dispatch switch statement
and into a separate function.

Change-Id: Ia40c3d9999be68248da0dcc69d298450ca6e4869
2021-06-03 14:37:45 +02:00
Harald Welte
dd5794c975 firmware: octsimtest: mcp23017 initializaiton
* driver should not have hard-coded understanding about I/O directions
* board code should pass the I/O direction to driver
* board code should use the correct I/O directions (A0..7, B0: output)

Change-Id: Id4a8e012a33cee01bb489e612e17920760b9be59
2021-06-03 14:37:45 +02:00
Harald Welte
d46f6bae2c firmware: octsimtest: Make slot mux configurable via USB
Change-Id: I4cdb250d2e1dbc5b8b0169f8b7c21e288b492e1d
2021-06-03 14:37:43 +02:00
Harald Welte
3561fc4c8b firmware: octsimtest: Fix IO_DIR pin definition
Change-Id: I776c9106bcd4ceb24a5d50ea05c6025dedb73822
2021-06-03 14:32:36 +02:00
Harald Welte
b69f5a85b3 contrib/jenkins.sh: Build 'cardem' app for 'octsimtest' board
Change-Id: Ia38bbb85c2828ab7307ffe688e50d7cdf70d6d39
2021-06-03 09:36:10 +02:00
Harald Welte
4996d7d634 octsimtest: Adjust VCC voltage thresholds (resistive VCC divider)
octsimtest has a resistive voltage divider in front of the VCC ADC
in order to also detect 5V.  We must make the thresholds board-specific
and adjust them for octsimtest.

Change-Id: I9e4adb4f349d2d838ea4100eb49271f3a0e7a2a5
2021-06-03 09:36:10 +02:00
Harald Welte
054d7ca499 cardem-pcsc: initialize libosmocore logging
Change-Id: I815d39190e944d9512ffc8e5f581515d7be9834f
2021-06-02 22:57:10 +02:00
Harald Welte
5b825beb41 octsimtest: Switch direction of I/O level shifter depending on uart tx / rx
Contrary to other hardware designs, octsimtest has a level-shifter in
the I/O line to support testing with 1.8, 3 and 5V.  This level shifter
is bi-directional, but the direction needs to be explicitly specified
via the SIM_IO_DIR signal attached to PA26.

Change-Id: I44171363b5bd69d6049b12c86f8143be83557cb2
2021-06-02 22:57:10 +02:00
Harald Welte
31d103b9f6 octsimtest: most code for support of this new board
* code for controlling the Card slot + frequencyt divider muxes
* put everything in place to build cardem application for it

Change-Id: I7e03e0c0f2999a1ce2dad966d98e22033fa58465
2021-06-02 22:56:12 +02:00
Harald Welte
73466e2b89 octsimtest: remove lots of unused #defines
The octsimtest board only supports cardem mode, not 'ccid'
nor 'sniffer'.  Remove related GPIO pin #defines from board.h

Change-Id: I43e8631d945ba183a1e5b1e37dd4565adb377154
2021-06-02 22:56:04 +02:00
Harald Welte
913c86b95d Add usb product ID of sysmoOCTSIMTEST
This is a custom board for production testing of the sysmoOCTSIM,
an 8-slot smart card reader.

Change-Id: I65839be50ac896c76f34755fb2800f836f6cdae4
2021-06-02 10:09:40 +02:00
Harald Welte
0516464620 assert: Use printf_sync() to ensure printing of assert / panic
Change-Id: Icc202e60445d9be1cdcd61176db5ed1704d583e7
2021-06-02 09:12:35 +02:00
Harald Welte
c1033c8611 simtrace2-cardem-pcsc: Reset the real card if reader resets cardem
When the cardem detects a reset from the phone/modem, pass this on
to the actual card via the PC/SC reader.  This is important to
reset the card state whenever requested by the stack/driver on the
phone/modem.

Change-Id: I7056476c5f81e8aa8f550afb86bf2380d1497ebb
Depends: libosmocore 20199da02d37a6d284915a27ec12641e79b8781c
2021-06-01 21:09:05 +02:00
Harald Welte
644c2131ca simtrace2-cardem-pcsc: Decode STATUS flags to strings
SIMtrace IRQ STATUS: flags=0x13, fi=9, di=6, wi=10 wtime=9600 (RESET VCC  CLK )

is more understandable than

SIMtrace IRQ STATUS: flags=0x13, fi=9, di=6, wi=10 wtime=9600

Change-Id: I5bbfa1d99ebee4b297d894a5f444dbe743c7ab70
2021-06-01 21:09:05 +02:00
Harald Welte
796501293d Revert "cardem: disable upload for simtrace2"
This reverts commit baa62777c8 which
deleted simtrace-cardem builds to prevent them from being published.

Change-Id: I63fd4bea2985fcc87f202d8b69a4f24661858185
2021-06-01 18:47:37 +02:00
Harald Welte
e33c2907bc jenkins.sh: build 'cardem' firmware also for simtrace board
Now that it is supported, we should also build + publish the related
binaries.

Change-Id: I9231503b865adc863959d74d98e7f24f83c293e9
2021-06-01 18:38:25 +02:00
Harald Welte
0f75d6ef1e simtrace board.h: Enable HAVE_CARDEM if we build the cardem firmware
likewise, enable HAVE_SNIFFER currently only if we build the sniffer
firmware.

It's been many years too long to finally get those all merged in one
firmware :(

Change-Id: Ib433f180746f75458a44f4988643465bd846b04b
2021-06-01 18:38:21 +02:00
Harald Welte
c690a1f130 st2-cardem-pcsc: Use ATR of real card by default
Before this patch, we would always use either a hard-coded default
ATR from the source code, or we would use one that the user specified
on the command line.

The more sane default is to pass-through the real ATR of the card.

Change-Id: I75bf618a6b0d983727de4c2f19b4b48ec3e12af8
Closes: OS#5107
Requires: libosmocore.git 22117a7164012d6d88fc202cd63df79c6068484d
2021-04-25 21:30:47 +02:00
Harald Welte
8e6ba005d4 st2-cardem-pcsc: Fix goto-in-while mess
There's some code that wasnts to goto within the while loop, and there's
some other code that wants to goto after the while loop.  Don't jump
from outside the while loop into the while loop.

Change-Id: Ic2a94ad034dd259f15712687443b569f0d18ff3f
2021-04-25 21:30:47 +02:00
Harald Welte
206d613b4d contrib/jenkins.sh: Switch from rita -> ftp.osmocom.org
We should use service-aliases and not the primary host name, as
that makes migration between machines hard.

Change-Id: I34b18457268ae6f8ae3a053c5424210074a4d52e
2021-04-22 11:21:12 +02:00
Harald Welte
7b681981ea card_emu: Fix computation of waiting time
As we store the waiting time (WT) in 'etu', we must adjust the formula
from ISO 7816-3.  The 'Fi' component in the formula only exists to
compute clock cycles from the etu, which we don't need here.

Without this patch, the waiting time would be way too large (by a factor
of 372 in the default case).

Change-Id: Ia21bc7303f9b38834b5b1753983ed2a99bfc7d95
Related: OS#1704
2021-04-08 21:28:37 +00:00
Harald Welte
e410842d8e card_emu: Fix USART timer, particularly in re-start situations
The existing code started the timer once (and expired once) but didn't
properly handle re-starting of the timer.  Neither did it handle
the 'half time expiration' case.  If we want to call a function after
half the WT expiring, we must of course program the hardware for half
the timeout, and not the full timeout...

Change-Id: Ia999d97f835c27597fcd1cf7ac78bac0ab9c98c1
Related: OS#1704
2021-04-08 21:28:37 +00:00
Harald Welte
752bc7f4b5 card_emu: Use USART timeout for waiting time
Instead of using the timer/counter peripheral to handle the waiting time
and corresponding timeout, the USART peripheral internal timeout
mechanism is used.

This is particularly important for the SIMtrace board since there
(contrary to other boards) the I/O signal is not wired to a TIO pin
of the timer/counter block, and hence Rx/Tx data cannot reset that
timer/counter.

As a result of this migration, cardem is now supported not only on
owhw + qmod, but also on the simtrace board.

The guts of this change have been lifted out of Change-Id
Ibcb2c8cace9137695adf5fb3de43566f7cfb93b5 by Kevin Redon, which was
unfortunately touching various different topics at the same time and
hence was split up. Some improvements are the introduction of the
ENABLE_TX_TIMER_ONLY mode, which avoids the USART interrupt handler
getting hammered with TXRDY between release of RST and start of the ATR.

Change-Id: Ibcb2c8cace9137695adf5fb3de43566f7cfb93b5
Related: OS#1704
2021-04-08 21:28:37 +00:00
Harald Welte
7f421ef014 card_emu: explicitly initialize PTS and TPDU states
Those are already initialized at various transitions of the master
7816 FSM, but let's properly initialize them at start-up, too.

Change-Id: I81b2a8ef3284559164700d94717e4ccf008f53df
2021-04-08 21:28:37 +00:00
Harald Welte
a708ea1d99 card_emu: improve reset detection conditions
* enter ISO_S_WAIT_RST when RST is asserted
* enter ISO_S_WAIT_ATR only when we RST is released while in state ISO_S_WAIT_RST

Change-Id: I620333aa8d45561a8028b948955a27f667b58406
2021-04-08 21:28:37 +00:00
Harald Welte
c1ffc8a603 iso7816_fidi: Add iso7816_3_ prefix to symbols; fix terminology
Fi/Di are not the index into the table, but the contents of the table
as resolved by Fi_index / Di_index.  Let's clarify the terminology.

Change-Id: If364e08e7c9a3a9707e6d54b9267c6a7c088e415
2021-04-08 21:28:37 +00:00
Harald Welte
79f0ea73a2 card_emu: Clarify and differentiate F/Fi/F_index/Fi_index
The ISO7816 spec terms are well-defined, let's not abuse them. We used
to consider "Fi" as the "index into the table of F values", while the
spec actually considers Fi as the initial value for F.

Let's make sure we use the terms quite clearly:
* Fi and Di are the initial values for F and D
* F*_index and D*_index are the indexes into the ISO7816-3 Tables

Furthermore, let's track Fi separately from F, as e.g. the waiting
time definition only considers Fi as indicated in the ATR, despite
an actually different F value might have been negotiated via PTS
meanwhile.

Change-Id: Ieb2425e8380a81b79df7b2bd072902994e9c3ee7
Related: OS##1704
2021-04-08 21:28:37 +00:00
Harald Welte
9454a062b5 card_emu: Rename fi to Fi and di to Di
As we will soon introduce the distinction between Fi and F, we should
use uppercase letters, as lower-case 'f' is defined in ISO7816-3 as
the frequency, which is different from the upper-case 'F'.

Change-Id: Iaede621551520576e9b9af878fa46fbc88e59c2a
2021-04-08 21:28:37 +00:00
Kévin Redon
6b7f8d142f make sim switch board specific
the simtrace board uses a bus switch not used on qmod and owhw to
switch the SIM between physical and virtual

Change-Id: Ieaf2ed4761fc3e04f33f9aac5c04a768c9a6f71e
Related: OS#1704
2021-04-08 21:28:37 +00:00
Harald Welte
9c95162d5c card_emu: waiting_time is stored in etu, not clocks.
The comment didn't reflect the source.  I checked all users and
the code consistently stores the waiting time in units of 'etu'.

Change-Id: I2bc4a7c19cee5fb487ad639ee48ecaea706f6172
2021-04-08 21:28:37 +00:00
Oliver Smith
878fadd74f firmware: disable stack protector by default
Disable stack protector for all boards/apps by default, not only
qmod-dfu. Use 'make STACK_PROTECTOR=1' to enable.

This was recommened by Eric:
"I'd argue that we do not want this in general, since it adds canaries
to all functions that deal with buffers, and therefore impacts the
overall timing in a non determinstic way depending on inlining and
optimizations, while contributing nothing in non debug builds."

Related: OS#5081
Change-Id: I30ad97f231ea5b401def650bc9adc7e9f2770df0
2021-04-08 12:04:47 +02:00
Oliver Smith
9e0e0ddd5a firmware: qmod-dfu: disable stack protector
Prevent build failure on debian 9, ubuntu 20.04, 20.10, where
bin/qmod-dfu-flash.elf does not fit the ROM.

Fixes: OS#5081
Change-Id: I9fffe4c323094679062428f41a4246b1c1b30ca2
2021-04-07 15:23:55 +02:00
Harald Welte
7a3d93682f Revert "add library providing ISO 7816-3 utilities"
This reverts commit 4a29f64cbe.

The code replicates to a large extent what is already present in iso7816_fidi.c
and I have serious doubts about the correctness of the computation in
its iso7816_3_calculate_wt() function.

Change-Id: I80dab4401d13306d573a6a35ce8729d2acc141e4
2021-04-06 02:17:38 +02:00
Harald Welte
01868775ba Revert "add ISO 7816-3 library to remsim project"
This reverts commit 4a58c08d67.

The code replicates to a large extent what is already present in iso7816_fidi.c
and I have serious doubts about the correctness of the computation in
its iso7816_3_calculate_wt() function.

Change-Id: I3f26da4e9aa8d7b0f4b4b7992269cf365a643ec7
2021-04-06 02:17:37 +02:00
Harald Welte
9ec3de9346 simtrace2-cardem-pcsc: Make it work again
* support Interrupt STATUS notifications
* use osmocom libusb abstraction
* use asynchronous URBs for interrupt + bulk

Change-Id: Ib04798572295f25477719124530b6584780c5b75
2021-04-05 20:37:00 +02:00
Kévin Redon
b218cc38d0 minor add comments
this is just to better understand the flow

Change-Id: I045286836176da729cc8c863866d6f6aa3836592
2021-04-04 23:01:41 +02:00
Kévin Redon
50360e0706 rename PIN_PHONE_{CLK,IO} to PIN_USIM1_{CLK,IO}
While this differs from tha naming in the schematics ({CLK,IO}_PHONE),
this matches the naming scheme used for USIM2 and the naming on other
boards.

Change-Id: I486b14260faec897e8c8698c4b7987bf36492497
2021-04-04 23:00:54 +02:00
Kévin Redon
4a58c08d67 add ISO 7816-3 library to remsim project
Change-Id: I99f3fecbc00d2379c3a6dc457b047c6fee41c292
2021-04-04 21:02:27 +02:00
Kévin Redon
4a29f64cbe add library providing ISO 7816-3 utilities
this will become part of libosmocore since it it common to smart
card related projects (such as osmo-ccid-firmware)

Change-Id: I3d4c65d137fc4555fcb256443feadd1c695de73d
2021-04-04 21:02:10 +02:00
Kévin Redon
debbf3c6fa cardem: currently simtrace does not support cardem
the SIMtrace board does not support the current card emulation
application because this uses a timer counter to handle the
timeouts, but on the SIMtrace board this is not connected to the
CLK signal

Change-Id: Idd09ea534179f0ede705573e1373dbd045c9828a
2021-04-04 18:06:51 +00:00
Eric Wild
0b1a3b4105 cardem: choose a more reasonable default ATR
PCSCd does not like invalid ATRs

Change-Id: I1eebfdc06be55931c2e80e2b515ac3a559737c38
2021-04-04 19:54:19 +02:00
Eric Wild
9316890a39 firmware: allow verbose builds
make V=1 can be used to echo all compilation commands, which is useful
because it allows IDEs to parse the gcc output in oder to properly index
the source files using the actual defines passed to the compiler.

Change-Id: I25c41dff89302a73ddd2a4aaba7cb14912fac3b8
2021-04-04 16:16:24 +00:00
Eric Wild
19cd3b0f71 firmware: do not allow undefined symbols
For some reason undefined symbols were downgraded to warnings, which
means building a firmware that calls missing functions  (= address zero)
was perfectly fine, which of course made development more exciting....

This applies to builtins, too, printf of one char gets downgraded to
putchar, which we don't have, so disable builtins.

Change-Id: I492f41ad4162b9d07b1881ae4aed019db2dff8b5
2021-04-04 16:16:24 +00:00
Kévin Redon
a1579ff4b0 minor: use same LED pattern for cardem as other applications
Change-Id: I5608c3312b648c0d59f79338ef1f97b6fe08f5b9
2021-04-04 15:02:19 +00:00
Oliver Smith
62ad58ad56 contrib/prepare_upload.sh: fix cd problems
Call the script from the proper directory, and cd into the topdir on top
of the script. Fixes:
/build/contrib/jenkins.sh: line 71: contrib/prepare_upload.sh: No such file or directory

Related: OS#4413
Change-Id: Icbfaa5579aab887830ca90b24a2e322df8d98f4f
2021-03-08 08:37:06 +01:00
Oliver Smith
1031d9b884 firmware: create duplicate files for upload only
Don't create copies of firmware files with version strings appended in
the normal build. Only do this before uploading the firmware files.

I have verified that "make" before this change and
"make; contrib/prepare_upload.sh" after produce the same files.

Close: OS#4413
Change-Id: I118a4ff397a178281c26a6b98112fa66b6f049ab
2021-03-05 15:38:48 +01:00
Oliver Smith
199cd431f3 gitignore: add firmware/apps/*/usb_strings.txt.patched
Change-Id: Ic99a5ae69ed755e6f74a1392678dcf71ab69e0d8
2021-03-05 15:04:06 +01:00
Oliver Smith
90e351f4a7 host: use git-version-gen/tarball-v. from topdir
Use .tarball-version from the topdir, because it only gets written there
when generating the OBS package. Remove the duplicate git-version-gen
script and use the one from the topdir to generate a version string if
building from the git tree.

Related: OS#4413
Change-Id: I4b197a218ab44632ff182ffbd72e15c2b20db341
2021-03-05 12:41:22 +01:00
Oliver Smith
09c3d45d6e firmware/Makefile: fix UNKNOWN in OBS packages
Fix having the version set to UNKNOWN in all packages built by OBS. The
osmo-ci.git scripts generating the source packages to be built by OBS
generate a ".tarball-version" file with a version string like
"0.7.0.70-657c", but it did not get used because the path was wrong.

Related: OS#4413
Related: https://osmocom.org/projects/cellular-infrastructure/wiki/Git-version-gen
Change-Id: Ic0b06011a604beec7c1c907c2c6e4ae927456e2e
2021-03-05 12:41:22 +01:00
Oliver Smith
810ecc5374 d/source/format: new file
Fixes:
  dpkg-source: warning: no source format specified in debian/source/format, see dpkg-source(1)

Related: OS#4413
Change-Id: I4c474547233ebb87a1246b01fbd7ff8879921c21
2021-03-05 12:41:22 +01:00
Eric
657cce1817 dfu: let the device reset itself
dfu flashing the ST12 was easy, but i was never able to
get ST34 into dfu mode. Changing the firmware so it resets
itself just like the octsim instead of starting a timer and
waiting for a reset from the host made it work every time for me.

Change-Id: Ida636ec925f40d6d56551f170150181350d03bbd
2021-01-29 11:02:27 +00:00
Harald Welte
aadd995664 remove old pre-autoconf makefile
Change-Id: Icd519a69a5cb1950daa79df4d9864e8dea091289
2020-10-27 15:55:07 +01:00
Harald Welte
0bb58e0b3c Update README
it has been long out of date.

Change-Id: I1137f33c5647f4d57a44224ee7259f3496edf1c4
2020-10-27 15:55:07 +01:00
Harald Welte
b1a56e0f77 rename simtrace2-remsim to simtrace2-cardem-pcsc
This renaming is to avoid any confusion with the osmo-remsim
project, living in its separate git repository.

The simtrace2-cardem-pcsc doesn't feature any 'remote' part.  Rather,
it emulates the SIM card interface towards the device/phone/modem,
and forwards it to a local PC/SC card reader.

Change-Id: Ic15f0a89964a72fe3ab7a5145a073720f6207e24
2020-10-27 15:48:37 +01:00
Harald Welte
80b8877a23 remove usb2udp
The UDP based forwarding really only ever was a quick hack to
demonstrate the capabilities.

Meanwhile, we've had the proper osmo-remsim project implemented,
which provides a much more reliable and comprehensive way of
managing SIM card emulation devices (SIMtrace2, sysmoQMOD, ...)
and collection of card readers (sysmoOCTSIM or any other PC/SC
supported readers).

Hence, remove the "UDP forwarding part.

Change-Id: Ia4b9447b95872b6e0dda6dca644f1ed4a87355a0
2020-10-27 15:48:35 +01:00
Leonard Hübner
1372aca28e remsim: adding cli argument to set the atr
Change-Id: I554b515e7954148f9ca5ba29417699da70b0945b
2020-10-27 15:34:36 +01:00
Harald Welte
a124c1714e migrate from BSC_FD_* to OSMO_FD_*
Change-Id: I01c834537e18eacdd1658f88a4b4a6d4690d87a6
2020-10-18 22:32:24 +02:00
Harald Welte
3907085239 dfu: Save another 60 bytes by changing the way we print horizontal lines
Change-Id: I1660a04fb3e42200bc2fdd23aa114119620125a1
2020-08-16 15:51:14 +02:00
Harald Welte
9866c7373c dfu: Shrink code by 144 bytes (by not calling PIO_InitializeInterrupts)
We are not using any PIO interrupts from DFU mode.  It's only used in
the main application firmware (verified by "git grep PIO_ConfigureIt")

Change-Id: Id1447af519df3183061f3d3f156a8dd84789af16
2020-08-16 15:47:00 +02:00
Harald Welte
1afb70a69d firmware: fix builds with gcc stack smashing protection enabled
On Ubuntu 20.04 when builiding dpkg packages, even when cross-compiling
firmware, gcc stack smashing protection is enabled.  Let's provide what
is minimally required in order to sucessfully complete builds on such
platforms.

Change-Id: Ic2f68f16b0730e7b5db17c30effc29a2909d1997
Closes: OS#4687
2020-08-05 11:59:26 +02:00
Harald Welte
859f1b0974 Introduce support for asynchronous USB transmission
libosmo-simtrace2 traditionally had only supported blocking, synchronous
I/O, while other osmocom programs such as remsim-client used
asynchronous USB I/O.

Using async USB I/O for IRQ + IN transfers while using blocking I/O for
OUT transfers doesn't seem to work reliably, so we have to offer a way
to perform the OUT transfers generated within libosmo-simtrace2 in async
mode.

Change-Id: Ib8939bdb7f533cd20a34a30a97f12b782b9816c2
2020-05-25 23:00:20 +02:00
Oliver Smith
4e73aaeba8 contrib: integrate RPM spec
Remove OpenSUSE bug report link, set version to 0.0.0, make it build with CentOS 8 etc.

Related: OS#4550
Change-Id: I8595642bc07bf3044720942a0f1802448920cb50
2020-05-19 15:59:01 +02:00
Oliver Smith
45e34c69de contrib: import RPM spec
Copy the RPM spec file from:
https://build.opensuse.org/project/show/home:mnhauke:osmocom:nightly

Related: OS#4550
Change-Id: I47ae01afb38fb18c462bf73501b49d6dc5d9f57f
2020-05-19 15:58:59 +02:00
Harald Welte
f46de7b70f simtrace2_siff: getopt_long() returns int, not char
This may be causing unwanted behavior while parsing the command
line arguments, as reported by some Raspi users.

Change-Id: I5b7db0795d16ab071e255c2c689e3b4872a933bb
Related: OS#4223
2020-03-19 09:18:31 +01:00
Harald Welte
e42492971e pio_it.c: Permit repeated calls to PIO_ConfigureIt()
The original code assumes that calls to PIO_ConfigureIt() are only
made once e.g. during board start-up.  Hoewever, we call those
at USB SetConfiguration time, when we know which particular hardware
function we are supposed to perform.   This means that after the host
has issued SetConfiguration more than a given number of times, the
code will assert() due to overflow of the static array.

Let's check if we already have allocated an array slot for a given pin
and reuse that allocated array bucket rather than allocating new ones
for the same pin.

Change-Id: I0c46d4b51eeebd58a8786d65e31e7a84e65b6a8e
Related: OS#4454
2020-03-13 15:28:40 +01:00
Harald Welte
a625ef0d9b USBD.c: Don't reset EP0 on SetConfiguration(0)
If we do this, the resulting USB code will fail on any of the
USB-IF Chapter 9 tests.  EP0 should not be reset.

Change-Id: I070faf4cb7029d3ccfa6c63f8f04aa0f02657536
2020-03-13 12:56:49 +01:00
Harald Welte
823f453d83 cosmetic: Add missing CR to LF in dispatch_received_usb_msg()
Change-Id: Ie1fc38ed4412b806e37688e0f9719573df06fd9f
2020-03-03 21:09:50 +01:00
Harald Welte
13cb311c06 extend osmo_st2_cardem_inst with fields required by osmo-remsim
Change-Id: Ib568e5212abfd1269a12c9e5672cdf23b4abff91
2020-03-03 21:09:50 +01:00
Harald Welte
e6806e58c2 cardem: Fix infinite loop + watchdog reset on long OUT message
In dispatch_received_usb_msg(), we ran into an infinite loop if a
too long messages was received on the OUT EP.  Let's break the loop.

Change-Id: I5325ed15d3dd79a42f8dac34d618e86b9334c301
Closes: OS#4429
2020-03-01 19:19:53 +00:00
Harald Welte
37220cce25 Disable interrupts during EEFC_ReadUniqueID()
Reading the Unique ID from flash is a rather tricky procedure: After the
STUI command has been issued, we cannot read normal flash anymore.
Rather, the unique ID is mapped at 0x00000000. This is unfortuantely
also where the exception vector table is stored.

EEFC_ReadUniqueID() is already linked to RAM, which is good.  Hoewver,
if an Interrupt happens between STUI and SPUI, then we try to access
the vector table and code from flash, which is illegal.  We run into
a hardfault and stay there until the watchdog resets the processor.

Change-Id: I3c4fad55b47e9013f6615a331983b3989ca805a7
Closes: OS#4428
2020-03-01 15:47:42 +01:00
Harald Welte
02712376df simtrace2_api: Add osmo_st2_cardem_request_config()
In Change-Id I7cdd3f9171dbed45de0089defe29d2b59044bd84 we introduced
firmware support for SIMTRACE_MSGT_BD_CEMU_CONFIG.  The respective
host part was so far only implemented in osmo-remsim-client-st2,
but not in libosmo-simtrace2.  Let's fix that.

Change-Id: Ia4822d360a271d2ce9725f761cb95de58663ac3b
2020-02-22 22:13:24 +01:00
Eric Wild
baa62777c8 cardem: disable upload for simtrace2
cardem on the st2 has been broken forever and still does not work, so
stop uploading cardem binaries

Change-Id: I33828f799d41386afb3f8dcd9bb510902877e03f
2020-01-30 17:22:40 +01:00
Eric Wild
1fad9229bf remsim: allow selecting pcsc reader number
The number can be queried using pcsc_scan -n

Change-Id: I9d347501a9f181f68e74799ad04a810553eb2c9e
2020-01-30 10:21:36 +00:00
Harald Welte
c7173bcc69 increase ringbuffer size from 512 to 1024 bytes
As reported in https://osmocom.org/issues/4335, there appear to
be some cards / use cases in which the 512 byte sized ringbuffer is
insufficient.  As we do have free RAM available, we can easily
increase the buffer size, despite not entirely knowing yet why
it needs to be *that* large.

Change-Id: Ie713d614ec5b334e9058d5d430e4bb660f5b8b69
Closes: OS#4335
2020-01-17 16:33:59 +01:00
Harald Welte
02f01e859c host/lib/gsmtap.c: Add GPLv2 disclaimer
Change-Id: Ie163af869c6aa2f3e2bd9007432dc6945384aaf2
2020-01-17 10:29:03 +01:00
Harald Welte
575214f248 host: Add COPYING file for host software (GPLv2)
Change-Id: I0f89a204939b0648eed94cc4f6e7c4f735c118fa
2020-01-17 10:23:31 +01:00
Kévin Redon
e88be9e782 add script to flash latest firmware
this python script lists the SIMtrace 2 devices connected to USB
and will flash the latest version of the application (if necessary).
it requires pyusb and dfu-util.
it is intended for end users so they don't need to read the length
and error-prone instructions provided in the wiki.

TODO:
- support updating bootloader (once dfu-ram image exists)
- use python implementation of dfu-util to be python only

Change-Id: I3ebe0f54b6e3b7b45478603cc0a5b56e87b1f461
2020-01-16 20:36:23 +00:00
Kévin Redon
b6e2f0f8e7 DFU: add DFU application
this adds the DFU as application, allowing to flash the bootloader.
a USB DFU alternative is added to flash the bootloader partition.

when the DFU is started as bootloader, the partition/alternative
to flash the bootloader is marked as "not available", and
ineffective.
the same happens for the application partition when DFU is started
as application.

this distinction is make at compile time, not at runtime, because
of size restrictions (the bootloader was already close to the
16 kB limit).
*_dfu_flash.bin should not be mixed with *_dfu_dfu.bin.
*_dfu_dfu.bin should be flashed as application using the already
existing DFU bootloader.
once this images is started (as application), the *_dfu_flash.bin
should be flashed as bootloader using the DFU application.

once the DFU bootloader has been flashed, soft resetting
(not re-powering) will cause the bootloader to start, allowing to
flash the application with a normal image (e.g. not DFU),
replacing the DFU application.
this switch to DFU only happens after downloading (e.g. flashing).

it is planned to have the DFU application erase itself after
flashing, but this is currently not implemented.

Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
2020-01-16 20:35:04 +00:00
Harald Welte
34200e4676 firmware: apps/cardem/main.c: Synchronize with apps/trace/main.c
In the end we want to share most of this, irrespective of the "APP".
Let's avoid unnecessary differences.

Change-Id: Icf063d4ca79edf66ffbe8e87a915deb77dec478a
2020-01-11 17:52:44 +01:00
Harald Welte
e3b2de45c4 firmware: move printing of welcome banner to common function print_banner()
This unifies the printing of the welcome banner, and it also ensures
that all modes print all information (serial number, reset cause).

Furthermore the APP and BOARD #defines from the make environment are
also printed.

Change-Id: I7e6bc05cee4b9ec0fd9a05dc90ce0b26a5763e5a
2020-01-11 17:52:36 +01:00
Harald Welte
ce4b5c25e8 library: Add osmo_st2_compatible_dev_idsp[]
This is a list of known-compatible USB VID/PID pairs.

Change-Id: I3ef66ebba307899c57077bfd633f84f30190f4dc
2019-12-26 08:07:59 +01:00
Harald Welte
7f7de1ec1d migrate to libosmousb
the code we used to have in libusb_util.c has been migrated to
libosmousb, a new part of libosmocore.git.  Let's remove our historic
copy and use the new shared library instead.

Change-Id: Ib588c08f873c4da8f3a02815ee2767674a6a5061
2019-12-26 08:07:19 +01:00
Harald Welte
8591495d74 Update .gitignore file for host
Change-Id: Id6449ea1c3e918e8c7748b9af7c8c354c1b607d5
2019-12-26 08:07:19 +01:00
Harald Welte
b566ea3e83 OSMO_ASSERT() on double-free or invalid pointer
Change-Id: I2ab8fb7b86b6f608bbd9c4f79369c64cbad88bdf
2019-12-25 08:51:44 +01:00
Harald Welte
563601cff2 [lib] apdu_dispatch: Don't print APDU state to stdout
The printing was always only done at the end of osmo_apdu_segment_in(),
so let's leave the decision up to the user if he wants to print the
state at every iteration or not.

We now provide osmo_apdu_dump_context_buf() to the user so he can obtain
a string representation of the internal state for logging at any time he
requires.

Change-Id: Id3e3cf1605dec84077b158c1c5715f8eef2641d5
2019-12-17 12:46:21 +00:00
Harald Welte
e9556efe88 [lib] apdu_dispatch: Use DLGLOBAL and don't printf() directly
Change-Id: I2f3ec49d34b6806e13af185fb629cabc486891fb
2019-12-17 12:46:21 +00:00
Harald Welte
cdc0853777 jenkins.sh: Add verify_value_string_arrays_are_terminated.py
Change-Id: I15f13e12711b87ce71b38b16ef17620850fd8eb7
2019-12-17 13:28:15 +01:00
Harald Welte
bfd27afd5f firmware: Reformat value_string to pass our validation scripts
This is a purely cosmetic change in terms of coding style, but it
fixes an [invalid] detection for unterminated value_string arrays
by our verify_value_string_arrays_are_terminated.py script:

Change-Id: I2f2370a673074f6bf5380106b6254b4aa1e8a792
ERROR: file contains unterminated value_string 'struct value_string iso7816_3_card_state_names[]': './deps/simtrace2/firmware/libcommon/source/card_emu.c'
ERROR: file contains unterminated value_string 'struct value_string tpdu_state_names[]': './deps/simtrace2/firmware/libcommon/source/card_emu.c'
2019-12-17 12:57:09 +01:00
Harald Welte
17cda3db8a simtrace2-sniff: Reformat value_string to pass our validation scripts
This is a purely cosmetic change in terms of coding style, but it
fixes an [invalid] detection for unterminated value_string arrays
by our verify_value_string_arrays_are_terminated.py script:

Change-Id: Iee905c744065df1dc54f04be752a65700897a92c
ERROR: file contains unterminated value_string 'struct value_string change_flags[]': './deps/simtrace2/host/src/simtrace2-sniff.c'
ERROR: file contains unterminated value_string 'struct value_string data_flags[]': './deps/simtrace2/host/src/simtrace2-sniff.c'
2019-12-17 12:04:56 +01:00
Harald Welte
e213cc4f59 cardem: Implement support for CEMU_FEAT_F_STATUS_IRQ
If this feature flag is set by the host application, we will start
generating SIMTRACE_MSGT_BD_CEMU_STATUS towards the interrupt endpoint
on any changes to the SIM card status, such as change of VCC/CLK/RST

Change-Id: I832b4ac4aeb6152195d985067ffdd64fa5a7d4cc
Related: OS#4330
2019-12-16 14:51:49 +01:00
Harald Welte
a5bbe78d2d cardem: Add SIMTRACE_MSGT_BD_CEMU_CONFIG
The new SIMTRACE_MSGT_BD_CEMU_CONFIG command can be used to set/change
a bitmask of optional features that can be enabled in the simtrace
by the host software.  This is useful for enabling features in the
firmware which are not supported by older host utilities.

The firmware will return the actually set/configured features in
response.

The feature bitmask is not yet used anywhere; it will be by subequent
patches.

Change-Id: I7cdd3f9171dbed45de0089defe29d2b59044bd84
2019-12-16 14:51:49 +01:00
Harald Welte
140f007c3e cardem: Make card_emu_report_status() optionally use IRQ endpoint
This just introduces the capability to report on IRQ, but we don't
actually use it yet.

Change-Id: I83db4463b7010ba243a8adbda3ac9393975b4814
2019-12-16 14:51:49 +01:00
Harald Welte
12c9b7ba02 card_emu: Remove extraneous initialization of ch->pts.state
ch->pts.state is initialized every time we enter ISO_S_WAIT_TPDU
state, so there's no need to reset it at other locations. KISS.

Change-Id: I5ff8b2671c3c893cc5f6542d48b65487ae8c5be1
2019-12-16 14:51:29 +01:00
Harald Welte
4d4405ff3a card_emu: Remove extraneous code
card_set_state(ch, ISO_S_WAIT_ATR) internally calls tc_etu_enable(),
so there's no need for the caller to do the same, too.

Change-Id: I2a2b4d64c40264623313a867957ffcefe57748f9
2019-12-16 14:51:28 +01:00
Harald Welte
6a3a714e2f card_emu: Always print state names in string representation
Change-Id: I81469e40f3720afdcb47048b45c63d6474887640
2019-12-16 14:49:56 +01:00
Harald Welte
e9f429d34c card_emu: Avoid recursive calls to card_set_state()
A function that is called to set the state should not in itself
contain logic to issue further state changes.

Let's shift the related block out to the end of card_emu_io_statechg(),
which is the only source of card_set_state() calls for the
WAIT_{POWER,CLK,RST} states anyway.

As an added benefit, the block of statements is now also executed if
there's no state change - something that was prevented by the
"if old == new" state guard at the top of card_set_state().  I believe
this may help us to cover more (non-standard) card activation sequences.

Change-Id: Ieefa1807099eb234cfd994bca83caaa0dcc919b6
2019-12-16 14:49:56 +01:00
Harald Welte
02d0d73cf1 card_emu: Initialize PTSS state every time we start PTS
Let's shift the responsibility from the caller side to the calee side.

Change-Id: I39661ca93c87b2e2071765f69578eec5aaf90ce4
2019-12-16 00:08:46 +01:00
Harald Welte
5b136021d8 host_communication: Send zero-length-packet on wMaxPacketSize
We need to send zero-length packets on bulk endpoints whenever the
transfer size is exactly a multiple of the wMaxPacketSize.

See USB 2.0 Specification Section 5.8.3 titled "Bulk Transfer Packet
Size constraints."

Change-Id: Ice3842399d5a5c4a18383860f81074497c6e7c9b
Closes: OS#4331
2019-12-16 00:08:46 +01:00
Harald Welte
81f4ef7750 cardem: RST resets all state (including release of buffers)
When the Modem is asserting RST, the emulated card should set all
of its state back to default/initial values and release any buffers
it may still hold in its state.

Change-Id: I66eca6afe4ff7d900c5b75df1e3ec6d52f6ef214
Related: OS#4251
2019-12-15 17:53:01 +01:00
Harald Welte
fa197ca343 cardem: Move card_emu_io_statechg() calls out of interrupt context
So far, we called card_emu_io_statechg() from interrupt context, which
was safe with the current code.  However, as we want to trigger a more
comprehensive reset of data structures, including the flushing of
message queues, it is best to shift this processing from interrupt
context to main loop context.

Change-Id: I3983078396538f32bdff55611c41d2163be4d796
Related: OS#4251
2019-12-15 17:52:00 +01:00
Harald Welte
e92cb50a6e card_emu: Factor out card_handle_reset() from card_emu_init()
Let's move all initialization of state that may change at runtime
to a separate function: card_handle_reset().

This has the advantage that the related function may also be called
at later/other instances, not just during initialization of card_emu.

Change-Id: I0954d192d001a3af5592010cc84a3a22aaf4b030
Related: OS#4251
2019-12-15 17:51:47 +01:00
Harald Welte
1714679106 pseudo_talloc: Increment number of buffers from 10 to 20
We need at least one per IN/IRQ endpoint, as well as at least 3 for
every OUT endpoint.  Plus some more depending on the application,
in case of cardem there could be one in uart_tx and one in uart_rx.

So for cardem, it should be 7 per slot, resulting 14 for dual-slot
devices like OWHW and QMOD.

Given that we have plenty of RAM available (utilization up from 49%
to 56% with this change), we can be on the comfortable size and
easily have 20 buffers for now.

Future MITM / triple-play applications likely need more.

Change-Id: I022ba3bb3e1f5fd0c364aafe1a23f8fd9b2d8499
Related: OS#4251
2019-12-15 17:39:26 +01:00
Harald Welte
a812de808d usb_buf: Properly initialize buffered_endpoint->ep number
The number is used only in print statements, and it's always '0' so far.

Change-Id: Id147e24d9d50c274fec963f00494cb20e2360b33
2019-12-15 17:25:14 +01:00
Harald Welte
b0b457df63 USBD_HAL: Don't disable UDP peripheral clock on suspend
Change-Id: I2169e2140762b37661f4567bb148326afd85cddc
Closes: OS#4329
2019-12-15 17:25:13 +01:00
Harald Welte
ad117091ca usb_buf: Actually limit queue to 3 elements, not 4
In Change-ID Ie15183f16b22193ffdaf01845db2eae4c7f43c17 we wanted
to limit the number of queue elements to 3, but actually implemented 4.

Change-Id: Ic5fb164f2dfd1c293c51bee8184fc34552267a54
2019-12-15 17:25:13 +01:00
Harald Welte
56be0bf317 cardem: Fix memory leak on unsupported SIMTRACE_MSGT_DT_CEMU_CARDINSERT
Some boards like QMOD cannot simulate a virtual card insert signal
towards the modem (as the mPCIe connector doesn't have that signal).

In these situations, we were aborting processing of the related OUT
endpoint command and forgot to release the related memory.

Change-Id: I489097b7e332004e0f2beca0b22fa36d5d1d31b5
Related: OS#4251
2019-12-14 23:26:02 +01:00
Harald Welte
60118315cc update copyright statement
Change-Id: I6ffced85cf2398bbf6dcc3123accb5610e766f61
2019-12-14 23:07:04 +01:00
Harald Welte
63c9e1f402 implement minimalistic talloc_report(); add 't' command on UART
This helps when debugging the firmware, as it shows the current
utliization of the 10-msgb-talloc pool.

Change-Id: Ib10c4396cd4c9c4a6257cf45886e367214787927
Related: OS#4251
2019-12-14 23:07:04 +01:00
Harald Welte
7c1d85eb4d qmod: Document '!' and '@' commands on UART
Change-Id: I38c69ef45e92fd0aa03907e984cf524331b53d57
2019-12-14 23:07:04 +01:00
Harald Welte
587248404c cosmetic: board_qmod: Annotate #endif with comments
Change-Id: I2e2de6c65d791767637b9c43a1c0ff9cbeabf5e9
2019-12-14 23:07:04 +01:00
Harald Welte
f620c3978c qmod: Don't print EEPROM operations in help when not supported
As of Change-Id I1c8cca2f7f0f0070d7bf1ade676e035c45e4d5ab, a firmware
compiled without ALLOW_PEER_ERASE will not support resetting the hub or
writing to its EEPROM.  Let's make sure to remove those options also
from the menu.

Change-Id: I3071332d85e6168947384ddc230298d3293e4668
2019-12-14 23:07:04 +01:00
Harald Welte
a14616c096 usb_buf: Limit the maximum queue length to 3 elements
If there are already three elements in the to-be-transmitted queue
for the EP, let's free the first element of the queue.  This is a
clear indication that the USB host is not polling the endpoint
regularly.  Maybe there's no host application running at all?

This should obsolete Change-Id Ie9ebdd2ff966f67c9afd1ed760f106558f0091ad

Change-Id: Ie15183f16b22193ffdaf01845db2eae4c7f43c17
Closes: OS#4251
2019-12-14 21:51:05 +01:00
Harald Welte
f4a625be53 usb_buf: count number of elements in queue
This is in preparation for limiting the maximum queue length

Change-Id: I7cb184d7a1ccb519010a2f3e3295cc3a5fbf8052
Related: OS#4251
2019-12-14 21:50:59 +01:00
Harald Welte
271be9d181 more comments in host_communication.c.
Change-Id: I8b0124ec96b56b7c89e4c7033a11cc93c4fa2d26
2019-12-14 21:13:37 +01:00
Harald Welte
342a7fe039 Add missing CR to achieve CRLF at end of log lines
Change-Id: Ic4afb2981f68811fddb272e64dbddd3397a12642
2019-12-14 17:26:21 +00:00
Harald Welte
3c003cc2fa Fix format string related warnings (int vs. long)
Change-Id: I924a16f03e2a099b9f8eb56746bff2b9101c6802
2019-12-14 11:47:06 +01:00
Harald Welte
37055b9286 stdio: Add support for %p format string (pointer address)
We actually llready had plrenty of code using %p, despite our stdio
not implementing it ;)

Change-Id: Iecf6c849ce5ef72a8fed9b19a18e215c61c3d09f
2019-12-14 11:47:06 +01:00
Kévin Redon
75a5f224c0 minor: improve trace output
the USB trace now respects the global setting.
the verbosity is also decreased, not showing USB activity unless
debugging.
this also saves some space.

the reset cause is now printed.
the strings increase the bootloader size, but it already exceeded
the 16 kB limit when trace level is set to info.

Change-Id: I9ba08d4bb4f188f6e7a202ea86acb7a42a2054f3
2019-12-11 16:58:07 +01:00
Kévin Redon
198c3fb21b improve shared bootloader/application memory
now both partitions (bootloader and application) use a commonly
defined memory location to shared the DFU state (which includes
the magic value to know which part to start), instead of using
a hard coded value.

the bootloader size has now also been restricted to 16 kB.
this limitation is enforced so to not be able to create larger
images, which could be corrupted when flashing the application.

bootloader and application flashing have been successfully tested
on qmod st12 and st34.

Change-Id: I204bed7e9391602672ed894decec1fc12e879275
2019-12-11 16:35:31 +01:00
Kévin Redon
98cf47adba Makefile: add linker option showing memory usage
this will help seeing how much free space is available for the
bootloader (which is restricted to 16 kB)

Change-Id: Ie74a1480c2f340765046be9bdfc3a8c4ba851e9b
2019-12-11 16:13:58 +01:00
Harald Welte
87940f1f83 Build only 'reasonable' combinations of APP/MEMORY
There's no point in building a DFU loeader that is to be flashed
via DFU - nor is there really any need for regular cardem/trace
that can be flahsed directly without DFU.  If anyone needs those,
they can still build them - but let's not confuse the average other
user.

Change-Id: I0abe86c6a942a59e5b2417d0532dffae654d7a18
Closes: OS#4087
2019-12-06 20:08:33 +01:00
Harald Welte
36f888f8b5 Patch actual board name into the USB iProduct string descriptor
"SIMtrace 2 compatible device" is pretty generic.  Let's have the
actual board name inside the string descriptors, giving a more
user friendly experience in case users are issuing 'lsusb' and the
like.

Change-Id: Ibcc338b504bd2a1605e31d7f5eadb7161f547c6a
2019-12-06 19:19:23 +01:00
Harald Welte
0a7c691b90 usb_strings.txt: s/SIMtrace Phone/SIMtrace Card Emulation/
This string dates back to some very early naming; let's reflect how
we have been calling this in reality for quite some time now.

Change-Id: I5a7497188385706a1e924784073c619fa9bfdd60
2019-12-06 19:19:23 +01:00
Harald Welte
c9af72dccb qmod DFU: Don't overwrite memory beyond end of usb_strings[]
The code in board_main_top() for QMOD blindly re-assigned some
members of the usb_strings[] array, writing to index 7 and 8.

However, that array only has those entries in the main firmware,
while in DFU that array has only 6 entries.  Depending on whatever
the linker has decided to put in the next memory location after
that array, we would overwrite that very early during boot-up.

Change-Id: I59e4e1a54e819808d5a8259a6d14f4b970a90020
Related: OS#4302
2019-12-06 18:47:25 +01:00
Kévin Redon
d70836f965 DFU: restart bootloader when USB conf failed
when starting the DFU bootloader, but USB configuration (e.g.
enumeration) failed, the MCU restarted in the main application.
this occured after a DFU detach and were the USB host missed the
USB reset.
now after MCU reset, the bootloader is started again, since this
is what was requested to begin with.
the bootloader will always restart in the bootloader until USB
enumeration succeeded.
this boot loop can be stopped by unplugging/removing power from
the device.

Change-Id: I4062a7d8a7934af2119c169759b614dc45990651
2019-12-03 15:51:52 +00:00
Kévin Redon
ed3ceec56f DFU: increase USB reset duration to 50 ms
the specification requires a reset duration of at least 10 ms.
reset is indicated by the device to the host by removing the
pull-up on D+ (host to device reset is a USB packet).
we used 20 ms, but on some setups (USB host, stack, hub, and load
dependent), this does not seem to be enough (no USB enumeration
was performed afterward, at least for the DFU bootloader).
increasing to 50 ms solved the issue on the affected setups.

instead of USB suspend, the more proper USB disconnect is used.
this mainly disables the pull-up provided by the USB peripheral.
USB activate is not required since the follow up initialisation
takes care of it.

Change-Id: If5ceb3b8f7a8f134d4439fdd138dd12b46589f97
2019-12-03 15:51:52 +00:00
Kévin Redon
15f48b2e89 minor: fix typo
Change-Id: I462291078fe9b05bfdf6fb7ab0f96b1edeecdac6
2019-12-03 15:48:51 +00:00
Kévin Redon
503e184157 cardem: use simplest ATR as default ATR
This is the shortest and simplest ATR possible according to the
ISO 7816-3 spec.

It does not offer any non-default parameters (F, D, WI, ...)

Change-Id: I4ff41b5120bcadca652296f9d3691f7606be2bd2
2019-12-02 19:38:45 +01:00
Kévin Redon
24c6fe21ab simtrace2-remsim: Use simplest ATR
this ATR does not encode any data and uses all defaults.
the lower default speed is also better handled by the hardware.
handling faster speeds is upcoming.

Change-Id: I5a4f2f94bea1a15aedbef5a6f2f49344387dc11d
2019-12-02 19:35:45 +01:00
Kévin Redon
8cbede7067 minor: ignore usbstring binary
Change-Id: I18fc3179f8b7f3f1272d26853007876156fc1e03
2019-12-02 19:30:37 +01:00
Kévin Redon
8b6991c18c better detect VCC and nRST changes on simtrace2 board
monitoring the state changes of the VCC and nRST lines is required
to correctly detect warm and cold reset

Change-Id: I72099956332724f84226e1495fdc5a5b1a034695
2019-12-02 19:28:52 +01:00
Kévin Redon
1cfc25e8c1 minor : fix typo in comment
Change-Id: Ie310143fe713a51fa1adf8bf7599374282341f2e
2019-12-02 19:28:07 +01:00
Kévin Redon
3864a794b4 minor: improve debug output
Change-Id: Ibfc22b95c0be3ac78bd50a40e31cc7d8546d81d9
2019-12-02 19:28:00 +01:00
Kévin Redon
e051ddd1f3 minor: move USB debug output from info to debug level
else it's too nosy while debugging other components, not often
used, and break the flow since it does not and a line.

Change-Id: I8920ff7c33b4c9fb174bb31a29334a63fcbede43
2019-12-02 19:27:19 +01:00
Kévin Redon
98fbf23897 dfu: minor: make debug output only verbose in info level
the longer output is to fast and often incomplete.
the shorter version is enough to view the progress when not
debugging.

Change-Id: I97bb84da68d1f3bc14fb7c05400edf1748f55460
2019-12-02 19:26:56 +01:00
Kévin Redon
9b367872c8 minor: updated copyright years
Change-Id: I9254b1ddf6436b5a4964b9124a36ae17bfc22886
2019-12-02 19:26:11 +01:00
Harald Welte
0b7e5f3af0 fix baudrate of 'make log'
Change-Id: Id186a594b1ce3ea0cd38f0cb82a99e5d87101433
2019-12-02 19:25:55 +01:00
Kévin Redon
72a62cfdb9 minor: fix spacing
Change-Id: I2f3127c7b276c9726fd0242e3e29be22f9d6255c
2019-12-02 19:25:37 +01:00
Harald Welte
483a3203fb simtrace2_api: Remove dead code
Change-Id: Iab393a6cf9ae1218e1554d9c0bfb7aab2cc3c35e
2019-12-02 11:23:51 +01:00
Oliver Smith
71cfc2b90d Fix topdir Makefile and debian packaging
Make building the debian packages work again. I've verified that it
works in my own OBS namespace.

This patch also adds missing pkgconf variables in host/Makefile.am, so
libosmo-simtrace2.pc installs properly.

Related: OS#4283
Fixes: 964cda309d ("host: use autotools and split shared code to libosmo-simtrace2")
Change-Id: I2377de1e8b149520922217a1ab16f6e22fe6462a
2019-11-28 11:53:09 +01:00
Oliver Smith
15e943ab8b simtrace2-sniff.c: fix printf usage
Fixes:

simtrace2-sniff.c:113:4: error: format not a string literal and no format arguments [-Werror=format-security]
    printf(flag_meanings[i].str);

Change-Id: I9793c680f070e724ce89272e9e489963c7516d52
2019-11-27 19:10:02 +01:00
Kévin Redon
b7f94dcb9f qmod: lower VCC threshold to 2.5V
on the QMOD board the VCC signal from the modem is measured using
an ADC (SIMtrace board just use card detect).
the threshold to consider VCC as activated was set to 2.8V, which
gives a bit of margin for the expected 3.0V.
still, we had one board where the voltage was 2.8V.
to be resilient against lower than expected voltages from
modems (or boards), we lowered the threshold to 2.5V.
this is still save for the SAM3S to correctly identify high/low
levels.

Change-Id: Iac2778903690045e4e63fef29f812205d00c28ed
2019-11-26 13:49:53 +01:00
Kévin Redon
c90de6983c free USB buffer when allocation failed
when the reader sends APDU headers (e.g. after multiple reset),
messages are queued for USB transmission.
but if no host software is connected to SIMtrace in card emulation
mode, the USB message queue is not emptied, leading to the memory
getting full and preventing allocation for newer messages (e.g.
more recent APDU).
in this case the oldest queued message is now dropped to free some
memory.

Change-Id: Ie9ebdd2ff966f67c9afd1ed760f106558f0091ad
2019-11-26 09:57:28 +00:00
Harald Welte
6f41349db9 merge simtrace2-discovery.[ch] to libusb_util.[ch]
Change-Id: I4defbec70986a90c1f0cfb7587393265b73c0163
2019-11-24 23:15:53 +01:00
Harald Welte
208890ad6e use osmo_st2_ or osmo_ prefix for [shared] library symbols
Change-Id: Ie2686b30717b9541b1217802ca967cd0a4cbde9b
2019-11-24 23:15:53 +01:00
Harald Welte
964cda309d host: use autotools and split shared code to libosmo-simtrace2
Change-Id: I57e77f927ee9e169cc794c5dc6b128a2d590201b
2019-11-24 23:15:53 +01:00
Harald Welte
331fa5a237 remove unused function process_do_error()
Change-Id: I02bc23a340b086b0de4e69affb6f965bff6bbc0b
2019-11-24 23:15:53 +01:00
Harald Welte
6fada5604b simtrace2-remsim: Implement/Fix the 'skip_atr' option
Change-Id: Id8206738635af0dd55836bbbcbfbe7381c375e97
2019-11-24 23:15:53 +01:00
Harald Welte
931fe558df fix typo: libisb -> libusb
Change-Id: I0a9505e3eeb7ae4ffda7081dcbb1ed63835600a5
2019-11-24 23:15:53 +01:00
Harald Welte
d401b12136 card_emu_tests: Cosmetic changes (re-order code; more comments)
Change-Id: I36aefc824187ee99d83a451d869b137c13334d91
2019-11-24 23:12:04 +01:00
Kévin Redon
389a4040d5 add DFU enter override capability
in case flashing the main application firmware using DFU failed,
the main application might be broken and not allow to switch again
to DFU mode to re-flash it correctly.
the other board have a way to force entering (e.g. staying in) the
bootloader using an external signal (e.g. a switch on the SIMtrace
board).
the OWHW DFU firmware did not have this functionality implemented.
the design (e.g. schematic) already has the SIMTRACE_BOOTLOADER
signal (on PA31) for this purpose.
now the DFU bootloader will start the DFU mode when the
SIMTRACE_BOOTLOADER is high.

this change has been tested on OWHWv2.

Change-Id: Iefff51a811ad0f3bf3a46b8e256b905d11344bea
2019-11-18 20:26:59 +01:00
Kévin Redon
5db9402a5f add serial and version info in USB description
as for the main application firmware, the DFU bootloader firmware
now also has the unique chip ID as iSerial in the USB description,
and an additional empty USB configuration indicates the firmware
version (e.g. DFU bootloader version).
these are only visible when the device is in DFU mode.

Change-Id: I11a2cd8079fda374d816da180f39f1c33d10af60
2019-11-18 20:06:13 +01:00
Kévin Redon
ac7e73a579 check RST/VCC/CLK line at every step of the activation
ISO-7816 specifies a card activation sequence: VCC on, CLK active, then RST
release.
we now check for the end state at every state of the activation in case the
reader does not strictly follows the sequence.

change has been tested on OWHW slot 1.

Change-Id: Ie55505ab3a70cbd64281af40af53d5e120313228
2019-11-14 20:11:48 +01:00
Kévin Redon
7233cf803a initialize VCC, RST, and VCC with actual values
previously the card RST, VCC, and CLK signal states have been initialized with
default values corresponding to an inactive reader.
this worked fine for actual inactive readers since the default values match
and would be updated when the signal changes (edge detection).
but if the reader is in another state, card activation detection could fail.
this is fixed since the actual signal values are now used during initialisation.

at the same time I changed the variable type from uint8_t to boolean since they
have only two possible states, and understanding the actual state when coding
is simpler (no need to check which integer corresponds to which state).

this change has been successfully tested on the 2 slots of OWHW board.

Change-Id: Ie9245d75d48ae93d16f97897d4fa5ad6cd402e73
2019-11-14 19:54:17 +01:00
Harald Welte
cdcdcc9f6d firmare/test/Makefile: Fix link order
Change-Id: I3ee8031f2823ad0817cb469526b1edfc0230b26b
2019-10-30 09:26:38 +01:00
Harald Welte
e876bf53e8 Attempt to fix master-simtrace2 publish stage (missing WORKSPACE env)
Change-Id: I5dfb22199727d424d83584f58c6517c80573e880
Related: OS#4243
2019-10-30 09:26:38 +01:00
Joachim Steiger
f7f1ea864d add/fix mcp23017 i2c gpio expander functions and tests
Change-Id: Ia2e5a1bf3f97272931014e54e587109297556c03
2019-10-24 18:09:05 +02:00
Kévin Redon
3feadfa910 define LEDs for octsimtest
the OctSIM tester has only one amber LED.
this is now mapped to the normally green LED, used for activity.
because the LED is driven by an NPN transistor (as open collector)
instead of being directly connected to the pin (as open collector)
like on the other boards, the logic is inverted.
since normally the LED is on on idle and blinks during activity,
it will now be off on idle an only blink on activity (unless the
code is extended to cope with the possible inverted logic).
because there is no second LED but the current code requires one,
I mapped is to an unused pin.

the octosimtest target still does not compile completely, but at
least the LED issue is fixed.

Change-Id: I1296833bef2804c611640fcf4756e47905660e7b
2019-10-04 15:55:02 +00:00
Kévin Redon
9acff5ee5a make LED definitions board specific
the LEDs (2 of them) were connected to the same pins on all
boards, up to the octsim-tester.
to be able to have board specific LEDs the definitions have moved
from common to the each board.
at the same time I added a bit of documentation what the LEDs are
used for.

Change-Id: I3226a9187a8d0b657ccf5dcd8f3586b2578f96d2
2019-10-04 15:55:02 +00:00
Kévin Redon
e5efbb156c hw: put board specific pin definition in corresponding file
SIM_PWEN and VCC_FWD are signals specific to the simtrace boards.
the corresponding pins PA5 and PA26 are used for other signal
on the octsim-tester.

Change-Id: I51f37dd112cf681f4b1dbb3d2320ff9a697eaa08
2019-10-04 15:55:02 +00:00
Kévin Redon
ede87e067d USB: place version string in interface
previously the version string was in the iConfiguration field of a
dedicated USB configuration.
this configuration had no interface, but the USB specification
requires at least one interface.
an interface has been added to this configuration.
the version string is now in the iInterface field, and the
iConfiguration field contains "firmware version".
the USB specification does not require an end-point, and none are
present.

Change-Id: I99361e313979711f4f45ad424a52faa3ddd7c558
2019-08-13 17:03:23 +02:00
Kévin Redon
acb7bd9fbe disable ERASE pin
disabling the ERASE pin prevents accidental erase for the flash
memory while the board is powered on (e.g. in case the user
overcomes the weak 100 kOhm pull-down for more than 220 ms by
touching or shorting the pin).
the flash is still erasable using the ERASE pin during power up.
it is only disabled after boot completed.

Change-Id: Ic3332eb1d4247a07988b2fd841f40e79862d06a7
2019-08-12 20:49:12 +02:00
Harald Welte
4b487b836a Fix builds on Ubuntu 16.04
The most recent commits introduced 'C99' syntax by declaring variables
inside the 'for' statement itself, rather than before.

This resulted in compile failures in the Ubuntu 16.04 builds on
build.opensuse.org:

[  105s] libcommon/source/usb.c: In function 'SIMtrace_USB_Initialize':
[  105s] libcommon/source/usb.c:679:2: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
[  105s]   for (uint8_t i = 0; i < ARRAY_SIZE(device_id_string) - 1; i++) {
[  105s]   ^
[  105s] libcommon/source/usb.c:679:2: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code
[  105s] libcommon/source/usb.c:686:15: error: redefinition of 'i'
[  105s]   for (uint8_t i = 0; i < ARRAY_SIZE(git_version) - 1; i++) {
[  105s]                ^
[  105s] libcommon/source/usb.c:679:15: note: previous definition of 'i' was here
[  105s]   for (uint8_t i = 0; i < ARRAY_SIZE(device_id_string) - 1; i++) {
[  105s]                ^
[  105s] libcommon/source/usb.c:686:2: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
[  105s]   for (uint8_t i = 0; i < ARRAY_SIZE(git_version) - 1; i++) {
[  105s]   ^
[  105s] libcommon/source/usb.c:692:15: error: redefinition of 'i'
[  105s]   for (uint8_t i = 0; i < ARRAY_SIZE(usb_strings) && i < ARRAY_SIZE(usb_strings_extended); i++) {
[  105s]                ^
[  105s] libcommon/source/usb.c:686:15: note: previous definition of 'i' was here
[  105s]   for (uint8_t i = 0; i < ARRAY_SIZE(git_version) - 1; i++) {
[  105s]                ^
[  105s] libcommon/source/usb.c:692:2: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
[  105s]   for (uint8_t i = 0; i < ARRAY_SIZE(usb_strings) && i < ARRAY_SIZE(usb_strings_extended); i++) {
[  105s]   ^
[  105s] Makefile:227: recipe for target 'obj/simtrace/flash_usb.o' faile

Change-Id: Ibdb837ac105664484b10873c2c0d9561051b1c2a
2019-08-08 10:18:35 +02:00
Kévin Redon
e0265462d8 add serial and version information in USB descriptor
the device ID (unique to the micro-controller) is now displayed in
the USB iSerial descriptor.
the git version is now also displayed in iConfiguration in an
additional (empty) configuration descriptor.
this allows the user to quickly get the device hardware serial and
firmware version just by using lsusb (no need for a custom USB
software).

Change-Id: If9fadecc097ca3e006990160936bf11b22eae4e0
2019-08-06 16:24:58 +00:00
Kévin Redon
d14970f95b publish: also upload latest
the jenkins script will now upload the versioned output to the
all directory, and a copy named "latest" in the latest directory.

Change-Id: I70114ef8414779e369da5cbf945854c9ace3464e
2019-08-01 17:23:23 +02:00
Joachim Steiger
b1a81c130e add new board and app for gpio testing on octsimtest board
Change-Id: I01243044002f51b34e8dc12c1b1f565bbf1740a2
2019-07-30 10:56:51 +02:00
Harald Welte
298a5ba722 contrib/jenkins.sh: don't delete old builds from ftp
Change-Id: I2b34b5d4525d62564d34a6583ee3739b82c07c68
2019-07-19 18:58:49 +02:00
Harald Welte
c3ef475ea5 contrib/jenkins.sh: also push the .elf files to the ftp (for gdb/objdump)
Change-Id: Ibccf92e30c84f34ff61b3e823151cf33f20a1c4f
2019-07-19 18:58:44 +02:00
Harald Welte
155f57abcf firmware: name binaries including their git version number
Change-Id: I4309810368ce4e8e13ede974b67e69ca3f0a6f53
Closes: OS#3452
2019-06-20 18:31:28 +02:00
Harald Welte
bc62335768 qmod: Disable hub reset and EEPROM erase/write by default
We recently introduced ALLOW_PEER_ERASE to control if the firmware
should contain code for the SAM3 to reset each other on QMOD.

Let's use the same define to also remove code for putting the USB
hub into reset as well as code for erasing + writing the hub EEPROM.

This is needed only during production, but it shouldn't be enabled
during normal operation of the product at the end user.

Change-Id: I1c8cca2f7f0f0070d7bf1ade676e035c45e4d5ab
2019-06-19 20:35:37 +02:00
Kévin Redon
63490361d2 remove unused make define
Change-Id: Ia9ef8ce705803df06cf1e4c3ac9731ce69e5e6c5
2019-05-23 16:34:29 +00:00
Kévin Redon
6228d187da add make DEFINE to remove assert ERASE code
remove code to assert peer ERASE line by default.
see README for more information.

Change-Id: I5f88ecf1e2dcf00c0297597f88dd361a6e088c1e
2019-05-23 16:34:29 +00:00
Kévin Redon
a634c0efee make peer ERASE more robust
adds command 'a' to allow setting/asserting the peer SAM3S ERASE
line on the next command.
this prevents against accidental erase since only the command 'y'
was required, without confirmation.
this could happen not only through accidental user input, but
noise on the serial line (noise would still cause other issues,
but at least now it will not "brick" the device).
now the sequence 'ay' is required, as any other command following
'a' would clear the permission again.

note: since ERASE is only setting a GPIO within this command
parsing function, not accidental function pointer problem calling
'board_exec_dbg_cmd' should cause accidental ERASE since it would
need to be called two times with the exact sequence

Change-Id: I06bfeaef09a397bd554bec84321e0dd64ccc3aac
2019-05-23 16:34:29 +00:00
Harald Welte
bb9b0dc8e8 Add freq_ctr app
The freq_ctr app is a small application that is implementing a
simplistic direct-mode frequency counter using the internal 32.768kHz
oscillator and two TC blocks. One of them is used to generate a 1Hz
signal, which is then subsequently used by the other TC to trigger
a counter read after exactly 1s.

This is in itself not something useful on a simtrace2 device.  However,
it is a separate 'app' and I prefer to have the code here in master
over some obscure branch that's easy to forget about.

Change-Id: I2249bfb8dd6a88d85d406f3b33537377133d0939
2019-02-28 20:05:59 +01:00
Harald Welte
b7e326cad3 Add minimal board-support for Olimex SAM3-P256
This is a general purpose evaluation board, and it makes sense to
support it particularly for the DFU bootloader.

Change-Id: I85aea8f1441158f991493c5fc767fdcad405545e
2019-02-28 19:10:07 +01:00
Kévin Redon
2fdcf3b38d cardem: add more debug information for TPDU state
this just adds the name of the TPDU state on top of the state number.

the ISO state is cleaned up accordingly

Change-Id: Id5104a2c3579dedb092c179748e9ed525673841c
2018-10-25 10:42:33 +02:00
Kévin Redon
7e5cda5732 remsim: fix TPDU response size transmission
the TDPU response data size can be up to 256.
this length cannot be stored in a uint8_t, which would cause the
length to become 0, no data being send, and the reader reset the
card because of misbehaviour of the card (i.e. no/malformed
response leading to the timeout of the waiting time).

Change-Id: Iae7671085aaa3115a02d82530dd7a0e7e2d4155e
2018-10-21 12:29:26 +00:00
Kévin Redon
032fc5f844 remsim: update copyright
Change-Id: Ibcf093877ee53f8446c97bfa50c8370ceda24c53
2018-10-21 12:29:10 +00:00
Kévin Redon
b1f99c909c remsim: add already parsed USB path argument info
Change-Id: I03de93ebb92b1d1b5004cbe865cdf1fa0b2b23ac
2018-10-21 12:29:10 +00:00
Martin Hauke
53b4e593aa Fix compiler warning: no-return-in-nonvoid-function simtrace2_usb.c
RPM post-build-checks found some issue and marks these as error:
[   61s] I: Program returns random data in a function
[   61s] E: simtrace2 no-return-in-nonvoid-function simtrace2_usb.c:88

Change-Id: Id16fb7fc4f13176b2b6443af02a5848d8fcfb069
2018-10-13 22:14:06 +00:00
Harald Welte
dc85fbc3e1 libusb_util.c: Avoid gcc warning about strncpy()
What we're doing is actually legal: We copy the full size of the
destination array, and then overwrite the last byte with NUL.  However,
gcc isn't smart enough to see that:

libusb_util.c:162:5: warning: ‘strncpy’ specified bound 20 equals destination size [-Wstringop-truncation]
     strncpy(out[out_idx].path, path, sizeof(out[out_idx].path));
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Let's copy one byte less to make it happy.

Change-Id: I30ddacdc73e5245c7c38b92d1e94e39b13fae7d3
2018-10-12 15:15:08 +02:00
Harald Welte
66ffb6d493 debian/control: Add dependency to libpcsclite-dev
The host utilities use libpcsclite, and the missing build dependency
causes build failures in our nightly OBS builds since commit
faf1e88e48 was merged:

[  131s] cc -o simtrace2-remsim simtrace2-remsim.o apdu_dispatch.o simtrace2-discovery.o libusb_util.o -Wl,-z,relro `pkg-config --libs libusb-1.0 libosmocore` -pthread `pkg-config --libs libosmosim libpcsclite`
[  131s] Package libpcsclite was not found in the pkg-config search path.
[  131s] Perhaps you should add the directory containing `libpcsclite.pc'
[  131s] to the PKG_CONFIG_PATH environment variable
[  131s] No package 'libpcsclite' found

Change-Id: I29adfc629e5e4ffd0bf8b9035ef9138fe7693d96
2018-09-23 16:59:23 +02:00
Kévin Redon
5b5d24ebf3 owhw: set the right simtrace USB ID in usb2udp
Change-Id: I0b54c2eb98b3fad1e2afaf9b81fbe4518b01fbda
2018-09-08 08:22:56 +02:00
Kévin Redon
faf1e88e48 host: clean library dependencies
remsim also needs libpcsclite
`pkg-config --libs libosmocore` and -losmocore are duplicates
`pkg-config --libs libosmosim` is equivalent to -losmosim
pthread it needed (by most applications) for static compilation
LDFLAGS+= allows static compilation when running
LDFLAGS="-static" make

Change-Id: Ic7bd6f2be074d6f652d4f84f4996c8588ea5f851
2018-09-06 23:15:44 +02:00
Kévin Redon
64f69fc4ac owhw: add missing function board_main_top
the board_main_top function was not defined, causing a hard fault
when initializing the board

Change-Id: Ib92003416648822c4115472992850c592bc4047a
2018-09-06 22:52:45 +02:00
Kévin Redon
6303c39a00 owhw: add missing function board_exec_dbg_cmd
the board_exec_dbg_cmd function was not defined, causing a hard
fault on user input

Change-Id: I3ecc1f7bdb2484f5a67c36163d33ebc065e4e709
2018-09-06 22:51:32 +02:00
Kévin Redon
ad0958e9e3 minor: update copyright
Change-Id: Iafcd029be9b3f8cf2e90f08d5e9802912d6a59b1
2018-09-06 22:49:56 +02:00
Kévin Redon
4f3a0356a4 minor: fix typo in comment
Change-Id: I3edb50abe93bc8574c9c1f25b34f75dab2e8f0ce
2018-09-06 22:48:11 +02:00
Kévin Redon
7d5d011095 minor: add checks on configurations and functions
these checks prevent out of bounds access and running
unset function pointers.

Change-Id: Ida889d40b898fc1ab8b885800431833570fdaafe
2018-09-06 22:47:01 +02:00
Kévin Redon
1dbcf62295 qmod: add LED user control
this is used during board testing

Change-Id: I4ccd787f6e307f523821725de158e3c6f1508ee2
2018-09-04 16:15:15 +02:00
Kévin Redon
e5f891a825 EEPROM: fix Wformat compile warning
Change-Id: I86434a46a75f2acc30e20c33edab6dd3f87e052b
2018-09-04 13:31:26 +02:00
Kévin Redon
a6bd7178b5 qmod: output EEPROM data only on debug level, and add completion output
the EEPROM byte output was causing data loss on the serial output,
resulting is automatic tests failing.
instead an end text will be output to detect the end of the procedure.

Change-Id: Ib8d3cbd01d0e34432d424355f4fafb24bc5273a1
2018-09-03 21:11:44 +02:00
Kévin Redon
ba15387b09 DFU: fix Wformat compile warning
Change-Id: I8c422d8a709f8311c40d37e1f1f01dcd3a199b6f
2018-09-03 21:11:44 +02:00
Kévin Redon
c171112994 stdio: fix detection of malformated format strings
the error code returned by vsnprintf was ignored,
resulting in printing the string from a previous print.

Change-Id: I8506b05d56da55d1357a1234917adf341b46e1db
2018-09-03 21:10:58 +02:00
Kévin Redon
29200c6223 stdio: add void 'l' format string qualifier
Wformat requires uint32_t to be used in format string with the 'l'
qualifier (l = long = at least 32 bits).
this qualifier was not handled before.
since on ARM 32-bit int == long we can simply ignore it (stdio
already does not support 64-bit data).

Change-Id: Ib506a66f68712c6b3eeb5129a39abf47ec86a2a7
2018-08-28 19:43:37 +02:00
Kévin Redon
80d9476602 UART: switch baud rate to 921600 bps
the higher baud rate allows for more debugging (without dropping
data) and is well supported by USB for UART adapters (this
standard baud rate is 8 x 115200).
the closest matching integer value is calculated for UART CR.
no floating point calculation can be used since this would
increase the size of the resulting binary by ~ 2kB (for the
softfp). this is not possible for the DFU since it already is
close to the maximum size of 16 kB.

Change-Id: I82b74f697342d580ccb79ada4715f35f4e8cca86
2018-08-28 19:19:10 +02:00
Kévin Redon
e2b0f971e5 set main clock for using UART at 921600 bps
UART baud rate is main clock (MCK) divided by CR*16.
The MCK values are chosen >= 48 MHz and <= 64 MHz to have a near
integer value CR for a baud rate of 921600 bps.
The end MCK frequency between simtrace and qmod differ slightly
but are close to 58 MHz.

Change-Id: Iaa4a97fc68494c93b9d128503515d88049de506c
2018-08-28 19:13:13 +02:00
Harald Welte
e07640c35a tag debian release 0.5.1
Change-Id: Id6559b1019353815eea9f6653b6560e9a8aab23a
2018-08-26 11:51:13 +02:00
Harald Welte
82b628524f simtrace2-sniff: Fix build with released libosmocore versions
There's still no released libosmocore defining the GSMTAP_TYPE_SIM
sub-types (Change-Id: I5bd0dff5a4a90cfe96d9c4f3dec6657e1d85bf7a
dated Jul 26, 2018).

Let's make sure users don't need an unreleased version of the library
if it's only about a few #defines that we can just copy here for
backwards compatibility.

Change-Id: I2fd9e14873711d60f194bb404420bbfbb0a00f48
2018-08-26 11:43:12 +02:00
Harald Welte
cb78b55c26 Revert "debian/control: Depend on libosmocore >= 0.12.1"
This reverts commit 77ff745cca.

libosmocore 0.12.1 is not recent enough, I misread the 'gitk' output.

Change-Id: I87a8e5bbb4aea0c991abe5372f840d76f17378eb
2018-08-26 11:43:11 +02:00
Harald Welte
77ff745cca debian/control: Depend on libosmocore >= 0.12.1
Only this version includes the GSMTAP_SIM_ATR and GSMTAP_SIM_APDU
definitions.

Change-Id: I988cad56aed755af416fc7f23822dcf0229dbb7d
2018-08-26 10:52:46 +02:00
Harald Welte
bd9d94994d v0.5 debian package release
Change-Id: Iaf56c03f966a5dfc8b750d926f0429223aeec54e
2018-08-26 10:37:39 +02:00
Harald Welte
95fac3aeab Add Debian packaging rules
Change-Id: Iece115e4dde87bff5dc36286668f50de0abdcb9e
2018-08-26 10:20:05 +02:00
Harald Welte
c17bf77ecc owhw: Fix cardem GPIO initialization pointer value
This fixes a bug, identified by the below compiler warning:

libboard/owhw/source/owhw.c: In function 'cardsim_gpio_init':
libboard/owhw/source/owhw.c:39:16: warning: passing argument 1 of 'PIO_Configure' from incompatible pointer type [-Wincompatible-pointer-types]
  PIO_Configure(&pins_cardsim, ARRAY_SIZE(pins_cardsim));
                ^
In file included from ./atmel_softpack_libraries/libchip_sam3s/chip.h:45:0,
                 from libboard/owhw/source/owhw.c:20:
./atmel_softpack_libraries/libchip_sam3s/include/pio.h:189:16: note: expected 'const Pin * {aka const struct _Pin *}' but argument is of type 'const Pin (*)[2] {aka const struct _Pin (*)[2]}'
 extern uint8_t PIO_Configure( const Pin *list, uint32_t size ) ;
                ^~~~~~~~~~~~~

Change-Id: I4c1de66c0b8475bb355b1d128f6ec88b2f2a7fcf
2018-08-26 10:20:05 +02:00
Harald Welte
c394109964 firmware: Enable -Wformat and resolve all related compiler warnings
There have been tons of format-string related bugs in our code which
we never discovered due to disabling -Wformat.  Let's fix that.

Change-Id: I5ec466361bcc526fac1f4897673264ee5af3458b
2018-08-26 10:20:05 +02:00
Harald Welte
888f196595 add master Makefile to build firmware and host tools
Change-Id: I715d3fdaff9d80673bb2208ea9d56637f4e459af
2018-08-26 10:20:02 +02:00
Harald Welte
f7f61cd10f Makefiles: Add "make install" target
Change-Id: Ic6835ce55930c60f909e140878c4abab8628e077
2018-08-26 10:09:43 +02:00
Harald Welte
0e95f53588 host: Fix "make clean": remove simtrace2-sniff
Change-Id: Ib233b6a4b3976286196da95036cadcf2d3382f77
2018-08-26 09:54:55 +02:00
Kévin Redon
76ef811a4e jenkins: add simtrace/trace to the builds
trace is now stable enough on simtrace to be built and uploaded.

Change-Id: I157fff9930d03a7ec52ecac4a1be0511ea66c010
2018-08-07 19:01:25 +02:00
Kévin Redon
fecfa2aa51 jenkins: clean after upload
the upload failed because after the firmware were built (make),
they where removed (make clean).
now they are removed only after the upload.

Change-Id: Ie4421a6fa9207eb541107de9c14f265626f6be96
2018-08-07 17:51:48 +02:00
Kévin Redon
c428516efa qmod: error on EEPROM erase fail
repeating the EEPROM erase (byte write) in case of byte write failure
could lead in an infinite loop.
log the error an return error code instead.

Change-Id: Id6f3654d877ca772ba04237da91a6e86e3f441ec
2018-08-07 15:14:37 +00:00
Kévin Redon
37e7861c4d jenkins: fix publish
the script argument was not saved in the publish variable used later
to decide if publishing/uploading is needed.

Change-Id: Ic768a8e96e5e4d72acf3979da1412d683f79ec55
2018-08-07 12:09:49 +02:00
Kévin Redon
ff3d84922d USB: increase USB reset time
USB reset can be signaled by pulling low USB D+ for at least 10 ms,
according to the USB specification. This force a re-enumeration.
This time is increased to 20 ms to work with more USB HUBs.

Some SAM3S based board have external D+ pull-up mechanism (such as
SIMtrace) which needs to be used to pull D+ low.
This is a legacy mechanism from SAM7S history.
This mechanism is not required anymore on the SAM3S, and the qmod
does not use it. When the USB HAL is suspended, the transceiver is
disabled, causing D+ and D- to be pulled low. Then the HAL is activated
again. This is particularly required when DFU is started (and
enumerated), and after flashing the SAM3S switched to the main
application (without reset), so it can properly re-enumerate.

This board difference is now defined on the board header.

Change-Id: I9b58d8101c2fcf5595026b675728826af26127a3
2018-08-07 12:09:49 +02:00
Harald Welte
9547e419eb qmod: Add 'e' command for erasing the EEPROM
Change-Id: Id7cb0db568dd3e9d796829bf0019d63048612998
2018-08-07 10:00:49 +00:00
Kévin Redon
8daba9cc9a gcc: fix warning
moving the define after the header fixes the following warning:
                 from ./atmel_softpack_libraries/libchip_sam3s/source/exceptions.c:46:
libcommon/include/stdio.h:63:12: warning: redundant redeclaration of 'printf_sync' [-Wredundant-decls]
 signed int printf_sync(const char *pFormat, ...);
            ^~~~~~~~~~~
./atmel_softpack_libraries/libchip_sam3s/source/exceptions.c:45:16: note: previous declaration of 'printf_sync' was here
 #define printf printf_sync
                ^~~~~~~~~~~
libcommon/include/stdio.h:51:12: note: in expansion of macro 'printf'
 signed int printf(const char *pFormat, ...);

Change-Id: I21a8de325e8f8b91297dd157f2d6a0f64434bb28
2018-08-06 16:23:33 +02:00
Kévin Redon
d5f583da60 jenkins: add build uploads
firmware binaries should be uploaded to
https://ftp.osmocom.org/binaries/simtrace2/firmware/
this directory wiki be documented in the SIMtrace 2 wiki for users
to get the latest firmware images without having to cross-compile
themselves.

Change-Id: I589531f59e54a0997b012bdd91e3bef9f847f517
2018-08-06 15:57:43 +02:00
Kévin Redon
04ccb770fd remsim: fix USB hanging USB transfer
After a couple of seconds of USB data exchange between remsim and
cardem, the USB transfer hangs.
On host side (remsim) I can see the USB BULK IN request.
On device side (cardem) I see that data has been submitted and
"sent" over USB, but on wireshark with USBmon I don't see the
corresponding USB BULK IN response.
When exiting remsim or just after powering of qmod (causing an
error in remsim) the USB BULK IN is show in wireshark. Thus it
must have been in a buffer, but not read by libusb_bulk_transfer.
By shortening the timeout a new libusb_bulk_transfer is made more
frequently, and the data gets read successfully.

T;his change also fixes the URB data display.

Change-Id: I1d124a41cc90893506933f6d76dc7331e52a74f9
2018-08-04 11:16:15 +02:00
Kévin Redon
910e6830b9 cardem (minor): trace tx data send over USB
Change-Id: I69cef43dd5a78e9f82cc045cdb90c326b03d1f68
2018-08-04 11:16:15 +02:00
Kévin Redon
9cccb2bab5 add libosmcore utilities
osmo_hexdump is particularly useful.
previously it was only defined, but not implemented.
this cause random behaviour upon call, often resulting in
memory corruption.

Change-Id: Ifd9120fa951f41693903fb657d10826959f1599f
2018-08-04 11:16:15 +02:00
Kévin Redon
8a4fba5ea2 cardem: add state name in trace
this helps reading the output while debugging quite a lot

Change-Id: Idf301e09cf14e2412e29dcb252563bc6e4e5c630
2018-08-04 11:16:15 +02:00
Kévin Redon
1b39fd31ee cardem (minor): remove to verbose log trace
Change-Id: Ie43a33af3728c0700f71527ca75d909a9ebd2529
2018-08-04 11:16:15 +02:00
Kévin Redon
0f4abf5eaa cardem: minor typo fix in comment
Change-Id: Ib1dee95e15db1c6bb3b45920d7c1a567e2ba474b
2018-08-04 11:16:15 +02:00
Kévin Redon
1836ac0761 add synchronous UART transmission and use it in exceptions
The default ISR (particularly the HardFault handler) print information,
but this information was not displayed on the console because the UART
IRQ is lower than some default blocking IRQ.
Allowing to set synchronous transfer corrects this.

The underlying Atmel exception library had to be modified to use the
synchronous output.

Making UART_PutChar always synchronous when called from an ISR is not
desired because we use TRACE_ macros is some ISR. The synchronous
output must be set explicitly.

Change-Id: I1b4ace5185cf2dc32684934ed12bf6a8682e9bad
2018-08-04 11:16:13 +02:00
Kévin Redon
dd36d9b010 sniff: send incomplete TPDU when reset is asserted
Change-Id: I8d7e4d604cded535e40d27c2be872268e0f24c20
2018-08-01 10:35:55 +02:00
Kévin Redon
8b8e58b00e cardem: use TC2 as WI and update WT after ATR
Change-Id: I3e51b16d557bc664f87563e1a3dce6642de474d2
2018-07-30 18:19:11 +02:00
Kévin Redon
8f70c3eb1f remsim: fix payload overwriting
The slot number is in the header, and correctly set in st_push_hdr.
Setting the slot in st_slot_tx_msg will overwrite the payload data.
This caused bytes three of the ATR to be changed from 0x96 to 0x00,
corrupting the ATR. This corruption is caught by the ATR checksum,
and the modem would reset the card (2 additional times) to try to
get correct ATR.

Change-Id: If971699993617fc50557d20582c344ea06645a3f
2018-07-30 15:03:55 +02:00
Kévin Redon
ebe672e926 cardem: use TC_ETU to trigger ATR sending
this changes how ATR is handled.
the ATR is also printed when set (as important debug information).
the test is also updated to correspond to the new mechanism (
simulating the timeout before sending the ATR)

Change-Id: I69df797e2feadffa9f5f977cb71b69386cee7cd0
2018-07-30 15:02:35 +02:00
Kévin Redon
d8ebd6ab77 cardem: increase watchdog to 2 seconds
a lot of the procedures are done in ISRs, but the watchdog is only
reset in the main loop.
this causes frequent reset, particularly at the beginning were
states have to the initialized.

Change-Id: Iad364444fca9d18f9a8cf47d5e0840ccd7bac2ef
2018-07-29 09:58:31 +02:00
Kévin Redon
738a04aefb cardem: show detailed reset cause
this helps detecting when a reset was due to the watchdog

Change-Id: I2d59c2f2c8fe9e559eddfafacf25879263ef81ff
2018-07-29 09:58:31 +02:00
Kévin Redon
2a44dc598d sniff: increase debug output
Change-Id: Ife0bbcf4a25aaa445a36768c00004e6e0d9a4947
2018-07-29 09:58:28 +02:00
Kévin Redon
ec396bf402 sniff: fix ATR checksum calculation
this issue also cause the sent ATR to be empty

Change-Id: I6edff7aeb3185c835656acde75886fb6c90c0582
2018-07-28 20:59:44 +02:00
Kévin Redon
697199676e sniff: ensure the checksum error flag is also printed
the firmware now also use a generic value_string array (as does the
host application)

Change-Id: I861bd8b52e8f2f2a4786bbe1cc834917119dc394
2018-07-28 20:59:41 +02:00
Kévin Redon
8e84f8125c sniff: rename reset hold/release to assert/deassert
this change is to match the nomenclature used in cardem

Change-Id: Ide99e731cad26aec949ad14d54f46fa611a0b7f8
2018-07-26 15:34:08 +02:00
Kévin Redon
d1c6536154 sniff: send ATR over GSMTAP
Change-Id: Id35129883f08002a4a796b56954a128e2b533245
2018-07-26 14:51:15 +02:00
Kévin Redon
352809992c USB: print decoded USB error
In case of error it also ensures the returned value is NULL.
Else a segfault would occur because the caller (e.g. remsim)
continued on with a free handler.

Change-Id: Ie7f20e3eff03acf77eb08283747ca8e032b9b4c8
2018-07-24 09:57:23 +02:00
Kévin Redon
a71a6f48cb I2C: return error after failed write
The previous mechanism of retrying a failed write could become a
infinite blocking loop (until watchdog tiemout).

Also the array size is used to know how much data to write and verify
instead of a constant.

Change-Id: I8d2d090c5f4d1195f4c7eb29b3958a7bb05f56ec
2018-07-24 09:54:18 +02:00
Kévin Redon
57b60d23cf I2C: add wait time after write to let EEPROM write
The Atmel AT24C02 defines a maximum tWR waiting time after a byte
write of 5 ms before a next write.
Enforcing this wait time also fixed the failed verification in qmod,
where it was reading 0xffff instead of the written value.

Change-Id: I42c90b8d0329e425f275067e87d584212a43a90b
2018-07-24 09:49:18 +02:00
Kévin Redon
b60538888f cardem: fix USB message parsing
the msg->l2h pointer was not set but used later on, e.g. in
dispatch_usb_command_cardem, case SIMTRACE_MSGT_DT_CEMU_SET_ATR):
>   case SIMTRACE_MSGT_DT_CEMU_SET_ATR:
>   >   atr = (struct cardemu_usb_msg_set_atr *) msg->l2h;
>   >   card_emu_set_atr(ci->ch, atr->atr, atr->atr_len);
l2h is by default 0, thus not pointing to the actual message l2h.
I wonder how cardem worked worked before with this issue though.

Change-Id: Ifbb53dbf478d8dade82251f769e78e1306e77434
2018-07-18 14:06:23 +02:00
Kévin Redon
680bdaba96 cardem: fix typo
Change-Id: Ibeeb01b21a3ccfa74642f13694a20054e920837e
2018-07-18 14:00:57 +02:00
Kévin Redon
f66af0c640 sniff: add checksum verification for ATR and PPS
a checksum error is only signaled in the USB message with the
corresponding flag.

Change-Id: I277868267c3199eea216ab47bdd09fb2fb944b06
2018-07-11 22:33:16 +02:00
Kévin Redon
5f6b8717a4 fix 'ISO_S_IN_ATR not handled' gcc warning
when building the cardem application GCC would output the following warning:
libcommon/source/card_emu.c: In function 'card_emu_process_rx_byte':
libcommon/source/card_emu.c:764:2: warning: enumeration value 'ISO_S_IN_ATR' not handled in switch [-Wswitch]
  switch (ch->state) {
  ^~~~~~

in card emulation the reader should not send data while the card is
sending its ATR.
this is true for other states already handled (RESET, ...). in
these cases an error message is output.
this behaviour is now the default case as data from the reader is
only expected in 3 cases: ISO_S_WAIT_TPDU, ISO_S_IN_TPDU, and
ISO_S_IN_PTS.

Change-Id: Ifbc8dbe1c9f176343304f211c7e6068fb977961e
2018-07-11 22:24:46 +02:00
Kévin Redon
ac0843af83 make adc2uv common
when building the trace app for the simtrace board gcc was outputing
the following error:
libboard/common/source/boardver_adc.c:20:17: warning: 'adc2uv' defined but not used [-Wunused-function]
 static uint32_t adc2uv(uint16_t adc)

adc2uv is used by qmod, and defined in two places:
in boardver_adc.c and mode_cardemu.c.

this change will have adc2uv only defined in boardver_adc.c and make
available in the header to be used by mode_cardemu.c.

Change-Id: I8a772638fa8dd02d8bc8b7631de5af5a22647c55
2018-07-11 22:24:46 +02:00
Kévin Redon
31ed8029b7 host sniff: add functions to print flags
Change-Id: If3c0a4790662bcc64db5ff03adcc033836e16ad0
2018-07-11 22:24:40 +02:00
Kévin Redon
3b7624c120 host sniff: process remaining usb messages in buffer
Change-Id: I1746c0187b2e5dbef44b4b336fee3bd9ded15079
2018-07-11 22:01:58 +02:00
Kévin Redon
f000831d72 sniffer: fix inverted reset meaning
Change-Id: I860e2e29c059e1e0ec126695bb68d489891a17da
2018-07-11 22:01:58 +02:00
Kévin Redon
b37bda0b55 sniffer: only allocate USB message if queue is not too long
When the host does not retrieved the USB messages, they keep getting
queue in the firmware, filling the RAM, and preventing further memory
to be allocated.

Change-Id: I0e447acdf757dcb5dc5c4d8b84a4235866914cad
2018-07-11 22:01:58 +02:00
Kévin Redon
c6b968067d sniffer: also send malformed message over USB
Change-Id: I124c8db1d2f836e185630bbe8b5e52eb085d702a
2018-07-11 22:01:58 +02:00
Kévin Redon
a95bb1e85d minor: fix linker warning
linker warning:
obj/simtrace/dfu_sniffer.o: In function `usb_send_data':
/media/data/work/simtrace2/simtrace2/firmware/libcommon/source/sniffer.c:338: warning: undefined reference to `putchar'

Change-Id: I934f3fcb474d4046e921511a024c3a0b8533c782
2018-07-11 22:01:58 +02:00
Kévin Redon
da5578bd85 sniffer: set LED pattern
The red and green LEDs are now used as follows:
- red on = power (firmware is running)
- red blink = error detected (e.g. during ISO-7816 parsing)
- green on = running (sniffer mode is running)
- green blink = activity (e.g. USB message sent)

Change-Id: Ib1b6ff87fb92d6ed3ecae4bc89386206aaab508e
2018-07-11 22:01:58 +02:00
Kévin Redon
d975411511 LED: add need pattern
new LED pattern: off for 200 ms and then on

Change-Id: Id2c40dc20d75ed6f38b735164ad1eb2860dc480c
2018-07-11 22:01:58 +02:00
Kévin Redon
a2fccba96c sniffer: move reset handling from ISR to main loop
Change-Id: Ia88fb4baf49017524bb201123da3511e5342ba48
2018-07-11 22:01:58 +02:00
Kévin Redon
411428eb5e sniffer: move data print before USB send
when the host software does not retrieve the USB messages the memory
is filled and no new USB messages can be allocated, preventing the
following code to print the message

Change-Id: Ie8946894a84cb853b45555f7abb1ca6f32111425
2018-07-11 22:01:58 +02:00
Kévin Redon
f82f0f6eff USB: add flags for sniff data and centralise transfer
Also fix issue in usb_msg_alloc_hdr and add cosmetic spaces around
operations.

Change-Id: I768a0ad639aa5e648a630af72d01f7b68082b6b6
2018-07-11 22:01:58 +02:00
Kévin Redon
55f0612c8e cosmetic: put spaces around operations
Change-Id: If5ba5f8d16680e8403944274336ea595017063db
2018-07-11 22:01:58 +02:00
Kévin Redon
33d1eb73fd replace leading spaces with tabs
Change-Id: I86783eba0827b58303b10310e9f6b9625e1a27f1
2018-07-11 22:01:58 +02:00
Kévin Redon
93717e43b3 set linux end of line
Change-Id: I5200f0d6f39b0641cac26a4109a3cd33e8474b9b
2018-07-11 22:01:58 +02:00
Kévin Redon
9a12d68c74 firmware: set license to GPLv2+
Change-Id: Id4c00159f984976b6d8641900fb64e36a3a30407
2018-07-11 22:01:58 +02:00
Kévin Redon
efbcf38afb host: set license to GPLv2+
Change-Id: I0948d74874af1d3a0f1b4cbcb4a838e4ecd9fe3f
2018-07-11 22:01:56 +02:00
Kévin Redon
9918c2840e DFU: use central DFU override check
TRACE_INFO will also provide the DFU start reason, but TRACE_INFO
(TRACE_LEVEL >= 4) should only be used for debugging.
WARNING: With TRACE_LEVEL >= 4 the DFU binary is over the maximum of
16 kiB allocated for the DFU bootloader.
Thus make combined will not boot the main application because its
start if after the expecte 16 kiB address; and flashing using DFU
will overwrite the DFU bootloader itself.

Change-Id: I82323e0f76c03f67df7dc8f2b6783166cc25f3aa
2018-07-11 20:48:24 +02:00
Kévin Redon
d24e9bde26 DFU: re-enable UART after testing forced bootloader
The qmod does not have a separate force button as simtrace has.
Instead it check is TX and RX of UART are shorted using PIO.
If the pins are not set back to the UART peripheral, the TRACE/debug
console output will not work anymore.

Change-Id: Id434b49909d6395a2f93a00f39d2d770a5725466
2018-07-07 14:56:50 +02:00
Kévin Redon
2bdaa73aff UART: remove unused code
PutChar already takes care of enabling the IRQ

Change-Id: I63af5eba27c9a6f3e23412060028e817e4d9f233
2018-07-07 14:53:50 +02:00
Kévin Redon
fcf2743552 UART: make IRQ/ISR enabling simpler
Change-Id: Id3742850eb5bac91559e0c2b4144bd7b1ae5b07b
2018-07-07 14:51:35 +02:00
Kévin Redon
d44cb80bc5 DFU: disable configured console UART before starting main app
The DFU uses the UART peripheral (with IRQ/ISR) for the debug output
console. Before starting the main application we should make sure
this configuration is reset to avoid interference (particularly the
IRQ/ISR).
This is not too important though since the main application
reconfigures the UART for console output.
Other peripheral could also be disabled (e.g. all other PIO used
by DFU), but most of them also get configured by the main application.

Change-Id: I8234d1b85938ad6393094c08183f613ad09ee01b
2018-07-07 14:43:50 +02:00
Kévin Redon
9e29a3eb37 DFU: set stack pointer before starting main app
The stack size is fixed. The linker script puts the stack section
after the bss section. The initial stack pointer is not at the
end of the RAM (as often seen).
Thus the initial stack pointer address of the main application
is different than the one from DFU. When starting the main
application the stack pointer needs to be set to the new value.
If this is not done the main application stack may overwrite the
data in bss, even without exceeding the fixed stack size.

Change-Id: Ie354d603fe302d3d5bdfa9c31575411de722323b
2018-07-07 14:18:58 +02:00
Kévin Redon
bf6b1b1a3e buffer: increase buffer size to 512 to cope with fast and long TPDUs
Change-Id: I194c90cf09306a982d80c5bf1222397af6e658a9
2018-07-04 17:55:20 +02:00
King Kévin
4cbdc7cf18 fix LED switching on/off
In the SIMtrace and QMOD schematics the LEDs are connected to +3.3V.
Thus to switch the LED on we need to set the pin low.

Change-Id: Id8cc27e6f0b6556ba5e7ea4d254dd0fe59042a0c
2018-07-04 17:55:20 +02:00
King Kévin
86f48fc962 minor style change: use ARRAY_SIZE
Change-Id: Ia5243c342535963a3800849cd5a7d183a510d2d6
2018-07-04 17:55:20 +02:00
King Kévin
1200a5228f sniffer: add waiting time WT update
the waiting time (WT) is used to detect timeouts (e.g. for
unresponsive card or just to signal an error/NAK). it is essential
to detect to timeout to end current data transfer (e.g. change state).
by default (after a reset) to timeout is 9600 ETU, but this can change
at two places:
- after the ATR using the value of TC2 (if present)
- after a PPS (only F is used, and not D)

because the timeout value can be larger than the 16-bit of the USART
TO register, an external variable needs to be used for the count down.

Change-Id: I9735660ffce161cec8d4e63fa60a66fc8ef57525
2018-07-04 17:55:20 +02:00
Kévin Redon
fe763b7698 sniffing: decrease USB IRQ prioprity to prevent USART overrun
Handling the USB message queue is done in an ISR and take quite some time.
This can cause a USART/SIM sniffing buffer overrun, resulting in data loss.
By setting the USB IRQ lower than the USART IRQ, the USB ISR can be
interrupted (for short) and no data gets lost.

Change-Id: I870a0aa8e251bbb53249c54bfcaa45de5b5a9486
2018-07-04 17:55:20 +02:00
Kévin Redon
c9bd715289 sniffing: fix procedure byte handling and make TPDU parsing more strict
Change-Id: If991152f11c4b864ab1386f21dc13c335e6b281f
2018-07-04 17:55:20 +02:00
Kévin Redon
35e8bdf879 sniffer: also send incomplete (e.g. timeout) data (PPS/ATR/TPDU)
Change-Id: Ib070aca181042b477f1ffec48d63dc56c1e4609a
2018-07-04 17:55:20 +02:00
Kévin Redon
709a431ab9 sniffing: move conversion convertion and flag processing from ISR to main loop to keep ISR fast and focus on data capture
Change-Id: Ieefa8a5f81dbcc12c1ad3059660dbffa0c1a4961
2018-07-04 17:55:20 +02:00
Kévin Redon
30f90a78fc console: drop data to be send when buffer is already full
don't wait for space to be available in the buffer since since would
prevent from processing non-console (e.g. debug) more important data

Change-Id: Ia625b09eb30bb7b43edd3989f697d8ef33200f28
2018-07-04 17:10:08 +02:00
Kévin Redon
7406337a7f sniffer: display F and D values frim PPS
Change-Id: I3641dcb6c24695a6d3dd3a1ee4333f56a07c99f0
2018-07-04 17:10:08 +02:00
Kévin Redon
6e3f1121e6 host USB: add host application to receive and display USB sniffing messages sent by firmware
Change-Id: Idefbf21e0bbd2a1e3647fe9aebaf88d1b62dae2d
2018-07-04 17:10:08 +02:00
Kévin Redon
de97fd25bd sniffer USB: implement USB communication and send parsed messages
Change-Id: Ice7817480705f2124b08c1ff9a8826558b6d8b2b
2018-07-04 17:10:08 +02:00
Kévin Redon
012940f48e USB device: add USB message structure for sniffer communication
Change-Id: Id2c6f32ade2fec9b9ef91bd8c5e1fd195f2d7351
2018-07-04 17:10:08 +02:00
Kévin Redon
e2f84f6a8b host USB: use central SIMtrace USB ID definition header
Change-Id: Id18e64fba0a2c308a8aef7d3865200bf0237cae9
2018-07-04 17:10:08 +02:00
Kévin Redon
4d6a4b949c host usb_util fix: used provided class, sub-class, and interfave when finding matching interfaces
Change-Id: Ibc06e751e6ca0f9e9a40d82c4eeddfb975240f91
2018-07-04 17:10:08 +02:00
Kévin Redon
a1012b170a USB: add central file to define USB IDs, classes, and endpoints
Change-Id: Iba81f32a92c68a973e8e7adbc4c2a1064ba5290f
2018-07-04 17:10:06 +02:00
Kévin Redon
42bd026416 minor: fix typos in comment
Change-Id: I01b49e047a586dff449d4e134751108e391a8822
2018-07-04 16:33:00 +02:00
Kévin Redon
638cec820f sniff: add WT timeout detection using USART timeout (TC is not required)
Change-Id: I4ec6e812e7e1eb91005027d2e864fc315550d79c
2018-07-04 16:33:00 +02:00
Kévin Redon
00ec89d73f sniff: add TPDU parsing (TPDUs become APDUs on the upper layer)
Change-Id: I09d050d95bd2ab140fe6b4926a37278eb08cc347
2018-07-04 16:33:00 +02:00
Kévin Redon
cf59919494 sniff: print parsed ATR and PPS; use red LED to show main application is running; use green LED to indicate activity (message parsed)
Change-Id: I8e906bdbf2c91e608757ae442dfb241f981b8f1e
2018-07-04 16:33:00 +02:00
Kévin Redon
11914d9658 LED: add short LED pulse blinking pattern
Change-Id: I0fdc2f902a3b92da6aa9b9c8500abae8a2f79447
2018-07-04 16:32:54 +02:00
Kévin Redon
3113e3d2e5 update_fidi: remove debug output since this function is called in time critical ISR
Change-Id: I08f407d407a18dae3f360ddc64769ddfaeb5b559
2018-07-04 14:29:28 +02:00
Kévin Redon
9def7631ba DFU: switch green LED on to indicate DFU mode, and red LED to indicate flashing activity
Change-Id: I8e34fd869ed94ad122d6a17f5a432f5a09b820bb
2018-07-04 14:29:28 +02:00
Kévin Redon
ca9e4bf4ba board: fix LED pin definition
Change-Id: Ia6c80c0268dec708845e1dad281caaa42027f9db
2018-07-04 14:29:28 +02:00
Kévin Redon
8210ec3f62 DFU: remove force bootloader button debug message since the console is output message is not initialized yet
Change-Id: Ibea0105929a8dc38b43dacd9d1e576d7b51d0c6a
2018-07-04 14:29:28 +02:00
Kévin Redon
8fa6ff5979 sniffer: use ISR to store sniffed data in buffer, add ATR and PPS parsing, and PPS related FiDi update
Change-Id: I4b38ce1d80e370fda6aa181e959ba3f1286bb922
2018-07-04 14:29:28 +02:00
Kévin Redon
866d20b10e trace: increase watchdog for 500 to 2000 ms to provide more time handling buffered data
Change-Id: Iacd85525f05e692b44183bd4c4585b9e70865cfe
2018-07-04 14:29:28 +02:00
Kévin Redon
4fe99fad59 ISO7816: change update_fidi to use provided USART
Also disables write protection for USART register if required

Change-Id: I716f4bc3a22800cbce402b146f14ef8b2aab2a98
2018-07-04 14:29:28 +02:00
Kévin Redon
7be52ec1ce SIMtrace: enable interrupt on edge dection for SIM_RST pin to reset the sniffer ISO state
Change-Id: I92ff29abd6a8690dd033d8cf13ad0d1ff9740fe5
2018-07-04 14:29:28 +02:00
Kévin Redon
a2b367633c SIMtrace: fix default SIM_RST pin state to allow phone controlled reset
Change-Id: I1942ec6bd499cb2e14f6d7699a2b2d9b4197e654
2018-07-04 14:29:28 +02:00
Kévin Redon
927ffb46eb SIMtrace: only enable main sniffing mode on SIMtrace board
Change-Id: Iff6ebb1d98aa0c31f6d78508afde8f1b05f0f85b
2018-07-04 14:29:28 +02:00
Kévin Redon
d7a6de57d2 sniffer: add state definitions, improve IRQ handling, update pins configuration
Change-Id: I6b5dfd6d573ac122a60585a24c8a620642805ad5
2018-07-04 14:29:27 +02:00
Kévin Redon
353351ddf4 simtrace: add support for sniffing on both USART
Change-Id: I69eb458e7cb186c990e5d6fbc780f37fdd0cd884
2018-07-04 14:28:19 +02:00
Kévin Redon
4091d78c4b board: comment USART definitions and add corresponding IRQ numbers
Change-Id: I3c38e7d75bc7b511827c33af69e335e50d0b35d2
2018-07-04 14:28:19 +02:00
Kévin Redon
ee62a9da56 simtrace: add dedicated power pins configuration for sniffing
Change-Id: Ie37edbae6ea42d2b0c2a30eb5590afd0be797d39
2018-07-04 14:28:17 +02:00
Kévin Redon
45ad62d8d4 sniff: use USART 0 instead of USART 1
Use USART 0 connected to the SIM card side to sniff the communication.
The card side can also measure ETU times.
Do proper pin initialization.
This code can already capture the ATR communication between phone and card.

Change-Id: I0597ec723cb2225540c89c3821b91d8a45adfcd6
2018-07-04 11:24:13 +00:00
Kévin Redon
2c4e2af21f SIMtrace board: comment and fix pin definition
Change-Id: Ic77ad5bf6c00c9122c6bb0e12b90e6c5406855fd
2018-07-04 11:24:13 +00:00
Kévin Redon
7b73462442 sniff mode: handle USART 1 RX interrupt to show sniffer data
Change-Id: I5504369aed39844b7cf21e5b3ccb542daa6b946e
2018-07-04 11:24:13 +00:00
Kévin Redon
36abece0b1 enable (empty) sniffer support for SIMtrace board
Change-Id: I51619135fd6f5423542f261e7d76bab1a5713e2b
2018-07-04 11:24:13 +00:00
Kévin Redon
f9997e9d26 copy working cardem app to trace
because the applications share the board capabilities defined in
libboard/*/include/board.h and USB configurations are enabled according
to the previously defined capabilities in libcommon/source.usb.c, all
applications actually offer the same functions.
thus creating the trace application is only mainly a cosmetic change, as the
sniffer function will also be present and enabled in the cardem application.

Change-Id: I24b3500a0905cbd622507722280b3c7e7f188bde
2018-07-04 11:24:13 +00:00
Harald Welte
05cc7f6531 ringbuffer: Don't print/TRAC from ringbuffer
In commit eac1bec428 we start to use the
ringbuffer inside the console printing code.  As a result, we must not
use TRACE_*() or printf() from within ringbuffer.c code to avoid
infinite recursion.

Instead, let rbuf_write() return a negative return value in case the
ring buffer overflows.  This way, the callers (outside the
console/stdout code) can print an error message themselves.

Change-Id: Ib009f013be119dbad22fa2b7d60ec8dee59baee5
2018-07-04 04:42:22 +02:00
Harald Welte
46893451de echo all command characters entered on serial console
This is required to make python pexpect.fdexpect happy, as it
requires that all characters are echo-ed back in order to detect
when the output of a given command starts.

Change-Id: I73b24e43f6c8b86a2766aba67d8307c184448aa0
2018-07-03 22:30:30 +02:00
196 changed files with 20607 additions and 10731 deletions

563
.clang-format Normal file
View File

@@ -0,0 +1,563 @@
# SPDX-License-Identifier: GPL-2.0
#
# clang-format configuration file. Intended for clang-format >= 4.
#
# For more information, see:
#
# Documentation/process/clang-format.rst
# https://clang.llvm.org/docs/ClangFormat.html
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
#AfterExternBlock: false # Unknown to clang-format-5.0
BeforeCatch: false
BeforeElse: false
IndentBraces: false
#SplitEmptyFunction: true # Unknown to clang-format-4.0
#SplitEmptyRecord: true # Unknown to clang-format-4.0
#SplitEmptyNamespace: true # Unknown to clang-format-4.0
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
#CompactNamespaces: false # Unknown to clang-format-4.0
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
#FixNamespaceComments: false # Unknown to clang-format-4.0
# Taken from:
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
# | sort | uniq
ForEachMacros:
- 'apei_estatus_for_each_section'
- 'ata_for_each_dev'
- 'ata_for_each_link'
- '__ata_qc_for_each'
- 'ata_qc_for_each'
- 'ata_qc_for_each_raw'
- 'ata_qc_for_each_with_internal'
- 'ax25_for_each'
- 'ax25_uid_for_each'
- '__bio_for_each_bvec'
- 'bio_for_each_bvec'
- 'bio_for_each_bvec_all'
- 'bio_for_each_integrity_vec'
- '__bio_for_each_segment'
- 'bio_for_each_segment'
- 'bio_for_each_segment_all'
- 'bio_list_for_each'
- 'bip_for_each_vec'
- 'bitmap_for_each_clear_region'
- 'bitmap_for_each_set_region'
- 'blkg_for_each_descendant_post'
- 'blkg_for_each_descendant_pre'
- 'blk_queue_for_each_rl'
- 'bond_for_each_slave'
- 'bond_for_each_slave_rcu'
- 'bpf_for_each_spilled_reg'
- 'btree_for_each_safe128'
- 'btree_for_each_safe32'
- 'btree_for_each_safe64'
- 'btree_for_each_safel'
- 'card_for_each_dev'
- 'cgroup_taskset_for_each'
- 'cgroup_taskset_for_each_leader'
- 'cpufreq_for_each_entry'
- 'cpufreq_for_each_entry_idx'
- 'cpufreq_for_each_valid_entry'
- 'cpufreq_for_each_valid_entry_idx'
- 'css_for_each_child'
- 'css_for_each_descendant_post'
- 'css_for_each_descendant_pre'
- 'device_for_each_child_node'
- 'displayid_iter_for_each'
- 'dma_fence_chain_for_each'
- 'do_for_each_ftrace_op'
- 'drm_atomic_crtc_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane_state'
- 'drm_atomic_for_each_plane_damage'
- 'drm_client_for_each_connector_iter'
- 'drm_client_for_each_modeset'
- 'drm_connector_for_each_possible_encoder'
- 'drm_for_each_bridge_in_chain'
- 'drm_for_each_connector_iter'
- 'drm_for_each_crtc'
- 'drm_for_each_crtc_reverse'
- 'drm_for_each_encoder'
- 'drm_for_each_encoder_mask'
- 'drm_for_each_fb'
- 'drm_for_each_legacy_plane'
- 'drm_for_each_plane'
- 'drm_for_each_plane_mask'
- 'drm_for_each_privobj'
- 'drm_mm_for_each_hole'
- 'drm_mm_for_each_node'
- 'drm_mm_for_each_node_in_range'
- 'drm_mm_for_each_node_safe'
- 'flow_action_for_each'
- 'for_each_acpi_dev_match'
- 'for_each_active_dev_scope'
- 'for_each_active_drhd_unit'
- 'for_each_active_iommu'
- 'for_each_aggr_pgid'
- 'for_each_available_child_of_node'
- 'for_each_bio'
- 'for_each_board_func_rsrc'
- 'for_each_bvec'
- 'for_each_card_auxs'
- 'for_each_card_auxs_safe'
- 'for_each_card_components'
- 'for_each_card_dapms'
- 'for_each_card_pre_auxs'
- 'for_each_card_prelinks'
- 'for_each_card_rtds'
- 'for_each_card_rtds_safe'
- 'for_each_card_widgets'
- 'for_each_card_widgets_safe'
- 'for_each_cgroup_storage_type'
- 'for_each_child_of_node'
- 'for_each_clear_bit'
- 'for_each_clear_bit_from'
- 'for_each_cmsghdr'
- 'for_each_compatible_node'
- 'for_each_component_dais'
- 'for_each_component_dais_safe'
- 'for_each_comp_order'
- 'for_each_console'
- 'for_each_cpu'
- 'for_each_cpu_and'
- 'for_each_cpu_not'
- 'for_each_cpu_wrap'
- 'for_each_dapm_widgets'
- 'for_each_dev_addr'
- 'for_each_dev_scope'
- 'for_each_dma_cap_mask'
- 'for_each_dpcm_be'
- 'for_each_dpcm_be_rollback'
- 'for_each_dpcm_be_safe'
- 'for_each_dpcm_fe'
- 'for_each_drhd_unit'
- 'for_each_dss_dev'
- 'for_each_dtpm_table'
- 'for_each_efi_memory_desc'
- 'for_each_efi_memory_desc_in_map'
- 'for_each_element'
- 'for_each_element_extid'
- 'for_each_element_id'
- 'for_each_endpoint_of_node'
- 'for_each_evictable_lru'
- 'for_each_fib6_node_rt_rcu'
- 'for_each_fib6_walker_rt'
- 'for_each_free_mem_pfn_range_in_zone'
- 'for_each_free_mem_pfn_range_in_zone_from'
- 'for_each_free_mem_range'
- 'for_each_free_mem_range_reverse'
- 'for_each_func_rsrc'
- 'for_each_hstate'
- 'for_each_if'
- 'for_each_iommu'
- 'for_each_ip_tunnel_rcu'
- 'for_each_irq_nr'
- 'for_each_link_codecs'
- 'for_each_link_cpus'
- 'for_each_link_platforms'
- 'for_each_lru'
- 'for_each_matching_node'
- 'for_each_matching_node_and_match'
- 'for_each_member'
- 'for_each_memcg_cache_index'
- 'for_each_mem_pfn_range'
- '__for_each_mem_range'
- 'for_each_mem_range'
- '__for_each_mem_range_rev'
- 'for_each_mem_range_rev'
- 'for_each_mem_region'
- 'for_each_migratetype_order'
- 'for_each_msi_entry'
- 'for_each_msi_entry_safe'
- 'for_each_msi_vector'
- 'for_each_net'
- 'for_each_net_continue_reverse'
- 'for_each_netdev'
- 'for_each_netdev_continue'
- 'for_each_netdev_continue_rcu'
- 'for_each_netdev_continue_reverse'
- 'for_each_netdev_feature'
- 'for_each_netdev_in_bond_rcu'
- 'for_each_netdev_rcu'
- 'for_each_netdev_reverse'
- 'for_each_netdev_safe'
- 'for_each_net_rcu'
- 'for_each_new_connector_in_state'
- 'for_each_new_crtc_in_state'
- 'for_each_new_mst_mgr_in_state'
- 'for_each_new_plane_in_state'
- 'for_each_new_private_obj_in_state'
- 'for_each_node'
- 'for_each_node_by_name'
- 'for_each_node_by_type'
- 'for_each_node_mask'
- 'for_each_node_state'
- 'for_each_node_with_cpus'
- 'for_each_node_with_property'
- 'for_each_nonreserved_multicast_dest_pgid'
- 'for_each_of_allnodes'
- 'for_each_of_allnodes_from'
- 'for_each_of_cpu_node'
- 'for_each_of_pci_range'
- 'for_each_old_connector_in_state'
- 'for_each_old_crtc_in_state'
- 'for_each_old_mst_mgr_in_state'
- 'for_each_oldnew_connector_in_state'
- 'for_each_oldnew_crtc_in_state'
- 'for_each_oldnew_mst_mgr_in_state'
- 'for_each_oldnew_plane_in_state'
- 'for_each_oldnew_plane_in_state_reverse'
- 'for_each_oldnew_private_obj_in_state'
- 'for_each_old_plane_in_state'
- 'for_each_old_private_obj_in_state'
- 'for_each_online_cpu'
- 'for_each_online_node'
- 'for_each_online_pgdat'
- 'for_each_pci_bridge'
- 'for_each_pci_dev'
- 'for_each_pci_msi_entry'
- 'for_each_pcm_streams'
- 'for_each_physmem_range'
- 'for_each_populated_zone'
- 'for_each_possible_cpu'
- 'for_each_present_cpu'
- 'for_each_prime_number'
- 'for_each_prime_number_from'
- 'for_each_process'
- 'for_each_process_thread'
- 'for_each_prop_codec_conf'
- 'for_each_prop_dai_codec'
- 'for_each_prop_dai_cpu'
- 'for_each_prop_dlc_codecs'
- 'for_each_prop_dlc_cpus'
- 'for_each_prop_dlc_platforms'
- 'for_each_property_of_node'
- 'for_each_registered_fb'
- 'for_each_requested_gpio'
- 'for_each_requested_gpio_in_range'
- 'for_each_reserved_mem_range'
- 'for_each_reserved_mem_region'
- 'for_each_rtd_codec_dais'
- 'for_each_rtd_components'
- 'for_each_rtd_cpu_dais'
- 'for_each_rtd_dais'
- 'for_each_set_bit'
- 'for_each_set_bit_from'
- 'for_each_set_clump8'
- 'for_each_sg'
- 'for_each_sg_dma_page'
- 'for_each_sg_page'
- 'for_each_sgtable_dma_page'
- 'for_each_sgtable_dma_sg'
- 'for_each_sgtable_page'
- 'for_each_sgtable_sg'
- 'for_each_sibling_event'
- 'for_each_subelement'
- 'for_each_subelement_extid'
- 'for_each_subelement_id'
- '__for_each_thread'
- 'for_each_thread'
- 'for_each_unicast_dest_pgid'
- 'for_each_vsi'
- 'for_each_wakeup_source'
- 'for_each_zone'
- 'for_each_zone_zonelist'
- 'for_each_zone_zonelist_nodemask'
- 'fwnode_for_each_available_child_node'
- 'fwnode_for_each_child_node'
- 'fwnode_graph_for_each_endpoint'
- 'gadget_for_each_ep'
- 'genradix_for_each'
- 'genradix_for_each_from'
- 'hash_for_each'
- 'hash_for_each_possible'
- 'hash_for_each_possible_rcu'
- 'hash_for_each_possible_rcu_notrace'
- 'hash_for_each_possible_safe'
- 'hash_for_each_rcu'
- 'hash_for_each_safe'
- 'hctx_for_each_ctx'
- 'hlist_bl_for_each_entry'
- 'hlist_bl_for_each_entry_rcu'
- 'hlist_bl_for_each_entry_safe'
- 'hlist_for_each'
- 'hlist_for_each_entry'
- 'hlist_for_each_entry_continue'
- 'hlist_for_each_entry_continue_rcu'
- 'hlist_for_each_entry_continue_rcu_bh'
- 'hlist_for_each_entry_from'
- 'hlist_for_each_entry_from_rcu'
- 'hlist_for_each_entry_rcu'
- 'hlist_for_each_entry_rcu_bh'
- 'hlist_for_each_entry_rcu_notrace'
- 'hlist_for_each_entry_safe'
- 'hlist_for_each_entry_srcu'
- '__hlist_for_each_rcu'
- 'hlist_for_each_safe'
- 'hlist_nulls_for_each_entry'
- 'hlist_nulls_for_each_entry_from'
- 'hlist_nulls_for_each_entry_rcu'
- 'hlist_nulls_for_each_entry_safe'
- 'i3c_bus_for_each_i2cdev'
- 'i3c_bus_for_each_i3cdev'
- 'ide_host_for_each_port'
- 'ide_port_for_each_dev'
- 'ide_port_for_each_present_dev'
- 'idr_for_each_entry'
- 'idr_for_each_entry_continue'
- 'idr_for_each_entry_continue_ul'
- 'idr_for_each_entry_ul'
- 'in_dev_for_each_ifa_rcu'
- 'in_dev_for_each_ifa_rtnl'
- 'inet_bind_bucket_for_each'
- 'inet_lhash2_for_each_icsk_rcu'
- 'key_for_each'
- 'key_for_each_safe'
- 'klp_for_each_func'
- 'klp_for_each_func_safe'
- 'klp_for_each_func_static'
- 'klp_for_each_object'
- 'klp_for_each_object_safe'
- 'klp_for_each_object_static'
- 'kunit_suite_for_each_test_case'
- 'kvm_for_each_memslot'
- 'kvm_for_each_vcpu'
- 'list_for_each'
- 'list_for_each_codec'
- 'list_for_each_codec_safe'
- 'list_for_each_continue'
- 'list_for_each_entry'
- 'list_for_each_entry_continue'
- 'list_for_each_entry_continue_rcu'
- 'list_for_each_entry_continue_reverse'
- 'list_for_each_entry_from'
- 'list_for_each_entry_from_rcu'
- 'list_for_each_entry_from_reverse'
- 'list_for_each_entry_lockless'
- 'list_for_each_entry_rcu'
- 'list_for_each_entry_reverse'
- 'list_for_each_entry_safe'
- 'list_for_each_entry_safe_continue'
- 'list_for_each_entry_safe_from'
- 'list_for_each_entry_safe_reverse'
- 'list_for_each_entry_srcu'
- 'list_for_each_prev'
- 'list_for_each_prev_safe'
- 'list_for_each_safe'
- 'llist_for_each'
- 'llist_for_each_entry'
- 'llist_for_each_entry_safe'
- 'llist_for_each_safe'
- 'mci_for_each_dimm'
- 'media_device_for_each_entity'
- 'media_device_for_each_intf'
- 'media_device_for_each_link'
- 'media_device_for_each_pad'
- 'nanddev_io_for_each_page'
- 'netdev_for_each_lower_dev'
- 'netdev_for_each_lower_private'
- 'netdev_for_each_lower_private_rcu'
- 'netdev_for_each_mc_addr'
- 'netdev_for_each_uc_addr'
- 'netdev_for_each_upper_dev_rcu'
- 'netdev_hw_addr_list_for_each'
- 'nft_rule_for_each_expr'
- 'nla_for_each_attr'
- 'nla_for_each_nested'
- 'nlmsg_for_each_attr'
- 'nlmsg_for_each_msg'
- 'nr_neigh_for_each'
- 'nr_neigh_for_each_safe'
- 'nr_node_for_each'
- 'nr_node_for_each_safe'
- 'of_for_each_phandle'
- 'of_property_for_each_string'
- 'of_property_for_each_u32'
- 'pci_bus_for_each_resource'
- 'pcl_for_each_chunk'
- 'pcl_for_each_segment'
- 'pcm_for_each_format'
- 'ping_portaddr_for_each_entry'
- 'plist_for_each'
- 'plist_for_each_continue'
- 'plist_for_each_entry'
- 'plist_for_each_entry_continue'
- 'plist_for_each_entry_safe'
- 'plist_for_each_safe'
- 'pnp_for_each_card'
- 'pnp_for_each_dev'
- 'protocol_for_each_card'
- 'protocol_for_each_dev'
- 'queue_for_each_hw_ctx'
- 'radix_tree_for_each_slot'
- 'radix_tree_for_each_tagged'
- 'rb_for_each'
- 'rbtree_postorder_for_each_entry_safe'
- 'rdma_for_each_block'
- 'rdma_for_each_port'
- 'rdma_umem_for_each_dma_block'
- 'resource_list_for_each_entry'
- 'resource_list_for_each_entry_safe'
- 'rhl_for_each_entry_rcu'
- 'rhl_for_each_rcu'
- 'rht_for_each'
- 'rht_for_each_entry'
- 'rht_for_each_entry_from'
- 'rht_for_each_entry_rcu'
- 'rht_for_each_entry_rcu_from'
- 'rht_for_each_entry_safe'
- 'rht_for_each_from'
- 'rht_for_each_rcu'
- 'rht_for_each_rcu_from'
- '__rq_for_each_bio'
- 'rq_for_each_bvec'
- 'rq_for_each_segment'
- 'scsi_for_each_prot_sg'
- 'scsi_for_each_sg'
- 'sctp_for_each_hentry'
- 'sctp_skb_for_each'
- 'shdma_for_each_chan'
- '__shost_for_each_device'
- 'shost_for_each_device'
- 'sk_for_each'
- 'sk_for_each_bound'
- 'sk_for_each_entry_offset_rcu'
- 'sk_for_each_from'
- 'sk_for_each_rcu'
- 'sk_for_each_safe'
- 'sk_nulls_for_each'
- 'sk_nulls_for_each_from'
- 'sk_nulls_for_each_rcu'
- 'snd_array_for_each'
- 'snd_pcm_group_for_each_entry'
- 'snd_soc_dapm_widget_for_each_path'
- 'snd_soc_dapm_widget_for_each_path_safe'
- 'snd_soc_dapm_widget_for_each_sink_path'
- 'snd_soc_dapm_widget_for_each_source_path'
- 'tb_property_for_each'
- 'tcf_exts_for_each_action'
- 'udp_portaddr_for_each_entry'
- 'udp_portaddr_for_each_entry_rcu'
- 'usb_hub_for_each_child'
- 'v4l2_device_for_each_subdev'
- 'v4l2_m2m_for_each_dst_buf'
- 'v4l2_m2m_for_each_dst_buf_safe'
- 'v4l2_m2m_for_each_src_buf'
- 'v4l2_m2m_for_each_src_buf_safe'
- 'virtio_device_for_each_vq'
- 'while_for_each_ftrace_op'
- 'xa_for_each'
- 'xa_for_each_marked'
- 'xa_for_each_range'
- 'xa_for_each_start'
- 'xas_for_each'
- 'xas_for_each_conflict'
- 'xas_for_each_marked'
- 'xbc_array_for_each_value'
- 'xbc_for_each_key_value'
- 'xbc_node_for_each_array_value'
- 'xbc_node_for_each_child'
- 'xbc_node_for_each_key_value'
- 'zorro_for_each_dev'
- 'for_each_line'
- 'for_each_non_empty_line'
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
IncludeCategories:
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
#IndentPPDirectives: None # Unknown to clang-format-5.0
IndentWidth: 8
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
# Taken from git's rules
#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: false
SortIncludes: false
#SortUsingDeclarations: false # Unknown to clang-format-4.0
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
SpaceBeforeParens: ControlStatements
#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 8
UseTab: Always
...

6
.gitignore vendored
View File

@@ -18,6 +18,8 @@ tags
*.bin *.bin
*.p *.p
host/simtrace2-list host/simtrace2-list
host/simtrace2-remsim host/simtrace2-cardem-pcsc
host/simtrace2-remsim-usb2udp host/contrib/simtrace2.spec
usb_strings_generated.h usb_strings_generated.h
firmware/usbstring/usbstring
firmware/apps/*/usb_strings.txt.patched

3
.gitreview Normal file
View File

@@ -0,0 +1,3 @@
[gerrit]
host=gerrit.osmocom.org
project=simtrace2

42
Makefile Normal file
View File

@@ -0,0 +1,42 @@
all: fw utils
define RULES
fw-$(1)-$(2):
make -C firmware BOARD=$(1) APP=$(2)
fw-$(1)-$(2)-clean:
make -C firmware BOARD=$(1) APP=$(2) clean
endef
$(eval $(call RULES,simtrace,dfu))
$(eval $(call RULES,simtrace,blupdate))
$(eval $(call RULES,simtrace,trace))
$(eval $(call RULES,simtrace,cardem))
$(eval $(call RULES,qmod,dfu))
$(eval $(call RULES,qmod,blupdate))
$(eval $(call RULES,qmod,cardem))
$(eval $(call RULES,ngff_cardem,dfu))
$(eval $(call RULES,ngff_cardem,blupdate))
$(eval $(call RULES,ngff_cardem,trace))
$(eval $(call RULES,ngff_cardem,cardem))
fw-clean: fw-simtrace-dfu-clean fw-simtrace-blupdate-clean fw-simtrace-trace-clean fw-simtrace-cardem-clean \
fw-qmod-dfu-clean fw-qmod-blupdate-clean fw-qmod-cardem-clean \
fw-ngff_cardem-dfu-clean fw-ngff_cardem-blupdate-clean fw-ngff_cardem-trace-clean fw-ngff_cardem-cardem-clean
fw: fw-simtrace-dfu fw-simtrace-blupdate fw-simtrace-trace fw-simtrace-cardem \
fw-qmod-dfu fw-qmod-blupdate fw-qmod-cardem \
fw-ngff_cardem-dfu fw-ngff_cardem-blupdate fw-ngff_cardem-trace fw-ngff_cardem-cardem
utils:
(cd host && \
autoreconf -fi && \
./configure --prefix=/usr --disable-werror && \
make)
clean: fw-clean
if [ -e host/Makefile ]; then \
make -C host clean; \
fi
install:
make -C firmware install
make -C host install

View File

@@ -5,9 +5,6 @@ This is the repository for the next-generation SIMtrace devices,
providing abilities to trace the communication between (U)SIM card and providing abilities to trace the communication between (U)SIM card and
phone, remote (U)SIM card forward, (U)SIM man-in-the-middle, and more. phone, remote (U)SIM card forward, (U)SIM man-in-the-middle, and more.
This is under heavy development, and right now it is not surprising if
things still break on a daily basis.
NOTE: Nothing in this repository applies to the SIMtrace v1.x hardware NOTE: Nothing in this repository applies to the SIMtrace v1.x hardware
or its associated firmware. SIMtrace v1.x is based on a different CPU / or its associated firmware. SIMtrace v1.x is based on a different CPU /
microcontroller architecture and uses a completely different software microcontroller architecture and uses a completely different software
@@ -16,12 +13,6 @@ stack and host software.
Supported Hardware Supported Hardware
------------------ ------------------
At this point, the primary development target is still the OWHW + sysmoQMOD
device, but we expect to add support for a SAM3 based SIMtrace hardware
board soon.
The goal is to support the following devices:
* Osmocom SIMtrace 1.x with SAM3 controller * Osmocom SIMtrace 1.x with SAM3 controller
** this is open hardware and schematics / PCB design is published ** this is open hardware and schematics / PCB design is published
* sysmocom sysmoQMOD (with 4 Modems, 4 SIM slots and 2 SAM3) * sysmocom sysmoQMOD (with 4 Modems, 4 SIM slots and 2 SAM3)
@@ -37,3 +28,11 @@ This repository contains several directory
* firmware - the firmware to run on the actual devices * firmware - the firmware to run on the actual devices
* hardware - some information related to the hardware * hardware - some information related to the hardware
* host - Programs to use on the USB host to interface with the hardware * host - Programs to use on the USB host to interface with the hardware
The host software includes
* libosmo-simtrace2 - a shared library to talk to devices running the simtrace2 firmware
* simtrace2-list - list any USB-attached devices running simtrace2 firmware
* simtrace2-sniff - interface the 'trace' firmware to obtain card protocol traces
* simtrace2-cardem-pcsc - interface the 'cardem' fimrware to use a SIM in a PC/SC reader

10
TODO-RELEASE Normal file
View File

@@ -0,0 +1,10 @@
# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
# LIBVERSION=c:r:a
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:0.
# If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
simtrace2 API/ABI change osmo_st2_transport new member

164
contrib/flash.py Executable file
View File

@@ -0,0 +1,164 @@
#!/usr/bin/env python
# encoding: utf-8
# python: 3.8.1
# library to enumerate USB devices
import usb.core
from usb.util import *
# more elegant structure
from typing import NamedTuple
# regular expressions utilities
import re
# open utilities to handle files
import os, sys
# to download the firmwares
import urllib.request
# to flash using DFU-util
import subprocess
# SIMtrace 2 device information
class Device(NamedTuple):
usb_vendor_id: int
usb_product_id: int
name: str
url: dict # 1: sniff/trace firmware, 2: card emulation firmware
# SIMtrace 2 devices definitions
DEVICE_SIMTRACE = Device(usb_vendor_id=0x1d50, usb_product_id=0x60e3, name="SIMtrace 2", url={"trace": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/simtrace-trace-dfu-latest.bin", "cardem": "https://osmocom.org/attachments/download/3868/simtrace-cardem-dfu.bin"})
DEVICE_QMOD = Device(usb_vendor_id=0x1d50, usb_product_id=0x4004, name="sysmoQMOD (Quad Modem)", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/qmod-cardem-dfu-latest.bin"})
DEVICE_OWHW = Device(usb_vendor_id=0x1d50, usb_product_id=0x4001, name="OWHW", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/owhw-cardem-dfu-latest.bin"})
DEVICE_OCTSIMTEST = Device(usb_vendor_id=0x1d50, usb_product_id=0x616d, name="OCTSIMTEST", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/octsimtest-cardem-dfu-latest.bin"})
DEVICE_NGFF_CARDEM = Device(usb_vendor_id=0x1d50, usb_product_id=0x616e, name="ngff-cardem", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/ngff_cardem-cardem-dfu-latest.bin"})
DEVICES = [DEVICE_SIMTRACE, DEVICE_QMOD, DEVICE_OCTSIMTEST, DEVICE_NGFF_CARDEM]
# which firmware does the SIMtrace USN interface subclass correspond
FIRMWARE_SUBCLASS = {1: "trace", 2: "cardem"}
def print_help():
print("this script will flash SIMtrace 2 - based devices")
print("when no argument is provided, it will try to flash the application firmware of all SIMtrace 2 devices connected to USB with the latest version")
print("to flash a specific firmware, provide the name as argument")
print("the possible firmwares are: trace, cardem")
print("to list all devices connected to USB, provide the argument \"list\"")
# the firmware to flash
to_flash = None
# parse command line argument
if len(sys.argv) == 2:
to_flash = sys.argv[1]
if to_flash not in ["list", "trace", "cardem"] and len(sys.argv) > 1:
print_help()
exit(0)
# get all USB devices
devices = []
devices_nb = 0
updated_nb = 0
usb_devices = usb.core.find(find_all=True)
for usb_device in usb_devices:
# find SIMtrace devices
definitions = list(filter(lambda x: x.usb_vendor_id == usb_device.idVendor and x.usb_product_id == usb_device.idProduct, DEVICES))
if 1 != len(definitions):
continue
devices_nb += 1
definition = definitions[0]
serial = usb_device.serial_number or "unknown"
usb_path = str(usb_device.bus) + "-" + ".".join(map(str, usb_device.port_numbers))
print("found " + definition.name + " device (chip ID " + serial + ") at USB path " + usb_path)
# determine if we are running DFU (in most cases the bootloader, but could also be the application)
dfu_interface = None
for configuration in usb_device:
# get DFU interface descriptor
dfu_interface = dfu_interface or find_descriptor(configuration, bInterfaceClass=254, bInterfaceSubClass=1)
if (None == dfu_interface):
print("no DFU USB interface found")
continue
dfu_mode = (2 == dfu_interface.bInterfaceProtocol) # InterfaceProtocol 1 is runtime mode, 2 is DFU mode
# determine firmware type (when not in DFU mode)
firmware = None
simtrace_interface = None
for configuration in usb_device:
simtrace_interface = simtrace_interface or find_descriptor(configuration, bInterfaceClass=255)
if simtrace_interface and simtrace_interface.bInterfaceSubClass in FIRMWARE_SUBCLASS:
firmware = firmware or FIRMWARE_SUBCLASS[simtrace_interface.bInterfaceSubClass]
if dfu_mode:
firmware = 'dfu'
if firmware:
print("installed firmware: " + firmware)
else:
print("unknown installed firmware")
continue
# determine version of the application/bootloader firmware
version = None
version_interface = None
for configuration in usb_device:
# get custom interface with string
version_interface = version_interface or find_descriptor(configuration, bInterfaceClass=255, bInterfaceSubClass=255)
if version_interface and version_interface.iInterface and version_interface.iInterface > 0 and get_string(usb_device, version_interface.iInterface):
version = get_string(usb_device, version_interface.iInterface)
if not version:
# the USB serial is set (in the application) since version 0.5.1.34-e026 from 2019-08-06
# https://git.osmocom.org/simtrace2/commit/?id=e0265462d8c05ebfa133db2039c2fbe3ebbd286e
# the USB serial is set (in the bootloader) since version 0.5.1.45-ac7e from 2019-11-18
# https://git.osmocom.org/simtrace2/commit/?id=5db9402a5f346e30288db228157f71c29aefce5a
# the firmware version is set (in the application) since version 0.5.1.37-ede8 from 2019-08-13
# https://git.osmocom.org/simtrace2/commit/?id=ede87e067dadd07119f24e96261b66ac92b3af6f
# the firmware version is set (in the bootloader) since version 0.5.1.45-ac7e from 2019-11-18
# https://git.osmocom.org/simtrace2/commit/?id=5db9402a5f346e30288db228157f71c29aefce5a
if dfu_mode:
if serial:
version = "< 0.5.1.45-ac7e"
else:
versoin = "< 0.5.1.45-ac7e"
else:
if serial:
version = "< 0.5.1.37-ede8"
else:
versoin = "< 0.5.1.34-e026"
print("device firmware version: " + version)
# flash latest firmware
if to_flash == "list": # we just want to list the devices, not flash them
continue
# check the firmware exists
if firmware == "dfu" and to_flash is None:
print("device is currently in DFU mode. you need to specify which firmware to flash")
continue
to_flash = to_flash or firmware
if to_flash not in definition.url.keys():
print("no firmware image available for " + firmware + " firmware")
continue
# download firmware
try:
dl_path, header = urllib.request.urlretrieve(definition.url[to_flash])
except:
print("could not download firmware " + definition.url[to_flash])
continue
dl_file = open(dl_path, "rb")
dl_data = dl_file.read()
dl_file.close()
# compare versions
dl_version = re.search(b'firmware \d+\.\d+\.\d+\.\d+-[0-9a-fA-F]{4}', dl_data)
if dl_version is None:
print("could not get version from downloaded firmware image")
os.remove(dl_path)
continue
dl_version = dl_version.group(0).decode("utf-8").split(" ")[1]
print("latest firmware version: " + dl_version)
versions = list(map(lambda x: int(x), version.split(" ")[-1].split("-")[0].split(".")))
dl_versions = list(map(lambda x: int(x), dl_version.split("-")[0].split(".")))
dl_newer = (versions[0] < dl_versions[0] or (versions[0] == dl_versions[0] and versions[1] < dl_versions[1]) or (versions[0] == dl_versions[0] and versions[1] == dl_versions[1] and versions[2] < dl_versions[2]) or (versions[0] == dl_versions[0] and versions[1] == dl_versions[1] and versions[2] == dl_versions[2] and versions[3] < dl_versions[3]))
if not dl_newer:
print("no need to flash latest version")
os.remove(dl_path)
continue
print("flashing latest version")
dfu_result = subprocess.run(["dfu-util", "--device", hex(definition.usb_vendor_id) + ":" + hex(definition.usb_product_id), "--path", usb_path, "--cfg", "1", "--alt", "1", "--reset", "--download", dl_path])
os.remove(dl_path)
if 0 != dfu_result.returncode:
printf("flashing firmware using dfu-util failed. ensure dfu-util is installed and you have the permissions to access this USB device")
continue
updated_nb += 1
print(str(devices_nb)+ " SIMtrace 2 device(s) found")
print(str(updated_nb)+ " SIMtrace 2 device(s) updated")

View File

@@ -9,6 +9,7 @@ fi
set -e set -e
publish="$1"
base="$PWD" base="$PWD"
deps="$base/deps" deps="$base/deps"
inst="$deps/install" inst="$deps/install"
@@ -20,13 +21,18 @@ mkdir "$deps" || true
osmo-build-dep.sh libosmocore "" '--disable-doxygen --enable-gnutls' osmo-build-dep.sh libosmocore "" '--disable-doxygen --enable-gnutls'
# verify only after building the dependency (to ensure we have most recent source of dependency)
verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH" export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="$inst/lib" export LD_LIBRARY_PATH="$inst/lib"
BUILDS="" BUILDS=""
BUILDS+="simtrace/dfu simtrace/cardem " # simtrace/trace simtrace/triple_play BUILDS+="simtrace/dfu simtrace/blupdate simtrace/trace simtrace/cardem "
BUILDS+="qmod/dfu qmod/cardem " BUILDS+="qmod/dfu qmod/blupdate qmod/cardem "
BUILDS+="owhw/dfu owhw/cardem " BUILDS+="owhw/dfu owhw/blupdate owhw/cardem "
BUILDS+="octsimtest/cardem "
BUILDS+="ngff_cardem/dfu ngff_cardem/blupdate ngff_cardem/cardem ngff_cardem/trace "
cd $TOPDIR/firmware cd $TOPDIR/firmware
for build in $BUILDS; do for build in $BUILDS; do
@@ -35,7 +41,6 @@ for build in $BUILDS; do
echo echo
echo "=============== $board / $app START ==============" echo "=============== $board / $app START =============="
make BOARD="$board" APP="$app" make BOARD="$board" APP="$app"
make BOARD="$board" APP="$app" clean
echo "=============== $board / $app RES:$? ==============" echo "=============== $board / $app RES:$? =============="
done done
@@ -50,8 +55,42 @@ make clean
echo echo
echo "=============== HOST START ==============" echo "=============== HOST START =============="
cd $TOPDIR/host cd $TOPDIR/host
make clean autoreconf --install --force
make ./configure --enable-sanitize --enable-werror
make clean $MAKE $PARALLEL_MAKE
#$MAKE distcheck || cat-testlogs.sh
make dist
#if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
# make -C "$base/doc/manuals" publish
#fi
if [ "x$publish" = "x--publish" ]; then
echo
echo "=============== UPLOAD BUILD =============="
$TOPDIR/contrib/prepare_upload.sh
cat > "/build/known_hosts" <<EOF
[ftp.osmocom.org]:48 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDgQ9HntlpWNmh953a2Gc8NysKE4orOatVT1wQkyzhARnfYUerRuwyNr1GqMyBKdSI9amYVBXJIOUFcpV81niA7zQRUs66bpIMkE9/rHxBd81SkorEPOIS84W4vm3SZtuNqa+fADcqe88Hcb0ZdTzjKILuwi19gzrQyME2knHY71EOETe9Yow5RD2hTIpB5ecNxI0LUKDq+Ii8HfBvndPBIr0BWYDugckQ3Bocf+yn/tn2/GZieFEyFpBGF/MnLbAAfUKIdeyFRX7ufaiWWz5yKAfEhtziqdAGZaXNaLG6gkpy3EixOAy6ZXuTAk3b3Y0FUmDjhOHllbPmTOcKMry9
[ftp.osmocom.org]:48 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPdWn1kEousXuKsZ+qJEZTt/NSeASxCrUfNDW3LWtH+d8Ust7ZuKp/vuyG+5pe5pwpPOgFu7TjN+0lVjYJVXH54=
[ftp.osmocom.org]:48 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8iivY70EiR5NiGChV39gRLjNpC8lvu1ZdHtdMw2zuX
EOF
SSH_COMMAND="ssh -o 'UserKnownHostsFile=/build/known_hosts' -p 48"
rsync --archive --verbose --compress --delete --rsh "$SSH_COMMAND" $TOPDIR/firmware/bin/*-latest.{bin,elf} binaries@ftp.osmocom.org:web-files/simtrace2/firmware/latest/
rsync --archive --verbose --compress --rsh "$SSH_COMMAND" --exclude $TOPDIR/firmware/bin/*-latest.{bin,elf} $TOPDIR/firmware/bin/*-*-*-*.{bin,elf} binaries@ftp.osmocom.org:web-files/simtrace2/firmware/all/
fi
echo
echo "=============== HOST CLEAN =============="
$MAKE maintainer-clean
echo
echo "=============== FIRMWARE CLEAN =============="
cd $TOPDIR/firmware/
for build in $BUILDS; do
board=`echo $build | cut -d "/" -f 1`
app=`echo $build | cut -d "/" -f 2`
make BOARD="$board" APP="$app" clean
done
osmo-clean-workspace.sh osmo-clean-workspace.sh

16
contrib/prepare_upload.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/sh -e
# Create copies of binaries with -latest, -$GIT_VERSION (OS#4413, OS#3452)
cd "$(dirname "$0")/.."
GIT_VERSION="$(./git-version-gen .tarball-version)"
echo "Copying binaries with "-latest" and "-$GIT_VERSION" appended..."
cd firmware/bin
for ext in bin elf; do
for file in *."$ext"; do
without_ext="${file%.*}"
cp -v "$file" "$without_ext-latest.$ext"
cp -v "$file" "$without_ext-$GIT_VERSION.$ext"
done
done

92
contrib/simtrace.lua Normal file
View File

@@ -0,0 +1,92 @@
usb_simtrace_protocol = Proto("USB_simtrace", "USB simtrace protocol")
local control_commands = {
-- /* SIMTRACE_MSGC_GENERIC */
[0x0000] = "SIMTRACE_CMD_DO_ERROR",
[0x0001] = "SIMTRACE_CMD_BD_BOARD_INFO",
-- /* SIMTRACE_MSGC_CARDEM */
[0x0101] = "SIMTRACE_MSGT_DT_CEMU_TX_DATA",
[0x0102] = "SIMTRACE_MSGT_DT_CEMU_SET_ATR",
[0x0103] = "SIMTRACE_MSGT_BD_CEMU_STATS",
[0x0104] = "SIMTRACE_MSGT_BD_CEMU_STATUS",
[0x0105] = "SIMTRACE_MSGT_DT_CEMU_CARDINSERT",
[0x0106] = "SIMTRACE_MSGT_DO_CEMU_RX_DATA",
[0x0107] = "SIMTRACE_MSGT_DO_CEMU_PTS",
[0x0108] = "SIMTRACE_MSGT_BD_CEMU_CONFIG",
-- /* SIMTRACE_MSGC_MODEM */
[0x0201] = "SIMTRACE_MSGT_DT_MODEM_RESET",
[0x0202] = "SIMTRACE_MSGT_DT_MODEM_SIM_SELECT",
[0x0203] = "SIMTRACE_MSGT_BD_MODEM_STATUS",
-- /* SIMTRACE_MSGC_SNIFF */
[0x0300] = "SIMTRACE_MSGT_SNIFF_CHANGE",
[0x0301] = "SIMTRACE_MSGT_SNIFF_FIDI",
[0x0302] = "SIMTRACE_MSGT_SNIFF_ATR",
[0x0304] = "SIMTRACE_MSGT_SNIFF_TPDU",
[0x0303] = "SIMTRACE_MSGT_SNIFF_PPS"
}
local msgtype = ProtoField.uint16("usb_simtrace.msgtype", "Message Type", base.HEX_DEC, control_commands)
local seqnr = ProtoField.uint8("usb_simtrace.seqnr", "Sequence Number", base.HEX_DEC)
local slotnr = ProtoField.uint8("usb_simtrace.slotnr", "Slot Number", base.HEX_DEC)
local reserved = ProtoField.uint16("usb_simtrace.reserved", "reserved", base.HEX_DEC)
local payloadlen = ProtoField.uint16("usb_simtrace.length", "length", base.HEX_DEC)
local payload = ProtoField.bytes("usb_simtrace.payload", "Data")
local pb_and_rx = ProtoField.uint32("usb_simtrace.pb_and_rx", "pb_and_rx", base.HEX_DEC, NULL, 0x8)
local pb_and_tx = ProtoField.uint32("usb_simtrace.pb_and_tx", "pb_and_tx", base.HEX_DEC, NULL, 0x4)
local final = ProtoField.uint32("usb_simtrace.final", "final", base.HEX_DEC, NULL, 0x2)
local tpdu_hdr = ProtoField.uint32("usb_simtrace.tpdu_hdr", "tpdu_hdr", base.HEX_DEC, NULL, 0x1)
local rxtxdatalen = ProtoField.uint16("usb_simtrace.rxtxdatalen", "rx/tx data length", base.HEX_DEC)
local rxtxdata = ProtoField.bytes("usb_simtrace.rxtxdata", "rx/tx (data)")
usb_simtrace_protocol.fields = {
msgtype, seqnr, slotnr, reserved, payloadlen, payload, pb_and_rx, pb_and_tx, final, tpdu_hdr, rxtxdatalen, rxtxdata
}
function dissect_rxtx(payload_data,pinfo,tree)
local headerSubtree = tree:add(usb_simtrace_protocol, payload_data, "rx/tx data")
local len = payload_data(8+4,2):le_uint();
local cmd32 = payload_data(8+0,4):le_uint();
headerSubtree:add(pb_and_rx, cmd32)
headerSubtree:add(pb_and_tx, cmd32)
headerSubtree:add(final, cmd32)
headerSubtree:add(tpdu_hdr, cmd32)
headerSubtree:add(rxtxdatalen, len)
headerSubtree:add_le(rxtxdata, payload_data(8+6,len))
end
function usb_simtrace_protocol.dissector(buffer, pinfo, tree)
length = buffer:len()
if length == 0 then return end
pinfo.cols.protocol = usb_simtrace_protocol.name
local subtree = tree:add(usb_simtrace_protocol, buffer(), "USB simtrace Data")
local command = buffer(0,2):uint()
subtree:add(msgtype, command):set_generated()
subtree:add(seqnr, buffer(2,1))
subtree:add(slotnr, buffer(3,1))
subtree:add_le(payloadlen, buffer(6,2))
pinfo.cols.info = string.format("Cmd 0x%04X : %s", command, control_commands[command])
local payload_data = buffer(8,length-8)
if(command == 0x0101 or command == 0x0106) then
return dissect_rxtx(buffer(),pinfo,subtree)
else
subtree:add(payload, payload_data)
end
end
function usb_simtrace_protocol.init()
local usb_product_dissectors = DissectorTable.get("usb.product")
usb_product_dissectors:add(0x1d50616d, usb_simtrace_protocol)
usb_product_dissectors:add(0x1d50616e, usb_simtrace_protocol)
DissectorTable.get("usb.bulk"):add(0xffff, usb_simtrace_protocol)
end

226
debian/changelog vendored Normal file
View File

@@ -0,0 +1,226 @@
simtrace2 (0.8.2) unstable; urgency=medium
* firmware/Makefile: don't use distribution's CFLAGS
-- Oliver Smith <osmith@sysmocom.de> Fri, 15 Sep 2023 11:17:37 +0200
simtrace2 (0.8.1) unstable; urgency=medium
* host/contrib/simtrace2.spec.in: fix soname
-- Oliver Smith <osmith@sysmocom.de> Fri, 10 Dec 2021 10:04:28 +0100
simtrace2 (0.8.0) unstable; urgency=medium
[ Harald Welte ]
* adapt to host tools in autotools
* simtrace2_api: Remove dead code
* fix baudrate of 'make log'
* qmod DFU: Don't overwrite memory beyond end of usb_strings[]
* usb_strings.txt: s/SIMtrace Phone/SIMtrace Card Emulation/
* Patch actual board name into the USB iProduct string descriptor
* Build only 'reasonable' combinations of APP/MEMORY
* stdio: Add support for %p format string (pointer address)
* Fix format string related warnings (int vs. long)
* Add missing CR to achieve CRLF at end of log lines
* more comments in host_communication.c.
* usb_buf: count number of elements in queue
* usb_buf: Limit the maximum queue length to 3 elements
* qmod: Don't print EEPROM operations in help when not supported
* cosmetic: board_qmod: Annotate #endif with comments
* qmod: Document '!' and '@' commands on UART
* implement minimalistic talloc_report(); add 't' command on UART
* update copyright statement
* cardem: Fix memory leak on unsupported SIMTRACE_MSGT_DT_CEMU_CARDINSERT
* usb_buf: Actually limit queue to 3 elements, not 4
* USBD_HAL: Don't disable UDP peripheral clock on suspend
* usb_buf: Properly initialize buffered_endpoint->ep number
* pseudo_talloc: Increment number of buffers from 10 to 20
* card_emu: Factor out card_handle_reset() from card_emu_init()
* cardem: Move card_emu_io_statechg() calls out of interrupt context
* cardem: RST resets all state (including release of buffers)
* host_communication: Send zero-length-packet on wMaxPacketSize
* card_emu: Initialize PTSS state every time we start PTS
* card_emu: Avoid recursive calls to card_set_state()
* card_emu: Always print state names in string representation
* card_emu: Remove extraneous code
* card_emu: Remove extraneous initialization of ch->pts.state
* cardem: Make card_emu_report_status() optionally use IRQ endpoint
* cardem: Add SIMTRACE_MSGT_BD_CEMU_CONFIG
* cardem: Implement support for CEMU_FEAT_F_STATUS_IRQ
* simtrace2-sniff: Reformat value_string to pass our validation scripts
* firmware: Reformat value_string to pass our validation scripts
* jenkins.sh: Add verify_value_string_arrays_are_terminated.py
* [lib] apdu_dispatch: Use DLGLOBAL and don't printf() directly
* [lib] apdu_dispatch: Don't print APDU state to stdout
* OSMO_ASSERT() on double-free or invalid pointer
* Update .gitignore file for host
* migrate to libosmousb
* library: Add osmo_st2_compatible_dev_idsp[]
* firmware: move printing of welcome banner to common function print_banner()
* firmware: apps/cardem/main.c: Synchronize with apps/trace/main.c
* host: Add COPYING file for host software (GPLv2)
* host/lib/gsmtap.c: Add GPLv2 disclaimer
* increase ringbuffer size from 512 to 1024 bytes
* simtrace2_api: Add osmo_st2_cardem_request_config()
* Disable interrupts during EEFC_ReadUniqueID()
* cardem: Fix infinite loop + watchdog reset on long OUT message
* extend osmo_st2_cardem_inst with fields required by osmo-remsim
* cosmetic: Add missing CR to LF in dispatch_received_usb_msg()
* USBD.c: Don't reset EP0 on SetConfiguration(0)
* pio_it.c: Permit repeated calls to PIO_ConfigureIt()
* simtrace2_siff: getopt_long() returns int, not char
* Introduce support for asynchronous USB transmission
* firmware: fix builds with gcc stack smashing protection enabled
* dfu: Shrink code by 144 bytes (by not calling PIO_InitializeInterrupts)
* dfu: Save another 60 bytes by changing the way we print horizontal lines
* migrate from BSC_FD_* to OSMO_FD_*
* remove usb2udp
* rename simtrace2-remsim to simtrace2-cardem-pcsc
* Update README
* remove old pre-autoconf makefile
* simtrace2-cardem-pcsc: Make it work again
* Revert "add ISO 7816-3 library to remsim project"
* Revert "add library providing ISO 7816-3 utilities"
* card_emu: waiting_time is stored in etu, not clocks.
* card_emu: Rename fi to Fi and di to Di
* card_emu: Clarify and differentiate F/Fi/F_index/Fi_index
* iso7816_fidi: Add iso7816_3_ prefix to symbols; fix terminology
* card_emu: improve reset detection conditions
* card_emu: explicitly initialize PTS and TPDU states
* card_emu: Use USART timeout for waiting time
* card_emu: Fix USART timer, particularly in re-start situations
* card_emu: Fix computation of waiting time
* contrib/jenkins.sh: Switch from rita -> ftp.osmocom.org
* st2-cardem-pcsc: Fix goto-in-while mess
* st2-cardem-pcsc: Use ATR of real card by default
* simtrace board.h: Enable HAVE_CARDEM if we build the cardem firmware
* jenkins.sh: build 'cardem' firmware also for simtrace board
* Revert "cardem: disable upload for simtrace2"
* simtrace2-cardem-pcsc: Decode STATUS flags to strings
* simtrace2-cardem-pcsc: Reset the real card if reader resets cardem
* assert: Use printf_sync() to ensure printing of assert / panic
* Add usb product ID of sysmoOCTSIMTEST
* octsimtest: remove lots of unused #defines
* octsimtest: most code for support of this new board
* octsimtest: Switch direction of I/O level shifter depending on uart tx / rx
* cardem-pcsc: initialize libosmocore logging
* octsimtest: Adjust VCC voltage thresholds (resistive VCC divider)
* contrib/jenkins.sh: Build 'cardem' app for 'octsimtest' board
* firmware: octsimtest: Fix IO_DIR pin definition
* firmware: octsimtest: Make slot mux configurable via USB
* firmware: octsimtest: mcp23017 initializaiton
* firmware: cardem: re-factor CARDINSERT command processing
* firmware: octsimtest: Support SIMTRACE_MSGT_DT_CEMU_CARDINSERT
* firmware: octsimtest: use TRACE_* macros instead of direct printf
* firmware: octsimtest: Fix disabling the card_insert signal
* firmware: octsimtest: Add i/I command for setting card-insert via I2C GPIO
* firmware: octsimtest: ensure all card_insert GPIO are 0 after reset
* don't printf() directly from library code, go via libosmocore logging
* simtrace2-list: Use osmo_st2_compatible_dev_ids[]
* board_gpio.gnumeric: Add ngff-cardem pin-out
* 99-simtrace2.rules: Add OCTSIMTEST
* contrib/flash.py: Add OCTSIMTEST support
* Introduce simtrace2-tool
* introduce support for new ngff_cardem board
* simtrace2.spec: Add simtrace2-tool binary to package
* contrib/jenkins.sh: Build APP=cardem for BOARD=ngff_cardem
* jenkins.sh: Build 'trace' firmware for ngff_cardem
* Use osmo_libusb_{init,exit}() instead of libusb_{init,exit}()
* simtrace2-cardem-pcsc: Remove double libusb initialization
* simtrace2-tool: Initialize logging to avoid error on first log output
* cardem-pcsc: Fix return of uninitialized variable
* host: Upgrade libosmocore dependency to 1.4.0
[ Kévin Redon ]
* minor: fix spacing
* minor: updated copyright years
* dfu: minor: make debug output only verbose in info level
* minor: move USB debug output from info to debug level
* minor: improve debug output
* minor : fix typo in comment
* better detect VCC and nRST changes on simtrace2 board
* minor: ignore usbstring binary
* simtrace2-remsim: Use simplest ATR
* cardem: use simplest ATR as default ATR
* minor: fix typo
* DFU: increase USB reset duration to 50 ms
* DFU: restart bootloader when USB conf failed
* Makefile: add linker option showing memory usage
* improve shared bootloader/application memory
* minor: improve trace output
* DFU: add DFU application
* add script to flash latest firmware
* minor: use same LED pattern for cardem as other applications
* cardem: currently simtrace does not support cardem
* add library providing ISO 7816-3 utilities
* add ISO 7816-3 library to remsim project
* rename PIN_PHONE_{CLK,IO} to PIN_USIM1_{CLK,IO}
* minor add comments
* make sim switch board specific
[ Eric Wild ]
* remsim: allow selecting pcsc reader number
* cardem: disable upload for simtrace2
* firmware: do not allow undefined symbols
* firmware: allow verbose builds
* cardem: choose a more reasonable default ATR
* contrib: add a basic simtrace lua dissector for wireshark
* cardem: free the buf
* cardemu: support 1v8 for the tester
* firmware: data sections
* firmware: proper makefile deps
* firmware: make the ngff beakout blink
* simtrace2-cardem: use local sim on exit
* contrib: more cardem dissection
* firmware: trace for ngff
* cardem: fix spurious NULL bytes during transfers
* contrib/jenkins.sh: build ngff_Cardem dfu bootloader
* contrib: allow manually forcing bulk simtrace dissection
* contrib/jenkins.sh: lower trace to make bl fit
* Revert "firmware: data sections"
* add the ngff cardem to default build targets
* drop unused exidx sections when linking
* clang build support
* fix bootloader led config crash
* firmware: add bootloader update "app"
* firmware: remove usb pullup that dates back to simtrace1
* firmware: increase reset delay before usb reattach
* firmware: drop cref printing
* add our default clang-format file
* firmware: add missing usb strings to blupdate that prevented building it
* jenkins: build bootloader updater
* firmware: remove dfu-dfu default target
[ Oliver Smith ]
* contrib: import RPM spec
* contrib: integrate RPM spec
* d/source/format: new file
* firmware/Makefile: fix UNKNOWN in OBS packages
* host: use git-version-gen/tarball-v. from topdir
* gitignore: add firmware/apps/*/usb_strings.txt.patched
* firmware: create duplicate files for upload only
* contrib/prepare_upload.sh: fix cd problems
* firmware: qmod-dfu: disable stack protector
* firmware: disable stack protector by default
* gitreview: new file
[ Leonard Hübner ]
* remsim: adding cli argument to set the atr
[ Eric ]
* dfu: let the device reset itself
-- Harald Welte <laforge@osmocom.org> Thu, 09 Dec 2021 08:12:56 +0100
simtrace2 (0.5.1) unstable; urgency=medium
* Backwards-compatibility with older (released, non-master) libosmocore
-- Harald Welte <lafore@gnumonks.org> Sun, 26 Aug 2018 11:50:36 +0200
simtrace2 (0.5) unstable; urgency=medium
* Initial debian package release.
-- Harald Welte <lafore@gnumonks.org> Sun, 26 Aug 2018 10:37:19 +0200

1
debian/compat vendored Normal file
View File

@@ -0,0 +1 @@
9

65
debian/control vendored Normal file
View File

@@ -0,0 +1,65 @@
Source: simtrace2
Maintainer: Harald Welte <laforge@gnumonks.org>
Section: devel
Priority: optional
Build-Depends: debhelper (>= 9),
autotools-dev,
autoconf,
automake,
libtool,
pkg-config,
git,
dh-autoreconf,
libosmocore-dev (>= 1.4.0),
libpcsclite-dev,
libnewlib-arm-none-eabi,
libusb-1.0-0-dev,
gcc-arm-none-eabi
Standards-Version: 3.9.8
Vcs-Git: git://git.osmocom.org/simtrace2.git
Vcs-Browser: http://git.osmocom.org/simtrace2/
Homepage: http://osmocom.org/projects/simtrace2/wiki
Package: simtrace2-firmware
Section: devel
Architecture: all
Recommends: dfu-util
Description: Firmware for SAM3 based SIMtrace2 USB Devices.
Open Source firmware for the Cortex-M3 microcontroller in the
"Osmocom SIMtrace2" USB-attached peripheral device. Will only work in
SAM3S-based SIMtrace2, not in its SAM7S-based predecessor SIMtrace!
Package: simtrace2-utils
Section: devel
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends}, ${misc:Depends}, libosmo-simtrace2-1
Recommends: simtrace2-firmware
Description: Host utilities to communicate with SIMtrace2 USB Devices.
Package: libosmo-simtrace2-1
Section: libs
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Osmocom SIMtrace2 library
This library contains core "driver" functionality to interface with the
Osmocom SIMtrace2 (and compatible) USB device firmware. It enables
applications to implement SIM card / smart card tracing as well as
SIM / smart card emulation functions.
Package: libosmo-simtrace2-dev
Section: libdevel
Architecture: any
Multi-Arch: same
Depends: libosmo-simtrace2-1, ${misc:Depends}
Description: Development headers for Osmocom SIMtrace2 library
This library contains core "driver" functionality to interface with the
Osmocom SIMtrace2 (and compatible) USB device firmware. It enables
applications to implement SIM card / smart card tracing as well as
SIM / smart card emulation functions.
.
The header files provided by this package may be used to develop
with any of the libosmocore libraries.
.
Also static libraries are installed with this package.

1
debian/libosmo-simtrace2-1.install vendored Normal file
View File

@@ -0,0 +1 @@
usr/lib/libosmo-simtrace2*.so.*

5
debian/libosmo-simtrace2-dev.install vendored Normal file
View File

@@ -0,0 +1,5 @@
usr/include/*
usr/lib/lib*.a
usr/lib/lib*.so
usr/lib/lib*.la
usr/lib/pkgconfig/*

19
debian/rules vendored Executable file
View File

@@ -0,0 +1,19 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
DEBIAN := $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2)
DEBVERS := $(shell echo '$(DEBIAN)' | cut -d- -f1)
VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/[+-].*//' -e 's/~//g')
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
export DEB_LDFLAGS_MAINT_STRIP = -Wl,-Bsymbolic-functions
%:
dh $@
override_dh_autoreconf:
cd host && dh_autoreconf

1
debian/simtrace2-firmware.install vendored Normal file
View File

@@ -0,0 +1 @@
usr/share/simtrace2/*.bin

1
debian/simtrace2-utils.install vendored Normal file
View File

@@ -0,0 +1 @@
usr/bin/simtrace2-*

1
debian/source/format vendored Normal file
View File

@@ -0,0 +1 @@
3.0 (native)

View File

@@ -28,22 +28,41 @@
# Makefile for compiling the Getting Started with SAM3S Microcontrollers project # Makefile for compiling the Getting Started with SAM3S Microcontrollers project
GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarball-version)
CFLAGS = \
-Werror=format-security \
-Wformat \
-g \
$(NULL)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# User-modifiable options # User-modifiable options
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# verbosity
V ?= 0
ifneq ("$(V)","0")
SILENT :=
else
SILENT := @
endif
# Chip & board used for compilation # Chip & board used for compilation
# (can be overriden by adding CHIP=chip and BOARD=board to the command-line) # (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
CHIP ?= sam3s4 CHIP ?= sam3s4
BOARD ?= qmod BOARD ?= qmod
# Defines which are the available memory targets for the SAM3S-EK board.
MEMORIES ?= flash dfu
# Output file basename
APP ?= dfu APP ?= dfu
# Output directories # Defines which are the available memory targets for the SAM3S-EK board.
ifeq ($(APP), dfu)
MEMORIES ?= flash
TRACE_LEVEL ?= 0
else
MEMORIES ?= dfu
endif
# Output directories and filename
OUTPUT = $(BOARD)-$(APP) OUTPUT = $(BOARD)-$(APP)
BIN = bin BIN = bin
OBJ = obj/$(BOARD) OBJ = obj/$(BOARD)
@@ -61,19 +80,26 @@ AT91LIB_USB_DFU_PATH = $(AT91LIB)/usb/device/dfu
# Tool suffix when cross-compiling # Tool suffix when cross-compiling
CROSS_COMPILE = arm-none-eabi- CROSS_COMPILE = arm-none-eabi-
LIBS = -Wl,--start-group -lgcc -Wl,--end-group -nostdlib USE_CLANG ?= 0
ifneq ("$(USE_CLANG)","0")
# Compilation tools # --target=thumbv7m-none-eabi
CC = clang
LD = ld.lld
SIZE = llvm-size
LIBS = -nostdlib
else
CC = $(CROSS_COMPILE)gcc CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld LD = $(CROSS_COMPILE)ld
SIZE = $(CROSS_COMPILE)size SIZE = $(CROSS_COMPILE)size
LIBS = -Wl,--start-group -lgcc -Wl,--end-group -nostdlib
endif
STRIP = $(CROSS_COMPILE)strip STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy OBJCOPY = $(CROSS_COMPILE)objcopy
GDB = $(CROSS_COMPILE)gdb GDB = $(CROSS_COMPILE)gdb
NM = $(CROSS_COMPILE)nm NM = $(CROSS_COMPILE)nm
TOP=.. TOP=..
GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarvers)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Files # Files
@@ -97,10 +123,11 @@ C_LIBCHIP = $(notdir $(wildcard $(AT91LIB)/libchip_sam3s/source/*.c) $(wildcard
C_LIBUSB = USBDescriptors.c USBRequests.c USBD.c USBDCallbacks.c USBDDriver.c USBDDriverCallbacks.c C_LIBUSB = USBDescriptors.c USBRequests.c USBD.c USBDCallbacks.c USBDDriver.c USBDDriverCallbacks.c
C_LIBUSB_RT = dfu.c dfu_runtime.c C_LIBUSB_RT = dfu.c dfu_runtime.c
C_LIBUSB_DFU = dfu.c dfu_desc.c dfu_driver.c C_LIBUSB_DFU = dfu.c dfu_desc.c dfu_driver.c
C_LIBCOMMON = string.c stdio.c fputs.c usb_buf.c ringbuffer.c pseudo_talloc.c host_communication.c C_LIBCOMMON = string.c stdio.c fputs.c usb_buf.c ringbuffer.c pseudo_talloc.c host_communication.c \
main_common.c stack_check.c
C_BOARD = $(notdir $(wildcard libboard/common/source/*.c)) C_BOARD = $(notdir $(wildcard libboard/common/source/*.c))
C_BOARD += $(notdir $(wildcard libboard/$(BOARD)/source/*.c)) C_BOARD += $(notdir $(wildcard libboard/$(BOARD)/source/*.c))
C_APPLEVEL = $(notdir $(wildcard apps/$(APP)/*.c)) C_APPLEVEL = $(notdir $(wildcard apps/$(APP)/*.c))
@@ -120,14 +147,18 @@ C_OBJECTS = $(C_FILES:%.c=%.o)
# TRACE_LEVEL_NO_TRACE 0 # TRACE_LEVEL_NO_TRACE 0
TRACE_LEVEL ?= 4 TRACE_LEVEL ?= 4
DEBUG_PHONE_SNIFF?=0 # allow asserting the peer SAM3S ERASE signal to completely erase the flash
# only applicable for qmod board
ALLOW_PEER_ERASE?=0
#CFLAGS+=-DUSB_NO_DEBUG=1 #CFLAGS+=-DUSB_NO_DEBUG=1
# Optimization level, put in comment for debugging # Optimization level, put in comment for debugging
ifneq ("$(USE_CLANG)","0")
OPTIMIZATION ?= -Oz
else
OPTIMIZATION ?= -Os OPTIMIZATION ?= -Os
endif
# Flags # Flags
INCLUDES_USB = -I$(AT91LIB)/usb/include -I$(AT91LIB) INCLUDES_USB = -I$(AT91LIB)/usb/include -I$(AT91LIB)
@@ -141,46 +172,60 @@ INCLUDES += -Ilibosmocore/include
INCLUDES += -Isrc_simtrace -Iinclude INCLUDES += -Isrc_simtrace -Iinclude
INCLUDES += -Iapps/$(APP) INCLUDES += -Iapps/$(APP)
CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wimplicit-int #-Wformat=2 ifneq ("$(USE_CLANG)","0")
CFLAGS += -Wno-unknown-warning-option -Wno-empty-body -fno-exceptions -fno-unwind-tables --config armv7em_soft_nofp_nosys
else
CFLAGS += -Wno-suggest-attribute=noreturn --param max-inline-insns-single=500
endif
CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wimplicit-int -Wformat=2
CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses
CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs #-Wunused CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs #-Wunused
CFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal #-Wundef CFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal #-Wundef
CFLAGS += -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings CFLAGS += -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings
CFLAGS += -Waggregate-return #-Wsign-compare CFLAGS += -Waggregate-return #-Wsign-compare
CFLAGS += -Wformat=0
CFLAGS += -Wmissing-format-attribute -Wno-deprecated-declarations CFLAGS += -Wmissing-format-attribute -Wno-deprecated-declarations
CFLAGS += #-Wpacked CFLAGS += #-Wpacked
CFLAGS += -Wredundant-decls -Wnested-externs #-Winline -Wlong-long CFLAGS += -Wredundant-decls -Wnested-externs #-Winline -Wlong-long
CFLAGS += -Wunreachable-code CFLAGS += -Wunreachable-code
#CFLAGS += -Wcast-align #CFLAGS += -Wcast-align
#CFLAGS += -std=c11 #CFLAGS += -std=c11
CFLAGS += -Wmissing-noreturn #CFLAGS += -Wmissing-noreturn
#CFLAGS += -Wconversion #CFLAGS += -Wconversion
CFLAGS += -Wno-unused-but-set-variable -Wno-unused-variable CFLAGS += -Wno-unused-but-set-variable -Wno-unused-variable
CFLAGS += -Wno-suggest-attribute=noreturn
# -mlong-calls -Wall # -mlong-calls -Wall
#CFLAGS += -save-temps -fverbose-asm #CFLAGS += -save-temps -fverbose-asm
#CFLAGS += -Wa,-a,-ad #CFLAGS += -Wa,-a,-ad
CFLAGS += -D__ARM CFLAGS += -D__ARM -fno-builtin
CFLAGS += --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb # -mfix-cortex-m3-ldrd CFLAGS += -mcpu=cortex-m3 -mthumb # -mfix-cortex-m3-ldrd
CFLAGS += -ffunction-sections -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_LEVEL=$(TRACE_LEVEL) -DDEBUG_PHONE_SNIFF=$(DEBUG_PHONE_SNIFF) CFLAGS += -ffunction-sections -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_LEVEL=$(TRACE_LEVEL) -DALLOW_PEER_ERASE=$(ALLOW_PEER_ERASE)
CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
CFLAGS += -DBOARD=\"$(BOARD)\" -DBOARD_$(BOARD) CFLAGS += -DBOARD=\"$(BOARD)\" -DBOARD_$(BOARD)
CFLAGS += -DAPPLICATION=\"$(APP)\" -DAPPLICATION_$(APP) CFLAGS += -DAPPLICATION=\"$(APP)\" -DAPPLICATION_$(APP)
# Disable stack protector by default (OS#5081)
ifeq ($(STACK_PROTECTOR), 1)
CFLAGS += -fstack-protector
else
CFLAGS += -fno-stack-protector
endif
ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -D__ASSEMBLY__ ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -D__ASSEMBLY__
LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=ResetException -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols $(LIB) LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=ResetException -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--no-undefined $(LIB)
ifeq ("$(USE_CLANG)","0")
LDFLAGS += -Wl,--warn-section-align -Wl,--print-memory-usage
endif
#LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats #LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats
# Append BIN directories to output filename
# Append OBJ and BIN directories to output filename
OUTPUT := $(BIN)/$(OUTPUT) OUTPUT := $(BIN)/$(OUTPUT)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Rules # Rules
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
all: apps/$(APP)/usb_strings_generated.h $(BIN) $(OBJ) $(MEMORIES) all: $(BIN) $(OBJ) $(MEMORIES)
combined: $(OUTPUT)-combined.bin combined: $(OUTPUT)-combined.bin
@@ -191,46 +236,77 @@ $(BIN)/$(BOARD)-dfu-flash-padded.bin: $(BIN)/$(BOARD)-dfu-flash.bin
$(OUTPUT)-combined.bin: $(BIN)/$(BOARD)-dfu-flash-padded.bin $(OUTPUT)-dfu.bin $(OUTPUT)-combined.bin: $(BIN)/$(BOARD)-dfu-flash-padded.bin $(OUTPUT)-dfu.bin
cat $^ > $@ cat $^ > $@
$(BIN) $(OBJ): $(BIN) $(OBJ): apps/$(APP)/usb_strings_generated.h
mkdir -p $@ mkdir -p $@
usbstring/usbstring: usbstring/usbstring.c usbstring/usbstring: usbstring/usbstring.c
gcc $^ -o $@ gcc $^ -o $@
apps/$(APP)/usb_strings_generated.h: apps/$(APP)/usb_strings.txt usbstring/usbstring .PHONY: apps/$(APP)/usb_strings.txt.patched
apps/$(APP)/usb_strings.txt.patched: apps/$(APP)/usb_strings.txt
sed "s/PRODUCT_STRING/$(shell cat libboard/$(BOARD)/product_string.txt)/" $< > $@
apps/$(APP)/usb_strings_generated.h: apps/$(APP)/usb_strings.txt.patched usbstring/usbstring
cat $< | usbstring/usbstring > $@ cat $< | usbstring/usbstring > $@
define RULES define RULES
C_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(C_OBJECTS)) C_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(C_OBJECTS))
ASM_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(ASM_OBJECTS)) ASM_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(ASM_OBJECTS))
EXTRA_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(EXTRA_OBJECTS))
$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1)) build_$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1)) $$(EXTRA_OBJECTS_$(1))
@$(CC) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/$$@.ld" -Wl,-Map,$(OUTPUT)-$$@.map -o $(OUTPUT)-$$@.elf $$^ $(LIBS) $(SILENT)$(CC) $(CFLAGS) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/$(1).ld" -Wl,-Map,$(OUTPUT)-$(1).map -o $(OUTPUT)-$(1).elf $$^ $(LIBS)
@$(NM) $(OUTPUT)-$$@.elf >$(OUTPUT)-$$@.elf.txt $(SILENT)$(NM) $(OUTPUT)-$(1).elf >$(OUTPUT)-$(1).elf.txt
@$(OBJCOPY) -O binary $(OUTPUT)-$$@.elf $(OUTPUT)-$$@.bin $(SILENT)$(OBJCOPY) -O binary $(OUTPUT)-$(1).elf $(OUTPUT)-$(1).bin
@$(SIZE) $$^ $(OUTPUT)-$$@.elf $(SILENT)$(SIZE) $$^ $(OUTPUT)-$(1).elf
$$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN) $$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN)
@echo [COMPILING $$<] @echo [COMPILING $$<]
@$(CC) $(CFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -Wa,-ahlms=$(BIN)/$$*.lst -c -o $$@ $$< $(SILENT)$(CC) $(CFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -c -o $$@ $$<
$$(ASM_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.S Makefile $(OBJ) $(BIN) $$(ASM_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.S Makefile $(OBJ) $(BIN)
@echo [ASSEMBLING $$@] @echo [ASSEMBLING $$@]
@$(CC) $(ASFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -c -o $$@ $$< $(SILENT)$(CC) $(ASFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -c -o $$@ $$<
debug_$(1): $(1) debug_$(1): $(1)
$(GDB) -x "$(BOARD_LIB)/resources/gcc/$(BOARD)_$(1).gdb" -ex "reset" -readnow -se $(OUTPUT)-$(1).elf $(GDB) -x "$(BOARD_LIB)/resources/gcc/$(BOARD)_$(1).gdb" -ex "reset" -readnow -se $(OUTPUT)-$(1).elf
endef endef
$(foreach MEMORY, $(MEMORIES), $(eval $(call RULES,$(MEMORY)))) ALL_MEMORIES = dfu flash ram
$(foreach MEMORY, $(ALL_MEMORIES), $(eval $(call RULES,$(MEMORY))))
# files with those names do exist..
.PHONY: ram
.PHONY: dfu
.PHONY: flash
ram: build_ram
dfu: build_dfu
ifeq ($(APP), blupdate)
$(info updating updater section with padded bootloader file..)
$(SILENT)dd if=/dev/zero bs=16384 count=1 of=$(BIN)/$(BOARD)-dfu-flash-padded.bin
$(SILENT)dd if=$(BIN)/$(BOARD)-dfu-flash.bin conv=notrunc of=$(BIN)/$(BOARD)-dfu-flash-padded.bin
$(SILENT)$(OBJCOPY) --update-section .blupdate=bin/$(BOARD)-dfu-flash-padded.bin bin/$(BOARD)-blupdate-dfu.elf
$(SILENT)$(OBJCOPY) -O binary bin/$(BOARD)-blupdate-dfu.elf bin/$(BOARD)-blupdate-dfu.bin
endif
flash: build_flash
#alternate way of embedding: obj file
#ifeq ($(APP), dfu)
# $(info bootloader bin file to obj..)
# $(SILENT)$(OBJCOPY) --rename-section .data=.fwupdate -I binary -O elf32-littlearm bin/$(BOARD)-dfu-flash.bin $(OBJ)/flash_fwupdate.o
#endif
program: program:
openocd -f openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 ./bin/project-flash.bin 0" -c "reset" -c "shutdown" openocd -f openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 ./bin/project-flash.bin 0" -c "reset" -c "shutdown"
SERIAL ?= /dev/ttyUSB0 SERIAL ?= /dev/ttyUSB0
log: log:
stty -F $(SERIAL) 115200 stty -F $(SERIAL) 921600
lsof $(SERIAL) && echo "log is already opened" || ( sed -u "s/\r//" $(SERIAL) | ts ) lsof $(SERIAL) && echo "log is already opened" || ( sed -u "s/\r//" $(SERIAL) | ts )
clean: clean:
-rm -f apps/$(APP)/usb_strings.txt.patched
-rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst `find . -name \*.p` -rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst `find . -name \*.p`
install:
mkdir -p $(DESTDIR)/usr/share/simtrace2
cp $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(DESTDIR)/usr/share/simtrace2

View File

@@ -24,6 +24,7 @@ Current boards supported are:
* `simtrace`: The good old Osmocom SIMtrace PCB with SAM3 instead of SAM7, open hardware. * `simtrace`: The good old Osmocom SIMtrace PCB with SAM3 instead of SAM7, open hardware.
* `qmod`: A sysmocom-proprietary quad mPCIe carrier board, publicly available * `qmod`: A sysmocom-proprietary quad mPCIe carrier board, publicly available
* `owhw`: An undisclosed sysmocom-internal board, not publicly available * `owhw`: An undisclosed sysmocom-internal board, not publicly available
* `octsimtest`: A sysmocom-proprietary production testing board, not publicly available
= Firmware = Firmware
@@ -51,6 +52,7 @@ Current applications supported are:
* `cardem`: To provide remote SIM operation capabilities. * `cardem`: To provide remote SIM operation capabilities.
* `trace`: To monitor the communication between a SIM card and a phone (corresponds to the functionality provide by the first SIMtrace) * `trace`: To monitor the communication between a SIM card and a phone (corresponds to the functionality provide by the first SIMtrace)
* `triple_play`: To support the three previous functionalities, using USB configurations. * `triple_play`: To support the three previous functionalities, using USB configurations.
* `gpio_test`: internal test code
== Memories == Memories
@@ -76,6 +78,10 @@ $ make TRACE_LEVEL=4
``` ```
Accepted values: 0 (NO_TRACE) to 5 (DEBUG) Accepted values: 0 (NO_TRACE) to 5 (DEBUG)
The qmod specific option `ALLOW_PEER_ERASE` controls if the UART debug command to assert the peer SAM3S ERASE line is present in the code.
Per default this is set to 0 to prevent accidentally erasing all firmware, including the DFU bootloader, which would then need to be flashed using SAM-BA or JTAG/SWD.
Setting `ALLOW_PEER_ERASE` to 1 enables back the debug command and should be used only for debugging or development purposes.
= Flashing = Flashing
To flash a firmware image follow the instructions provided in the [wiki](https://projects.osmocom.org/projects/simtrace2/wiki/). To flash a firmware image follow the instructions provided in the [wiki](https://projects.osmocom.org/projects/simtrace2/wiki/).

View File

@@ -0,0 +1,12 @@
C_FILES += $(C_LIBUSB_DFU)
# Trace level used for compilation
# (can be overridden by adding TRACE_LEVEL=#number to the command-line)
# TRACE_LEVEL_DEBUG 5
# TRACE_LEVEL_INFO 4
# TRACE_LEVEL_WARNING 3
# TRACE_LEVEL_ERROR 2
# TRACE_LEVEL_FATAL 1
# TRACE_LEVEL_NO_TRACE 0
TRACE_LEVEL ?= 3

View File

@@ -0,0 +1,134 @@
/* SIMtrace 2 firmware USB DFU bootloader
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018-2019 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "board.h"
#include "core_cm3.h"
#include "flashd.h"
#include "utils.h"
#include "usb/device/dfu/dfu.h"
#include "usb/common/dfu/usb_dfu.h"
#include "manifest.h"
#include "USBD_HAL.h"
#include <osmocom/core/timer.h>
/* actual section content must be replaced with the padded bootloader by running objcopy! */
const uint32_t bl_update_data[BOARD_DFU_BOOT_SIZE / sizeof(uint32_t)] __attribute__((section(".fwupdate"))) = { 0xFF };
unsigned int g_unique_id[4];
/* remember if the watchdog has been configured in the main loop so we can kick it in the ISR */
static bool watchdog_configured = false;
extern uint32_t _end;
extern uint32_t _srelocate;
extern uint32_t _etext;
void DFURT_SwitchToDFU(void)
{
}
void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request)
{
}
int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, uint8_t *data, unsigned int len)
{
return 0;
}
int USBDFU_handle_upload(uint8_t altif, unsigned int offset, uint8_t *data, unsigned int req_len)
{
return 0;
}
int USBDFU_OverrideEnterDFU(void)
{
return 0;
}
__attribute__((section(".ramfunc"), noinline)) static uint32_t flash_wait_ready()
{
Efc *efc = EFC;
uint32_t dwStatus;
do {
dwStatus = efc->EEFC_FSR;
} while ((dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
return (dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE));
}
__attribute__((section(".ramfunc"), noinline)) static void flash_cmd(uint32_t dwCommand, uint32_t dwArgument)
{
Efc *efc = EFC;
uint32_t dwStatus;
efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand);
}
__attribute__((section(".ramfunc"), noinline, noreturn)) static void erase_first_app_sector()
{
/* page 64 */
uint32_t first_app_page = (BOARD_DFU_BOOT_SIZE / IFLASH_PAGE_SIZE);
uint32_t *first_app_address = (uint32_t *)(IFLASH_ADDR + first_app_page * IFLASH_PAGE_SIZE + 0);
#if 1
/* overwrite first app sector so we don't keep booting this */
for (int i = 0; i < IFLASH_PAGE_SIZE / 4; i++)
first_app_address[i] = 0xffffffff;
flash_cmd(EFC_FCMD_EWP, first_app_page);
#else
/* why does erasing the whole flash with a protected bootloader not work at all? */
flash_cmd(EFC_FCMD_EA, 0);
#endif
flash_wait_ready();
for (;;)
NVIC_SystemReset();
}
#define MAX_USB_ITER BOARD_MCK / 72 // This should be around a second
extern int main(void)
{
uint8_t isUsbConnected = 0;
unsigned int i = 0;
uint32_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos;
/* Enable watchdog for 2000ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | (WDT_GetPeriod(2000) << 16) |
WDT_GetPeriod(2000));
watchdog_configured = true;
EEFC_ReadUniqueID(g_unique_id);
printf("\n\r\n\r");
printf("bootloader updater %s for board %s\n\r"
"(C) 2010-2017 by Harald Welte, 2018-2019 by Kevin Redon\n\r",
manifest_revision, manifest_board);
/* clear g_dfu on power-up reset */
memset(g_dfu, 0, sizeof(*g_dfu));
TRACE_INFO("USB init...\n\r");
/* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */
USBD_Disconnect();
/* Initialize the flash to be able to write it, using the IAP ROM code */
FLASHD_Initialize(BOARD_MCK, 1);
__disable_irq();
FLASHD_Unlock(IFLASH_ADDR, IFLASH_ADDR + IFLASH_SIZE - 1, 0, 0);
FLASHD_Write(IFLASH_ADDR, bl_update_data, BOARD_DFU_BOOT_SIZE);
erase_first_app_sector();
}

View File

@@ -0,0 +1,6 @@
sysmocom - s.f.m.c. GmbH
PRODUCT_STRING
bootloader updater
RAM
Flash (Application Partition)
Flash (Bootloader Partition)

View File

@@ -1,3 +1,3 @@
C_FILES += $(C_LIBUSB_RT) C_FILES += $(C_LIBUSB_RT)
C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c

View File

@@ -1,4 +1,22 @@
// FIXME: Copyright license here /* SIMtrace 2 firmware card emulation application
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018-2019, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Headers * Headers
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
@@ -6,10 +24,9 @@
#include "board.h" #include "board.h"
#include "simtrace.h" #include "simtrace.h"
#include "utils.h" #include "utils.h"
#include "main_common.h"
#include <osmocom/core/timer.h> #include <osmocom/core/timer.h>
unsigned int g_unique_id[4];
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Internal variables * Internal variables
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
@@ -22,7 +39,7 @@ typedef struct {
void (*exit) (void); void (*exit) (void);
/* main loop content for given configuration */ /* main loop content for given configuration */
void (*run) (void); void (*run) (void);
/* Interrupt handler for USART1 */ /* Interrupt handler for USART0 */
void (*usart0_irq) (void); void (*usart0_irq) (void);
/* Interrupt handler for USART1 */ /* Interrupt handler for USART1 */
void (*usart1_irq) (void); void (*usart1_irq) (void);
@@ -36,6 +53,8 @@ static const conf_func config_func_ptrs[] = {
.init = Sniffer_init, .init = Sniffer_init,
.exit = Sniffer_exit, .exit = Sniffer_exit,
.run = Sniffer_run, .run = Sniffer_run,
.usart0_irq = Sniffer_usart0_irq,
.usart1_irq = Sniffer_usart1_irq,
}, },
#endif #endif
#ifdef HAVE_CCID #ifdef HAVE_CCID
@@ -52,8 +71,13 @@ static const conf_func config_func_ptrs[] = {
.init = mode_cardemu_init, .init = mode_cardemu_init,
.exit = mode_cardemu_exit, .exit = mode_cardemu_exit,
.run = mode_cardemu_run, .run = mode_cardemu_run,
#if defined (ngff_cardem)
.usart0_irq = mode_cardemu_usart1_irq,
.usart1_irq = mode_cardemu_usart0_irq,
#else
.usart0_irq = mode_cardemu_usart0_irq, .usart0_irq = mode_cardemu_usart0_irq,
.usart1_irq = mode_cardemu_usart1_irq, .usart1_irq = mode_cardemu_usart1_irq,
#endif
}, },
#endif #endif
#ifdef HAVE_MITM #ifdef HAVE_MITM
@@ -84,7 +108,11 @@ static volatile enum confNum simtrace_config = CFG_NUM_CCID;
void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum) void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
{ {
TRACE_INFO_WP("cfgChanged%d ", cfgnum); TRACE_INFO_WP("cfgChanged%d ", cfgnum);
simtrace_config = cfgnum; if (cfgnum < ARRAY_SIZE(config_func_ptrs)) {
simtrace_config = cfgnum;
} else {
TRACE_ERROR("trying to set out of bounds config %u\r\n", cfgnum);
}
} }
void USART1_IrqHandler(void) void USART1_IrqHandler(void)
@@ -108,7 +136,8 @@ static void check_exec_dbg_cmd(void)
return; return;
ch = UART_GetChar(); ch = UART_GetChar();
/* We must echo the character to make python fdexpect happy, which we use in factory testing */
fputc(ch, stdout);
board_exec_dbg_cmd(ch); board_exec_dbg_cmd(ch);
} }
@@ -123,27 +152,16 @@ extern int main(void)
unsigned int i = 0; unsigned int i = 0;
led_init(); led_init();
led_blink(LED_RED, BLINK_3O_5F); led_blink(LED_RED, BLINK_ALWAYS_ON);
led_blink(LED_GREEN, BLINK_ALWAYS_ON);
/* Enable watchdog for 500ms, with no window */ /* Enable watchdog for 2000ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(500) << 16) | WDT_GetPeriod(500)); (WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
PIO_InitializeInterrupts(0); PIO_InitializeInterrupts(0);
EEFC_ReadUniqueID(g_unique_id); print_banner();
printf("\n\r\n\r"
"=============================================================================\n\r"
"SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\n\r"
"=============================================================================\n\r");
TRACE_INFO("Chip ID: 0x%08x (Ext 0x%08x)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]);
TRACE_INFO("Reset Cause: 0x%x\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
board_main_top(); board_main_top();
TRACE_INFO("USB init...\n\r"); TRACE_INFO("USB init...\n\r");
@@ -164,14 +182,15 @@ extern int main(void)
} }
TRACE_INFO("calling configure of all configurations...\n\r"); TRACE_INFO("calling configure of all configurations...\n\r");
for (i = 1; i < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]); for (i = 1; i < ARRAY_SIZE(config_func_ptrs); i++) {
++i) {
if (config_func_ptrs[i].configure) if (config_func_ptrs[i].configure)
config_func_ptrs[i].configure(); config_func_ptrs[i].configure();
} }
TRACE_INFO("calling init of config %u...\n\r", simtrace_config); TRACE_INFO("calling init of config %u...\n\r", simtrace_config);
config_func_ptrs[simtrace_config].init(); if (config_func_ptrs[simtrace_config].init) {
config_func_ptrs[simtrace_config].init();
}
last_simtrace_config = simtrace_config; last_simtrace_config = simtrace_config;
TRACE_INFO("entering main loop...\n\r"); TRACE_INFO("entering main loop...\n\r");
@@ -199,11 +218,17 @@ extern int main(void)
if (last_simtrace_config != simtrace_config) { if (last_simtrace_config != simtrace_config) {
TRACE_INFO("USB config chg %u -> %u\n\r", TRACE_INFO("USB config chg %u -> %u\n\r",
last_simtrace_config, simtrace_config); last_simtrace_config, simtrace_config);
config_func_ptrs[last_simtrace_config].exit(); if (config_func_ptrs[last_simtrace_config].exit) {
config_func_ptrs[simtrace_config].init(); config_func_ptrs[last_simtrace_config].exit();
}
if (config_func_ptrs[simtrace_config].init) {
config_func_ptrs[simtrace_config].init();
}
last_simtrace_config = simtrace_config; last_simtrace_config = simtrace_config;
} else { } else {
config_func_ptrs[simtrace_config].run(); if (config_func_ptrs[simtrace_config].run) {
config_func_ptrs[simtrace_config].run();
}
} }
} }
} }

View File

@@ -1,8 +1,8 @@
sysmocom - s.f.m.c. GmbH sysmocom - s.f.m.c. GmbH
SIMtrace 2 compatible device PRODUCT_STRING
SIMtrace Sniffer SIMtrace Sniffer
SIMtrace CCID SIMtrace CCID
SIMtrace Phone SIMtrace Card Emulation
SIMtrace MITM SIMtrace MITM
CardEmulator Modem 1 CardEmulator Modem 1
CardEmulator Modem 2 CardEmulator Modem 2

View File

@@ -1,27 +1,68 @@
/* SIMtrace 2 firmware USB DFU bootloader
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018-2019 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "board.h" #include "board.h"
#include "utils.h" #include "utils.h"
#include "usb/device/dfu/dfu.h" #include "usb/device/dfu/dfu.h"
#include "usb/common/dfu/usb_dfu.h" #include "usb/common/dfu/usb_dfu.h"
#include "manifest.h" #include "manifest.h"
#include "USBD_HAL.h"
#include <osmocom/core/timer.h> #include <osmocom/core/timer.h>
/* USB alternate interface index used to identify which partition to flash */
/** USB alternate interface index indicating RAM partition */
#define ALTIF_RAM 0 #define ALTIF_RAM 0
/** USB alternate interface index indicating flash partition */
#if defined(ENVIRONMENT_flash)
#define ALTIF_FLASH 1 #define ALTIF_FLASH 1
#elif defined(ENVIRONMENT_dfu)
#define ALTIF_FLASH 2
#endif
unsigned int g_unique_id[4]; unsigned int g_unique_id[4];
/* remember if the watchdog has been configured in the main loop so we can kick it in the ISR */ /* remember if the watchdog has been configured in the main loop so we can kick it in the ISR */
static bool watchdog_configured = false; static bool watchdog_configured = false;
/* There is not enough space in the 16 KiB DFU bootloader to include led.h functions */
#ifdef PINS_LEDS
/** LED pin configurations */
static const Pin pinsLeds[] = { PINS_LEDS } ;
#endif
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Callbacks * Callbacks
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define RAM_ADDR(offset) (IRAM_ADDR + BOARD_DFU_RAM_SIZE + offset) #define RAM_ADDR(offset) (IRAM_ADDR + BOARD_DFU_RAM_SIZE + offset)
#if defined(ENVIRONMENT_flash)
#define FLASH_ADDR(offset) (IFLASH_ADDR + BOARD_DFU_BOOT_SIZE + offset) #define FLASH_ADDR(offset) (IFLASH_ADDR + BOARD_DFU_BOOT_SIZE + offset)
#elif defined(ENVIRONMENT_dfu)
#define FLASH_ADDR(offset) (IFLASH_ADDR + offset)
#endif
#define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE) #define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE)
#define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE) #if defined(ENVIRONMENT_flash)
#define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE)
#elif defined(ENVIRONMENT_dfu)
#define IFLASH_END ((uint8_t *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE)
#endif
/* incoming call-back: Host has transferred 'len' bytes (stored at /* incoming call-back: Host has transferred 'len' bytes (stored at
* 'data'), which we shall write to 'offset' into the partition * 'data'), which we shall write to 'offset' into the partition
@@ -40,7 +81,15 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
WDT_Restart(WDT); WDT_Restart(WDT);
} }
printf("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len); #if TRACE_LEVEL >= TRACE_LEVEL_INFO
TRACE_INFO("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len);
#else
printf("DL off=%u\n\r", offset);
#endif
#ifdef PINS_LEDS
PIO_Clear(&pinsLeds[LED_NUM_RED]);
#endif
switch (altif) { switch (altif) {
case ALTIF_RAM: case ALTIF_RAM:
@@ -48,47 +97,56 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
if (addr < IRAM_ADDR || addr + len >= IRAM_ADDR + IRAM_SIZE || addr + len >= stack_addr) { if (addr < IRAM_ADDR || addr + len >= IRAM_ADDR + IRAM_SIZE || addr + len >= stack_addr) {
g_dfu->state = DFU_STATE_dfuERROR; g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS; g_dfu->status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL; rc = DFU_RET_STALL;
break;
} }
memcpy((void *)addr, data, len); memcpy((void *)addr, data, len);
return DFU_RET_ZLP; rc = DFU_RET_ZLP;
break;
case ALTIF_FLASH: case ALTIF_FLASH:
addr = FLASH_ADDR(offset); addr = FLASH_ADDR(offset);
#if defined(ENVIRONMENT_flash)
if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + IFLASH_SIZE) { if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + IFLASH_SIZE) {
#elif defined(ENVIRONMENT_dfu)
if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + BOARD_DFU_BOOT_SIZE) {
#endif
g_dfu->state = DFU_STATE_dfuERROR; g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS; g_dfu->status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL; rc = DFU_RET_STALL;
break;
} }
rc = FLASHD_Unlock(addr, addr + len, 0, 0); rc = FLASHD_Unlock(addr, addr + len, 0, 0);
if (rc != 0) { if (rc != 0) {
TRACE_ERROR("DFU download flash unlock failed\n\r"); TRACE_ERROR("DFU download flash unlock failed\n\r");
/* FIXME: set error codes */ rc = DFU_RET_STALL;
return DFU_RET_STALL; break;
} }
rc = FLASHD_Write(addr, data, len); rc = FLASHD_Write(addr, data, len);
if (rc != 0) { if (rc != 0) {
TRACE_ERROR("DFU download flash erase failed\n\r"); TRACE_ERROR("DFU download flash erase failed\n\r");
/* FIXME: set error codes */ rc = DFU_RET_STALL;
return DFU_RET_STALL; break;
} }
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (((uint8_t*)addr)[i]!=data[i]) { if (((uint8_t*)addr)[i]!=data[i]) {
TRACE_ERROR("DFU download flash data written not correct\n\r"); TRACE_ERROR("DFU download flash data written not correct\n\r");
return DFU_RET_STALL; rc = DFU_RET_STALL;
break;
} }
} }
rc = FLASHD_Lock(addr, addr + len, 0, 0); rc = DFU_RET_ZLP;
if (rc != 0) { break;
TRACE_ERROR("DFU download flash lock failed\n\r");
/* FIXME: set error codes */
return DFU_RET_STALL;
}
return DFU_RET_ZLP;
default: default:
/* FIXME: set error codes */
TRACE_ERROR("DFU download for unknown AltIf %d\n\r", altif); TRACE_ERROR("DFU download for unknown AltIf %d\n\r", altif);
return DFU_RET_STALL; rc = DFU_RET_STALL;
break;
} }
#ifdef PINS_LEDS
PIO_Set(&pinsLeds[LED_NUM_RED]);
#endif
return rc;
} }
/* incoming call-back: Host has requested to read back 'req_len' bytes /* incoming call-back: Host has requested to read back 'req_len' bytes
@@ -144,22 +202,30 @@ WEAK int board_override_enter_dfu(void)
int USBDFU_OverrideEnterDFU(void) int USBDFU_OverrideEnterDFU(void)
{ {
uint32_t *app_part = (uint32_t *)FLASH_ADDR(0); uint32_t *app_part = (uint32_t *)FLASH_ADDR(0);
/* at the first call we are before the text segment has been relocated,
* so g_dfu is not initialized yet */
g_dfu = &_g_dfu;
if (USB_DFU_MAGIC == g_dfu->magic) {
return 1;
}
/* If the loopback jumper is set, we enter DFU mode */ /* If the loopback jumper is set, we enter DFU mode */
if (board_override_enter_dfu()) if (board_override_enter_dfu()) {
return 1; return 2;
}
/* if the first word of the application partition doesn't look /* if the first word of the application partition doesn't look
* like a stack pointer (i.e. point to RAM), enter DFU mode */ * like a stack pointer (i.e. point to RAM), enter DFU mode */
if ((app_part[0] < IRAM_ADDR) || if ((app_part[0] < IRAM_ADDR) || ((uint8_t *)app_part[0] > IRAM_END)) {
((uint8_t *)app_part[0] > IRAM_END)) return 3;
return 1; }
/* if the second word of the application partition doesn't look /* if the second word of the application partition doesn't look
* like a function from flash (reset vector), enter DFU mode */ * like a function from flash (reset vector), enter DFU mode */
if (((uint32_t *)app_part[1] < app_part) || if (((uint32_t *)app_part[1] < app_part) ||
((uint8_t *)app_part[1] > IFLASH_END)) ((uint8_t *)app_part[1] > IFLASH_END)) {
return 1; return 4;
}
return 0; return 0;
} }
@@ -177,6 +243,17 @@ static void check_exec_dbg_cmd(void)
//board_exec_dbg_cmd(ch); //board_exec_dbg_cmd(ch);
} }
/* print a horizontal line of '=' characters; Doing this in a loop vs. using a 'const'
* string saves us ~60 bytes of executable size (matters particularly for DFU loader) */
static void print_line(void)
{
int i;
for (i = 0; i < 78; i++)
fputc('=', stdout);
fputc('\n', stdout);
fputc('\r', stdout);
}
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Main * Main
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
@@ -187,32 +264,74 @@ extern int main(void)
unsigned int i = 0; unsigned int i = 0;
uint32_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos; uint32_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos;
#if 0
led_init();
led_blink(LED_GREEN, BLINK_3O_30F);
led_blink(LED_RED, BLINK_3O_30F);
#endif
/* Enable watchdog for 2000ms, with no window */ /* Enable watchdog for 2000ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000)); (WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
watchdog_configured = true; watchdog_configured = true;
PIO_InitializeInterrupts(0); #ifdef PINS_LEDS
/* Configure LED */
PIO_Configure(pinsLeds, PIO_LISTSIZE(pinsLeds));
PIO_Set(&pinsLeds[LED_NUM_RED]);
PIO_Clear(&pinsLeds[LED_NUM_GREEN]);
#endif
EEFC_ReadUniqueID(g_unique_id); EEFC_ReadUniqueID(g_unique_id);
printf("\n\r\n\r" printf("\n\r\n\r");
"=============================================================================\n\r" print_line();
"DFU bootloader %s for board %s (C) 2010-2017 by Harald Welte\n\r" printf("DFU bootloader %s for board %s\n\r"
"=============================================================================\n\r", "(C) 2010-2017 by Harald Welte, 2018-2019 by Kevin Redon\n\r",
manifest_revision, manifest_board); manifest_revision, manifest_board);
print_line();
TRACE_INFO("Chip ID: 0x%08x (Ext 0x%08x)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID); #if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
TRACE_INFO("Chip ID: 0x%08lx (Ext 0x%08lx)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r", TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
g_unique_id[0], g_unique_id[1], g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]); g_unique_id[2], g_unique_id[3]);
TRACE_INFO("Reset Cause: 0x%x\n\r", reset_cause); static const char* reset_causes[] = {
"general reset (first power-up reset)",
"backup reset (return from backup mode)",
"watchdog reset (watchdog fault occurred)",
"software reset (processor reset required by the software)",
"user reset (NRST pin detected low)",
};
if (reset_cause < ARRAY_SIZE(reset_causes)) {
TRACE_INFO("Reset Cause: %s\n\r", reset_causes[reset_cause]);
} else {
TRACE_INFO("Reset Cause: 0x%lx\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
}
#endif
#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
/* Find out why we are in the DFU bootloader, and not the main application */
TRACE_INFO("DFU bootloader start reason: ");
switch (USBDFU_OverrideEnterDFU()) {
case 0:
if (SCB->VTOR < IFLASH_ADDR + BOARD_DFU_BOOT_SIZE) {
TRACE_INFO_WP("unknown\n\r");
} else {
TRACE_INFO_WP("DFU is the main application\n\r");
}
break;
case 1:
TRACE_INFO_WP("DFU switch requested by main application\n\r");
break;
case 2:
TRACE_INFO_WP("bootloader forced (button pressed or jumper set)\n\r");
break;
case 3:
TRACE_INFO_WP("stack pointer (first application word) does no point in RAM\n\r");
break;
case 4: // the is no reason
TRACE_INFO_WP("reset vector (second application word) does no point in flash\n\r");
break;
default:
TRACE_INFO_WP("unknown\n\r");
break;
}
#endif
/* clear g_dfu on power-up reset */ /* clear g_dfu on power-up reset */
if (reset_cause == 0) if (reset_cause == 0)
@@ -222,11 +341,8 @@ extern int main(void)
TRACE_INFO("USB init...\n\r"); TRACE_INFO("USB init...\n\r");
/* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */ /* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */
const Pin usb_dp_pullup = PIN_USB_PULLUP; USBD_Disconnect();
PIO_Configure(&usb_dp_pullup, 1); mdelay(500);
PIO_Set(&usb_dp_pullup);
mdelay(15);
PIO_Clear(&usb_dp_pullup);
USBDFU_Initialize(&dfu_descriptors); USBDFU_Initialize(&dfu_descriptors);
while (USBD_GetState() < USBD_STATE_CONFIGURED) { while (USBD_GetState() < USBD_STATE_CONFIGURED) {
@@ -234,8 +350,8 @@ extern int main(void)
check_exec_dbg_cmd(); check_exec_dbg_cmd();
#if 1 #if 1
if (i >= MAX_USB_ITER * 3) { if (i >= MAX_USB_ITER * 3) {
TRACE_ERROR("Resetting board (USB could " TRACE_ERROR("Resetting board (USB could not be configured)\n\r");
"not be configured)\n\r"); g_dfu->magic = USB_DFU_MAGIC; // start the bootloader after reboot
USBD_Disconnect(); USBD_Disconnect();
NVIC_SystemReset(); NVIC_SystemReset();
} }

View File

@@ -1,5 +1,6 @@
sysmocom - s.f.m.c. GmbH sysmocom - s.f.m.c. GmbH
SIMtrace 2 compatible device PRODUCT_STRING
DFU (Device Firmware Upgrade) DFU (Device Firmware Upgrade)
RAM RAM
Flash (Application Partition) Flash (Application Partition)
Flash (Bootloader Partition)

View File

@@ -0,0 +1,3 @@
C_FILES += $(C_LIBUSB_RT)
C_FILES += freq_ctr.c

View File

@@ -0,0 +1,55 @@
#include <stdint.h>
#include "utils.h"
#include "tc_etu.h"
#include "chip.h"
/* pins for Channel 0 of TC-block 0 */
#define PIN_TIOA0 {PIO_PA0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/* pins for Channel 1 of TC-block 0 */
#define PIN_TIOA1 {PIO_PA15, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_TCLK1 {PIO_PA28, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
static const Pin pins_tc[] = { PIN_TIOA0, PIN_TIOA1, PIN_TCLK1 };
static TcChannel *tc1 = &TC0->TC_CHANNEL[1];
void TC1_IrqHandler(void)
{
uint32_t sr = tc1->TC_SR;
printf("TC1=%lu; SR=0x%08lx\r\n", tc1->TC_RA, sr);
}
void freq_ctr_init(void)
{
TcChannel *tc0 = &TC0->TC_CHANNEL[0];
PIO_Configure(pins_tc, ARRAY_SIZE(pins_tc));
PMC_EnablePeripheral(ID_TC0);
PMC_EnablePeripheral(ID_TC1);
/* route TCLK1 to XC1 */
TC0->TC_BMR &= ~TC_BMR_TC1XC1S_Msk;
TC0->TC_BMR |= TC_BMR_TC1XC1S_TCLK1;
/* TC0 in wveform mode: Run from SCLK. Raise TIOA on RA; lower TIOA on RC + trigger */
tc0->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK5 | TC_CMR_BURST_NONE |
TC_CMR_EEVTEDG_NONE | TC_CMR_WAVSEL_UP_RC | TC_CMR_WAVE |
TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR;
tc0->TC_RA = 16384; /* set high at 16384 */
tc0->TC_RC = 32786; /* set low at 32786 */
/* TC1 in capture mode: Run from XC1. Trigger on TIOA rising. Load RA on rising */
tc1->TC_CMR = TC_CMR_TCCLKS_XC1 | TC_CMR_BURST_NONE |
TC_CMR_ETRGEDG_RISING | TC_CMR_ABETRG | TC_CMR_LDRA_RISING;
/* Interrupt us if the external trigger happens */
tc1->TC_IER = TC_IER_ETRGS;
NVIC_EnableIRQ(TC1_IRQn);
TC0->TC_BCR = TC_BCR_SYNC;
tc0->TC_CCR = TC_CCR_CLKEN|TC_CCR_SWTRG;
tc1->TC_CCR = TC_CCR_CLKEN|TC_CCR_SWTRG;
}

View File

@@ -0,0 +1,54 @@
#include "board.h"
#include "utils.h"
#include "osmocom/core/timer.h"
extern void freq_ctr_init(void);
/* returns '1' in case we should break any endless loop */
static void check_exec_dbg_cmd(void)
{
int ch;
if (!UART_IsRxReady())
return;
ch = UART_GetChar();
board_exec_dbg_cmd(ch);
}
extern int main(void)
{
led_init();
led_blink(LED_RED, BLINK_ALWAYS_ON);
led_blink(LED_GREEN, BLINK_ALWAYS_ON);
/* Enable watchdog for 2000 ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
PIO_InitializeInterrupts(0);
printf("\n\r\n\r"
"=============================================================================\n\r"
"Freq Ctr firmware " GIT_VERSION " (C) 2019 by Harald Welte\n\r"
"=============================================================================\n\r");
board_main_top();
TRACE_INFO("starting frequency counter...\n\r");
freq_ctr_init();
TRACE_INFO("entering main loop...\n\r");
while (1) {
WDT_Restart(WDT);
check_exec_dbg_cmd();
osmo_timers_prepare();
osmo_timers_update();
}
}

View File

@@ -0,0 +1,10 @@
sysmocom - s.f.m.c. GmbH
PRODUCT_STRING
SIMtrace Sniffer
SIMtrace CCID
SIMtrace Card Emulation
SIMtrace MITM
CardEmulator Modem 1
CardEmulator Modem 2
CardEmulator Modem 3
CardEmulator Modem 4

View File

@@ -0,0 +1,3 @@
C_FILES += $(C_LIBUSB_RT)
C_FILES += gpio_test.c

View File

@@ -0,0 +1,8 @@
#include <stdint.h>
#include "utils.h"
#include "chip.h"
void gpio_test_init(void)
{
printf("FIXME run tests here\n\r");
}

View File

@@ -0,0 +1,54 @@
#include "board.h"
#include "utils.h"
#include "osmocom/core/timer.h"
extern void gpio_test_init(void);
/* returns '1' in case we should break any endless loop */
static void check_exec_dbg_cmd(void)
{
int ch;
if (!UART_IsRxReady())
return;
ch = UART_GetChar();
board_exec_dbg_cmd(ch);
}
extern int main(void)
{
led_init();
led_blink(LED_RED, BLINK_ALWAYS_ON);
led_blink(LED_GREEN, BLINK_ALWAYS_ON);
/* Enable watchdog for 2000 ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
PIO_InitializeInterrupts(0);
printf("\n\r\n\r"
"=============================================================================\n\r"
"GPIO Test firmware " GIT_VERSION " (C) 2019 Sysmocom GmbH\n\r"
"=============================================================================\n\r");
board_main_top();
TRACE_INFO("starting gpio test...\n\r");
gpio_test_init();
TRACE_INFO("entering main loop...\n\r");
while (1) {
WDT_Restart(WDT);
check_exec_dbg_cmd();
osmo_timers_prepare();
osmo_timers_update();
}
}

View File

@@ -0,0 +1,10 @@
sysmocom - s.f.m.c. GmbH
PRODUCT_STRING
SIMtrace Sniffer
SIMtrace CCID
SIMtrace Card Emulation
SIMtrace MITM
CardEmulator Modem 1
CardEmulator Modem 2
CardEmulator Modem 3
CardEmulator Modem 4

View File

@@ -0,0 +1,3 @@
C_FILES += $(C_LIBUSB_RT)
C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c

View File

@@ -0,0 +1,222 @@
/* SIMtrace 2 firmware sniffer application
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "board.h"
#include "simtrace.h"
#include "utils.h"
#include "main_common.h"
#include "osmocom/core/timer.h"
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
typedef struct {
/* static initialization, called whether or not the usb config is active */
void (*configure) (void);
/* initialization function after the config was selected */
void (*init) (void);
/* de-initialization before selecting new config */
void (*exit) (void);
/* main loop content for given configuration */
void (*run) (void);
/* Interrupt handler for USART0 */
void (*usart0_irq) (void);
/* Interrupt handler for USART1 */
void (*usart1_irq) (void);
} conf_func;
static const conf_func config_func_ptrs[] = {
/* array slot 0 is empty, usb configs start at 1 */
#ifdef HAVE_SNIFFER
[CFG_NUM_SNIFF] = {
.configure = Sniffer_configure,
.init = Sniffer_init,
.exit = Sniffer_exit,
.run = Sniffer_run,
.usart0_irq = Sniffer_usart0_irq,
.usart1_irq = Sniffer_usart1_irq,
},
#endif
#ifdef HAVE_CCID
[CFG_NUM_CCID] = {
.configure = CCID_configure,
.init = CCID_init,
.exit = CCID_exit,
.run = CCID_run,
},
#endif
#ifdef HAVE_CARDEM
[CFG_NUM_PHONE] = {
.configure = mode_cardemu_configure,
.init = mode_cardemu_init,
.exit = mode_cardemu_exit,
.run = mode_cardemu_run,
.usart0_irq = mode_cardemu_usart0_irq,
.usart1_irq = mode_cardemu_usart1_irq,
},
#endif
#ifdef HAVE_MITM
[CFG_NUM_MITM] = {
.configure = MITM_configure,
.init = MITM_init,
.exit = MITM_exit,
.run = MITM_run,
},
#endif
};
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
#if defined(HAVE_SNIFFER)
static volatile enum confNum simtrace_config = CFG_NUM_SNIFF;
#elif defined(HAVE_CARDEM)
static volatile enum confNum simtrace_config = CFG_NUM_PHONE;
#elif defined(HAVE_CCID)
static volatile enum confNum simtrace_config = CFG_NUM_CCID;
#endif
/*----------------------------------------------------------------------------
* Callbacks
*----------------------------------------------------------------------------*/
void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
{
TRACE_INFO_WP("cfgChanged%d ", cfgnum);
simtrace_config = cfgnum;
}
void USART1_IrqHandler(void)
{
if (config_func_ptrs[simtrace_config].usart1_irq)
config_func_ptrs[simtrace_config].usart1_irq();
}
void USART0_IrqHandler(void)
{
if (config_func_ptrs[simtrace_config].usart0_irq)
config_func_ptrs[simtrace_config].usart0_irq();
}
/* returns '1' in case we should break any endless loop */
static void check_exec_dbg_cmd(void)
{
int ch;
if (!UART_IsRxReady())
return;
ch = UART_GetChar();
board_exec_dbg_cmd(ch);
}
/*------------------------------------------------------------------------------
* Main
*------------------------------------------------------------------------------*/
#define MAX_USB_ITER BOARD_MCK/72 // This should be around a second
extern int main(void)
{
uint8_t isUsbConnected = 0;
enum confNum last_simtrace_config = simtrace_config;
unsigned int i = 0;
/* Configure LED output
* red on = power
* red blink = error
* green on = running
* green blink = activity
*/
led_init();
led_blink(LED_RED, BLINK_ALWAYS_ON);
led_blink(LED_GREEN, BLINK_ALWAYS_ON);
/* Enable watchdog for 2000 ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
PIO_InitializeInterrupts(0);
print_banner();
board_main_top();
TRACE_INFO("USB init...\n\r");
SIMtrace_USB_Initialize();
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
WDT_Restart(WDT);
check_exec_dbg_cmd();
#if 0
if (i >= MAX_USB_ITER * 3) {
TRACE_ERROR("Resetting board (USB could "
"not be configured)\n\r");
USBD_Disconnect();
NVIC_SystemReset();
}
#endif
i++;
}
TRACE_INFO("calling configure of all configurations...\n\r");
for (i = 1; i < ARRAY_SIZE(config_func_ptrs); i++) {
if (config_func_ptrs[i].configure)
config_func_ptrs[i].configure();
}
TRACE_INFO("calling init of config %u...\n\r", simtrace_config);
config_func_ptrs[simtrace_config].init();
last_simtrace_config = simtrace_config;
TRACE_INFO("entering main loop...\n\r");
while (1) {
WDT_Restart(WDT);
#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG
const char rotor[] = { '-', '\\', '|', '/' };
putchar('\b');
putchar(rotor[i++ % ARRAY_SIZE(rotor)]);
#endif
check_exec_dbg_cmd();
osmo_timers_prepare();
osmo_timers_update();
if (USBD_GetState() < USBD_STATE_CONFIGURED) {
if (isUsbConnected) {
isUsbConnected = 0;
}
} else if (isUsbConnected == 0) {
TRACE_INFO("USB is now configured\n\r");
isUsbConnected = 1;
}
if (last_simtrace_config != simtrace_config) {
TRACE_INFO("USB config chg %u -> %u\n\r",
last_simtrace_config, simtrace_config);
config_func_ptrs[last_simtrace_config].exit();
config_func_ptrs[simtrace_config].init();
last_simtrace_config = simtrace_config;
} else {
config_func_ptrs[simtrace_config].run();
}
}
}

View File

@@ -0,0 +1,10 @@
sysmocom - s.f.m.c. GmbH
PRODUCT_STRING
SIMtrace Sniffer
SIMtrace CCID
SIMtrace Card Emulation
SIMtrace MITM
CardEmulator Modem 1
CardEmulator Modem 2
CardEmulator Modem 3
CardEmulator Modem 4

View File

@@ -1,3 +1,3 @@
C_FILES += $(C_LIBUSB_RT) C_FILES += $(C_LIBUSB_RT)
C_FILES += card_emu.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c C_FILES += card_emu.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c

View File

@@ -1,4 +1,21 @@
// FIXME: Copyright license here /* SIMtrace 2 firmware card emulation, CCID, and sniffer application
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Headers * Headers
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
@@ -9,8 +26,6 @@
#include "req_ctx.h" #include "req_ctx.h"
#include <osmocom/core/timer.h> #include <osmocom/core/timer.h>
unsigned int g_unique_id[4];
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Internal variables * Internal variables
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
@@ -132,17 +147,7 @@ extern int main(void)
PIO_InitializeInterrupts(0); PIO_InitializeInterrupts(0);
EEFC_ReadUniqueID(g_unique_id); print_banner();
printf("\r\n\r\n"
"=============================================================================\r\n"
"SIMtrace2 firmware " GIT_REVISION " (C) 2010-2017 by Harald Welte\r\n"
"=============================================================================\r\n");
TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\r\n",
g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]);
board_main_top(); board_main_top();
TRACE_INFO("USB init...\r\n"); TRACE_INFO("USB init...\r\n");

View File

@@ -1,113 +1,113 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *
* \section Purpose * \section Purpose
* *
* Interface for configuration the Enhanced Embedded Flash Controller (EEFC) peripheral. * Interface for configuration the Enhanced Embedded Flash Controller (EEFC) peripheral.
* *
* \section Usage * \section Usage
* *
* -# Enable/disable %flash ready interrupt sources using EFC_EnableFrdyIt() * -# Enable/disable %flash ready interrupt sources using EFC_EnableFrdyIt()
* and EFC_DisableFrdyIt(). * and EFC_DisableFrdyIt().
* -# Translates the given address into which EEFC, page and offset values * -# Translates the given address into which EEFC, page and offset values
* for difference density %flash memory using EFC_TranslateAddress(). * for difference density %flash memory using EFC_TranslateAddress().
* -# Computes the address of a %flash access given the EFC, page and offset * -# Computes the address of a %flash access given the EFC, page and offset
* for difference density %flash memory using EFC_ComputeAddress(). * for difference density %flash memory using EFC_ComputeAddress().
* -# Start the executing command with EFC_StartCommand() * -# Start the executing command with EFC_StartCommand()
* -# Retrieve the current status of the EFC using EFC_GetStatus(). * -# Retrieve the current status of the EFC using EFC_GetStatus().
* -# Retrieve the result of the last executed command with EFC_GetResult(). * -# Retrieve the result of the last executed command with EFC_GetResult().
*/ */
#ifndef _EEFC_ #ifndef _EEFC_
#define _EEFC_ #define _EEFC_
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include <stdint.h> #include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Definitions * Definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/* EFC command */ /* EFC command */
#define EFC_FCMD_GETD 0x00 #define EFC_FCMD_GETD 0x00
#define EFC_FCMD_WP 0x01 #define EFC_FCMD_WP 0x01
#define EFC_FCMD_WPL 0x02 #define EFC_FCMD_WPL 0x02
#define EFC_FCMD_EWP 0x03 #define EFC_FCMD_EWP 0x03
#define EFC_FCMD_EWPL 0x04 #define EFC_FCMD_EWPL 0x04
#define EFC_FCMD_EA 0x05 #define EFC_FCMD_EA 0x05
#define EFC_FCMD_SLB 0x08 #define EFC_FCMD_SLB 0x08
#define EFC_FCMD_CLB 0x09 #define EFC_FCMD_CLB 0x09
#define EFC_FCMD_GLB 0x0A #define EFC_FCMD_GLB 0x0A
#define EFC_FCMD_SFB 0x0B #define EFC_FCMD_SFB 0x0B
#define EFC_FCMD_CFB 0x0C #define EFC_FCMD_CFB 0x0C
#define EFC_FCMD_GFB 0x0D #define EFC_FCMD_GFB 0x0D
#define EFC_FCMD_STUI 0x0E /* Start unique ID */ #define EFC_FCMD_STUI 0x0E /* Start unique ID */
#define EFC_FCMD_SPUI 0x0F /* Stop unique ID */ #define EFC_FCMD_SPUI 0x0F /* Stop unique ID */
/* The IAP function entry addreass */ /* The IAP function entry addreass */
#define CHIP_FLASH_IAP_ADDRESS (0x00800008) #define CHIP_FLASH_IAP_ADDRESS (0x00800008)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
extern void EFC_EnableFrdyIt( Efc* efc ) ; extern void EFC_EnableFrdyIt( Efc* efc ) ;
extern void EFC_DisableFrdyIt( Efc* efc ) ; extern void EFC_DisableFrdyIt( Efc* efc ) ;
extern void EFC_SetWaitState( Efc* efc, uint8_t cycles ) ; extern void EFC_SetWaitState( Efc* efc, uint8_t cycles ) ;
extern void EFC_TranslateAddress( Efc** pEfc, uint32_t dwAddress, uint16_t *pwPage, uint16_t *pwOffset ) ; extern void EFC_TranslateAddress( Efc** pEfc, uint32_t dwAddress, uint16_t *pwPage, uint16_t *pwOffset ) ;
extern void EFC_ComputeAddress( Efc* efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress ) ; extern void EFC_ComputeAddress( Efc* efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress ) ;
extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument ) ; extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument ) ;
extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP ) ; extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP ) ;
extern uint32_t EFC_GetStatus( Efc* efc ) ; extern uint32_t EFC_GetStatus( Efc* efc ) ;
extern uint32_t EFC_GetResult( Efc* efc ) ; extern uint32_t EFC_GetResult( Efc* efc ) ;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* #ifndef _EEFC_ */ #endif /* #ifndef _EEFC_ */

View File

@@ -1,79 +1,79 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *
* The flash driver provides the unified interface for flash program operations. * The flash driver provides the unified interface for flash program operations.
* *
*/ */
#ifndef _FLASHD_ #ifndef _FLASHD_
#define _FLASHD_ #define _FLASHD_
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
extern void FLASHD_Initialize( uint32_t dwMCk, uint32_t dwUseIAP ) ; extern void FLASHD_Initialize( uint32_t dwMCk, uint32_t dwUseIAP ) ;
extern uint32_t FLASHD_Erase( uint32_t dwAddress ) ; extern uint32_t FLASHD_Erase( uint32_t dwAddress ) ;
extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize ) ; extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize ) ;
extern uint32_t FLASHD_Lock( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) ; extern uint32_t FLASHD_Lock( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) ;
extern uint32_t FLASHD_Unlock( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) ; extern uint32_t FLASHD_Unlock( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) ;
extern uint32_t FLASHD_IsLocked( uint32_t dwStart, uint32_t dwEnd ) ; extern uint32_t FLASHD_IsLocked( uint32_t dwStart, uint32_t dwEnd ) ;
extern uint32_t FLASHD_SetGPNVM( uint8_t gpnvm ) ; extern uint32_t FLASHD_SetGPNVM( uint8_t gpnvm ) ;
extern uint32_t FLASHD_ClearGPNVM( uint8_t gpnvm ) ; extern uint32_t FLASHD_ClearGPNVM( uint8_t gpnvm ) ;
extern uint32_t FLASHD_IsGPNVMSet( uint8_t gpnvm ) ; extern uint32_t FLASHD_IsGPNVMSet( uint8_t gpnvm ) ;
#define FLASHD_IsSecurityBitSet() FLASHD_IsGPNVMSet( 0 ) #define FLASHD_IsSecurityBitSet() FLASHD_IsGPNVMSet( 0 )
#define FLASHD_SetSecurityBit() FLASHD_SetGPNVM( 0 ) #define FLASHD_SetSecurityBit() FLASHD_SetGPNVM( 0 )
extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID ) ; extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID ) ;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* #ifndef _FLASHD_ */ #endif /* #ifndef _FLASHD_ */

View File

@@ -1,290 +1,290 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** \addtogroup efc_module Working with EEFC /** \addtogroup efc_module Working with EEFC
* The EEFC driver provides the interface to configure and use the EEFC * The EEFC driver provides the interface to configure and use the EEFC
* peripheral. * peripheral.
* *
* The user needs to set the number of wait states depending on the frequency used.\n * The user needs to set the number of wait states depending on the frequency used.\n
* Configure number of cycles for flash read/write operations in the FWS field of EEFC_FMR. * Configure number of cycles for flash read/write operations in the FWS field of EEFC_FMR.
* *
* It offers a function to send flash command to EEFC and waits for the * It offers a function to send flash command to EEFC and waits for the
* flash to be ready. * flash to be ready.
* *
* To send flash command, the user could do in either of following way: * To send flash command, the user could do in either of following way:
* <ul> * <ul>
* <li>Write a correct key, command and argument in EEFC_FCR. </li> * <li>Write a correct key, command and argument in EEFC_FCR. </li>
* <li>Or, Use IAP (In Application Programming) function which is executed from * <li>Or, Use IAP (In Application Programming) function which is executed from
* ROM directly, this allows flash programming to be done by code running in flash.</li> * ROM directly, this allows flash programming to be done by code running in flash.</li>
* <li>Once the command is achieved, it can be detected even by polling EEFC_FSR or interrupt. * <li>Once the command is achieved, it can be detected even by polling EEFC_FSR or interrupt.
* </ul> * </ul>
* *
* The command argument could be a page number,GPNVM number or nothing, it depends on * The command argument could be a page number,GPNVM number or nothing, it depends on
* the command itself. Some useful functions in this driver could help user tranlate physical * the command itself. Some useful functions in this driver could help user tranlate physical
* flash address into a page number and vice verse. * flash address into a page number and vice verse.
* *
* For more accurate information, please look at the EEFC section of the * For more accurate information, please look at the EEFC section of the
* Datasheet. * Datasheet.
* *
* Related files :\n * Related files :\n
* \ref efc.c\n * \ref efc.c\n
* \ref efc.h.\n * \ref efc.h.\n
*/ */
/*@{*/ /*@{*/
/*@}*/ /*@}*/
/** /**
* \file * \file
* *
* Implementation of Enhanced Embedded Flash Controller (EEFC). * Implementation of Enhanced Embedded Flash Controller (EEFC).
* *
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include "efc.h" #include "efc.h"
#include <assert.h> #include <assert.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Enables the flash ready interrupt source on the EEFC peripheral. * \brief Enables the flash ready interrupt source on the EEFC peripheral.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
*/ */
extern void EFC_EnableFrdyIt( Efc* efc ) extern void EFC_EnableFrdyIt( Efc* efc )
{ {
efc->EEFC_FMR |= EEFC_FMR_FRDY ; efc->EEFC_FMR |= EEFC_FMR_FRDY ;
} }
/** /**
* \brief Disables the flash ready interrupt source on the EEFC peripheral. * \brief Disables the flash ready interrupt source on the EEFC peripheral.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
*/ */
extern void EFC_DisableFrdyIt( Efc* efc ) extern void EFC_DisableFrdyIt( Efc* efc )
{ {
efc->EEFC_FMR &= ~((uint32_t)EEFC_FMR_FRDY) ; efc->EEFC_FMR &= ~((uint32_t)EEFC_FMR_FRDY) ;
} }
/** /**
* \brief Set read/write wait state on the EEFC perpherial. * \brief Set read/write wait state on the EEFC perpherial.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
* \param cycles the number of wait states in cycle. * \param cycles the number of wait states in cycle.
*/ */
extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles ) extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles )
{ {
uint32_t dwValue ; uint32_t dwValue ;
dwValue = efc->EEFC_FMR ; dwValue = efc->EEFC_FMR ;
dwValue &= ~((uint32_t)EEFC_FMR_FWS_Msk) ; dwValue &= ~((uint32_t)EEFC_FMR_FWS_Msk) ;
dwValue |= EEFC_FMR_FWS(ucCycles); dwValue |= EEFC_FMR_FWS(ucCycles);
efc->EEFC_FMR = dwValue ; efc->EEFC_FMR = dwValue ;
} }
/** /**
* \brief Returns the current status of the EEFC. * \brief Returns the current status of the EEFC.
* *
* \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE). * \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE).
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
*/ */
extern uint32_t EFC_GetStatus( Efc* efc ) extern uint32_t EFC_GetStatus( Efc* efc )
{ {
return efc->EEFC_FSR ; return efc->EEFC_FSR ;
} }
/** /**
* \brief Returns the result of the last executed command. * \brief Returns the result of the last executed command.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
*/ */
extern uint32_t EFC_GetResult( Efc* efc ) extern uint32_t EFC_GetResult( Efc* efc )
{ {
return efc->EEFC_FRR ; return efc->EEFC_FRR ;
} }
/** /**
* \brief Translates the given address page and offset values. * \brief Translates the given address page and offset values.
* \note The resulting values are stored in the provided variables if they are not null. * \note The resulting values are stored in the provided variables if they are not null.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
* \param address Address to translate. * \param address Address to translate.
* \param pPage First page accessed. * \param pPage First page accessed.
* \param pOffset Byte offset in first page. * \param pOffset Byte offset in first page.
*/ */
extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset ) extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset )
{ {
Efc *pEfc ; Efc *pEfc ;
uint16_t wPage ; uint16_t wPage ;
uint16_t wOffset ; uint16_t wOffset ;
assert( dwAddress >= IFLASH_ADDR ) ; assert( dwAddress >= IFLASH_ADDR ) ;
assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ; assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
pEfc = EFC ; pEfc = EFC ;
wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE; wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE;
wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE; wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE;
TRACE_DEBUG( "Translated 0x%08X to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ; TRACE_DEBUG( "Translated 0x%08lX to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ;
/* Store values */ /* Store values */
if ( pEfc ) if ( pEfc )
{ {
*ppEfc = pEfc ; *ppEfc = pEfc ;
} }
if ( pwPage ) if ( pwPage )
{ {
*pwPage = wPage ; *pwPage = wPage ;
} }
if ( pwOffset ) if ( pwOffset )
{ {
*pwOffset = wOffset ; *pwOffset = wOffset ;
} }
} }
/** /**
* \brief Computes the address of a flash access given the page and offset. * \brief Computes the address of a flash access given the page and offset.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
* \param page Page number. * \param page Page number.
* \param offset Byte offset inside page. * \param offset Byte offset inside page.
* \param pAddress Computed address (optional). * \param pAddress Computed address (optional).
*/ */
extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress ) extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress )
{ {
uint32_t dwAddress ; uint32_t dwAddress ;
assert( efc ) ; assert( efc ) ;
assert( wPage <= IFLASH_NB_OF_PAGES ) ; assert( wPage <= IFLASH_NB_OF_PAGES ) ;
assert( wOffset < IFLASH_PAGE_SIZE ) ; assert( wOffset < IFLASH_PAGE_SIZE ) ;
/* Compute address */ /* Compute address */
dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ; dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ;
/* Store result */ /* Store result */
if ( pdwAddress != NULL ) if ( pdwAddress != NULL )
{ {
*pdwAddress = dwAddress ; *pdwAddress = dwAddress ;
} }
} }
/** /**
* \brief Starts the executing the given command on the EEFC and returns as soon as the command is started. * \brief Starts the executing the given command on the EEFC and returns as soon as the command is started.
* *
* \note It does NOT set the FMCN field automatically. * \note It does NOT set the FMCN field automatically.
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
* \param command Command to execute. * \param command Command to execute.
* \param argument Command argument (should be 0 if not used). * \param argument Command argument (should be 0 if not used).
*/ */
extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument ) extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument )
{ {
/* Check command & argument */ /* Check command & argument */
switch ( dwCommand ) switch ( dwCommand )
{ {
case EFC_FCMD_WP: case EFC_FCMD_WP:
case EFC_FCMD_WPL: case EFC_FCMD_WPL:
case EFC_FCMD_EWP: case EFC_FCMD_EWP:
case EFC_FCMD_EWPL: case EFC_FCMD_EWPL:
case EFC_FCMD_SLB: case EFC_FCMD_SLB:
case EFC_FCMD_CLB: case EFC_FCMD_CLB:
assert( dwArgument < IFLASH_NB_OF_PAGES ) ; assert( dwArgument < IFLASH_NB_OF_PAGES ) ;
break ; break ;
case EFC_FCMD_SFB: case EFC_FCMD_SFB:
case EFC_FCMD_CFB: case EFC_FCMD_CFB:
assert( dwArgument < 2 ) ; assert( dwArgument < 2 ) ;
break; break;
case EFC_FCMD_GETD: case EFC_FCMD_GETD:
case EFC_FCMD_EA: case EFC_FCMD_EA:
case EFC_FCMD_GLB: case EFC_FCMD_GLB:
case EFC_FCMD_GFB: case EFC_FCMD_GFB:
case EFC_FCMD_STUI: case EFC_FCMD_STUI:
assert( dwArgument == 0 ) ; assert( dwArgument == 0 ) ;
break; break;
default: assert( 0 ) ; default: assert( 0 ) ;
} }
/* Start command Embedded flash */ /* Start command Embedded flash */
assert( (efc->EEFC_FSR & EEFC_FMR_FRDY) == EEFC_FMR_FRDY ) ; assert( (efc->EEFC_FSR & EEFC_FMR_FRDY) == EEFC_FMR_FRDY ) ;
efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ; efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
} }
/** /**
* \brief Performs the given command and wait until its completion (or an error). * \brief Performs the given command and wait until its completion (or an error).
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
* \param command Command to perform. * \param command Command to perform.
* \param argument Optional command argument. * \param argument Optional command argument.
* *
* \return 0 if successful, otherwise returns an error code. * \return 0 if successful, otherwise returns an error code.
*/ */
extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP ) extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP )
{ {
if ( dwUseIAP != 0 ) if ( dwUseIAP != 0 )
{ {
/* Pointer on IAP function in ROM */ /* Pointer on IAP function in ROM */
static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ; static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ;
IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ; IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ;
IAP_PerformCommand( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ; IAP_PerformCommand( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ;
return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ; return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ;
} }
else else
{ {
uint32_t dwStatus ; uint32_t dwStatus ;
efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ; efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
do do
{ {
dwStatus = efc->EEFC_FSR ; dwStatus = efc->EEFC_FSR ;
} }
while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ; while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ;
return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ; return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,453 +1,453 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2010, Atmel Corporation * Copyright (c) 2010, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** \file */ /** \file */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include "pio.h" #include "pio.h"
#include "pmc.h" #include "pmc.h"
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local functions * Local functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Configures one or more pin(s) of a PIO controller as being controlled by * \brief Configures one or more pin(s) of a PIO controller as being controlled by
* peripheral A. Optionally, the corresponding internal pull-up(s) can be enabled. * peripheral A. Optionally, the corresponding internal pull-up(s) can be enabled.
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask of one or more pin(s) to configure. * \param mask Bitmask of one or more pin(s) to configure.
* \param enablePullUp Indicates if the pin(s) internal pull-up shall be * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
* configured. * configured.
*/ */
static void PIO_SetPeripheralA( static void PIO_SetPeripheralA(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char enablePullUp) unsigned char enablePullUp)
{ {
unsigned int abcdsr; unsigned int abcdsr;
/* Disable interrupts on the pin(s) */ /* Disable interrupts on the pin(s) */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable the pull-up(s) if necessary */ /* Enable the pull-up(s) if necessary */
if (enablePullUp) { if (enablePullUp) {
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
} }
else { else {
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
} }
abcdsr = pio->PIO_ABCDSR[0]; abcdsr = pio->PIO_ABCDSR[0];
pio->PIO_ABCDSR[0] &= (~mask & abcdsr); pio->PIO_ABCDSR[0] &= (~mask & abcdsr);
abcdsr = pio->PIO_ABCDSR[1]; abcdsr = pio->PIO_ABCDSR[1];
pio->PIO_ABCDSR[1] &= (~mask & abcdsr); pio->PIO_ABCDSR[1] &= (~mask & abcdsr);
pio->PIO_PDR = mask; pio->PIO_PDR = mask;
} }
/** /**
* \brief Configures one or more pin(s) of a PIO controller as being controlled by * \brief Configures one or more pin(s) of a PIO controller as being controlled by
* peripheral B. Optionally, the corresponding internal pull-up(s) can be enabled. * peripheral B. Optionally, the corresponding internal pull-up(s) can be enabled.
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask of one or more pin(s) to configure. * \param mask Bitmask of one or more pin(s) to configure.
* \param enablePullUp Indicates if the pin(s) internal pull-up shall be * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
* configured. * configured.
*/ */
static void PIO_SetPeripheralB( static void PIO_SetPeripheralB(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char enablePullUp) unsigned char enablePullUp)
{ {
unsigned int abcdsr; unsigned int abcdsr;
/* Disable interrupts on the pin(s) */ /* Disable interrupts on the pin(s) */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable the pull-up(s) if necessary */ /* Enable the pull-up(s) if necessary */
if (enablePullUp) { if (enablePullUp) {
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
} }
else { else {
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
} }
abcdsr = pio->PIO_ABCDSR[0]; abcdsr = pio->PIO_ABCDSR[0];
pio->PIO_ABCDSR[0] = (mask | abcdsr); pio->PIO_ABCDSR[0] = (mask | abcdsr);
abcdsr = pio->PIO_ABCDSR[1]; abcdsr = pio->PIO_ABCDSR[1];
pio->PIO_ABCDSR[1] &= (~mask & abcdsr); pio->PIO_ABCDSR[1] &= (~mask & abcdsr);
pio->PIO_PDR = mask; pio->PIO_PDR = mask;
} }
/** /**
* \brief Configures one or more pin(s) of a PIO controller as being controlled by * \brief Configures one or more pin(s) of a PIO controller as being controlled by
* peripheral C. Optionally, the corresponding internal pull-up(s) can be enabled. * peripheral C. Optionally, the corresponding internal pull-up(s) can be enabled.
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask of one or more pin(s) to configure. * \param mask Bitmask of one or more pin(s) to configure.
* \param enablePullUp Indicates if the pin(s) internal pull-up shall be * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
* configured. * configured.
*/ */
static void PIO_SetPeripheralC( static void PIO_SetPeripheralC(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char enablePullUp) unsigned char enablePullUp)
{ {
unsigned int abcdsr; unsigned int abcdsr;
/* Disable interrupts on the pin(s) */ /* Disable interrupts on the pin(s) */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable the pull-up(s) if necessary */ /* Enable the pull-up(s) if necessary */
if (enablePullUp) { if (enablePullUp) {
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
} }
else { else {
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
} }
abcdsr = pio->PIO_ABCDSR[0]; abcdsr = pio->PIO_ABCDSR[0];
pio->PIO_ABCDSR[0] &= (~mask & abcdsr); pio->PIO_ABCDSR[0] &= (~mask & abcdsr);
abcdsr = pio->PIO_ABCDSR[1]; abcdsr = pio->PIO_ABCDSR[1];
pio->PIO_ABCDSR[1] = (mask | abcdsr); pio->PIO_ABCDSR[1] = (mask | abcdsr);
pio->PIO_PDR = mask; pio->PIO_PDR = mask;
} }
/** /**
* \brief Configures one or more pin(s) of a PIO controller as being controlled by * \brief Configures one or more pin(s) of a PIO controller as being controlled by
* peripheral D. Optionally, the corresponding internal pull-up(s) can be enabled. * peripheral D. Optionally, the corresponding internal pull-up(s) can be enabled.
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask of one or more pin(s) to configure. * \param mask Bitmask of one or more pin(s) to configure.
* \param enablePullUp Indicates if the pin(s) internal pull-up shall be * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
* configured. * configured.
*/ */
static void PIO_SetPeripheralD( static void PIO_SetPeripheralD(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char enablePullUp) unsigned char enablePullUp)
{ {
unsigned int abcdsr; unsigned int abcdsr;
/* Disable interrupts on the pin(s) */ /* Disable interrupts on the pin(s) */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable the pull-up(s) if necessary */ /* Enable the pull-up(s) if necessary */
if (enablePullUp) { if (enablePullUp) {
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
} }
else { else {
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
} }
abcdsr = pio->PIO_ABCDSR[0]; abcdsr = pio->PIO_ABCDSR[0];
pio->PIO_ABCDSR[0] = (mask | abcdsr); pio->PIO_ABCDSR[0] = (mask | abcdsr);
abcdsr = pio->PIO_ABCDSR[1]; abcdsr = pio->PIO_ABCDSR[1];
pio->PIO_ABCDSR[1] = (mask | abcdsr); pio->PIO_ABCDSR[1] = (mask | abcdsr);
pio->PIO_PDR = mask; pio->PIO_PDR = mask;
} }
/** /**
* \brief Configures one or more pin(s) or a PIO controller as inputs. Optionally, * \brief Configures one or more pin(s) or a PIO controller as inputs. Optionally,
* the corresponding internal pull-up(s) and glitch filter(s) can be enabled. * the corresponding internal pull-up(s) and glitch filter(s) can be enabled.
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask indicating which pin(s) to configure as input(s). * \param mask Bitmask indicating which pin(s) to configure as input(s).
* \param enablePullUp Indicates if the internal pull-up(s) must be enabled. * \param enablePullUp Indicates if the internal pull-up(s) must be enabled.
* \param enableFilter Indicates if the glitch filter(s) must be enabled. * \param enableFilter Indicates if the glitch filter(s) must be enabled.
*/ */
static void PIO_SetInput( static void PIO_SetInput(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char attribute) unsigned char attribute)
{ {
/* Disable interrupts */ /* Disable interrupts */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable pull-up(s) if necessary */ /* Enable pull-up(s) if necessary */
if (attribute & PIO_PULLUP) if (attribute & PIO_PULLUP)
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
else else
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
/* Enable Input Filter if necessary */ /* Enable Input Filter if necessary */
if (attribute & (PIO_DEGLITCH | PIO_DEBOUNCE)) if (attribute & (PIO_DEGLITCH | PIO_DEBOUNCE))
pio->PIO_IFER = mask; pio->PIO_IFER = mask;
else else
pio->PIO_IFDR = mask; pio->PIO_IFDR = mask;
/* Enable de-glitch or de-bounce if necessary */ /* Enable de-glitch or de-bounce if necessary */
if (attribute & PIO_DEGLITCH) if (attribute & PIO_DEGLITCH)
{ {
pio->PIO_IFSCDR = mask; pio->PIO_IFSCDR = mask;
} }
else else
{ {
if (attribute & PIO_DEBOUNCE) if (attribute & PIO_DEBOUNCE)
{ {
pio->PIO_IFSCER = mask; pio->PIO_IFSCER = mask;
} }
} }
/* Configure pin as input */ /* Configure pin as input */
pio->PIO_ODR = mask; pio->PIO_ODR = mask;
pio->PIO_PER = mask; pio->PIO_PER = mask;
} }
/** /**
* \brief Configures one or more pin(s) of a PIO controller as outputs, with the * \brief Configures one or more pin(s) of a PIO controller as outputs, with the
* given default value. Optionally, the multi-drive feature can be enabled * given default value. Optionally, the multi-drive feature can be enabled
* on the pin(s). * on the pin(s).
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask indicating which pin(s) to configure. * \param mask Bitmask indicating which pin(s) to configure.
* \param defaultValue Default level on the pin(s). * \param defaultValue Default level on the pin(s).
* \param enableMultiDrive Indicates if the pin(s) shall be configured as * \param enableMultiDrive Indicates if the pin(s) shall be configured as
* open-drain. * open-drain.
* \param enablePullUp Indicates if the pin shall have its pull-up activated. * \param enablePullUp Indicates if the pin shall have its pull-up activated.
*/ */
static void PIO_SetOutput( static void PIO_SetOutput(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char defaultValue, unsigned char defaultValue,
unsigned char enableMultiDrive, unsigned char enableMultiDrive,
unsigned char enablePullUp) unsigned char enablePullUp)
{ {
/* Disable interrupts */ /* Disable interrupts */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable pull-up(s) if necessary */ /* Enable pull-up(s) if necessary */
if (enablePullUp) { if (enablePullUp) {
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
} }
else { else {
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
} }
/* Enable multi-drive if necessary */ /* Enable multi-drive if necessary */
if (enableMultiDrive) { if (enableMultiDrive) {
pio->PIO_MDER = mask; pio->PIO_MDER = mask;
} }
else { else {
pio->PIO_MDDR = mask; pio->PIO_MDDR = mask;
} }
/* Set default value */ /* Set default value */
if (defaultValue) { if (defaultValue) {
pio->PIO_SODR = mask; pio->PIO_SODR = mask;
} }
else { else {
pio->PIO_CODR = mask; pio->PIO_CODR = mask;
} }
/* Configure pin(s) as output(s) */ /* Configure pin(s) as output(s) */
pio->PIO_OER = mask; pio->PIO_OER = mask;
pio->PIO_PER = mask; pio->PIO_PER = mask;
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Global functions * Global functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Configures a list of Pin instances, each of which can either hold a single * \brief Configures a list of Pin instances, each of which can either hold a single
* pin or a group of pins, depending on the mask value; all pins are configured * pin or a group of pins, depending on the mask value; all pins are configured
* by this function. The size of the array must also be provided and is easily * by this function. The size of the array must also be provided and is easily
* computed using PIO_LISTSIZE whenever its length is not known in advance. * computed using PIO_LISTSIZE whenever its length is not known in advance.
* *
* \param list Pointer to a list of Pin instances. * \param list Pointer to a list of Pin instances.
* \param size Size of the Pin list (calculated using PIO_LISTSIZE). * \param size Size of the Pin list (calculated using PIO_LISTSIZE).
* *
* \return 1 if the pins have been configured properly; otherwise 0. * \return 1 if the pins have been configured properly; otherwise 0.
*/ */
uint8_t PIO_Configure( const Pin *list, uint32_t size ) uint8_t PIO_Configure( const Pin *list, uint32_t size )
{ {
/* Configure pins */ /* Configure pins */
while ( size > 0 ) while ( size > 0 )
{ {
switch ( list->type ) switch ( list->type )
{ {
case PIO_PERIPH_A: case PIO_PERIPH_A:
PIO_SetPeripheralA(list->pio, PIO_SetPeripheralA(list->pio,
list->mask, list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0); (list->attribute & PIO_PULLUP) ? 1 : 0);
break; break;
case PIO_PERIPH_B: case PIO_PERIPH_B:
PIO_SetPeripheralB(list->pio, PIO_SetPeripheralB(list->pio,
list->mask, list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0); (list->attribute & PIO_PULLUP) ? 1 : 0);
break; break;
case PIO_PERIPH_C: case PIO_PERIPH_C:
PIO_SetPeripheralC(list->pio, PIO_SetPeripheralC(list->pio,
list->mask, list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0); (list->attribute & PIO_PULLUP) ? 1 : 0);
break; break;
case PIO_PERIPH_D: case PIO_PERIPH_D:
PIO_SetPeripheralD(list->pio, PIO_SetPeripheralD(list->pio,
list->mask, list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0); (list->attribute & PIO_PULLUP) ? 1 : 0);
break; break;
case PIO_INPUT: case PIO_INPUT:
PMC_EnablePeripheral(list->id); PMC_EnablePeripheral(list->id);
PIO_SetInput(list->pio, PIO_SetInput(list->pio,
list->mask, list->mask,
list->attribute); list->attribute);
break; break;
case PIO_OUTPUT_0: case PIO_OUTPUT_0:
case PIO_OUTPUT_1: case PIO_OUTPUT_1:
PIO_SetOutput(list->pio, PIO_SetOutput(list->pio,
list->mask, list->mask,
(list->type == PIO_OUTPUT_1), (list->type == PIO_OUTPUT_1),
(list->attribute & PIO_OPENDRAIN) ? 1 : 0, (list->attribute & PIO_OPENDRAIN) ? 1 : 0,
(list->attribute & PIO_PULLUP) ? 1 : 0); (list->attribute & PIO_PULLUP) ? 1 : 0);
break; break;
default: return 0; default: return 0;
} }
list++; list++;
size--; size--;
} }
return 1; return 1;
} }
/** /**
* \brief Sets a high output level on all the PIOs defined in the given Pin instance. * \brief Sets a high output level on all the PIOs defined in the given Pin instance.
* This has no immediate effects on PIOs that are not output, but the PIO * This has no immediate effects on PIOs that are not output, but the PIO
* controller will memorize the value they are changed to outputs. * controller will memorize the value they are changed to outputs.
* *
* \param pin Pointer to a Pin instance describing one or more pins. * \param pin Pointer to a Pin instance describing one or more pins.
*/ */
void PIO_Set(const Pin *pin) void PIO_Set(const Pin *pin)
{ {
pin->pio->PIO_SODR = pin->mask; pin->pio->PIO_SODR = pin->mask;
} }
/** /**
* \brief Sets a low output level on all the PIOs defined in the given Pin instance. * \brief Sets a low output level on all the PIOs defined in the given Pin instance.
* This has no immediate effects on PIOs that are not output, but the PIO * This has no immediate effects on PIOs that are not output, but the PIO
* controller will memorize the value they are changed to outputs. * controller will memorize the value they are changed to outputs.
* *
* \param pin Pointer to a Pin instance describing one or more pins. * \param pin Pointer to a Pin instance describing one or more pins.
*/ */
void PIO_Clear(const Pin *pin) void PIO_Clear(const Pin *pin)
{ {
pin->pio->PIO_CODR = pin->mask; pin->pio->PIO_CODR = pin->mask;
} }
/** /**
* \brief Returns 1 if one or more PIO of the given Pin instance currently have * \brief Returns 1 if one or more PIO of the given Pin instance currently have
* a high level; otherwise returns 0. This method returns the actual value that * a high level; otherwise returns 0. This method returns the actual value that
* is being read on the pin. To return the supposed output value of a pin, use * is being read on the pin. To return the supposed output value of a pin, use
* PIO_GetOutputDataStatus() instead. * PIO_GetOutputDataStatus() instead.
* *
* \param pin Pointer to a Pin instance describing one or more pins. * \param pin Pointer to a Pin instance describing one or more pins.
* *
* \return 1 if the Pin instance contains at least one PIO that currently has * \return 1 if the Pin instance contains at least one PIO that currently has
* a high level; otherwise 0. * a high level; otherwise 0.
*/ */
unsigned char PIO_Get( const Pin *pin ) unsigned char PIO_Get( const Pin *pin )
{ {
unsigned int reg ; unsigned int reg ;
if ( (pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1) ) if ( (pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1) )
{ {
reg = pin->pio->PIO_ODSR ; reg = pin->pio->PIO_ODSR ;
} }
else else
{ {
reg = pin->pio->PIO_PDSR ; reg = pin->pio->PIO_PDSR ;
} }
if ( (reg & pin->mask) == 0 ) if ( (reg & pin->mask) == 0 )
{ {
return 0 ; return 0 ;
} }
else else
{ {
return 1 ; return 1 ;
} }
} }
/** /**
* \brief Returns 1 if one or more PIO of the given Pin are configured to output a * \brief Returns 1 if one or more PIO of the given Pin are configured to output a
* high level (even if they are not output). * high level (even if they are not output).
* To get the actual value of the pin, use PIO_Get() instead. * To get the actual value of the pin, use PIO_Get() instead.
* *
* \param pin Pointer to a Pin instance describing one or more pins. * \param pin Pointer to a Pin instance describing one or more pins.
* *
* \return 1 if the Pin instance contains at least one PIO that is configured * \return 1 if the Pin instance contains at least one PIO that is configured
* to output a high level; otherwise 0. * to output a high level; otherwise 0.
*/ */
unsigned char PIO_GetOutputDataStatus(const Pin *pin) unsigned char PIO_GetOutputDataStatus(const Pin *pin)
{ {
if ((pin->pio->PIO_ODSR & pin->mask) == 0) { if ((pin->pio->PIO_ODSR & pin->mask) == 0) {
return 0; return 0;
} }
else { else {
return 1; return 1;
} }
} }
/* /*
* \brief Configures Glitch or Debouncing filter for input. * \brief Configures Glitch or Debouncing filter for input.
* *
* \param pin Pointer to a Pin instance describing one or more pins. * \param pin Pointer to a Pin instance describing one or more pins.
* \param cuttoff Cutt off frequency for debounce filter. * \param cuttoff Cutt off frequency for debounce filter.
*/ */
void PIO_SetDebounceFilter( const Pin *pin, uint32_t cuttoff ) void PIO_SetDebounceFilter( const Pin *pin, uint32_t cuttoff )
{ {
Pio *pio = pin->pio; Pio *pio = pin->pio;
pio->PIO_IFSCER = pin->mask; /* set Debouncing, 0 bit field no effect */ pio->PIO_IFSCER = pin->mask; /* set Debouncing, 0 bit field no effect */
pio->PIO_SCDR = ((32678/(2*(cuttoff))) - 1) & 0x3FFF; /* the lowest 14 bits work */ pio->PIO_SCDR = ((32678/(2*(cuttoff))) - 1) & 0x3FFF; /* the lowest 14 bits work */
} }

View File

@@ -1,315 +1,327 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation * Copyright (c) 2008, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/* /*
* \file * \file
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include <assert.h> #include <assert.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local definitions * Local definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/* Maximum number of interrupt sources that can be defined. This /* Maximum number of interrupt sources that can be defined. This
* constant can be increased, but the current value is the smallest possible * constant can be increased, but the current value is the smallest possible
* that will be compatible with all existing projects. */ * that will be compatible with all existing projects. */
#define MAX_INTERRUPT_SOURCES 7 #define MAX_INTERRUPT_SOURCES 7
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local types * Local types
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* Describes a PIO interrupt source, including the PIO instance triggering the * Describes a PIO interrupt source, including the PIO instance triggering the
* interrupt and the associated interrupt handler. * interrupt and the associated interrupt handler.
*/ */
typedef struct _InterruptSource typedef struct _InterruptSource
{ {
/* Pointer to the source pin instance. */ /* Pointer to the source pin instance. */
const Pin *pPin; const Pin *pPin;
/* Interrupt handler. */ /* Interrupt handler. */
void (*handler)( const Pin* ) ; void (*handler)( const Pin* ) ;
} InterruptSource ; } InterruptSource ;
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local variables * Local variables
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/* List of interrupt sources. */ /* List of interrupt sources. */
static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES] ; static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES] ;
/* Number of currently defined interrupt sources. */ /* Number of currently defined interrupt sources. */
static uint32_t _dwNumSources = 0; static uint32_t _dwNumSources = 0;
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local Functions * Local Functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/** /**
* \brief Stub, to handling all PIO Capture interrupts, if not defined. * \brief Stub, to handling all PIO Capture interrupts, if not defined.
*/ */
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
extern WEAK void PIO_CaptureHandler( void ) extern WEAK void PIO_CaptureHandler( void )
{ {
} }
/** /**
* \brief Handles all interrupts on the given PIO controller. * \brief Handles all interrupts on the given PIO controller.
* \param id PIO controller ID. * \param id PIO controller ID.
* \param pPio PIO controller base address. * \param pPio PIO controller base address.
*/ */
extern void PioInterruptHandler( uint32_t id, Pio *pPio ) extern void PioInterruptHandler( uint32_t id, Pio *pPio )
{ {
uint32_t status; uint32_t status;
uint32_t i; uint32_t i;
/* Read PIO controller status */ /* Read PIO controller status */
status = pPio->PIO_ISR; status = pPio->PIO_ISR;
status &= pPio->PIO_IMR; status &= pPio->PIO_IMR;
/* Check pending events */ /* Check pending events */
if ( status != 0 ) if ( status != 0 )
{ {
TRACE_DEBUG( "PIO interrupt on PIO controller #%" PRIu32 "\n\r", id ) ; TRACE_DEBUG( "PIO interrupt on PIO controller #%" PRIu32 "\n\r", id ) ;
/* Find triggering source */ /* Find triggering source */
i = 0; i = 0;
while ( status != 0 ) while ( status != 0 )
{ {
/* There cannot be an unconfigured source enabled. */ /* There cannot be an unconfigured source enabled. */
assert(i < _dwNumSources); assert(i < _dwNumSources);
/* Source is configured on the same controller */ /* Source is configured on the same controller */
if (_aIntSources[i].pPin->id == id) if (_aIntSources[i].pPin->id == id)
{ {
/* Source has PIOs whose statuses have changed */ /* Source has PIOs whose statuses have changed */
if ( (status & _aIntSources[i].pPin->mask) != 0 ) if ( (status & _aIntSources[i].pPin->mask) != 0 )
{ {
TRACE_DEBUG( "Interrupt source #%" PRIu32 " triggered\n\r", i ) ; TRACE_DEBUG( "Interrupt source #%" PRIu32 " triggered\n\r", i ) ;
_aIntSources[i].handler(_aIntSources[i].pPin); _aIntSources[i].handler(_aIntSources[i].pPin);
status &= ~(_aIntSources[i].pPin->mask); status &= ~(_aIntSources[i].pPin->mask);
} }
} }
i++; i++;
} }
} }
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Global Functions * Global Functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Parallel IO Controller A interrupt handler * \brief Parallel IO Controller A interrupt handler
* \Redefined PIOA interrupt handler for NVIC interrupt table. * \Redefined PIOA interrupt handler for NVIC interrupt table.
*/ */
extern void PIOA_IrqHandler( void ) extern void PIOA_IrqHandler( void )
{ {
if ( PIOA->PIO_PCISR != 0 ) if ( PIOA->PIO_PCISR != 0 )
{ {
PIO_CaptureHandler() ; PIO_CaptureHandler() ;
} }
PioInterruptHandler( ID_PIOA, PIOA ) ; PioInterruptHandler( ID_PIOA, PIOA ) ;
} }
/** /**
* \brief Parallel IO Controller B interrupt handler * \brief Parallel IO Controller B interrupt handler
* \Redefined PIOB interrupt handler for NVIC interrupt table. * \Redefined PIOB interrupt handler for NVIC interrupt table.
*/ */
extern void PIOB_IrqHandler( void ) extern void PIOB_IrqHandler( void )
{ {
PioInterruptHandler( ID_PIOB, PIOB ) ; PioInterruptHandler( ID_PIOB, PIOB ) ;
} }
/** /**
* \brief Parallel IO Controller C interrupt handler * \brief Parallel IO Controller C interrupt handler
* \Redefined PIOC interrupt handler for NVIC interrupt table. * \Redefined PIOC interrupt handler for NVIC interrupt table.
*/ */
extern void PIOC_IrqHandler( void ) extern void PIOC_IrqHandler( void )
{ {
PioInterruptHandler( ID_PIOC, PIOC ) ; PioInterruptHandler( ID_PIOC, PIOC ) ;
} }
/** /**
* \brief Initializes the PIO interrupt management logic * \brief Initializes the PIO interrupt management logic
* *
* The desired priority of PIO interrupts must be provided. * The desired priority of PIO interrupts must be provided.
* Calling this function multiple times result in the reset of currently * Calling this function multiple times result in the reset of currently
* configured interrupts. * configured interrupts.
* *
* \param priority PIO controller interrupts priority. * \param priority PIO controller interrupts priority.
*/ */
extern void PIO_InitializeInterrupts( uint32_t dwPriority ) extern void PIO_InitializeInterrupts( uint32_t dwPriority )
{ {
TRACE_DEBUG( "PIO_Initialize()\n\r" ) ; TRACE_DEBUG( "PIO_Initialize()\n\r" ) ;
/* Reset sources */ /* Reset sources */
_dwNumSources = 0 ; _dwNumSources = 0 ;
/* Configure PIO interrupt sources */ /* Configure PIO interrupt sources */
TRACE_DEBUG( "PIO_Initialize: Configuring PIOA\n\r" ) ; TRACE_DEBUG( "PIO_Initialize: Configuring PIOA\n\r" ) ;
PMC_EnablePeripheral( ID_PIOA ) ; PMC_EnablePeripheral( ID_PIOA ) ;
PIOA->PIO_ISR ; PIOA->PIO_ISR ;
PIOA->PIO_IDR = 0xFFFFFFFF ; PIOA->PIO_IDR = 0xFFFFFFFF ;
NVIC_DisableIRQ( PIOA_IRQn ) ; NVIC_DisableIRQ( PIOA_IRQn ) ;
NVIC_ClearPendingIRQ( PIOA_IRQn ) ; NVIC_ClearPendingIRQ( PIOA_IRQn ) ;
NVIC_SetPriority( PIOA_IRQn, dwPriority ) ; NVIC_SetPriority( PIOA_IRQn, dwPriority ) ;
NVIC_EnableIRQ( PIOA_IRQn ) ; NVIC_EnableIRQ( PIOA_IRQn ) ;
TRACE_DEBUG( "PIO_Initialize: Configuring PIOB\n\r" ) ; TRACE_DEBUG( "PIO_Initialize: Configuring PIOB\n\r" ) ;
PMC_EnablePeripheral( ID_PIOB ) ; PMC_EnablePeripheral( ID_PIOB ) ;
PIOB->PIO_ISR ; PIOB->PIO_ISR ;
PIOB->PIO_IDR = 0xFFFFFFFF ; PIOB->PIO_IDR = 0xFFFFFFFF ;
NVIC_DisableIRQ( PIOB_IRQn ) ; NVIC_DisableIRQ( PIOB_IRQn ) ;
NVIC_ClearPendingIRQ( PIOB_IRQn ) ; NVIC_ClearPendingIRQ( PIOB_IRQn ) ;
NVIC_SetPriority( PIOB_IRQn, dwPriority ) ; NVIC_SetPriority( PIOB_IRQn, dwPriority ) ;
NVIC_EnableIRQ( PIOB_IRQn ) ; NVIC_EnableIRQ( PIOB_IRQn ) ;
TRACE_DEBUG( "PIO_Initialize: Configuring PIOC\n\r" ) ; TRACE_DEBUG( "PIO_Initialize: Configuring PIOC\n\r" ) ;
PMC_EnablePeripheral( ID_PIOC ) ; PMC_EnablePeripheral( ID_PIOC ) ;
PIOC->PIO_ISR ; PIOC->PIO_ISR ;
PIOC->PIO_IDR = 0xFFFFFFFF ; PIOC->PIO_IDR = 0xFFFFFFFF ;
NVIC_DisableIRQ( PIOC_IRQn ) ; NVIC_DisableIRQ( PIOC_IRQn ) ;
NVIC_ClearPendingIRQ( PIOC_IRQn ) ; NVIC_ClearPendingIRQ( PIOC_IRQn ) ;
NVIC_SetPriority( PIOC_IRQn, dwPriority ) ; NVIC_SetPriority( PIOC_IRQn, dwPriority ) ;
NVIC_EnableIRQ( PIOC_IRQn ) ; NVIC_EnableIRQ( PIOC_IRQn ) ;
} }
/** static InterruptSource *find_intsource4pin(const Pin *pPin)
* Configures a PIO or a group of PIO to generate an interrupt on status {
* change. The provided interrupt handler will be called with the triggering unsigned int i ;
* pin as its parameter (enabling different pin instances to share the same for (i = 0; i < _dwNumSources; i++) {
* handler). if (_aIntSources[i].pPin == pPin)
* \param pPin Pointer to a Pin instance. return &_aIntSources[i];
* \param handler Interrupt handler function pointer. }
*/ return NULL;
extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) ) }
{
Pio* pio ; /**
InterruptSource* pSource ; * Configures a PIO or a group of PIO to generate an interrupt on status
* change. The provided interrupt handler will be called with the triggering
TRACE_DEBUG( "PIO_ConfigureIt()\n\r" ) ; * pin as its parameter (enabling different pin instances to share the same
* handler).
assert( pPin ) ; * \param pPin Pointer to a Pin instance.
pio = pPin->pio ; * \param handler Interrupt handler function pointer.
assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ; */
extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) )
/* Define new source */ {
TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%" PRIu32 ".\n\r", _dwNumSources ) ; Pio* pio ;
InterruptSource* pSource ;
pSource = &(_aIntSources[_dwNumSources]) ;
pSource->pPin = pPin ; TRACE_DEBUG( "PIO_ConfigureIt()\n\r" ) ;
pSource->handler = handler ;
_dwNumSources++ ; assert( pPin ) ;
pio = pPin->pio ;
/* PIO3 with additional interrupt support
* Configure additional interrupt mode registers */ pSource = find_intsource4pin(pPin);
if ( pPin->attribute & PIO_IT_AIME ) if (!pSource) {
{ /* Define new source */
// enable additional interrupt mode TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%" PRIu32 ".\n\r", _dwNumSources ) ;
pio->PIO_AIMER = pPin->mask ; assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ;
pSource = &(_aIntSources[_dwNumSources]) ;
// if bit field of selected pin is 1, set as Rising Edge/High level detection event pSource->pPin = pPin ;
if ( pPin->attribute & PIO_IT_RE_OR_HL ) _dwNumSources++ ;
{ }
pio->PIO_REHLSR = pPin->mask ; pSource->handler = handler ;
}
else /* PIO3 with additional interrupt support
{ * Configure additional interrupt mode registers */
pio->PIO_FELLSR = pPin->mask; if ( pPin->attribute & PIO_IT_AIME )
} {
// enable additional interrupt mode
/* if bit field of selected pin is 1, set as edge detection source */ pio->PIO_AIMER = pPin->mask ;
if (pPin->attribute & PIO_IT_EDGE)
pio->PIO_ESR = pPin->mask; // if bit field of selected pin is 1, set as Rising Edge/High level detection event
else if ( pPin->attribute & PIO_IT_RE_OR_HL )
pio->PIO_LSR = pPin->mask; {
} pio->PIO_REHLSR = pPin->mask ;
else }
{ else
/* disable additional interrupt mode */ {
pio->PIO_AIMDR = pPin->mask; pio->PIO_FELLSR = pPin->mask;
} }
}
/* if bit field of selected pin is 1, set as edge detection source */
/** if (pPin->attribute & PIO_IT_EDGE)
* Enables the given interrupt source if it has been configured. The status pio->PIO_ESR = pPin->mask;
* register of the corresponding PIO controller is cleared prior to enabling else
* the interrupt. pio->PIO_LSR = pPin->mask;
* \param pPin Interrupt source to enable. }
*/ else
extern void PIO_EnableIt( const Pin *pPin ) {
{ /* disable additional interrupt mode */
TRACE_DEBUG( "PIO_EnableIt()\n\r" ) ; pio->PIO_AIMDR = pPin->mask;
}
assert( pPin != NULL ) ; }
#ifndef NOASSERT /**
uint32_t i = 0; * Enables the given interrupt source if it has been configured. The status
uint32_t dwFound = 0; * register of the corresponding PIO controller is cleared prior to enabling
* the interrupt.
while ( (i < _dwNumSources) && !dwFound ) * \param pPin Interrupt source to enable.
{ */
if ( _aIntSources[i].pPin == pPin ) extern void PIO_EnableIt( const Pin *pPin )
{ {
dwFound = 1 ; TRACE_DEBUG( "PIO_EnableIt()\n\r" ) ;
}
i++ ; assert( pPin != NULL ) ;
}
assert( dwFound != 0 ) ; #ifndef NOASSERT
#endif uint32_t i = 0;
uint32_t dwFound = 0;
pPin->pio->PIO_ISR;
pPin->pio->PIO_IER = pPin->mask ; while ( (i < _dwNumSources) && !dwFound )
} {
if ( _aIntSources[i].pPin == pPin )
/** {
* Disables a given interrupt source, with no added side effects. dwFound = 1 ;
* }
* \param pPin Interrupt source to disable. i++ ;
*/ }
extern void PIO_DisableIt( const Pin *pPin ) assert( dwFound != 0 ) ;
{ #endif
assert( pPin != NULL ) ;
pPin->pio->PIO_ISR;
TRACE_DEBUG( "PIO_DisableIt()\n\r" ) ; pPin->pio->PIO_IER = pPin->mask ;
}
pPin->pio->PIO_IDR = pPin->mask;
} /**
* Disables a given interrupt source, with no added side effects.
*
* \param pPin Interrupt source to disable.
*/
extern void PIO_DisableIt( const Pin *pPin )
{
assert( pPin != NULL ) ;
TRACE_DEBUG( "PIO_DisableIt()\n\r" ) ;
pPin->pio->PIO_IDR = pPin->mask;
}

View File

@@ -1,168 +1,168 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include "trace.h" #include "trace.h"
#include <assert.h> #include <assert.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local definitions * Local definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define MASK_STATUS0 0xFFFFFFFC #define MASK_STATUS0 0xFFFFFFFC
#define MASK_STATUS1 0xFFFFFFFF #define MASK_STATUS1 0xFFFFFFFF
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Enables the clock of a peripheral. The peripheral ID is used * \brief Enables the clock of a peripheral. The peripheral ID is used
* to identify which peripheral is targetted. * to identify which peripheral is targetted.
* *
* \note The ID must NOT be shifted (i.e. 1 << ID_xxx). * \note The ID must NOT be shifted (i.e. 1 << ID_xxx).
* *
* \param id Peripheral ID (ID_xxx). * \param id Peripheral ID (ID_xxx).
*/ */
extern void PMC_EnablePeripheral( uint32_t dwId ) extern void PMC_EnablePeripheral( uint32_t dwId )
{ {
assert( dwId < 35 ) ; assert( dwId < 35 ) ;
if ( dwId < 32 ) if ( dwId < 32 )
{ {
if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId) ) if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId) )
{ {
TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %" PRIu32 " is already enabled\n\r", dwId ) ; TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %" PRIu32 " is already enabled\n\r", dwId ) ;
} }
else else
{ {
PMC->PMC_PCER0 = 1 << dwId ; PMC->PMC_PCER0 = 1 << dwId ;
} }
} }
else else
{ {
dwId -= 32; dwId -= 32;
if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId)) if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId))
{ {
TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %" PRIu32 " is already enabled\n\r", dwId + 32 ) ; TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %" PRIu32 " is already enabled\n\r", dwId + 32 ) ;
} }
else else
{ {
PMC->PMC_PCER1 = 1 << dwId ; PMC->PMC_PCER1 = 1 << dwId ;
} }
} }
} }
/** /**
* \brief Disables the clock of a peripheral. The peripheral ID is used * \brief Disables the clock of a peripheral. The peripheral ID is used
* to identify which peripheral is targetted. * to identify which peripheral is targetted.
* *
* \note The ID must NOT be shifted (i.e. 1 << ID_xxx). * \note The ID must NOT be shifted (i.e. 1 << ID_xxx).
* *
* \param id Peripheral ID (ID_xxx). * \param id Peripheral ID (ID_xxx).
*/ */
extern void PMC_DisablePeripheral( uint32_t dwId ) extern void PMC_DisablePeripheral( uint32_t dwId )
{ {
assert( dwId < 35 ) ; assert( dwId < 35 ) ;
if ( dwId < 32 ) if ( dwId < 32 )
{ {
if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) ) if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) )
{ {
TRACE_DEBUG("PMC_DisablePeripheral: clock of peripheral" " %" PRIu32 " is not enabled\n\r", dwId ) ; TRACE_DEBUG("PMC_DisablePeripheral: clock of peripheral" " %" PRIu32 " is not enabled\n\r", dwId ) ;
} }
else else
{ {
PMC->PMC_PCDR0 = 1 << dwId ; PMC->PMC_PCDR0 = 1 << dwId ;
} }
} }
else else
{ {
dwId -= 32 ; dwId -= 32 ;
if ( (PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) ) if ( (PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) )
{ {
TRACE_DEBUG( "PMC_DisablePeripheral: clock of peripheral" " %" PRIu32 " is not enabled\n\r", dwId + 32 ) ; TRACE_DEBUG( "PMC_DisablePeripheral: clock of peripheral" " %" PRIu32 " is not enabled\n\r", dwId + 32 ) ;
} }
else else
{ {
PMC->PMC_PCDR1 = 1 << dwId ; PMC->PMC_PCDR1 = 1 << dwId ;
} }
} }
} }
/** /**
* \brief Enable all the periph clock via PMC. * \brief Enable all the periph clock via PMC.
*/ */
extern void PMC_EnableAllPeripherals( void ) extern void PMC_EnableAllPeripherals( void )
{ {
PMC->PMC_PCER0 = MASK_STATUS0 ; PMC->PMC_PCER0 = MASK_STATUS0 ;
while ( (PMC->PMC_PCSR0 & MASK_STATUS0) != MASK_STATUS0 ) ; while ( (PMC->PMC_PCSR0 & MASK_STATUS0) != MASK_STATUS0 ) ;
PMC->PMC_PCER1 = MASK_STATUS1 ; PMC->PMC_PCER1 = MASK_STATUS1 ;
while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != MASK_STATUS1 ) ; while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != MASK_STATUS1 ) ;
TRACE_DEBUG( "Enable all periph clocks\n\r" ) ; TRACE_DEBUG( "Enable all periph clocks\n\r" ) ;
} }
/** /**
* \brief Disable all the periph clock via PMC. * \brief Disable all the periph clock via PMC.
*/ */
extern void PMC_DisableAllPeripherals( void ) extern void PMC_DisableAllPeripherals( void )
{ {
PMC->PMC_PCDR0 = MASK_STATUS0 ; PMC->PMC_PCDR0 = MASK_STATUS0 ;
while ( (PMC->PMC_PCSR0 & MASK_STATUS0) != 0 ) ; while ( (PMC->PMC_PCSR0 & MASK_STATUS0) != 0 ) ;
PMC->PMC_PCDR1 = MASK_STATUS1 ; PMC->PMC_PCDR1 = MASK_STATUS1 ;
while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != 0 ) ; while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != 0 ) ;
TRACE_DEBUG( "Disable all periph clocks\n\r" ) ; TRACE_DEBUG( "Disable all periph clocks\n\r" ) ;
} }
/** /**
* \brief Get Periph Status for the given peripheral ID. * \brief Get Periph Status for the given peripheral ID.
* *
* \param id Peripheral ID (ID_xxx). * \param id Peripheral ID (ID_xxx).
*/ */
extern uint32_t PMC_IsPeriphEnabled( uint32_t dwId ) extern uint32_t PMC_IsPeriphEnabled( uint32_t dwId )
{ {
assert( dwId < 35 ) ; assert( dwId < 35 ) ;
if ( dwId < 32 ) if ( dwId < 32 )
{ {
return ( PMC->PMC_PCSR0 & (1 << dwId) ) ; return ( PMC->PMC_PCSR0 & (1 << dwId) ) ;
} }
else { else {
return ( PMC->PMC_PCSR1 & (1 << (dwId - 32)) ) ; return ( PMC->PMC_PCSR1 & (1 << (dwId - 32)) ) ;
} }
} }

View File

@@ -1,352 +1,352 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** \addtogroup spi_module Working with SPI /** \addtogroup spi_module Working with SPI
* The SPI driver provides the interface to configure and use the SPI * The SPI driver provides the interface to configure and use the SPI
* peripheral. * peripheral.
* *
* The Serial Peripheral Interface (SPI) circuit is a synchronous serial * The Serial Peripheral Interface (SPI) circuit is a synchronous serial
* data link that provides communication with external devices in Master * data link that provides communication with external devices in Master
* or Slave Mode. * or Slave Mode.
* *
* To use the SPI, the user has to follow these few steps: * To use the SPI, the user has to follow these few steps:
* -# Enable the SPI pins required by the application (see pio.h). * -# Enable the SPI pins required by the application (see pio.h).
* -# Configure the SPI using the \ref SPI_Configure(). This enables the * -# Configure the SPI using the \ref SPI_Configure(). This enables the
* peripheral clock. The mode register is loaded with the given value. * peripheral clock. The mode register is loaded with the given value.
* -# Configure all the necessary chip selects with \ref SPI_ConfigureNPCS(). * -# Configure all the necessary chip selects with \ref SPI_ConfigureNPCS().
* -# Enable the SPI by calling \ref SPI_Enable(). * -# Enable the SPI by calling \ref SPI_Enable().
* -# Send/receive data using \ref SPI_Write() and \ref SPI_Read(). Note that \ref SPI_Read() * -# Send/receive data using \ref SPI_Write() and \ref SPI_Read(). Note that \ref SPI_Read()
* must be called after \ref SPI_Write() to retrieve the last value read. * must be called after \ref SPI_Write() to retrieve the last value read.
* -# Send/receive data using the PDC with the \ref SPI_WriteBuffer() and * -# Send/receive data using the PDC with the \ref SPI_WriteBuffer() and
* \ref SPI_ReadBuffer() functions. * \ref SPI_ReadBuffer() functions.
* -# Disable the SPI by calling \ref SPI_Disable(). * -# Disable the SPI by calling \ref SPI_Disable().
* *
* For more accurate information, please look at the SPI section of the * For more accurate information, please look at the SPI section of the
* Datasheet. * Datasheet.
* *
* Related files :\n * Related files :\n
* \ref spi.c\n * \ref spi.c\n
* \ref spi.h.\n * \ref spi.h.\n
*/ */
/*@{*/ /*@{*/
/*@}*/ /*@}*/
/** /**
* \file * \file
* *
* Implementation of Serial Peripheral Interface (SPI) controller. * Implementation of Serial Peripheral Interface (SPI) controller.
* *
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include "pmc.h" #include "pmc.h"
#include "spi.h" #include "spi.h"
#include <stdint.h> #include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Enables a SPI peripheral. * \brief Enables a SPI peripheral.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_Enable( Spi* spi ) extern void SPI_Enable( Spi* spi )
{ {
spi->SPI_CR = SPI_CR_SPIEN ; spi->SPI_CR = SPI_CR_SPIEN ;
} }
/** /**
* \brief Disables a SPI peripheral. * \brief Disables a SPI peripheral.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_Disable( Spi* spi ) extern void SPI_Disable( Spi* spi )
{ {
spi->SPI_CR = SPI_CR_SPIDIS ; spi->SPI_CR = SPI_CR_SPIDIS ;
} }
/** /**
* \brief Enables one or more interrupt sources of a SPI peripheral. * \brief Enables one or more interrupt sources of a SPI peripheral.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param sources Bitwise OR of selected interrupt sources. * \param sources Bitwise OR of selected interrupt sources.
*/ */
extern void SPI_EnableIt( Spi* spi, uint32_t dwSources ) extern void SPI_EnableIt( Spi* spi, uint32_t dwSources )
{ {
spi->SPI_IER = dwSources ; spi->SPI_IER = dwSources ;
} }
/** /**
* \brief Disables one or more interrupt sources of a SPI peripheral. * \brief Disables one or more interrupt sources of a SPI peripheral.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param sources Bitwise OR of selected interrupt sources. * \param sources Bitwise OR of selected interrupt sources.
*/ */
extern void SPI_DisableIt( Spi* spi, uint32_t dwSources ) extern void SPI_DisableIt( Spi* spi, uint32_t dwSources )
{ {
spi->SPI_IDR = dwSources ; spi->SPI_IDR = dwSources ;
} }
/** /**
* \brief Configures a SPI peripheral as specified. The configuration can be computed * \brief Configures a SPI peripheral as specified. The configuration can be computed
* using several macros (see \ref spi_configuration_macros). * using several macros (see \ref spi_configuration_macros).
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param id Peripheral ID of the SPI. * \param id Peripheral ID of the SPI.
* \param configuration Value of the SPI configuration register. * \param configuration Value of the SPI configuration register.
*/ */
extern void SPI_Configure( Spi* spi, uint32_t dwId, uint32_t dwConfiguration ) extern void SPI_Configure( Spi* spi, uint32_t dwId, uint32_t dwConfiguration )
{ {
PMC_EnablePeripheral( dwId ) ; PMC_EnablePeripheral( dwId ) ;
spi->SPI_CR = SPI_CR_SPIDIS ; spi->SPI_CR = SPI_CR_SPIDIS ;
/* Execute a software reset of the SPI twice */ /* Execute a software reset of the SPI twice */
spi->SPI_CR = SPI_CR_SWRST ; spi->SPI_CR = SPI_CR_SWRST ;
spi->SPI_CR = SPI_CR_SWRST ; spi->SPI_CR = SPI_CR_SWRST ;
spi->SPI_MR = dwConfiguration ; spi->SPI_MR = dwConfiguration ;
} }
/** /**
* \brief Configures a chip select of a SPI peripheral. The chip select configuration * \brief Configures a chip select of a SPI peripheral. The chip select configuration
* is computed using several macros (see \ref spi_configuration_macros). * is computed using several macros (see \ref spi_configuration_macros).
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param npcs Chip select to configure (0, 1, 2 or 3). * \param npcs Chip select to configure (0, 1, 2 or 3).
* \param configuration Desired chip select configuration. * \param configuration Desired chip select configuration.
*/ */
void SPI_ConfigureNPCS( Spi* spi, uint32_t dwNpcs, uint32_t dwConfiguration ) void SPI_ConfigureNPCS( Spi* spi, uint32_t dwNpcs, uint32_t dwConfiguration )
{ {
spi->SPI_CSR[dwNpcs] = dwConfiguration ; spi->SPI_CSR[dwNpcs] = dwConfiguration ;
} }
/** /**
* \brief Get the current status register of the given SPI peripheral. * \brief Get the current status register of the given SPI peripheral.
* \note This resets the internal value of the status register, so further * \note This resets the internal value of the status register, so further
* read may yield different values. * read may yield different values.
* \param spi Pointer to a Spi instance. * \param spi Pointer to a Spi instance.
* \return SPI status register. * \return SPI status register.
*/ */
extern uint32_t SPI_GetStatus( Spi* spi ) extern uint32_t SPI_GetStatus( Spi* spi )
{ {
return spi->SPI_SR ; return spi->SPI_SR ;
} }
/** /**
* \brief Reads and returns the last word of data received by a SPI peripheral. This * \brief Reads and returns the last word of data received by a SPI peripheral. This
* method must be called after a successful SPI_Write call. * method must be called after a successful SPI_Write call.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* *
* \return readed data. * \return readed data.
*/ */
extern uint32_t SPI_Read( Spi* spi ) extern uint32_t SPI_Read( Spi* spi )
{ {
while ( (spi->SPI_SR & SPI_SR_RDRF) == 0 ) ; while ( (spi->SPI_SR & SPI_SR_RDRF) == 0 ) ;
return spi->SPI_RDR & 0xFFFF ; return spi->SPI_RDR & 0xFFFF ;
} }
/** /**
* \brief Sends data through a SPI peripheral. If the SPI is configured to use a fixed * \brief Sends data through a SPI peripheral. If the SPI is configured to use a fixed
* peripheral select, the npcs value is meaningless. Otherwise, it identifies * peripheral select, the npcs value is meaningless. Otherwise, it identifies
* the component which shall be addressed. * the component which shall be addressed.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param npcs Chip select of the component to address (0, 1, 2 or 3). * \param npcs Chip select of the component to address (0, 1, 2 or 3).
* \param data Word of data to send. * \param data Word of data to send.
*/ */
extern void SPI_Write( Spi* spi, uint32_t dwNpcs, uint16_t wData ) extern void SPI_Write( Spi* spi, uint32_t dwNpcs, uint16_t wData )
{ {
/* Send data */ /* Send data */
while ( (spi->SPI_SR & SPI_SR_TXEMPTY) == 0 ) ; while ( (spi->SPI_SR & SPI_SR_TXEMPTY) == 0 ) ;
spi->SPI_TDR = wData | SPI_PCS( dwNpcs ) ; spi->SPI_TDR = wData | SPI_PCS( dwNpcs ) ;
while ( (spi->SPI_SR & SPI_SR_TDRE) == 0 ) ; while ( (spi->SPI_SR & SPI_SR_TDRE) == 0 ) ;
} }
/** /**
* \brief Check if SPI transfer finish. * \brief Check if SPI transfer finish.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* *
* \return Returns 1 if there is no pending write operation on the SPI; otherwise * \return Returns 1 if there is no pending write operation on the SPI; otherwise
* returns 0. * returns 0.
*/ */
extern uint32_t SPI_IsFinished( Spi* spi ) extern uint32_t SPI_IsFinished( Spi* spi )
{ {
return ((spi->SPI_SR & SPI_SR_TXEMPTY) != 0) ; return ((spi->SPI_SR & SPI_SR_TXEMPTY) != 0) ;
} }
/** /**
* \brief Enable Spi PDC transmit * \brief Enable Spi PDC transmit
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_PdcEnableTx( Spi* spi ) extern void SPI_PdcEnableTx( Spi* spi )
{ {
spi->SPI_PTCR = SPI_PTCR_TXTEN ; spi->SPI_PTCR = SPI_PTCR_TXTEN ;
} }
/** /**
* \brief Disable Spi PDC transmit * \brief Disable Spi PDC transmit
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_PdcDisableTx( Spi* spi ) extern void SPI_PdcDisableTx( Spi* spi )
{ {
spi->SPI_PTCR = SPI_PTCR_TXTDIS ; spi->SPI_PTCR = SPI_PTCR_TXTDIS ;
} }
/** /**
* \brief Enable Spi PDC receive * \brief Enable Spi PDC receive
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_PdcEnableRx( Spi* spi ) extern void SPI_PdcEnableRx( Spi* spi )
{ {
spi->SPI_PTCR = SPI_PTCR_RXTEN ; spi->SPI_PTCR = SPI_PTCR_RXTEN ;
} }
/** /**
* \brief Disable Spi PDC receive * \brief Disable Spi PDC receive
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_PdcDisableRx( Spi* spi ) extern void SPI_PdcDisableRx( Spi* spi )
{ {
spi->SPI_PTCR = SPI_PTCR_RXTDIS ; spi->SPI_PTCR = SPI_PTCR_RXTDIS ;
} }
/** /**
* \brief Set PDC transmit and next transmit buffer address and size. * \brief Set PDC transmit and next transmit buffer address and size.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param txBuf PDC transmit buffer address. * \param txBuf PDC transmit buffer address.
* \param txCount Length in bytes of the transmit buffer. * \param txCount Length in bytes of the transmit buffer.
* \param txNextBuf PDC next transmit buffer address. * \param txNextBuf PDC next transmit buffer address.
* \param txNextCount Length in bytes of the next transmit buffer. * \param txNextCount Length in bytes of the next transmit buffer.
*/ */
extern void SPI_PdcSetTx( Spi* spi, void* pvTxBuf, uint32_t dwTxCount, void* pvTxNextBuf, uint32_t dwTxNextCount ) extern void SPI_PdcSetTx( Spi* spi, void* pvTxBuf, uint32_t dwTxCount, void* pvTxNextBuf, uint32_t dwTxNextCount )
{ {
spi->SPI_TPR = (uint32_t)pvTxBuf ; spi->SPI_TPR = (uint32_t)pvTxBuf ;
spi->SPI_TCR = dwTxCount ; spi->SPI_TCR = dwTxCount ;
spi->SPI_TNPR = (uint32_t)pvTxNextBuf ; spi->SPI_TNPR = (uint32_t)pvTxNextBuf ;
spi->SPI_TNCR = dwTxNextCount ; spi->SPI_TNCR = dwTxNextCount ;
} }
/** /**
* \brief Set PDC receive and next receive buffer address and size. * \brief Set PDC receive and next receive buffer address and size.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param rxBuf PDC receive buffer address. * \param rxBuf PDC receive buffer address.
* \param rxCount Length in bytes of the receive buffer. * \param rxCount Length in bytes of the receive buffer.
* \param rxNextBuf PDC next receive buffer address. * \param rxNextBuf PDC next receive buffer address.
* \param rxNextCount Length in bytes of the next receive buffer. * \param rxNextCount Length in bytes of the next receive buffer.
*/ */
extern void SPI_PdcSetRx( Spi* spi, void* pvRxBuf, uint32_t dwRxCount, void* pvRxNextBuf, uint32_t dwRxNextCount ) extern void SPI_PdcSetRx( Spi* spi, void* pvRxBuf, uint32_t dwRxCount, void* pvRxNextBuf, uint32_t dwRxNextCount )
{ {
spi->SPI_RPR = (uint32_t)pvRxBuf ; spi->SPI_RPR = (uint32_t)pvRxBuf ;
spi->SPI_RCR = dwRxCount ; spi->SPI_RCR = dwRxCount ;
spi->SPI_RNPR = (uint32_t)pvRxNextBuf ; spi->SPI_RNPR = (uint32_t)pvRxNextBuf ;
spi->SPI_RNCR = dwRxNextCount ; spi->SPI_RNCR = dwRxNextCount ;
} }
/** /**
* \brief Sends the contents of buffer through a SPI peripheral, using the PDC to * \brief Sends the contents of buffer through a SPI peripheral, using the PDC to
* take care of the transfer. * take care of the transfer.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param buffer Data buffer to send. * \param buffer Data buffer to send.
* \param length Length of the data buffer. * \param length Length of the data buffer.
*/ */
extern uint32_t SPI_WriteBuffer( Spi* spi, void* pvBuffer, uint32_t dwLength ) extern uint32_t SPI_WriteBuffer( Spi* spi, void* pvBuffer, uint32_t dwLength )
{ {
/* Check if first bank is free */ /* Check if first bank is free */
if ( spi->SPI_TCR == 0 ) if ( spi->SPI_TCR == 0 )
{ {
spi->SPI_TPR = (uint32_t)pvBuffer ; spi->SPI_TPR = (uint32_t)pvBuffer ;
spi->SPI_TCR = dwLength ; spi->SPI_TCR = dwLength ;
spi->SPI_PTCR = PERIPH_PTCR_TXTEN ; spi->SPI_PTCR = PERIPH_PTCR_TXTEN ;
return 1 ; return 1 ;
} }
/* Check if second bank is free */ /* Check if second bank is free */
else else
{ {
if ( spi->SPI_TNCR == 0 ) if ( spi->SPI_TNCR == 0 )
{ {
spi->SPI_TNPR = (uint32_t)pvBuffer ; spi->SPI_TNPR = (uint32_t)pvBuffer ;
spi->SPI_TNCR = dwLength ; spi->SPI_TNCR = dwLength ;
return 1 ; return 1 ;
} }
} }
/* No free banks */ /* No free banks */
return 0 ; return 0 ;
} }
/** /**
* \brief Reads data from a SPI peripheral until the provided buffer is filled. This * \brief Reads data from a SPI peripheral until the provided buffer is filled. This
* method does NOT need to be called after SPI_Write or SPI_WriteBuffer. * method does NOT need to be called after SPI_Write or SPI_WriteBuffer.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param buffer Data buffer to store incoming bytes. * \param buffer Data buffer to store incoming bytes.
* \param length Length in bytes of the data buffer. * \param length Length in bytes of the data buffer.
*/ */
extern uint32_t SPI_ReadBuffer( Spi* spi, void *pvBuffer, uint32_t dwLength ) extern uint32_t SPI_ReadBuffer( Spi* spi, void *pvBuffer, uint32_t dwLength )
{ {
/* Check if the first bank is free */ /* Check if the first bank is free */
if ( spi->SPI_RCR == 0 ) if ( spi->SPI_RCR == 0 )
{ {
spi->SPI_RPR = (uint32_t)pvBuffer ; spi->SPI_RPR = (uint32_t)pvBuffer ;
spi->SPI_RCR = dwLength ; spi->SPI_RCR = dwLength ;
spi->SPI_PTCR = PERIPH_PTCR_RXTEN ; spi->SPI_PTCR = PERIPH_PTCR_RXTEN ;
return 1 ; return 1 ;
} }
/* Check if second bank is free */ /* Check if second bank is free */
else else
{ {
if ( spi->SPI_RNCR == 0 ) if ( spi->SPI_RNCR == 0 )
{ {
spi->SPI_RNPR = (uint32_t)pvBuffer ; spi->SPI_RNPR = (uint32_t)pvBuffer ;
spi->SPI_RNCR = dwLength ; spi->SPI_RNCR = dwLength ;
return 1 ; return 1 ;
} }
} }
/* No free bank */ /* No free bank */
return 0 ; return 0 ;
} }

View File

@@ -1,175 +1,175 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *
* Implementation of Timer Counter (TC). * Implementation of Timer Counter (TC).
* *
*/ */
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Headers * Headers
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include <assert.h> #include <assert.h>
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Global functions * Global functions
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
/** /**
* \brief Configures a Timer Counter Channel * \brief Configures a Timer Counter Channel
* *
* Configures a Timer Counter to operate in the given mode. Timer is stopped * Configures a Timer Counter to operate in the given mode. Timer is stopped
* after configuration and must be restarted with TC_Start(). All the * after configuration and must be restarted with TC_Start(). All the
* interrupts of the timer are also disabled. * interrupts of the timer are also disabled.
* *
* \param pTc Pointer to a Tc instance. * \param pTc Pointer to a Tc instance.
* \param channel Channel number. * \param channel Channel number.
* \param mode Operating mode (TC_CMR value). * \param mode Operating mode (TC_CMR value).
*/ */
extern void TC_Configure( Tc *pTc, uint32_t dwChannel, uint32_t dwMode ) extern void TC_Configure( Tc *pTc, uint32_t dwChannel, uint32_t dwMode )
{ {
TcChannel* pTcCh ; TcChannel* pTcCh ;
assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ; assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
pTcCh = pTc->TC_CHANNEL+dwChannel ; pTcCh = pTc->TC_CHANNEL+dwChannel ;
/* Disable TC clock */ /* Disable TC clock */
pTcCh->TC_CCR = TC_CCR_CLKDIS ; pTcCh->TC_CCR = TC_CCR_CLKDIS ;
/* Disable interrupts */ /* Disable interrupts */
pTcCh->TC_IDR = 0xFFFFFFFF ; pTcCh->TC_IDR = 0xFFFFFFFF ;
/* Clear status register */ /* Clear status register */
pTcCh->TC_SR ; pTcCh->TC_SR ;
/* Set mode */ /* Set mode */
pTcCh->TC_CMR = dwMode ; pTcCh->TC_CMR = dwMode ;
} }
/** /**
* \brief Reset and Start the TC Channel * \brief Reset and Start the TC Channel
* *
* Enables the timer clock and performs a software reset to start the counting. * Enables the timer clock and performs a software reset to start the counting.
* *
* \param pTc Pointer to a Tc instance. * \param pTc Pointer to a Tc instance.
* \param dwChannel Channel number. * \param dwChannel Channel number.
*/ */
extern void TC_Start( Tc *pTc, uint32_t dwChannel ) extern void TC_Start( Tc *pTc, uint32_t dwChannel )
{ {
TcChannel* pTcCh ; TcChannel* pTcCh ;
assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ; assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
pTcCh = pTc->TC_CHANNEL+dwChannel ; pTcCh = pTc->TC_CHANNEL+dwChannel ;
pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ; pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;
} }
/** /**
* \brief Stop TC Channel * \brief Stop TC Channel
* *
* Disables the timer clock, stopping the counting. * Disables the timer clock, stopping the counting.
* *
* \param pTc Pointer to a Tc instance. * \param pTc Pointer to a Tc instance.
* \param dwChannel Channel number. * \param dwChannel Channel number.
*/ */
extern void TC_Stop(Tc *pTc, uint32_t dwChannel ) extern void TC_Stop(Tc *pTc, uint32_t dwChannel )
{ {
TcChannel* pTcCh ; TcChannel* pTcCh ;
assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ; assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
pTcCh = pTc->TC_CHANNEL+dwChannel ; pTcCh = pTc->TC_CHANNEL+dwChannel ;
pTcCh->TC_CCR = TC_CCR_CLKDIS ; pTcCh->TC_CCR = TC_CCR_CLKDIS ;
} }
/** /**
* \brief Find best MCK divisor * \brief Find best MCK divisor
* *
* Finds the best MCK divisor given the timer frequency and MCK. The result * Finds the best MCK divisor given the timer frequency and MCK. The result
* is guaranteed to satisfy the following equation: * is guaranteed to satisfy the following equation:
* \code * \code
* (MCK / (DIV * 65536)) <= freq <= (MCK / DIV) * (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
* \endcode * \endcode
* with DIV being the highest possible value. * with DIV being the highest possible value.
* *
* \param dwFreq Desired timer frequency. * \param dwFreq Desired timer frequency.
* \param dwMCk Master clock frequency. * \param dwMCk Master clock frequency.
* \param dwDiv Divisor value. * \param dwDiv Divisor value.
* \param dwTcClks TCCLKS field value for divisor. * \param dwTcClks TCCLKS field value for divisor.
* \param dwBoardMCK Board clock frequency. * \param dwBoardMCK Board clock frequency.
* *
* \return 1 if a proper divisor has been found, otherwise 0. * \return 1 if a proper divisor has been found, otherwise 0.
*/ */
extern uint32_t TC_FindMckDivisor( uint32_t dwFreq, uint32_t dwMCk, uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK ) extern uint32_t TC_FindMckDivisor( uint32_t dwFreq, uint32_t dwMCk, uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK )
{ {
const uint32_t adwDivisors[5] = { 2, 8, 32, 128, dwBoardMCK / 32768 } ; const uint32_t adwDivisors[5] = { 2, 8, 32, 128, dwBoardMCK / 32768 } ;
uint32_t dwIndex = 0 ; uint32_t dwIndex = 0 ;
/* Satisfy lower bound */ /* Satisfy lower bound */
while ( dwFreq < ((dwMCk / adwDivisors[dwIndex]) / 65536) ) while ( dwFreq < ((dwMCk / adwDivisors[dwIndex]) / 65536) )
{ {
dwIndex++ ; dwIndex++ ;
/* If no divisor can be found, return 0 */ /* If no divisor can be found, return 0 */
if ( dwIndex == (sizeof( adwDivisors )/sizeof( adwDivisors[0] )) ) if ( dwIndex == (sizeof( adwDivisors )/sizeof( adwDivisors[0] )) )
{ {
return 0 ; return 0 ;
} }
} }
/* Try to maximize DIV while satisfying upper bound */ /* Try to maximize DIV while satisfying upper bound */
while ( dwIndex < 4 ) while ( dwIndex < 4 )
{ {
if ( dwFreq > (dwMCk / adwDivisors[dwIndex + 1]) ) if ( dwFreq > (dwMCk / adwDivisors[dwIndex + 1]) )
{ {
break ; break ;
} }
dwIndex++ ; dwIndex++ ;
} }
/* Store results */ /* Store results */
if ( dwDiv ) if ( dwDiv )
{ {
*dwDiv = adwDivisors[dwIndex] ; *dwDiv = adwDivisors[dwIndex] ;
} }
if ( dwTcClks ) if ( dwTcClks )
{ {
*dwTcClks = dwIndex ; *dwTcClks = dwIndex ;
} }
return 1 ; return 1 ;
} }

View File

@@ -8,6 +8,11 @@ void EEFC_ReadUniqueID(unsigned int *pdwUniqueID)
{ {
unsigned int status; unsigned int status;
/* disable interrupts, as interrupt vectors are stored in flash,
* and after STUI was issued, we can no longer access flassh until
* SPUI complets */
__disable_irq();
/* Errata / Workaround: Set bit 16 of EEFC Flash Mode Register /* Errata / Workaround: Set bit 16 of EEFC Flash Mode Register
* to 1 */ * to 1 */
EFC->EEFC_FMR |= (1 << 16); EFC->EEFC_FMR |= (1 << 16);
@@ -40,4 +45,6 @@ void EEFC_ReadUniqueID(unsigned int *pdwUniqueID)
do { do {
status = EFC->EEFC_FSR; status = EFC->EEFC_FSR;
} while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY); } while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
__enable_irq();
} }

View File

@@ -1,410 +1,410 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** \addtogroup usart_module Working with USART /** \addtogroup usart_module Working with USART
* The USART driver provides the interface to configure and use the USART peripheral.\n * The USART driver provides the interface to configure and use the USART peripheral.\n
* *
* The USART supports several kinds of comminication modes such as full-duplex asynchronous/ * The USART supports several kinds of comminication modes such as full-duplex asynchronous/
* synchronous serial commnunication,RS485 with driver control signal,ISO7816,SPI and Test modes. * synchronous serial commnunication,RS485 with driver control signal,ISO7816,SPI and Test modes.
* *
* To start a USART transfer with \ref AT91SAM3S_PDC "PDC" support, the user could follow these steps: * To start a USART transfer with \ref AT91SAM3S_PDC "PDC" support, the user could follow these steps:
* <ul> * <ul>
* <li> Configure USART with expected mode and baudrate(see \ref USART_Configure), which could be done by: * <li> Configure USART with expected mode and baudrate(see \ref USART_Configure), which could be done by:
* -# Resetting and disabling transmitter and receiver by setting US_CR(Control Register). </li> * -# Resetting and disabling transmitter and receiver by setting US_CR(Control Register). </li>
* -# Conifguring the USART in a specific mode by setting USART_MODE bits in US_MR(Mode Register) </li> * -# Conifguring the USART in a specific mode by setting USART_MODE bits in US_MR(Mode Register) </li>
* -# Setting baudrate which is different from mode to mode. * -# Setting baudrate which is different from mode to mode.
</li> </li>
* <li> Enable transmitter or receiver respectively by set US_CR_TXEN or US_CR_RXEN in US_CR.</li> * <li> Enable transmitter or receiver respectively by set US_CR_TXEN or US_CR_RXEN in US_CR.</li>
* <li> Read from or write to the peripheral with \ref USART_ReadBuffer or \ref USART_WriteBuffer. * <li> Read from or write to the peripheral with \ref USART_ReadBuffer or \ref USART_WriteBuffer.
These operations could be done by polling or interruption. </li> These operations could be done by polling or interruption. </li>
* <li> For polling, check the status bit US_CSR_ENDRX/US_CSR_RXBUFF (READ) or US_CSR_ENDTX/ * <li> For polling, check the status bit US_CSR_ENDRX/US_CSR_RXBUFF (READ) or US_CSR_ENDTX/
US_CSR_TXBUFE (WRITE). </li> US_CSR_TXBUFE (WRITE). </li>
* <li> For interruption,"enable" the status bit through US_IER and * <li> For interruption,"enable" the status bit through US_IER and
realize the hanler with USARTx_IrqHandler according to IRQ vector realize the hanler with USARTx_IrqHandler according to IRQ vector
table which is defined in board_cstartup_<toolchain>.c table which is defined in board_cstartup_<toolchain>.c
To enable the interruption of USART,it should be configured with priority and enabled first through To enable the interruption of USART,it should be configured with priority and enabled first through
NVIC .</li> NVIC .</li>
* </ul> * </ul>
* *
* For more accurate information, please look at the USART section of the * For more accurate information, please look at the USART section of the
* Datasheet. * Datasheet.
* *
* Related files :\n * Related files :\n
* \ref usart.c\n * \ref usart.c\n
* \ref usart.h\n * \ref usart.h\n
*/ */
/** /**
* \file * \file
* *
* Implementation of USART (Universal Synchronous Asynchronous Receiver Transmitter) * Implementation of USART (Universal Synchronous Asynchronous Receiver Transmitter)
* controller. * controller.
* *
*/ */
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Headers * Headers
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include "trace.h" #include "trace.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local definitions * Local definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Exported functions * Exported functions
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
/** /**
* \brief Configures an USART peripheral with the specified parameters. * \brief Configures an USART peripheral with the specified parameters.
* *
* *
* \param usart Pointer to the USART peripheral to configure. * \param usart Pointer to the USART peripheral to configure.
* \param mode Desired value for the USART mode register (see the datasheet). * \param mode Desired value for the USART mode register (see the datasheet).
* \param baudrate Baudrate at which the USART should operate (in Hz). * \param baudrate Baudrate at which the USART should operate (in Hz).
* \param masterClock Frequency of the system master clock (in Hz). * \param masterClock Frequency of the system master clock (in Hz).
*/ */
void USART_Configure(Usart *usart, void USART_Configure(Usart *usart,
uint32_t mode, uint32_t mode,
uint32_t baudrate, uint32_t baudrate,
uint32_t masterClock) uint32_t masterClock)
{ {
/* Reset and disable receiver & transmitter*/ /* Reset and disable receiver & transmitter*/
usart->US_CR = US_CR_RSTRX | US_CR_RSTTX usart->US_CR = US_CR_RSTRX | US_CR_RSTTX
| US_CR_RXDIS | US_CR_TXDIS; | US_CR_RXDIS | US_CR_TXDIS;
/* Configure mode*/ /* Configure mode*/
usart->US_MR = mode; usart->US_MR = mode;
/* Configure baudrate*/ /* Configure baudrate*/
/* Asynchronous, no oversampling*/ /* Asynchronous, no oversampling*/
if ( ((mode & US_MR_SYNC) == 0) && ((mode & US_MR_OVER) == 0) ) if ( ((mode & US_MR_SYNC) == 0) && ((mode & US_MR_OVER) == 0) )
{ {
usart->US_BRGR = (masterClock / baudrate) / 16; usart->US_BRGR = (masterClock / baudrate) / 16;
} }
if( ((mode & US_MR_USART_MODE_SPI_MASTER) == US_MR_USART_MODE_SPI_MASTER) if( ((mode & US_MR_USART_MODE_SPI_MASTER) == US_MR_USART_MODE_SPI_MASTER)
|| ((mode & US_MR_SYNC) == US_MR_SYNC)) || ((mode & US_MR_SYNC) == US_MR_SYNC))
{ {
if( (mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK) if( (mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK)
{ {
usart->US_BRGR = masterClock / baudrate; usart->US_BRGR = masterClock / baudrate;
} }
else else
{ {
if ( (mode & US_MR_USCLKS_DIV) == US_MR_USCLKS_DIV) if ( (mode & US_MR_USCLKS_DIV) == US_MR_USCLKS_DIV)
{ {
usart->US_BRGR = masterClock / baudrate / 8; usart->US_BRGR = masterClock / baudrate / 8;
} }
} }
} }
/* TODO other modes*/ /* TODO other modes*/
} }
/** /**
* \brief Enables or disables the transmitter of an USART peripheral. * \brief Enables or disables the transmitter of an USART peripheral.
* *
* *
* \param usart Pointer to an USART peripheral * \param usart Pointer to an USART peripheral
* \param enabled If true, the transmitter is enabled; otherwise it is * \param enabled If true, the transmitter is enabled; otherwise it is
* disabled. * disabled.
*/ */
void USART_SetTransmitterEnabled(Usart *usart, uint8_t enabled) void USART_SetTransmitterEnabled(Usart *usart, uint8_t enabled)
{ {
if (enabled) { if (enabled) {
usart->US_CR = US_CR_TXEN; usart->US_CR = US_CR_TXEN;
} }
else { else {
usart->US_CR = US_CR_TXDIS; usart->US_CR = US_CR_TXDIS;
} }
} }
/** /**
* \brief Enables or disables the receiver of an USART peripheral * \brief Enables or disables the receiver of an USART peripheral
* *
* *
* \param usart Pointer to an USART peripheral * \param usart Pointer to an USART peripheral
* \param enabled If true, the receiver is enabled; otherwise it is disabled. * \param enabled If true, the receiver is enabled; otherwise it is disabled.
*/ */
void USART_SetReceiverEnabled(Usart *usart, void USART_SetReceiverEnabled(Usart *usart,
uint8_t enabled) uint8_t enabled)
{ {
if (enabled) { if (enabled) {
usart->US_CR = US_CR_RXEN; usart->US_CR = US_CR_RXEN;
} }
else { else {
usart->US_CR = US_CR_RXDIS; usart->US_CR = US_CR_RXDIS;
} }
} }
/** /**
* \brief Sends one packet of data through the specified USART peripheral. This * \brief Sends one packet of data through the specified USART peripheral. This
* function operates synchronously, so it only returns when the data has been * function operates synchronously, so it only returns when the data has been
* actually sent. * actually sent.
* *
* *
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \param data Data to send including 9nth bit and sync field if necessary (in * \param data Data to send including 9nth bit and sync field if necessary (in
* the same format as the US_THR register in the datasheet). * the same format as the US_THR register in the datasheet).
* \param timeOut Time out value (0 = no timeout). * \param timeOut Time out value (0 = no timeout).
*/ */
void USART_Write( void USART_Write(
Usart *usart, Usart *usart,
uint16_t data, uint16_t data,
volatile uint32_t timeOut) volatile uint32_t timeOut)
{ {
if (timeOut == 0) { if (timeOut == 0) {
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
} }
else { else {
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0) { while ((usart->US_CSR & US_CSR_TXEMPTY) == 0) {
if (timeOut == 0) { if (timeOut == 0) {
TRACE_ERROR("USART_Write: Timed out.\n\r"); TRACE_ERROR("USART_Write: Timed out.\n\r");
return; return;
} }
timeOut--; timeOut--;
} }
} }
usart->US_THR = data; usart->US_THR = data;
} }
/** /**
* \brief Sends the contents of a data buffer through the specified USART peripheral. * \brief Sends the contents of a data buffer through the specified USART peripheral.
* This function returns immediately (1 if the buffer has been queued, 0 * This function returns immediately (1 if the buffer has been queued, 0
* otherwise); poll the ENDTX and TXBUFE bits of the USART status register * otherwise); poll the ENDTX and TXBUFE bits of the USART status register
* to check for the transfer completion. * to check for the transfer completion.
* *
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \param buffer Pointer to the data buffer to send. * \param buffer Pointer to the data buffer to send.
* \param size Size of the data buffer (in bytes). * \param size Size of the data buffer (in bytes).
*/ */
uint8_t USART_WriteBuffer( uint8_t USART_WriteBuffer(
Usart *usart, Usart *usart,
void *buffer, void *buffer,
uint32_t size) uint32_t size)
{ {
/* Check if the first PDC bank is free*/ /* Check if the first PDC bank is free*/
if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) { if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {
usart->US_TPR = (uint32_t) buffer; usart->US_TPR = (uint32_t) buffer;
usart->US_TCR = size; usart->US_TCR = size;
usart->US_PTCR = US_PTCR_TXTEN; usart->US_PTCR = US_PTCR_TXTEN;
return 1; return 1;
} }
/* Check if the second PDC bank is free*/ /* Check if the second PDC bank is free*/
else if (usart->US_TNCR == 0) { else if (usart->US_TNCR == 0) {
usart->US_TNPR = (uint32_t) buffer; usart->US_TNPR = (uint32_t) buffer;
usart->US_TNCR = size; usart->US_TNCR = size;
return 1; return 1;
} }
else { else {
return 0; return 0;
} }
} }
/** /**
* \brief Reads and return a packet of data on the specified USART peripheral. This * \brief Reads and return a packet of data on the specified USART peripheral. This
* function operates asynchronously, so it waits until some data has been * function operates asynchronously, so it waits until some data has been
* received. * received.
* *
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \param timeOut Time out value (0 -> no timeout). * \param timeOut Time out value (0 -> no timeout).
*/ */
uint16_t USART_Read( uint16_t USART_Read(
Usart *usart, Usart *usart,
volatile uint32_t timeOut) volatile uint32_t timeOut)
{ {
if (timeOut == 0) { if (timeOut == 0) {
while ((usart->US_CSR & US_CSR_RXRDY) == 0); while ((usart->US_CSR & US_CSR_RXRDY) == 0);
} }
else { else {
while ((usart->US_CSR & US_CSR_RXRDY) == 0) { while ((usart->US_CSR & US_CSR_RXRDY) == 0) {
if (timeOut == 0) { if (timeOut == 0) {
TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ; TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ;
return 0; return 0;
} }
timeOut--; timeOut--;
} }
} }
return usart->US_RHR; return usart->US_RHR;
} }
/** /**
* \brief Reads data from an USART peripheral, filling the provided buffer until it * \brief Reads data from an USART peripheral, filling the provided buffer until it
* becomes full. This function returns immediately with 1 if the buffer has * becomes full. This function returns immediately with 1 if the buffer has
* been queued for transmission; otherwise 0. * been queued for transmission; otherwise 0.
* *
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \param buffer Pointer to the buffer where the received data will be stored. * \param buffer Pointer to the buffer where the received data will be stored.
* \param size Size of the data buffer (in bytes). * \param size Size of the data buffer (in bytes).
*/ */
uint8_t USART_ReadBuffer(Usart *usart, uint8_t USART_ReadBuffer(Usart *usart,
void *buffer, void *buffer,
uint32_t size) uint32_t size)
{ {
/* Check if the first PDC bank is free*/ /* Check if the first PDC bank is free*/
if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) { if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) {
usart->US_RPR = (uint32_t) buffer; usart->US_RPR = (uint32_t) buffer;
usart->US_RCR = size; usart->US_RCR = size;
usart->US_PTCR = US_PTCR_RXTEN; usart->US_PTCR = US_PTCR_RXTEN;
return 1; return 1;
} }
/* Check if the second PDC bank is free*/ /* Check if the second PDC bank is free*/
else if (usart->US_RNCR == 0) { else if (usart->US_RNCR == 0) {
usart->US_RNPR = (uint32_t) buffer; usart->US_RNPR = (uint32_t) buffer;
usart->US_RNCR = size; usart->US_RNCR = size;
return 1; return 1;
} }
else { else {
return 0; return 0;
} }
} }
/** /**
* \brief Returns 1 if some data has been received and can be read from an USART; * \brief Returns 1 if some data has been received and can be read from an USART;
* otherwise returns 0. * otherwise returns 0.
* *
* \param usart Pointer to an Usart instance. * \param usart Pointer to an Usart instance.
*/ */
uint8_t USART_IsDataAvailable(Usart *usart) uint8_t USART_IsDataAvailable(Usart *usart)
{ {
if ((usart->US_CSR & US_CSR_RXRDY) != 0) { if ((usart->US_CSR & US_CSR_RXRDY) != 0) {
return 1; return 1;
} }
else { else {
return 0; return 0;
} }
} }
/** /**
* \brief Sets the filter value for the IRDA demodulator. * \brief Sets the filter value for the IRDA demodulator.
* *
* \param pUsart Pointer to an Usart instance. * \param pUsart Pointer to an Usart instance.
* \param filter Filter value. * \param filter Filter value.
*/ */
void USART_SetIrdaFilter(Usart *pUsart, uint8_t filter) void USART_SetIrdaFilter(Usart *pUsart, uint8_t filter)
{ {
assert( pUsart != NULL ) ; assert( pUsart != NULL ) ;
pUsart->US_IF = filter; pUsart->US_IF = filter;
} }
/** /**
* \brief Sends one packet of data through the specified USART peripheral. This * \brief Sends one packet of data through the specified USART peripheral. This
* function operates synchronously, so it only returns when the data has been * function operates synchronously, so it only returns when the data has been
* actually sent. * actually sent.
* *
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \param c Character to send * \param c Character to send
*/ */
void USART_PutChar( void USART_PutChar(
Usart *usart, Usart *usart,
uint8_t c) uint8_t c)
{ {
/* Wait for the transmitter to be ready*/ /* Wait for the transmitter to be ready*/
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
/* Send character*/ /* Send character*/
usart->US_THR = c; usart->US_THR = c;
/* Wait for the transfer to complete*/ /* Wait for the transfer to complete*/
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
} }
/** /**
* \brief Return 1 if a character can be read in USART * \brief Return 1 if a character can be read in USART
*/ */
uint32_t USART_IsRxReady(Usart *usart) uint32_t USART_IsRxReady(Usart *usart)
{ {
return (usart->US_CSR & US_CSR_RXRDY); return (usart->US_CSR & US_CSR_RXRDY);
} }
/** /**
* \brief Get present status * \brief Get present status
*/ */
uint32_t USART_GetStatus(Usart *usart) uint32_t USART_GetStatus(Usart *usart)
{ {
return usart->US_CSR; return usart->US_CSR;
} }
/** /**
* \brief Enable interrupt * \brief Enable interrupt
*/ */
void USART_EnableIt(Usart *usart,uint32_t mode) void USART_EnableIt(Usart *usart,uint32_t mode)
{ {
usart->US_IER = mode; usart->US_IER = mode;
} }
/** /**
* \brief Disable interrupt * \brief Disable interrupt
*/ */
void USART_DisableIt(Usart *usart,uint32_t mode) void USART_DisableIt(Usart *usart,uint32_t mode)
{ {
usart->US_IDR = mode; usart->US_IDR = mode;
} }
/** /**
* \brief Reads and returns a character from the USART. * \brief Reads and returns a character from the USART.
* *
* \note This function is synchronous (i.e. uses polling). * \note This function is synchronous (i.e. uses polling).
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \return Character received. * \return Character received.
*/ */
uint8_t USART_GetChar(Usart *usart) uint8_t USART_GetChar(Usart *usart)
{ {
while ((usart->US_CSR & US_CSR_RXRDY) == 0); while ((usart->US_CSR & US_CSR_RXRDY) == 0);
return usart->US_RHR; return usart->US_RHR;
} }

View File

@@ -1,132 +1,132 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *
* Implementation of Watchdog Timer (WDT) controller. * Implementation of Watchdog Timer (WDT) controller.
* *
*/ */
/** \addtogroup wdt_module Working with WDT /** \addtogroup wdt_module Working with WDT
* The WDT driver provides the interface to configure and use the WDT * The WDT driver provides the interface to configure and use the WDT
* peripheral. * peripheral.
* *
* The WDT can be used to prevent system lock-up if the software becomes * The WDT can be used to prevent system lock-up if the software becomes
* trapped in a deadlock. It can generate a general reset or a processor * trapped in a deadlock. It can generate a general reset or a processor
* reset only. It is clocked by slow clock divided by 128. * reset only. It is clocked by slow clock divided by 128.
* *
* The WDT is running at reset with 16 seconds watchdog period (slow clock at 32.768 kHz) * The WDT is running at reset with 16 seconds watchdog period (slow clock at 32.768 kHz)
* and external reset generation enabled. The user must either disable it or * and external reset generation enabled. The user must either disable it or
* reprogram it to meet the application requires. * reprogram it to meet the application requires.
* *
* To use the WDT, the user could follow these few steps: * To use the WDT, the user could follow these few steps:
* <ul> * <ul>
* <li>Enable watchdog with given mode using \ref WDT_Enable(). * <li>Enable watchdog with given mode using \ref WDT_Enable().
* <li>Restart the watchdog using \ref WDT_Restart() within the watchdog period. * <li>Restart the watchdog using \ref WDT_Restart() within the watchdog period.
* </ul> * </ul>
* *
* For more accurate information, please look at the WDT section of the * For more accurate information, please look at the WDT section of the
* Datasheet. * Datasheet.
* *
* \note * \note
* The Watchdog Mode Register (WDT_MR) can be written only once.\n * The Watchdog Mode Register (WDT_MR) can be written only once.\n
* *
* Related files :\n * Related files :\n
* \ref wdt.c\n * \ref wdt.c\n
* \ref wdt.h.\n * \ref wdt.h.\n
*/ */
/*@{*/ /*@{*/
/*@}*/ /*@}*/
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Headers * Headers
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include <stdint.h> #include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Enable watchdog with given mode. * \brief Enable watchdog with given mode.
* *
* \note The Watchdog Mode Register (WDT_MR) can be written only once. * \note The Watchdog Mode Register (WDT_MR) can be written only once.
* Only a processor reset resets it. * Only a processor reset resets it.
* *
* \param dwMode WDT mode to be set * \param dwMode WDT mode to be set
*/ */
extern void WDT_Enable( Wdt* pWDT, uint32_t dwMode ) extern void WDT_Enable( Wdt* pWDT, uint32_t dwMode )
{ {
pWDT->WDT_MR = dwMode ; pWDT->WDT_MR = dwMode ;
} }
/** /**
* \brief Disable watchdog. * \brief Disable watchdog.
* *
* \note The Watchdog Mode Register (WDT_MR) can be written only once. * \note The Watchdog Mode Register (WDT_MR) can be written only once.
* Only a processor reset resets it. * Only a processor reset resets it.
*/ */
extern void WDT_Disable( Wdt* pWDT ) extern void WDT_Disable( Wdt* pWDT )
{ {
pWDT->WDT_MR = WDT_MR_WDDIS; pWDT->WDT_MR = WDT_MR_WDDIS;
} }
/** /**
* \brief Watchdog restart. * \brief Watchdog restart.
*/ */
extern void WDT_Restart( Wdt* pWDT ) extern void WDT_Restart( Wdt* pWDT )
{ {
pWDT->WDT_CR = 0xA5000001; pWDT->WDT_CR = 0xA5000001;
} }
/** /**
* \brief Watchdog get status. * \brief Watchdog get status.
*/ */
extern uint32_t WDT_GetStatus( Wdt* pWDT ) extern uint32_t WDT_GetStatus( Wdt* pWDT )
{ {
return (pWDT->WDT_SR & 0x3) ; return (pWDT->WDT_SR & 0x3) ;
} }
/** /**
* \brief Watchdog get period. * \brief Watchdog get period.
* *
* \param dwMs desired watchdog period in millisecond. * \param dwMs desired watchdog period in millisecond.
*/ */
extern uint32_t WDT_GetPeriod( uint32_t dwMs ) extern uint32_t WDT_GetPeriod( uint32_t dwMs )
{ {
if ( (dwMs < 4) || (dwMs > 16000) ) if ( (dwMs < 4) || (dwMs > 16000) )
{ {
return 0 ; return 0 ;
} }
return ((dwMs << 8) / 1000) ; return ((dwMs << 8) / 1000) ;
} }

View File

@@ -300,7 +300,7 @@ void USBD_SetConfiguration(uint8_t cfgnum)
else { else {
deviceState = USBD_STATE_ADDRESS; deviceState = USBD_STATE_ADDRESS;
/* Reset all endpoints */ /* Reset all endpoints */
USBD_HAL_ResetEPs(0xFFFFFFFF, USBD_STATUS_RESET, 0); USBD_HAL_ResetEPs(0xFFFFFFFE, USBD_STATUS_RESET, 0);
} }
} }

View File

@@ -251,7 +251,7 @@ static void GetDescriptor(
switch (type) { switch (type) {
case USBGenericDescriptor_DEVICE: case USBGenericDescriptor_DEVICE:
TRACE_INFO_WP("Dev "); TRACE_DEBUG_WP("Dev ");
/* Adjust length and send descriptor */ /* Adjust length and send descriptor */
@@ -263,7 +263,7 @@ static void GetDescriptor(
break; break;
case USBGenericDescriptor_CONFIGURATION: case USBGenericDescriptor_CONFIGURATION:
TRACE_INFO_WP("Cfg "); TRACE_DEBUG_WP("Cfg ");
/* Adjust length and send descriptor */ /* Adjust length and send descriptor */
@@ -280,7 +280,7 @@ static void GetDescriptor(
break; break;
case USBGenericDescriptor_DEVICEQUALIFIER: case USBGenericDescriptor_DEVICEQUALIFIER:
TRACE_INFO_WP("Qua "); TRACE_DEBUG_WP("Qua ");
/* Check if descriptor exists */ /* Check if descriptor exists */
@@ -301,7 +301,7 @@ static void GetDescriptor(
break; break;
case USBGenericDescriptor_OTHERSPEEDCONFIGURATION: case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
TRACE_INFO_WP("OSC "); TRACE_DEBUG_WP("OSC ");
/* Check if descriptor exists */ /* Check if descriptor exists */
@@ -327,7 +327,7 @@ static void GetDescriptor(
break; break;
case USBGenericDescriptor_STRING: case USBGenericDescriptor_STRING:
TRACE_INFO_WP("Str%d ", indexRDesc); TRACE_DEBUG_WP("Str%d ", indexRDesc);
/* Check if descriptor exists */ /* Check if descriptor exists */
@@ -504,13 +504,13 @@ void USBDDriver_RequestHandler(
uint32_t length; uint32_t length;
uint32_t address; uint32_t address;
TRACE_INFO_WP("Std "); TRACE_DEBUG_WP("Std ");
/* Check request code */ /* Check request code */
switch (USBGenericRequest_GetRequest(pRequest)) { switch (USBGenericRequest_GetRequest(pRequest)) {
case USBGenericRequest_GETDESCRIPTOR: case USBGenericRequest_GETDESCRIPTOR:
TRACE_INFO_WP("gDesc "); TRACE_DEBUG_WP("gDesc ");
/* Send the requested descriptor */ /* Send the requested descriptor */
type = USBGetDescriptorRequest_GetDescriptorType(pRequest); type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
@@ -520,7 +520,7 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_SETADDRESS: case USBGenericRequest_SETADDRESS:
TRACE_INFO_WP("sAddr "); TRACE_DEBUG_WP("sAddr ");
/* Sends a zero-length packet and then set the device address */ /* Sends a zero-length packet and then set the device address */
address = USBSetAddressRequest_GetAddress(pRequest); address = USBSetAddressRequest_GetAddress(pRequest);
@@ -528,7 +528,7 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_SETCONFIGURATION: case USBGenericRequest_SETCONFIGURATION:
TRACE_INFO_WP("sCfg "); TRACE_DEBUG_WP("sCfg ");
/* Set the requested configuration */ /* Set the requested configuration */
cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest); cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
@@ -536,27 +536,27 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_GETCONFIGURATION: case USBGenericRequest_GETCONFIGURATION:
TRACE_INFO_WP("gCfg "); TRACE_DEBUG_WP("gCfg ");
/* Send the current configuration number */ /* Send the current configuration number */
GetConfiguration(pDriver); GetConfiguration(pDriver);
break; break;
case USBGenericRequest_GETSTATUS: case USBGenericRequest_GETSTATUS:
TRACE_INFO_WP("gSta "); TRACE_DEBUG_WP("gSta ");
/* Check who is the recipient */ /* Check who is the recipient */
switch (USBGenericRequest_GetRecipient(pRequest)) { switch (USBGenericRequest_GetRecipient(pRequest)) {
case USBGenericRequest_DEVICE: case USBGenericRequest_DEVICE:
TRACE_INFO_WP("Dev "); TRACE_DEBUG_WP("Dev ");
/* Send the device status */ /* Send the device status */
GetDeviceStatus(pDriver); GetDeviceStatus(pDriver);
break; break;
case USBGenericRequest_ENDPOINT: case USBGenericRequest_ENDPOINT:
TRACE_INFO_WP("Ept "); TRACE_DEBUG_WP("Ept ");
/* Send the endpoint status */ /* Send the endpoint status */
eptnum = USBGenericRequest_GetEndpointNumber(pRequest); eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
@@ -572,13 +572,13 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_CLEARFEATURE: case USBGenericRequest_CLEARFEATURE:
TRACE_INFO_WP("cFeat "); TRACE_DEBUG_WP("cFeat ");
/* Check which is the requested feature */ /* Check which is the requested feature */
switch (USBFeatureRequest_GetFeatureSelector(pRequest)) { switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
case USBFeatureRequest_ENDPOINTHALT: case USBFeatureRequest_ENDPOINTHALT:
TRACE_INFO_WP("Hlt "); TRACE_DEBUG_WP("Hlt ");
/* Unhalt endpoint and send a zero-length packet */ /* Unhalt endpoint and send a zero-length packet */
USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest)); USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
@@ -586,7 +586,7 @@ void USBDDriver_RequestHandler(
break; break;
case USBFeatureRequest_DEVICEREMOTEWAKEUP: case USBFeatureRequest_DEVICEREMOTEWAKEUP:
TRACE_INFO_WP("RmWU "); TRACE_DEBUG_WP("RmWU ");
/* Disable remote wake-up and send a zero-length packet */ /* Disable remote wake-up and send a zero-length packet */
pDriver->isRemoteWakeUpEnabled = 0; pDriver->isRemoteWakeUpEnabled = 0;
@@ -602,13 +602,13 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_SETFEATURE: case USBGenericRequest_SETFEATURE:
TRACE_INFO_WP("sFeat "); TRACE_DEBUG_WP("sFeat ");
/* Check which is the selected feature */ /* Check which is the selected feature */
switch (USBFeatureRequest_GetFeatureSelector(pRequest)) { switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
case USBFeatureRequest_DEVICEREMOTEWAKEUP: case USBFeatureRequest_DEVICEREMOTEWAKEUP:
TRACE_INFO_WP("RmWU "); TRACE_DEBUG_WP("RmWU ");
/* Enable remote wake-up and send a ZLP */ /* Enable remote wake-up and send a ZLP */
pDriver->isRemoteWakeUpEnabled = 1; pDriver->isRemoteWakeUpEnabled = 1;
@@ -616,25 +616,25 @@ void USBDDriver_RequestHandler(
break; break;
case USBFeatureRequest_ENDPOINTHALT: case USBFeatureRequest_ENDPOINTHALT:
TRACE_INFO_WP("Halt "); TRACE_DEBUG_WP("Halt ");
/* Halt endpoint */ /* Halt endpoint */
USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest)); USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
USBD_Write(0, 0, 0, 0, 0); USBD_Write(0, 0, 0, 0, 0);
break; break;
case USBFeatureRequest_OTG_B_HNP_ENABLE: case USBFeatureRequest_OTG_B_HNP_ENABLE:
TRACE_INFO_WP("OTG_B_HNP_ENABLE "); TRACE_DEBUG_WP("OTG_B_HNP_ENABLE ");
pDriver->otg_features_supported |= pDriver->otg_features_supported |=
1<<USBFeatureRequest_OTG_B_HNP_ENABLE; 1<<USBFeatureRequest_OTG_B_HNP_ENABLE;
USBD_Write(0, 0, 0, 0, 0); USBD_Write(0, 0, 0, 0, 0);
break; break;
case USBFeatureRequest_OTG_A_HNP_SUPPORT: case USBFeatureRequest_OTG_A_HNP_SUPPORT:
TRACE_INFO_WP("OTG_A_HNP_SUPPORT "); TRACE_DEBUG_WP("OTG_A_HNP_SUPPORT ");
pDriver->otg_features_supported |= pDriver->otg_features_supported |=
1<<USBFeatureRequest_OTG_A_HNP_SUPPORT; 1<<USBFeatureRequest_OTG_A_HNP_SUPPORT;
USBD_Write(0, 0, 0, 0, 0); USBD_Write(0, 0, 0, 0, 0);
break; break;
case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT: case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT:
TRACE_INFO_WP("OTG_A_ALT_HNP_SUPPORT "); TRACE_DEBUG_WP("OTG_A_ALT_HNP_SUPPORT ");
pDriver->otg_features_supported |= pDriver->otg_features_supported |=
1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT; 1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT;
USBD_Write(0, 0, 0, 0, 0); USBD_Write(0, 0, 0, 0, 0);
@@ -649,7 +649,7 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_SETINTERFACE: case USBGenericRequest_SETINTERFACE:
TRACE_INFO_WP("sInterface "); TRACE_DEBUG_WP("sInterface ");
infnum = USBInterfaceRequest_GetInterface(pRequest); infnum = USBInterfaceRequest_GetInterface(pRequest);
setting = USBInterfaceRequest_GetAlternateSetting(pRequest); setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
@@ -657,7 +657,7 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_GETINTERFACE: case USBGenericRequest_GETINTERFACE:
TRACE_INFO_WP("gInterface "); TRACE_DEBUG_WP("gInterface ");
infnum = USBInterfaceRequest_GetInterface(pRequest); infnum = USBInterfaceRequest_GetInterface(pRequest);
GetInterface(pDriver, infnum); GetInterface(pDriver, infnum);

View File

@@ -39,8 +39,8 @@ struct dfu_desc {
#define DFU_FUNC_DESC { \ #define DFU_FUNC_DESC { \
.bLength = USB_DT_DFU_SIZE, \ .bLength = USB_DT_DFU_SIZE, \
.bDescriptorType = USB_DT_DFU, \ .bDescriptorType = USB_DT_DFU, \
.bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD, \ .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, \
.wDetachTimeOut = 0xff00, \ .wDetachTimeOut = 0x00, \
.wTransferSize = BOARD_DFU_PAGE_SIZE, \ .wTransferSize = BOARD_DFU_PAGE_SIZE, \
.bcdDFUVersion = 0x0100, \ .bcdDFUVersion = 0x0100, \
} }
@@ -101,7 +101,7 @@ struct dfudata {
extern struct dfudata _g_dfu; extern struct dfudata _g_dfu;
extern struct dfudata *g_dfu; extern struct dfudata *g_dfu;
void set_usb_serial_str(const uint8_t *serial_usbstr); void set_usb_serial_str(void);
void DFURT_SwitchToDFU(void); void DFURT_SwitchToDFU(void);
@@ -124,6 +124,9 @@ void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors);
/* USBD tells us to switch from DFU mode to application mode */ /* USBD tells us to switch from DFU mode to application mode */
void USBDFU_SwitchToApp(void); void USBDFU_SwitchToApp(void);
/* USBD tells us to switch from to DFU mode */
void USBDFU_SwitchToDFU(void);
/* Return values to be used by USBDFU_handle_{dn,up}load */ /* Return values to be used by USBDFU_handle_{dn,up}load */
#define DFU_RET_NOTHING 0 #define DFU_RET_NOTHING 0
#define DFU_RET_ZLP 1 #define DFU_RET_ZLP 1

View File

@@ -13,14 +13,107 @@
#include <usb/common/dfu/usb_dfu.h> #include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h> #include <usb/device/dfu/dfu.h>
#include "usb_strings_generated.h"
enum { enum {
STR_MANUF = 1, STR_MANUF = 1,
STR_PROD, STR_PROD,
STR_CONFIG, STR_CONFIG,
// strings for the first alternate interface (e.g. DFU)
_STR_FIRST_ALT, _STR_FIRST_ALT,
STR_SERIAL = (_STR_FIRST_ALT+BOARD_DFU_NUM_IF), // serial string
STR_SERIAL = (_STR_FIRST_ALT + BOARD_DFU_NUM_IF),
// version string (on additional interface)
VERSION_CONF_STR,
VERSION_STR,
// count
STRING_DESC_CNT,
}; };
/* string used to replace one of both DFU flash partition atlsettings */
static const unsigned char usb_string_notavailable[] = {
USBStringDescriptor_LENGTH(13),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('n'),
USBStringDescriptor_UNICODE('o'),
USBStringDescriptor_UNICODE('t'),
USBStringDescriptor_UNICODE(' '),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('v'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('i'),
USBStringDescriptor_UNICODE('l'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('b'),
USBStringDescriptor_UNICODE('l'),
USBStringDescriptor_UNICODE('e'),
};
/* USB string for the serial (using 128-bit device ID) */
static unsigned char usb_string_serial[] = {
USBStringDescriptor_LENGTH(32),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('0'),
USBStringDescriptor_UNICODE('0'),
USBStringDescriptor_UNICODE('1'),
USBStringDescriptor_UNICODE('1'),
USBStringDescriptor_UNICODE('2'),
USBStringDescriptor_UNICODE('2'),
USBStringDescriptor_UNICODE('3'),
USBStringDescriptor_UNICODE('3'),
USBStringDescriptor_UNICODE('4'),
USBStringDescriptor_UNICODE('4'),
USBStringDescriptor_UNICODE('5'),
USBStringDescriptor_UNICODE('5'),
USBStringDescriptor_UNICODE('6'),
USBStringDescriptor_UNICODE('6'),
USBStringDescriptor_UNICODE('7'),
USBStringDescriptor_UNICODE('7'),
USBStringDescriptor_UNICODE('8'),
USBStringDescriptor_UNICODE('8'),
USBStringDescriptor_UNICODE('9'),
USBStringDescriptor_UNICODE('9'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('b'),
USBStringDescriptor_UNICODE('b'),
USBStringDescriptor_UNICODE('c'),
USBStringDescriptor_UNICODE('c'),
USBStringDescriptor_UNICODE('d'),
USBStringDescriptor_UNICODE('d'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE('f'),
USBStringDescriptor_UNICODE('f'),
};
/* USB string for the version */
static const unsigned char usb_string_version_conf[] = {
USBStringDescriptor_LENGTH(16),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('f'),
USBStringDescriptor_UNICODE('i'),
USBStringDescriptor_UNICODE('r'),
USBStringDescriptor_UNICODE('m'),
USBStringDescriptor_UNICODE('w'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('r'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE(' '),
USBStringDescriptor_UNICODE('v'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE('r'),
USBStringDescriptor_UNICODE('s'),
USBStringDescriptor_UNICODE('i'),
USBStringDescriptor_UNICODE('o'),
USBStringDescriptor_UNICODE('n'),
};
static const char git_version[] = GIT_VERSION;
static unsigned char usb_string_version[2 + ARRAY_SIZE(git_version) * 2 - 2];
/** array of static (from usb_strings) and runtime (serial, version) USB strings */
static const unsigned char *usb_strings_extended[STRING_DESC_CNT];
static const USBDeviceDescriptor fsDevice = { static const USBDeviceDescriptor fsDevice = {
.bLength = sizeof(USBDeviceDescriptor), .bLength = sizeof(USBDeviceDescriptor),
.bDescriptorType = USBGenericDescriptor_DEVICE, .bDescriptorType = USBGenericDescriptor_DEVICE,
@@ -28,18 +121,14 @@ static const USBDeviceDescriptor fsDevice = {
.bDeviceClass = 0, .bDeviceClass = 0,
.bDeviceSubClass = 0, .bDeviceSubClass = 0,
.bDeviceProtocol = 0, .bDeviceProtocol = 0,
.bMaxPacketSize0 = BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0), .bMaxPacketSize0 = USBEndpointDescriptor_MAXCTRLSIZE_FS,
.idVendor = BOARD_USB_VENDOR_ID, .idVendor = BOARD_USB_VENDOR_ID,
.idProduct = BOARD_DFU_USB_PRODUCT_ID, .idProduct = BOARD_DFU_USB_PRODUCT_ID,
.bcdDevice = BOARD_USB_RELEASE, .bcdDevice = BOARD_USB_RELEASE,
.iManufacturer = STR_MANUF, .iManufacturer = STR_MANUF,
.iProduct = STR_PROD, .iProduct = STR_PROD,
#ifdef BOARD_USB_SERIAL
.iSerialNumber = STR_SERIAL, .iSerialNumber = STR_SERIAL,
#else .bNumConfigurations = 2, // DFU + version configurations
.iSerialNumber = 0,
#endif
.bNumConfigurations = 1,
}; };
/* Alternate Interface Descriptor, we use one per partition/memory type */ /* Alternate Interface Descriptor, we use one per partition/memory type */
@@ -52,7 +141,7 @@ static const USBDeviceDescriptor fsDevice = {
.bNumEndpoints = 0, \ .bNumEndpoints = 0, \
.bInterfaceClass = 0xfe, \ .bInterfaceClass = 0xfe, \
.bInterfaceSubClass = 1, \ .bInterfaceSubClass = 1, \
.iInterface = (_STR_FIRST_ALT+ALT), \ .iInterface = (_STR_FIRST_ALT + ALT), \
.bInterfaceProtocol = 2, \ .bInterfaceProtocol = 2, \
} }
@@ -85,17 +174,79 @@ const struct dfu_desc dfu_cfg_descriptor = {
.func_dfu = DFU_FUNC_DESC .func_dfu = DFU_FUNC_DESC
}; };
#include "usb_strings_generated.h" void set_usb_serial_str(void)
#if 0
void set_usb_serial_str(const uint8_t *serial_usbstr)
{ {
usb_strings[STR_SERIAL] = serial_usbstr; unsigned int i;
}
// put device ID into USB serial number description
unsigned int device_id[4];
EEFC_ReadUniqueID(device_id);
char device_id_string[32 + 1];
snprintf(device_id_string, ARRAY_SIZE(device_id_string), "%08x%08x%08x%08x",
device_id[0], device_id[1], device_id[2], device_id[3]);
for (i = 0; i < ARRAY_SIZE(device_id_string) - 1; i++) {
usb_string_serial[2 + 2 * i] = device_id_string[i];
}
// put version into USB string
usb_string_version[0] = USBStringDescriptor_LENGTH(ARRAY_SIZE(git_version) - 1);
usb_string_version[1] = USBGenericDescriptor_STRING;
for (i = 0; i < ARRAY_SIZE(git_version) - 1; i++) {
usb_string_version[2 + i * 2 + 0] = git_version[i];
usb_string_version[2 + i * 2 + 1] = 0;
}
// fill extended USB strings
for (i = 0; i < ARRAY_SIZE(usb_strings) && i < ARRAY_SIZE(usb_strings_extended); i++) {
usb_strings_extended[i] = usb_strings[i];
}
#if defined(ENVIRONMENT_dfu)
usb_strings_extended[_STR_FIRST_ALT + 1] = usb_string_notavailable;
#elif defined(ENVIRONMENT_flash)
usb_strings_extended[_STR_FIRST_ALT + 2] = usb_string_notavailable;
#endif #endif
usb_strings_extended[STR_SERIAL] = usb_string_serial;
usb_strings_extended[VERSION_CONF_STR] = usb_string_version_conf;
usb_strings_extended[VERSION_STR] = usb_string_version;
}
/* USB descriptor just to show the version */
typedef struct _SIMTraceDriverConfigurationDescriptorVersion {
/** Standard configuration descriptor. */
USBConfigurationDescriptor configuration;
USBInterfaceDescriptor version;
} __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorVersion;
static const SIMTraceDriverConfigurationDescriptorVersion
configurationDescriptorVersion = {
/* Standard configuration descriptor for the interface descriptor*/
.configuration = {
.bLength = sizeof(USBConfigurationDescriptor),
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
.wTotalLength = sizeof(SIMTraceDriverConfigurationDescriptorVersion),
.bNumInterfaces = 1,
.bConfigurationValue = 2,
.iConfiguration = VERSION_CONF_STR,
.bmAttributes = USBD_BMATTRIBUTES,
.bMaxPower = USBConfigurationDescriptor_POWER(100),
},
/* Interface standard descriptor just holding the version information */
.version = {
.bLength = sizeof(USBInterfaceDescriptor),
.bDescriptorType = USBGenericDescriptor_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = USB_CLASS_PROPRIETARY,
.bInterfaceSubClass = 0xff,
.bInterfaceProtocol = 0,
.iInterface = VERSION_STR,
},
};
static const USBConfigurationDescriptor *conf_desc_arr[] = { static const USBConfigurationDescriptor *conf_desc_arr[] = {
&dfu_cfg_descriptor.ucfg, &dfu_cfg_descriptor.ucfg,
&configurationDescriptorVersion.configuration,
}; };
const USBDDriverDescriptors dfu_descriptors = { const USBDDriverDescriptors dfu_descriptors = {
@@ -108,6 +259,6 @@ const USBDDriverDescriptors dfu_descriptors = {
.pHsConfiguration = NULL, .pHsConfiguration = NULL,
.pHsQualifier = NULL, .pHsQualifier = NULL,
.pHsOtherSpeed = NULL, .pHsOtherSpeed = NULL,
.pStrings = usb_strings, .pStrings = usb_strings_extended,
.numStrings = ARRAY_SIZE(usb_strings), .numStrings = ARRAY_SIZE(usb_strings_extended),
}; };

View File

@@ -33,8 +33,7 @@
#include <usb/common/dfu/usb_dfu.h> #include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h> #include <usb/device/dfu/dfu.h>
/* FIXME: this was used for a special ELF section which then got called /** specific memory location shared across bootloader and application */
* by DFU code and Application code, across flash partitions */
#define __dfudata __attribute__ ((section (".dfudata"))) #define __dfudata __attribute__ ((section (".dfudata")))
#define __dfufunc #define __dfufunc
@@ -42,11 +41,14 @@
static USBDDriver usbdDriver; static USBDDriver usbdDriver;
static unsigned char if_altsettings[1]; static unsigned char if_altsettings[1];
/** structure containing the DFU state and magic value to know if DFU or application should be started */
__dfudata struct dfudata _g_dfu = { __dfudata struct dfudata _g_dfu = {
.state = DFU_STATE_appIDLE, .state = DFU_STATE_dfuIDLE,
.past_manifest = 0, .past_manifest = 0,
.total_bytes = 0, .total_bytes = 0,
}; };
/** variable to structure containing DFU state */
struct dfudata *g_dfu = &_g_dfu; struct dfudata *g_dfu = &_g_dfu;
WEAK void dfu_drv_updstatus(void) WEAK void dfu_drv_updstatus(void)
@@ -83,7 +85,7 @@ static void __dfufunc handle_getstate(void)
{ {
uint8_t u8 = g_dfu->state; uint8_t u8 = g_dfu->state;
TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu->state); TRACE_DEBUG("handle_getstate(%ld)\n\r", g_dfu->state);
USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0); USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0);
} }
@@ -447,6 +449,7 @@ void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors)
/* We already start in DFU idle mode */ /* We already start in DFU idle mode */
g_dfu->state = DFU_STATE_dfuIDLE; g_dfu->state = DFU_STATE_dfuIDLE;
set_usb_serial_str();
USBDDriver_Initialize(&usbdDriver, pDescriptors, if_altsettings); USBDDriver_Initialize(&usbdDriver, pDescriptors, if_altsettings);
USBD_Init(); USBD_Init();
USBD_Connect(); USBD_Connect();
@@ -460,7 +463,20 @@ void USBDFU_SwitchToApp(void)
/* make sure the MAGIC is not set to enter DFU again */ /* make sure the MAGIC is not set to enter DFU again */
g_dfu->magic = 0; g_dfu->magic = 0;
printf("switching to app\r\n"); /* disconnect from USB to ensure re-enumeration */
USBD_Disconnect();
/* disable any interrupts during transition */
__disable_irq();
/* Tell the hybrid to execute FTL JUMP! */
NVIC_SystemReset();
}
void USBDFU_SwitchToDFU(void)
{
/* make sure the MAGIC is not set to enter DFU again */
g_dfu->magic = USB_DFU_MAGIC;
/* disconnect from USB to ensure re-enumeration */ /* disconnect from USB to ensure re-enumeration */
USBD_Disconnect(); USBD_Disconnect();

View File

@@ -36,7 +36,12 @@
#include <usb/common/dfu/usb_dfu.h> #include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h> #include <usb/device/dfu/dfu.h>
struct dfudata *g_dfu = (struct dfudata *) IRAM_ADDR; /** specific memory location shared across bootloader and application */
#define __dfudata __attribute__ ((section (".dfudata")))
/** structure containing the magic value to know if DFU or application should be started */
__dfudata struct dfudata _g_dfu;
/** variable to structure containing the magic value to know if DFU or application should be started */
struct dfudata *g_dfu = &_g_dfu;
/* FIXME: this was used for a special ELF section which then got called /* FIXME: this was used for a special ELF section which then got called
* by DFU code and Application code, across flash partitions */ * by DFU code and Application code, across flash partitions */
@@ -63,7 +68,7 @@ static void __dfufunc handle_getstate(void)
{ {
uint8_t u8 = g_dfu->state; uint8_t u8 = g_dfu->state;
TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu->state); TRACE_DEBUG("handle_getstate(%lu)\n\r", g_dfu->state);
USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0); USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0);
} }
@@ -160,6 +165,8 @@ void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request)
* will then trigger DFURT_SwitchToDFU() below */ * will then trigger DFURT_SwitchToDFU() below */
TRACE_DEBUG("\r\n====dfu_detach\n\r"); TRACE_DEBUG("\r\n====dfu_detach\n\r");
g_dfu->state = DFU_STATE_appDETACH; g_dfu->state = DFU_STATE_appDETACH;
USBD_Write(0, 0, 0, 0, 0);
DFURT_SwitchToDFU();
ret = DFU_RET_ZLP; ret = DFU_RET_ZLP;
goto out; goto out;
break; break;
@@ -204,13 +211,14 @@ out:
void DFURT_SwitchToDFU(void) void DFURT_SwitchToDFU(void)
{ {
__disable_irq();
/* store the magic value that the DFU loader can detect and /* store the magic value that the DFU loader can detect and
* activate itself, rather than boot into the application */ * activate itself, rather than boot into the application */
g_dfu->magic = USB_DFU_MAGIC; g_dfu->magic = USB_DFU_MAGIC;
__DMB();
/* Disconnect the USB by remoting the pull-up */ /* Disconnect the USB by removing the pull-up */
USBD_Disconnect(); USBD_Disconnect();
__disable_irq();
/* reset the processor, we will start execution with the /* reset the processor, we will start execution with the
* ResetVector of the bootloader */ * ResetVector of the bootloader */

View File

@@ -214,6 +214,8 @@ typedef void (*MblTransferCallback)(void *pArg,
* Exported functions * Exported functions
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
extern uint16_t USBD_GetEndpointSize(uint8_t bEndpoint);
//extern void USBD_IrqHandler(void); //extern void USBD_IrqHandler(void);
extern void USBD_Init(void); extern void USBD_Init(void);

View File

@@ -1,3 +1,22 @@
/* SIMtrace 2 common board pin definitions
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef _BOARD_ #ifndef _BOARD_
#define _BOARD_ #define _BOARD_
@@ -37,18 +56,12 @@
/** Core definition */ /** Core definition */
#define cortexm3 #define cortexm3
#define BOARD_MCK 48000000 /* LEDs are used to indicate the status
* the LED definition is board specific
#define PIO_LED_RED PIO_PA17 * most boards have two LEDs, one green and one red
#define PIO_LED_GREEN PIO_PA17 * the red LED indicates of the main firmware is ready (on) or if there is an error (blinking)
* the green LED indicates if the firmware is idling (on) or if there is activity (blinking)
#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} */
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
#define LED_NUM_RED 0
#define LED_NUM_GREEN 1
/** USART0 pin RX */ /** USART0 pin RX */
#define PIN_USART0_RXD {PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} #define PIN_USART0_RXD {PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** USART0 pin TX */ /** USART0 pin TX */
@@ -63,8 +76,8 @@
#define PINS_UART { PIO_PA9A_URXD0|PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} #define PINS_UART { PIO_PA9A_URXD0|PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** UART0 */ /** UART0 */
/** Console baudrate always using 115200. */ /** Console baud rate in bps */
#define CONSOLE_BAUDRATE 115200 #define CONSOLE_BAUDRATE 921600
/** UART peripheral used by the console (UART0). */ /** UART peripheral used by the console (UART0). */
#define CONSOLE_UART UART0 #define CONSOLE_UART UART0
/** UART peripheral ID used by the console (UART0). */ /** UART peripheral ID used by the console (UART0). */
@@ -81,44 +94,31 @@
#define BOARD_ISO7816_BASE_USART USART0 #define BOARD_ISO7816_BASE_USART USART0
#define BOARD_ISO7816_ID_USART ID_USART0 #define BOARD_ISO7816_ID_USART ID_USART0
/* USART peripherals for a phone and SIM card setup */
/* USART peripheral connected to the SIM card */
#define USART_SIM USART0 #define USART_SIM USART0
/* ID of USART peripheral connected to the SIM card */
#define ID_USART_SIM ID_USART0 #define ID_USART_SIM ID_USART0
#define USART_PHONE USART1 /* Interrupt request ID of USART peripheral connected to the SIM card */
#define ID_USART_PHONE ID_USART1 #define IRQ_USART_SIM USART0_IRQn
/* USART peripheral connected to the phone */
#define SIM_PWEN PIO_PA5 #define USART_PHONE USART1
#define VCC_FWD PIO_PA26 /* ID of USART peripheral connected to the phone */
#define ID_USART_PHONE ID_USART1
/** Pin configuration to control USB pull-up on D+ /* Interrupt request ID of USART peripheral connected to the phone */
* @details the USB pull-up on D+ is enable by default on the board but can be disabled by setting PA16 high #define IRQ_USART_PHONE USART1_IRQn
*/
#define PIN_USB_PULLUP {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
// Board has UDP controller // Board has UDP controller
#define BOARD_USB_UDP #define BOARD_USB_UDP
// D+ has external pull-up
#define BOARD_USB_PULLUP_EXTERNAL
#define BOARD_USB_NUMENDPOINTS 8
// FIXME: in all other cases return 0?
#define BOARD_USB_ENDPOINTS_MAXPACKETSIZE(i) (((i == 4) || (i == 5))? 512 : 64)
#define BOARD_USB_ENDPOINTS_BANKS(i) (((i == 0) || (i == 3)) ? 1 : 2)
#define USB_VENDOR_OPENMOKO 0x1d50
#define USB_PRODUCT_OWHW_SAM3_DFU 0x4001 /* was 0x4000 */
#define USB_PRODUCT_OWHW_SAM3 0x4001
#define USB_PRODUCT_QMOD_HUB 0x4002
#define USB_PRODUCT_QMOD_SAM3_DFU 0x4004 /* was 0x4003 */
#define USB_PRODUCT_QMOD_SAM3 0x4004
#define USB_PRODUCT_SIMTRACE2_DFU 0x60e3 /* was 0x60e2 */
#define USB_PRODUCT_SIMTRACE2 0x60e3
#define BOARD_USB_DFU #define BOARD_USB_DFU
#define BOARD_DFU_BOOT_SIZE (16 * 1024) #define BOARD_DFU_BOOT_SIZE (16 * 1024)
#define BOARD_DFU_RAM_SIZE (2 * 1024) #define BOARD_DFU_RAM_SIZE (2 * 1024)
#define BOARD_DFU_PAGE_SIZE 512 #define BOARD_DFU_PAGE_SIZE 512
#define BOARD_DFU_NUM_IF 2 /** number of DFU interfaces (used to flash specific partitions) */
#define BOARD_DFU_NUM_IF 3
extern void board_exec_dbg_cmd(int ch); extern void board_exec_dbg_cmd(int ch);
extern void board_main_top(void); extern void board_main_top(void);

View File

@@ -26,7 +26,6 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *

View File

@@ -1,3 +1,18 @@
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once #pragma once
int get_board_version_adc(void); int get_board_version_adc(void);
uint32_t adc2uv(uint16_t adc);

View File

@@ -1,3 +1,17 @@
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once #pragma once
enum led { enum led {
@@ -13,9 +27,12 @@ enum led_pattern {
BLINK_3O_30F = 3, BLINK_3O_30F = 3,
BLINK_3O_1F_3O_30F = 4, BLINK_3O_1F_3O_30F = 4,
BLINK_3O_1F_3O_1F_3O_30F= 5, BLINK_3O_1F_3O_1F_3O_30F= 5,
BLINK_200O_F = 6, BLINK_2O_F = 6,
BLINK_600O_F = 7, BLINK_200O_F = 7,
BLINK_CUSTOM = 8, BLINK_600O_F = 8,
BLINK_CUSTOM = 9,
BLINK_2F_O = 10,
BLINK_5O_5F = 11,
_NUM_LED_BLINK _NUM_LED_BLINK
}; };

View File

@@ -1,4 +1,17 @@
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef _MANIFEST_H #ifndef _MANIFEST_H
#define _MANIFEST_H #define _MANIFEST_H

View File

@@ -1,4 +1,26 @@
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once #pragma once
/** switch card lines to use physical or emulated card
* @param[in] nr card interface number (i.e. slot)
* @param[in] physical which physical interface to switch to (e.g. 0: physical, 1: virtual)
* @return 0 on success, negative else
*/
int sim_switch_use_physical(unsigned int nr, int physical); int sim_switch_use_physical(unsigned int nr, int physical);
/** initialise card switching capabilities
* @return number of switchable card interfaces
*/
int sim_switch_init(void); int sim_switch_init(void);

View File

@@ -2,6 +2,7 @@
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* *
* All rights reserved. * All rights reserved.
* *
@@ -26,19 +27,17 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
#ifndef _UART_CONSOLE_ #ifndef _UART_CONSOLE_
#define _UART_CONSOLE_ #define _UART_CONSOLE_
#include <stdint.h> #include <stdint.h>
extern void UART_Configure( uint32_t dwBaudrate, uint32_t dwMasterClock ) ; extern void UART_Configure( uint32_t dwBaudrate, uint32_t dwMasterClock ) ;
extern void UART_Exit( void ) ;
extern void UART_PutChar( uint8_t uc ) ; extern void UART_PutChar( uint8_t uc ) ;
extern void UART_PutChar_Sync( uint8_t uc ) ;
extern uint32_t UART_GetChar( void ) ; extern uint32_t UART_GetChar( void ) ;
extern uint32_t UART_IsRxReady( void ) ; extern uint32_t UART_IsRxReady( void ) ;
extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize ) ; extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize ) ;
extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) ; extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) ;
extern uint32_t UART_GetInteger( uint32_t* pdwValue ) ; extern uint32_t UART_GetInteger( uint32_t* pdwValue ) ;

View File

@@ -39,9 +39,9 @@ SEARCH_DIR(.)
MEMORY MEMORY
{ {
/* reserve the first 16k (= 0x4000) for the DFU bootloader */ /* reserve the first 16k (= 0x4000) for the DFU bootloader */
rom (rx) : ORIGIN = 0x00404000, LENGTH = 0x0003c000 /* flash, 256K */ rom (rx) : ORIGIN = 0x00400000 + 16K, LENGTH = 256K - 16K /* flash, 256K */
/* reserve the first 32 (= 0x20) bytes for the _g_dfu struct */ /* note: dfudata will be at the start */
ram (rwx) : ORIGIN = 0x20000020, LENGTH = 0x0000bfe0 /* sram, 48K */ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K /* SRAM, 48K */
} }
/* Section Definitions */ /* Section Definitions */
@@ -96,13 +96,18 @@ SECTIONS
_efixed = .; /* End of text section */ _efixed = .; /* End of text section */
} > rom } > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */ /DISCARD/ :
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{ {
*(.ARM.exidx* .gnu.linkonce.armexidx.*) *(.ARM.exidx)
}
.blupdate :
{
. = ALIGN(4);
_blupdate_start = .;
KEEP(*(.fwupdate .fwupdate.*));
_blupdate_end = .;
} > rom } > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4); . = ALIGN(4);
_etext = .; _etext = .;
@@ -111,6 +116,8 @@ SECTIONS
{ {
. = ALIGN(4); . = ALIGN(4);
_srelocate = .; _srelocate = .;
/* we must make sure the .dfudata is linked to start of RAM */
*(.dfudata .dfudata.*);
*(.ramfunc .ramfunc.*); *(.ramfunc .ramfunc.*);
*(.data .data.*); *(.data .data.*);
. = ALIGN(4); . = ALIGN(4);

View File

@@ -38,8 +38,8 @@ SEARCH_DIR(.)
/* Memory Spaces Definitions */ /* Memory Spaces Definitions */
MEMORY MEMORY
{ {
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00040000 /* flash, 256K */ rom (rx) : ORIGIN = 0x00400000, LENGTH = 16K /* flash, 256K, but only the first 16K should be used for the bootloader */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000 /* sram, 48K */ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K /* SRAM, 48K */
} }
/* Section Definitions */ /* Section Definitions */
@@ -94,13 +94,10 @@ SECTIONS
_efixed = .; /* End of text section */ _efixed = .; /* End of text section */
} > rom } > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */ /DISCARD/ :
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{ {
*(.ARM.exidx* .gnu.linkonce.armexidx.*) *(.ARM.exidx)
} > rom }
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4); . = ALIGN(4);
_etext = .; _etext = .;

View File

@@ -1,215 +1,209 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2010, Atmel Corporation * Copyright (c) 2010, Atmel Corporation
* Copyright (C) 2017, Harald Welte <laforge@gnumonks.org> * Copyright (c) 2017, Harald Welte <laforge@gnumonks.org>
* * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* All rights reserved. *
* * All rights reserved.
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions are met: * Redistribution and use in source and binary forms, with or without
* * modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the disclaimer below. * - Redistributions of source code must retain the above copyright notice,
* * this list of conditions and the disclaimer below.
* Atmel's name may not be used to endorse or promote products derived from *
* this software without specific prior written permission. * Atmel's name may not be used to endorse or promote products derived from
* * this software without specific prior written permission.
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR *
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* ---------------------------------------------------------------------------- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ * ----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* Headers /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ * Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include "board_lowlevel.h" #include "board.h"
#include "board_lowlevel.h"
/*----------------------------------------------------------------------------
* Exported variables /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ * Exported variables
*----------------------------------------------------------------------------*/
/* Stack Configuration */
#define STACK_SIZE 0x900 /** Stack size (in DWords) */ /* Stack Configuration */
__attribute__ ((aligned(8),section(".stack"))) #define STACK_SIZE 0x900 /** Stack size (in DWords) */
uint32_t pdwStack[STACK_SIZE] ; __attribute__ ((aligned(8),section(".stack")))
uint32_t pdwStack[STACK_SIZE] ;
/* Initialize segments */
extern uint32_t _sfixed; /* Initialize segments */
extern uint32_t _efixed; extern uint32_t _sfixed;
extern uint32_t _etext; extern uint32_t _efixed;
extern uint32_t _srelocate; extern uint32_t _etext;
extern uint32_t _erelocate; extern uint32_t _srelocate;
extern uint32_t _szero; extern uint32_t _erelocate;
extern uint32_t _ezero; extern uint32_t _szero;
extern uint32_t _ezero;
/*----------------------------------------------------------------------------
* ProtoTypes /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ * ProtoTypes
*----------------------------------------------------------------------------*/
/** \cond DOXYGEN_SHOULD_SKIP_THIS */
extern int main( void ) ; /** \cond DOXYGEN_SHOULD_SKIP_THIS */
/** \endcond */ extern int main( void ) ;
void ResetException( void ) ; /** \endcond */
void ResetException( void ) ;
/*------------------------------------------------------------------------------
* Exception Table /*------------------------------------------------------------------------------
*------------------------------------------------------------------------------*/ * Exception Table
*------------------------------------------------------------------------------*/
__attribute__((section(".vectors")))
IntFunc exception_table[] = { __attribute__((section(".vectors")))
IntFunc exception_table[] = {
/* Configure Initial Stack Pointer, using linker-generated symbols */
(IntFunc)(&pdwStack[STACK_SIZE-1]), /* Configure Initial Stack Pointer, using linker-generated symbols */
ResetException, (IntFunc)(&pdwStack[STACK_SIZE-1]),
ResetException,
NMI_Handler,
HardFault_Handler, NMI_Handler,
MemManage_Handler, HardFault_Handler,
BusFault_Handler, MemManage_Handler,
UsageFault_Handler, BusFault_Handler,
0, 0, 0, 0, /* Reserved */ UsageFault_Handler,
SVC_Handler, 0, 0, 0, 0, /* Reserved */
DebugMon_Handler, SVC_Handler,
0, /* Reserved */ DebugMon_Handler,
PendSV_Handler, 0, /* Reserved */
SysTick_Handler, PendSV_Handler,
SysTick_Handler,
/* Configurable interrupts */
SUPC_IrqHandler, /* 0 Supply Controller */ /* Configurable interrupts */
RSTC_IrqHandler, /* 1 Reset Controller */ SUPC_IrqHandler, /* 0 Supply Controller */
RTC_IrqHandler, /* 2 Real Time Clock */ RSTC_IrqHandler, /* 1 Reset Controller */
RTT_IrqHandler, /* 3 Real Time Timer */ RTC_IrqHandler, /* 2 Real Time Clock */
WDT_IrqHandler, /* 4 Watchdog Timer */ RTT_IrqHandler, /* 3 Real Time Timer */
PMC_IrqHandler, /* 5 PMC */ WDT_IrqHandler, /* 4 Watchdog Timer */
EEFC_IrqHandler, /* 6 EEFC */ PMC_IrqHandler, /* 5 PMC */
IrqHandlerNotUsed, /* 7 Reserved */ EEFC_IrqHandler, /* 6 EEFC */
UART0_IrqHandler, /* 8 UART0 */ IrqHandlerNotUsed, /* 7 Reserved */
UART1_IrqHandler, /* 9 UART1 */ UART0_IrqHandler, /* 8 UART0 */
SMC_IrqHandler, /* 10 SMC */ UART1_IrqHandler, /* 9 UART1 */
PIOA_IrqHandler, /* 11 Parallel IO Controller A */ SMC_IrqHandler, /* 10 SMC */
PIOB_IrqHandler, /* 12 Parallel IO Controller B */ PIOA_IrqHandler, /* 11 Parallel IO Controller A */
PIOC_IrqHandler, /* 13 Parallel IO Controller C */ PIOB_IrqHandler, /* 12 Parallel IO Controller B */
USART0_IrqHandler, /* 14 USART 0 */ PIOC_IrqHandler, /* 13 Parallel IO Controller C */
USART1_IrqHandler, /* 15 USART 1 */ USART0_IrqHandler, /* 14 USART 0 */
IrqHandlerNotUsed, /* 16 Reserved */ USART1_IrqHandler, /* 15 USART 1 */
IrqHandlerNotUsed, /* 17 Reserved */ IrqHandlerNotUsed, /* 16 Reserved */
MCI_IrqHandler, /* 18 MCI */ IrqHandlerNotUsed, /* 17 Reserved */
TWI0_IrqHandler, /* 19 TWI 0 */ MCI_IrqHandler, /* 18 MCI */
TWI1_IrqHandler, /* 20 TWI 1 */ TWI0_IrqHandler, /* 19 TWI 0 */
SPI_IrqHandler, /* 21 SPI */ TWI1_IrqHandler, /* 20 TWI 1 */
SSC_IrqHandler, /* 22 SSC */ SPI_IrqHandler, /* 21 SPI */
TC0_IrqHandler, /* 23 Timer Counter 0 */ SSC_IrqHandler, /* 22 SSC */
TC1_IrqHandler, /* 24 Timer Counter 1 */ TC0_IrqHandler, /* 23 Timer Counter 0 */
TC2_IrqHandler, /* 25 Timer Counter 2 */ TC1_IrqHandler, /* 24 Timer Counter 1 */
TC3_IrqHandler, /* 26 Timer Counter 3 */ TC2_IrqHandler, /* 25 Timer Counter 2 */
TC4_IrqHandler, /* 27 Timer Counter 4 */ TC3_IrqHandler, /* 26 Timer Counter 3 */
TC5_IrqHandler, /* 28 Timer Counter 5 */ TC4_IrqHandler, /* 27 Timer Counter 4 */
ADC_IrqHandler, /* 29 ADC controller */ TC5_IrqHandler, /* 28 Timer Counter 5 */
DAC_IrqHandler, /* 30 DAC controller */ ADC_IrqHandler, /* 29 ADC controller */
PWM_IrqHandler, /* 31 PWM */ DAC_IrqHandler, /* 30 DAC controller */
CRCCU_IrqHandler, /* 32 CRC Calculation Unit */ PWM_IrqHandler, /* 31 PWM */
ACC_IrqHandler, /* 33 Analog Comparator */ CRCCU_IrqHandler, /* 32 CRC Calculation Unit */
USBD_IrqHandler, /* 34 USB Device Port */ ACC_IrqHandler, /* 33 Analog Comparator */
IrqHandlerNotUsed /* 35 not used */ USBD_IrqHandler, /* 34 USB Device Port */
}; IrqHandlerNotUsed /* 35 not used */
};
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
#include "usb/device/dfu/dfu.h" #if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) && defined(ENVIRONMENT_flash)
static void BootIntoApp(void) #include "usb/device/dfu/dfu.h"
{ static void BootIntoApp(void)
unsigned int *pSrc; {
void (*appReset)(void); unsigned int *pSrc;
void (*appReset)(void);
pSrc = (unsigned int *) ((unsigned char *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE);
SCB->VTOR = ((unsigned int)(pSrc)) | (0x0 << 7); pSrc = (unsigned int *) ((unsigned char *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE);
appReset = (void(*)(void))pSrc[1]; /* set vector table to application vector table (store at the beginning of the application) */
SCB->VTOR = (unsigned int)(pSrc);
g_dfu->state = DFU_STATE_appIDLE; /* set stack pointer to address provided in the beginning of the application (loaded into a register first) */
__asm__ volatile ("MSR msp,%0" : :"r"(*pSrc));
appReset(); /* start application (by jumping to the reset function which address is stored as second entry of the vector table) */
} appReset = (void(*)(void))pSrc[1];
#endif
g_dfu->state = DFU_STATE_appIDLE;
/**
* \brief This is the code that gets called on processor reset. appReset();
* To initialize the device, and call the main() routine. }
*/ #endif
void ResetException( void )
{ /**
uint32_t *pSrc, *pDest ; * \brief This is the code that gets called on processor reset.
* To initialize the device, and call the main() routine.
/* Low level Initialize */ */
LowLevelInit() ; void ResetException( void )
{
uint32_t *pSrc, *pDest ;
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
/* we are before the text segment has been relocated, so g_dfu is /* Low level Initialize */
* not initialized yet */ LowLevelInit() ;
g_dfu = &_g_dfu;
if ((g_dfu->magic != USB_DFU_MAGIC) && !USBDFU_OverrideEnterDFU()) {
/* start application if valid #if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) && defined(ENVIRONMENT_flash)
* the application starts with the vector table // boot application if there is not DFU override
* the first entry in the vector table is the initial stack pointer (SP) address if (!USBDFU_OverrideEnterDFU() && SCB->VTOR < IFLASH_ADDR + BOARD_DFU_BOOT_SIZE) {
* the stack will be placed in RAM, which begins at 0x2000 0000 UART_Exit();
* there is up to 48 KB of RAM (0xc000) __disable_irq();
* since the stack grown "downwards" it should start at the end of the RAM: max 0x2000 c000 BootIntoApp();
* if the SP is not in this range (e.g. flash has been erased) there is no valid application /* Infinite loop */
* the second entry in the vector table is the reset address, corresponding to the application start while ( 1 ) ;
*/ }
if (((*((uint32_t*)(IFLASH_ADDR+BOARD_DFU_BOOT_SIZE)))&0xFFFF0000)==0x20000000) { #endif
BootIntoApp();
/* Infinite loop */ /* Initialize the relocate segment */
while ( 1 ) ; pSrc = &_etext ;
} pDest = &_srelocate ;
}
#endif if ( pSrc != pDest )
{
/* Initialize the relocate segment */ for ( ; pDest < &_erelocate ; )
pSrc = &_etext ; {
pDest = &_srelocate ; *pDest++ = *pSrc++ ;
}
if ( pSrc != pDest ) }
{
for ( ; pDest < &_erelocate ; ) /* Clear the zero segment */
{ for ( pDest = &_szero ; pDest < &_ezero ; )
*pDest++ = *pSrc++ ; {
} *pDest++ = 0;
} }
/* Clear the zero segment */ /* Set the vector table base address */
for ( pDest = &_szero ; pDest < &_ezero ; ) pSrc = (uint32_t *)&_sfixed;
{ SCB->VTOR = ( (uint32_t)pSrc & SCB_VTOR_TBLOFF_Msk ) ;
*pDest++ = 0;
} if ( ((uint32_t)pSrc >= IRAM_ADDR) && ((uint32_t)pSrc < IRAM_ADDR+IRAM_SIZE) )
{
/* Set the vector table base address */ SCB->VTOR |= 1 << SCB_VTOR_TBLBASE_Pos ;
pSrc = (uint32_t *)&_sfixed; }
SCB->VTOR = ( (uint32_t)pSrc & SCB_VTOR_TBLOFF_Msk ) ;
/* App should have disabled interrupts during the transition */
if ( ((uint32_t)pSrc >= IRAM_ADDR) && ((uint32_t)pSrc < IRAM_ADDR+IRAM_SIZE) ) __enable_irq();
{
SCB->VTOR |= 1 << SCB_VTOR_TBLBASE_Pos ; /* Branch to main function */
} main() ;
/* App should have disabled interrupts during the transition */ /* Infinite loop */
__enable_irq(); while ( 1 ) ;
}
/* Branch to main function */
main() ;
/* Infinite loop */
while ( 1 ) ;
}

View File

@@ -1,216 +1,225 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* All rights reserved. *
* * All rights reserved.
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions are met: * Redistribution and use in source and binary forms, with or without
* * modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the disclaimer below. * - Redistributions of source code must retain the above copyright notice,
* * this list of conditions and the disclaimer below.
* Atmel's name may not be used to endorse or promote products derived from *
* this software without specific prior written permission. * Atmel's name may not be used to endorse or promote products derived from
* * this software without specific prior written permission.
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR *
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* ---------------------------------------------------------------------------- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ * ----------------------------------------------------------------------------
*/
/**
* \file /**
* * \file
* Provides the low-level initialization function that called on chip startup. *
*/ * Provides the low-level initialization function that called on chip startup.
*/
/*----------------------------------------------------------------------------
* Headers /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ * Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include "board.h"
/*----------------------------------------------------------------------------
* Local definitions /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ * Local definitions
*----------------------------------------------------------------------------*/
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK) #define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)
#if (BOARD_MCK == 48000000)
#if (BOARD_MAINOSC == 18432000) /** configure PLL to generate main clock based on main oscillator frequency */
/* Clock settings at 48MHz for 18 MHz crystal */ #if (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 48000000)
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(13-1) \ | CKGR_PLLAR_MULA(8-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(5)) | CKGR_PLLAR_DIVA(2))
#elif (BOARD_MAINOSC == 12000000) #elif (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 58000000)
/* QMod has 12 MHz clock, so multply by 8 (96 MHz) and divide by 2 */ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ | CKGR_PLLAR_MULA(29-1) \
| CKGR_PLLAR_MULA(8-1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_DIVA(6))
| CKGR_PLLAR_DIVA(2)) #elif (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 60000000)
#else #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
#error "Please define PLLA config for your MAINOSC frequency" | CKGR_PLLAR_MULA(10-1) \
#endif /* MAINOSC */ | CKGR_PLLAR_PLLACOUNT(0x1) \
#elif (BOARD_MCK == 64000000) | CKGR_PLLAR_DIVA(2))
#if (BOARD_MAINOSC == 18432000) #elif (BOARD_MAINOSC == 18432000) && (BOARD_MCK == 47923200)
/* Clock settings at 64MHz for 18 MHz crystal: 64.512 MHz */ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ | CKGR_PLLAR_MULA(13-1) \
| CKGR_PLLAR_MULA(7-1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_DIVA(5))
| CKGR_PLLAR_DIVA(2)) #elif (BOARD_MAINOSC == 18432000) && (BOARD_MCK == 58982400)
#elif (BOARD_MAINOSC == 12000000) #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
/* QMod has 12 MHz clock, so multply by 10 / div by 2: 60 MHz */ | CKGR_PLLAR_MULA(16-1) \
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_MULA(10-1) \ | CKGR_PLLAR_DIVA(5))
| CKGR_PLLAR_PLLACOUNT(0x1) \ #elif (BOARD_MAINOSC == 18432000) && (BOARD_MCK == 64512000)
| CKGR_PLLAR_DIVA(2)) #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
#error "Please define PLLA config for your MAINOSC frequency" | CKGR_PLLAR_MULA(7-1) \
#endif /* MAINOSC */ | CKGR_PLLAR_PLLACOUNT(0x1) \
#else | CKGR_PLLAR_DIVA(2))
#error "No PLL settings for current BOARD_MCK." #else
#endif #error "Please define PLLA config for your BOARD_MCK/MAINOSC frequency"
#endif
#if (BOARD_MAINOSC == 12000000)
#define PLLB_CFG (CKGR_PLLBR_DIVB(2)|CKGR_PLLBR_MULB(8-1)|CKGR_PLLBR_PLLBCOUNT_Msk) #if (BOARD_MAINOSC == 12000000)
#elif (BOARD_MAINOSC == 18432000) #define PLLB_CFG (CKGR_PLLBR_DIVB(2)|CKGR_PLLBR_MULB(8-1)|CKGR_PLLBR_PLLBCOUNT_Msk)
#define PLLB_CFG (CKGR_PLLBR_DIVB(5)|CKGR_PLLBR_MULB(13-1)|CKGR_PLLBR_PLLBCOUNT_Msk) #elif (BOARD_MAINOSC == 18432000)
#else #define PLLB_CFG (CKGR_PLLBR_DIVB(5)|CKGR_PLLBR_MULB(13-1)|CKGR_PLLBR_PLLBCOUNT_Msk)
#error "Please configure PLLB for your MAINOSC freq" #else
#endif #error "Please configure PLLB for your MAINOSC freq"
#endif
/* Define clock timeout */
#define CLOCK_TIMEOUT 0xFFFFFFFF /* Define clock timeout */
#define CLOCK_TIMEOUT 0xFFFFFFFF
/**
* \brief Configure 48MHz Clock for USB /**
*/ * \brief Configure 48MHz Clock for USB
static void _ConfigureUsbClock(void) */
{ static void _ConfigureUsbClock(void)
/* Enable PLLB for USB */ {
PMC->CKGR_PLLBR = PLLB_CFG; /* Enable PLLB for USB */
while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0) ; PMC->CKGR_PLLBR = PLLB_CFG;
while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0) ;
/* USB Clock uses PLLB */
PMC->PMC_USB = PMC_USB_USBDIV(0) /* /1 (no divider) */ /* USB Clock uses PLLB */
| PMC_USB_USBS; /* PLLB */ PMC->PMC_USB = PMC_USB_USBDIV(0) /* /1 (no divider) */
} | PMC_USB_USBS; /* PLLB */
}
/*----------------------------------------------------------------------------
* Exported functions /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ * Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Performs the low-level initialization of the chip. /**
* This includes EFC and master clock configuration. * \brief Performs the low-level initialization of the chip.
* It also enable a low level on the pin NRST triggers a user reset. * This includes EFC and master clock configuration.
*/ * It also enable a low level on the pin NRST triggers a user reset.
extern WEAK void LowLevelInit( void ) */
{ extern WEAK void LowLevelInit( void )
uint32_t timeout = 0; {
uint32_t timeout = 0;
/* Configure the Supply Monitor to reset the CPU in case VDDIO is
* lower than 3.0V. As we run the board on 3.3V, any lower voltage /* Configure the Supply Monitor to reset the CPU in case VDDIO is
* might be some kind of leakage that creeps in some way, but is not * lower than 3.0V. As we run the board on 3.3V, any lower voltage
* the "official" power supply */ * might be some kind of leakage that creeps in some way, but is not
SUPC->SUPC_SMMR = SUPC_SMMR_SMTH_3_0V | SUPC_SMMR_SMSMPL_CSM | * the "official" power supply */
SUPC_SMMR_SMRSTEN_ENABLE; SUPC->SUPC_SMMR = SUPC_SMMR_SMTH_3_0V | SUPC_SMMR_SMSMPL_CSM |
SUPC_SMMR_SMRSTEN_ENABLE;
/* enable both LED and green LED */
PIOA->PIO_PER |= PIO_LED_RED | PIO_LED_GREEN; /* disable ERASE pin to prevent accidental flash erase */
PIOA->PIO_OER |= PIO_LED_RED | PIO_LED_GREEN; MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO12;
PIOA->PIO_CODR |= PIO_LED_RED | PIO_LED_GREEN;
/* enable both LED and green LED */
/* Set 3 FWS for Embedded Flash Access */ PIOA->PIO_PER |= PIO_LED_RED | PIO_LED_GREEN;
EFC->EEFC_FMR = EEFC_FMR_FWS(3); PIOA->PIO_OER |= PIO_LED_RED | PIO_LED_GREEN;
PIOA->PIO_CODR |= PIO_LED_RED | PIO_LED_GREEN;
/* Select external slow clock */
/* if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) /* Set 3 FWS for Embedded Flash Access */
{ EFC->EEFC_FMR = EEFC_FMR_FWS(3);
SUPC->SUPC_CR = (uint32_t)(SUPC_CR_XTALSEL_CRYSTAL_SEL | SUPC_CR_KEY(0xA5));
timeout = 0; /* Select external slow clock */
while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) ); /* if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST)
} {
*/ SUPC->SUPC_CR = (uint32_t)(SUPC_CR_XTALSEL_CRYSTAL_SEL | SUPC_CR_KEY(0xA5));
timeout = 0;
#ifndef qmod while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) );
/* Initialize main oscillator */ }
if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) */
{
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN; #ifndef qmod
timeout = 0; /* Initialize main oscillator */
while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT)); if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
} {
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
/* Switch to 3-20MHz Xtal oscillator */ timeout = 0;
PIOB->PIO_PDR = (1 << 8) | (1 << 9); while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT));
PIOB->PIO_PUDR = (1 << 8) | (1 << 9); }
PIOB->PIO_PPDDR = (1 << 8) | (1 << 9);
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; /* Switch to 3-20MHz Xtal oscillator */
/* wait for Main XTAL oscillator stabilization */ PIOB->PIO_PDR = (1 << 8) | (1 << 9);
timeout = 0; PIOB->PIO_PUDR = (1 << 8) | (1 << 9);
while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT)); PIOB->PIO_PPDDR = (1 << 8) | (1 << 9);
#else PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
/* QMOD has external 12MHz clock source */ /* wait for Main XTAL oscillator stabilization */
PIOB->PIO_PDR = (1 << 9); timeout = 0;
PIOB->PIO_PUDR = (1 << 9); while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT));
PIOB->PIO_PPDDR = (1 << 9); #else
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY| CKGR_MOR_MOSCSEL; /* QMOD has external 12MHz clock source */
#endif PIOB->PIO_PDR = (1 << 9);
PIOB->PIO_PUDR = (1 << 9);
/* disable the red LED after main clock initialization */ PIOB->PIO_PPDDR = (1 << 9);
PIOA->PIO_SODR = PIO_LED_RED; PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY| CKGR_MOR_MOSCSEL;
#endif
/* "switch" to main clock as master clock source (should already be the case */
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; /* disable the red LED after main clock initialization */
/* wait for master clock to be ready */ PIOA->PIO_SODR = PIO_LED_RED;
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* "switch" to main clock as master clock source (should already be the case */
/* Initialize PLLA */ PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
PMC->CKGR_PLLAR = BOARD_PLLAR; /* wait for master clock to be ready */
/* Wait for PLLA to lock */ for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT)); /* Initialize PLLA */
PMC->CKGR_PLLAR = BOARD_PLLAR;
/* Switch to main clock (again ?!?) */ /* Wait for PLLA to lock */
PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; timeout = 0;
/* wait for master clock to be ready */ while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT));
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* Switch to main clock (again ?!?) */
/* switch to PLLA as master clock source */ PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
PMC->PMC_MCKR = BOARD_MCKR ; /* wait for master clock to be ready */
/* wait for master clock to be ready */ for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* switch to PLLA as master clock source */
/* Configure SysTick for 1ms */ PMC->PMC_MCKR = BOARD_MCKR ;
SysTick_Config(BOARD_MCK/1000); /* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
_ConfigureUsbClock();
} /* Configure SysTick for 1ms */
SysTick_Config(BOARD_MCK/1000);
/* SysTick based delay function */
_ConfigureUsbClock();
volatile uint32_t jiffies; }
/* Interrupt handler for SysTick interrupt */ /* SysTick based delay function */
void SysTick_Handler(void)
{ volatile uint32_t jiffies;
jiffies++;
} /* Interrupt handler for SysTick interrupt */
void SysTick_Handler(void)
void mdelay(unsigned int msecs) {
{ jiffies++;
uint32_t jiffies_start = jiffies; }
do {
} while ((jiffies - jiffies_start) < msecs); void mdelay(unsigned int msecs)
} {
uint32_t jiffies_start = jiffies;
do {
} while ((jiffies - jiffies_start) < msecs);
}
void abort() {
NVIC_SystemReset();
while(1) {};
}

View File

@@ -1,9 +1,22 @@
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h" #include "board.h"
#include "boardver_adc.h" #include "boardver_adc.h"
/* FIXME: share this with mode_cardemu.c */
#define UV_PER_LSB ((3300 * 1000) / 4096) #define UV_PER_LSB ((3300 * 1000) / 4096)
static uint32_t adc2uv(uint16_t adc) uint32_t adc2uv(uint16_t adc)
{ {
uint32_t uv = (uint32_t) adc * UV_PER_LSB; uint32_t uv = (uint32_t) adc * UV_PER_LSB;
return uv; return uv;
@@ -73,7 +86,7 @@ int get_board_version_adc(void)
/* convert to voltage */ /* convert to voltage */
sample = ADC->ADC_CDR[2]; sample = ADC->ADC_CDR[2];
uv = adc2uv(sample); uv = adc2uv(sample);
TRACE_INFO("VERSION_DET ADC=%u => %u uV\r\n", sample, uv); TRACE_INFO("VERSION_DET ADC=%u => %lu uV\r\n", sample, uv);
/* FIXME: convert to board version based on thresholds */ /* FIXME: convert to board version based on thresholds */

View File

@@ -1,3 +1,22 @@
/* LED control
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
@@ -16,9 +35,9 @@ static void led_set(enum led led, int on)
ASSERT(led < PIO_LISTSIZE(pinsLeds)); ASSERT(led < PIO_LISTSIZE(pinsLeds));
if (on) if (on)
PIO_Set(&pinsLeds[led]); PIO_Clear(&pinsLeds[led]);
else else
PIO_Clear(&pinsLeds[led]); PIO_Set(&pinsLeds[led]);
} }
/* LED blinking code */ /* LED blinking code */
@@ -27,7 +46,7 @@ static void led_set(enum led led, int on)
struct blink_state { struct blink_state {
/* duration of the state in ms */ /* duration of the state in ms */
uint16_t duration; uint16_t duration;
/* bringhtness of LED during the state */ /* brightness of LED during the state */
uint8_t on; uint8_t on;
} __attribute__((packed)); } __attribute__((packed));
@@ -39,6 +58,10 @@ static const struct blink_state bs_on[] = {
{ 0, 1 } { 0, 1 }
}; };
static const struct blink_state bs_5on_5off[] = {
{ 500, 1 }, { 500, 0 }
};
static const struct blink_state bs_3on_5off[] = { static const struct blink_state bs_3on_5off[] = {
{ 300, 1 }, { 500, 0 } { 300, 1 }, { 500, 0 }
}; };
@@ -54,13 +77,23 @@ static const struct blink_state bs_3on_1off_3on_30off[] = {
static const struct blink_state bs_3on_1off_3on_1off_3on_30off[] = { static const struct blink_state bs_3on_1off_3on_1off_3on_30off[] = {
{ 300, 1 }, { 100, 0 }, { 300, 1 }, { 100, 0 }, { 300, 1 }, { 3000, 0 } { 300, 1 }, { 100, 0 }, { 300, 1 }, { 100, 0 }, { 300, 1 }, { 3000, 0 }
}; };
static const struct blink_state bs_2on_off[] = {
{ 200, 1 }, { 0, 0 },
};
static const struct blink_state bs_200on_off[] = { static const struct blink_state bs_200on_off[] = {
{ 20000, 1 }, { 0, 0 }, { 20000, 1 }, { 0, 0 },
}; };
static const struct blink_state bs_600on_off[] = { static const struct blink_state bs_600on_off[] = {
{ 60000, 1 }, { 0, 0 }, { 60000, 1 }, { 0, 0 },
}; };
static const struct blink_state bs_2off_on[] = {
{ 200, 0 }, { 0, 1 },
};
/* a blink pattern is an array of blink_states */ /* a blink pattern is an array of blink_states */
struct blink_pattern { struct blink_pattern {
@@ -78,6 +111,10 @@ static const struct blink_pattern patterns[] = {
.states = bs_on, .states = bs_on,
.size = ARRAY_SIZE(bs_on), .size = ARRAY_SIZE(bs_on),
}, },
[BLINK_5O_5F] = {
.states = bs_5on_5off,
.size = ARRAY_SIZE(bs_5on_5off),
},
[BLINK_3O_5F] = { [BLINK_3O_5F] = {
.states = bs_3on_5off, .states = bs_3on_5off,
.size = ARRAY_SIZE(bs_3on_5off), .size = ARRAY_SIZE(bs_3on_5off),
@@ -94,6 +131,10 @@ static const struct blink_pattern patterns[] = {
.states = bs_3on_1off_3on_1off_3on_30off, .states = bs_3on_1off_3on_1off_3on_30off,
.size = ARRAY_SIZE(bs_3on_1off_3on_1off_3on_30off), .size = ARRAY_SIZE(bs_3on_1off_3on_1off_3on_30off),
}, },
[BLINK_2O_F] = {
.states = bs_2on_off,
.size = ARRAY_SIZE(bs_2on_off),
},
[BLINK_200O_F] = { [BLINK_200O_F] = {
.states = bs_200on_off, .states = bs_200on_off,
.size = ARRAY_SIZE(bs_200on_off), .size = ARRAY_SIZE(bs_200on_off),
@@ -102,6 +143,11 @@ static const struct blink_pattern patterns[] = {
.states = bs_600on_off, .states = bs_600on_off,
.size = ARRAY_SIZE(bs_600on_off), .size = ARRAY_SIZE(bs_600on_off),
}, },
[BLINK_2F_O] = {
.states = bs_2off_on,
.size = ARRAY_SIZE(bs_2off_on),
},
}; };
struct led_state { struct led_state {
@@ -158,16 +204,16 @@ static void blink_tmr_cb(void *data)
} }
static struct led_state led_state[] = { static struct led_state led_state[] = {
[LED_GREEN] = {
.led = LED_GREEN,
.timer.cb = blink_tmr_cb,
.timer.data = &led_state[LED_GREEN],
},
[LED_RED] = { [LED_RED] = {
.led = LED_RED, .led = LED_RED,
.timer.cb = blink_tmr_cb, .timer.cb = blink_tmr_cb,
.timer.data = &led_state[LED_RED], .timer.data = &led_state[LED_RED],
}, },
[LED_GREEN] = {
.led = LED_GREEN,
.timer.cb = blink_tmr_cb,
.timer.data = &led_state[LED_GREEN],
},
}; };
#endif /* PINS_LEDS */ #endif /* PINS_LEDS */

View File

@@ -1,4 +1,17 @@
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "manifest.h" #include "manifest.h"
const char *manifest_application = APPLICATION; const char *manifest_application = APPLICATION;

View File

@@ -1,417 +1,453 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* All rights reserved. *
* * All rights reserved.
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions are met: * Redistribution and use in source and binary forms, with or without
* * modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the disclaimer below. * - Redistributions of source code must retain the above copyright notice,
* * this list of conditions and the disclaimer below.
* Atmel's name may not be used to endorse or promote products derived from *
* this software without specific prior written permission. * Atmel's name may not be used to endorse or promote products derived from
* * this software without specific prior written permission.
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR *
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* ---------------------------------------------------------------------------- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ * ----------------------------------------------------------------------------
*/
/**
* \file /**
* * \file
* Implements UART console. *
* * Implements UART console.
*/ *
*/
/*----------------------------------------------------------------------------
* Headers /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ * Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include "board.h"
#include <stdio.h>
#include <stdint.h> #include <stdio.h>
#include <stdint.h>
#include "ringbuffer.h"
#include "ringbuffer.h"
/*----------------------------------------------------------------------------
* Definitions /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ * Definitions
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Variables /*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/ * Variables
*----------------------------------------------------------------------------*/
/** Is Console Initialized. */
static uint8_t _ucIsConsoleInitialized=0; /** Is Console Initialized. */
/** Ring buffer to queue data to be sent */ static uint8_t _ucIsConsoleInitialized=0;
static ringbuf uart_tx_buffer; /** Ring buffer to queue data to be sent */
static ringbuf uart_tx_buffer;
/**
* \brief Configures an USART peripheral with the specified parameters. /**
* * \brief Configures an USART peripheral with the specified parameters.
* \param baudrate Baudrate at which the USART should operate (in Hz). *
* \param masterClock Frequency of the system master clock (in Hz). * \param baudrate Baudrate at which the USART should operate (in Hz).
*/ * \param masterClock Frequency of the system master clock (in Hz).
extern void UART_Configure( uint32_t baudrate, uint32_t masterClock) */
{ extern void UART_Configure( uint32_t baudrate, uint32_t masterClock)
const Pin pPins[] = CONSOLE_PINS; {
Uart *pUart = CONSOLE_UART; const Pin pPins[] = CONSOLE_PINS;
Uart *pUart = CONSOLE_UART;
/* Configure PIO */
PIO_Configure(pPins, PIO_LISTSIZE(pPins)); /* Configure PIO */
PIO_Configure(pPins, PIO_LISTSIZE(pPins));
/* Configure PMC */
PMC->PMC_PCER0 = 1 << CONSOLE_ID; /* Configure PMC */
PMC->PMC_PCER0 = 1 << CONSOLE_ID;
/* Reset and disable receiver & transmitter */
pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX /* Reset and disable receiver & transmitter */
| UART_CR_RXDIS | UART_CR_TXDIS; pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX
| UART_CR_RXDIS | UART_CR_TXDIS;
/* Configure mode */
pUart->UART_MR = UART_MR_PAR_NO; /* Configure mode */
pUart->UART_MR = UART_MR_PAR_NO;
/* Configure baudrate */
/* Asynchronous, no oversampling */ /* Configure baudrate */
pUart->UART_BRGR = (masterClock / baudrate) / 16; /* Asynchronous, no oversampling */
//pUart->UART_BRGR = (masterClock / baudrate) / 16;
/* Disable PDC channel */ if ((masterClock / baudrate) % 16 >= 7) {
pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS; pUart->UART_BRGR = ( masterClock / baudrate) / 16 + 1;
} else {
/* Reset transmit ring buffer */ pUart->UART_BRGR = ( masterClock / baudrate) / 16 + 0;
rbuf_reset(&uart_tx_buffer); }
/* Enable TX interrupts */ /* Disable PDC channel */
pUart->UART_IER = UART_IER_TXRDY; pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
NVIC_EnableIRQ(CONSOLE_IRQ);
/* Reset transmit ring buffer */
/* Enable receiver and transmitter */ rbuf_reset(&uart_tx_buffer);
pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
/* Enable TX interrupts */
/* Remember the configuration is complete */ pUart->UART_IER = UART_IER_TXRDY;
_ucIsConsoleInitialized=1 ; NVIC_EnableIRQ(CONSOLE_IRQ);
}
/* Enable receiver and transmitter */
/** Interrupt Service routine to transmit queued data */ pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
void CONSOLE_ISR(void)
{ /* Remember the configuration is complete */
Uart *uart = CONSOLE_UART; _ucIsConsoleInitialized=1 ;
if (uart->UART_SR & UART_SR_TXRDY) { }
if (!rbuf_is_empty(&uart_tx_buffer)) {
//uart->UART_IER = UART_IER_TXRDY; /**
uart->UART_THR = rbuf_read(&uart_tx_buffer); * \brief Disables the USART peripheral and related IRQ
} else { */
uart->UART_IDR = UART_IER_TXRDY; void UART_Exit(void)
} {
} if (!_ucIsConsoleInitialized) {
} return;
}
/**
* \brief Outputs a character on the UART line. Uart *pUart = CONSOLE_UART;
* pUart->UART_IDR = UART_IDR_TXRDY;
* \note This function is synchronous (i.e. uses polling). pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA;
* \param c Character to send. PMC->PMC_PCDR0 = 1 << CONSOLE_ID;
*/ NVIC_DisableIRQ(CONSOLE_IRQ);
extern void UART_PutChar( uint8_t c ) }
{
Uart *pUart = CONSOLE_UART ; /** Interrupt Service routine to transmit queued data */
void CONSOLE_ISR(void)
/* Initialize console is not already done */ {
if ( !_ucIsConsoleInitialized ) Uart *uart = CONSOLE_UART;
{ if (uart->UART_SR & UART_SR_TXRDY) {
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK); if (!rbuf_is_empty(&uart_tx_buffer)) {
} uart->UART_THR = rbuf_read(&uart_tx_buffer);
} else {
/* Wait until there is space in the buffer */ uart->UART_IDR = UART_IER_TXRDY;
while (rbuf_is_full(&uart_tx_buffer)) { }
if (pUart->UART_SR & UART_SR_TXEMPTY) { }
pUart->UART_IER = UART_IER_TXRDY; }
CONSOLE_ISR();
} /**
} * \brief Outputs a character on the UART line.
*
/* Put character into buffer */ * \note This function is asynchronous (i.e. uses a buffer and interrupt to complete the transfer).
rbuf_write(&uart_tx_buffer, c); * \param c Character to send.
if (pUart->UART_SR & UART_SR_TXEMPTY) { */
pUart->UART_IER = UART_IER_TXRDY; void UART_PutChar( uint8_t uc )
CONSOLE_ISR(); {
} Uart *pUart = CONSOLE_UART ;
}
/* Initialize console is not already done */
/** if ( !_ucIsConsoleInitialized )
* \brief Input a character from the UART line. {
* UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
* \note This function is synchronous }
* \return character received.
*/ if (!rbuf_is_full(&uart_tx_buffer)) {
extern uint32_t UART_GetChar( void ) rbuf_write(&uart_tx_buffer, uc);
{ if (!(pUart->UART_IMR & UART_IMR_TXRDY)) {
Uart *pUart = CONSOLE_UART ; pUart->UART_IER = UART_IER_TXRDY;
CONSOLE_ISR();
if ( !_ucIsConsoleInitialized ) }
{ }
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK); }
}
/**
while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 ) * \brief Outputs a character on the UART line.
WDT_Restart(WDT); *
* \note This function is synchronous (i.e. uses polling and blocks until the transfer is complete).
return pUart->UART_RHR ; * \param c Character to send.
} */
void UART_PutChar_Sync( uint8_t uc )
/** {
* \brief Check if there is Input from UART line. Uart *pUart = CONSOLE_UART ;
*
* \return true if there is Input. /* Initialize console is not already done */
*/ if ( !_ucIsConsoleInitialized )
extern uint32_t UART_IsRxReady( void ) {
{ UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
Uart *pUart = CONSOLE_UART; }
if ( !_ucIsConsoleInitialized ) while (!(pUart->UART_SR & UART_SR_TXRDY)); /* Wait for transfer buffer to be empty */
{ pUart->UART_THR = uc; /* Send data to UART peripheral */
UART_Configure( CONSOLE_BAUDRATE, BOARD_MCK ) ; while (!(pUart->UART_SR & UART_SR_TXRDY)); /* Wait for transfer buffer to transferred to shift register */
} while (!(pUart->UART_SR & UART_SR_TXEMPTY)); /* Wait for transfer shift register to be empty (i.e. transfer is complete) */
}
return (pUart->UART_SR & UART_SR_RXRDY) > 0 ;
} /**
* \brief Input a character from the UART line.
/** *
* Displays the content of the given frame on the UART0. * \note This function is synchronous
* * \return character received.
* \param pucFrame Pointer to the frame to dump. */
* \param dwSize Buffer size in bytes. extern uint32_t UART_GetChar( void )
*/ {
extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize ) Uart *pUart = CONSOLE_UART ;
{
uint32_t dw ; if ( !_ucIsConsoleInitialized )
{
for ( dw=0 ; dw < dwSize ; dw++ ) UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
{ }
printf( "%02X ", pucFrame[dw] ) ;
} while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 )
WDT_Restart(WDT);
printf( "\n\r" ) ;
} return pUart->UART_RHR ;
}
/**
* Displays the content of the given buffer on the UART0. /**
* * \brief Check if there is Input from UART line.
* \param pucBuffer Pointer to the buffer to dump. *
* \param dwSize Buffer size in bytes. * \return true if there is Input.
* \param dwAddress Start address to display */
*/ extern uint32_t UART_IsRxReady( void )
extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) {
{ Uart *pUart = CONSOLE_UART;
uint32_t i ;
uint32_t j ; if ( !_ucIsConsoleInitialized )
uint32_t dwLastLineStart ; {
uint8_t* pucTmp ; UART_Configure( CONSOLE_BAUDRATE, BOARD_MCK ) ;
}
for ( i=0 ; i < (dwSize / 16) ; i++ )
{ return (pUart->UART_SR & UART_SR_RXRDY) > 0 ;
printf( "0x%08X: ", (unsigned int)(dwAddress + (i*16)) ) ; }
pucTmp = (uint8_t*)&pucBuffer[i*16] ;
/**
for ( j=0 ; j < 4 ; j++ ) * Displays the content of the given frame on the UART0.
{ *
printf( "%02X%02X%02X%02X ", pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3] ) ; * \param pucFrame Pointer to the frame to dump.
pucTmp += 4 ; * \param dwSize Buffer size in bytes.
} */
extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize )
pucTmp=(uint8_t*)&pucBuffer[i*16] ; {
uint32_t dw ;
for ( j=0 ; j < 16 ; j++ )
{ for ( dw=0 ; dw < dwSize ; dw++ )
UART_PutChar( *pucTmp++ ) ; {
} printf( "%02X ", pucFrame[dw] ) ;
}
printf( "\n\r" ) ;
} printf( "\n\r" ) ;
}
if ( (dwSize%16) != 0 )
{ /**
dwLastLineStart=dwSize - (dwSize%16) ; * Displays the content of the given buffer on the UART0.
*
printf( "0x%08X: ", (unsigned int)(dwAddress + dwLastLineStart) ) ; * \param pucBuffer Pointer to the buffer to dump.
for ( j=dwLastLineStart ; j < dwLastLineStart+16 ; j++ ) * \param dwSize Buffer size in bytes.
{ * \param dwAddress Start address to display
if ( (j!=dwLastLineStart) && (j%4 == 0) ) */
{ extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress )
printf( " " ) ; {
} uint32_t i ;
uint32_t j ;
if ( j < dwSize ) uint32_t dwLastLineStart ;
{ uint8_t* pucTmp ;
printf( "%02X", pucBuffer[j] ) ;
} for ( i=0 ; i < (dwSize / 16) ; i++ )
else {
{ printf( "0x%08X: ", (unsigned int)(dwAddress + (i*16)) ) ;
printf(" ") ; pucTmp = (uint8_t*)&pucBuffer[i*16] ;
}
} for ( j=0 ; j < 4 ; j++ )
{
printf( " " ) ; printf( "%02X%02X%02X%02X ", pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3] ) ;
for ( j=dwLastLineStart ; j < dwSize ; j++ ) pucTmp += 4 ;
{ }
UART_PutChar( pucBuffer[j] ) ;
} pucTmp=(uint8_t*)&pucBuffer[i*16] ;
printf( "\n\r" ) ; for ( j=0 ; j < 16 ; j++ )
} {
} UART_PutChar( *pucTmp++ ) ;
}
/**
* Reads an integer printf( "\n\r" ) ;
* }
* \param pdwValue Pointer to the uint32_t variable to contain the input value.
*/ if ( (dwSize%16) != 0 )
extern uint32_t UART_GetInteger( uint32_t* pdwValue ) {
{ dwLastLineStart=dwSize - (dwSize%16) ;
uint8_t ucKey ;
uint8_t ucNbNb=0 ; printf( "0x%08X: ", (unsigned int)(dwAddress + dwLastLineStart) ) ;
uint32_t dwValue=0 ; for ( j=dwLastLineStart ; j < dwLastLineStart+16 ; j++ )
{
while ( 1 ) if ( (j!=dwLastLineStart) && (j%4 == 0) )
{ {
ucKey=UART_GetChar() ; printf( " " ) ;
UART_PutChar( ucKey ) ; }
if ( ucKey >= '0' && ucKey <= '9' ) if ( j < dwSize )
{ {
dwValue = (dwValue * 10) + (ucKey - '0'); printf( "%02X", pucBuffer[j] ) ;
ucNbNb++ ; }
} else
else {
{ printf(" ") ;
if ( ucKey == 0x0D || ucKey == ' ' ) }
{ }
if ( ucNbNb == 0 )
{ printf( " " ) ;
printf( "\n\rWrite a number and press ENTER or SPACE!\n\r" ) ; for ( j=dwLastLineStart ; j < dwSize ; j++ )
return 0 ; {
} UART_PutChar( pucBuffer[j] ) ;
else }
{
printf( "\n\r" ) ; printf( "\n\r" ) ;
*pdwValue=dwValue ; }
}
return 1 ;
} /**
} * Reads an integer
else *
{ * \param pdwValue Pointer to the uint32_t variable to contain the input value.
printf( "\n\r'%c' not a number!\n\r", ucKey ) ; */
extern uint32_t UART_GetInteger( uint32_t* pdwValue )
return 0 ; {
} uint8_t ucKey ;
} uint8_t ucNbNb=0 ;
WDT_Restart(WDT); uint32_t dwValue=0 ;
}
} while ( 1 )
{
/** ucKey=UART_GetChar() ;
* Reads an integer and check the value UART_PutChar( ucKey ) ;
*
* \param pdwValue Pointer to the uint32_t variable to contain the input value. if ( ucKey >= '0' && ucKey <= '9' )
* \param dwMin Minimum value {
* \param dwMax Maximum value dwValue = (dwValue * 10) + (ucKey - '0');
*/ ucNbNb++ ;
extern uint32_t UART_GetIntegerMinMax( uint32_t* pdwValue, uint32_t dwMin, uint32_t dwMax ) }
{ else
uint32_t dwValue=0 ; {
if ( ucKey == 0x0D || ucKey == ' ' )
if ( UART_GetInteger( &dwValue ) == 0 ) {
{ if ( ucNbNb == 0 )
return 0 ; {
} printf( "\n\rWrite a number and press ENTER or SPACE!\n\r" ) ;
return 0 ;
if ( dwValue < dwMin || dwValue > dwMax ) }
{ else
printf( "\n\rThe number have to be between %d and %d\n\r", (int)dwMin, (int)dwMax ) ; {
printf( "\n\r" ) ;
return 0 ; *pdwValue=dwValue ;
}
return 1 ;
printf( "\n\r" ) ; }
}
*pdwValue = dwValue ; else
{
return 1 ; printf( "\n\r'%c' not a number!\n\r", ucKey ) ;
}
return 0 ;
/** }
* Reads an hexadecimal number }
* WDT_Restart(WDT);
* \param pdwValue Pointer to the uint32_t variable to contain the input value. }
*/ }
extern uint32_t UART_GetHexa32( uint32_t* pdwValue )
{ /**
uint8_t ucKey ; * Reads an integer and check the value
uint32_t dw = 0 ; *
uint32_t dwValue = 0 ; * \param pdwValue Pointer to the uint32_t variable to contain the input value.
* \param dwMin Minimum value
for ( dw=0 ; dw < 8 ; dw++ ) * \param dwMax Maximum value
{ */
ucKey = UART_GetChar() ; extern uint32_t UART_GetIntegerMinMax( uint32_t* pdwValue, uint32_t dwMin, uint32_t dwMax )
UART_PutChar( ucKey ) ; {
uint32_t dwValue=0 ;
if ( ucKey >= '0' && ucKey <= '9' )
{ if ( UART_GetInteger( &dwValue ) == 0 )
dwValue = (dwValue * 16) + (ucKey - '0') ; {
} return 0 ;
else }
{
if ( ucKey >= 'A' && ucKey <= 'F' ) if ( dwValue < dwMin || dwValue > dwMax )
{ {
dwValue = (dwValue * 16) + (ucKey - 'A' + 10) ; printf( "\n\rThe number have to be between %d and %d\n\r", (int)dwMin, (int)dwMax ) ;
}
else return 0 ;
{ }
if ( ucKey >= 'a' && ucKey <= 'f' )
{ printf( "\n\r" ) ;
dwValue = (dwValue * 16) + (ucKey - 'a' + 10) ;
} *pdwValue = dwValue ;
else
{ return 1 ;
printf( "\n\rIt is not a hexa character!\n\r" ) ; }
return 0 ; /**
} * Reads an hexadecimal number
} *
} * \param pdwValue Pointer to the uint32_t variable to contain the input value.
} */
extern uint32_t UART_GetHexa32( uint32_t* pdwValue )
printf("\n\r" ) ; {
*pdwValue = dwValue ; uint8_t ucKey ;
uint32_t dw = 0 ;
return 1 ; uint32_t dwValue = 0 ;
}
for ( dw=0 ; dw < 8 ; dw++ )
#if defined __ICCARM__ /* IAR Ewarm 5.41+ */ {
/** ucKey = UART_GetChar() ;
* \brief Outputs a character on the UART. UART_PutChar( ucKey ) ;
*
* \param c Character to output. if ( ucKey >= '0' && ucKey <= '9' )
* {
* \return The character that was output. dwValue = (dwValue * 16) + (ucKey - '0') ;
*/ }
extern WEAK signed int putchar( signed int c ) else
{ {
UART_PutChar( c ) ; if ( ucKey >= 'A' && ucKey <= 'F' )
{
return c ; dwValue = (dwValue * 16) + (ucKey - 'A' + 10) ;
} }
#endif // defined __ICCARM__ else
{
if ( ucKey >= 'a' && ucKey <= 'f' )
{
dwValue = (dwValue * 16) + (ucKey - 'a' + 10) ;
}
else
{
printf( "\n\rIt is not a hexa character!\n\r" ) ;
return 0 ;
}
}
}
}
printf("\n\r" ) ;
*pdwValue = dwValue ;
return 1 ;
}
#if defined __ICCARM__ /* IAR Ewarm 5.41+ */
/**
* \brief Outputs a character on the UART.
*
* \param c Character to output.
*
* \return The character that was output.
*/
extern WEAK signed int putchar( signed int c )
{
UART_PutChar( c ) ;
return c ;
}
#endif // defined __ICCARM__

View File

@@ -0,0 +1,166 @@
/* Osmocom ngff-cardem board definition
*
* (C) 2021 by Harald Welte <laforge@osmocom.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#include "board_common.h"
#include "simtrace_usb.h"
/** Name of the board */
#define BOARD_NAME "NGFF-CARDEM"
/** Board definition */
#define ngff_cardem
/** oscillator used as main clock source (in Hz) */
#define BOARD_MAINOSC 12000000
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58000000 // 12.000 * 29 / 6
/** MCU pin connected to red LED */
#define PIO_LED_RED PIO_PA17
/** MCU pin connected to green LED */
#define PIO_LED_GREEN PIO_PA18
/** red LED pin definition */
#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** green LED pin definition */
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LEDs pin definition */
#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
/** index for red LED in LEDs pin definition array */
#define LED_NUM_RED 0
/** index for green LED in LEDs pin definition array */
#define LED_NUM_GREEN 1
/** the green LED is actually red and used as indication for USIM1 */
#define LED_USIM1 LED_GREEN
/* USIM 2 interface (USART) */
#define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_USIM2_IO {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PINS_ISO7816_USIM2 PIN_USIM2_CLK, PIN_USIM2_IO
/* USIM 2 interface (TC) */
#define PIN_USIM2_IO_TC {PIO_PA1, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_USIM2_CLK_TC {PIO_PA4, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PINS_TC_USIM2 PIN_USIM2_IO_TC, PIN_USIM2_CLK_TC
/* USIM 1 interface (USART) */
#define PIN_USIM1_IO {PIO_PA22, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_USIM1_CLK {PIO_PA23, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PINS_ISO7816_USIM1 PIN_USIM1_CLK, PIN_USIM1_IO
/* USIM 1 interface (TC) */
#define PIN_USIM1_IO_TC {PIO_PA27, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_USIM1_CLK_TC {PIO_PA29, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PINS_TC_USIM1 PIN_USIM1_IO_TC, PIN_USIM1_CLK_TC
#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
#define PIN_USIM1_VCC {PIO_PB3, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}
#define PIN_USIM2_nRST {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
//#define PIN_USIM2_VCC {PIO_PB2, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}
#define PINS_USIM1 PINS_TC_USIM1, PINS_ISO7816_USIM1, PIN_USIM1_nRST
#define PINS_USIM2 PINS_TC_USIM2, PINS_ISO7816_USIM2, PIN_USIM2_nRST
/* from v3 and onwards only (!) */
#define PIN_DET_USIM1_PRES {PIO_PA8, PIOA, ID_PIOA, PIO_INPUT, PIO_DEGLITCH | PIO_IT_EDGE}
/* inputs reading the WWAN LED level */
#define PIN_WWAN1 {PIO_PA15, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}
#define PINS_WWAN_IN { PIN_WWAN1 }
#define PIN_MODEM_EN {PIO_PA11, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define PIN_N_MODEM_PWR_ON {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/* outputs controlling RESET input of modems */
#define PIN_PERST1 {PIO_PA25, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define PINS_PERST { PIN_PERST1 }
#define PIN_VERSION_DET {PIO_PA19, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_DEFAULT}
/* GPIO towards SPDT switches between real SIM and SAM3 */
//#define PIN_SIM_SWITCH1 {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
//#define PIN_SIM_SWITCH2 {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP
#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
#define BOARD_USB_PRODUCT_ID USB_PRODUCT_NGFF_CARDEM
#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_NGFF_CARDEM
#define BOARD_USB_RELEASE 0x010
#define DETECT_VCC_BY_ADC
#define VCC_UV_THRESH_1V8 1500000
#define VCC_UV_THRESH_3V VCC_UV_THRESH_1V8
#ifdef APPLICATION_cardem
#define HAVE_CARDEM
#define HAVE_BOARD_CARDINSERT
struct cardem_inst;
void board_set_card_insert(struct cardem_inst *ci, bool card_insert);
#endif
#ifdef APPLICATION_trace
#define HAVE_SNIFFER
#endif
/* Card I/O data signal input/output (I/O_SIM in schematic) */
#define PIN_SIM_IO {PIO_PA6A_TXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Card CLK clock input (CLK_SIM in schematic) */
#define PIN_SIM_CLK {PIO_PA2B_SCK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/* Card RST reset signal input (use as input since the phone will drive it) */
#define PIN_SIM_RST_SNIFF {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEGLITCH | PIO_IT_EDGE}
/* Pins used to sniff phone-card communication */
#define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF
/* Pin to measure card I/O timing (to start measuring the ETU on I/O activity; connected I/O_SIM in schematic) */
#define PIN_SIM_IO_INPUT {PIO_PA1B_TIOB0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/* Pin used as clock input (to measure the ETU duration; connected to CLK_SIM in schematic) */
#define PIN_SIM_CLK_INPUT {PIO_PA4B_TCLK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/* Pins used to measure ETU timing (using timer counter) */
#define PINS_TC PIN_SIM_IO_INPUT, PIN_SIM_CLK_INPUT
//default state: NO uart connected, modem connected to physical sim, NO sim presence override, modem powers sim slot
#define pin_conn_usim1_default {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define pin_conn_usim2_default {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define pin_conn_mdm_sim_default {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define pin_conn_set_sim_det_default {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define pin_en_st_sim_vdd_default {PIO_PB2, PIOB, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT}
#define pin_en_mdm_sim_vdd_default {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
//cardem state: uart2 (!) connected, NO modem connected to physical sim, sim presence override, NOTHING powers sim slot
#define pin_conn_usim1_cem {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define pin_conn_usim2_cem {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define pin_conn_mdm_sim_cem {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define pin_en_st_sim_vdd_cem {PIO_PB2, PIOB, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT}
#define pin_en_mdm_sim_vdd_cem {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
//trace state: uart2 (!) connected, modem connected to physical sim, st powers sim slot
#define pin_conn_usim1_trace {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define pin_conn_usim2_trace {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define pin_conn_mdm_sim_trace {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define pin_conn_set_sim_det_trace {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define pin_en_st_sim_vdd_trace {PIO_PB2, PIOB, ID_PIOB, PIO_OUTPUT_1, PIO_DEFAULT}
#define pin_en_mdm_sim_vdd_trace {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define PIN_MODEM_EN_off {PIO_PA11, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define PINS_SIM_DEFAULT pin_conn_usim1_default, pin_conn_usim2_default, pin_conn_mdm_sim_default, pin_conn_set_sim_det_default, PIN_N_MODEM_PWR_ON, PIN_MODEM_EN, pin_en_st_sim_vdd_default, pin_en_mdm_sim_vdd_default
#define PINS_SIM_CARDEM pin_conn_usim1_cem, pin_conn_usim2_cem, pin_conn_mdm_sim_cem, pin_en_mdm_sim_vdd_cem, pin_en_st_sim_vdd_cem// , pin_conn_set_sim_det_cem
#define PINS_BUS_SNIFF pin_conn_usim1_trace, pin_conn_usim2_trace, pin_conn_mdm_sim_trace, pin_conn_set_sim_det_trace,PIN_MODEM_EN_off
#define PINS_PWR_SNIFF PIN_N_MODEM_PWR_ON, PIN_MODEM_EN, pin_en_st_sim_vdd_trace, pin_en_mdm_sim_vdd_trace

View File

@@ -0,0 +1,22 @@
/* card presence utilities
*
* (C) 2016-2017 by Harald Welte <hwelte@hmw-consulting.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
int is_card_present(int port);
int card_present_init(void);

View File

@@ -0,0 +1,20 @@
/* Code to read/track the status of the WWAN LEDs of attached modems
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
int wwan_led_active(int wwan);
int wwan_led_init(void);

View File

@@ -0,0 +1,21 @@
/* Code to control the PERST lines of attached modems
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
int wwan_perst_set(int modem_nr, int active);
int wwan_perst_do_reset_pulse(int modem_nr, unsigned int duration_ms);
int wwan_perst_init(void);

View File

@@ -0,0 +1 @@
ngff-cardem

View File

@@ -0,0 +1,159 @@
/* sysmocom ngff-cardem application code
*
* (C) 2021 Harald Welte <laforge@osmocom.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "simtrace.h"
#include "utils.h"
#include "led.h"
#include "wwan_led.h"
#include "wwan_perst.h"
#include "sim_switch.h"
#include "boardver_adc.h"
#include "card_pres.h"
#include <osmocom/core/timer.h>
#include "usb_buf.h"
/* array of generated USB Strings */
extern unsigned char *usb_strings[];
/* returns '1' in case we should break any endless loop */
void board_exec_dbg_cmd(int ch)
{
switch (ch) {
case '?':
printf("\t?\thelp\n\r");
printf("\tR\treset SAM3\n\r");
printf("\tl\tswitch off LED 1\n\r");
printf("\tL\tswitch on LED 1\n\r");
printf("\tg\tswitch off LED 2\n\r");
printf("\tG\tswitch on LED 2\n\r");
printf("\t1\tGenerate 1ms reset pulse on WWAN1\n\r");
printf("\t!\tSwitch Channel A from physical -> remote\n\r");
printf("\tt\t(pseudo)talloc report\n\r");
break;
case 'R':
printf("Asking NVIC to reset us\n\r");
USBD_Disconnect();
NVIC_SystemReset();
break;
case 'l':
led_blink(LED_GREEN, BLINK_ALWAYS_OFF);
printf("LED 1 switched off\n\r");
break;
case 'L':
led_blink(LED_GREEN, BLINK_ALWAYS_ON);
printf("LED 1 switched on\n\r");
break;
case 'g':
led_blink(LED_RED, BLINK_ALWAYS_OFF);
printf("LED 2 switched off\n\r");
break;
case 'G':
led_blink(LED_RED, BLINK_ALWAYS_ON);
printf("LED 2 switched on\n\r");
break;
case '1':
printf("Resetting Modem\n\r");
wwan_perst_do_reset_pulse(0, 300);
break;
case '!':
sim_switch_use_physical(0, 0);
break;
case 't':
talloc_report(NULL, stdout);
break;
default:
printf("Unknown command '%c'\n\r", ch);
break;
}
}
void board_main_top(void)
{
#ifndef APPLICATION_dfu
usb_buf_init();
wwan_led_init();
wwan_perst_init();
sim_switch_init();
#endif
/* Obtain the circuit board version (currently just prints voltage) */
get_board_version_adc();
#ifndef APPLICATION_dfu
/* Initialize checking for card insert/remove events */
card_present_init();
#endif
wwan_perst_set(0, 0);
}
static int uart_has_loopback_jumper(void)
{
unsigned int i;
const Pin uart_loopback_pins[] = {
{PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT},
{PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
};
/* Configure UART pins as I/O */
PIO_Configure(uart_loopback_pins, PIO_LISTSIZE(uart_loopback_pins));
/* Send pattern over UART TX and check if it is received on RX
* If the loop doesn't get interrupted, RxD always follows TxD and thus a
* loopback jumper has been placed on RxD/TxD, and we will boot
* into DFU unconditionally
*/
int has_loopback_jumper = 1;
for (i = 0; i < 10; i++) {
/* Set TxD high; abort if RxD doesn't go high either */
PIO_Set(&uart_loopback_pins[1]);
if (!PIO_Get(&uart_loopback_pins[0])) {
has_loopback_jumper = 0;
break;
}
/* Set TxD low, abort if RxD doesn't go low either */
PIO_Clear(&uart_loopback_pins[1]);
if (PIO_Get(&uart_loopback_pins[0])) {
has_loopback_jumper = 0;
break;
}
}
/* Put pins back to UART mode */
const Pin uart_pins[] = {PINS_UART};
PIO_Configure(uart_pins, PIO_LISTSIZE(uart_pins));
return has_loopback_jumper;
}
int board_override_enter_dfu(void)
{
/* If the loopback jumper is set, we enter DFU mode */
if (uart_has_loopback_jumper())
return 1;
return 0;
}
static const Pin deton = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
static const Pin detoff = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT};
void board_set_card_insert(struct cardem_inst *ci, bool card_insert)
{
PIO_Configure(card_insert ? &deton : &detoff, 1);
}

View File

@@ -0,0 +1,76 @@
/* card presence utilities
*
* (C) 2016-2021 by Harald Welte <hwelte@hmw-consulting.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <osmocom/core/timer.h>
#include "board.h"
#include "utils.h"
#include "card_pres.h"
#define NUM_CARDPRES 1
#define TIMER_INTERVAL_MS 500
static const Pin pin_cardpres[NUM_CARDPRES] = { PIN_DET_USIM1_PRES };
static int last_state[NUM_CARDPRES] = { -1 };
static struct osmo_timer_list cardpres_timer;
/* Determine if a SIM card is present in the given slot */
int is_card_present(int port)
{
const Pin *pin;
int present;
if (port < 0 || port >= NUM_CARDPRES)
return -1;
pin = &pin_cardpres[port];
/* high active here */
present = PIO_Get(pin);
return present;
}
static void cardpres_tmr_cb(void *data)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(pin_cardpres); i++) {
int state = is_card_present(i);
if (state != last_state[i]) {
TRACE_INFO("%u: Card Detect Status %d -> %d\r\n", i, last_state[i], state);
/* FIXME: report to USB host */
last_state[i] = state;
}
}
osmo_timer_schedule(&cardpres_timer, 0, TIMER_INTERVAL_MS*1000);
}
int card_present_init(void)
{
unsigned int i;
PIO_Configure(pin_cardpres, ARRAY_SIZE(pin_cardpres));
/* start timer */
cardpres_timer.cb = cardpres_tmr_cb;
osmo_timer_schedule(&cardpres_timer, 0, TIMER_INTERVAL_MS*1000);
return 2;
}

View File

@@ -0,0 +1,81 @@
/* Code to switch between local (physical) and remote (emulated) SIM
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "trace.h"
#include "led.h"
#include "sim_switch.h"
//uart12bus 2-20e pa20
//uart22bus 1-20e pa28
//usim2bus 1-10e pa0 pivot
//sim det 2-10e pa13
static const Pin pins_default[] = {PINS_SIM_DEFAULT};
static const Pin pins_cem[] = {PINS_SIM_CARDEM};
static int initialized = 0;
int sim_switch_use_physical(unsigned int nr, int physical)
{
const Pin pin = PIN_MODEM_EN;// PIN_N_MODEM_PWR_ON;
enum led led;
if (!initialized) {
TRACE_ERROR("Somebody forgot to call sim_switch_init()\r\n");
sim_switch_init();
}
TRACE_INFO("Modem %d: %s SIM\n\r", nr,
physical ? "physical" : "virtual");
switch (nr) {
case 0:
led = LED_USIM1;
break;
default:
TRACE_ERROR("Invalid SIM%u\n\r", nr);
return -1;
}
if (physical) {
TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
PIO_Configure(pins_default, PIO_LISTSIZE(pins_default));
led_blink(led, BLINK_ALWAYS_ON);
} else {
TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
PIO_Configure(pins_cem, PIO_LISTSIZE(pins_cem));
led_blink(led, BLINK_5O_5F);
}
/* just power cycle the modem because this circumvents weird issues with unreliable signals */
PIO_Clear(&pin);
mdelay(200);
PIO_Set(&pin);
return 0;
}
int sim_switch_init(void)
{
PIO_Configure(pins_default, PIO_LISTSIZE(pins_default));
initialized = 1;
return 1;
}

View File

@@ -0,0 +1,93 @@
/* Code to read/track the status of the WWAN LEDs of attached modems
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
/* Depending on the board this is running on, it might be possible
* for the controller to read the status of the WWAN LED output lines of
* the cellular modem. If the board supports this, it sets the
* PIN_WWAN1 and/or PIN_WWAN2 defines in its board.h file.
*/
#include "board.h"
#include "wwan_led.h"
#ifdef PIN_WWAN1
static const Pin pin_wwan1 = PIN_WWAN1;
static void wwan1_irqhandler(const Pin *pPin)
{
int active = wwan_led_active(0);
TRACE_INFO("0: WWAN LED %u\r\n", active);
/* TODO: notify host via USB */
}
#endif
#ifdef PIN_WWAN2
static const Pin pin_wwan2 = PIN_WWAN2;
static void wwan2_irqhandler(const Pin *pPin)
{
int active = wwan_led_active(1);
TRACE_INFO("1: WWAN LED %u\r\n", active);
/* TODO: notify host via USB */
}
#endif
/* determine if a given WWAN led is currently active or not */
int wwan_led_active(int wwan)
{
const Pin *pin;
int active;
switch (wwan) {
#ifdef PIN_WWAN1
case 0:
pin = &pin_wwan1;
break;
#endif
#ifdef PIN_WWAN2
case 1:
pin = &pin_wwan2;
break;
#endif
default:
return -1;
}
active = PIO_Get(pin) ? 0 : 1;
return active;
}
int wwan_led_init(void)
{
int num_leds = 0;
#ifdef PIN_WWAN1
PIO_Configure(&pin_wwan1, 1);
PIO_ConfigureIt(&pin_wwan1, wwan1_irqhandler);
PIO_EnableIt(&pin_wwan1);
num_leds++;
#endif
#ifdef PIN_WWAN2
PIO_Configure(&pin_wwan2, 1);
PIO_ConfigureIt(&pin_wwan2, wwan2_irqhandler);
PIO_EnableIt(&pin_wwan2);
num_leds++;
#endif
return num_leds;
}

View File

@@ -0,0 +1,127 @@
/* Code to control the PERST lines of attached modems
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
/* Depending on the board this is running on, it might be possible
* for the controller to set the status of the PERST input line of
* the cellular modem. If the board supports this, it sets the
* PIN_PERST1 and/or PIN_PERST2 defines in its board.h file.
*/
#include "board.h"
#include "trace.h"
#include "wwan_perst.h"
#include <osmocom/core/timer.h>
struct wwan_perst {
uint8_t idx;
const Pin pin;
struct osmo_timer_list timer;
};
#ifdef PIN_PERST1
static struct wwan_perst perst1 = {
.idx = 0,
.pin = PIN_PERST1,
};
#endif
#ifdef PIN_PERST2
static struct wwan_perst perst2 = {
.idx = 1,
.pin = PIN_PERST2,
};
#endif
static int initialized = 0;
static void perst_tmr_cb(void *data)
{
struct wwan_perst *perst = data;
/* release the (low-active) reset */
TRACE_INFO("%u: De-asserting modem reset\r\n", perst->idx);
PIO_Clear(&perst->pin);
}
static struct wwan_perst *get_perst_for_modem(int modem_nr)
{
if (!initialized) {
TRACE_ERROR("Somebody forgot to call wwan_perst_init()\r\n");
wwan_perst_init();
}
switch (modem_nr) {
#ifdef PIN_PERST1
case 0:
return &perst1;
#endif
#ifdef PIN_PERST2
case 1:
return &perst2;
#endif
default:
return NULL;
}
}
int wwan_perst_do_reset_pulse(int modem_nr, unsigned int duration_ms)
{
struct wwan_perst *perst = get_perst_for_modem(modem_nr);
if (!perst)
return -1;
TRACE_INFO("%u: Asserting modem reset\r\n", modem_nr);
PIO_Set(&perst->pin);
osmo_timer_schedule(&perst->timer, duration_ms/1000, (duration_ms%1000)*1000);
return 0;
}
int wwan_perst_set(int modem_nr, int active)
{
struct wwan_perst *perst = get_perst_for_modem(modem_nr);
if (!perst)
return -1;
osmo_timer_del(&perst->timer);
if (active) {
TRACE_INFO("%u: Asserting modem reset\r\n", modem_nr);
PIO_Set(&perst->pin);
} else {
TRACE_INFO("%u: De-asserting modem reset\r\n", modem_nr);
PIO_Clear(&perst->pin);
}
return 0;
}
int wwan_perst_init(void)
{
int num_perst = 0;
#ifdef PIN_PERST1
PIO_Configure(&perst1.pin, 1);
perst1.timer.cb = perst_tmr_cb;
perst1.timer.data = (void *) &perst1;
num_perst++;
#endif
#ifdef PIN_PERST2
PIO_Configure(&perst2.pin, 1);
perst2.timer.cb = perst_tmr_cb;
perst2.timer.data = (void *) &perst2;
num_perst++;
#endif
initialized = 1;
return num_perst;
}

View File

@@ -0,0 +1,123 @@
/* octSIMtest with SAM3S board definition
*
* (C) 2019 by sysmocom -s.f.m.c. GmbH, Author:Joachim Steiger <jsteiger@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#include "board_common.h"
#include "simtrace_usb.h"
/* Name of the board */
#define BOARD_NAME "OCTSIMTEST"
/* Board definition */
#define octsimtest
/** oscillator used as main clock source (in Hz) */
#define BOARD_MAINOSC 18432000
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58982400 // 18.432 * 16 / 5
/** Pin configuration **/
/** there is no red LED, but the code needs this second LED, thus we provide an unused pin */
#define PIO_LED_RED PIO_PB13
/** MCU pin connected to green LED, which is actually amber, and the logic is inverted since it is connected to an NPN transistor (used as open drain) */
#define PIO_LED_GREEN PIO_PA4
/** red LED pin definition */
#define PIN_LED_RED {PIO_LED_RED, PIOB, ID_PIOB, PIO_OUTPUT_1, PIO_DEFAULT}
/** green LED pin definition */
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LEDs pin definition */
#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
/** index for red LED in LEDs pin definition array */
#define LED_NUM_RED 0
/** index for green LED in LEDs pin definition array */
#define LED_NUM_GREEN 1
/* Button to force bootloader start (shorted to ground when pressed */
#define PIN_BOOTLOADER_SW {PIO_PA5, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP}
// FIXME PA8 is 32khz xtal on octsimtest
/* Pull card presence pin high (shorted to ground in card slot when card is present) */
/** Phone connection **/
/* Phone USIM slot 1 VCC pin (VCC_PHONE in schematic) */
#define PIN_USIM1_VCC {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
/* Phone USIM slot 1 RST pin (active low; RST_PHONE in schematic) */
#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_EDGE | PIO_DEGLITCH }
/* Phone I/O data signal input/output (I/O_PHONE in schematic) */
#define PIN_PHONE_IO {PIO_PA22A_TXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Phone CLK clock input (CLK_PHONE in schematic) */
#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Pin used to switch level shifter in I/O line between rx (0) and tx (1) */
#define PIN_USIM1_IO_DIR {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/* Pin used for phone USIM slot 1 communication */
#define PINS_USIM1 PIN_PHONE_IO, PIN_PHONE_CLK, PIN_PHONE_CLK_INPUT, PIN_USIM1_VCC, PIN_PHONE_IO_INPUT, PIN_USIM1_nRST, PIN_USIM1_IO_DIR
/* Phone I/O data signal input/output (unused USART RX input; connected to I/O_PHONE in schematic) */
#define PIN_PHONE_IO_INPUT {PIO_PA21A_RXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Pin used as clock input (to measure the ETU duration; connected to CLK_PHONE in schematic) */
#define PIN_PHONE_CLK_INPUT {PIO_PA29B_TCLK2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/** Default pin configuration **/
/** External SPI flash interface **/
/* SPI MISO pin definition */
#define PIN_SPI_MISO {PIO_PA12A_MISO, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP}
/* SPI MOSI pin definition */
#define PIN_SPI_MOSI {PIO_PA13A_MOSI, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* SPI SCK pin definition */
#define PIN_SPI_SCK {PIO_PA14A_SPCK, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* SPI pins definition. Contains MISO, MOSI & SCK */
#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SCK
/* SPI chip select 0 pin definition */
#define PIN_SPI_NPCS0 {PIO_PA11A_NPCS0, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* SPI flash write protect pin (active low, pulled low) */
#define PIN_SPI_WP {PA15, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/** USB definitions */
/* OpenMoko SIMtrace 2 USB vendor ID */
#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
/* OpenMoko SIMtrace 2 USB product ID (main application/runtime mode) */
#define BOARD_USB_PRODUCT_ID USB_PRODUCT_OCTSIMTEST
/* OpenMoko SIMtrace 2 DFU USB product ID (DFU bootloader/DFU mode) */
#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_OCTSIMTEST
/* USB release number (bcdDevice, shown as 0.00) */
#define BOARD_USB_RELEASE 0x000
/* Indicate SIMtrace is bus power in USB attributes */
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
#define DETECT_VCC_BY_ADC
/* we have a resistive voltage divider of 47 + 30 kOhms to also detect 5V supply power */
#define VCC_UV_THRESH_1V8 (1500000*47)/(47+30)
#define VCC_UV_THRESH_3V (2500000*47)/(47+30)
#define HAVE_SLOT_MUX
#define HAVE_BOARD_CARDINSERT
struct cardem_inst;
void board_set_card_insert(struct cardem_inst *ci, bool card_insert);
/** Supported modes */
/* SIMtrace board supports sniffer mode */
//#define HAVE_SNIFFER
/* SIMtrace board supports CCID mode */
//#define HAVE_CCID
/* SIMtrace board supports card emulation mode */
#define HAVE_CARDEM
/* SIMtrace board supports man-in-the-middle mode */
//#define HAVE_MITM
/* octsimtest board supports gpio_test mode */
#define HAVE_GPIO_TEST

View File

@@ -0,0 +1,28 @@
/* I2C EEPROM memory read and write utilities
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#include <stdbool.h>
void i2c_pin_init(void);
bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte);
uint8_t i2c_read_byte(bool nack, bool send_stop);
void i2c_stop_cond(void);
int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
int eeprom_read_byte(uint8_t slave, uint8_t addr);

View File

@@ -0,0 +1,27 @@
/* mcp23017 i2c gpio expander read and write utilities
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#define MCP23017_ADDRESS 0x20
int mcp23017_init(uint8_t slave, uint8_t iodira, uint8_t iodirb);
int mcp23017_test(uint8_t slave);
int mcp23017_toggle(uint8_t slave);
int mcp23017_set_output_a(uint8_t slave, uint8_t val);
int mcp23017_set_output_b(uint8_t slave, uint8_t val);
//int mcp23017_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
//int mcp23017_read_byte(uint8_t slave, uint8_t addr);

View File

@@ -0,0 +1,17 @@
#pragma once
void mux_init(void);
int mux_set_slot(uint8_t s);
int mux_get_slot(void);
void mux_set_freq(uint8_t s);
/* this reflects the wiring between U5 and U4 */
#define MUX_FREQ_DIV_2 0
#define MUX_FREQ_DIV_4 1
#define MUX_FREQ_DIV_16 2
#define MUX_FREQ_DIV_32 3
#define MUX_FREQ_DIV_32 3
#define MUX_FREQ_DIV_128 4
#define MUX_FREQ_DIV_512 5
#define MUX_FREQ_DIV_2048 6
#define MUX_FREQ_DIV_4096 7

View File

@@ -0,0 +1 @@
sysmoOCTSIM-Tester

View File

@@ -0,0 +1,124 @@
/* SIMtrace with SAM3S specific application code
*
* (C) 2017 by Harald Welte <laforge@gnumonks.org>
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdbool.h>
#include "board.h"
#include "simtrace.h"
#include "utils.h"
#include "sim_switch.h"
#include <osmocom/core/timer.h>
#include "usb_buf.h"
#include "i2c.h"
#include "mcp23017.h"
#include "mux.h"
static bool mcp2317_present = false;
void board_exec_dbg_cmd(int ch)
{
switch (ch) {
case '?':
printf("\t?\thelp\n\r");
printf("\t0-8\tselect physical SIM slot\n\r");
printf("\tR\treset SAM3\n\r");
printf("\tm\trun mcp23017 test\n\r");
printf("\ti\tset card insert via I2C\n\r");
printf("\tI\tdisable card insert\n\r");
break;
case '0': mux_set_slot(0); break;
case '1': mux_set_slot(1); break;
case '2': mux_set_slot(2); break;
case '3': mux_set_slot(3); break;
case '4': mux_set_slot(4); break;
case '5': mux_set_slot(5); break;
case '6': mux_set_slot(6); break;
case '7': mux_set_slot(7); break;
case 'R':
printf("Asking NVIC to reset us\n\r");
USBD_Disconnect();
NVIC_SystemReset();
break;
case 'm':
mcp23017_test(MCP23017_ADDRESS);
break;
case 'i':
printf("Setting card insert (slot=%u)\r\n", mux_get_slot());
mcp23017_set_output_a(MCP23017_ADDRESS, (1 << mux_get_slot()));
break;
case 'I':
printf("Releasing card insert (slot=%u)\r\n", mux_get_slot());
mcp23017_set_output_a(MCP23017_ADDRESS, 0);
break;
default:
printf("Unknown command '%c'\n\r", ch);
break;
}
}
void board_main_top(void)
{
#ifndef APPLICATION_dfu
usb_buf_init();
mux_init();
i2c_pin_init();
/* PORT A: all outputs, Port B0 output, B1..B7 unused */
if (mcp23017_init(MCP23017_ADDRESS, 0x00, 0xfe) == 0) {
mcp2317_present = true;
mcp23017_set_output_a(MCP23017_ADDRESS, 0);
}
/* Initialize checking for card insert/remove events */
//card_present_init();
#endif
}
int board_override_enter_dfu(void)
{
const Pin bl_sw_pin = PIN_BOOTLOADER_SW;
PIO_Configure(&bl_sw_pin, 1);
/* Enter DFU bootloader in case the respective button is pressed */
if (PIO_Get(&bl_sw_pin) == 0) {
/* do not print to early since the console is not initialized yet */
//printf("BOOTLOADER switch pressed -> Force DFU\n\r");
return 1;
} else
return 0;
}
void board_set_card_insert(struct cardem_inst *ci, bool card_insert)
{
int s = mux_get_slot();
/* A0 .. A7 of the MCP are each connected to the gate of a FET which closes
* the sim-present signal of the respective slot */
if (mcp2317_present) {
if (card_insert) {
/* we must enable card-presence of the active slot and disable it on all others */
mcp23017_set_output_a(MCP23017_ADDRESS, (1 << s));
} else {
/* we disable all card insert signals */
mcp23017_set_output_a(MCP23017_ADDRESS, 0);
}
} else {
TRACE_WARNING("No MCP23017 present; cannot set CARD_INSERT\r\n");
}
}

View File

@@ -0,0 +1,225 @@
/* I2C EEPROM memory read and write utilities
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include <stdbool.h>
/* Low-Level I2C Routines */
static const Pin pin_sda = {PIO_PA30, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
static const Pin pin_sda_in = {PIO_PA30, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT };
static const Pin pin_scl = {PIO_PA31, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
static void i2c_delay()
{
volatile int v;
int i;
/* 100 cycles results in SCL peak length of 44us, so it's about
* 440ns per cycle here */
for (i = 0; i < 14; i++) {
v = 0;
}
}
void i2c_pin_init(void)
{
PIO_Configure(&pin_scl, PIO_LISTSIZE(pin_scl));
PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
}
static void set_scl(void)
{
PIO_Set(&pin_scl);
i2c_delay();
}
static void set_sda(void)
{
PIO_Set(&pin_sda);
i2c_delay();
}
static void clear_scl(void)
{
PIO_Clear(&pin_scl);
i2c_delay();
}
static void clear_sda(void)
{
PIO_Clear(&pin_sda);
i2c_delay();
}
static bool read_sda(void)
{
bool ret;
PIO_Configure(&pin_sda_in, PIO_LISTSIZE(pin_sda_in));
if (PIO_Get(&pin_sda_in))
ret = true;
else
ret = false;
PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
return ret;
}
/* Core I2C Routines */
static bool i2c_started = false;
static void i2c_start_cond(void)
{
if (i2c_started) {
set_sda();
set_scl();
}
clear_sda();
i2c_delay();
clear_scl();
i2c_started = true;
}
void i2c_stop_cond(void)
{
clear_sda();
set_scl();
set_sda();
i2c_delay();
i2c_started = false;
}
static void i2c_write_bit(bool bit)
{
if (bit)
set_sda();
else
clear_sda();
i2c_delay(); // ?
set_scl();
clear_scl();
}
static bool i2c_read_bit(void)
{
bool bit;
set_sda();
set_scl();
bit = read_sda();
clear_scl();
return bit;
}
bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
{
uint8_t bit;
bool nack;
if (send_start)
i2c_start_cond();
for (bit = 0; bit < 8; bit++) {
i2c_write_bit((byte & 0x80) != 0);
byte <<= 1;
}
nack = i2c_read_bit();
if (send_stop)
i2c_stop_cond();
return nack;
}
uint8_t i2c_read_byte(bool nack, bool send_stop)
{
uint8_t byte = 0;
uint8_t bit;
for (bit = 0; bit < 8; bit++) {
byte = (byte << 1) | i2c_read_bit();
}
i2c_write_bit(nack);
if (send_stop)
i2c_stop_cond();
return byte;
}
/* EEPROM related code */
int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
{
bool nack;
WDT_Restart(WDT);
/* Write slave address */
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, true, byte);
if (nack)
goto out_stop;
/* Wait tWR time to ensure EEPROM is writing correctly (tWR = 5 ms for AT24C02) */
mdelay(5);
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}
int eeprom_read_byte(uint8_t slave, uint8_t addr)
{
bool nack;
WDT_Restart(WDT);
/* dummy write cycle */
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
/* Re-start with read */
nack = i2c_write_byte(true, false, (slave << 1) | 1);
if (nack)
goto out_stop;
return i2c_read_byte(true, true);
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}

View File

@@ -0,0 +1,156 @@
#include "board.h"
#include <stdbool.h>
#include "i2c.h"
#include "mcp23017.h"
//defines from https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h under BSD license
// registers
#define MCP23017_IODIRA 0x00
#define MCP23017_IPOLA 0x02
#define MCP23017_GPINTENA 0x04
#define MCP23017_DEFVALA 0x06
#define MCP23017_INTCONA 0x08
#define MCP23017_IOCONA 0x0A
#define MCP23017_GPPUA 0x0C
#define MCP23017_INTFA 0x0E
#define MCP23017_INTCAPA 0x10
#define MCP23017_GPIOA 0x12
#define MCP23017_OLATA 0x14
#define MCP23017_IODIRB 0x01
#define MCP23017_IPOLB 0x03
#define MCP23017_GPINTENB 0x05
#define MCP23017_DEFVALB 0x07
#define MCP23017_INTCONB 0x09
#define MCP23017_IOCONB 0x0B
#define MCP23017_GPPUB 0x0D
#define MCP23017_INTFB 0x0F
#define MCP23017_INTCAPB 0x11
#define MCP23017_GPIOB 0x13
#define MCP23017_OLATB 0x15
#define MCP23017_INT_ERR 255
//bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
//uint8_t i2c_read_byte(bool nack, bool send_stop)
//static void i2c_stop_cond(void)
int mcp23017_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
{
bool nack;
WDT_Restart(WDT);
// Write slave address
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, true, byte);
if (nack)
goto out_stop;
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}
int mcp23017_read_byte(uint8_t slave, uint8_t addr)
{
bool nack;
WDT_Restart(WDT);
// dummy write cycle
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
// Re-start with read
nack = i2c_write_byte(true, false, (slave << 1) | 1);
if (nack)
goto out_stop;
return i2c_read_byte(true, true);
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}
int mcp23017_init(uint8_t slave, uint8_t iodira, uint8_t iodirb)
{
TRACE_DEBUG("mcp23017_init\n\r");
// all gpio input
if (mcp23017_write_byte(slave, MCP23017_IODIRA, iodira))
goto out_err;
// msb of portb output, rest input
if (mcp23017_write_byte(slave, MCP23017_IODIRB, iodirb))
goto out_err;
if (mcp23017_write_byte(slave, MCP23017_IOCONA, 0x20)) //disable SEQOP (autoinc addressing)
goto out_err;
TRACE_DEBUG("mcp23017 found\n\r");
return 0;
out_err:
TRACE_WARNING("mcp23017 NOT found!\n\r");
return -1;
}
int mcp23017_test(uint8_t slave)
{
printf("mcp23017_test\n\r");
printf("GPIOA 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_GPIOA));
printf("GPIOB 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_GPIOB));
printf("IODIRA 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IODIRA));
printf("IODIRB 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IODIRB));
printf("IOCONA 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IOCONA));
printf("IOCONB 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IOCONB));
return 0;
}
int mcp23017_set_output_a(uint8_t slave, uint8_t val)
{
return mcp23017_write_byte(slave, MCP23017_OLATA, val);
}
int mcp23017_set_output_b(uint8_t slave, uint8_t val)
{
return mcp23017_write_byte(slave, MCP23017_OLATB, val);
}
int mcp23017_toggle(uint8_t slave)
{
// example writing MSB of gpio
static bool foo=false;
if (foo)
{
printf("+\n\r");
mcp23017_write_byte(slave, MCP23017_OLATB, 0x80);
foo=false;
}
else
{
printf("-\n\r");
mcp23017_write_byte(slave, MCP23017_OLATB, 0x00);
foo=true;
}
return 0;
}

View File

@@ -0,0 +1,113 @@
/* sysmoOCTSIMTEST support for multiplexers
*
* (C) 2021 by Harald Welte <laforge@gnumonks.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "mux.h"
#include <stdbool.h>
#include <errno.h>
/* 3-bit S0..S2 signal for slot selection */
static const Pin pin_in_sel[3] = {
{ PIO_PA1, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
{ PIO_PA2, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
{ PIO_PA3, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
};
/* 3-bit S0..S2 signal for frequency divider selection */
static const Pin pin_freq_sel[3] = {
{ PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
{ PIO_PA17, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
{ PIO_PA18, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
};
/* low-active output enable for all muxes */
static const Pin pin_oe = { PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT };
static uint8_t g_mux_slot = 0;
/* initialize the external 1:8 multiplexers */
void mux_init(void)
{
PIO_Configure(&pin_oe, PIO_LISTSIZE(pin_oe));
PIO_Configure(pin_in_sel, PIO_LISTSIZE(pin_in_sel));
PIO_Configure(pin_freq_sel, PIO_LISTSIZE(pin_freq_sel));
mux_set_slot(0);
}
/* set the slot selection mux */
int mux_set_slot(uint8_t s)
{
TRACE_INFO("%s(%u)\r\n", __func__, s);
if (s > 7)
return -EINVAL;
/* !OE = H: disconnect input and output of muxes */
PIO_Set(&pin_oe);
if (s & 1)
PIO_Set(&pin_in_sel[0]);
else
PIO_Clear(&pin_in_sel[0]);
if (s & 2)
PIO_Set(&pin_in_sel[1]);
else
PIO_Clear(&pin_in_sel[1]);
if (s & 4)
PIO_Set(&pin_in_sel[2]);
else
PIO_Clear(&pin_in_sel[2]);
/* !OE = L: (re-)enable the output of muxes */
PIO_Clear(&pin_oe);
g_mux_slot = s;
return s;
}
int mux_get_slot(void)
{
return g_mux_slot;
}
/* set the frequency divider mux */
void mux_set_freq(uint8_t s)
{
TRACE_INFO("%s(%u)\r\n", __func__, s);
/* no need for 'break before make' here, this would also affect
* the SIM card I/O signals which we don't want to disturb */
if (s & 1)
PIO_Set(&pin_freq_sel[0]);
else
PIO_Clear(&pin_freq_sel[0]);
if (s & 2)
PIO_Set(&pin_freq_sel[1]);
else
PIO_Clear(&pin_freq_sel[1]);
if (s & 4)
PIO_Set(&pin_freq_sel[2]);
else
PIO_Clear(&pin_freq_sel[2]);
/* !OE = L: ensure enable the output of muxes */
PIO_Clear(&pin_oe);
}

View File

@@ -0,0 +1,37 @@
/* Code to switch between local (physical) and remote (emulated) SIM
*
* (C) 2021 by Harald Welte <hwelte@hmw-consulting.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "trace.h"
#include "sim_switch.h"
int sim_switch_use_physical(unsigned int nr, int physical)
{
if (physical) {
TRACE_ERROR("%u: Use local/physical SIM - UNSUPPORTED!\r\n", nr);
} else {
TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
}
return 0;
}
int sim_switch_init(void)
{
return 1; // SIMtrace hardware has only one switchable interface
}

View File

@@ -1,12 +1,53 @@
/* OWHW board definition
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once #pragma once
#include "board_common.h" #include "board_common.h"
#include "simtrace_usb.h"
/** Name of the board */ /** Name of the board */
#define BOARD_NAME "OWHW" #define BOARD_NAME "OWHW"
/** Board definition */ /** Board definition */
#define owhw #define owhw
/** oscillator used as main clock source (in Hz) */
#define BOARD_MAINOSC 18432000 #define BOARD_MAINOSC 18432000
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58982400 // 18.432 * 16 / 5
/** MCU pin connected to red LED */
#define PIO_LED_RED PIO_PA17
/** MCU pin connected to green LED */
#define PIO_LED_GREEN PIO_PA18
/** red LED pin definition */
#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** green LED pin definition */
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LEDs pin definition */
#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
/** index for red LED in LEDs pin definition array */
#define LED_NUM_RED 0
/** index for green LED in LEDs pin definition array */
#define LED_NUM_GREEN 1
/* pin connected to the SIMTRACE_BOOTLOADER signal. set high to force DFU bootloader start */
#define PIN_BOOTLOADER {PIO_PA31, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
/* USIM 2 interface (USART) */ /* USIM 2 interface (USART) */
#define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} #define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}

View File

@@ -0,0 +1 @@
OWHW

Some files were not shown because too many files have changed in this diff Show More