Skip to content
This repository has been archived by the owner on Nov 11, 2024. It is now read-only.

Commit

Permalink
Iteration N: Michael's iteration.
Browse files Browse the repository at this point in the history
A new common API, the wrap-safe `uTimeout` API, is added and all timeouts are routed through it.  The implementation of the API includes the ability to speed up the apparent wrap-rate of the underlying tick; this will be used on one of our test instances to give it a good thrashing.
  • Loading branch information
RobMeades committed Apr 3, 2024
1 parent 3cf5348 commit 01f1aac
Show file tree
Hide file tree
Showing 145 changed files with 3,959 additions and 1,154 deletions.
4 changes: 2 additions & 2 deletions DEVELOPMENT_PRINCIPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ The only exception to the above is when there has been active work on the `ubxli
As an aside, if `master` moves on underneath a branch **THAT YOU ALONE** are working on, please do a `rebase` of that development branch onto `master`, rather then merging the changes from `master` onto your branch, (i.e. checkout `master` locally, pull the latest `master` and then `rebase` your branch onto `master`); the reason for this is that, otherwise, the merge process can be confused and end up thinking that you intend to remove things that have just been added in the `master` branch. If you share the branch with someone else, i.e. you are not working on it alone, then take care because rebasing obviously changes history; it may still be the right thing to do, 'cos the ground has indeed moved underneath you, history _has_ changed, but make sure that anyone else who is working on the branch with you is aware of what you have done when you push the branch back to the repo.

# Beware The Wrap
Embedded systems usually have no better than a 32 bit millisecond tick count, i.e. a signed 32 bit counter that will wrap at `INT32_MAX`, so modulo 2^31, or 2,147,483,648, or about 25 days; the return value of the port layer `uPortGetTickTimeMs()` is an `int32_t` for this reason.
Embedded systems usually have no better than a 32 bit millisecond tick count, i.e. a 32 bit counter that will wrap at 2^32 - 1, or 4,294,967,295, or about 50 days (25 days if treated as signed); the return value of the port layer `uPortGetTickTimeMs()` is a 32-bit integer for this reason.

The systems that `ubxlib` is built into will need to be up for longer than 25 days, so the `ubxlib` code must behave well around such a wrap and, specifically, not unintentionally become stuck for 25 days if the tick counter happens to wrap while the code is waiting on it. Always use the `uPortTickTimeExpiredMs()` or `uPortTickTimeBeyondStopMs()` functions (see [u_port.h](/port/api/u_port.h)) while waiting for a number of ticks to pass; these are designed to ensure that nothing will get stuck.
The systems that `ubxlib` is built into will need to be up for longer than 50 days, so the `ubxlib` code must behave well around such a wrap and, specifically, not unintentionally become stuck for 50 days if the tick counter happens to wrap while the code is waiting on it. For any timeouts or delays, **always** use the [uTimeout](/common/timeout/api/u_timeout.h) API, which defines an "anonymous" `uTimeoutStart_t` structure that can be populated with a call to `uTimeoutStart()` and then checked with the `uTimeoutExpiredMs()` or the `uTimeoutExpiredSeconds()` functions; these are designed to ensure that nothing will get stuck.

# Be Explicit About Units
Where a number represents a quantity it will have a unit: seconds, milliseconds, nanoseconds, Volts, milliVolts, decibels, decibels relative to one milliWatt (dBm), words (as opposed to bytes), sheep, etc. You may recall the tale of the [Mars Climate Orbiter](https://en.wikipedia.org/wiki/Mars_Climate_Orbiter), a $327 million spacecraft that was lost because the NASA navigation software expected measurements in newton-seconds while their contractor was providing measurements in pound-force seconds, a factor of 4.5 different; where a number represents a quantity, **be explicit** about the unit by including it in the variable/parameter name. For instance, presented with a variable/parameter named `timeout`, you could get things wrong by three orders of magnitude or more when applying that parameter, without realising it; naming it something like `timeoutMs` or `timeoutSeconds` will make the intended usage clear.
236 changes: 204 additions & 32 deletions ble/api/u_ble_gap.h

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions ble/src/gen2/u_ble_cfg_extmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
#include "u_cfg_sw.h"
#include "u_port_os.h"

#include "u_timeout.h"

#include "u_at_client.h"

#include "u_short_range_module_type.h"
Expand Down
1 change: 1 addition & 0 deletions ble/src/gen2/u_ble_gap_extmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "stdlib.h" // strol(), atoi(), strol(), strtof()
#include "string.h" // memset(), strncpy(), strtok_r(), strtol()
#include "u_error_common.h"
#include "u_timeout.h"
#include "u_at_client.h"
#include "u_ble.h"
#include "u_ble_cfg.h"
Expand Down
1 change: 1 addition & 0 deletions ble/src/gen2/u_ble_gatt_extmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "stdlib.h" // strol(), atoi(), strol(), strtof()
#include "string.h" // memset(), strncpy(), strtok_r(), strtol()
#include "u_error_common.h"
#include "u_timeout.h"
#include "u_at_client.h"
#include "u_ble.h"
#include "u_ble_cfg.h"
Expand Down
1 change: 1 addition & 0 deletions ble/src/gen2/u_ble_sps_extmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "u_port_event_queue.h"
#include "u_cfg_os_platform_specific.h"

#include "u_timeout.h"
#include "u_at_client.h"
#include "u_ble_sps.h"
#include "u_ble_private.h"
Expand Down
2 changes: 2 additions & 0 deletions ble/src/u_ble_cfg_extmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
#include "u_cfg_sw.h"
#include "u_port_os.h"

#include "u_timeout.h"

#include "u_at_client.h"

#include "u_short_range_module_type.h"
Expand Down
1 change: 1 addition & 0 deletions ble/src/u_ble_gap_extmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "stdlib.h" // strol(), atoi(), strol(), strtof()
#include "string.h" // memset(), strncpy(), strtok_r(), strtol()
#include "u_error_common.h"
#include "u_timeout.h"
#include "u_at_client.h"
#include "u_ble.h"
#include "u_ble_cfg.h"
Expand Down
1 change: 1 addition & 0 deletions ble/src/u_ble_gatt_extmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "stdlib.h" // strol(), atoi(), strol(), strtof()
#include "string.h" // memset(), strncpy(), strtok_r(), strtol()
#include "u_error_common.h"
#include "u_timeout.h"
#include "u_at_client.h"
#include "u_ble.h"
#include "u_ble_cfg.h"
Expand Down
1 change: 1 addition & 0 deletions ble/src/u_ble_nus.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "stdlib.h" // strol(), atoi(), strol(), strtof()
#include "string.h" // memset(), strncpy(), strtok_r(), strtol()
#include "u_error_common.h"
#include "u_timeout.h"
#include "u_at_client.h"
#include "u_ble.h"
#include "u_ble_cfg.h"
Expand Down
1 change: 1 addition & 0 deletions ble/src/u_ble_sps_extmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "u_port_event_queue.h"
#include "u_cfg_os_platform_specific.h"

#include "u_timeout.h"
#include "u_at_client.h"
#include "u_ble_sps.h"
#include "u_ble_private.h"
Expand Down
4 changes: 3 additions & 1 deletion ble/src/u_ble_sps_intmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

#include "u_error_common.h"

#include "u_timeout.h"

#include "u_device_shared.h"

#include "u_cfg_sw.h"
Expand Down Expand Up @@ -1240,7 +1242,7 @@ int32_t uBleSpsSend(uDeviceHandle_t devHandle, int32_t channel, const char *pDat
int32_t time = startTime;

// Note: this loop is constructed slightly differently to usual
// and so can't use uPortTickTimeExpiredMs() but it
// and so can't use uTimeoutExpiredMs() but it
// _does_ perform tick time comparisons in a wrap-safe manner
while ((bytesLeftToSend > 0) && (time - startTimeMs < timeout)) {
int32_t bytesToSendNow = bytesLeftToSend;
Expand Down
Loading

0 comments on commit 01f1aac

Please sign in to comment.