383 Commits

Author SHA1 Message Date
Kévin Redon
f48aac560c sniffing: decrease USB IRQ prioprity to prevent USART overrun
Change-Id: I870a0aa8e251bbb53249c54bfcaa45de5b5a9486

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.
2018-07-03 16:18:00 +02:00
Kévin Redon
d28d3fc4c0 sniffing: fix procedure byte handling and make TPDU parsing for strict
Change-Id: If991152f11c4b864ab1386f21dc13c335e6b281f
2018-07-03 16:17:00 +02:00
Kévin Redon
50d071fb0e sniffer: also send incomplete (e.g. timeout) data (PPS/ATR/TPDU)
Change-Id: Ib070aca181042b477f1ffec48d63dc56c1e4609a
2018-07-03 16:15:58 +02:00
Kévin Redon
36be182ea2 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-03 16:10:04 +02:00
Kévin Redon
bdb0795e61 buffer: increase buffer size to 512 to cope with fast and long TPDUs
Change-Id: I194c90cf09306a982d80c5bf1222397af6e658a9
2018-07-03 16:03:17 +02:00
Kévin Redon
b65e4b6823 console: drop data to be send when buffer is already full
Change-Id: Ia625b09eb30bb7b43edd3989f697d8ef33200f28

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
2018-07-03 15:59:57 +02:00
Kévin Redon
05cc8bd36a sniffer: display F and D values frim PPS
Change-Id: I3641dcb6c24695a6d3dd3a1ee4333f56a07c99f0
2018-07-03 15:57:03 +02:00
Kévin Redon
de6e3488a0 Merge branch 'kredon/simtrace' of ssh://gerrit.osmocom.org:29418/simtrace2 into kredon/simtrace
Change-Id: Id868520d6603f2bcb79a0aaaf6413dc83938524b
2018-07-01 19:02:40 +02:00
Kévin Redon
f6c2f4def3 host USB: add host application to receive and display USB sniffing messages sent by firmware
Change-Id: Idefbf21e0bbd2a1e3647fe9aebaf88d1b62dae2d
2018-07-01 18:33:28 +02:00
Kévin Redon
f9f1261c18 sniffer USB: implement USB communication and send parsed messages
Change-Id: Ice7817480705f2124b08c1ff9a8826558b6d8b2b
2018-07-01 18:33:28 +02:00
Kévin Redon
310ad81bad USB device: add USB message structure for sniffer communication
Change-Id: Id2c6f32ade2fec9b9ef91bd8c5e1fd195f2d7351
2018-07-01 18:33:28 +02:00
Kévin Redon
1c84e5e312 host USB: use central SIMtrace USB ID definition header
Change-Id: Id18e64fba0a2c308a8aef7d3865200bf0237cae9
2018-07-01 18:33:28 +02:00
Kévin Redon
c06b1d6f7c host usb_util fix: used provided class, sub-class, and interfave when finding matching interfaces
Change-Id: Ibc06e751e6ca0f9e9a40d82c4eeddfb975240f91
2018-07-01 18:33:28 +02:00
Kévin Redon
0c9079f1ae USB: add central file to define USB IDs, classes, and endpoints
Change-Id: Iba81f32a92c68a973e8e7adbc4c2a1064ba5290f
2018-07-01 18:33:28 +02:00
Kévin Redon
cb700ef087 reintroduce adc2uv used in boardver_adc.c and mode_cardemu.c
Change-Id: I52e3919adfd1d888eb130b5ec9298315c4e507c9
2018-07-01 18:33:28 +02:00
Kévin Redon
4635c71c06 minor: fix typos in comment
Change-Id: I01b49e047a586dff449d4e134751108e391a8822
2018-07-01 18:33:28 +02:00
Kévin Redon
6123460055 sniff: add WT timeout detection using USART timeout (TC is not required)
Change-Id: I4ec6e812e7e1eb91005027d2e864fc315550d79c
2018-07-01 18:33:28 +02:00
Kévin Redon
15a3384e9a sniff: add TPDU parsing (TPDUs become APDUs on the upper layer)
Change-Id: I09d050d95bd2ab140fe6b4926a37278eb08cc347
2018-07-01 18:33:28 +02:00
Kévin Redon
f40c10d2f2 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-01 18:33:28 +02:00
Kévin Redon
8fd88b8a59 LED: add short LED pulse blinking pattern
Change-Id: I0fdc2f902a3b92da6aa9b9c8500abae8a2f79447
2018-07-01 18:33:28 +02:00
Kévin Redon
10553e7f0c update_fidi: remove debug output since this function is called in time critical ISR
Change-Id: I08f407d407a18dae3f360ddc64769ddfaeb5b559
2018-07-01 18:33:28 +02:00
Kévin Redon
833a540efa DFU: switch green LED on to indicate DFU mode, and red LED to indicate flashing activity
Change-Id: I8e34fd869ed94ad122d6a17f5a432f5a09b820bb
2018-07-01 18:33:28 +02:00
Kévin Redon
23d7306ef0 board: fix LED pin definition
Change-Id: Ia6c80c0268dec708845e1dad281caaa42027f9db
2018-07-01 18:33:28 +02:00
Kévin Redon
4646e04d1f DFU: remove force bootloader button debug message since the console is output message is not initialized yet
Change-Id: Ibea0105929a8dc38b43dacd9d1e576d7b51d0c6a
2018-07-01 18:33:28 +02:00
Kévin Redon
216a2149e1 sniffer: use ISR to store sniffed data in buffer, add ATR and PPS parsing, and PPS related FiDi update 2018-07-01 18:33:28 +02:00
Kévin Redon
13f720b650 trace: increase watchdog for 500 to 2000 ms to provide more time handling buffered data 2018-07-01 18:33:28 +02:00
Kévin Redon
ae1ce57d4c ISO7816: change update_fidi to use provided USART, and disable write protection for USART register if required 2018-07-01 18:33:28 +02:00
Kévin Redon
5dce338c6b SIMtrace: enable interrupt on edge dection for SIM_RST pin to reset the sniffer ISO state 2018-07-01 18:33:28 +02:00
Kévin Redon
ad6e7eff00 SIMtrace: fix default SIM_RST pin state to allow phone controlled reset 2018-07-01 18:33:28 +02:00
Kévin Redon
5b63e437bc SIMtrace: only enable main sniffing mode on SIMtrace board 2018-07-01 18:33:28 +02:00
Kévin Redon
915f1636b0 sniffer: add state definitions, improve IRQ handling, update pins configuration 2018-07-01 18:33:28 +02:00
Kévin Redon
04a63b386e simtrace: add support for sniffing on both USART 2018-07-01 18:33:28 +02:00
Kévin Redon
b88c73bcfd board: comment USART definitions and add corresponding IRQ numbers 2018-07-01 18:33:28 +02:00
Kévin Redon
1225e41aad simtrace: add dedicated power pins configuration for sniffing 2018-07-01 18:33:28 +02:00
Kévin Redon
7ddf46ce1c 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.
2018-07-01 18:33:28 +02:00
Kévin Redon
5a7c848b43 SIMtrace board: comment and fix pin definition 2018-07-01 18:33:28 +02:00
Kévin Redon
aa70887ce0 sniff mode: handle USART 1 RX interrupt to show sniffer data 2018-07-01 18:33:28 +02:00
Kévin Redon
baff8d2c22 add more USB configuration checks and error messages 2018-07-01 18:33:28 +02:00
Kévin Redon
7bcbae3ad9 enable (empty) sniffer support for SIMtrace board 2018-07-01 18:33:28 +02:00
Kévin Redon
33d62aa17a 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.
2018-07-01 18:33:28 +02:00
Kévin Redon
e4cd52c2e3 fix: remove unused code
adc2uv is not used in boardver_adc.c.
a FIXME comment says it should be shared with mode_cardemu.c.
the exact same code is already available in mode_cardemu.c
2018-07-01 18:33:28 +02:00
Harald Welte
cb6e20596e contrib/jenkins.sh: Also run firmware tests + build-test host software
Change-Id: Ie53857164d0a21daac334057c5bafbfd9912bf4b
2018-07-01 16:33:25 +02:00
Harald Welte
bb2eb19fb1 firmware/test: Add more include paths
Change-Id: I4287fbae6921ed0605265812df5d7243e8857864
2018-07-01 08:47:39 +02:00
Harald Welte
9d90d284ed Use system include <foo.h> notation for libosmocore headers
the curent local copies of libosmocore headers + source is a temporary
hack anyway. We should instead rely on a system-wide install of
libosmocore cross-compiled for arm-none-eabi.  But leave that as a
second (later) step beyond this patch.

Change-Id: Ia63fd842d45a2b404233b4326050e7eda0604cf0
2018-06-29 22:26:57 +02:00
Harald Welte
ebe8b2069c Makefile: fix automatic creation of obj directory
since we're using obj/$BOARD, we must use "-p" to create the directory
recursively
2018-06-29 21:44:12 +02:00
Harald Welte
105c1dce4f add contrib/jenkins.sh for build verification
The contrib/jenkins.sh script will build all supported apps for all
supported builds.  It will be used by jenkins/gerrit build testing.
2018-06-29 21:39:42 +02:00
Harald Welte
1cfc2614dd apps/dfu/main.c: Avoid variable declaration in for loop initial
This fixes the following compile error:

apps/dfu/main.c:73:3: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
   for (unsigned int i=0; i<len; i++) {
   ^
apps/dfu/main.c:73:3: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code

which was recently introduced in b73f0a00bc
2018-06-29 21:07:41 +02:00
Kévin Redon
a9bca48914 ring buffer: increase buffer size from 128 to 256 to cope with large debug output 2018-06-29 20:07:31 +02:00
Kévin Redon
eac1bec428 console: use buffer and interrupts instead of busy loops for UART debug output 2018-06-29 20:07:31 +02:00
Kévin Redon
51c128bc35 DFU: fix typo in USB strings 2018-06-29 20:07:31 +02:00
Kévin Redon
869dbfafe4 DFU: incread watchdog timeout and restart watchdog before writing in flash to prevent the watchdog to trigger while flashing 2018-06-29 20:07:31 +02:00
Kévin Redon
80303c135b DFU: only boot the application if it has a valid start 2018-06-29 20:07:31 +02:00
Kévin Redon
d86cab0080 DFU: uncomment print message when DFU is forced using the button 2018-06-29 20:07:31 +02:00
Kévin Redon
b73f0a00bc DFU: unlock the flash before writing, verify written data, and relock it 2018-06-29 20:07:31 +02:00
Kévin Redon
f5869d4a59 USB: implement USB reset by setting the on-board pull-up on D+ low 2018-06-29 20:07:31 +02:00
Kévin Redon
4136c242a8 USBD: send empty packet when non-existing descriptor string is requested
Sometimes descriptor string 0xee is requested.
This is a mechanism used by Microsoft Windows to further identify the USB device.
Instead of stalling, as is the original code, leading to an USB reset, we send an empty packet.
I am not sure if sending an empty string would be better, but an empty packet seems sufficient.
2018-06-29 20:07:31 +02:00
Kévin Redon
318309f30f dfu: fix address destination check and add stack overwrite check in USBDFU_handle_dnload
During DFU download the destination start address is checked to not exceed the
RAM or flash end address, but it is also necessary to check if the end of the
data to be downloaded is also within the allowed range.
When downloading to RAM it is also necessary to check if the data to be
downloaded does not overwrite (i.e. corrupt) the stack.
2018-06-29 20:07:31 +02:00
Kévin Redon
0828b914e7 README: rewrite to better explain environment variables and point to the wiki for flashing 2018-06-29 20:07:31 +02:00
Kévin Redon
76be7c806e fix pointer casting warning
fixes following warning:
libboard/common/source/board_cstartup_gnu.c:137:11: warning: assignment to 'void (*)(void)' from 'unsigned int' makes pointer from integer without a cast [-Wint-conversion]
  appReset = pSrc[1];
2018-06-29 20:07:31 +02:00
Kévin Redon
a38a126361 fix: initialize uninitialized variable in USBDFU_DFU_RequestHandler 2018-06-29 20:07:31 +02:00
Kévin Redon
a484b02271 sniffer: use ISR to store sniffed data in buffer, add ATR and PPS parsing, and PPS related FiDi update 2018-06-25 16:00:33 +02:00
Kévin Redon
8643420daa trace: increase watchdog for 500 to 2000 ms to provide more time handling buffered data 2018-06-25 15:57:44 +02:00
Kévin Redon
0aafbac7eb ring buffer: increase buffer size from 128 to 256 to cope with large debug output 2018-06-25 15:56:33 +02:00
Kévin Redon
67e181fb15 console: use buffer and interrupts instead of busy loops for UART debug output 2018-06-25 15:55:33 +02:00
Kévin Redon
2bac56494f ISO7816: change update_fidi to use provided USART, and disable write protection for USART register if required 2018-06-25 15:53:19 +02:00
Kévin Redon
f908f659fc SIMtrace: enable interrupt on edge dection for SIM_RST pin to reset the sniffer ISO state 2018-06-25 15:49:28 +02:00
Kévin Redon
42af4949a7 SIMtrace: fix default SIM_RST pin state to allow phone controlled reset 2018-06-24 11:31:36 +02:00
Kévin Redon
4814b15bbf SIMtrace: only enable main sniffing mode on SIMtrace board 2018-06-24 11:30:31 +02:00
Kévin Redon
78a8ab71e1 DFU: fix typo in USB strings 2018-06-24 11:27:09 +02:00
Kévin Redon
6b38297e20 DFU: incread watchdog timeout and restart watchdog before writing in flash to prevent the watchdog to trigger while flashing 2018-06-17 22:36:44 +02:00
Kévin Redon
3f8a4c28e8 DFU: only boot the application if it has a valid start 2018-06-17 22:35:17 +02:00
Kévin Redon
41d01b9d54 DFU: uncomment print message when DFU is forced using the button 2018-06-17 22:34:47 +02:00
Kévin Redon
88b2b077ef DFU: unlock the flash before writing, verify written data, and relock it 2018-06-17 22:33:29 +02:00
Kévin Redon
9a921ac630 USB: implement USB reset by setting the on-board pull-up on D+ low 2018-06-17 22:31:21 +02:00
Kévin Redon
2ab8f8e3fd sniffer: add state definitions, improve IRQ handling, update pins configuration 2018-06-11 13:46:35 +02:00
Kévin Redon
a34471d923 simtrace: add support for sniffing on both USART 2018-06-11 13:45:16 +02:00
Kévin Redon
762276e271 board: comment USART definitions and add corresponding IRQ numbers 2018-06-11 13:43:27 +02:00
Kévin Redon
2d972f5910 simtrace: add dedicated power pins configuration for sniffing 2018-06-11 13:42:23 +02:00
Kévin Redon
d0b4a9da81 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.
2018-06-07 18:56:47 +02:00
Kévin Redon
7f4f8983dd USBD: send empty packet when non-existing descriptor string is requested
Sometimes descriptor string 0xee is requested.
This is a mechanism used by Microsoft Windows to further identify the USB device.
Instead of stalling, as is the original code, leading to an USB reset, we send an empty packet.
I am not sure if sending an empty string would be better, but an empty packet seems sufficient.
2018-06-06 17:03:24 +02:00
Kévin Redon
86ea4faef6 SIMtrace board: comment and fix pin definition 2018-06-06 17:02:33 +02:00
Kévin Redon
a1f198276d sniff mode: handle USART 1 RX interrupt to show sniffer data 2018-06-06 16:13:48 +02:00
Kévin Redon
b53ab5b4ef add more USB configuration checks and error messages 2018-06-04 16:30:48 +02:00
Kévin Redon
38a467e630 enable (empty) sniffer support for SIMtrace board 2018-06-04 16:30:01 +02:00
Kévin Redon
7b51f72e83 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.
2018-06-04 16:21:34 +02:00
Kévin Redon
f79ae1c54a dfu: fix address destination check and add stack overwrite check in USBDFU_handle_dnload
During DFU download the destination start address is checked to not exceed the
RAM or flash end address, but it is also necessary to check if the end of the
data to be downloaded is also within the allowed range.
When downloading to RAM it is also necessary to check if the data to be
downloaded does not overwrite (i.e. corrupt) the stack.
2018-06-01 11:02:56 +02:00
Kévin Redon
de2d03ca22 README: rewrite to better explain environment variables and point to the wiki for flashing 2018-05-21 19:35:56 +02:00
Kévin Redon
fe72bf11fd fix pointer casting warning
fixes following warning:
libboard/common/source/board_cstartup_gnu.c:137:11: warning: assignment to 'void (*)(void)' from 'unsigned int' makes pointer from integer without a cast [-Wint-conversion]
  appReset = pSrc[1];
2018-05-21 19:34:01 +02:00
Kévin Redon
0471d2a390 fix: initialize uninitialized variable in USBDFU_DFU_RequestHandler 2018-05-21 18:52:06 +02:00
Kévin Redon
5be1b612f7 fix: remove unused code
adc2uv is not used in boardver_adc.c.
a FIXME comment says it should be shared with mode_cardemu.c.
the exact same code is already available in mode_cardemu.c
2018-05-21 17:51:34 +02:00
Kévin Redon
6822716428 add printf attribute declaration to remove warning
the __attribute__ ((format (printf, 1, 0))) declaration remove the following
compilation warning:
warning: function 'osmo_panic' might be a candidate for 'gnu_printf' format
 attribute [-Wsuggest-attribute=format]
   osmo_panic_default(fmt, args);
2018-05-21 17:18:58 +02:00
Kévin Redon
a93f7273b3 fix: remove duplicate volatile declaration 2018-05-21 17:17:20 +02:00
Kévin Redon
432ba5140e add copyright notice
The original board startup script is provided by Atmel.
It has been modified to handle application or DFU booting.
The copyright notice has been updated to reflect this change.
2018-05-21 17:13:50 +02:00
Harald Welte
849d20e29e Add firmware/TODO.txt that was not committed so far 2018-05-11 15:49:31 +02:00
Harald Welte
e48d6f2321 Add README.md 2018-05-11 15:48:54 +02:00
Harald Welte
af616ec4e2 CCID driver: Use USBD_GetDriver() instead of non-initialized state variable 2017-11-29 00:45:23 +01:00
Harald Welte
6051e126da CCID: re-enable control request handler for CCID class requests 2017-11-29 00:26:34 +01:00
Harald Welte
7f62c24532 USB: Handle DFU requests by USBD.c to keep application callback
e.g. in CCID mode we need to treat class-specific control requests,
and we want to do this in a way how the CCID code doesn't need to
understand about DFU.
2017-11-29 00:24:28 +01:00
Harald Welte
75cf93e04d rename ccid.c to mode_ccid.c to align with mode_cardemu.c 2017-11-28 23:00:40 +01:00
Harald Welte
2afd57f00a cardem: Don't dispatch UART IRQs to possible NULL pointers
A given configuration might not expose callback functions for
the UART interrupts.
2017-11-28 22:52:56 +01:00
Harald Welte
0633b25974 iso7816_4: Re-trigger watchdog while waiting for character 2017-11-28 22:47:09 +01:00
Harald Welte
c1e2254854 simtrace: Boot into DFU when BOOTLOADER button is pressed
This recovers the old functionality of the SAM7 based OpenPCD firmware.
2017-11-28 22:29:53 +01:00
Harald Welte
27f5fc681c DFU: Move "Override DFU" (force DFU) code to board-specific section
Each board can define its own conditions on which the controller should
boot into DFU mode rather than normal application mode.  Let's move the
"UART loopback jumper" to QMOD specific part.  For SIMtrace we have an
actual button and can use that in a future patch.
2017-11-28 22:15:56 +01:00
Harald Welte
7b250bfc8d board_simtrace: Add minimal debug menu on debug USART 2017-11-28 22:10:49 +01:00
Harald Welte
ed75c62acf {ccid,sniffer}.c: Add comments on USB callbacks 2017-11-28 21:23:12 +01:00
Harald Welte
5c081911a9 remove dead code (source/phone.c), superseded by card_emu.c/mode_cardemu.c 2017-11-28 21:21:50 +01:00
Harald Welte
5e6e8dcbde Make build of CCID code succeed again on BOARD=simtrace 2017-11-28 20:58:06 +01:00
Harald Welte
c35998e20d Makefile: Disable -Wundef and -Wsign-compare for now
This silences tons of warnings which are making it hard to identify
actual issues when looking at the compiler output.
2017-11-28 20:47:23 +01:00
Harald Welte
ba2ad563cc fix build of APP=cardem on BOARD=simtrace 2017-11-28 19:49:41 +01:00
Harald Welte
fc87c24326 mode_cardem: Build on platforms without WWAN_PERST suppotrt 2017-11-28 19:17:27 +01:00
Harald Welte
f231541601 Fix typos in usb.c, llist_irqsafe.h and dfu.h 2017-11-28 19:16:57 +01:00
Harald Welte
119624f46f WIP: use local_irq_{save,restore}() 2017-11-04 12:28:30 +01:00
Harald Welte
7b36306113 [firmware] WIP: make talloc irq-safe 2017-11-04 12:17:09 +01:00
Harald Welte
eb50c9f914 [firmware] sim_switch + wwan_perst: Don't re-initialize
The logic to detect if the respective module is already initialized
or not was broken.  When performing initialization, we of course need
to set initialized=1.
2017-11-03 20:52:35 +01:00
Harald Welte
965d5c918a [firmware] cardemu: Skip CARD_INSERT if board doesn't support it 2017-11-03 20:48:11 +01:00
Harald Welte
514c6d1da0 [firmware] wwan_perst: Print index when releasing WWAN_PERST 2017-11-03 20:40:56 +01:00
Harald Welte
e7f2f9a5e0 [firmware] wwam_led: use 0/1 instead of 1/2
most (all) other code modules have already moved over to
consistently using a 0-based index.
2017-11-03 20:38:31 +01:00
Harald Welte
4e837d45db [firmware] card_pres: use modem number at start of line
... like most other code modules, too
2017-11-03 20:36:17 +01:00
Harald Welte
b52b886186 [firmware] card_pres: Use 0/1 index number instead of 1/2
We have moved most (all?) other code to work with slots 0/1
rather than 1/2.
2017-11-03 20:33:10 +01:00
Harald Welte
c47fc5febf set local slot LED according to remote/local state.
The LED is illuminated as long as the slot is in local (physical SIM
card) mode.
2017-05-20 14:46:57 +01:00
Harald Welte
02d0ec6e08 uart_console: Re-start watchdog during busy-waiting for serial chars 2017-05-20 14:46:57 +01:00
Harald Welte
3b646955b9 Fix swapped manufacturer/product strings
the */usb_strings.txt files always assumed that the first line is the
manufacturer string, followed by the product string in the second line.

However, the enum strDescNum had it the other way around. Let's fix it
by adjusting the enum to reality.

Fixes: SYS#3591
2017-05-14 23:15:11 +02:00
Harald Welte
a601635885 host: Allow matching of device to USB path, not just address
USB addresses change every time the device re-enumerates, while the path
reflects the physical topology of USB connections and stays persistent
unless the usb cabling is changed.  Let's allow the user to specify the
path instead of the address to uniquely identify a given slot.
2017-05-11 01:31:45 +02:00
Harald Welte
37ad41e092 host: Ignore some more libusb error return codes
It seems that sometimes we get even an LIBUSB_ERROR_IO and failing on
errors breaks the application, while ignoring it works.  Not sure why
that really is, but for now it increases reliability.
2017-05-11 01:13:58 +02:00
Harald Welte
66de830f55 host: Switch SIM to remote and issue modem reset on startup
as soon as simtrace2-remotesim is started, we issue the command to
instruct the use of the remote SIM card and ask the modem to reset
itself (to start using the new remote sim).
2017-05-11 01:13:04 +02:00
Harald Welte
23c00b6ad3 cardemu: Fix interpretation of MSGC_MODEM messages
msg->l2h should always point at the first byte of the header after the
generic simtrace header.  For some reason this doesn't work if used
globally, but it is required for the MSGC_MODEM messages to be
interpreted correctly.
2017-05-11 01:11:43 +02:00
Harald Welte
253991789a dfu: make sure to not bloat the loader with main board init stuff. 2017-05-11 00:47:29 +02:00
Harald Welte
0709d2d842 perst/sim_switch: Log events using TRACE_INFO 2017-05-11 00:06:00 +02:00
Harald Welte
44622dfd8d consistently use 0-based counting of modems/slots 2017-05-11 00:04:50 +02:00
Harald Welte
b91f6ad848 firmware: fix various compiler warnings 2017-05-10 23:20:50 +02:00
Harald Welte
9f38dddfcc host: fix various compiler warnings 2017-05-10 23:20:50 +02:00
Harald Welte
d03960525e host: Split transport from slot
In current implementations, we have one interface (with it's own
separate set of USB end-points) per slot.  However, the USB protocol
already includes a slot-number in the header to be able to remove that
restriction in future versions.

Also, if the USB protocol is used remotely over a network, then we could
multiplex differnt slots from different USB interfaces into one stream
on the network side.

In order to prepare the data structures in the host program, let's
introduce that logical split there, too.  Might seem a bit like
overkill, but I don't want to rewrite all code later...
2017-05-10 23:20:46 +02:00
Harald Welte
08b77ba9ee host: split the transport layer from card emulation
We want to be able to use some code irrespective of the application
(emulation, tracing, ...), so let's split the transport struct out of
the cardem_instance.
2017-05-09 15:11:53 +02:00
Harald Welte
296c401275 host: cosmetic cleanup, function renaming 2017-05-09 15:02:52 +02:00
Harald Welte
5c583d3535 Generalize SIM switching code and allow local/remote switching via USB 2017-05-09 13:24:28 +02:00
Harald Welte
114e74d322 wwan_perst: Warn if somebody failed to initialize us 2017-05-09 13:24:28 +02:00
Harald Welte
2e9254ac3f cardem: Implement WWAN Modem reset via USB
Using the SIMTRACE_MSGT_DT_MODEM_RESET message
2017-05-09 13:24:28 +02:00
Harald Welte
cb093ce878 wwan_perst: Support varying timeout and permanent active/inactive 2017-05-09 13:24:28 +02:00
Harald Welte
25a9a80ff5 Convert to new generalized SIMTRACE2 USB protocol
The current protocol was card-emulation specific.  The new protocol is
generic/flexible enough to accommodate both tracing and card emulation,
as well as modem control and other future extensions.
2017-05-09 13:24:23 +02:00
Harald Welte
ed1efc5035 qmod: debug_cmd: Avoid 'Unknown command' for valid commands 2017-05-07 23:10:02 +02:00
Harald Welte
f8c83a4d64 Make hardfault handler a bit more verbose 2017-05-07 23:10:02 +02:00
Harald Welte
28174982b6 qmod: Initialize ST12 specific I/O pins only on ST12 2017-05-07 23:10:02 +02:00
Harald Welte
8e7fca3255 migrate from req_ctx to msgb
We now generalize the USB communiction and abandon the 'req_ctx'
structure inherited from openpcd.  Instead we use the libosmocore 'msgb'
structure to handle incoming and outgoing USB tranfers.  We also use
linuxlist-based msgb-queues for each endpoint.
2017-05-07 23:09:56 +02:00
Harald Welte
eb81d23a56 import libosmocore msgb handling (and dependencies)
This is supposed to be replaced with upstream libosmocore, as soon as
that has a proper maintained embedded build (again).
2017-05-07 13:18:36 +02:00
Harald Welte
0380d74405 Makefile: remove .p files during 'make clean' 2017-05-07 11:20:40 +02:00
Harald Welte
9457bf765d Makefile: Don't warn about failed inlines 2017-05-07 11:20:24 +02:00
Harald Welte
9ac794c770 Add llist_add_irqsafe() similar to llist_add_tail_irqsafe() 2017-05-07 11:19:45 +02:00
Harald Welte
41eb98b78d board_gpio.gnumeric: Update to QMOD v3 (SIMPRES1/SIMPRES2) 2017-05-05 23:17:31 +02:00
Harald Welte
caca0b1e7a Makefile: Add new 'combined' target to build combined DFU+APP image 2017-05-05 23:17:31 +02:00
Harald Welte
6d1128e9d1 QMOD: Add code to determine SIM Card presence 2017-05-05 23:17:27 +02:00
Harald Welte
7e4390f181 qmod: wwan_led.c: Fix handling of LED for second Modem 2017-05-05 20:58:53 +02:00
Harald Welte
9164a6d335 qmod: Disable various console commands on ST34
A number of commands related to the USB hub and the EEPROM are only
available on ST12, but not on ST34.  Let's remove them if not
applicable.
2017-05-05 20:58:52 +02:00
Harald Welte
2cbc9b29f3 use same USB Product ID for DFU and runtime mode
This was introduced for interoperability with operating systems that
might prefer such setup (I heard that Windows prefers this about a
decade ago, but I don't have any personal experience with it).

However, using different VID/PID between DFU and RT breaks usability of
dfu-util, and I really think this matters much more to our users and
developers.
2017-05-05 00:34:28 +02:00
Harald Welte
8196e4d1be remove old python userspace code
the USB protocol is changing fundamentally anyway, and APDU handling for
card emulation is inside the device, so the old code is incompatible
anyway.
2017-03-08 15:34:23 +01:00
Harald Welte
601e0d3e35 update + split README into general and firmware-specific part 2017-03-08 15:33:33 +01:00
Harald Welte
3d4869cbb4 add missing usbstring.c 2017-03-07 15:51:49 +01:00
Harald Welte
353330dcc7 qmod: Fix polarity of SPDT switch
the default boot state should be to use the local SIM, until the user
changes it (currently only possible via entering '!' or '@' on the
serial console).  The code so far had this completely inverted.
2017-03-07 08:17:19 +01:00
Harald Welte
3bbaba0090 DFU: Disable LED blinking code
Something odd is happening that breaks DFU mode if we blink.  Let's
remove this feature for now.
2017-03-06 22:47:06 +01:00
Harald Welte
e8869fb8ff DFU: Resolve DFU runtime descriptor dynamically from descriptors
We cannoy simply use the DFU runtime descriptor of the DFU mode, but we
have to use the descriptor of the specific currently-selected runtime
configuration.  Let's iterate over the descriptors of a configuration
and find the DFU runtime descriptor in it.
2017-03-06 22:44:42 +01:00
Harald Welte
5b108d8cf0 DFU: initialize g_dfu during real power up
At power-up we need to initialize g_dfu once, to ensure a consistent
state.  Afterwards we want to keep it across (software) reset, but on
power-up the memory would otherwise be filled with random data, causing
issues with detection of DFU/Runtime switching.
2017-03-06 21:51:55 +01:00
Harald Welte
96065cacd7 add simtrace2-list to .gitignore 2017-03-06 21:05:44 +01:00
Harald Welte
1892fc1d7c add udev rules for all (currently) supported devices 2017-03-06 21:03:41 +01:00
Harald Welte
822d66ef69 simtrace2-remsim: Improve support for many interfaces + devices
Rather than using the first available interface on the first available
device, we now have a "simtrace2-list" program that lists all compatible
interfaces on all configurations of all devices on the system
2017-03-06 21:03:31 +01:00
Harald Welte
62bfd8a7a9 simtrace2-remsim: Document and add longopts for UDP forwarding 2017-03-06 20:56:14 +01:00
Harald Welte
b170ea90d3 host: fix some compiler warnings (now that we have -Wall) 2017-03-06 18:59:41 +01:00
Harald Welte
dea64cb746 host: Add "-Wall -g" CFLAGS to get compiler warnings 2017-03-06 18:57:08 +01:00
Harald Welte
2ba03bb9fc simtrace2-remsim: Move away from global variables
When we want to run multiple instances of the card-emulator (e.g. for
multi-modem/multi-card versions of the hardware), the code shouldn't be
using any global variables but have them per-instance.
2017-03-06 18:57:01 +01:00
Harald Welte
abba8a8d85 LED: Introduce LED blinking pattern code
It might be useful to display some different blinking patterns to
indicate specific system state (such as DFU mode vs. regular firmware)
2017-03-06 16:58:00 +01:00
Harald Welte
054216d94d usb: Use different SubClass values for card-emulation and sniffer
This way, host code can dynamically detect which interface supports
which functionality.

The related #defines should be moved to a header file that's shared with
the host application code.
2017-03-06 10:07:17 +01:00
Harald Welte
eab7e456fe USB: Don't specify Class/Subclass 0xff at device level
Actually, at device level we want to specify 0, so we can select
individual Class/Subclass values at Interface values.

Table 9-8 of the USB2 Specification is quite clear about this.
2017-03-06 10:04:56 +01:00
Harald Welte
495a67da7d usb: consistently use named structure initializers 2017-03-06 09:55:37 +01:00
Harald Welte
912b183b29 qmod: Use different Interface Strings for Modem1+2 / Modem 3+4
This makes it obvious in 'lsusb' and to other software on the USB host
which interface is for which of the modems.
2017-03-06 09:28:13 +01:00
Harald Welte
809e5840f9 qmod: Add code to switch between physical and virtual SIM 2017-03-06 09:16:40 +01:00
Harald Welte
0a8306ec69 add gnumeric spreadsheet with GPIO/Pin assignments of all boards
This software is supposed to support a SIMTRACE1 with SAM#, as well
ast the OWHW and QMOD hardware.  Let's compare the GPIO/Pin assignments
of the SAM3 in one shared spreadsheet.
2017-03-05 22:17:28 +01:00
Harald Welte
2bff7cd9c2 tc_etu: Don't confiugre unused TIOA pin of TC0 + TC2
When initializing the TC blocks, let's only configure the GPIO pins TCLK
and TIOB, and not the unused TIOA pin.  That pin is actually used for
(separate) different functions in both qmod and owhw.
2017-03-05 22:15:54 +01:00
Harald Welte
705e899e5f qmod: (re)activate USB port remapping.
The port mapping is now as follows:

* port 1: ST12
* port 2: modem 1
* port 3: modem 2
* port 4: ST34
* port 5: modem 3
* port 6: modem 4
* port 7: daisy-chaining port
2017-03-05 17:10:26 +01:00
Harald Welte
0e2959859a qmod: Replace hand-crafted delay loop with call to mdelay() 2017-03-05 16:48:47 +01:00
Harald Welte
c6e482d581 qmod eeprom/i2c: Re-start watchdog while slow bit-banging 2017-03-05 16:24:29 +01:00
Harald Welte
1776997f8a remove old 'notes' file with german textaul notes 2017-03-05 13:30:32 +01:00
Harald Welte
596e666fa0 fix symlink that caused host programs to not build 2017-03-05 13:28:32 +01:00
Harald Welte
2363fa0327 Generate USB Strings from apps/*/usb_strings.txt files at compile time
This way we can skip the manually-crafted USB string definitions in the
dfu_desc.c and usb.c files.
2017-03-05 10:16:25 +01:00
Harald Welte
1405100dff DFU: Introduce board/app-specific override for booting in DFU mode
Using the USBDFU_OverrideEnterDFU() function, a board/application can
define extra conditions when the system should boot in DFU mode, even if
it was not explicitly switched to DFU mode from the application.

The app/dfu/main.c uses this mechanism to boot into DFU mode if the
stack + reset vector addresses are not plausible (i.e. some random junk
appears to be flashed in the application partition) or if the user
places a jumper accross the RxD+TxD lines of the debug UART.  The idea
is that the system can be recovered by placing this jumper and then
re-installing the application from DFU.
2017-03-04 19:17:27 +01:00
Harald Welte
7214b4747f Make sure to print CPU Reset Cause when starting the software 2017-03-03 19:02:09 +01:00
Harald Welte
45ebe4591a Enable Watchdog (500ms) 2017-03-03 19:01:53 +01:00
Harald Welte
aaba4af46c Use Supply Controller to avoid running SAM3 on voltages lower than 3.0V
Sometimes there is some leakage current via some I/O that's sufficient
to power up the  SAM3S.  Use the supply monitor to make sure the CPU
will be reset (and kept in reset) if the supply voltage is below 3.0V.
2017-03-03 18:48:13 +01:00
Harald Welte
3ecbf678db only simtrace is bus-powered, SAM3 on qmod + owhw are self-powered 2017-03-03 02:10:34 +01:00
Harald Welte
8adf0ac2ce DFU app: call into board_main_top() for qmod related initialization 2017-03-03 01:52:34 +01:00
Harald Welte
f415d7163b Call USBD_Disconnect before software-triggered CPU reset
This makes sure that we'll re-enumerate on the USB, as a CPU reset
apparently doesn't automatically release the pull-up and notify the hub
that we were gone?
2017-03-03 01:51:43 +01:00
Harald Welte
ec0837c463 change from \r\n (CRLF) to \n\r (LFCR)
For some strange reason my output is garbled in both the 'screen' and
'cu' teerminal programs and 'raw' terminal (stty) mode.  I fail to
understand why, but let's simply adjust the code as needed for now.
2017-03-03 01:33:24 +01:00
Harald Welte
0de99cd069 DFU: String descriptors for DFU alt-interfaces
they are only shown in DFU mode for now, until we find a way to export
them over to the runtime.
2017-03-03 01:20:19 +01:00
Harald Welte
ac4f66e5d1 DFU: Set 10ms bwPollTimeout (lowest possible as per spec) 2017-03-03 01:13:34 +01:00
Harald Welte
91fc40240e DFU: make sure to properly initialize g_dfu pointer before using it 2017-03-03 01:05:22 +01:00
Harald Welte
b04f4f0ee8 DFU Runtime: Add missing return after handling USB standard requests
the same as 479e97e338 but this time for
the runtime, not for DFU.
2017-03-03 00:36:39 +01:00
Harald Welte
e8eea29cf6 dfu: fix cosmetic issue in debug message 2017-03-03 00:35:51 +01:00
Harald Welte
d1e963479e DFU: fix transitions between runtime and DFU mode
we now always go through a processor reset to avoid any state that might
be persistent/left-over during the switch.
2017-03-03 00:34:17 +01:00
Harald Welte
db17e83960 cstartup: (re-)enable interrupts before calling main() 2017-03-02 23:19:13 +01:00
Harald Welte
ec9b5fff3f dfu/main.c: Initialize FLASHD driver before using it 2017-03-02 23:18:40 +01:00
Harald Welte
0af4948211 cstartup / USBD: Use correct Makefile conditionals for DFU 2017-03-02 23:18:02 +01:00
Harald Welte
adbe72a5ba Makefile: Define APPLICATION_foo BOARD_bar and ENVIRONMENT_baz #defines
This can help us with conditional code
2017-03-02 23:16:01 +01:00
Harald Welte
e36970cac7 dfu: print Chip ID during boot 2017-03-02 19:24:14 +01:00
Harald Welte
cab66419d6 flashd: Set 6 Wait states as per Errata requiremens for Revision A
It is utterly unacceptable that Atmel is shipping example code in 2011,
which doesn't support parts that are shipped still in 2016.  They would
have had five years to fix their code to implement the chip errata :(
2017-03-02 19:22:50 +01:00
Harald Welte
479e97e338 DFU: Add missing 'return' after handling generic USB control request 2017-03-02 16:53:13 +01:00
Harald Welte
203abf5f6e dfu_desc: Add some string descriptors and fix configuration desc table 2017-03-02 16:52:48 +01:00
Harald Welte
ee9ebb30da stdio: Increase max string size to 512 and don't endless-loop!! 2017-03-02 16:52:08 +01:00
Harald Welte
b2ad7f76a1 dfu_des.c: Cosmetic changes, use named initializers 2017-03-01 22:15:28 +01:00
Harald Welte
0395bd15b3 move PLLB (for USB) initialization to board_lowlevel.c
This way it is present both inside the DFU loader and in the main app.
2017-02-28 01:28:56 +01:00
Harald Welte
c430ac1f2a have local stdio.h file to avoid newlib issues
... we should move to -nostdinc at some point :/
2017-02-28 01:25:12 +01:00
Harald Welte
adba0ce80b fix g_dfu access from both DFU and runtime access
We need to refer to g_dfu as a pointer from all code.  In DFU mode, it
gets assigned to the address of _g_dfu, which is placed by the linker
script at the start of RAM.  In runtime mode, the pointer is statically
defined to point at the start of RAM.  The linker script for the runtime
(dfu environment) is adjusted to save the first 32 bytes for the _g_dfu
structure.
2017-02-28 01:10:32 +01:00
Harald Welte
65cca7cccc ensure g_dfu is linked to start of RAM when building DFU loader 2017-02-28 01:10:27 +01:00
Harald Welte
db30727514 remove obsolete old linker script 2017-02-28 01:10:27 +01:00
Harald Welte
32852bc1d9 DFU: towards a more complete implementation
* we now actually route the EP0 control requests in DFU mode to the
  correct handler (weak linker symbols are tricky)
* we now actually call code to read/write data from/to RAM/FLASH
2017-02-28 01:10:23 +01:00
Harald Welte
edf9c9d322 Makefile: Optimize for size
This gets the dfu image down from 19 to 11 kBytes, with is well within
the 16kbyte limit for the DFU partition.
2017-02-27 23:24:22 +01:00
Harald Welte
37b6e41f84 move last few files from src_board / include_board 2017-02-27 23:20:38 +01:00
Harald Welte
964f509f59 remove pio_capture, we don't use it
As it registers a non-weak exception handler, it consumes memory in
every build
2017-02-27 23:14:16 +01:00
Harald Welte
96e62a4664 stdio.c: fix compiler warning 2017-02-27 23:05:15 +01:00
Harald Welte
045ea3eb7b timer.h: Fix compiler warnings about redefinition 2017-02-27 23:02:26 +01:00
Harald Welte
d09829dcc6 Remove newlib dependency, include own stdio/string/assert 2017-02-27 23:00:26 +01:00
Harald Welte
d52523185f fix some compiler warnings 2017-02-27 22:18:47 +01:00
Harald Welte
d8a003dfd7 Structure build system to build for multiple boards/apps/environments 2017-02-27 22:18:45 +01:00
Harald Welte
a1cd0f31c8 fix compilation of card_emu_tests 2017-02-27 14:29:07 +01:00
Harald Welte
3f5e3ddffc Change directory structure to align with Atmel softpack
This way we can easily check with 'diff' for differences in our code and
Atmel softpack.  Also, this layout is more suitable for building various
different firmware images (e.g. factory-test, dfu-loader, main
application) for a variety of different boards (simtrace, owhw, qmod).
2017-02-27 14:24:11 +01:00
Harald Welte
7ed6f3bc37 WIP: Introduce USB DFU code from my at91lib DFU port 2017-02-27 09:28:34 +01:00
Harald Welte
aa3b867abb WIP: split main from board-speciic parts 2017-02-26 15:59:56 +01:00
Harald Welte
a05ccc9103 build efc.o and flashd.o as part of build process 2017-02-26 15:51:10 +01:00
Harald Welte
e9eaf90d35 import efc.[ch] and flashd.[ch] from SAM3S softpack 2.1 2017-02-26 12:52:01 +01:00
Harald Welte
1d91058eee qmod: Inver initial state of PERST signals
The signals are driving an external NPN transistor, so the default state
must be low at reset to en sure that !PERST on the modem input is
de-asserted by default.
2017-02-10 19:50:24 +01:00
Harald Welte
4a9bce127f qmod: invert WWAN_PERST logic (we use transistors now) 2017-02-10 19:19:52 +01:00
Harald Welte
6732248f71 Add support for board version reading via ADC 2017-02-10 19:19:48 +01:00
Harald Welte
9c78cff10b Extend WWAN modem PERST to 300ms
It seems like a lot of modems have rather long (100ms!) minimum reset
durations.  Makes me wonder if it's an actual reset line or rather juts
some GPIO that they poll/sample every so often.  Then there are other
modems that state the reset *must not* be longer than 1s.  So let's
choose 300ms as a value in-between.
2017-02-04 14:58:49 +01:00
Harald Welte
987f59aa02 Import libosmocore timer infrastructure and use it for PERST
The PERST is thus no longer busy-waiting but starting a timer to release
the PERST after 1ms.
2017-02-04 14:58:45 +01:00
Harald Welte
b41598b602 Introudce an include_libosmocore directory and move (updated) linuxlist there 2017-02-04 12:15:58 +01:00
Harald Welte
7e5c7d5b82 Add debug commands '1' and '2' to generate 1ms reset pulses to modems 2017-02-03 22:59:04 +01:00
Harald Welte
31f817c3ac Add support for controlling PERST of WWAN modems (on qmod) 2017-02-03 22:22:20 +01:00
Harald Welte
83207e0cad Add 'mdelay()' function to busy-wait for given number of milli-seconds 2017-02-03 22:22:17 +01:00
Harald Welte
2819e9c131 wwan_led: Read + report status changes of WWAN LED inputs 2017-02-03 07:49:28 +01:00
Harald Welte
af6147997d qmod: Remove 'U' debug command and directly initialize USB
The hack to manually delay the USB initialization is no longer needed as
finally the USB enumerates.
2017-01-12 18:59:41 +01:00
Harald Welte
fb3f308f2f board_lowlevel: Clean up PLLA configuration
The PLL setting doesn't depend on the 'qmod' board type but on the
combination of the BOARD_MAINOSC and BOARD_MCK #defines.  So let's
remove the '#ifdef qmod' from the equation.

The only 'qmod' specific part is whether or not to use the internal xtal
oscillator or not.
2017-01-12 18:16:23 +01:00
Harald Welte
84ad98585c usb: Cofnigure PLLB according to board.h BOARD_MAINOSC
Actually we don't even need to use PLLB for USB and could simply use
PLLA, but then we don't c are about the extra 2.5mA
2017-01-12 18:06:57 +01:00
Harald Welte
7861132fad qmod: Don't violate PLL minimum output frequency
Table 42-31 ofd DOC6500 states that the minimum output frequency of the
PLL is 60 MHz.   The existing qmod code violated this by configuring the
PLL multiplier output to 12*4 = 48 MHz.  Let's use 12*8 = 96 and then
divide that by two to get to the desired 48 MHz.

This might help to resolve the non-working USB on the qmod so far.
2017-01-12 11:07:04 +01:00
Harald Welte
b871363be7 qmod: cosmetic changes to EEPROM hex array
* move it out of the function so it actually is present in .rodata,
  rather than having a long sequence of stores into a stack buffer
* use 16 bytes per line so it is easier to find + change bits in there
2017-01-11 23:08:35 +01:00
Harald Welte
b30783c83e qmod EEPROM: Dont't mark any ports as non-removable
.. and don't disable any ports during bus-powered operation (which we
don't support anyway).
2017-01-11 23:02:26 +01:00
Harald Welte
ae8a465f36 qmod: Commit missing changes to EEPROM
The firmware we used for testing contained some local changes which were
not committed.  They primarily relate to the port re-ordering feature as
well as the amount of power (0x32 = 100mA) is now used consequently.
2017-01-11 22:59:09 +01:00
Harald Welte
6dfcf70f63 qmod: Start with _HUB_RESET=0 -> HUB_RESET=1 (not in reset)
Booting with the hub reset active would in turn cut our own power
supply as the hub disables all downstream port power in that case.
2017-01-11 22:23:13 +01:00
Harald Welte
f9a182d24d qmod: breal the command loop when 'U' is pressed and proceed to USB init 2017-01-11 22:22:16 +01:00
Harald Welte
afbb747170 qmod: do not automatically clear _HUB_RESET after EEPROM write
we'd rather have explicit control over that
2017-01-11 22:21:28 +01:00
Harald Welte
e07aed6543 qmod: debug menu: Add 'U' command to proceed to USB 2016-12-22 22:32:15 +01:00
Harald Welte
396354cbdb qmod: debug menu: make sure to always print something 2016-12-22 22:29:57 +01:00
Harald Welte
006b16ddc2 quad-modem: Add debug console commands for debugging 2016-12-22 21:29:41 +01:00
Harald Welte
e974fbb9e5 Issue ST12_PRTPWR_OVERRIDE before putting hub in reset
When we reset the hub, the hub will actively drvie the PRTPWR signal of
the SITMRACE12 low, resulting in the SAM3 being shut off.  If we want to
"survive" this, we need to set the OVERRIDE before we go into reset.

Right now, we never release the signal again, keeping ST12 enabled
permanently, which is of course not what we want in general.
2016-10-19 19:36:07 +02:00
Harald Welte
15e026ec34 qmod: Set PIN_PRTPWR_OVERRIDE to output/low 2016-10-11 17:46:09 +02:00
Harald Welte
4e3b9a5140 qmod: attempt to swithc the DN/DP wires of the SAM3 2016-09-05 14:04:43 +02:00
Harald Welte
67415e3385 HACK: Add EEPROM writing at boot of SAM3 on qmod
This is not for production use, but just for hardware verification
2016-09-01 20:57:56 +02:00
Harald Welte
73d697d788 i2c-bitbang: increase speed to ~110kHz 2016-09-01 18:58:41 +02:00
Harald Welte
0aea9fff28 Fix reading SDA in I2C bit-banging code
We need to use pin_sda_in, not pin_sda to read the PIO Input.
2016-09-01 18:39:12 +02:00
Harald Welte
c6ae98c53a i2c_bitbang: Change logic when to use i2c_delay() 2016-09-01 11:57:09 +02:00
Harald Welte
226b40aba4 WIP: bit-banging I2C support for EEPROM access on QMOD
for now, it just continuously reads the EEPROM bytes and dumps them to
the serial console for testing.
2016-08-21 19:33:24 +02:00
Harald Welte
a02b641650 Add support for 'qmod' (quad-modem) board
You can compile the firmware for this new target using 'make
BOARD=qmod'.

The QMOD differs from simtrace+owhw in terms of low-level
initialization, as it has an external 12MHz clock at XIN, thus bypasses
the main oscillator and needs different PLL configuration.
2016-08-21 18:32:12 +02:00
Harald Welte
fd9c041ec8 fix TRACE_ENTRY line termination (LF -> CRLF) 2016-03-20 18:20:14 +01:00
Harald Welte
990f01051f Add HardFault Exception Handler
The HardFault exception handler prints the stacked register as well
as some SCB registers to help debugging even in absence of JTAG.
2016-03-20 18:19:35 +01:00
Harald Welte
e26c943fa1 exceptions: Print name of exception to console 2016-03-20 18:19:18 +01:00
Harald Welte
622b6be774 Fix ADC based VCC detection
* we need to actually return the voltage
* we need to use the correct register name for the CIDR
2016-03-20 18:19:18 +01:00
Harald Welte
3bafe43376 dynamically dispatch USART IRQs
The different modes (configurations) will have different interrupt
handlers, so we need to dispatch them via config_func_ptrs
2016-03-20 18:19:12 +01:00
Harald Welte
dde112e71c print instance/channel number in all trace messages
When debugging issues related to two concurrent SIM card emulations,
it is vital to know to which USART a message relates.
2016-03-20 16:42:11 +01:00
Harald Welte
8ee15dbc2a read SAM3S unique serial number at start and print it 2016-03-20 16:00:39 +01:00
Harald Welte
28772ebcdc ADC: Make errata work-arounds depend on run-time detection of chip version 2016-03-20 15:44:52 +01:00
Harald Welte
1871c25b6d simtrace2-remsim: Instruct SAM3S to simulate card removal on SIGINT
When stopping the program, we inform the card simulator to indicate
a card removal to the GSM phone/modem.
2016-03-20 15:30:46 +01:00
Harald Welte
cf1c19abe0 src_simtrace/main: debug/trace logging improvements 2016-03-20 15:18:18 +01:00
Harald Welte
04e37a8481 firmware/main: Disable the rotor unless TRACE_DEBUG 2016-03-20 15:18:03 +01:00
Harald Welte
5541e8a819 USBD_HAL: Hard-code TRACE_LEVEL_WARNING
we don't want to have USB related messages mess up our console
2016-03-20 15:13:47 +01:00
Harald Welte
9daaa79222 simtrace2-remsim: Send an ATR that allows for a 5MHz/16 divider
This ATR is useful to test higher speeds up to 312500 bits/s
2016-03-20 15:01:20 +01:00
Harald Welte
53079bbbac debug/tracing updates 2016-03-20 14:58:35 +01:00
Harald Welte
c58bba0833 wait for UART Tx completion before switching baud rate at PTS 2016-03-20 14:57:53 +01:00
Harald Welte
c8beefbf85 wait for transmitter to be done before receiving
At higher speeds, it seems we are turning off the transmitter before we
are enabling the receiver.  Unfortunately the TXEN bit in the uart mode
register is read-only, so we don't really know if the transmitter is
enabled or not.  It seems we can simply keep transmitter + reciver
running at the same time, and use the TXEMPTY bit as reliable means to
determine if we're busy transmtting.
2016-03-20 14:40:47 +01:00
Harald Welte
903d63a1e0 card_emu: Alwasys update state before enabling UART Rx/Tx
The UART Rx/Tx irq might hit us before we actually reach the line that
changes the state.  So always update the state before enabling UART
Rx/Tx.
2016-03-20 13:38:39 +01:00
Harald Welte
52d554657c card_emu: Avoid PTS related race-condition
We should not set the new Fi/Di values before we actually transmitted
the PTSS PCK at the old baud rate first.
2016-03-20 13:38:05 +01:00
Harald Welte
ccb8a22037 card_emu: Avoid PTS related race-condition
We should not set the new Fi/Di values before we actually transmitted
the PTSS PCK at the old baud rate first.
2016-03-20 13:37:11 +01:00
Harald Welte
a929f218d2 card_emu: Differentiate between TRACE_{DEBUG/ERROR/INFO} 2016-03-20 13:36:42 +01:00
Harald Welte
07872b6cdd VCC/ADC: finish implementing VCC detection via ADC
... however, keep it disabled due to ADCVREF not being connected on
OWHWv1/v2.
2016-03-20 11:45:36 +01:00
Harald Welte
6dcacf3efe OWHW: fix operation with second modem/UART
We can now enable CARDEMU_SECOND_UART in owhw/board.h, as it no
longer interferes with operation of the first port (USIM1).  Whether
the second port actuall works still remains to be tested at this point.
2016-03-20 10:06:05 +01:00
Harald Welte
419eb8acf2 WIP: Use ADC to determine VCC voltage 2016-03-20 10:04:03 +01:00
Harald Welte
ff16065047 implement CEMU_USB_MSGT_DT_GET_STATUS
card_emu can now report its current satus upon request.
2016-03-19 21:59:06 +01:00
Harald Welte
02d5096b31 add host .o and executables to .gitignore 2016-03-19 21:38:59 +01:00
Harald Welte
2315e6ba07 ensure git version ends up in firmware image 2016-03-19 21:37:55 +01:00
Harald Welte
236caf68eb remote-sim host tools: Auto-discover the endpoint addresses
We now auto-discover the end-point addresses based on the interface
descriptor.  The user can also use the new "--interface" command line
argument to set a non-zero intrerface.  In combination, this should
enable support for the remote-sim functionality on the second UART
on OWHW.
2016-03-19 21:28:09 +01:00
Harald Welte
095ac6cbe2 Add simtrace2-remsim applications 2016-03-19 13:52:31 +01:00
Harald Welte
b26d0038f6 split/segment multiple commands from single USB transfer
UDP end-points are streams, so when we receive data on the OUT
endpoint callback, the buffer might contain several commands.  When
dispatching the messages, split (segment) them again before dispatching
them to their respective handlers.
2016-03-19 13:33:02 +01:00
Harald Welte
d295b92192 ensure usb_msg_hdr contains raw message length
we want to ensure that the length of every (current or future) message
can be determined by looking at cardemu_usb_msg_hdr.msg_len, rather than
having a length that is relative to the respective specific command.
2016-03-18 21:01:36 +01:00
Harald Welte
b8f9450c18 shrink ringbuffer size to 128 bytes
We only use it to implemet a software FIFO between the UART Rx IRQ
and the code that processes it.  1k is way too large for that.
2016-03-18 10:33:31 +01:00
Harald Welte
9f240b6d34 use irq-safe version of llist operations between USB callback and main 2016-03-18 10:32:56 +01:00
Harald Welte
da15ca01bf mode_cardemu: mask the USART status register with mask register
otherwise it might be reacting on stale bits in CSR, which actually are
no longer able to cause any interrupts.
2016-03-17 21:14:04 +01:00
Harald Welte
3d27c84635 host_comm: Fix race condition in handling OUT USB transfers 2016-03-17 20:07:45 +01:00
Harald Welte
250cd2c062 host_communication: set rctx->tot_len after receiving USB transfer 2016-03-17 18:19:39 +01:00
Harald Welte
372f4cc7ba board_lowlevel: Use LED definitions from board.h
... this is more portable.
2016-03-16 22:22:57 +01:00
Harald Welte
5820ea9327 dispatch_usb_command: Ensure list consistency + avoid mem leaks
When iterating over the queue of req_ctx, make sure to unlink each
buffer before processing it.  And during processing, ensure all buffers
are reelased back to the memory management.
2016-03-16 22:22:57 +01:00
Harald Welte
0eaa992682 cardem: Add support for USB host based set/clear of card_insert
This way the application on the USB host can control whether the
emulator should emulate that the card be inserted or not.  We change the
reset-default back to 'not inserted' (GPIO output 0) and wait for the
application to explicitly request this by issuing
CEMU_USB_MSGT_DT_CARDINSERT.
2016-03-16 22:22:57 +01:00
Harald Welte
7abdb51f8f ringbuffer: Make ring buffer access irq-save
We have to temporarily disable nterrupts when performing rinbuffer
operations, as the ring buffer is used both from IRQ as well as process
context.
2016-03-16 22:22:54 +01:00
Harald Welte
7dd3dfd992 convert all src_simtrace code to kernel coding style
Let's use the Osmocom standard, based on the Linux kernel standard:
tab-indent and 8-charracter tab width.
2016-03-16 20:45:10 +01:00
Harald Welte
1605564489 ensure USB config numbers always start from 1
Depending on which features (and thus USB configurations) are included
in the firmware, we need to re-define the ordering of the configuration
numbers, as the Atmel USBD driver simply assumes that configurations are
numbered 1..N without any gaps in the sequence.
2016-03-16 20:45:10 +01:00
Harald Welte
072daddf98 main.c: Only call the configure() function of a configuration if it exists 2016-03-16 20:45:10 +01:00
Harald Welte
40901a0f14 various printf/debug output improvements
... among those is a rotor (\|/-) that is printed by the main loop,
so one can observe if the main loop is still executing or the system
is somehow stuck.
2016-03-16 20:45:09 +01:00
Harald Welte
57b3a250d4 Add Card-Emulation for second UART/USIM to USB descriptors 2016-03-16 20:45:09 +01:00
Harald Welte
13e8202c81 mode_cardem: Prepare for full support of second UART/USIM
So far we have only been working with a single UART/USIM. Let's
make things more data structure driven and pass around handles to
the data structures rather than hardcoding...
2016-03-16 20:45:09 +01:00
Harald Welte
06b27f64a2 mode_cardemu: Implement CEMU_USB_MSGT_DT_SET_ATR
This way the host PC can set the ATR of the emulated card
2016-03-16 20:45:09 +01:00
Harald Welte
ebb80eda19 introduce 'main' queue between USB receive and UART TX
In order to handle other USB commands like GET_STATUS, SET_ATR
or GET_STATS, we introduce an intermediary queue.  The USB receive
completion call-back puts the command on that intermediate 'main'
queue.  From that intermediate queue, the are further
dispatched/processed according to their mesage type.
2016-03-16 20:45:09 +01:00
Harald Welte
ad43440d93 card_emu: Fix various compiler warnings by switch/default/break 2016-03-16 20:45:09 +01:00
Harald Welte
5e00400a05 board_lowlevel.c: Improve main oscillator initialization
* ensure the PB8/PB9 pins are actually not in GPIO mode, which they
  apparently are on boot-up
* ensure that neither pull-up nor pull-down are enabled on PB8/PB9
* ensure we first start the oscillator, before selecting it

The sum of the above changes seems to make oscillator start-up much more
reliable than before.  The time needed for initialization is now pretty
stable, and the occasional 15-20second clock stabiliziation has not been
observed with this change.
2016-03-16 20:45:09 +01:00
Harald Welte
a0cf200695 host_communication: keep track of number of pending/queued req_ctx 2016-03-02 10:35:51 +01:00
Harald Welte
acd48c51f2 HACK: always use the USART interrupt handler of mode_cardemu()
This must be fixed in a way that the per-configuration interrupt
handler is called, depending on the USB configuration that is set.
2016-03-02 10:34:24 +01:00
Harald Welte
fcdd660fb1 card_emu: Don't de-reference a NULL variable 2016-03-02 10:33:58 +01:00
Harald Welte
fde250a54b uart_console.c: Don't redefine constants from board.h 2016-03-02 10:33:11 +01:00
Harald Welte
715bc05f55 Increase serial console sped to 230400 bps
This makes debug printf's twice as fast (half as slow) and thus
has less of an impact on execution speed than the previous 115200
2016-03-02 10:31:59 +01:00
Harald Welte
12d4bdfbb1 mode_cardemu: Process RX interrupts before TX
It's always more important to pull out a received character from
the receive holding register to avoid the risk of overflow, so let's
do that first.
2016-03-02 10:31:03 +01:00
Harald Welte
dda7355306 card_emu: Only transmit NULL byte from the right state
The reader cannot accept a waiting time extension at any time. Rather,
it can only accept it if it is currently  waiting for a procedure byte.
2016-03-02 10:29:55 +01:00
Harald Welte
f1697e2dd9 card_emu: Only allocate a new buffer if needed in send_tpdu_header() 2016-03-02 10:28:54 +01:00
Harald Welte
acae412b2a explicitly inform card_emu once data to transmit has arrived 2016-03-02 10:27:58 +01:00
Harald Welte
8a416b1812 mode_cardemu: fix ordering of events when switching rx/tx mode 2016-03-01 00:42:04 +01:00
Harald Welte
45688d4c3b mode_cardemu: Disable UART TXRDY generation if we don't have data to TX
When the ISO7816 state machine requires us to transmit something, but
we don't have data ready to transmit, we should switch off TXRDY
interrupt generation.

What's missing is of course the other part that re-enabls TXRDY
generation once new data is available
2016-02-29 21:35:38 +01:00
Harald Welte
349c54bc3b req_ctx: LF -> CR+LF 2016-02-29 21:35:24 +01:00
Harald Welte
22925ea707 test: Add TRACE_INFO and TRACE_ERROR definitions 2016-02-29 21:14:25 +01:00
Harald Welte
4678388c3c board_lowlevel: More comments about clock initialization 2016-02-29 19:45:59 +01:00
Harald Welte
ebbb645f4b req_ctx: Fix allocation (allocate 1 block, not all) and call _init() 2016-02-29 17:57:51 +01:00
Harald Welte
54cb3d017f host_communication/card_emu: adapt to nwe req_ctx / queuing paradignm 2016-02-29 14:12:40 +01:00
Harald Welte
f672e9d63a req_ctx: Convert from hand-coded linked lists to linuxlist.h
This also removes the actual queuing code from req_ctx, and
leaves this to the caller.  Only tw out of the existing states actually
required the ordering requirement enforced by the qeue, and in the
future we will need to have per-endpoint queues anyway.  Both means it
is better to manage queues outside the req_ctx, and leve that as a pure
memory allocator.
2016-02-29 14:10:22 +01:00
Harald Welte
b66ce249d0 req_ctx: Add better explanation about the various states 2016-02-29 14:07:07 +01:00
Harald Welte
22bf67fc9c card_emu: Use \r\n instead of \n
When printing over the actual serial port (as opposed to the unit
tests) we need CR+LF, and not just LF.
2016-02-29 10:18:59 +01:00
Harald Welte
708d85c085 trace.h: Don't print file/function name in TRACE_DEBUG() 2016-02-29 10:16:05 +01:00
Harald Welte
c0bd7f0aaa mode_cardemu: Move GPIO detection to IRQ, use ring buffer for UART RX
We don't want to call into the bulk of card_emu.c from interrupt
context, so let's introduce a ring buffer as a softwre-FIFO between
the USART receiving a byte and the processing of that byte in
card_emu.c, which is then performed from the main loop outside
interrupt context.
2016-02-29 10:13:33 +01:00
Harald Welte
47ee283d14 card_emu_io_statechg(): properly determine edges from levels
The caller might not have edge triggering and just gives us the
current state.  we have to use that informtaion to determine the
edges when something is actually switched on or off.
2016-02-29 10:09:46 +01:00
Harald Welte
99f62a6def mode_cardemu: update_fidi just needs to execute
the actual translation of the Fi/Di values to the divider is
already made, we just need to update the USART divider here.
2016-02-29 10:08:49 +01:00
Harald Welte
2ad0ca15a8 host_communication: Fix TRACE_ERROR syntax 2016-02-29 10:07:16 +01:00
Harald Welte
43f7949fe0 card_emu: Add TRACE_DEBUG once TPDU header is sent to USB 2016-02-29 10:06:54 +01:00
Harald Welte
b086ab0242 owhw: Fix GPIO for USIM1_RST (24, not 23!) and enable SET_USIM1_PRES 2016-02-29 10:05:53 +01:00
Harald Welte
9dbc46e799 mode_cardemu: Proper enabling/disabling of USART IRQ sources
we always have to disable all intrerrupts that we don't want to be
enabled
2016-02-29 10:05:10 +01:00
Harald Welte
ba0c688103 owhw: Make owhw/board.h the default for now
I will re-introduce simtrace2 hardware support later
2016-02-28 19:32:36 +01:00
Harald Welte
4dc3db7beb req_ctx: Use only 10 small buffers, and no large ones 2016-02-28 19:32:01 +01:00
Harald Welte
203ea19227 req_ctx: Use the linked lists between req_ctx to ensure ordering
It is important we send the buffers in-order, and not re-order
them between the main program and the USB host.
2016-02-28 19:31:24 +01:00
Harald Welte
bd71768e5f mode_card_emu: connect the update_fidi() callback 2016-02-28 19:30:05 +01:00
Harald Welte
2a6d3afd6c re-introduce req_ctx buffers into the host communication 2016-02-28 19:29:14 +01:00
Harald Welte
29f8f0e5d4 improvements in req_ctx debugging 2016-02-28 12:44:30 +01:00
Harald Welte
2fb5996d30 owhw: fix GPIO definitions (output low level by default) 2016-02-28 12:34:26 +01:00
Harald Welte
8c49636127 card_emu.c: avoid re-defining update_fidi() symbol 2016-02-27 16:24:09 +01:00
Harald Welte
390760a006 add board/owhw.c 2016-02-27 16:23:46 +01:00
Harald Welte
54a7cec7bd Add card_emu_target.c to bind card_emu.c code into target firmware 2016-02-27 16:23:14 +01:00
Harald Welte
17db2f1112 card_emu: Fix PTS checksum verification
If the checksum doesn't match, the card should not apply any Fi/Di
changes, not respond anything and simply expect the next TPDU.
2016-02-26 09:48:57 +01:00
Harald Welte
4ba66d0098 implement forwarding of PTS/PPS from emulator to host PC + test case 2016-02-26 09:40:34 +01:00
Harald Welte
86d047b8f4 card_emu_test: Verify content of emulator->reader bytes 2016-02-25 00:26:17 +01:00
Harald Welte
0ef96d5735 card_emu: Ensure the length is properly set on a TPDU header rctx 2016-02-25 00:09:17 +01:00
Harald Welte
0ab6fcd173 card_emu_tests: Verify context of USB request contexts
when the emulator has received some data, don't just check that
we see it coming up on teh USB side, but actually also check
the content of those messages
2016-02-25 00:08:22 +01:00
Harald Welte
c043e64ef1 card_emu_tests: move test cases into functions 2016-02-24 23:26:55 +01:00
Harald Welte
eef6c2a46c card_emu_test: Add test for card-TX (reader-RX) APDU 2016-02-24 22:19:03 +01:00
Harald Welte
f16b618755 card_emu: Fix the length checks for transmit beyond rctx->tot_len 2016-02-24 22:18:46 +01:00
Harald Welte
22cdf2af59 card_sim: fix passing handle to tc_etu_*() functions 2016-02-24 22:18:11 +01:00
Harald Welte
6bf8c12b13 update card_emu_tests to recent card_emu changes 2016-02-24 21:04:08 +01:00
Harald Welte
042f0d366b tc_etu: Add explicit enable/disable functions
We don't want the tc_etu to call into card_emu at all times,
e.g. while clock is applied, but RST is not yet present.

Rather, we want to explicitly enable it once RST is released
2016-02-24 21:01:50 +01:00
Harald Welte
855ba9e168 card_emu: Ensure TX happens synchronously before state changes
we cannot first chage the state and then transmit the byte
asynchronously later, this introduces race conditions.  Do it
in-line by explicit calls to the UART Tx function.
2016-02-24 21:00:46 +01:00
Harald Welte
849269f4cc add OWHW board.h file 2015-11-30 12:16:53 +01:00
Harald Welte
2d3371ed65 split board.h into generic part and simtrace-specific part 2015-11-30 11:59:03 +01:00
Harald Welte
61bb30e4ea card_emu: Correctly handle SW after reader -> card data phase 2015-11-14 23:44:14 +01:00
Harald Welte
84ec252ff4 card_emu_test: test APDUs with both Rx and Tx data phase 2015-11-14 23:05:13 +01:00
Harald Welte
4d8046743e card_emu: Fix state transitions for both Rx and Tx data phase
We now use the P3 value to determine how many characters to
receive (in case of Reader->Card payload phase).
2015-11-14 23:05:13 +01:00
Harald Welte
b5288e8ac4 card_emu: Introduce new flush_rx_buffer() function and use it 2015-11-14 23:05:13 +01:00
Harald Welte
e7194abb9e card_emu: Ensure to re-set PTS state when coming out of reset 2015-11-14 23:05:10 +01:00
Harald Welte
52922ffa32 card_emu: Properly handle end of a procedure-byte carrying REQ_CTX
how we proceed changes depending on whether we should continue to
receive or transmit...
2015-11-14 20:59:56 +01:00
Harald Welte
05b41c62f6 card_emu: fix set_tpdu_state()
* don't enter a state we are already in
* enable the UART receiver not only when waiting for CLA, but also
  generally when we're waiting for more data from the reader
2015-11-14 20:58:48 +01:00
Harald Welte
2935b3c479 card_emu: detect end of TX data from CEMU_DATA_F_FINAL
When the USB host software sets this flag, we terminate the
TPDU transmission after the last character in this frame and
transition again to the WAIT_TPDU state.
2015-11-14 20:00:14 +01:00
Harald Welte
b436286ed6 card_emu_tests: extend first TPDU test to sending PB + SW in response 2015-11-14 19:02:33 +01:00
Harald Welte
836990d244 req_ctx: Fix compiler warnings 2015-11-14 17:38:04 +01:00
Harald Welte
d79dc4f6f2 card_emu: Implement get_byte_pts() 2015-11-14 13:33:10 +01:00
Harald Welte
4c473dad30 card_emu: Fail with assert in case next_tpdu_state from wrong state 2015-11-14 13:32:05 +01:00
Harald Welte
612d65ad62 card_emu: Make update_fidi() void 2015-11-14 13:30:43 +01:00
Harald Welte
16cf408a49 card_emu.c: More comments about data structures 2015-11-11 19:02:48 +01:00
Harald Welte
9d3e38242c initial commit of more code towards card emulation
I couldn't help but to spend my sunday on working towards card
emulation, including
* various state machines in the target about ISO7816 states
* tc_etu timer import from simtrace1
* req_ctx import from simtrace1 (needs renaming and simplifiation)
* USB protocol description as cardemu_prot.h
* some host-based testing code to test the state machines

The code seems to work fine throughout card reset, sending ATR and
receiving the TPDU header of the first APDU, up to the point where it
marks the TPDU header as to-be-transmitted over th bulk-in endpoint.

Sending the ATR must be done inside the firmware for timing
requirements.

From that point onwards, the host needs to respond at the very least
with a procedure byte, and some indication whether or not the card
emulator should continue to transmit data (card->reader), or receive
data (reader->card).

The code is intentionally not hooked up yet with the USB logic nor with
the UART.  I want host-based testing completed before doing that.
2015-11-09 00:50:54 +01:00
Harald Welte
f64f68871e move ARRAY_SIZE() definition to utils.h 2015-11-08 21:31:48 +01:00
Harald Welte
30a53f823a Move Fi/Di calculation functions to separate C file 2015-11-08 14:29:55 +01:00
Harald Welte
6d44c1fdd3 USB: Add manufacturer name string descriptor
... and use indexed array initializers for more safety/clarity
2015-11-07 19:01:30 +01:00
Harald Welte
8a5b580a72 CCID usb descriptor: We support 3V only, not 5V. 2015-11-07 18:53:43 +01:00
Harald Welte
ec4fe2358b Mark more local functions as static 2015-11-07 18:48:26 +01:00
Harald Welte
844db577f2 change to own USB vendor/device ID
we shouldn't re-use the vendor/device ID usd by simtrace1, as the
protocol is incompatible and applications for simtrace 1 don't work with
simtrace2.   Also, there's a different processor architecutre in the
hardware.
2015-11-07 18:38:04 +01:00
Harald Welte
beb729391b USB descriptors: call it SIMtrace 2 and add spaces to strings 2015-11-07 18:35:41 +01:00
Harald Welte
8d6a5d8f89 move USBDDriverCallbacks_ConfigurationChanged() to main.c
This alows us to mark simtrace_config as static variable and keep all
code related to this variable local to main.c
2015-11-07 18:27:05 +01:00
Harald Welte
d4c1421c91 conf_func: Mark const and static.
const saves RAM, and static avoids namespace pollution.
2015-11-07 18:25:46 +01:00
Harald Welte
fefd571701 conf_func: Use named struct initializers and named array subscripts
As part of this, we also do away with the '-1' based array subscripts
2015-11-07 18:25:19 +01:00
Harald Welte
15d72cc631 add some comments on the conf_func members 2015-11-07 18:19:06 +01:00
207 changed files with 20717 additions and 3915 deletions

16
.gitignore vendored
View File

@@ -7,7 +7,17 @@ cscope.out
*/__pycache__
*.E
*.pyc
sam3s_example/mains/zwizwa_ccid.c
Baselibc
venv
tags
*.hobj
*.o
*.a
*.lst
*.map
*.elf
*.size
*.bin
*.p
host/simtrace2-list
host/simtrace2-remsim
host/simtrace2-remsim-usb2udp
usb_strings_generated.h

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "usb_application/pysim"]
path = usb_application/pysim
url = git://git.osmocom.org/pysim

131
README.md
View File

@@ -1,112 +1,39 @@
# SIMtrace v2.0
The SIMtrace software together with the corresponding hardware provides a means to trace the communication between a SIM card and a mobile phone, and intercept it starting with SIMtrace software version 2.0 (together with SIMtrace board version 1.5).
Furthermore, it provides a SIM card emulation and CCID reader mode.
SIMtrace v2.0
=============
## How to compile
A Makefile is provided. It created an image under bin/project-flash.bin, which can directly be flashed on the board (see section "How to flash").
This is the repository for the next-generation SIMtrace devices,
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.
The level of debug messages can be altered at compile time:
```
$ make TRACE_LEVEL=4
```
Accepted values: 0 (NO_TRACE) to 5 (DEBUG)
This is under heavy development, and right now it is not surprising if
things still break on a daily basis.
## How to flash
For flashing the firmware, there are at least two options.
The first one is using openocd and a JTAG key.
For this option, a JTAG connector has to be soldered onto the board, which is not attached per default.
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 /
microcontroller architecture and uses a completely different software
stack and host software.
The Makefile already provides an option for that:
```
$ make program
```
This command will call the following command:
```
$ openocd -f openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 ./bin/project-flash.bin 0" -c "reset" -c "shutdown"
```
Supported Hardware
------------------
The second option is using rumba for flashing. No further hardware has to be provided for this option.
The software can be obtained with the following shell command:
```
$ git clone git://git.osmocom.org/osmo-sdr.git
```
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.
Flashing the compiled firmware can be done with the following command:
```
$ $OSMO_SDR_DIR/utils/rumba /dev/ttyACM0 flashmcu $FIRMWARE_DIR/bin/project-flash.bin
```
The goal is to support the following devices:
## How to set udev rules
The next step is defining the udev rules for simtrace.
Open the file /etc/udev/rules.d/90-simtrace.rules and enter those four lines:
* Osmocom SIMtrace 1.x with SAM3 controller
** this is open hardware and schematics / PCB design is published
* sysmocom sysmoQMOD (with 4 Modems, 4 SIM slots and 2 SAM3)
** this is a proprietary device, publicly available from sysmocom
* sysmocom OWHW (with 2 Modems and 1 SAM3 onboard)
** this is not publicly available hardware, but still supported
```
# Temporary VID and PID
SUBSYSTEM=="usb", ATTR{idVendor}=="03eb", ATTR{idProduct}=="6004", MODE="666"
# Future SIMtrace VID and PID
SUBSYSTEM=="usb", ATTR{idVendor}=="16c0", ATTR{idProduct}=="0762)", MODE="666"
```
This Repository
---------------
After reloading the udev rules, SIMtrace should be recognized by the operating system.
This repository contains several directory
## How to use
After flashing the firmware and defining the udev rules, the python program simtrace.py can be used in order to command the board.
First, the configuration has to be set using the -C option, which has to be passed a number determining the mode:
1: Sniffer mode
2: CCID reader mode
3: Mobile phone emulation mode
4: MITM mode
For example, setting the device into MITM mode can be achieved with the following command:
```
$ simtrace.py -C4
```
After setting the configuration, one of the following functionalities can be started:
```
-s, --sniff Sniff communication!
-S, --select_file Transmit SELECT cmd!
-p, --phone Emulates simcard
-m, --mitm Intercept communication (MITM)
```
For example, in order to use simtrace in sniffer mode, the following command can be executed:
```
$ simtrace.py -C1 -s
```
For more information, execute the following command:
```
$ simtrace.py -h
```
## Logging
The Makefile furthermore provides an easy option for reading the log messages.
SIMtrace sends out log messages over the serial interface, using a connector with a 2.5mm jack.
Using a serial to USB converter, the log messages can be read using the following command:
```
$ make log SERIAL=/dev/ttyUSB*
```
If no SERIAL is defined, /dev/ttyUSB0 is taken by default.
## Known issues
* If there is an error, it might result from a missing instruction byte in the list of instructions that expect data from the simcard.
It can be updated in the file in apdu_split.py
Especially, if the sniffer mode works well, but the mitm mode fails, that's a good place to start looking.
The array is of the following form:
`INS_data_expected = [0xC0, 0xB0, 0x12]`
* For interacting with the SIM card (CCID reader and MITM mode), pcscd has to be
started on the computer.
* The maximum operating frequency of the device and hardware is not determined yet.
The function for changing the FIDI is not tested yet because no device could be obtained, which would change the FIDI in the middle of the communication.
Most devices stick with the default FIDI.
* The software assumes a master-slave-protocol: The master sends a command, the slave answers this.
If this premise is not met, the software will not operate properly.
This should be taken into account when programming the Mobile phone emulator or MITM mode.
* firmware - the firmware to run on the actual devices
* hardware - some information related to the hardware
* host - Programs to use on the USB host to interface with the hardware

57
contrib/jenkins.sh Executable file
View File

@@ -0,0 +1,57 @@
#!/bin/bash
TOPDIR=`pwd`
if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
exit 2
fi
set -e
base="$PWD"
deps="$base/deps"
inst="$deps/install"
export deps inst
osmo-clean-workspace.sh
mkdir "$deps" || true
osmo-build-dep.sh libosmocore "" '--disable-doxygen --enable-gnutls'
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="$inst/lib"
BUILDS=""
BUILDS+="simtrace/dfu simtrace/cardem " # simtrace/trace simtrace/triple_play
BUILDS+="qmod/dfu qmod/cardem "
BUILDS+="owhw/dfu owhw/cardem "
cd $TOPDIR/firmware
for build in $BUILDS; do
board=`echo $build | cut -d "/" -f 1`
app=`echo $build | cut -d "/" -f 2`
echo
echo "=============== $board / $app START =============="
make BOARD="$board" APP="$app"
make BOARD="$board" APP="$app" clean
echo "=============== $board / $app RES:$? =============="
done
echo
echo "=============== FIRMWARE TESTS ==========="
cd $TOPDIR/firmware/test
make clean
make
./card_emu_test
make clean
echo
echo "=============== HOST START =============="
cd $TOPDIR/host
make clean
make
make clean
osmo-clean-workspace.sh

View File

@@ -34,49 +34,34 @@
# Chip & board used for compilation
# (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
CHIP = sam3s2
BOARD = simtrace
CHIP ?= sam3s4
BOARD ?= qmod
# Defines which are the available memory targets for the SAM3S-EK board.
MEMORIES = flash
# Trace level used for compilation
# (can be overriden 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 = 1
#FIXME: Remove this variable
NOAUTOCALLBACK=no
DEBUG_PHONE_SNIFF=0
#CFLAGS+=-DUSB_NO_DEBUG=1
# Optimization level, put in comment for debugging
OPTIMIZATION = -O0
MEMORIES ?= flash dfu
# Output file basename
OUTPUT = project
APP ?= dfu
# Output directories
OUTPUT = $(BOARD)-$(APP)
BIN = bin
OBJ = obj
OBJ = obj/$(BOARD)
#-------------------------------------------------------------------------------
# Tools
#-------------------------------------------------------------------------------
AT91LIB_USB_COMMON_CORE_PATH = atmel_softpack_libraries/usb/common/core
AT91LIB_USB_CORE_PATH = atmel_softpack_libraries/usb/device/core
AT91LIB = ./atmel_softpack_libraries
AT91LIB_USB_COMMON_CORE_PATH = $(AT91LIB)/usb/common/core
AT91LIB_USB_CORE_PATH = $(AT91LIB)/usb/device/core
AT91LIB_USB_DFU_PATH = $(AT91LIB)/usb/device/dfu
# Tool suffix when cross-compiling
CROSS_COMPILE = arm-none-eabi-
LIBS = -Wl,--start-group -lgcc -lc -Wl,--end-group
LIBS = -Wl,--start-group -lgcc -Wl,--end-group -nostdlib
# Compilation tools
CC = $(CROSS_COMPILE)gcc
@@ -87,42 +72,8 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
GDB = $(CROSS_COMPILE)gdb
NM = $(CROSS_COMPILE)nm
# Flags
INCLUDES_USB = -Iatmel_softpack_libraries/usb/include
INCLUDES = -Iinclude_board -Iinclude_sam3s -Iinclude -Isrc_simtrace
INCLUDES += -Icmsis
INCLUDES += $(INCLUDES_USB)
CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wimplicit-int #-Wformat=2
CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses
CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs #-Wunused
CFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef
CFLAGS += -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings
CFLAGS += -Wsign-compare -Waggregate-return
CFLAGS += -Wformat=0
CFLAGS += -Wmissing-format-attribute -Wno-deprecated-declarations
CFLAGS += #-Wpacked
CFLAGS += -Wredundant-decls -Wnested-externs -Winline #-Wlong-long
CFLAGS += -Wunreachable-code
CFLAGS += -Wcast-align
CFLAGS += -std=c11
CFLAGS += -Wmissing-noreturn
#CFLAGS += -Wconversion
CFLAGS += -Wno-unused-but-set-variable -Wno-unused-variable
CFLAGS += -Wno-suggest-attribute=noreturn
# To reduce application size use only integer printf function.
CFLAGS += -Dprintf=iprintf
# -mlong-calls -Wall
#CFLAGS += -save-temps -fverbose-asm
#CFLAGS += -Wa,-a,-ad
CFLAGS += --param max-inline-insns-single=500 -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)
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)
#LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats
TOP=..
GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarvers)
#-------------------------------------------------------------------------------
# Files
@@ -130,17 +81,97 @@ LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-secti
# Directories where source files can be found
USB_PATHS = $(AT91LIB_USB_CORE_PATH) $(AT91LIB_USB_COMMON_CORE_PATH)
VPATH += src_board src_sam3s cmsis $(USB_PATHS) src_simtrace
USB_PATHS = $(AT91LIB_USB_CORE_PATH) $(AT91LIB_USB_DFU_PATH) $(AT91LIB_USB_COMMON_CORE_PATH)
VPATH += $(USB_PATHS)
VPATH += $(AT91LIB)/libchip_sam3s/source/ $(AT91LIB)/libchip_sam3s/cmsis
VPATH += libboard/common/source libboard/$(BOARD)/source
VPATH += libcommon/source
VPATH += libosmocore/source
VPATH += apps/$(APP)
# Objects built from C source files
C_CMSIS = core_cm3.o
C_LOWLEVEL = board_cstartup_gnu.o board_lowlevel.o syscalls.o exceptions.o
C_LIBLEVEL = spi.o pio.o pmc.o usart.o pio_it.o pio_capture.o uart_console.o iso7816_4.o wdt.o led.o tc.o
C_CCID = cciddriver.o USBD.o USBDDriver.o USBD_HAL.o USBRequests.o USBDCallbacks.o USBDescriptors.o USBDDriverCallbacks.o
C_SIMTRACE = simtrace_iso7816.o usb.o ccid.o sniffer.o phone.o mitm.o ringbuffer.o host_communication.o #iso7816_uart.o
C_APPLEVEL = main.o
C_OBJECTS = $(C_CMSIS) $(C_LOWLEVEL) $(C_LIBLEVEL) $(C_APPLEVEL) $(C_CCID) $(C_SIMTRACE)
C_OSMOCORE = $(notdir $(wildcard libosmocore/source/*.c))
C_LIBCHIP = $(notdir $(wildcard $(AT91LIB)/libchip_sam3s/source/*.c) $(wildcard $(AT91LIB)/libchip_sam3s/cmsis/*.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_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_BOARD = $(notdir $(wildcard libboard/common/source/*.c))
C_BOARD += $(notdir $(wildcard libboard/$(BOARD)/source/*.c))
C_APPLEVEL = $(notdir $(wildcard apps/$(APP)/*.c))
C_FILES = $(C_OSMOCORE) $(C_LIBCHIP) $(C_LIBUSB) $(C_LIBCOMMON) $(C_BOARD) $(C_APPLEVEL)
-include apps/$(APP)/Makefile
C_OBJECTS = $(C_FILES:%.c=%.o)
# Trace level used for compilation
# (can be overriden 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 ?= 4
DEBUG_PHONE_SNIFF?=0
#CFLAGS+=-DUSB_NO_DEBUG=1
# Optimization level, put in comment for debugging
OPTIMIZATION ?= -Os
# Flags
INCLUDES_USB = -I$(AT91LIB)/usb/include -I$(AT91LIB)
INCLUDES = $(INCLUDES_USB)
INCLUDES += -I$(AT91LIB)/libchip_sam3s -I$(AT91LIB)/libchip_sam3s/include
INCLUDES += -I$(AT91LIB)/libchip_sam3s/cmsis
INCLUDES += -Ilibboard/common/include -Ilibboard/$(BOARD)/include
INCLUDES += -Ilibcommon/include
INCLUDES += -Ilibosmocore/include
INCLUDES += -Isrc_simtrace -Iinclude
INCLUDES += -Iapps/$(APP)
CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wimplicit-int #-Wformat=2
CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses
CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs #-Wunused
CFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal #-Wundef
CFLAGS += -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings
CFLAGS += -Waggregate-return #-Wsign-compare
CFLAGS += -Wformat=0
CFLAGS += -Wmissing-format-attribute -Wno-deprecated-declarations
CFLAGS += #-Wpacked
CFLAGS += -Wredundant-decls -Wnested-externs #-Winline -Wlong-long
CFLAGS += -Wunreachable-code
#CFLAGS += -Wcast-align
#CFLAGS += -std=c11
CFLAGS += -Wmissing-noreturn
#CFLAGS += -Wconversion
CFLAGS += -Wno-unused-but-set-variable -Wno-unused-variable
CFLAGS += -Wno-suggest-attribute=noreturn
# -mlong-calls -Wall
#CFLAGS += -save-temps -fverbose-asm
#CFLAGS += -Wa,-a,-ad
CFLAGS += -D__ARM
CFLAGS += --param max-inline-insns-single=500 -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 += -DGIT_VERSION=\"$(GIT_VERSION)\"
CFLAGS += -DBOARD=\"$(BOARD)\" -DBOARD_$(BOARD)
CFLAGS += -DAPPLICATION=\"$(APP)\" -DAPPLICATION_$(APP)
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)
#LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats
# Append OBJ and BIN directories to output filename
OUTPUT := $(BIN)/$(OUTPUT)
@@ -149,28 +180,43 @@ OUTPUT := $(BIN)/$(OUTPUT)
# Rules
#-------------------------------------------------------------------------------
all: $(BIN) $(OBJ) $(MEMORIES)
all: apps/$(APP)/usb_strings_generated.h $(BIN) $(OBJ) $(MEMORIES)
combined: $(OUTPUT)-combined.bin
$(BIN)/$(BOARD)-dfu-flash-padded.bin: $(BIN)/$(BOARD)-dfu-flash.bin
dd if=/dev/zero bs=16384 count=1 of=$@
dd if=$< conv=notrunc of=$@
$(OUTPUT)-combined.bin: $(BIN)/$(BOARD)-dfu-flash-padded.bin $(OUTPUT)-dfu.bin
cat $^ > $@
$(BIN) $(OBJ):
mkdir $@
mkdir -p $@
usbstring/usbstring: usbstring/usbstring.c
gcc $^ -o $@
apps/$(APP)/usb_strings_generated.h: apps/$(APP)/usb_strings.txt usbstring/usbstring
cat $< | usbstring/usbstring > $@
define RULES
C_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(C_OBJECTS))
ASM_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(ASM_OBJECTS))
$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1))
@$(CC) $(LDFLAGS) $(LD_OPTIONAL) -T"$$@.ld" -Wl,-Map,$(OUTPUT)-$$@.map -o $(OUTPUT)-$$@.elf $$^ $(LIBS)
@$(CC) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/$$@.ld" -Wl,-Map,$(OUTPUT)-$$@.map -o $(OUTPUT)-$$@.elf $$^ $(LIBS)
@$(NM) $(OUTPUT)-$$@.elf >$(OUTPUT)-$$@.elf.txt
@$(OBJCOPY) -O binary $(OUTPUT)-$$@.elf $(OUTPUT)-$$@.bin
@$(SIZE) $$^ $(OUTPUT)-$$@.elf
$$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN)
@echo [COMPILING $$<]
@$(CC) $(CFLAGS) -D$(1) -Wa,-ahlms=$(BIN)/$$*.lst -c -o $$@ $$<
@$(CC) $(CFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -Wa,-ahlms=$(BIN)/$$*.lst -c -o $$@ $$<
$$(ASM_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.S Makefile $(OBJ) $(BIN)
@echo [ASSEMBLING $$@]
@$(CC) $(ASFLAGS) -D$(1) -c -o $$@ $$<
@$(CC) $(ASFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -c -o $$@ $$<
debug_$(1): $(1)
$(GDB) -x "$(BOARD_LIB)/resources/gcc/$(BOARD)_$(1).gdb" -ex "reset" -readnow -se $(OUTPUT)-$(1).elf
@@ -187,7 +233,4 @@ log:
lsof $(SERIAL) && echo "log is already opened" || ( sed -u "s/\r//" $(SERIAL) | ts )
clean:
-rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst
rmbak:
-rm *~ $(BIN)/*~
-rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst `find . -name \*.p`

81
firmware/README.txt Normal file
View File

@@ -0,0 +1,81 @@
This is the source code for SIMtrace 2 firmwares.
= Hardware
== Micro-Controller
The firmware is for Microchip (formerly Atmel) ATSAM3S4B micro-controllers (MCU).
Product page: https://www.microchip.com/wwwproducts/en/ATSAM3S4B
Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-6500-32-bit-Cortex-M3-Microcontroller-SAM3S4-SAM3S2-SAM3S1_Datasheet.pdf
Note: The SAM3S is now not recommended for new designs.
It can be replaced by the pin-compatible SAM4S.
The MCU can be specified using the environment variable `CHIP` (set to `sam3s4` per default) for future MCU support.
== Boards
The SIMtrace 2 firmware supports multiple boards.
A board defines a given circuit board.
While compiling the firmware, set the target board using the `BOARD` environment variable (set to `qmod` per default).
The supported boards correspond to sub-folders under `libboard`.
Current boards supported are:
* `simtrace`: The good old Osmocom SIMtrace PCB with SAM3 instead of SAM7, open hardware.
* `qmod`: A sysmocom-proprietary quad mPCIe carrier board, publicly available
* `owhw`: An undisclosed sysmocom-internal board, not publicly available
= Firmware
== Library
The firmware uses the manufacturer provided Software Package (SoftPack) micro-controller library.
The original library is available at https://www.microchip.com/design-centers/32-bit/softpacks/legacy-softpacks .
Version 2.1 from 2001 is used: http://ww1.microchip.com/downloads/en/DeviceDoc/SAM3S_softpack_2.1_for_CodeSourcery_2010q1.zip
The SIMtrace 2 project uses the `libboard_sam3s-ek`, `libchip_sam3s`, and `usb` sub-libraries, saved in `atmel_softpack_libraries` (with local modifications).
Note: SoftPack is the legacy micro-controller library.
This library is now replaced by the Advanced Software Framework (ASF): https://www.microchip.com/avr-support/advanced-software-framework-(asf) .
The SAM3S ASF documentation is available at http://asf.atmel.com/docs/latest/sam3s/html/index.html .
== Applications
An application is a specific piece of software with given functionality.
While compiling the firmware, set the target application using the `APP` environment variable (set to `dfu` per default).
The supported applications correspond to sub-folder under `apps`.
Current applications supported are:
* `dfu`: The USB DFU bootloader to flash further main appliction firmwares.
* `ccid`: To use SIMtrace 2 as USB CCID smartcard reader.
* `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)
* `triple_play`: To support the three previous functionalities, using USB configurations.
== Memories
Firmwares can be run from several memory locations:
* flash: Run natively from start of flash memory
* dfu: Run after a DFU bootloader from an offset after the first 16k of flash (the first 16k are reserved for the bootloader)
* ram: Run from within the RAM of the chip, downloaded via JTAG/SWD
== Building
A given firmware build is made for a specific combination of an application `APP` running in a certain memory `MEM` on a given board `BOARD`.
When building using `make`, set the target application using the `APP` environment variable and target board using the `BOARD` environment variable, e.g.:
* make APP=cardem BOARD=qmod
* make APP=dfu BOARD=qmod
The Makefile will create output files in the format: `bin/$(BOARD)-$(APP)-$(MEM).{elf,bin}`
The level of debug messages can be altered at compile time:
```
$ make TRACE_LEVEL=4
```
Accepted values: 0 (NO_TRACE) to 5 (DEBUG)
= Flashing
To flash a firmware image follow the instructions provided in the [wiki](https://projects.osmocom.org/projects/simtrace2/wiki/).

22
firmware/TODO.txt Normal file
View File

@@ -0,0 +1,22 @@
== Important DFU topics / reliability ==
x some kind of DFU fallback / boot cycle counter ?
* CRC check of image before attempting to execute it ?
x Keep WDT running while in DFU or app
? USB control request for flash erase
== QModem related ==
x new vendor/product ID for hub and SAM3s
* board-specfic string descriptors
* re-mapping of USB ports in EEPROM
== Lower Priority ==
* unique serial number in iSerial?
* printing of banner from generic function
* board_main_top() automatically before calling main()
x compile-time USB string generation
* shared USB strings for DFU and runtime
* version detection voltage ranges
* locking of bootloader pages?
* debug console command for switch-to-dfu
* read CPU reset cause (and time?) via USB

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 tc_etu.c usb.c

209
firmware/apps/cardem/main.c Normal file
View File

@@ -0,0 +1,209 @@
// FIXME: Copyright license here
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "board.h"
#include "simtrace.h"
#include "utils.h"
#include <osmocom/core/timer.h>
unsigned int g_unique_id[4];
/*------------------------------------------------------------------------------
* 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 USART1 */
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,
},
#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;
led_init();
led_blink(LED_RED, BLINK_3O_5F);
/* Enable watchdog for 500ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(500) << 16) | WDT_GetPeriod(500));
PIO_InitializeInterrupts(0);
EEFC_ReadUniqueID(g_unique_id);
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();
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 < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]);
++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
SIMtrace 2 compatible device
SIMtrace Sniffer
SIMtrace CCID
SIMtrace Phone
SIMtrace MITM
CardEmulator Modem 1
CardEmulator Modem 2
CardEmulator Modem 3
CardEmulator Modem 4

View File

View File

@@ -0,0 +1,12 @@
C_FILES += $(C_LIBUSB_DFU)
# Trace level used for compilation
# (can be overriden 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

295
firmware/apps/dfu/main.c Normal file
View File

@@ -0,0 +1,295 @@
#include "board.h"
#include "utils.h"
#include "usb/device/dfu/dfu.h"
#include "usb/common/dfu/usb_dfu.h"
#include "manifest.h"
#include <osmocom/core/timer.h>
#define ALTIF_RAM 0
#define ALTIF_FLASH 1
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;
/* 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
*----------------------------------------------------------------------------*/
#define RAM_ADDR(offset) (IRAM_ADDR + BOARD_DFU_RAM_SIZE + offset)
#define FLASH_ADDR(offset) (IFLASH_ADDR + BOARD_DFU_BOOT_SIZE + offset)
#define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE)
#define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE)
/* incoming call-back: Host has transferred 'len' bytes (stored at
* 'data'), which we shall write to 'offset' into the partition
* associated with 'altif'. Guaranted to be less than
* BOARD_DFU_PAGE_SIZE */
int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
uint8_t *data, unsigned int len)
{
uint32_t addr;
unsigned int i;
int rc;
/* address of the last allocated variable on the stack */
uint32_t stack_addr = (uint32_t)&rc;
/* kick the dog to have enough time to flash */
if (watchdog_configured) {
WDT_Restart(WDT);
}
printf("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len);
#ifdef PINS_LEDS
PIO_Clear(&pinsLeds[LED_NUM_RED]);
#endif
switch (altif) {
case ALTIF_RAM:
addr = RAM_ADDR(offset);
if (addr < IRAM_ADDR || addr + len >= IRAM_ADDR + IRAM_SIZE || addr + len >= stack_addr) {
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
rc = DFU_RET_STALL;
break;
}
memcpy((void *)addr, data, len);
rc = DFU_RET_ZLP;
break;
case ALTIF_FLASH:
addr = FLASH_ADDR(offset);
if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + IFLASH_SIZE) {
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
rc = DFU_RET_STALL;
break;
}
rc = FLASHD_Unlock(addr, addr + len, 0, 0);
if (rc != 0) {
TRACE_ERROR("DFU download flash unlock failed\n\r");
rc = DFU_RET_STALL;
break;
}
rc = FLASHD_Write(addr, data, len);
if (rc != 0) {
TRACE_ERROR("DFU download flash erase failed\n\r");
rc = DFU_RET_STALL;
break;
}
for (i = 0; i < len; i++) {
if (((uint8_t*)addr)[i]!=data[i]) {
TRACE_ERROR("DFU download flash data written not correct\n\r");
rc = DFU_RET_STALL;
break;
}
}
rc = DFU_RET_ZLP;
break;
default:
/* FIXME: set error codes */
TRACE_ERROR("DFU download for unknown AltIf %d\n\r", altif);
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
* starting from 'offset' of the firmware * associated with partition
* 'altif' */
int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
uint8_t *data, unsigned int req_len)
{
uint32_t addr;
printf("upload(altif=%u, offset=%u, len=%u)", altif, offset, req_len);
switch (altif) {
case ALTIF_RAM:
addr = RAM_ADDR(offset);
if (addr > IRAM_ADDR + IRAM_SIZE) {
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return -1;
}
if ((uint8_t *)addr + req_len > IRAM_END)
req_len = IRAM_END - (uint8_t *)addr;
memcpy(data, (void *)addr, req_len);
break;
case ALTIF_FLASH:
addr = FLASH_ADDR(offset);
if (addr > IFLASH_ADDR + IFLASH_SIZE) {
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return -1;
}
if ((uint8_t *)addr + req_len > IFLASH_END)
req_len = IFLASH_END - (uint8_t *)addr;
memcpy(data, (void *)addr, req_len);
break;
default:
TRACE_ERROR("DFU upload for unknown AltIf %d\n\r", altif);
/* FIXME: set error codes */
return -1;
}
printf("=%u\n\r", req_len);
return req_len;
}
/* can be overridden by board specific code, e.g. by pushbutton */
WEAK int board_override_enter_dfu(void)
{
return 0;
}
/* using this function we can determine if we should enter DFU mode
* during boot, or if we should proceed towards the application/runtime */
int USBDFU_OverrideEnterDFU(void)
{
uint32_t *app_part = (uint32_t *)FLASH_ADDR(0);
/* If the loopback jumper is set, we enter DFU mode */
if (board_override_enter_dfu())
return 1;
/* if the first word of the application partition doesn't look
* like a stack pointer (i.e. point to RAM), enter DFU mode */
if ((app_part[0] < IRAM_ADDR) ||
((uint8_t *)app_part[0] > IRAM_END))
return 1;
/* if the second word of the application partition doesn't look
* like a function from flash (reset vector), enter DFU mode */
if (((uint32_t *)app_part[1] < app_part) ||
((uint8_t *)app_part[1] > IFLASH_END))
return 1;
return 0;
}
/* 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;
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;
#ifdef PINS_LEDS
/* Configure LED */
PIO_Configure(pinsLeds, sizeof(pinsLeds));
PIO_Set(&pinsLeds[LED_NUM_RED]);
PIO_Clear(&pinsLeds[LED_NUM_GREEN]);
#endif
/* Enable watchdog for 500ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(500) << 16) | WDT_GetPeriod(500));
PIO_InitializeInterrupts(0);
EEFC_ReadUniqueID(g_unique_id);
printf("\n\r\n\r"
"=============================================================================\n\r"
"DFU bootloader %s for board %s (C) 2010-2017 by Harald Welte\n\r"
"=============================================================================\n\r",
manifest_revision, manifest_board);
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", reset_cause);
/* clear g_dfu on power-up reset */
if (reset_cause == 0)
memset(g_dfu, 0, sizeof(*g_dfu));
board_main_top();
TRACE_INFO("USB init...\n\r");
/* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */
const Pin usb_dp_pullup = PIN_USB_PULLUP;
PIO_Configure(&usb_dp_pullup, 1);
PIO_Set(&usb_dp_pullup);
mdelay(15);
PIO_Clear(&usb_dp_pullup);
USBDFU_Initialize(&dfu_descriptors);
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
WDT_Restart(WDT);
check_exec_dbg_cmd();
#if 1
if (i >= MAX_USB_ITER * 3) {
TRACE_ERROR("Resetting board (USB could "
"not be configured)\n\r");
USBD_Disconnect();
NVIC_SystemReset();
}
#endif
i++;
}
/* Initialize the flash to be able to write it, using the IAP ROM code */
FLASHD_Initialize(BOARD_MCK, 1);
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();
#if 0
osmo_timers_prepare();
osmo_timers_update();
#endif
if (USBD_GetState() < USBD_STATE_CONFIGURED) {
if (isUsbConnected) {
isUsbConnected = 0;
}
} else if (isUsbConnected == 0) {
TRACE_INFO("USB is now configured\n\r");
isUsbConnected = 1;
}
}
}

View File

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

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 tc_etu.c usb.c

268
firmware/apps/trace/main.c Normal file
View File

@@ -0,0 +1,268 @@
/*
* (C) 2010-2017 by Harald Welte <hwelte@sysmocom.de>
* (C) 2018 by Kevin Redon <kredon@sysmocom.de>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "board.h"
#include "simtrace.h"
#include "utils.h"
#include "osmocom/core/timer.h"
unsigned int g_unique_id[4];
/*------------------------------------------------------------------------------
* 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);
if (cfgnum >= sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) {
TRACE_FATAL_WP("no functions defined for configuration %d\n\r", 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, green = activity */
led_init();
led_blink(LED_RED, BLINK_ALWAYS_ON);
led_blink(LED_GREEN, BLINK_ALWAYS_OFF);
/* 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);
EEFC_ReadUniqueID(g_unique_id);
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);
TRACE_INFO("USB configuration used: %d\n\r", simtrace_config);
board_main_top();
TRACE_INFO("USB init...\n\r");
SIMtrace_USB_Initialize();
TRACE_INFO_WP("USBD_Inited\n\r");
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 < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]); ++i) {
if (config_func_ptrs[i].configure) {
config_func_ptrs[i].configure();
} else {
TRACE_WARNING("no configure function defined for configuration %d\n\r", i);
}
}
TRACE_INFO("cfg %d\n\r", simtrace_config);
TRACE_INFO("calling init of config %u...\n\r", simtrace_config);
if (simtrace_config >= sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) {
TRACE_ERROR("no functions defined for configuration %d\n\r", simtrace_config);
} else {
if (config_func_ptrs[simtrace_config].init) {
config_func_ptrs[simtrace_config].init();
} else {
TRACE_ERROR("no init function defined for configuration %d\n\r", simtrace_config);
}
}
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);
if (last_simtrace_config < sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) {
if (config_func_ptrs[last_simtrace_config].exit) {
config_func_ptrs[last_simtrace_config].exit();
} else {
TRACE_WARNING("exit not defined for configuration %d\n\r", last_simtrace_config);
}
} else {
TRACE_ERROR("no functions defined for configuration %d\n\r", last_simtrace_config);
}
if (simtrace_config < sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) {
if (config_func_ptrs[simtrace_config].init) {
config_func_ptrs[simtrace_config].init();
} else {
TRACE_WARNING("init not defined for configuration %d\n\r", simtrace_config);
}
} else {
TRACE_FATAL("no functions defined for configuration %d\n\r", simtrace_config);
}
last_simtrace_config = simtrace_config;
} else {
if (config_func_ptrs[simtrace_config].run) {
config_func_ptrs[simtrace_config].run();
} else {
TRACE_ERROR("run not defined for configuration %d\n\r", simtrace_config);
}
}
}
}

View File

@@ -0,0 +1,10 @@
sysmocom - s.f.m.c. GmbH
SIMtrace 2 compatible device
SIMtrace Sniffer
SIMtrace CCID
SIMtrace Phone
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 iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c

View File

@@ -0,0 +1,208 @@
// FIXME: Copyright license here
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "board.h"
#include "simtrace.h"
#include "utils.h"
#include "req_ctx.h"
#include <osmocom/core/timer.h>
unsigned int g_unique_id[4];
/*------------------------------------------------------------------------------
* 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 USART1 */
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,
},
#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)
{
config_func_ptrs[simtrace_config].usart1_irq();
}
void USART0_IrqHandler(void)
{
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;
LED_Configure(LED_NUM_RED);
LED_Configure(LED_NUM_GREEN);
LED_Set(LED_NUM_RED);
/* Disable watchdog */
WDT_Disable(WDT);
req_ctx_init();
PIO_InitializeInterrupts(0);
EEFC_ReadUniqueID(g_unique_id);
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();
TRACE_INFO("USB init...\r\n");
SIMtrace_USB_Initialize();
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
check_exec_dbg_cmd();
#if 0
if (i >= MAX_USB_ITER * 3) {
TRACE_ERROR("Resetting board (USB could "
"not be configured)\r\n");
USBD_Disconnect();
NVIC_SystemReset();
}
#endif
i++;
}
TRACE_INFO("calling configure of all configurations...\r\n");
for (i = 1; i < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]);
++i) {
if (config_func_ptrs[i].configure)
config_func_ptrs[i].configure();
}
TRACE_INFO("calling init of config %u...\r\n", simtrace_config);
config_func_ptrs[simtrace_config].init();
last_simtrace_config = simtrace_config;
TRACE_INFO("entering main loop...\r\n");
while (1) {
#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\r\n");
LED_Set(LED_NUM_GREEN);
LED_Clear(LED_NUM_RED);
isUsbConnected = 1;
}
if (last_simtrace_config != simtrace_config) {
TRACE_INFO("USB config chg %u -> %u\r\n",
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

@@ -52,5 +52,8 @@
#include "trace.h"
#include "wdt.h"
#include "unique_id.h"
#include "efc.h"
#include "flashd.h"
#endif /* _LIB_SAM3S_ */

View File

@@ -0,0 +1,113 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \section Purpose
*
* Interface for configuration the Enhanced Embedded Flash Controller (EEFC) peripheral.
*
* \section Usage
*
* -# Enable/disable %flash ready interrupt sources using EFC_EnableFrdyIt()
* and EFC_DisableFrdyIt().
* -# Translates the given address into which EEFC, page and offset values
* for difference density %flash memory using EFC_TranslateAddress().
* -# Computes the address of a %flash access given the EFC, page and offset
* for difference density %flash memory using EFC_ComputeAddress().
* -# Start the executing command with EFC_StartCommand()
* -# Retrieve the current status of the EFC using EFC_GetStatus().
* -# Retrieve the result of the last executed command with EFC_GetResult().
*/
#ifndef _EEFC_
#define _EEFC_
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <stdint.h>
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
/* EFC command */
#define EFC_FCMD_GETD 0x00
#define EFC_FCMD_WP 0x01
#define EFC_FCMD_WPL 0x02
#define EFC_FCMD_EWP 0x03
#define EFC_FCMD_EWPL 0x04
#define EFC_FCMD_EA 0x05
#define EFC_FCMD_SLB 0x08
#define EFC_FCMD_CLB 0x09
#define EFC_FCMD_GLB 0x0A
#define EFC_FCMD_SFB 0x0B
#define EFC_FCMD_CFB 0x0C
#define EFC_FCMD_GFB 0x0D
#define EFC_FCMD_STUI 0x0E /* Start unique ID */
#define EFC_FCMD_SPUI 0x0F /* Stop unique ID */
/* The IAP function entry addreass */
#define CHIP_FLASH_IAP_ADDRESS (0x00800008)
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
extern void EFC_EnableFrdyIt( Efc* efc ) ;
extern void EFC_DisableFrdyIt( Efc* efc ) ;
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_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 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_GetResult( Efc* efc ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _EEFC_ */

View File

@@ -1,72 +1,79 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \section Purpose
*
* Small set of functions for simple and portable LED usage.
*
* \section Usage
*
* -# Configure one or more LEDs using LED_Configure and
* LED_ConfigureAll.
* -# Set, clear and toggle LEDs using LED_Set, LED_Clear and
* LED_Toggle.
*
* LEDs are numbered starting from 0; the number of LEDs depend on the
* board being used. All the functions defined here will compile properly
* regardless of whether the LED is defined or not; they will simply
* return 0 when a LED which does not exist is given as an argument.
* Also, these functions take into account how each LED is connected on to
* board; thus, \ref LED_Set might change the level on the corresponding pin
* to 0 or 1, but it will always light the LED on; same thing for the other
* methods.
*/
#ifndef _LED_
#define _LED_
#include <stdint.h>
//------------------------------------------------------------------------------
// Global Functions
//------------------------------------------------------------------------------
extern uint32_t LED_Configure( uint32_t dwLed ) ;
extern uint32_t LED_Set( uint32_t dwLed ) ;
extern uint32_t LED_Clear( uint32_t dwLed ) ;
extern uint32_t LED_Toggle( uint32_t dwLed ) ;
#endif /* #ifndef LED_H */
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* The flash driver provides the unified interface for flash program operations.
*
*/
#ifndef _FLASHD_
#define _FLASHD_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
extern void FLASHD_Initialize( uint32_t dwMCk, uint32_t dwUseIAP ) ;
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_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_IsLocked( uint32_t dwStart, uint32_t dwEnd ) ;
extern uint32_t FLASHD_SetGPNVM( uint8_t gpnvm ) ;
extern uint32_t FLASHD_ClearGPNVM( uint8_t gpnvm ) ;
extern uint32_t FLASHD_IsGPNVMSet( uint8_t gpnvm ) ;
#define FLASHD_IsSecurityBitSet() FLASHD_IsGPNVMSet( 0 )
#define FLASHD_SetSecurityBit() FLASHD_SetGPNVM( 0 )
extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _FLASHD_ */

View File

@@ -176,7 +176,7 @@ extern void TRACE_CONFIGURE( uint32_t dwBaudRate, uint32_t dwMCk ) ;
/* Trace compilation depends on TRACE_LEVEL value */
#if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
#define TRACE_DEBUG(...) { printf("-D- " __VA_ARGS__); printf("(%s func. %s)\n\r", __FILE__, __FUNCTION__); }
#define TRACE_DEBUG(...) { printf("-D- " __VA_ARGS__); }
#define TRACE_DEBUG_WP(...) { printf(__VA_ARGS__); }
#else
#define TRACE_DEBUG(...) { }

View File

@@ -0,0 +1,3 @@
#pragma once
void EEFC_ReadUniqueID(unsigned int *pdwUniqueID);

View File

@@ -45,8 +45,14 @@
* Headers
*---------------------------------------------------------------------------*/
#ifdef TRACE_LEVEL
#undef TRACE_LEVEL
#endif
#define TRACE_LEVEL TRACE_LEVEL_WARNING
#include "chip.h"
#include "USBD_HAL.h"
#include <usb/device/dfu/dfu.h>
#include <stdbool.h>
#include <stdint.h>
@@ -1156,6 +1162,22 @@ void USBD_IrqHandler(void)
else if ((status & UDP_ISR_ENDBUSRES) != 0) {
TRACE_INFO_WP("EoBRes ");
#if defined(BOARD_USB_DFU)
#if defined(APPLICATION_dfu)
/* if we are currently in the DFU bootloader, and we are beyond
* the MANIFEST stage, we shall switch to the normal
* application */
if (g_dfu->past_manifest)
USBDFU_SwitchToApp();
#else
/* if we are currently in the main application, and we are in
* appDETACH state, switch into the DFU bootloader */
if (g_dfu->state == DFU_STATE_appDETACH)
DFURT_SwitchToDFU();
#endif /* APPLICATION_dfu */
#endif /* BOARD_USB_DFU */
/* Flush and enable the Suspend interrupt */
UDP->UDP_ICR = UDP_ICR_WAKEUP | UDP_ICR_RXRSM | UDP_ICR_RXSUSP;
UDP->UDP_IER = UDP_IER_RXSUSP;

View File

@@ -0,0 +1,290 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup efc_module Working with EEFC
* The EEFC driver provides the interface to configure and use the EEFC
* peripheral.
*
* 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.
*
* It offers a function to send flash command to EEFC and waits for the
* flash to be ready.
*
* To send flash command, the user could do in either of following way:
* <ul>
* <li>Write a correct key, command and argument in EEFC_FCR. </li>
* <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>
* <li>Once the command is achieved, it can be detected even by polling EEFC_FSR or interrupt.
* </ul>
*
* 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
* flash address into a page number and vice verse.
*
* For more accurate information, please look at the EEFC section of the
* Datasheet.
*
* Related files :\n
* \ref efc.c\n
* \ref efc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Enhanced Embedded Flash Controller (EEFC).
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include "efc.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Enables the flash ready interrupt source on the EEFC peripheral.
*
* \param efc Pointer to a Efc instance
*/
extern void EFC_EnableFrdyIt( Efc* efc )
{
efc->EEFC_FMR |= EEFC_FMR_FRDY ;
}
/**
* \brief Disables the flash ready interrupt source on the EEFC peripheral.
*
* \param efc Pointer to a Efc instance
*/
extern void EFC_DisableFrdyIt( Efc* efc )
{
efc->EEFC_FMR &= ~((uint32_t)EEFC_FMR_FRDY) ;
}
/**
* \brief Set read/write wait state on the EEFC perpherial.
*
* \param efc Pointer to a Efc instance
* \param cycles the number of wait states in cycle.
*/
extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles )
{
uint32_t dwValue ;
dwValue = efc->EEFC_FMR ;
dwValue &= ~((uint32_t)EEFC_FMR_FWS_Msk) ;
dwValue |= EEFC_FMR_FWS(ucCycles);
efc->EEFC_FMR = dwValue ;
}
/**
* \brief Returns the current status of the EEFC.
*
* \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE).
*
* \param efc Pointer to a Efc instance
*/
extern uint32_t EFC_GetStatus( Efc* efc )
{
return efc->EEFC_FSR ;
}
/**
* \brief Returns the result of the last executed command.
*
* \param efc Pointer to a Efc instance
*/
extern uint32_t EFC_GetResult( Efc* efc )
{
return efc->EEFC_FRR ;
}
/**
* \brief Translates the given address page and offset values.
* \note The resulting values are stored in the provided variables if they are not null.
*
* \param efc Pointer to a Efc instance
* \param address Address to translate.
* \param pPage First page accessed.
* \param pOffset Byte offset in first page.
*/
extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset )
{
Efc *pEfc ;
uint16_t wPage ;
uint16_t wOffset ;
assert( dwAddress >= IFLASH_ADDR ) ;
assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
pEfc = EFC ;
wPage = (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 ) ;
/* Store values */
if ( pEfc )
{
*ppEfc = pEfc ;
}
if ( pwPage )
{
*pwPage = wPage ;
}
if ( pwOffset )
{
*pwOffset = wOffset ;
}
}
/**
* \brief Computes the address of a flash access given the page and offset.
*
* \param efc Pointer to a Efc instance
* \param page Page number.
* \param offset Byte offset inside page.
* \param pAddress Computed address (optional).
*/
extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress )
{
uint32_t dwAddress ;
assert( efc ) ;
assert( wPage <= IFLASH_NB_OF_PAGES ) ;
assert( wOffset < IFLASH_PAGE_SIZE ) ;
/* Compute address */
dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ;
/* Store result */
if ( pdwAddress != NULL )
{
*pdwAddress = dwAddress ;
}
}
/**
* \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.
* \param efc Pointer to a Efc instance
* \param command Command to execute.
* \param argument Command argument (should be 0 if not used).
*/
extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument )
{
/* Check command & argument */
switch ( dwCommand )
{
case EFC_FCMD_WP:
case EFC_FCMD_WPL:
case EFC_FCMD_EWP:
case EFC_FCMD_EWPL:
case EFC_FCMD_SLB:
case EFC_FCMD_CLB:
assert( dwArgument < IFLASH_NB_OF_PAGES ) ;
break ;
case EFC_FCMD_SFB:
case EFC_FCMD_CFB:
assert( dwArgument < 2 ) ;
break;
case EFC_FCMD_GETD:
case EFC_FCMD_EA:
case EFC_FCMD_GLB:
case EFC_FCMD_GFB:
case EFC_FCMD_STUI:
assert( dwArgument == 0 ) ;
break;
default: assert( 0 ) ;
}
/* Start command Embedded flash */
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) ;
}
/**
* \brief Performs the given command and wait until its completion (or an error).
*
* \param efc Pointer to a Efc instance
* \param command Command to perform.
* \param argument Optional command argument.
*
* \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 )
{
if ( dwUseIAP != 0 )
{
/* Pointer on IAP function in ROM */
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( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ;
return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ;
}
else
{
uint32_t dwStatus ;
efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
do
{
dwStatus = efc->EEFC_FSR ;
}
while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ;
return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ;
}
}

View File

@@ -52,6 +52,7 @@
*/
void IrqHandlerNotUsed( void )
{
printf("NotUsed\r\n");
while ( 1 ) ;
}
@@ -60,15 +61,96 @@ void IrqHandlerNotUsed( void )
*/
WEAK void NMI_Handler( void )
{
printf("NMI\r\n");
while ( 1 ) ;
}
/**
* \brief Default HardFault interrupt handler.
*/
struct hardfault_args {
unsigned long r0;
unsigned long r1;
unsigned long r2;
unsigned long r3;
unsigned long r12;
unsigned long lr;
unsigned long pc;
unsigned long psr;
};
void hard_fault_handler_c(struct hardfault_args *args)
{
printf("\r\nHardFault\r\n");
printf("R0=%08x, R1=%08x, R2=%08x, R3=%08x, R12=%08x\r\n",
args->r0, args->r1, args->r2, args->r3, args->r12);
printf("LR[R14]=%08x, PC[R15]=%08x, PSR=%08x\r\n",
args->lr, args->pc, args->psr);
printf("BFAR=%08x, CFSR=%08x, HFSR=%08x\r\n",
SCB->BFAR, SCB->CFSR, SCB->HFSR);
printf("DFSR=%08x, AFSR=%08x, SHCSR=%08x\r\n",
SCB->DFSR, SCB->CFSR, SCB->SHCSR);
if (SCB->HFSR & 0x40000000)
printf("FORCED ");
if (SCB->HFSR & 0x00000002)
printf("VECTTBL ");
uint32_t ufsr = SCB->CFSR >> 16;
if (ufsr & 0x0200)
printf("DIVBYZERO ");
if (ufsr & 0x0100)
printf("UNALIGNED ");
if (ufsr & 0x0008)
printf("NOCP ");
if (ufsr & 0x0004)
printf("INVPC ");
if (ufsr & 0x0002)
printf("INVSTATE ");
if (ufsr & 0x0001)
printf("UNDEFINSTR ");
uint32_t bfsr = (SCB->CFSR >> 8) & 0xff;
if (bfsr & 0x80)
printf("BFARVALID ");
if (bfsr & 0x10)
printf("STKERR ");
if (bfsr & 0x08)
printf("UNSTKERR ");
if (bfsr & 0x04)
printf("IMPRECISERR ");
if (bfsr & 0x02)
printf("PRECISERR ");
if (bfsr & 0x01)
printf("IBUSERR ");
uint32_t mmfsr = (SCB->CFSR & 0xff);
if (mmfsr & 0x80)
printf("MMARVALID ");
if (mmfsr & 0x10)
printf("MSTKERR ");
if (mmfsr & 0x08)
printf("MUNSTKERR ");
if (mmfsr & 0x02)
printf("DACCVIOL ");
if (mmfsr & 0x01)
printf("IACCVIOL ");
while ( 1 ) ;
}
__attribute__((naked))
WEAK void HardFault_Handler( void )
{
while ( 1 ) ;
__asm volatile(
".syntax unified \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
//" ldr r1, [r0, #24] \n"
" b hard_fault_handler_c\n"
".syntax divided \n");
}
/**
@@ -76,6 +158,7 @@ WEAK void HardFault_Handler( void )
*/
WEAK void MemManage_Handler( void )
{
printf("MemManage\r\n");
while ( 1 ) ;
}
@@ -84,6 +167,7 @@ WEAK void MemManage_Handler( void )
*/
WEAK void BusFault_Handler( void )
{
printf("BusFault\r\n");
while ( 1 ) ;
}
@@ -92,6 +176,7 @@ WEAK void BusFault_Handler( void )
*/
WEAK void UsageFault_Handler( void )
{
printf("UsageFault\r\n");
while ( 1 ) ;
}
@@ -100,6 +185,7 @@ WEAK void UsageFault_Handler( void )
*/
WEAK void SVC_Handler( void )
{
printf("SVC\r\n");
while ( 1 ) ;
}
@@ -108,6 +194,7 @@ WEAK void SVC_Handler( void )
*/
WEAK void DebugMon_Handler( void )
{
printf("DebugMon\r\n");
while ( 1 ) ;
}
@@ -116,6 +203,7 @@ WEAK void DebugMon_Handler( void )
*/
WEAK void PendSV_Handler( void )
{
printf("PendSV\r\n");
while ( 1 ) ;
}
@@ -124,6 +212,7 @@ WEAK void PendSV_Handler( void )
*/
WEAK void SysTick_Handler( void )
{
printf("SysTick\r\n");
while ( 1 ) ;
}
@@ -132,6 +221,7 @@ WEAK void SysTick_Handler( void )
*/
WEAK void SUPC_IrqHandler( void )
{
printf("SUPC\r\n");
while ( 1 ) ;
}
@@ -140,6 +230,7 @@ WEAK void SUPC_IrqHandler( void )
*/
WEAK void RSTC_IrqHandler( void )
{
printf("RSTC\r\n");
while ( 1 ) ;
}
@@ -148,6 +239,7 @@ WEAK void RSTC_IrqHandler( void )
*/
WEAK void RTC_IrqHandler( void )
{
printf("RTC\r\n");
while ( 1 ) ;
}
@@ -156,6 +248,7 @@ WEAK void RTC_IrqHandler( void )
*/
WEAK void RTT_IrqHandler( void )
{
printf("RTT\r\n");
while ( 1 ) ;
}
@@ -164,6 +257,7 @@ WEAK void RTT_IrqHandler( void )
*/
WEAK void WDT_IrqHandler( void )
{
printf("WDT\r\n");
while ( 1 ) ;
}
@@ -172,6 +266,7 @@ WEAK void WDT_IrqHandler( void )
*/
WEAK void PMC_IrqHandler( void )
{
printf("PMC\r\n");
while ( 1 ) ;
}
@@ -180,6 +275,7 @@ WEAK void PMC_IrqHandler( void )
*/
WEAK void EEFC_IrqHandler( void )
{
printf("EEFC\r\n");
while ( 1 ) ;
}
@@ -188,6 +284,7 @@ WEAK void EEFC_IrqHandler( void )
*/
WEAK void UART0_IrqHandler( void )
{
printf("UART0\r\n");
while ( 1 ) ;
}
@@ -196,6 +293,7 @@ WEAK void UART0_IrqHandler( void )
*/
WEAK void UART1_IrqHandler( void )
{
printf("UART1\r\n");
while ( 1 ) ;
}
@@ -204,6 +302,7 @@ WEAK void UART1_IrqHandler( void )
*/
WEAK void SMC_IrqHandler( void )
{
printf("SMC\r\n");
while ( 1 ) ;
}
@@ -212,6 +311,7 @@ WEAK void SMC_IrqHandler( void )
*/
WEAK void PIOA_IrqHandler( void )
{
printf("PIOA\r\n");
while ( 1 ) ;
}
@@ -220,6 +320,7 @@ WEAK void PIOA_IrqHandler( void )
*/
WEAK void PIOB_IrqHandler( void )
{
printf("PIOB\r\n");
while ( 1 ) ;
}
@@ -228,6 +329,7 @@ WEAK void PIOB_IrqHandler( void )
*/
WEAK void PIOC_IrqHandler( void )
{
printf("PIOC\r\n");
while ( 1 ) ;
}
@@ -236,6 +338,7 @@ WEAK void PIOC_IrqHandler( void )
*/
WEAK void USART0_IrqHandler( void )
{
printf("USART0\r\n");
while ( 1 ) ;
}
@@ -244,6 +347,7 @@ WEAK void USART0_IrqHandler( void )
*/
WEAK void USART1_IrqHandler( void )
{
printf("USART1\r\n");
while ( 1 ) ;
}
@@ -252,6 +356,7 @@ WEAK void USART1_IrqHandler( void )
*/
WEAK void MCI_IrqHandler( void )
{
printf("MCI\r\n");
while ( 1 ) ;
}
@@ -260,6 +365,7 @@ WEAK void MCI_IrqHandler( void )
*/
WEAK void TWI0_IrqHandler( void )
{
printf("TWI0\r\n");
while ( 1 ) ;
}
@@ -268,6 +374,7 @@ WEAK void TWI0_IrqHandler( void )
*/
WEAK void TWI1_IrqHandler( void )
{
printf("TWI1\r\n");
while ( 1 ) ;
}
@@ -276,6 +383,7 @@ WEAK void TWI1_IrqHandler( void )
*/
WEAK void SPI_IrqHandler( void )
{
printf("SPI\r\n");
while ( 1 ) ;
}
@@ -284,6 +392,7 @@ WEAK void SPI_IrqHandler( void )
*/
WEAK void SSC_IrqHandler( void )
{
printf("SSC\r\n");
while ( 1 ) ;
}
@@ -292,6 +401,7 @@ WEAK void SSC_IrqHandler( void )
*/
WEAK void TC0_IrqHandler( void )
{
printf("TC0\r\n");
while ( 1 ) ;
}
@@ -300,6 +410,7 @@ WEAK void TC0_IrqHandler( void )
*/
WEAK void TC1_IrqHandler( void )
{
printf("TC1\r\n");
while ( 1 ) ;
}
@@ -308,6 +419,7 @@ WEAK void TC1_IrqHandler( void )
*/
WEAK void TC2_IrqHandler( void )
{
printf("TC2\r\n");
while ( 1 ) ;
}
@@ -316,6 +428,7 @@ WEAK void TC2_IrqHandler( void )
*/
WEAK void TC3_IrqHandler( void )
{
printf("TC3\r\n");
while ( 1 ) ;
}
@@ -324,6 +437,7 @@ WEAK void TC3_IrqHandler( void )
*/
WEAK void TC4_IrqHandler( void )
{
printf("TC4\r\n");
while ( 1 ) ;
}
@@ -332,6 +446,7 @@ WEAK void TC4_IrqHandler( void )
*/
WEAK void TC5_IrqHandler( void )
{
printf("TC5\r\n");
while ( 1 ) ;
}
@@ -340,6 +455,7 @@ WEAK void TC5_IrqHandler( void )
*/
WEAK void ADC_IrqHandler( void )
{
printf("ADC\r\n");
while ( 1 ) ;
}
@@ -348,6 +464,7 @@ WEAK void ADC_IrqHandler( void )
*/
WEAK void DAC_IrqHandler( void )
{
printf("DAC\r\n");
while ( 1 ) ;
}
@@ -356,6 +473,7 @@ WEAK void DAC_IrqHandler( void )
*/
WEAK void PWM_IrqHandler( void )
{
printf("PWM\r\n");
while ( 1 ) ;
}
@@ -364,6 +482,7 @@ WEAK void PWM_IrqHandler( void )
*/
WEAK void CRCCU_IrqHandler( void )
{
printf("CRCCU\r\n");
while ( 1 ) ;
}
@@ -372,6 +491,7 @@ WEAK void CRCCU_IrqHandler( void )
*/
WEAK void ACC_IrqHandler( void )
{
printf("ACC\r\n");
while ( 1 ) ;
}
@@ -380,5 +500,6 @@ WEAK void ACC_IrqHandler( void )
*/
WEAK void USBD_IrqHandler( void )
{
printf("USBD\r\n");
while ( 1 ) ;
}

View File

@@ -0,0 +1,517 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup flashd_module Flash Memory Interface
* The flash driver manages the programming, erasing, locking and unlocking sequences
* with dedicated commands.
*
* To implement flash programing operation, the user has to follow these few steps :
* <ul>
* <li>Configue flash wait states to initializes the flash. </li>
* <li>Checks whether a region to be programmed is locked. </li>
* <li>Unlocks the user region to be programmed if the region have locked before.</li>
* <li>Erases the user page before program (optional).</li>
* <li>Writes the user page from the page buffer.</li>
* <li>Locks the region of programmed area if any.</li>
* </ul>
*
* Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption.
* A check of this validity and padding for 32-bit alignment should be done in write algorithm.
* Lock/unlock range associated with the user address range is automatically translated.
*
* This security bit can be enabled through the command "Set General Purpose NVM Bit 0".
*
* A 128-bit factory programmed unique ID could be read to serve several purposes.
*
* The driver accesses the flash memory by calling the lowlevel module provided in \ref efc_module.
* For more accurate information, please look at the EEFC section of the Datasheet.
*
* Related files :\n
* \ref flashd.c\n
* \ref flashd.h.\n
* \ref efc.c\n
* \ref efc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* The flash driver provides the unified interface for flash program operations.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include "flashd.h"
#include "efc.h"
#include <string.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
//static NO_INIT uint8_t _aucPageBuffer[IFLASH_PAGE_SIZE] ;
static NO_INIT uint32_t _adwPageBuffer[IFLASH_PAGE_SIZE/4] ;
static uint8_t* _aucPageBuffer = (uint8_t*)_adwPageBuffer;
static NO_INIT uint32_t _dwUseIAP ;
/*----------------------------------------------------------------------------
* Local macros
*----------------------------------------------------------------------------*/
#define min( a, b ) (((a) < (b)) ? (a) : (b))
/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/
/**
* \brief Computes the lock range associated with the given address range.
*
* \param dwStart Start address of lock range.
* \param dwEnd End address of lock range.
* \param pdwActualStart Actual start address of lock range.
* \param pdwActualEnd Actual end address of lock range.
*/
static void ComputeLockRange( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd )
{
Efc* pStartEfc ;
Efc* pEndEfc ;
uint16_t wStartPage ;
uint16_t wEndPage ;
uint16_t wNumPagesInRegion ;
uint16_t wActualStartPage ;
uint16_t wActualEndPage ;
// Convert start and end address in page numbers
EFC_TranslateAddress( &pStartEfc, dwStart, &wStartPage, 0 ) ;
EFC_TranslateAddress( &pEndEfc, dwEnd, &wEndPage, 0 ) ;
// Find out the first page of the first region to lock
wNumPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ;
wActualStartPage = wStartPage - (wStartPage % wNumPagesInRegion) ;
wActualEndPage = wEndPage ;
if ( (wEndPage % wNumPagesInRegion) != 0 )
{
wActualEndPage += wNumPagesInRegion - (wEndPage % wNumPagesInRegion) ;
}
// Store actual page numbers
EFC_ComputeAddress( pStartEfc, wActualStartPage, 0, pdwActualStart ) ;
EFC_ComputeAddress( pEndEfc, wActualEndPage, 0, pdwActualEnd ) ;
TRACE_DEBUG( "Actual lock range is 0x%06X - 0x%06X\n\r", *pdwActualStart, *pdwActualEnd ) ;
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Initializes the flash driver.
*
* \param mck Master clock frequency in Hz.
*/
extern void FLASHD_Initialize( uint32_t dwMCk, uint32_t dwUseIAP )
{
EFC_DisableFrdyIt( EFC ) ;
#if 1
/* See Revision A errata 46.1.1.3 */
EFC_SetWaitState(EFC, 6);
#else
if ( (dwMCk/1000000) >= 64 )
{
EFC_SetWaitState( EFC, 2 ) ;
}
else
{
if ( (dwMCk/1000000) >= 50 )
{
EFC_SetWaitState( EFC, 1 ) ;
}
else
{
EFC_SetWaitState( EFC, 0 ) ;
}
}
#endif
_dwUseIAP=dwUseIAP ;
}
/**
* \brief Erases the entire flash.
*
* \param address Flash start address.
* \return 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_Erase( uint32_t dwAddress )
{
Efc* pEfc ;
uint16_t wPage ;
uint16_t wOffset ;
uint32_t dwError ;
assert( (dwAddress >=IFLASH_ADDR) || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)) ) ;
// Translate write address
EFC_TranslateAddress( &pEfc, dwAddress, &wPage, &wOffset ) ;
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_EA, 0, _dwUseIAP ) ;
return dwError ;
}
/**
* \brief Writes a data buffer in the internal flash
*
* \note This function works in polling mode, and thus only returns when the
* data has been effectively written.
* \param address Write address.
* \param pBuffer Data buffer.
* \param size Size of data buffer in bytes.
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize )
{
Efc* pEfc ;
uint16_t page ;
uint16_t offset ;
uint32_t writeSize ;
uint32_t pageAddress ;
uint16_t padding ;
uint32_t dwError ;
uint32_t sizeTmp ;
uint32_t *pAlignedDestination ;
uint32_t *pAlignedSource ;
assert( pvBuffer ) ;
assert( dwAddress >=IFLASH_ADDR ) ;
assert( (dwAddress + dwSize) <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
/* Translate write address */
EFC_TranslateAddress( &pEfc, dwAddress, &page, &offset ) ;
/* Write all pages */
while ( dwSize > 0 )
{
/* Copy data in temporary buffer to avoid alignment problems */
writeSize = min((uint32_t)IFLASH_PAGE_SIZE - offset, dwSize ) ;
EFC_ComputeAddress(pEfc, page, 0, &pageAddress ) ;
padding = IFLASH_PAGE_SIZE - offset - writeSize ;
/* Pre-buffer data */
memcpy( _aucPageBuffer, (void *) pageAddress, offset);
/* Buffer data */
memcpy( _aucPageBuffer + offset, pvBuffer, writeSize);
/* Post-buffer data */
memcpy( _aucPageBuffer + offset + writeSize, (void *) (pageAddress + offset + writeSize), padding);
/* Write page
* Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption
*/
pAlignedDestination = (uint32_t*)pageAddress ;
pAlignedSource = (uint32_t*)_adwPageBuffer ;
sizeTmp = IFLASH_PAGE_SIZE ;
while ( sizeTmp >= 4 )
{
*pAlignedDestination++ = *pAlignedSource++;
sizeTmp -= 4;
}
/* Send writing command */
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_EWP, page, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
/* Progression */
dwAddress += IFLASH_PAGE_SIZE ;
pvBuffer = (void *)((uint32_t) pvBuffer + writeSize) ;
dwSize -= writeSize ;
page++;
offset = 0;
}
return 0 ;
}
/**
* \brief Locks all the regions in the given address range. The actual lock range is
* reported through two output parameters.
*
* \param start Start address of lock range.
* \param end End address of lock range.
* \param pActualStart Start address of the actual lock range (optional).
* \param pActualEnd End address of the actual lock range (optional).
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t FLASHD_Lock( uint32_t start, uint32_t end, uint32_t *pActualStart, uint32_t *pActualEnd )
{
Efc *pEfc ;
uint32_t actualStart, actualEnd ;
uint16_t startPage, endPage ;
uint32_t dwError ;
uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
/* Compute actual lock range and store it */
ComputeLockRange( start, end, &actualStart, &actualEnd ) ;
if ( pActualStart != NULL )
{
*pActualStart = actualStart ;
}
if ( pActualEnd != NULL )
{
*pActualEnd = actualEnd;
}
/* Compute page numbers */
EFC_TranslateAddress( &pEfc, actualStart, &startPage, 0 ) ;
EFC_TranslateAddress( 0, actualEnd, &endPage, 0 ) ;
/* Lock all pages */
while ( startPage < endPage )
{
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_SLB, startPage, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
startPage += numPagesInRegion;
}
return 0 ;
}
/**
* \brief Unlocks all the regions in the given address range. The actual unlock range is
* reported through two output parameters.
* \param start Start address of unlock range.
* \param end End address of unlock range.
* \param pActualStart Start address of the actual unlock range (optional).
* \param pActualEnd End address of the actual unlock range (optional).
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t FLASHD_Unlock( uint32_t start, uint32_t end, uint32_t *pActualStart, uint32_t *pActualEnd )
{
Efc* pEfc ;
uint32_t actualStart, actualEnd ;
uint16_t startPage, endPage ;
uint32_t dwError ;
uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
// Compute actual unlock range and store it
ComputeLockRange(start, end, &actualStart, &actualEnd);
if ( pActualStart != NULL )
{
*pActualStart = actualStart ;
}
if ( pActualEnd != NULL )
{
*pActualEnd = actualEnd ;
}
// Compute page numbers
EFC_TranslateAddress( &pEfc, actualStart, &startPage, 0 ) ;
EFC_TranslateAddress( 0, actualEnd, &endPage, 0 ) ;
// Unlock all pages
while ( startPage < endPage )
{
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_CLB, startPage, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
startPage += numPagesInRegion ;
}
return 0 ;
}
/**
* \brief Returns the number of locked regions inside the given address range.
*
* \param start Start address of range
* \param end End address of range.
*/
extern uint32_t FLASHD_IsLocked( uint32_t start, uint32_t end )
{
Efc *pEfc ;
uint16_t startPage, endPage ;
uint8_t startRegion, endRegion ;
uint32_t numPagesInRegion ;
uint32_t status ;
uint32_t dwError ;
uint32_t numLockedRegions = 0 ;
assert( end >= start ) ;
assert( (start >=IFLASH_ADDR) && (end <= IFLASH_ADDR + IFLASH_SIZE) ) ;
// Compute page numbers
EFC_TranslateAddress( &pEfc, start, &startPage, 0 ) ;
EFC_TranslateAddress( 0, end, &endPage, 0 ) ;
// Compute region numbers
numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ;
startRegion = startPage / numPagesInRegion ;
endRegion = endPage / numPagesInRegion ;
if ((endPage % numPagesInRegion) != 0)
{
endRegion++ ;
}
// Retrieve lock status
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_GLB, 0, _dwUseIAP ) ;
assert( !dwError ) ;
status = EFC_GetResult( pEfc ) ;
// Check status of each involved region
while ( startRegion < endRegion )
{
if ( (status & (1 << startRegion)) != 0 )
{
numLockedRegions++ ;
}
startRegion++ ;
}
return numLockedRegions ;
}
/**
* \brief Check if the given GPNVM bit is set or not.
*
* \param gpnvm GPNVM bit index.
* \returns 1 if the given GPNVM bit is currently set; otherwise returns 0.
*/
extern uint32_t FLASHD_IsGPNVMSet( uint8_t ucGPNVM )
{
uint32_t dwError ;
uint32_t dwStatus ;
assert( ucGPNVM < 2 ) ;
/* Get GPNVMs status */
dwError = EFC_PerformCommand( EFC, EFC_FCMD_GFB, 0, _dwUseIAP ) ;
assert( !dwError ) ;
dwStatus = EFC_GetResult( EFC ) ;
/* Check if GPNVM is set */
if ( (dwStatus & (1 << ucGPNVM)) != 0 )
{
return 1 ;
}
else
{
return 0 ;
}
}
/**
* \brief Sets the selected GPNVM bit.
*
* \param gpnvm GPNVM bit index.
* \returns 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_SetGPNVM( uint8_t ucGPNVM )
{
assert( ucGPNVM < 2 ) ;
if ( !FLASHD_IsGPNVMSet( ucGPNVM ) )
{
return EFC_PerformCommand( EFC, EFC_FCMD_SFB, ucGPNVM, _dwUseIAP ) ;
}
else
{
return 0 ;
}
}
/**
* \brief Clears the selected GPNVM bit.
*
* \param gpnvm GPNVM bit index.
* \returns 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_ClearGPNVM( uint8_t ucGPNVM )
{
assert( ucGPNVM < 2 ) ;
if ( FLASHD_IsGPNVMSet( ucGPNVM ) )
{
return EFC_PerformCommand( EFC, EFC_FCMD_CFB, ucGPNVM, _dwUseIAP ) ;
}
else
{
return 0 ;
}
}
/**
* \brief Read the unique ID.
*
* \param uniqueID pointer on a 4bytes char containing the unique ID value.
* \returns 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID )
{
uint32_t dwError ;
assert( pdwUniqueID != NULL ) ;
pdwUniqueID[0] = 0 ;
pdwUniqueID[1] = 0 ;
pdwUniqueID[2] = 0 ;
pdwUniqueID[3] = 0 ;
EFC_StartCommand( EFC, EFC_FCMD_STUI, 0 ) ;
pdwUniqueID[0] = *(uint32_t*) IFLASH_ADDR;
pdwUniqueID[1] = *(uint32_t*)(IFLASH_ADDR + 4) ;
pdwUniqueID[2] = *(uint32_t*)(IFLASH_ADDR + 8) ;
pdwUniqueID[3] = *(uint32_t*)(IFLASH_ADDR + 12) ;
dwError = EFC_PerformCommand( EFC, EFC_FCMD_SPUI, 0, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
return 0 ;
}

View File

@@ -83,9 +83,9 @@ static uint32_t _dwNumSources = 0;
* \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.

View File

@@ -0,0 +1,43 @@
#include "chip.h"
#define EFC_FCMD_STUI 0x0E
#define EFC_FCMD_SPUI 0x0F
__attribute__ ((section(".ramfunc")))
void EEFC_ReadUniqueID(unsigned int *pdwUniqueID)
{
unsigned int status;
/* Errata / Workaround: Set bit 16 of EEFC Flash Mode Register
* to 1 */
EFC->EEFC_FMR |= (1 << 16);
/* Send the Start Read unique Identifier command (STUI) by
* writing the Flash Command Register with the STUI command. */
EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
/* Wait for the FRDY bit to fall */
do {
status = EFC->EEFC_FSR;
} while ((status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY);
/* The Unique Identifier is located in the first 128 bits of the
* Flash memory mapping. So, at the address 0x400000-0x400003.
* */
pdwUniqueID[0] = *(uint32_t *) IFLASH_ADDR;
pdwUniqueID[1] = *(uint32_t *) (IFLASH_ADDR + 4);
pdwUniqueID[2] = *(uint32_t *) (IFLASH_ADDR + 8);
pdwUniqueID[3] = *(uint32_t *) (IFLASH_ADDR + 12);
/* To stop the Unique Identifier mode, the user needs to send
* the Stop Read unique Identifier command (SPUI) by writing the
* Flash Command Register with the SPUI command. */
EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI;
/* When the Stop read Unique Unique Identifier command (SPUI)
* has been performed, the FRDY bit in the Flash Programming
* Status Register (EEFC_FSR) rises. */
do {
status = EFC->EEFC_FSR;
} while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
}

View File

@@ -0,0 +1,81 @@
#ifndef _USB_DFU_H
#define _USB_DFU_H
/* USB Device Firmware Update Implementation for OpenPCD
* (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
*
* Protocol definitions for USB DFU
*
* This ought to be compliant to the USB DFU Spec 1.0 as available from
* http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
*
*/
#include <stdint.h>
#include <usb/include/USBRequests.h>
#define USB_DT_DFU 0x21
struct usb_dfu_func_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bmAttributes;
#define USB_DFU_CAN_DOWNLOAD (1 << 0)
#define USB_DFU_CAN_UPLOAD (1 << 1)
#define USB_DFU_MANIFEST_TOL (1 << 2)
#define USB_DFU_WILL_DETACH (1 << 3)
uint16_t wDetachTimeOut;
uint16_t wTransferSize;
uint16_t bcdDFUVersion;
} __attribute__ ((packed));
#define USB_DT_DFU_SIZE 9
/* DFU class-specific requests (Section 3, DFU Rev 1.1) */
#define USB_REQ_DFU_DETACH 0x00
#define USB_REQ_DFU_DNLOAD 0x01
#define USB_REQ_DFU_UPLOAD 0x02
#define USB_REQ_DFU_GETSTATUS 0x03
#define USB_REQ_DFU_CLRSTATUS 0x04
#define USB_REQ_DFU_GETSTATE 0x05
#define USB_REQ_DFU_ABORT 0x06
struct dfu_status {
uint8_t bStatus;
uint8_t bwPollTimeout[3];
uint8_t bState;
uint8_t iString;
} __attribute__((packed));
#define DFU_STATUS_OK 0x00
#define DFU_STATUS_errTARGET 0x01
#define DFU_STATUS_errFILE 0x02
#define DFU_STATUS_errWRITE 0x03
#define DFU_STATUS_errERASE 0x04
#define DFU_STATUS_errCHECK_ERASED 0x05
#define DFU_STATUS_errPROG 0x06
#define DFU_STATUS_errVERIFY 0x07
#define DFU_STATUS_errADDRESS 0x08
#define DFU_STATUS_errNOTDONE 0x09
#define DFU_STATUS_errFIRMWARE 0x0a
#define DFU_STATUS_errVENDOR 0x0b
#define DFU_STATUS_errUSBR 0x0c
#define DFU_STATUS_errPOR 0x0d
#define DFU_STATUS_errUNKNOWN 0x0e
#define DFU_STATUS_errSTALLEDPKT 0x0f
enum dfu_state {
DFU_STATE_appIDLE = 0,
DFU_STATE_appDETACH = 1,
DFU_STATE_dfuIDLE = 2,
DFU_STATE_dfuDNLOAD_SYNC = 3,
DFU_STATE_dfuDNBUSY = 4,
DFU_STATE_dfuDNLOAD_IDLE = 5,
DFU_STATE_dfuMANIFEST_SYNC = 6,
DFU_STATE_dfuMANIFEST = 7,
DFU_STATE_dfuMANIFEST_WAIT_RST = 8,
DFU_STATE_dfuUPLOAD_IDLE = 9,
DFU_STATE_dfuERROR = 10,
};
#endif /* _USB_DFU_H */

View File

@@ -47,6 +47,8 @@
#include "USBD.h"
#include "USBD_HAL.h"
extern void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request);
/*---------------------------------------------------------------------------
* Definitions
*---------------------------------------------------------------------------*/
@@ -144,7 +146,11 @@ void USBD_RequestHandler(uint8_t bEndpoint,
bEndpoint);
}
else {
#if defined(BOARD_USB_DFU) && !defined(APPLICATION_dfu)
USBDFU_Runtime_RequestHandler(pRequest);
#else
USBDCallbacks_RequestReceived(pRequest);
#endif
}
}

View File

@@ -2,6 +2,7 @@
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
* Copyright (c) 2018, Kevin Redon <kredon@sysmocom.de>
*
* All rights reserved.
*
@@ -331,8 +332,13 @@ static void GetDescriptor(
/* Check if descriptor exists */
if (indexRDesc >= numStrings) {
USBD_Stall(0);
/* Sometimes descriptor string 0xee is requested.
* This is a mechanism used by Microsoft Windows to further identify the USB device.
* Instead of stalling, as is the original code, leading to an USB reset, we send an empty packet.
* I am not sure if sending an empty string would be better, but an empty packet seems sufficient.
*/
//USBD_Stall(0);
USBD_Write(0, NULL, 0, 0, 0);
}
else {

View File

@@ -0,0 +1,49 @@
#include <usb/include/USBDescriptors.h>
#include <usb/device/dfu/dfu.h>
/* String 1 "SimTrace DFU Interface - Application Partition" */
const struct USBStringDescriptor USBDFU_string1 = {
.hdr = {
.bLength = sizeof(USBGenericDescriptor) + 46 * sizeof(unsigned short),
.bDescriptorType = USBGenericDescriptor_STRING,
},
.wData = { 0x0053, 0x0069, 0x006d, 0x0054, 0x0072, 0x0061,
0x0063, 0x0065, 0x0020, 0x0044, 0x0046, 0x0055,
0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072,
0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d,
0x0020, 0x0041, 0x0070, 0x0070, 0x006c, 0x0069,
0x0063, 0x0061, 0x0074, 0x0069, 0x006f, 0x006e,
0x0020, 0x0050, 0x0061, 0x0072, 0x0074, 0x0069,
0x0074, 0x0069, 0x006f, 0x006e, },
};
/* String 2 "SimTrace DFU Interface - Bootloader Partition" */
const struct USBStringDescriptor USBDFU_string2 = {
.hdr = {
.bLength = sizeof(USBGenericDescriptor) + 45 * sizeof(unsigned short),
.bDescriptorType = USBGenericDescriptor_STRING,
},
.wData = { 0x0053, 0x0069, 0x006d, 0x0054, 0x0072, 0x0061,
0x0063, 0x0065, 0x0020, 0x0044, 0x0046, 0x0055,
0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072,
0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d,
0x0020, 0x0042, 0x006f, 0x006f, 0x0074, 0x006c,
0x006f, 0x0061, 0x0064, 0x0065, 0x0072, 0x0020,
0x0050, 0x0061, 0x0072, 0x0074, 0x0069, 0x0074,
0x0069, 0x006f, 0x006e, },
};
/* String 3 "SimTrace DFU Interface - RAM" */
const struct USBStringDescriptor USBDFU_string3 = {
.hdr = {
.bLength = sizeof(USBGenericDescriptor) + 28 * sizeof(unsigned short),
.bDescriptorType = USBGenericDescriptor_STRING,
},
.wData = { 0x0053, 0x0069, 0x006d, 0x0054, 0x0072, 0x0061,
0x0063, 0x0065, 0x0020, 0x0044, 0x0046, 0x0055,
0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072,
0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d,
0x0020, 0x0052, 0x0041, 0x004d, },
};

View File

@@ -0,0 +1,132 @@
#ifndef _USB_DEV_DFU_H
#define _USB_DEV_DFU_H
#include <stdint.h>
#include <board.h>
#include <usb/include/USBDescriptors.h>
#include <usb/include/USBDDriver.h>
#if 0
/* This is valid for CCID */
#define CONFIG_DFU_NUM_APP_IF 1
#define CONFIG_DFU_NUM_APP_STR 4
#else
/* This is valid for CDC-Serial */
#define CONFIG_DFU_NUM_APP_IF 2
#define CONFIG_DFU_NUM_APP_STR 2
#endif
struct USBStringDescriptor {
USBGenericDescriptor hdr;
unsigned short wData[];
} __attribute__((packed));
#ifdef BOARD_USB_DFU
#include <usb/common/dfu/usb_dfu.h>
/* for board-specific config */
#include <board.h>
struct dfu_desc {
USBConfigurationDescriptor ucfg;
USBInterfaceDescriptor uif[BOARD_DFU_NUM_IF];
struct usb_dfu_func_descriptor func_dfu;
} __attribute__ ((packed));
/* USB DFU functional descriptor */
#define DFU_FUNC_DESC { \
.bLength = USB_DT_DFU_SIZE, \
.bDescriptorType = USB_DT_DFU, \
.bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD, \
.wDetachTimeOut = 0xff00, \
.wTransferSize = BOARD_DFU_PAGE_SIZE, \
.bcdDFUVersion = 0x0100, \
}
/* Number of DFU interface during runtime mode */
#define DFURT_NUM_IF 1
/* to be used by the runtime as part of its USB descriptor structure
* declaration */
#define DFURT_IF_DESCRIPTOR_STRUCT \
USBInterfaceDescriptor dfu_rt; \
struct usb_dfu_func_descriptor func_dfu;
/* to be used by the runtime as part of its USB Dsecriptor structure
* definition */
#define DFURT_IF_DESCRIPTOR(dfuIF, dfuSTR) \
.dfu_rt = { \
.bLength = sizeof(USBInterfaceDescriptor), \
.bDescriptorType = USBGenericDescriptor_INTERFACE, \
.bInterfaceNumber = dfuIF, \
.bAlternateSetting = 0, \
.bNumEndpoints = 0, \
.bInterfaceClass = 0xFE, \
.bInterfaceSubClass = 0x01, \
.bInterfaceProtocol = 0x01, \
.iInterface = dfuSTR, \
}, \
.func_dfu = DFU_FUNC_DESC \
/* provided by dfu_desc.c */
extern const struct dfu_desc dfu_cfg_descriptor;
extern const USBDDriverDescriptors dfu_descriptors;
#else /* BOARD_USB_DFU */
/* no DFU bootloader is being used */
#define DFURT_NUM_IF 0
#define DFURT_IF_DESCRIPTOR_STRUCT
#define DFURT_IF_DESCRIPTOR(a, b)
#endif /* BOARD_USB_DFU */
/* magic value we use during boot to detect if we should start in DFU
* mode or runtime mode */
#define USB_DFU_MAGIC 0xDFDFDFDF
/* The API between the core DFU handler and the board/soc specific code */
struct dfudata {
uint32_t magic;
uint8_t status;
uint32_t state;
int past_manifest;
unsigned int total_bytes;
};
/* RAM address for this magic value above */
extern struct dfudata _g_dfu;
extern struct dfudata *g_dfu;
void set_usb_serial_str(const uint8_t *serial_usbstr);
void DFURT_SwitchToDFU(void);
/* call-backs from DFU USB function driver to the board/SOC */
extern int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
uint8_t *data, unsigned int len);
extern int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
uint8_t *data, unsigned int req_len);
extern int USBDFU_OverrideEnterDFU(void);
/* function to be called at end of EP0 handler during runtime */
void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request);
/* function to be called at end of EP0 handler during DFU mode */
void USBDFU_DFU_RequestHandler(const USBGenericRequest *request);
/* initialization of USB DFU driver (in DFU mode */
void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors);
/* USBD tells us to switch from DFU mode to application mode */
void USBDFU_SwitchToApp(void);
/* Return values to be used by USBDFU_handle_{dn,up}load */
#define DFU_RET_NOTHING 0
#define DFU_RET_ZLP 1
#define DFU_RET_STALL 2
#endif

View File

@@ -0,0 +1,113 @@
/* DFU related USB Descriptors */
/* (C) 2006-2017 Harald Welte <hwelte@hmw-consulting.de> */
#include <unistd.h>
#include "board.h"
#include "utils.h"
#include <usb/include/USBDescriptors.h>
#include <usb/include/USBDDriver.h>
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
enum {
STR_MANUF = 1,
STR_PROD,
STR_CONFIG,
_STR_FIRST_ALT,
STR_SERIAL = (_STR_FIRST_ALT+BOARD_DFU_NUM_IF),
};
static const USBDeviceDescriptor fsDevice = {
.bLength = sizeof(USBDeviceDescriptor),
.bDescriptorType = USBGenericDescriptor_DEVICE,
.bcdUSB = USBDeviceDescriptor_USB2_00,
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = USBEndpointDescriptor_MAXCTRLSIZE_FS,
.idVendor = BOARD_USB_VENDOR_ID,
.idProduct = BOARD_DFU_USB_PRODUCT_ID,
.bcdDevice = BOARD_USB_RELEASE,
.iManufacturer = STR_MANUF,
.iProduct = STR_PROD,
#ifdef BOARD_USB_SERIAL
.iSerialNumber = STR_SERIAL,
#else
.iSerialNumber = 0,
#endif
.bNumConfigurations = 1,
};
/* Alternate Interface Descriptor, we use one per partition/memory type */
#define DFU_IF(ALT) \
{ \
.bLength = sizeof(USBInterfaceDescriptor), \
.bDescriptorType = USBGenericDescriptor_INTERFACE, \
.bInterfaceNumber = 0, \
.bAlternateSetting = ALT, \
.bNumEndpoints = 0, \
.bInterfaceClass = 0xfe, \
.bInterfaceSubClass = 1, \
.iInterface = (_STR_FIRST_ALT+ALT), \
.bInterfaceProtocol = 2, \
}
/* overall descriptor for the DFU configuration, including all
* descriptors for alternate interfaces */
const struct dfu_desc dfu_cfg_descriptor = {
.ucfg = {
.bLength = sizeof(USBConfigurationDescriptor),
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
.wTotalLength = sizeof(struct dfu_desc),
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = STR_CONFIG,
.bmAttributes = BOARD_USB_BMATTRIBUTES,
.bMaxPower = 100,
},
.uif[0] = DFU_IF(0),
#if BOARD_DFU_NUM_IF > 1
.uif[1] = DFU_IF(1),
#endif
#if BOARD_DFU_NUM_IF > 2
.uif[2] = DFU_IF(2),
#endif
#if BOARD_DFU_NUM_IF > 3
.uif[3] = DFU_IF(3),
#endif
#if BOARD_DFU_NUM_IF > 4
.uif[4] = DFU_IF(4),
#endif
.func_dfu = DFU_FUNC_DESC
};
#include "usb_strings_generated.h"
#if 0
void set_usb_serial_str(const uint8_t *serial_usbstr)
{
usb_strings[STR_SERIAL] = serial_usbstr;
}
#endif
static const USBConfigurationDescriptor *conf_desc_arr[] = {
&dfu_cfg_descriptor.ucfg,
};
const USBDDriverDescriptors dfu_descriptors = {
.pFsDevice = &fsDevice,
.pFsConfiguration = (const USBConfigurationDescriptor **)&conf_desc_arr,
/* DFU only supports FS for now */
.pFsQualifier = NULL,
.pFsOtherSpeed = NULL,
.pHsDevice = NULL,
.pHsConfiguration = NULL,
.pHsQualifier = NULL,
.pHsOtherSpeed = NULL,
.pStrings = usb_strings,
.numStrings = ARRAY_SIZE(usb_strings),
};

View File

@@ -0,0 +1,486 @@
/* USB Device Firmware Update Implementation for OpenPCD, OpenPICC SIMtrace
* (C) 2006-2017 by Harald Welte <hwelte@hmw-consulting.de>
*
* This ought to be compliant to the USB DFU Spec 1.0 as available from
* http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
*
* 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 <unistd.h>
#include <board.h>
#include <core_cm3.h>
#include "trace.h"
#include <usb/include/USBDescriptors.h>
#include <usb/include/USBRequests.h>
#include <usb/include/USBD.h>
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
/* FIXME: this was used for a special ELF section which then got called
* by DFU code and Application code, across flash partitions */
#define __dfudata __attribute__ ((section (".dfudata")))
#define __dfufunc
/// Standard device driver instance.
static USBDDriver usbdDriver;
static unsigned char if_altsettings[1];
__dfudata struct dfudata _g_dfu = {
.state = DFU_STATE_appIDLE,
.past_manifest = 0,
.total_bytes = 0,
};
struct dfudata *g_dfu = &_g_dfu;
WEAK void dfu_drv_updstatus(void)
{
TRACE_INFO("DFU: updstatus()\n\r");
/* we transition immediately from MANIFEST_SYNC to MANIFEST,
* as the flash-writing is not asynchronous in this
* implementation */
if (g_dfu->state == DFU_STATE_dfuMANIFEST_SYNC)
g_dfu->state = DFU_STATE_dfuMANIFEST;
}
static __dfufunc void handle_getstatus(void)
{
/* has to be static as USBD_Write is async ? */
static struct dfu_status dstat;
static const uint8_t poll_timeout_10ms[] = { 10, 0, 0 };
dfu_drv_updstatus();
/* send status response */
dstat.bStatus = g_dfu->status;
dstat.bState = g_dfu->state;
dstat.iString = 0;
memcpy(&dstat.bwPollTimeout, poll_timeout_10ms, sizeof(dstat.bwPollTimeout));
TRACE_DEBUG("handle_getstatus(%u, %u)\n\r", dstat.bStatus, dstat.bState);
USBD_Write(0, (char *)&dstat, sizeof(dstat), NULL, 0);
}
static void __dfufunc handle_getstate(void)
{
uint8_t u8 = g_dfu->state;
TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu->state);
USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0);
}
static void TerminateCtrlInWithNull(void *pArg,
unsigned char status,
unsigned long int transferred,
unsigned long int remaining)
{
USBD_Write(0, // Endpoint #0
0, // No data buffer
0, // No data buffer
(TransferCallback) 0,
(void *) 0);
}
static uint8_t dfu_buf[BOARD_DFU_PAGE_SIZE];
/* download of a single page has completed */
static void dnload_cb(void *arg, unsigned char status, unsigned long int transferred,
unsigned long int remaining)
{
int rc;
TRACE_DEBUG("COMPLETE\n\r");
if (status != USBD_STATUS_SUCCESS) {
TRACE_ERROR("USBD download callback status %d\n\r", status);
USBD_Stall(0);
return;
}
rc = USBDFU_handle_dnload(if_altsettings[0], g_dfu->total_bytes, dfu_buf, transferred);
switch (rc) {
case DFU_RET_ZLP:
g_dfu->total_bytes += transferred;
g_dfu->state = DFU_STATE_dfuDNLOAD_IDLE;
TerminateCtrlInWithNull(0,0,0,0);
break;
case DFU_RET_STALL:
g_dfu->state = DFU_STATE_dfuERROR;
USBD_Stall(0);
break;
case DFU_RET_NOTHING:
break;
}
}
static int handle_dnload(uint16_t val, uint16_t len, int first)
{
int rc;
if (len > BOARD_DFU_PAGE_SIZE) {
TRACE_ERROR("DFU length exceeds flash page size\n\r");
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL;
}
if (len & 0x03) {
TRACE_ERROR("DFU length not four-byte-aligned\n\r");
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL;
}
if (first)
g_dfu->total_bytes = 0;
if (len == 0) {
TRACE_DEBUG("zero-size write -> MANIFEST_SYNC\n\r");
g_dfu->state = DFU_STATE_dfuMANIFEST_SYNC;
return DFU_RET_ZLP;
}
/* else: actually read data */
rc = USBD_Read(0, dfu_buf, len, &dnload_cb, 0);
if (rc == USBD_STATUS_SUCCESS)
return DFU_RET_NOTHING;
else
return DFU_RET_STALL;
}
/* upload of a single page has completed */
static void upload_cb(void *arg, unsigned char status, unsigned long int transferred,
unsigned long int remaining)
{
int rc;
TRACE_DEBUG("COMPLETE\n\r");
if (status != USBD_STATUS_SUCCESS) {
TRACE_ERROR("USBD upload callback status %d\n\r", status);
USBD_Stall(0);
return;
}
g_dfu->total_bytes += transferred;
}
static int handle_upload(uint16_t val, uint16_t len, int first)
{
int rc;
if (first)
g_dfu->total_bytes = 0;
if (len > BOARD_DFU_PAGE_SIZE) {
TRACE_ERROR("DFU length exceeds flash page size\n\r");
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL;
}
rc = USBDFU_handle_upload(if_altsettings[0], g_dfu->total_bytes, dfu_buf, len);
if (rc < 0) {
TRACE_ERROR("application handle_upload() returned %d\n\r", rc);
return DFU_RET_STALL;
}
if (USBD_Write(0, dfu_buf, rc, &upload_cb, 0) == USBD_STATUS_SUCCESS)
return rc;
return DFU_RET_STALL;
}
/* this function gets daisy-chained into processing EP0 requests */
void USBDFU_DFU_RequestHandler(const USBGenericRequest *request)
{
uint8_t req = USBGenericRequest_GetRequest(request);
uint16_t len = USBGenericRequest_GetLength(request);
uint16_t val = USBGenericRequest_GetValue(request);
int rc, ret = DFU_RET_NOTHING;
TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r",
USBGenericRequest_GetType(request),
USBGenericRequest_GetRecipient(request),
val, len);
/* check for GET_DESCRIPTOR on DFU */
if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD &&
USBGenericRequest_GetRecipient(request) == USBGenericRequest_DEVICE &&
USBGenericRequest_GetRequest(request) == USBGenericRequest_GETDESCRIPTOR &&
USBGetDescriptorRequest_GetDescriptorType(request) == USB_DT_DFU) {
uint16_t length = sizeof(struct usb_dfu_func_descriptor);
const USBDeviceDescriptor *pDevice;
int terminateWithNull;
if (USBD_IsHighSpeed())
pDevice = usbdDriver.pDescriptors->pHsDevice;
else
pDevice = usbdDriver.pDescriptors->pFsDevice;
terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
USBD_Write(0, &dfu_cfg_descriptor.func_dfu, length,
terminateWithNull ? TerminateCtrlInWithNull : 0, 0);
return;
}
/* forward all non-DFU specific messages to core handler*/
if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS ||
USBGenericRequest_GetRecipient(request) != USBGenericRequest_INTERFACE) {
TRACE_DEBUG("std_ho_usbd ");
USBDDriver_RequestHandler(&usbdDriver, request);
return;
}
switch (g_dfu->state) {
case DFU_STATE_appIDLE:
case DFU_STATE_appDETACH:
TRACE_ERROR("Invalid DFU State reached in DFU mode\r\n");
ret = DFU_RET_STALL;
break;
case DFU_STATE_dfuIDLE:
switch (req) {
case USB_REQ_DFU_DNLOAD:
if (len == 0) {
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
goto out;
}
g_dfu->state = DFU_STATE_dfuDNLOAD_SYNC;
ret = handle_dnload(val, len, 1);
break;
case USB_REQ_DFU_UPLOAD:
g_dfu->state = DFU_STATE_dfuUPLOAD_IDLE;
handle_upload(val, len, 1);
break;
case USB_REQ_DFU_ABORT:
/* no zlp? */
ret = DFU_RET_ZLP;
break;
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
goto out;
break;
}
break;
case DFU_STATE_dfuDNLOAD_SYNC:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
/* FIXME: state transition depending on block completeness */
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
goto out;
}
break;
case DFU_STATE_dfuDNBUSY:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
/* FIXME: only accept getstatus if bwPollTimeout
* has elapsed */
handle_getstatus();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
goto out;
}
break;
case DFU_STATE_dfuDNLOAD_IDLE:
switch (req) {
case USB_REQ_DFU_DNLOAD:
g_dfu->state = DFU_STATE_dfuDNLOAD_SYNC;
ret = handle_dnload(val, len, 0);
break;
case USB_REQ_DFU_ABORT:
g_dfu->state = DFU_STATE_dfuIDLE;
ret = DFU_RET_ZLP;
break;
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
break;
}
break;
case DFU_STATE_dfuMANIFEST_SYNC:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
break;
}
break;
case DFU_STATE_dfuMANIFEST:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
/* we don't want to change to WAIT_RST, as it
* would mean that we can not support another
* DFU transaction before doing the actual
* reset. Instead, we switch to idle and note
* that we've already been through MANIFST in
* the global variable 'past_manifest'.
*/
//g_dfu->state = DFU_STATE_dfuMANIFEST_WAIT_RST;
g_dfu->state = DFU_STATE_dfuIDLE;
g_dfu->past_manifest = 1;
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
break;
}
break;
case DFU_STATE_dfuMANIFEST_WAIT_RST:
/* we should never go here */
break;
case DFU_STATE_dfuUPLOAD_IDLE:
switch (req) {
case USB_REQ_DFU_UPLOAD:
/* state transition if less data then requested */
rc = handle_upload(val, len, 0);
if (rc >= 0 && rc < len)
g_dfu->state = DFU_STATE_dfuIDLE;
break;
case USB_REQ_DFU_ABORT:
g_dfu->state = DFU_STATE_dfuIDLE;
/* no zlp? */
ret = DFU_RET_ZLP;
break;
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
break;
}
break;
case DFU_STATE_dfuERROR:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
case USB_REQ_DFU_CLRSTATUS:
g_dfu->state = DFU_STATE_dfuIDLE;
g_dfu->status = DFU_STATUS_OK;
/* no zlp? */
ret = DFU_RET_ZLP;
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
break;
}
break;
}
out:
switch (ret) {
case DFU_RET_NOTHING:
break;
case DFU_RET_ZLP:
USBD_Write(0, 0, 0, 0, 0);
break;
case DFU_RET_STALL:
USBD_Stall(0);
break;
}
}
/* we assume the caller has enabled the required clock/PLL for USB */
void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors)
{
/* We already start in DFU idle mode */
g_dfu->state = DFU_STATE_dfuIDLE;
USBDDriver_Initialize(&usbdDriver, pDescriptors, if_altsettings);
USBD_Init();
USBD_Connect();
//USBD_ConfigureSpeed(1);
NVIC_EnableIRQ(UDP_IRQn);
}
void USBDFU_SwitchToApp(void)
{
/* make sure the MAGIC is not set to enter DFU again */
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();
}
/* A board can provide a function overriding this, enabling a
* board-specific 'boot into DFU' override, like a specific GPIO that
* needs to be pulled a certain way. */
WEAK int USBDFU_OverrideEnterDFU(void)
{
return 0;
}
void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
{
USBDFU_DFU_RequestHandler(request);
}

View File

@@ -0,0 +1,218 @@
/* DFU related functions that are active at runtime, i.e. during the
* normal operation of the device firmware, *not* during DFU update mode
* (C) 2006 Harald Welte <hwelte@hmw-consulting.de>
*
* This ought to be compliant to the USB DFU Spec 1.0 as available from
* http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
*
* 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 <assert.h>
#include <core_cm3.h>
#include <usb/include/USBD.h>
#include <usb/device/dfu/dfu.h>
#include "trace.h"
#include <usb/include/USBDescriptors.h>
#include <usb/include/USBRequests.h>
#include <usb/include/USBD.h>
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
struct dfudata *g_dfu = (struct dfudata *) IRAM_ADDR;
/* FIXME: this was used for a special ELF section which then got called
* by DFU code and Application code, across flash partitions */
#define __dfufunc
static __dfufunc void handle_getstatus(void)
{
/* has to be static as USBD_Write is async ? */
static struct dfu_status dstat;
static const uint8_t poll_timeout_10ms[] = { 10, 0, 0 };
/* send status response */
dstat.bStatus = g_dfu->status;
dstat.bState = g_dfu->state;
dstat.iString = 0;
memcpy(&dstat.bwPollTimeout, poll_timeout_10ms, sizeof(dstat.bwPollTimeout));
TRACE_DEBUG("handle_getstatus(%u, %u)\n\r", dstat.bStatus, dstat.bState);
USBD_Write(0, (char *)&dstat, sizeof(dstat), NULL, 0);
}
static void __dfufunc handle_getstate(void)
{
uint8_t u8 = g_dfu->state;
TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu->state);
USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0);
}
static const uint8_t *get_dfu_func_desc(void)
{
USBDDriver *usbdDriver = USBD_GetDriver();
const USBConfigurationDescriptor *cfg_desc;
const USBGenericDescriptor *gen_desc;
if (USBD_IsHighSpeed())
cfg_desc = &usbdDriver->pDescriptors->pHsConfiguration[usbdDriver->cfgnum];
else
cfg_desc = usbdDriver->pDescriptors->pFsConfiguration[usbdDriver->cfgnum];
for (gen_desc = (const USBGenericDescriptor *) cfg_desc;
(const uint8_t *) gen_desc < (const uint8_t *) cfg_desc + cfg_desc->wTotalLength;
gen_desc = (const USBGenericDescriptor *) ((const uint8_t *)gen_desc + gen_desc->bLength)) {
if (gen_desc->bDescriptorType == USB_DT_DFU)
return (const uint8_t *) gen_desc;
}
return NULL;
}
static void TerminateCtrlInWithNull(void *pArg,
unsigned char status,
unsigned long int transferred,
unsigned long int remaining)
{
USBD_Write(0, // Endpoint #0
0, // No data buffer
0, // No data buffer
(TransferCallback) 0,
(void *) 0);
}
/* this function gets daisy-chained into processing EP0 requests */
void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request)
{
USBDDriver *usbdDriver = USBD_GetDriver();
uint8_t req = USBGenericRequest_GetRequest(request);
uint16_t len = USBGenericRequest_GetLength(request);
uint16_t val = USBGenericRequest_GetValue(request);
int rc, ret = DFU_RET_NOTHING;
TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r",
USBGenericRequest_GetType(request),
USBGenericRequest_GetRecipient(request),
val, len);
/* check for GET_DESCRIPTOR on DFU */
if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD &&
USBGenericRequest_GetRecipient(request) == USBGenericRequest_DEVICE &&
USBGenericRequest_GetRequest(request) == USBGenericRequest_GETDESCRIPTOR &&
USBGetDescriptorRequest_GetDescriptorType(request) == USB_DT_DFU) {
uint16_t length = sizeof(struct usb_dfu_func_descriptor);
const USBDeviceDescriptor *pDevice;
const uint8_t *dfu_func_desc = get_dfu_func_desc();
int terminateWithNull;
ASSERT(dfu_func_desc);
if (USBD_IsHighSpeed())
pDevice = usbdDriver->pDescriptors->pHsDevice;
else
pDevice = usbdDriver->pDescriptors->pFsDevice;
terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
USBD_Write(0, dfu_func_desc, length,
terminateWithNull ? TerminateCtrlInWithNull : 0, 0);
return;
}
/* forward all non-DFU specific messages to core handler*/
if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS ||
USBGenericRequest_GetRecipient(request) != USBGenericRequest_INTERFACE) {
TRACE_DEBUG("std_ho_usbd ");
USBDCallbacks_RequestReceived(request);
return;
}
switch (g_dfu->state) {
case DFU_STATE_appIDLE:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
case USB_REQ_DFU_DETACH:
/* we switch it DETACH state, send a ZLP and
* return. The next USB reset in this state
* will then trigger DFURT_SwitchToDFU() below */
TRACE_DEBUG("\r\n====dfu_detach\n\r");
g_dfu->state = DFU_STATE_appDETACH;
ret = DFU_RET_ZLP;
goto out;
break;
default:
ret = DFU_RET_STALL;
}
break;
case DFU_STATE_appDETACH:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_appIDLE;
ret = DFU_RET_STALL;
goto out;
break;
}
/* FIXME: implement timer to return to appIDLE */
break;
default:
TRACE_ERROR("Invalid DFU State reached in Runtime Mode\r\n");
ret = DFU_RET_STALL;
break;
}
out:
switch (ret) {
case DFU_RET_NOTHING:
break;
case DFU_RET_ZLP:
USBD_Write(0, 0, 0, 0, 0);
break;
case DFU_RET_STALL:
USBD_Stall(0);
break;
}
}
void DFURT_SwitchToDFU(void)
{
/* store the magic value that the DFU loader can detect and
* activate itself, rather than boot into the application */
g_dfu->magic = USB_DFU_MAGIC;
/* Disconnect the USB by remoting the pull-up */
USBD_Disconnect();
__disable_irq();
/* reset the processor, we will start execution with the
* ResetVector of the bootloader */
NVIC_SystemReset();
}

View File

@@ -1,190 +0,0 @@
#ifndef _BOARD_
#define _BOARD_
/** Headers */
#include "chip.h"
/* We need this for a nop instruction in USB_HAL.c */
#define __CC_ARM
/** Board */
#include "board_lowlevel.h"
#include "uart_console.h"
#include "iso7816_4.h"
#include "led.h"
#include "cciddriver.h"
#include "usart.h"
#include "USBD.h"
#include "USBD_Config.h"
#include "USBDDriver.h"
/** Highlevel */
#include "trace.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "inttypes.h"
#include "simtrace.h"
#define MIN(a, b) ((a < b) ? a : b)
#ifdef __GNUC__
#undef __GNUC__
#endif
/** Name of the board */
#define BOARD_NAME "SAM3S-SIMTRACE"
/** Board definition */
#define simtrace
/** Family definition (already defined) */
#define sam3s
/** Core definition */
#define cortexm3
#define BOARD_MAINOSC 18432000
#define BOARD_MCK 48000000
#define LED_RED PIO_PA17
#define LED_GREEN PIO_PA18
#define PIN_LED_RED {LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define PIN_LED_GREEN {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
/** Phone (SIM card emulator)/CCID Reader/MITM configuration **/
/* Normally the communication lines between phone and SIM card are disconnected */
// Disconnect SIM card I/O, VPP line from the phone lines
// FIXME: Per default pins are input, therefore high-impedance, therefore they don not activate the bus switch, right?
#define PIN_SC_SW_DEFAULT {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
// Disconnect SIM card RST, CLK line from the phone lines
#define PIN_IO_SW_DEFAULT {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define PINS_BUS_DEFAULT PIN_SC_SW_DEFAULT, PIN_IO_SW_DEFAULT
/** Sniffer configuration **/
// Connect VPP, CLK and RST lines from smartcard to the phone
#define PIN_SC_SW_SNIFF {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define PIN_IO_SW_SNIFF {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define PINS_BUS_SNIFF PIN_SC_SW_SNIFF, PIN_IO_SW_SNIFF
#define PINS_SIM_SNIFF_SIM PIN_PHONE_IO, PIN_PHONE_CLK
/** USART0 pin RX */
#define PIN_USART0_RXD {PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** USART0 pin TX */
#define PIN_USART0_TXD {PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define BOARD_PIN_USART_RXD PIN_USART0_RXD
#define BOARD_PIN_USART_TXD PIN_USART0_TXD
#define BOARD_ID_USART ID_USART0
#define BOARD_USART_BASE USART0
#define PINS_UART { PIO_PA9A_URXD0|PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** UART0 */
/** Console baudrate always using 115200. */
#define CONSOLE_BAUDRATE 115200
/** Usart Hw interface used by the console (UART0). */
#define CONSOLE_USART UART0
/** Usart Hw ID used by the console (UART0). */
#define CONSOLE_ID ID_UART0
/** Pins description corresponding to Rxd,Txd, (UART pins) */
#define CONSOLE_PINS {PINS_UART}
/// Smartcard detection pin
// FIXME: add connect pin as iso pin...should it be periph b or interrupt oder input?
#define BOARD_ISO7816_BASE_USART USART0
#define BOARD_ISO7816_ID_USART ID_USART0
#define USART_SIM USART0
#define ID_USART_SIM ID_USART0
#define USART_PHONE USART1
#define ID_USART_PHONE ID_USART1
#define SIM_PWEN PIO_PA5
#define VCC_FWD PIO_PA26
#define SIM_PWEN_PIN {PIO_PA5, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define PWR_PINS \
/* Enable power converter 4.5-6V to 3.3V; low: off */ \
{SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}, \
/* Enable second power converter: VCC_PHONE to VCC_SIM; high: on */ \
{VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define SW_SIM PIO_PA8
#define SMARTCARD_CONNECT_PIN {SW_SIM, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE }
//#define SMARTCARD_CONNECT_PIN {SW_SIM, PIOB, ID_PIOB, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_IT_EDGE}
/// PIN used for resetting the smartcard
// FIXME: Card is resetted with pin set to 0 --> PIO_OUTPUT_1 as default is right?
#define PIN_ISO7816_RSTMC {PIO_PA7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/// Pins used for connect the smartcard
#define PIN_SIM_IO_INPUT {PIO_PA1, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
#define PIN_SIM_IO {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_SIM_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_SIM_CLK_INPUT {PIO_PA4, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
//#define PINS_ISO7816 PIN_USART1_TXD, PIN_USART1_SCK, PIN_ISO7816_RSTMC
#define PINS_ISO7816 PIN_SIM_IO, PIN_SIM_CLK, PIN_ISO7816_RSTMC // SIM_PWEN_PIN, PIN_SIM_IO2, PIN_SIM_CLK2
#define PINS_TC PIN_SIM_IO_INPUT, PIN_SIM_CLK_INPUT
#define VCC_PHONE {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
#define PIN_ISO7816_RST_PHONE {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_RISE_EDGE | PIO_DEGLITCH }
#define PIN_PHONE_IO_INPUT {PIO_PA21, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
#define PIN_PHONE_IO {PIO_PA22, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} // External Clock Input on PA28
//#define PIN_PHONE_CLK {PIO_PA23A_SCK1, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} // External Clock Input on PA28
#define PIN_PHONE_CLK_INPUT {PIO_PA29, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
#define PINS_ISO7816_PHONE PIN_PHONE_IO, PIN_PHONE_CLK, PIN_PHONE_CLK_INPUT, VCC_PHONE, PIN_PHONE_IO_INPUT, PIN_ISO7816_RST_PHONE
//, VCC_PHONE
//** SPI interface **/
/// SPI MISO pin definition (PA12).
#define PIN_SPI_MISO {1 << 12, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP}
/// SPI MOSI pin definition (PA13).
#define PIN_SPI_MOSI {1 << 13, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/// SPI SPCK pin definition (PA14).
#define PIN_SPI_SPCK {1 << 14, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/// SPI pins definition. Contains MISO, MOSI & SPCK (PA12, PA13 & PA14).
#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SPCK
/// SPI chip select 0 pin definition (PA11).
#define PIN_SPI_NPCS0 {1 << 11, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
//** USB **/
// USB pull-up control pin definition (PA16).
// Default: 1 (USB Pullup deactivated)
#define PIN_USB_PULLUP {1 << 16, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
// Board has UDP controller
#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)
/// USB attributes configuration descriptor (bus or self powered, remote wakeup)
//#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
//#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_RWAKEUP
#define SIMTRACE_VENDOR_ID 0x16c0
#define SIMTRACE_PRODUCT_ID 0x0762
#define USB_VENDOR_ID OPENPCD_VENDOR_ID
#define USB_PRODUCT_ID SIMTRACE_PRODUCT_ID
#endif

View File

@@ -0,0 +1,120 @@
#ifndef _BOARD_
#define _BOARD_
/** Headers */
#include "chip.h"
/* We need this for a nop instruction in USB_HAL.c */
#define __CC_ARM
/** Board */
#include "board_lowlevel.h"
#include "uart_console.h"
#include "iso7816_4.h"
#include "led.h"
#include "cciddriver.h"
#include "usart.h"
#include "USBD.h"
#include "USBD_Config.h"
#include "USBDDriver.h"
/** Highlevel */
#include "trace.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "inttypes.h"
#include "syscalls.h"
#define MIN(a, b) ((a < b) ? a : b)
#ifdef __GNUC__
#undef __GNUC__
#endif
/** Family definition (already defined) */
#define sam3s
/** Core definition */
#define cortexm3
#define BOARD_MCK 48000000
#define PIO_LED_RED PIO_PA17
#define PIO_LED_GREEN PIO_PA18
#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 */
#define PIN_USART0_RXD {PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** USART0 pin TX */
#define PIN_USART0_TXD {PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define BOARD_PIN_USART_RXD PIN_USART0_RXD
#define BOARD_PIN_USART_TXD PIN_USART0_TXD
#define BOARD_ID_USART ID_USART0
#define BOARD_USART_BASE USART0
#define PINS_UART { PIO_PA9A_URXD0|PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** UART0 */
/** Console baudrate always using 115200. */
#define CONSOLE_BAUDRATE 115200
/** UART peripheral used by the console (UART0). */
#define CONSOLE_UART UART0
/** UART peripheral ID used by the console (UART0). */
#define CONSOLE_ID ID_UART0
/** UART ISR used by the console (UART0). */
#define CONSOLE_ISR UART0_IrqHandler
/** UART IRQ used by the console (UART0). */
#define CONSOLE_IRQ UART0_IRQn
/** Pins description corresponding to Rxd,Txd, (UART pins) */
#define CONSOLE_PINS {PINS_UART}
/// Smartcard detection pin
// FIXME: add connect pin as iso pin...should it be periph b or interrupt oder input?
#define BOARD_ISO7816_BASE_USART 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
/* ID of USART peripheral connected to the SIM card */
#define ID_USART_SIM ID_USART0
/* Interrupt request ID of USART peripheral connected to the SIM card */
#define IRQ_USART_SIM USART0_IRQn
/* USART peripheral connected to the phone */
#define USART_PHONE USART1
/* ID of USART peripheral connected to the phone */
#define ID_USART_PHONE ID_USART1
/* Interrupt request ID of USART peripheral connected to the phone */
#define IRQ_USART_PHONE USART1_IRQn
#define SIM_PWEN PIO_PA5
#define VCC_FWD PIO_PA26
/** Pin configuration to control USB pull-up on D+
* @details the USB pull-up on D+ is enable by default on the board but can be disabled by setting PA16 high
*/
#define PIN_USB_PULLUP {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
// Board has UDP controller
#define BOARD_USB_UDP
// D+ has external pull-up
#define BOARD_USB_PULLUP_EXTERNAL
#define BOARD_USB_DFU
#define BOARD_DFU_BOOT_SIZE (16 * 1024)
#define BOARD_DFU_RAM_SIZE (2 * 1024)
#define BOARD_DFU_PAGE_SIZE 512
#define BOARD_DFU_NUM_IF 2
extern void board_exec_dbg_cmd(int ch);
extern void board_main_top(void);
extern int board_override_enter_dfu(void);
#endif

View File

@@ -0,0 +1,4 @@
#pragma once
uint32_t adc2uv(uint16_t adc);
int get_board_version_adc(void);

View File

@@ -0,0 +1,29 @@
#pragma once
enum led {
LED_RED,
LED_GREEN,
_NUM_LED
};
enum led_pattern {
BLINK_ALWAYS_OFF = 0,
BLINK_ALWAYS_ON = 1,
BLINK_3O_5F = 2,
BLINK_3O_30F = 3,
BLINK_3O_1F_3O_30F = 4,
BLINK_3O_1F_3O_1F_3O_30F= 5,
BLINK_2O_F = 6,
BLINK_200O_F = 7,
BLINK_600O_F = 8,
BLINK_CUSTOM = 9,
_NUM_LED_BLINK
};
void led_init(void);
void led_fini(void);
void led_stop(void);
void led_start(void);
void led_blink(enum led led, enum led_pattern blink);
enum led_pattern led_get(enum led led);

View File

@@ -0,0 +1,10 @@
#ifndef _MANIFEST_H
#define _MANIFEST_H
extern const char *manifest_application;
extern const char *manifest_revision;
extern const char *manifest_board;
extern const char *manifest_environment;
#endif /* !_MANIFEST_H */

View File

@@ -0,0 +1,4 @@
#pragma once
int sim_switch_use_physical(unsigned int nr, int physical);
int sim_switch_init(void);

View File

@@ -0,0 +1,142 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal FLASH on the ATSAM3S1
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00010000 /* Flash, 64K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 /* sram, 16K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
/* we must make sure the .dfudata is linked to start of RAM */
*(.dfudata .dfudata.*);
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,140 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the ATSAM3S1
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00010000 /* Flash, 64K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 /* sram, 16K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > ram
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > ram
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,91 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the AT91SAM3S1
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(entry)
/* Memory Spaces Definitions */
MEMORY
{
romcodesram (W!RX) : ORIGIN = 0x20000000, LENGTH = 0x0800
sram (W!RX) : ORIGIN = 0x20000800, LENGTH = 0x00003800 /* sram, 16K - sizeof(romcodesram) */
}
/* Entry point */
/*ENTRY (ResetException)*/
SECTIONS
{
/* startup code in the .isr_vector */
.text :
{
. = ALIGN(4);
_stext = .;
KEEP(*(.isr_vector .isr_vector.*))
*(.mailbox)
*(.text .text.*)
*(.rodata .rodata.*)
*(.glue_7)
*(.glue_7t)
*(.gcc_except_table)
*(.rodata .rodata*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
_etext = .;
} > sram
/* data */
.data :
{
. = ALIGN(4);
_sidata = .;
_sdata = .;
*(.data)
*(.data.*)
. = ALIGN(4);
_edata = .;
} > sram
.bss (NOLOAD) : {
_szero = .;
*(.bss)
. = ALIGN(4);
_ezero = .;
} >sram
/* Stack in SRAM */
_sstack = 0x20003FFC;
}
end = .;

View File

@@ -0,0 +1,142 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal FLASH on the ATSAM3S2
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00020000 /* flash, 128K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* sram, 32K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
/* we must make sure the .dfudata is linked to start of RAM */
*(.dfudata .dfudata.*);
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,140 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the ATSAM3S2
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT ("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00020000 /* flash, 128K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* sram, 32K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > ram
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > ram
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,91 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the AT91SAM3S2
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(entry)
/* Memory Spaces Definitions */
MEMORY
{
romcodesram (W!RX) : ORIGIN = 0x20000000, LENGTH = 0x0800
sram (W!RX) : ORIGIN = 0x20000800, LENGTH = 0x00007800 /* sram, 32K - sizeof(romcodesram) */
}
/* Entry point */
/*ENTRY (ResetException)*/
SECTIONS
{
/* startup code in the .isr_vector */
.text :
{
. = ALIGN(4);
_stext = .;
KEEP(*(.isr_vector .isr_vector.*))
*(.mailbox)
*(.text .text.*)
*(.rodata .rodata.*)
*(.glue_7)
*(.glue_7t)
*(.gcc_except_table)
*(.rodata .rodata*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
_etext = .;
} > sram
/* data */
.data :
{
. = ALIGN(4);
_sidata = .;
_sdata = .;
*(.data)
*(.data.*)
. = ALIGN(4);
_edata = .;
} > sram
.bss (NOLOAD) : {
_szero = .;
*(.bss)
. = ALIGN(4);
_ezero = .;
} >sram
/* Stack in SRAM */
_sstack = 0x20007FFC;
}
end = .;

View File

@@ -0,0 +1,142 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal FLASH on the ATSAM3S4
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
/* reserve the first 16k (= 0x4000) for the DFU bootloader */
rom (rx) : ORIGIN = 0x00404000, LENGTH = 0x0003c000 /* flash, 256K */
/* reserve the first 32 (= 0x20) bytes for the _g_dfu struct */
ram (rwx) : ORIGIN = 0x20000020, LENGTH = 0x0000bfe0 /* sram, 48K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
. = ALIGN(4);
_end = . ;
}

View File

@@ -1,143 +1,142 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal FLASH on the ATSAM3S4
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
ENTRY(main)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00020000 /* flash, 256K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* sram, 48K */
/* rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00040000 /* flash, 256K */
/*ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000 /* sram, 48K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
. = ALIGN(4);
_end = . ;
}
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal FLASH on the ATSAM3S4
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00040000 /* flash, 256K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000 /* sram, 48K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
/* we must make sure the .dfudata is linked to start of RAM */
*(.dfudata .dfudata.*);
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,140 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the ATSAM3S4
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00040000 /* flash, 256K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000 /* sram, 48K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > ram
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > ram
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,91 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* 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.
*
* 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
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the AT91SAM3S4
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(entry)
/* Memory Spaces Definitions */
MEMORY
{
romcodesram (W!RX) : ORIGIN = 0x20000000, LENGTH = 0x01000
sram (W!RX) : ORIGIN = 0x20001000, LENGTH = 0x0000B000 /* sram, 48K - sizeof(romcodesram) */
}
/* Entry point */
/*ENTRY (ResetException)*/
SECTIONS
{
/* startup code in the .isr_vector */
.text :
{
. = ALIGN(4);
_stext = .;
KEEP(*(.isr_vector .isr_vector.*))
*(.mailbox)
*(.text .text.*)
*(.rodata .rodata.*)
*(.glue_7)
*(.glue_7t)
*(.gcc_except_table)
*(.rodata .rodata*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
_etext = .;
} > sram
/* data */
.data :
{
. = ALIGN(4);
_sidata = .;
_sdata = .;
*(.data)
*(.data.*)
. = ALIGN(4);
_edata = .;
} > sram
.bss (NOLOAD) : {
_szero = .;
*(.bss)
. = ALIGN(4);
_ezero = .;
} >sram
/* Stack in SRAM */
_sstack = 0x2000BFFC;
}
end = .;

View File

@@ -0,0 +1,31 @@
#*******************************************************
#
# Connect to J-Link and debug application in flash.
#
# define 'reset' command
define reset
# Connect to the J-Link gdb server
target remote localhost:2331
# Reset the chip to get to a known state
monitor reset
# Select flash device
monitor flash device = AT91SAM3S4C
# Enable flash download and flash breakpoints
monitor flash download = 1
# Load the program
load
# Reset peripheral (RSTC_CR)
set *0x400e1400 = 0xA5000004
# Initializing PC and stack pointer
mon reg sp=(0x400000)
set *0x400004 = *0x400004 & 0xFFFFFFFE
mon reg pc=(0x400004)
info reg
# end of 'reset' command
end

View File

@@ -0,0 +1,27 @@
#*************************************************
#
# Connect to J-Link and debug application in sram on SAM3S
#
# Note:
# First, users should modify Step1 and Step2 according to their project,
# then do Step3.
# Step1: Connect to the J-Link gdb server
define reset
target remote localhost:2331
monitor reset
# Step2: Load file(eg. getting-started project)
load
# Step3: Reset peripheral (RSTC_CR)
set *0x400e1400 = 0xA5000004
# Step4: Initializing PC and stack pointer
# Modify pc value to even before writing pc register
mon reg sp=(0x20000000)
set *0x20000004 = *0x20000004 & 0xFFFFFFFE
mon reg pc=(0x20000004)
info reg
end

View File

@@ -0,0 +1,27 @@
#*************************************************
#
# Connect to J-Link and debug application in sram on SAM3S
#
# Note:
# First, users should modify Step1 and Step2 according to their project,
# then do Step3.
# Step1: Connect to the J-Link gdb server
define reset
target remote localhost:2331
monitor reset
# Step2: Load file(eg. getting-started project)
load
# Step3: Reset peripheral (RSTC_CR)
set *0x400e1400 = 0xA5000004
# Step4: Initializing PC and stack pointer
# Modify pc value to even before writing pc register
mon reg sp=(0x20000000)
set *0x20000004 = *0x20000004 & 0xFFFFFFFE
mon reg pc=(0x20000004)
info reg
end

View File

@@ -2,6 +2,7 @@
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2010, Atmel Corporation
* Copyright (C) 2017, Harald Welte <laforge@gnumonks.org>
*
* All rights reserved.
*
@@ -61,7 +62,6 @@ extern uint32_t _ezero;
extern int main( void ) ;
/** \endcond */
void ResetException( void ) ;
extern void __libc_init_array( void ) ;
/*------------------------------------------------------------------------------
* Exception Table
@@ -125,6 +125,23 @@ IntFunc exception_table[] = {
IrqHandlerNotUsed /* 35 not used */
};
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
#include "usb/device/dfu/dfu.h"
static void BootIntoApp(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);
appReset = (void(*)(void))pSrc[1];
g_dfu->state = DFU_STATE_appIDLE;
appReset();
}
#endif
/**
* \brief This is the code that gets called on processor reset.
* To initialize the device, and call the main() routine.
@@ -136,6 +153,29 @@ void ResetException( void )
/* Low level Initialize */
LowLevelInit() ;
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
/* we are before the text segment has been relocated, so g_dfu is
* not initialized yet */
g_dfu = &_g_dfu;
if ((g_dfu->magic != USB_DFU_MAGIC) && !USBDFU_OverrideEnterDFU()) {
/* start application if valid
* the application starts with the vector table
* the first entry in the vector table is the initial stack pointer (SP) address
* the stack will be placed in RAM, which begins at 0x2000 0000
* there is up to 48 KB of RAM (0xc000)
* since the stack grown "downwards" it should start at the end of the RAM: max 0x2000 c000
* if the SP is not in this range (e.g. flash has been erased) there is no valid application
* the second entry in the vector table is the reset address, corresponding to the application start
*/
if (((*((uint32_t*)(IFLASH_ADDR+BOARD_DFU_BOOT_SIZE)))&0xFFFF0000)==0x20000000) {
BootIntoApp();
/* Infinite loop */
while ( 1 ) ;
}
}
#endif
/* Initialize the relocate segment */
pSrc = &_etext ;
pDest = &_srelocate ;
@@ -163,8 +203,8 @@ void ResetException( void )
SCB->VTOR |= 1 << SCB_VTOR_TBLBASE_Pos ;
}
/* Initialize the C library */
__libc_init_array() ;
/* App should have disabled interrupts during the transition */
__enable_irq();
/* Branch to main function */
main() ;

View File

@@ -43,31 +43,69 @@
* Local definitions
*----------------------------------------------------------------------------*/
/* Clock settings at 48MHz for 18 MHz crystal */
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)
#if (BOARD_MCK == 48000000)
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
#if (BOARD_MAINOSC == 18432000)
/* Clock settings at 48MHz for 18 MHz crystal */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(0xc) \
| CKGR_PLLAR_MULA(13-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(0x5))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)
/* Clock settings at 64MHz for 18 MHz crystal */
#elif (BOARD_MCK == 64000000)
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
| CKGR_PLLAR_DIVA(5))
#elif (BOARD_MAINOSC == 12000000)
/* QMod has 12 MHz clock, so multply by 8 (96 MHz) and divide by 2 */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(0x06) \
| CKGR_PLLAR_MULA(8-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(0x2))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)
| CKGR_PLLAR_DIVA(2))
#else
#error "No settings for current BOARD_MCK."
#error "Please define PLLA config for your MAINOSC frequency"
#endif /* MAINOSC */
#elif (BOARD_MCK == 64000000)
#if (BOARD_MAINOSC == 18432000)
/* Clock settings at 64MHz for 18 MHz crystal: 64.512 MHz */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(7-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2))
#elif (BOARD_MAINOSC == 12000000)
/* QMod has 12 MHz clock, so multply by 10 / div by 2: 60 MHz */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(10-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2))
#error "Please define PLLA config for your MAINOSC frequency"
#endif /* MAINOSC */
#else
#error "No PLL settings for current BOARD_MCK."
#endif
#if (BOARD_MAINOSC == 12000000)
#define PLLB_CFG (CKGR_PLLBR_DIVB(2)|CKGR_PLLBR_MULB(8-1)|CKGR_PLLBR_PLLBCOUNT_Msk)
#elif (BOARD_MAINOSC == 18432000)
#define PLLB_CFG (CKGR_PLLBR_DIVB(5)|CKGR_PLLBR_MULB(13-1)|CKGR_PLLBR_PLLBCOUNT_Msk)
#else
#error "Please configure PLLB for your MAINOSC freq"
#endif
/* Define clock timeout */
#define CLOCK_TIMEOUT 0xFFFFFFFF
/**
* \brief Configure 48MHz Clock for USB
*/
static void _ConfigureUsbClock(void)
{
/* Enable PLLB for USB */
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) */
| PMC_USB_USBS; /* PLLB */
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
@@ -81,6 +119,18 @@ extern WEAK void LowLevelInit( void )
{
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
* might be some kind of leakage that creeps in some way, but is not
* the "official" power supply */
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;
PIOA->PIO_OER |= PIO_LED_RED | PIO_LED_GREEN;
PIOA->PIO_CODR |= PIO_LED_RED | PIO_LED_GREEN;
/* Set 3 FWS for Embedded Flash Access */
EFC->EEFC_FMR = EEFC_FMR_FWS(3);
@@ -93,30 +143,74 @@ extern WEAK void LowLevelInit( void )
}
*/
#ifndef qmod
/* Initialize main oscillator */
/* if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
{
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT));
}*/
}
/* Switch to 3-20MHz Xtal oscillator */
PIOB->PIO_PDR = (1 << 8) | (1 << 9);
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;
/* wait for Main XTAL oscillator stabilization */
timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT));
#else
/* QMOD has external 12MHz clock source */
PIOB->PIO_PDR = (1 << 9);
PIOB->PIO_PUDR = (1 << 9);
PIOB->PIO_PPDDR = (1 << 9);
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY| CKGR_MOR_MOSCSEL;
#endif
/* disable the red LED after main clock initialization */
PIOA->PIO_SODR = PIO_LED_RED;
/* "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;
/* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* Initialize PLLA */
PMC->CKGR_PLLAR = BOARD_PLLAR;
/* Wait for PLLA to lock */
timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT));
/* Switch to main clock */
/* Switch to main clock (again ?!?) */
PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
/* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* switch to PLLA as master clock source */
PMC->PMC_MCKR = BOARD_MCKR ;
/* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* Configure SysTick for 1ms */
SysTick_Config(BOARD_MCK/1000);
_ConfigureUsbClock();
}
/* SysTick based delay function */
volatile uint32_t jiffies;
/* Interrupt handler for SysTick interrupt */
void SysTick_Handler(void)
{
jiffies++;
}
void mdelay(unsigned int msecs)
{
uint32_t jiffies_start = jiffies;
do {
} while ((jiffies - jiffies_start) < msecs);
}

View File

@@ -0,0 +1,82 @@
#include "board.h"
#include "boardver_adc.h"
#define UV_PER_LSB ((3300 * 1000) / 4096)
uint32_t adc2uv(uint16_t adc)
{
uint32_t uv = (uint32_t) adc * UV_PER_LSB;
return uv;
}
/***********************************************************************
* ADC for board version detection
***********************************************************************/
#ifdef PIN_VERSION_DET
static int adc_sam3s_reva_errata = 0;
static const Pin pin_version_det = PIN_VERSION_DET;
/* Warning: Don't call this while other code (like the SIM VCC voltage
* reading) is running. The idea is you call this once during board
* startup and cache the result in a (global) variable if you need it
* later throughout the code */
int get_board_version_adc(void)
{
uint32_t chip_arch = CHIPID->CHIPID_CIDR & CHIPID_CIDR_ARCH_Msk;
uint32_t chip_ver = CHIPID->CHIPID_CIDR & CHIPID_CIDR_VERSION_Msk;
uint16_t sample;
uint32_t uv;
PIO_Configure(&pin_version_det, 1);
PMC_EnablePeripheral(ID_ADC);
ADC->ADC_CR |= ADC_CR_SWRST;
if (chip_ver == 0 &&
(chip_arch == CHIPID_CIDR_ARCH_SAM3SxA ||
chip_arch == CHIPID_CIDR_ARCH_SAM3SxB ||
chip_arch == CHIPID_CIDR_ARCH_SAM3SxC)) {
TRACE_INFO("Enabling Rev.A ADC Errata work-around\r\n");
adc_sam3s_reva_errata = 1;
}
if (adc_sam3s_reva_errata) {
/* Errata Work-Around to clear EOCx flags */
volatile uint32_t foo;
int i;
for (i = 0; i < 16; i++)
foo = ADC->ADC_CDR[i];
}
/* Initialize ADC for AD2, fADC=48/24=2MHz */
ADC->ADC_MR = ADC_MR_TRGEN_DIS | ADC_MR_LOWRES_BITS_12 |
ADC_MR_SLEEP_NORMAL | ADC_MR_FWUP_OFF |
ADC_MR_FREERUN_OFF | ADC_MR_PRESCAL(23) |
ADC_MR_STARTUP_SUT8 | ADC_MR_SETTLING(3) |
ADC_MR_ANACH_NONE | ADC_MR_TRACKTIM(4) |
ADC_MR_TRANSFER(1) | ADC_MR_USEQ_NUM_ORDER;
/* enable AD2 channel only */
ADC->ADC_CHER = ADC_CHER_CH2;
/* Make sure we don't use interrupts as that's what the SIM card
* VCC ADC code is using */
ADC->ADC_IER = 0;
NVIC_DisableIRQ(ADC_IRQn);
ADC->ADC_CR |= ADC_CR_START;
/* busy-wait, actually read the value */
do { } while (!(ADC->ADC_ISR & ADC_ISR_EOC2));
/* convert to voltage */
sample = ADC->ADC_CDR[2];
uv = adc2uv(sample);
TRACE_INFO("VERSION_DET ADC=%u => %u uV\r\n", sample, uv);
/* FIXME: convert to board version based on thresholds */
return 0;
}
#endif /* PIN_VERSION_DET */

View File

@@ -0,0 +1,265 @@
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <osmocom/core/timer.h>
#include "board.h"
#include "utils.h"
#include "led.h"
#ifdef PINS_LEDS
static const Pin pinsLeds[] = { PINS_LEDS } ;
static void led_set(enum led led, int on)
{
ASSERT(led < PIO_LISTSIZE(pinsLeds));
if (on)
PIO_Clear(&pinsLeds[led]);
else
PIO_Set(&pinsLeds[led]);
}
/* LED blinking code */
/* a single state in a sequence of blinking */
struct blink_state {
/* duration of the state in ms */
uint16_t duration;
/* brightness of LED during the state */
uint8_t on;
} __attribute__((packed));
static const struct blink_state bs_off[] = {
{ 0, 0 }
};
static const struct blink_state bs_on[] = {
{ 0, 1 }
};
static const struct blink_state bs_3on_5off[] = {
{ 300, 1 }, { 500, 0 }
};
static const struct blink_state bs_3on_30off[] = {
{ 300, 1 }, { 3000, 0 }
};
static const struct blink_state bs_3on_1off_3on_30off[] = {
{ 300, 1 }, { 100, 0 }, { 300, 1 }, { 3000, 0 }
};
static const struct blink_state bs_3on_1off_3on_1off_3on_30off[] = {
{ 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[] = {
{ 20000, 1 }, { 0, 0 },
};
static const struct blink_state bs_600on_off[] = {
{ 60000, 1 }, { 0, 0 },
};
/* a blink pattern is an array of blink_states */
struct blink_pattern {
const struct blink_state *states;
uint16_t size;
};
/* compiled-in default blinking patterns */
static const struct blink_pattern patterns[] = {
[BLINK_ALWAYS_OFF] = {
.states = bs_off,
.size = ARRAY_SIZE(bs_off),
},
[BLINK_ALWAYS_ON] = {
.states = bs_on,
.size = ARRAY_SIZE(bs_on),
},
[BLINK_3O_5F] = {
.states = bs_3on_5off,
.size = ARRAY_SIZE(bs_3on_5off),
},
[BLINK_3O_30F] = {
.states = bs_3on_30off,
.size = ARRAY_SIZE(bs_3on_30off),
},
[BLINK_3O_1F_3O_30F] = {
.states = bs_3on_1off_3on_30off,
.size = ARRAY_SIZE(bs_3on_1off_3on_30off),
},
[BLINK_3O_1F_3O_1F_3O_30F] = {
.states = 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] = {
.states = bs_200on_off,
.size = ARRAY_SIZE(bs_200on_off),
},
[BLINK_600O_F] = {
.states = bs_600on_off,
.size = ARRAY_SIZE(bs_600on_off),
},
};
struct led_state {
/* which led are we handling */
enum led led;
/* timer */
struct osmo_timer_list timer;
/* pointer and size of blink array */
const struct blink_pattern *pattern;
unsigned int cur_state;
unsigned int illuminated;
/* static allocated space for custom blinking pattern */
struct blink_pattern pattern_cust;
struct blink_state blink_cust[10];
};
static unsigned int cur_state_inc(struct led_state *ls)
{
ls->cur_state = (ls->cur_state + 1) % ls->pattern->size;
return ls->cur_state;
}
static const struct blink_state *
next_blink_state(struct led_state *ls)
{
return &ls->pattern->states[cur_state_inc(ls)];
}
/* apply the next state to the LED */
static void apply_blinkstate(struct led_state *ls,
const struct blink_state *bs)
{
led_set(ls->led, bs->on);
ls->illuminated = bs->on;
/* re-schedule the timer */
if (bs->duration) {
uint32_t us = bs->duration * 1000;
osmo_timer_schedule(&ls->timer, us / 1000000, us % 1000000);
}
}
static void blink_tmr_cb(void *data)
{
struct led_state *ls = data;
const struct blink_state *next_bs = next_blink_state(ls);
/* apply the next state to the LED */
apply_blinkstate(ls, next_bs);
}
static struct led_state led_state[] = {
[LED_RED] = {
.led = LED_RED,
.timer.cb = blink_tmr_cb,
.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 */
void led_blink(enum led led, enum led_pattern blink)
{
#ifdef PINS_LEDS
struct led_state *ls;
if (led >= ARRAY_SIZE(led_state))
return;
ls = &led_state[led];
/* stop previous blinking, if any */
osmo_timer_del(&ls->timer);
led_set(led, 0);
ls->illuminated = 0;
ls->pattern = NULL;
ls->cur_state = 0;
switch (blink) {
case BLINK_CUSTOM:
ls->pattern = &ls->pattern_cust;
break;
default:
if (blink >= ARRAY_SIZE(patterns))
return;
ls->pattern = &patterns[blink];
break;
}
if (ls->pattern && ls->pattern->size > 0)
apply_blinkstate(ls, &ls->pattern->states[0]);
#endif
}
enum led_pattern led_get(enum led led)
{
#ifdef PINS_LEDS
struct led_state *ls;
unsigned int i;
if (led >= ARRAY_SIZE(led_state))
return -1;
ls = &led_state[led];
if (ls->pattern == &ls->pattern_cust)
return BLINK_CUSTOM;
for (i = 0; i < ARRAY_SIZE(patterns); i++) {
if (ls->pattern == &patterns[i])
return i;
}
#endif
/* default case, shouldn't be reached */
return -1;
}
void led_start(void)
{
led_set(LED_GREEN, led_state[LED_GREEN].illuminated);
led_set(LED_RED, led_state[LED_RED].illuminated);
}
void led_stop(void)
{
led_set(LED_GREEN, 0);
led_set(LED_RED, 0);
}
void led_init(void)
{
#ifdef PINS_LEDS
PIO_Configure(pinsLeds, PIO_LISTSIZE(pinsLeds));
led_set(LED_GREEN, 0);
led_set(LED_RED, 0);
#endif
}
void led_fini(void)
{
#ifdef PINS_LEDS
/* we don't actually need to do this, but just in case... */
osmo_timer_del(&led_state[LED_RED].timer);
osmo_timer_del(&led_state[LED_GREEN].timer);
led_set(LED_GREEN, 0);
led_set(LED_RED, 0);
#endif
}

View File

@@ -0,0 +1,7 @@
#include "manifest.h"
const char *manifest_application = APPLICATION;
const char *manifest_revision = GIT_VERSION;
const char *manifest_board = BOARD;
const char *manifest_environment = ENVIRONMENT;

View File

@@ -0,0 +1,74 @@
/* Code to switch between local (physical) and remote (emulated) SIM */
#include "board.h"
#include "trace.h"
#include "led.h"
#include "sim_switch.h"
#ifdef PIN_SIM_SWITCH1
static const Pin pin_conn_usim1 = {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
#endif
#ifdef PIN_SIM_SWITCH2
static const Pin pin_conn_usim2 = {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
#endif
static int initialized = 0;
int sim_switch_use_physical(unsigned int nr, int physical)
{
const Pin *pin;
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) {
#ifdef PIN_SIM_SWITCH1
case 0:
pin = &pin_conn_usim1;
led = LED_USIM1;
break;
#endif
#ifdef PIN_SIM_SWITCH2
case 1:
pin = &pin_conn_usim2;
led = LED_USIM2;
break;
#endif
default:
TRACE_ERROR("Invalid SIM%u\n\r", nr);
return -1;
}
if (physical) {
TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
PIO_Clear(pin);
led_blink(led, BLINK_ALWAYS_ON);
} else {
TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
PIO_Set(pin);
led_blink(led, BLINK_ALWAYS_OFF);
}
return 0;
}
int sim_switch_init(void)
{
int num_switch = 0;
#ifdef PIN_SIM_SWITCH1
PIO_Configure(&pin_conn_usim1, 1);
num_switch++;
#endif
#ifdef PIN_SIM_SWITCH2
PIO_Configure(&pin_conn_usim2, 1);
num_switch++;
#endif
initialized = 1;
return num_switch;
}

View File

@@ -43,25 +43,20 @@
#include <stdio.h>
#include <stdint.h>
#include "ringbuffer.h"
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
/** Console baudrate always using 115200. */
#define CONSOLE_BAUDRATE 115200
/** Usart Hw interface used by the console (UART0). */
#define CONSOLE_USART UART0
/** Usart Hw ID used by the console (UART0). */
#define CONSOLE_ID ID_UART0
/** Pins description corresponding to Rxd,Txd, (UART pins) */
#define CONSOLE_PINS {PINS_UART}
/*----------------------------------------------------------------------------
* Variables
*----------------------------------------------------------------------------*/
/** Is Console Initialized. */
static uint8_t _ucIsConsoleInitialized=0 ;
static uint8_t _ucIsConsoleInitialized=0;
/** Ring buffer to queue data to be sent */
static ringbuf uart_tx_buffer;
/**
* \brief Configures an USART peripheral with the specified parameters.
@@ -72,7 +67,7 @@ static uint8_t _ucIsConsoleInitialized=0 ;
extern void UART_Configure( uint32_t baudrate, uint32_t masterClock)
{
const Pin pPins[] = CONSOLE_PINS;
Uart *pUart = CONSOLE_USART;
Uart *pUart = CONSOLE_UART;
/* Configure PIO */
PIO_Configure(pPins, PIO_LISTSIZE(pPins));
@@ -94,12 +89,34 @@ extern void UART_Configure( uint32_t baudrate, uint32_t masterClock)
/* Disable PDC channel */
pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
/* Reset transmit ring buffer */
rbuf_reset(&uart_tx_buffer);
/* Enable TX interrupts */
pUart->UART_IER = UART_IER_TXRDY;
NVIC_EnableIRQ(CONSOLE_IRQ);
/* Enable receiver and transmitter */
pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
/* Remember the configuration is complete */
_ucIsConsoleInitialized=1 ;
}
/** Interrupt Service routine to transmit queued data */
void CONSOLE_ISR(void)
{
Uart *uart = CONSOLE_UART;
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);
} else {
uart->UART_IDR = UART_IER_TXRDY;
}
}
}
/**
* \brief Outputs a character on the UART line.
*
@@ -108,19 +125,26 @@ extern void UART_Configure( uint32_t baudrate, uint32_t masterClock)
*/
extern void UART_PutChar( uint8_t c )
{
Uart *pUart=CONSOLE_USART ;
Uart *pUart = CONSOLE_UART ;
/* Initialize console is not already done */
if ( !_ucIsConsoleInitialized )
{
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
}
/* Wait for the transmitter to be ready */
while ( (pUart->UART_SR & UART_SR_TXEMPTY) == 0 ) ;
/* Send character */
pUart->UART_THR=c ;
/* Only store input if buffer is not full, else drop it */
bool trigger_isr = false;
if (rbuf_is_empty(&uart_tx_buffer)) {
trigger_isr = true;
}
if (!rbuf_is_full(&uart_tx_buffer)) {
rbuf_write(&uart_tx_buffer, c);
}
if (trigger_isr) {
pUart->UART_IER = UART_IER_TXRDY;
CONSOLE_ISR();
}
}
/**
@@ -131,14 +155,15 @@ extern void UART_PutChar( uint8_t c )
*/
extern uint32_t UART_GetChar( void )
{
Uart *pUart=CONSOLE_USART ;
Uart *pUart = CONSOLE_UART ;
if ( !_ucIsConsoleInitialized )
{
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
}
while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 ) ;
while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 )
WDT_Restart(WDT);
return pUart->UART_RHR ;
}
@@ -150,7 +175,7 @@ extern uint32_t UART_GetChar( void )
*/
extern uint32_t UART_IsRxReady( void )
{
Uart *pUart=CONSOLE_USART ;
Uart *pUart = CONSOLE_UART;
if ( !_ucIsConsoleInitialized )
{
@@ -290,6 +315,7 @@ extern uint32_t UART_GetInteger( uint32_t* pdwValue )
return 0 ;
}
}
WDT_Restart(WDT);
}
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include "board_common.h"
#include "simtrace_usb.h"
/** Name of the board */
#define BOARD_NAME "OWHW"
/** Board definition */
#define owhw
#define BOARD_MAINOSC 18432000
/* 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_SET_USIM1_PRES {PIO_PA12, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#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_SET_USIM2_PRES {PIO_PA14, PIOA, ID_PIOA, PIO_OUTPUT_0, 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, PIN_SET_USIM1_PRES
#define PINS_USIM2 PINS_TC_USIM2, PINS_ISO7816_USIM2, PIN_USIM2_nRST, PIN_SET_USIM2_PRES
#define PINS_CARDSIM { PIN_SET_USIM1_PRES, PIN_SET_USIM2_PRES }
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP
#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
#define BOARD_USB_PRODUCT_ID USB_PRODUCT_OWHW_SAM3
#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_OWHW_SAM3_DFU
#define BOARD_USB_RELEASE 0x010
#define CARDEMU_SECOND_UART
/* Disable VCC/ADC detection, as OWHWv2 has no ADCVREF */
//#define DETECT_VCC_BY_ADC
#define HAVE_CARDEM

View File

@@ -0,0 +1,40 @@
/* Card simulator specific functions */
/* (C) 2015 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 "chip.h"
#include "board.h"
#include "utils.h"
static const Pin pins_cardsim[] = PINS_CARDSIM;
void cardsim_set_simpres(uint8_t slot, int present)
{
if (slot > 1)
return;
if (present)
PIO_Set(&pins_cardsim[slot]);
else
PIO_Clear(&pins_cardsim[slot]);
}
void cardsim_gpio_init(void)
{
PIO_Configure(&pins_cardsim, ARRAY_SIZE(pins_cardsim));
}

View File

@@ -0,0 +1,77 @@
#pragma once
#include "board_common.h"
#include "simtrace_usb.h"
#define LED_USIM1 LED_GREEN
#define LED_USIM2 LED_RED
/** Name of the board */
#define BOARD_NAME "QMOD"
/** Board definition */
#define qmod
#define BOARD_MAINOSC 12000000
/* 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_PA12, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}
#define PIN_DET_USIM2_PRES {PIO_PA8, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}
/* only in v2 and lower (!) */
#define PIN_PRTPWR_OVERRIDE {PIO_PA8, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* inputs reading the WWAN LED level */
#define PIN_WWAN1 {PIO_PA15, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}
#define PIN_WWAN2 {PIO_PA16, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}
#define PINS_WWAN_IN { PIN_WWAN1, PIN_WWAN2 }
/* outputs controlling RESET input of modems */
#define PIN_PERST1 {PIO_PA25, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_PULLUP}
#define PIN_PERST2 {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_PULLUP}
#define PINS_PERST { PIN_PERST1, PIN_PERST2 }
#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_QMOD_SAM3
#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_QMOD_SAM3_DFU
#define BOARD_USB_RELEASE 0x010
#define CARDEMU_SECOND_UART
#define DETECT_VCC_BY_ADC
#define HAVE_CARDEM

View File

@@ -0,0 +1,4 @@
#pragma once
int is_card_present(int port);
int card_present_init(void);

View File

@@ -0,0 +1,5 @@
#pragma once
void i2c_pin_init(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,4 @@
#pragma once
int wwan_led_active(int wwan);
int wwan_led_init(void);

View File

@@ -0,0 +1,5 @@
#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,287 @@
/* Quad-modem speciic application code */
/* (C) 2016-2016 by Harald Welte <laforge@gnumonks.org> */
#include "board.h"
#include "simtrace.h"
#include "utils.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"
static const Pin pin_hubpwr_override = PIN_PRTPWR_OVERRIDE;
static const Pin pin_hub_rst = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
static const Pin pin_1234_detect = {PIO_PA14, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP};
static const Pin pin_peer_rst = {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
static const Pin pin_peer_erase = {PIO_PA11, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
/* array of generated USB Strings */
extern unsigned char *usb_strings[];
static int qmod_sam3_is_12(void)
{
if (PIO_Get(&pin_1234_detect) == 0)
return 1;
else
return 0;
}
const unsigned char __eeprom_bin[256] = {
USB_VENDOR_OPENMOKO & 0xff,
USB_VENDOR_OPENMOKO >> 8,
USB_PRODUCT_QMOD_HUB & 0xff,
USB_PRODUCT_QMOD_HUB >> 8,
0x00, 0x00, 0x9b, 0x20, 0x09, 0x00, 0x00, 0x00, 0x32, 0x32, 0x32, 0x32, /* 0x00 - 0x0f */
0x32, 0x04, 0x09, 0x18, 0x0d, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x6d, 0x00, 0x6f, 0x00, /* 0x10 - 0x1f */
0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x20, 0x00, 0x73, 0x00, 0x2e, 0x00, /* 0x20 - 0x2f */
0x66, 0x00, 0x2e, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x47, 0x00, /* 0x30 - 0x3f */
0x6d, 0x00, 0x62, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 - 0x4f */
0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x75, 0x00, 0x61, 0x00, 0x64, 0x00, 0x20, 0x00, 0x6d, 0x00, /* 0x50 - 0x5f */
0x6f, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x76, 0x00, 0x32, 0x00, 0x00, 0x00, /* 0x60 - 0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x7f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80 - 0x8f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90 - 0x9f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0 - 0xaf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0 - 0xbf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 - 0xcf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 - 0xdf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0 - 0xef */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x56, 0x23, 0x71, 0x04, 0x00, /* 0xf0 - 0xff */
};
#include "i2c.h"
static int write_hub_eeprom(void)
{
const unsigned int __eeprom_bin_len = 256;
int i;
/* wait */
mdelay(100);
TRACE_INFO("Writing EEPROM...\n\r");
/* write the EEPROM once */
for (i = 0; i < 256; i++) {
int rc = eeprom_write_byte(0x50, i, __eeprom_bin[i]);
/* if the result was negative, repeat that write */
if (rc < 0)
i--;
}
/* then pursue re-reading it again and again */
TRACE_INFO("Verifying EEPROM...\n\r");
for (i = 0; i < 256; i++) {
int byte = eeprom_read_byte(0x50, i);
TRACE_INFO("0x%02x: %02x\n\r", i, byte);
if (byte != __eeprom_bin[i])
TRACE_ERROR("Byte %u is wrong, expected 0x%02x, found 0x%02x\n\r",
i, __eeprom_bin[i], byte);
}
/* FIXME: Release PIN_PRTPWR_OVERRIDE after we know the hub is
* again powering us up */
return 0;
}
static void board_exec_dbg_cmd_st12only(int ch)
{
uint32_t addr, val;
/* functions below only work on primary (ST12) */
if (!qmod_sam3_is_12())
return;
switch (ch) {
case 'E':
write_hub_eeprom();
break;
case 'O':
printf("Setting PRTPWR_OVERRIDE\n\r");
PIO_Set(&pin_hubpwr_override);
break;
case 'o':
printf("Clearing PRTPWR_OVERRIDE\n\r");
PIO_Clear(&pin_hubpwr_override);
break;
case 'H':
printf("Clearing _HUB_RESET -> HUB_RESET high (inactive)\n\r");
PIO_Clear(&pin_hub_rst);
break;
case 'h':
/* high level drives transistor -> HUB_RESET low */
printf("Asserting _HUB_RESET -> HUB_RESET low (active)\n\r");
PIO_Set(&pin_hub_rst);
break;
case 'w':
if (PIO_GetOutputDataStatus(&pin_hub_rst) == 0)
printf("WARNING: attempting EEPROM access while HUB not in reset\n\r");
printf("Please enter EEPROM offset:\n\r");
UART_GetIntegerMinMax(&addr, 0, 255);
printf("Please enter EEPROM value:\n\r");
UART_GetIntegerMinMax(&val, 0, 255);
printf("Writing value 0x%02x to EEPROM offset 0x%02x\n\r", val, addr);
eeprom_write_byte(0x50, addr, val);
break;
case 'r':
printf("Please enter EEPROM offset:\n\r");
UART_GetIntegerMinMax(&addr, 0, 255);
printf("EEPROM[0x%02x] = 0x%02x\n\r", addr, eeprom_read_byte(0x50, addr));
break;
default:
printf("Unknown command '%c'\n\r", ch);
break;
}
}
/* 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");
if (qmod_sam3_is_12()) {
printf("\tE\tprogram EEPROM\n\r");
printf("\tO\tEnable PRTPWR_OVERRIDE\n\r");
printf("\to\tDisable PRTPWR_OVERRIDE\n\r");
printf("\tH\tRelease HUB RESET (high)\n\r");
printf("\th\tAssert HUB RESET (low)\n\r");
printf("\tw\tWrite single byte in EEPROM\n\r");
printf("\tr\tRead single byte from EEPROM\n\r");
}
printf("\tX\tRelease peer SAM3 from reset\n\r");
printf("\tx\tAssert peer SAM3 reset\n\r");
printf("\tY\tRelease peer SAM3 ERASE signal\n\r");
printf("\ty\tAssert peer SAM3 ERASE signal\n\r");
printf("\tU\tProceed to USB Initialization\n\r");
printf("\t1\tGenerate 1ms reset pulse on WWAN1\n\r");
printf("\t2\tGenerate 1ms reset pulse on WWAN2\n\r");
break;
case 'R':
printf("Asking NVIC to reset us\n\r");
USBD_Disconnect();
NVIC_SystemReset();
break;
case 'X':
printf("Clearing _SIMTRACExx_RST -> SIMTRACExx_RST high (inactive)\n\r");
PIO_Clear(&pin_peer_rst);
break;
case 'x':
printf("Setting _SIMTRACExx_RST -> SIMTRACExx_RST low (active)\n\r");
PIO_Set(&pin_peer_rst);
break;
case 'Y':
printf("Clearing SIMTRACExx_ERASE (inactive)\n\r");
PIO_Clear(&pin_peer_erase);
break;
case 'y':
printf("Seetting SIMTRACExx_ERASE (active)\n\r");
PIO_Set(&pin_peer_erase);
break;
case '1':
printf("Resetting Modem 1 (of this SAM3)\n\r");
wwan_perst_do_reset_pulse(0, 300);
break;
case '2':
printf("Resetting Modem 2 (of this SAM3)\n\r");
wwan_perst_do_reset_pulse(1, 300);
break;
case '!':
sim_switch_use_physical(0, 0);
break;
case '@':
sim_switch_use_physical(0, 0);
break;
default:
if (!qmod_sam3_is_12())
printf("Unknown command '%c'\n\r", ch);
else
board_exec_dbg_cmd_st12only(ch);
break;
}
}
void board_main_top(void)
{
#ifndef APPLICATION_dfu
usb_buf_init();
wwan_led_init();
wwan_perst_init();
sim_switch_init();
#endif
/* make sure we can detect whether running in ST12 or ST34 */
PIO_Configure(&pin_1234_detect, 1);
if (qmod_sam3_is_12()) {
/* set PIN_PRTPWR_OVERRIDE to output-low to avoid the internal
* pull-up on the input to keep SIMTRACE12 alive */
PIO_Configure(&pin_hubpwr_override, 1);
PIO_Configure(&pin_hub_rst, 1);
}
PIO_Configure(&pin_peer_rst, 1);
PIO_Configure(&pin_peer_erase, 1);
#ifndef APPLICATION_dfu
i2c_pin_init();
#endif
if (qmod_sam3_is_12()) {
TRACE_INFO("Detected Quad-Modem ST12\n\r");
} else {
TRACE_INFO("Detected Quad-Modem ST34\n\r");
/* make sure we use the second set of USB Strings
* calling the interfaces "Modem 3" and "Modem 4" rather
* than 1+2 */
usb_strings[7] = usb_strings[9];
usb_strings[8] = usb_strings[10];
}
/* 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
}
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));
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]))
return 0;
/* Set TxD low, abort if RxD doesn't go low either */
PIO_Clear(&uart_loopback_pins[1]);
if (PIO_Get(&uart_loopback_pins[0]))
return 0;
}
/* if we reached here, RxD always follows TxD and thus a
* loopback jumper has been placed on RxD/TxD, and we will boot
* into DFU unconditionally */
return 1;
}
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;
}

View File

@@ -0,0 +1,58 @@
#include <osmocom/core/timer.h>
#include "board.h"
#include "utils.h"
#include "card_pres.h"
#define NUM_CARDPRES 2
#define TIMER_INTERVAL_MS 500
static const Pin pin_cardpres[NUM_CARDPRES] = { PIN_DET_USIM1_PRES, PIN_DET_USIM2_PRES };
static int last_state[NUM_CARDPRES] = { -1, -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];
/* Card present signals are low-active, as we have a switch
* against GND and an internal-pull-up in the SAM3 */
present = PIO_Get(pin) ? 0 : 1;
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,207 @@
#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;
}
static 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;
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,80 @@
/* Code to read/track the status of the WWAN LEDs of attached modems
*
* 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 tiven 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,114 @@
/* Code to control the PERST lines of attached modems
*
* 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;
}

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