Commit 47a19019 authored by Philip Brechler's avatar Philip Brechler
Browse files

Merge branch 'master' into plaetzchen/ios-workaround

parents 613f483f 83a19117
...@@ -6,6 +6,35 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ...@@ -6,6 +6,35 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased] ## [Unreleased]
## [v1.7] - 2019-08-24 21:48 - [Garlic]
[Garlic]: https://card10.badge.events.ccc.de/release/card10-v1.7-Garlic.zip
### Added
- **ESB**: Epic Serial Bus (Better than USB!), stability improvements of the
USB module. Preparation for mass-storage access in the Firmware.
- Enabled the Hardware Watchdog; Card10 will reset itself if the firmware crashes
- Log messages when BLE is pairing / connected.
- The name of the offending app is printed to the serial console, if an app
crashes the metatdata parser.
### Changed
- Improved log messages in cases of lock-contention.
- Menu will show an error message if a crash occurs.
### Fixed
- Fixed race-conditions in serial writes by using a queue.
- "Card10 Nickname" crashing if only `nickname.txt` exists.
- Lockup when debug prints are enabled.
- Delayed BHI160 startup a bit so the PMIC task can check the battery first.
- Relaxed the PMIC lock-timeouts so other task can take a little more time.
- Fixed off-by-one error in `gfx_line()`.
- Fixed the API interrupts sometimes getting stuck.
- Fixed binary building on MacOS.
- Fixed race-conditions in serial console prints by introducing a queue.
- Fixed API & MAX30001 mutexes being initialized late sometimes.
- Fixed wrong stripe width in bi flag.
## [v1.6] - 2019-08-23 20:30 - [Fennel] ## [v1.6] - 2019-08-23 20:30 - [Fennel]
[Fennel]: https://card10.badge.events.ccc.de/release/card10-v1.6-Fennel.zip [Fennel]: https://card10.badge.events.ccc.de/release/card10-v1.6-Fennel.zip
...@@ -124,7 +153,8 @@ fbf7c8c0 fix(menu.py) Refactored menu.py based on !138 ...@@ -124,7 +153,8 @@ fbf7c8c0 fix(menu.py) Refactored menu.py based on !138
## [v1.0] - 2019-08-21 00:50 ## [v1.0] - 2019-08-21 00:50
Initial release. Initial release.
[Unreleased]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.6...master [Unreleased]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.7...master
[v1.7]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.6...v1.7
[v1.6]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.5...v1.6 [v1.6]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.5...v1.6
[v1.5]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.4...v1.5 [v1.5]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.4...v1.5
[v1.4]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.3...v1.4 [v1.4]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.3...v1.4
......
...@@ -77,9 +77,11 @@ CHUNK_ACK: ...@@ -77,9 +77,11 @@ CHUNK_ACK:
===== === ===== ===
0 1-4 0 1-4
----- --- ----- ---
C CRC C CRC(*)
===== === ===== ===
CRC32 of the whole CHUNK packet including first byte, offset and payload.
FINISH: FINISH:
=== === === ===
......
...@@ -88,9 +88,11 @@ html_context = { ...@@ -88,9 +88,11 @@ html_context = {
# -- Options for Auto-Doc ---------------------------------------------------- {{{ # -- Options for Auto-Doc ---------------------------------------------------- {{{
autodoc_mock_imports = [ autodoc_mock_imports = [
"buttons",
"interrupt",
"sys_display", "sys_display",
"sys_leds", "sys_leds",
"buttons", "sys_max30001",
"ucollections", "ucollections",
"urandom", "urandom",
"utime", "utime",
......
...@@ -31,8 +31,9 @@ Dependencies ...@@ -31,8 +31,9 @@ Dependencies
- macOS (Note: The card10 firmware team used Linux so far. macOS recommendations here are experimental.) - macOS (Note: The card10 firmware team used Linux so far. macOS recommendations here are experimental.)
You can use `Homebrew`_ to install the required tools. You can use `Homebrew`_ to install the required tools. The version of the
The version of the Arm crosscompiler tool chain is quite important; with the wrong version, e.g. strip and/or ld might throw strange errors. ARM crosscompiler tool chain is quite important; with the wrong version,
e.g. strip and/or ld might throw strange errors.
.. code-block:: shell-session .. code-block:: shell-session
...@@ -40,8 +41,10 @@ Dependencies ...@@ -40,8 +41,10 @@ Dependencies
brew install px4/px4/gcc-arm-none-eabi-63 brew install px4/px4/gcc-arm-none-eabi-63
brew install coreutils brew install coreutils
.. _Homebrew: https://brew.sh/
- Alternative: Download `ARM's GNU toolchain`_. **TODO** - Alternative: Download `ARM's GNU toolchain`_. **TODO**
.. _Homebrew: https://brew.sh/
* **python3**: For meson and various scripts needed for building. * **python3**: For meson and various scripts needed for building.
* **meson** (>0.43.0) & **ninja**: Unfortunately most distros only have very old versions * **meson** (>0.43.0) & **ninja**: Unfortunately most distros only have very old versions
...@@ -140,3 +143,13 @@ In order to do a rebuild you can issue a clean command to ninja via ...@@ -140,3 +143,13 @@ In order to do a rebuild you can issue a clean command to ninja via
$ ninja -C build/ -t clean $ ninja -C build/ -t clean
Otherwise, rerunning ``./bootstrap.sh`` will also clean the build-directory. Otherwise, rerunning ``./bootstrap.sh`` will also clean the build-directory.
.. note::
If you try to flash pycardium_epicardium.bin (renamed to card10.bin)
and the bootloader does not finish updating, the file might be too large.
~700kB is the normal size, but problems were reported where the file size
was >1MB. This was caused by the ``tr`` tool in the build process
(it's supposed to create a large file with 0xff in it) - this requires the
LC_ALL environment variable to be not set, or set to "C"
(but not UTF8 or similar).
\ No newline at end of file
``max30001`` - MAX30001 ``max30001`` - MAX30001
===================== =======================
.. automodule:: max30001 .. automodule:: max30001
:members: :members:
...@@ -6,7 +6,7 @@ BIN1="$2" ...@@ -6,7 +6,7 @@ BIN1="$2"
BIN2="$3" BIN2="$3"
BINOUT="$4" BINOUT="$4"
dd if=/dev/zero ibs=1k count=448 2>/dev/null | LANG=C LC_CTYPE=C tr "\000" "\377" > "$BINOUT" dd if=/dev/zero ibs=1k count=448 2>/dev/null | LANG=C LC_CTYPE=C LC_ALL=C LC_COLLATE=C tr "\000" "\377" > "$BINOUT"
dd if="$BIN1" of="$BINOUT" conv=notrunc 2>/dev/null dd if="$BIN1" of="$BINOUT" conv=notrunc 2>/dev/null
dd if="$BIN2" >> "$BINOUT" 2>/dev/null dd if="$BIN2" >> "$BINOUT" 2>/dev/null
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
#define INCLUDE_vTaskSuspend 1 #define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelay 1 #define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1 #define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTimerPendFunctionCall 1
/* Allow static allocation of data structures */ /* Allow static allocation of data structures */
#define configSUPPORT_STATIC_ALLOCATION 1 #define configSUPPORT_STATIC_ALLOCATION 1
......
...@@ -38,7 +38,7 @@ struct api_call_mem { ...@@ -38,7 +38,7 @@ struct api_call_mem {
api_id_t id; api_id_t id;
/* ID of the current interrupt */ /* ID of the current interrupt */
api_int_id_t int_id; volatile api_int_id_t int_id;
/* /*
* Buffer for arguments/return value. This buffer will be * Buffer for arguments/return value. This buffer will be
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include "app_main.h" #include "app_main.h"
#include "app_ui.h" #include "app_ui.h"
#include "modules/log.h"
/************************************************************************************************** /**************************************************************************************************
Global Variables Global Variables
**************************************************************************************************/ **************************************************************************************************/
...@@ -283,6 +285,8 @@ void AppHandleNumericComparison(dmSecCnfIndEvt_t *pCnfInd) ...@@ -283,6 +285,8 @@ void AppHandleNumericComparison(dmSecCnfIndEvt_t *pCnfInd)
{ {
uint32_t confirm = DmSecGetCompareValue(pCnfInd->confirm); uint32_t confirm = DmSecGetCompareValue(pCnfInd->confirm);
LOG_INFO("ble", "Confirm Value: %ld", confirm);
/* display confirmation value */ /* display confirmation value */
AppUiDisplayConfirmValue(confirm); AppUiDisplayConfirmValue(confirm);
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include "hrps/hrps_api.h" #include "hrps/hrps_api.h"
#include "rscp/rscp_api.h" #include "rscp/rscp_api.h"
#include "modules/log.h"
/************************************************************************************************** /**************************************************************************************************
Macros Macros
**************************************************************************************************/ **************************************************************************************************/
...@@ -373,6 +375,7 @@ static void bleSetup(bleMsg_t *pMsg) ...@@ -373,6 +375,7 @@ static void bleSetup(bleMsg_t *pMsg)
static void bleProcMsg(bleMsg_t *pMsg) static void bleProcMsg(bleMsg_t *pMsg)
{ {
uint8_t uiEvent = APP_UI_NONE; uint8_t uiEvent = APP_UI_NONE;
hciLeConnCmplEvt_t *connOpen;
switch(pMsg->hdr.event) switch(pMsg->hdr.event)
{ {
...@@ -395,36 +398,88 @@ static void bleProcMsg(bleMsg_t *pMsg) ...@@ -395,36 +398,88 @@ static void bleProcMsg(bleMsg_t *pMsg)
break; break;
case DM_ADV_START_IND: case DM_ADV_START_IND:
LOG_INFO("ble", "Advertisement started");
uiEvent = APP_UI_ADV_START; uiEvent = APP_UI_ADV_START;
break; break;
case DM_ADV_STOP_IND: case DM_ADV_STOP_IND:
LOG_INFO("ble", "Advertisement stopped");
uiEvent = APP_UI_ADV_STOP; uiEvent = APP_UI_ADV_STOP;
break; break;
case DM_CONN_OPEN_IND: case DM_CONN_OPEN_IND:
connOpen = &pMsg->dm.connOpen;
LOG_INFO("ble", "connection from %02X:%02X:%02X:%02X:%02X:%02X opened",
connOpen->peerAddr[0], connOpen->peerAddr[1],
connOpen->peerAddr[2], connOpen->peerAddr[3],
connOpen->peerAddr[4], connOpen->peerAddr[5]);
BasProcMsg(&pMsg->hdr); BasProcMsg(&pMsg->hdr);
uiEvent = APP_UI_CONN_OPEN; uiEvent = APP_UI_CONN_OPEN;
break; break;
case DM_CONN_CLOSE_IND: case DM_CONN_CLOSE_IND:
switch (pMsg->dm.connClose.reason)
{
case HCI_ERR_CONN_TIMEOUT:
LOG_INFO("ble", "Connection closed (0x%02X), Connection timeout",
pMsg->dm.connClose.reason);
break;
case HCI_ERR_LOCAL_TERMINATED:
LOG_INFO("ble", "Connection closed (0x%02X), Connection terminated by local host",
pMsg->dm.connClose.reason);
break;
case HCI_ERR_REMOTE_TERMINATED:
LOG_INFO("ble", "Connection closed (0x%02X), Remote user terminated connection",
pMsg->dm.connClose.reason);
break;
case HCI_ERR_CONN_FAIL:
LOG_INFO("ble", "Connection closed (0x%02X), Connection failed to be established",
pMsg->dm.connClose.reason);
break;
case HCI_ERR_MIC_FAILURE:
LOG_INFO("ble", "Connection closed (0x%02X), Connection terminated due to MIC failure",
pMsg->dm.connClose.reason);
break;
default:
LOG_INFO("ble", "Connection closed (0x%02X)",
pMsg->dm.connClose.reason);
break;
}
bleClose(pMsg); bleClose(pMsg);
uiEvent = APP_UI_CONN_CLOSE; uiEvent = APP_UI_CONN_CLOSE;
break; break;
case DM_SEC_PAIR_CMPL_IND: case DM_SEC_PAIR_CMPL_IND:
LOG_INFO("ble", "Secure pairing successful, auth: 0x%02X",
pMsg->dm.pairCmpl.auth);
uiEvent = APP_UI_SEC_PAIR_CMPL; uiEvent = APP_UI_SEC_PAIR_CMPL;
break; break;
case DM_SEC_PAIR_FAIL_IND: case DM_SEC_PAIR_FAIL_IND:
switch (pMsg->hdr.status) {
case SMP_ERR_TIMEOUT:
LOG_INFO("ble", "Secure pairing failed (0x%02X), Transaction timeout",
pMsg->hdr.status);
break;
case SMP_ERR_ATTEMPTS:
LOG_INFO("ble", "Secure pairing failed (0x%02X), Repeated attempts",
pMsg->hdr.status);
break;
default:
LOG_INFO("ble", "Secure pairing failed (0x%02X)",
pMsg->hdr.status);
break;
}
uiEvent = APP_UI_SEC_PAIR_FAIL; uiEvent = APP_UI_SEC_PAIR_FAIL;
break; break;
case DM_SEC_ENCRYPT_IND: case DM_SEC_ENCRYPT_IND:
LOG_INFO("ble", "Encrypted handshake successful");
uiEvent = APP_UI_SEC_ENCRYPT; uiEvent = APP_UI_SEC_ENCRYPT;
break; break;
case DM_SEC_ENCRYPT_FAIL_IND: case DM_SEC_ENCRYPT_FAIL_IND:
LOG_INFO("ble", "Encrypted handshake failed");
uiEvent = APP_UI_SEC_ENCRYPT_FAIL; uiEvent = APP_UI_SEC_ENCRYPT_FAIL;
break; break;
...@@ -441,6 +496,7 @@ static void bleProcMsg(bleMsg_t *pMsg) ...@@ -441,6 +496,7 @@ static void bleProcMsg(bleMsg_t *pMsg)
break; break;
case DM_HW_ERROR_IND: case DM_HW_ERROR_IND:
LOG_ERR("ble", "HW Error");
uiEvent = APP_UI_HW_ERROR; uiEvent = APP_UI_HW_ERROR;
break; break;
......
/*******************************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*
* $Id: main.c 32120 2017-11-28 23:51:11Z lorne.smith $
*
*******************************************************************************
*/
/**
* @file main.c
* @brief USB CDC-ACM example
* @details This project creates a virtual COM port, which loops back data sent to it.
* Load the project, connect a cable from the PC to the USB connector
* on the Evaluation Kit, and observe that the PC now recognizes a new COM port.
* A driver for the COM port, if needed, is located in the Driver/ subdirectory.
*
*/
#include <stdio.h>
#include <stddef.h>
#include "mxc_config.h"
#include "mxc_sys.h"
#include "mxc_delay.h"
#include "board.h"
#include "led.h"
#include "usb.h"
#include "usb_event.h"
#include "enumerate.h"
#include "cdc_acm.h"
#include "descriptors.h"
#include "modules/modules.h"
#include "modules/log.h"
#include <errno.h>
/***** Definitions *****/
#define EVENT_ENUM_COMP MAXUSB_NUM_EVENTS
#define BUFFER_SIZE 64
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
/***** Global Data *****/
//SWYM: rename to CDC_xy or put into struct CDC_state
volatile int configured; //SWYM: actually unused...
volatile int suspended;
volatile unsigned int event_flags;
int remote_wake_en;
/***** Function Prototypes *****/
static int setconfig_callback(usb_setup_pkt *sud, void *cbdata);
static int setfeature_callback(usb_setup_pkt *sud, void *cbdata);
static int clrfeature_callback(usb_setup_pkt *sud, void *cbdata);
static int event_callback(maxusb_event_t evt, void *data);
static void usb_app_sleep(void);
static void usb_app_wakeup(void);
static int usb_read_callback(void);
//static void echo_usb(void);
/***** File Scope Variables *****/
/* This EP assignment must match the Configuration Descriptor */
static const acm_cfg_t acm_cfg = {
1, /* EP OUT */
MXC_USBHS_MAX_PACKET, /* OUT max packet size */
2, /* EP IN */
MXC_USBHS_MAX_PACKET, /* IN max packet size */
3, /* EP Notify */
MXC_USBHS_MAX_PACKET, /* Notify max packet size */
};
static volatile int usb_read_complete;
int usb_startup_cb()
{
const sys_cfg_usbhs_t sys_usbhs_cfg = NULL;
return SYS_USBHS_Init(&sys_usbhs_cfg);
}
int usb_shutdown_cb()
{
return SYS_USBHS_Shutdown();
}
/* User-supplied function to delay usec micro-seconds */
void delay_us(unsigned int usec)
{
/* mxc_delay() takes unsigned long, so can't use it directly */
mxc_delay(usec);
}
/******************************************************************************/
int cdcacm_init(void)
{
maxusb_cfg_options_t usb_opts;
/* Initialize state */
configured = 0;
suspended = 0;
event_flags = 0;
remote_wake_en = 0;
/* Start out in full speed */
usb_opts.enable_hs = 0;
usb_opts.delay_us =
delay_us; /* Function which will be used for delays */
usb_opts.init_callback = usb_startup_cb;
usb_opts.shutdown_callback = usb_shutdown_cb;
/* Initialize the usb module */
if (usb_init(&usb_opts) != 0) {
LOG_ERR("cdcacm", "usb_init() failed");
return -EIO;
}
/* Initialize the enumeration module */
if (enum_init() != 0) {
LOG_ERR("cdcacm", "enum_init() failed");
return -EIO;
}
/* Register enumeration data */
enum_register_descriptor(
ENUM_DESC_DEVICE, (uint8_t *)&device_descriptor, 0
);
enum_register_descriptor(
ENUM_DESC_CONFIG, (uint8_t *)&config_descriptor, 0
);
enum_register_descriptor(ENUM_DESC_STRING, lang_id_desc, 0);
enum_register_descriptor(ENUM_DESC_STRING, mfg_id_desc, 1);
enum_register_descriptor(ENUM_DESC_STRING, prod_id_desc, 2);
/* Handle configuration */
enum_register_callback(ENUM_SETCONFIG, setconfig_callback, NULL);
/* Handle feature set/clear */
enum_register_callback(ENUM_SETFEATURE, setfeature_callback, NULL);
enum_register_callback(ENUM_CLRFEATURE, clrfeature_callback, NULL);
/* Initialize the class driver */
if (acm_init(&config_descriptor.comm_interface_descriptor) != 0) {
LOG_ERR("cdcacm", "acm_init() failed");
return -EIO;
}
/* Register callbacks */
usb_event_enable(MAXUSB_EVENT_NOVBUS, event_callback, NULL);
usb_event_enable(MAXUSB_EVENT_VBUS, event_callback, NULL);
acm_register_callback(ACM_CB_READ_READY, usb_read_callback);
usb_read_complete = 0;
/* Start with USB in low power mode */
usb_app_sleep();
/* TODO: Fix priority */
NVIC_SetPriority(USB_IRQn, 6);
NVIC_EnableIRQ(USB_IRQn);
return 0;
}
int cdcacm_num_read_avail(void)
{
return acm_canread();
}
uint8_t cdcacm_read(void)
{
while (acm_canread() <= 0) {
}
uint8_t buf;
acm_read(&buf, 1);
return buf;
}
void cdcacm_write(uint8_t *data, int len)
{
static int lockup_disable = 0;
if (acm_present() && !lockup_disable) {
int ret = acm_write(data, len);
if (ret < 0) {
lockup_disable = 1;
LOG_ERR("cdcacm", "fifo lockup detected");
} else if (ret != len) {
LOG_WARN(
"cdcacm", "write length mismatch, got %d", ret
);
}
}
}
/******************************************************************************/
#if 0
static void echo_usb(void)
{
int chars;
uint8_t buffer[BUFFER_SIZE];
if ((chars = acm_canread()) > 0) {
if (chars > BUFFER_SIZE) {
chars = BUFFER_SIZE;
}
// Read the data from USB
if (acm_read(buffer, chars) != chars) {
printf("acm_read() failed\n");
return;
}
// Echo it back
if (acm_present()) {
if (acm_write(buffer, chars) != chars) {
printf("acm_write() failed\n");
}
}
}
}
#endif