Import of the watch repository from Pebble
65
docs/battery_state.dot
Normal file
|
@ -0,0 +1,65 @@
|
|||
digraph G {
|
||||
compound=true;
|
||||
Initialized [label=<<b>Initialized (0)</b><br/><font color='#6E6E6E'>q is unknown</font>>];
|
||||
PreStandby [label=<<b>PreStandby (8)</b><br/><font color='#6E6E6E'>q < 2 mAh</font>>];
|
||||
Standby [label=<<b>Standby (9)</b><br/><font color='#6E6E6E'>q < 2 mAh (unless manually entered)</font>>];
|
||||
|
||||
/* Charging flow */
|
||||
subgraph cluster0 {
|
||||
{rank=same;
|
||||
FullPlugged [label=<<b>FullPlugged (4)</b><br/><font color='#6E6E6E'>q ~= 130mAh</font>>, group="charging"];
|
||||
O1[style=invis];
|
||||
}
|
||||
{rank=same;
|
||||
HighCharging [label=<<b>HighCharging (5)</b><br/><font color='#6E6E6E'>25 mAh <= q < 130 mAh</font>>, group="charging"];
|
||||
O2[style=invis];
|
||||
}
|
||||
{rank=same;
|
||||
LowCharging [label=<<b>LowCharging (6)</b><br/><font color='#6E6E6E'>5 mAh <= q < 25 mAh</font>>, group="charging"];
|
||||
O3[style=invis];
|
||||
}
|
||||
{rank=same;
|
||||
CriticalCharging [label=<<b>CriticalCharging (7)</b><br/><font color='#6E6E6E'>q < 5 mAh</font>>, group="charging"];
|
||||
O4[style=invis];
|
||||
}
|
||||
|
||||
CriticalCharging -> LowCharging [label=">3.2V", constraint=false, weight=100];
|
||||
LowCharging -> HighCharging [label=">3.8V", constraint=false, weight=100];
|
||||
HighCharging -> FullPlugged [color=green, constraint=false, weight=100];
|
||||
|
||||
edge[style=invis];
|
||||
O1->O2->O3->O4;
|
||||
|
||||
color=blue;
|
||||
}
|
||||
|
||||
subgraph cluster1 {
|
||||
FullDischarging [label=<<b>FullDischarging (1)</b><br/><font color='#6E6E6E'>q > 30mAh (~125h)</font>>, group="discharging"];
|
||||
LowDischarging [label=<<b>LowDischarging (2)</b><br/><font color='#6E6E6E'>5 mAh <= q < 30mAh (~31h)</font>>, group="discharging"];
|
||||
CriticalDischarging [label=<<b>CriticalDischarging (3)</b><br/><font color='#6E6E6E'>2 mAh <= q < 5 mAh (~3h)</font>>, group="discharging"];
|
||||
|
||||
FullDischarging -> LowDischarging [label="<=3.7V"];
|
||||
LowDischarging -> CriticalDischarging [label="<=3.3V"];
|
||||
CriticalDischarging -> PreStandby [label="<=3.1V"];
|
||||
|
||||
color=red;
|
||||
}
|
||||
|
||||
Initialized -> FullDischarging [color=red, lhead=cluster1];
|
||||
Initialized -> FullPlugged [color=blue, lhead=cluster0, constraint=false];
|
||||
|
||||
|
||||
FullPlugged -> FullDischarging [color=red]
|
||||
CriticalCharging -> PreStandby [color=red, weight=0.1];
|
||||
HighCharging -> FullDischarging [color=red, constraint=false, weight=0.1];
|
||||
LowCharging -> FullDischarging [color=red, constraint=false, weight=0.1];
|
||||
|
||||
FullDischarging -> LowCharging [color=blue, weight=0.01];
|
||||
FullDischarging -> HighCharging [color=blue, constraint=false, weight=0.1];
|
||||
LowDischarging -> LowCharging [color=blue, constraint=false, weight=0.1];
|
||||
CriticalDischarging -> LowCharging [color=blue, constraint=false, weight=0.1];
|
||||
|
||||
|
||||
PreStandby -> CriticalCharging [color=blue, weight=0.1];
|
||||
PreStandby -> Standby [label="30s timeout", weight=0.1];
|
||||
}
|
500
docs/common.dox
Normal file
|
@ -0,0 +1,500 @@
|
|||
/**
|
||||
|
||||
@defgroup Foundation Foundation
|
||||
\brief The core of the Pebble SDK
|
||||
|
||||
The Pebble SDK consists of different frameworks that are organized by functionality.
|
||||
Each framework includes an API and provides access to the software libraries supported
|
||||
natively by Pebble OS. You use these interfaces (APIs) in the C programming
|
||||
language to write software for the Pebble platform.
|
||||
|
||||
Frameworks are grouped hierarchically into Foundation, Graphics, Standard C and User Interface.
|
||||
|
||||
The Foundation framework is the core of the Pebble OS.
|
||||
|
||||
@defgroup Graphics Graphics
|
||||
\brief Low-level drawing routines
|
||||
|
||||
The Graphics framework defines a set of APIs that can be used to draw paths, primitives and text,
|
||||
as well as handle the loading of fonts and the setting of graphics contexts for compositing, fill color
|
||||
and text color.
|
||||
|
||||
@defgroup Smartstrap
|
||||
\brief Communicating with a Smartstrap
|
||||
|
||||
Smartstrap APIs allow Pebble watches to communicate with electronics connected to the
|
||||
watch through the accessory port.
|
||||
|
||||
Apps communicate with smartstraps by manipulating the attributes which the smartstrap supports
|
||||
or by reading and writing raw data using the raw data attribute (see \ref
|
||||
SMARTSTRAP_RAW_DATA_SERVICE_ID and \ref SMARTSTRAP_RAW_DATA_ATTRIBUTE_ID). A service is a collection of
|
||||
attributes which may be supported by a smartstrap. Once a smartstrap is connected, the
|
||||
availability handler will be called (if subscribed) for each service which is supported by the
|
||||
smartstrap. Then, the app may make read and write requests to attributes within that service on
|
||||
the smartstrap.
|
||||
|
||||
Performing a read request on an attribute will cause the did_read handler to be called for the
|
||||
attribute when either a valid response is received from the smartstrap, or some error (i.e. a
|
||||
timeout) occurs.
|
||||
|
||||
Performing a write request on an attribute will cause the did_write handler to be called for the
|
||||
attribute when the write is completed or an error occurs.
|
||||
|
||||
When either the first attribute is created (see \ref smartstrap_attribute_create), or an
|
||||
availability_did_change handler is subscribed (see \ref smartstrap_subscribe), whichever comes
|
||||
first, power will be applied to the smartstrap, and connection establishment will begin. As part
|
||||
of the connection establishment, the smartstrap will report the services which it supports, at
|
||||
which point the smartstrap APIs will report them as being available and allow requests to be
|
||||
issued. If all created attributes are destroyed (see \ref smartstrap_attribute_destroy) and the
|
||||
availability_did_change handler is unsubscribed (see \ref smartstrap_unsubscribe), power will no
|
||||
longer be applied to the smartstrap and the services which it supported will no longer be
|
||||
available.
|
||||
|
||||
Multiple attributes may have a read or write request pending at any given time, but individual
|
||||
attributes may only have a single request (either read or write) pending at any given time.
|
||||
|
||||
Calls made to \ref smartstrap_attribute_create on a platform that does not support smartstraps
|
||||
will return NULL. Other calls will do nothing, and return SmartstrapResultNotPresent if
|
||||
possible.
|
||||
|
||||
For code samples, a list of available attributes, and technical details of the Smartstrap
|
||||
protocol, see the
|
||||
<a href="//developer.getpebble.com/guides/hardware/">Building Smartstraps Guide</a>.
|
||||
|
||||
@defgroup UI User Interface
|
||||
\brief Everything related to user interface
|
||||
|
||||
The User Interface framework enables your Pebble watchface or watchapp to handle basic UI components,
|
||||
like clicks, layers, vibes, windows and window stacks.
|
||||
|
||||
@defgroup Fonts Fonts
|
||||
\brief Custom and system fonts
|
||||
|
||||
|
||||
Pebble OS provides you with a wide range of system fonts that you can use when you need to display and
|
||||
render text or numbers in your Pebble watchface or watchapp.
|
||||
|
||||
If you want to use a system font, you call fonts_get_system_font() and simply pass it the name of the
|
||||
system font you want.
|
||||
|
||||
To use a custom font, call fonts_load_custom_font(). The sample code feature_custom_font shows how you can
|
||||
do this programmatically, using a font resource to convert a TrueType font into a rasterized version of that
|
||||
font at a specified font size.
|
||||
|
||||
For example:
|
||||
|
||||
\code{.c}
|
||||
GFont custom_font = fonts_load_custom_font
|
||||
(resource_get_handle(RESOURCE_ID_FONT_OSP_DIN_44));
|
||||
\endcode
|
||||
|
||||
Raster Gothic Condensed is the font used throughout the Pebble system, largely because it is optimized
|
||||
for monochromatic displays. Pebble selected this font because it allows a relatively large number of
|
||||
characters to be displayed on a single line, also because the font has an excellent readability vs. size ratio.
|
||||
|
||||
Refer to the chapter \htmlinclude UsingResources.html which explains how to work with font resources and embed
|
||||
a font into your app.
|
||||
|
||||
@defgroup Math Math
|
||||
\brief Math routines.
|
||||
|
||||
Below is a code example that uses the trigonometry functions to calculate the coordinate at which
|
||||
the second hand of a watch ends, using seconds from the system time.
|
||||
\code{.c}
|
||||
GPoint secondHand;
|
||||
GPoint center;
|
||||
struct tm *tick_time = ...;
|
||||
int32_t secondHandLength = ...;
|
||||
...
|
||||
int32_t second_angle = TRIG_MAX_ANGLE * tick_time->tm_sec / 60;
|
||||
secondHand.y = (-cos_lookup(second_angle) * secondHandLength / TRIG_MAX_RATIO) + center.y;
|
||||
secondHand.x = (sin_lookup(second_angle) * secondHandLength / TRIG_MAX_RATIO) + center.x;
|
||||
\endcode
|
||||
|
||||
|
||||
@defgroup EventService Event Service
|
||||
\brief APIs to handle event services
|
||||
|
||||
Pebble OS provides you with a set of APIs for handling event services, like accelerometer taps, app focus
|
||||
for interactivity, battery states, Bluetooth connections, and tick timers to call when a time component has
|
||||
changed. You use event services to be notified, for example, when something happens on Pebble, like losing
|
||||
the connection to the phone or when a notification covers the screen and requires your Pebble game to pause.
|
||||
|
||||
@defgroup App App
|
||||
\brief App entry point and event loop.
|
||||
|
||||
|
||||
App is a module that provides you with an event loop for your Pebble app.
|
||||
All interaction between Pebble apps and the underlying Pebble OS takes place through an event loop.
|
||||
Before calling the \ref app_event_loop() function, you subscribe to event services and implement event handlers.
|
||||
Each handler receives specific types of Events dispatched throughout the life of the Pebble watchapp.
|
||||
|
||||
The \ref app_event_loop() function takes care of both waiting for new events to become available on the
|
||||
watchapp event bus and routing new events to the appropriate handler. \ref EventService allows an app to
|
||||
directly register for different types of events. This function will block until the watchapp is ready
|
||||
to exit, and should be placed in the app's main() function.
|
||||
|
||||
A watchapp typically configures and uses the \ref app_event_loop() as follows:
|
||||
|
||||
\code{.c}
|
||||
int main(void) {
|
||||
// do set up here
|
||||
|
||||
// Enter the main event loop. This will block until the app is ready to exit.
|
||||
app_event_loop();
|
||||
|
||||
// do clean up here
|
||||
}
|
||||
\endcode
|
||||
|
||||
@defgroup StandardC Standard C
|
||||
\brief Standard C types, functions, constants, etc.
|
||||
The standard C functions available here, such as \ref snprintf() and \ref time(), are provided by the firmware. Using these functions will not significantly increase the size of your app beyond what is needed to call the function. You may use other standard C functions not listed here, but be aware that not all will successfully be added to your app, and if they are added, your app's binary size will increase accordingly.
|
||||
|
||||
@addtogroup StandardC
|
||||
@{
|
||||
|
||||
@defgroup StandardMath Math
|
||||
\brief Standard math functions.
|
||||
|
||||
@addtogroup StandardMath
|
||||
@{
|
||||
|
||||
\fn int rand()
|
||||
\brief Generate a pseudo-random integer between 0 and \ref RAND_MAX inclusive. This function can be seeded by \ref srand().
|
||||
|
||||
A simple way to change the range to be an integer between 0 and n-1 inclusive is using \% e.g. `rand() % n`.
|
||||
|
||||
\return The pseudo-randomly generated number
|
||||
|
||||
\fn void srand(unsigned int seed)
|
||||
\brief Seed the pseudo-random number generator.
|
||||
|
||||
When your app starts, the pseudo-random number generator is automatically seeded with a random number that is generated by a high-entropy hardware random number generator.
|
||||
|
||||
This function affects subsequent calls to \ref rand() to produce a sequence of numbers for a given seed value. You can use this to either create a different sequence of numbers by always using a different seed or to obtain the same sequence of numbers by reusing the same seed.
|
||||
\param seed The source number used to generate a sequence of pseudo-random numbers
|
||||
|
||||
\def RAND_MAX
|
||||
\brief The maximum integer value \ref rand() may return.
|
||||
|
||||
@}
|
||||
|
||||
@defgroup StandardLocale Locale
|
||||
\brief Standard locale functions.
|
||||
|
||||
@addtogroup StandardLocale
|
||||
@{
|
||||
\fn char *setlocale(int category, char *locale)
|
||||
\brief Set the app's locale for a category of routines.
|
||||
|
||||
`setlocale` can be used to:
|
||||
- set the app's locale to a specific locale: `setlocale(LC_ALL, "en_CA")`
|
||||
- set the app's locale to the system locale: `setlocale(LC_ALL, "")`
|
||||
- get the app's curent locale: `setlocale(LC_ALL, NULL)`
|
||||
|
||||
\param category The category of routines for which to set the locale
|
||||
\param locale The ISO formatted locale to use, or "" for the system locale
|
||||
\return the locale after the change is applied, NULL on failure (e.g. unsuported category)
|
||||
\note Currently, we only support two categories: LC_ALL and LC_TIME
|
||||
|
||||
@}
|
||||
|
||||
@defgroup StandardMemory Memory
|
||||
\brief Standard memory functions.
|
||||
|
||||
@addtogroup StandardMemory
|
||||
@{
|
||||
|
||||
\fn void *malloc(size_t size)
|
||||
\brief Allocates a requested amount of memory.
|
||||
\param size The number of bytes to allocate
|
||||
\return A pointer to the allocated memory or NULL on error.
|
||||
|
||||
\fn void free(void *ptr)
|
||||
\brief Frees previously allocated memory.
|
||||
\param ptr The memory buffer to free.
|
||||
|
||||
\fn void *calloc(size_t count, size_t size)
|
||||
\brief Allocates space for count objects that are size bytes and fills the
|
||||
memory with bytes of value 0
|
||||
\param count The number of objects to allocate space for
|
||||
\param size The size of the object type being allocated
|
||||
\return A pointer to the allocated memory or NULL on error.
|
||||
|
||||
\fn void *realloc(void *ptr, size_t size)
|
||||
\brief Takes the memory allocated at ptr and changes the length of its
|
||||
allocation to the size specified. Copies the smaller of the length of the
|
||||
original allocation or the new size into the newly allocated buffer.
|
||||
\param ptr The memory allocation to be changed
|
||||
\param size The size to change the ptr allocation to
|
||||
\return A pointer to the new allocated memory or NULL on error
|
||||
|
||||
\fn int memcmp(const void *ptr1, const void *ptr2, size_t n)
|
||||
\brief Compares the first n bytes of memory regions ptr1 and ptr2
|
||||
\param ptr1 The pointer to the first memory region to compare
|
||||
\param ptr2 The pointer to the second memory region to compare
|
||||
\param n The number of bytes to compare
|
||||
\return 0 if the first n bytes of ptr1 and ptr 2 match. Otherwise, the sign is determined by the sign of the difference between the first pair of bytes that differ in ptr1 and ptr2.
|
||||
|
||||
\fn void *memcpy(void *dest, const void *src, size_t n)
|
||||
\brief Copies n bytes from src to dest.
|
||||
\param dest The pointer to the destination memory region
|
||||
\param src The pointer to the source memory region
|
||||
\param n The number of bytes to copy
|
||||
|
||||
\fn void *memmove(void *dest, const void *src, size_t n);
|
||||
\brief Copies n bytes from src to dest by first copying to a temporary area first, allowing dest and src to potentially overlap. This can be used to move data to a location that overlaps its previous location.
|
||||
\param dest The pointer to the destination memory region
|
||||
\param src The pointer to the source memory region
|
||||
\param n The number of bytes to copy
|
||||
|
||||
\fn void *memset(void *dest, int c, size_t n);
|
||||
\brief Sets n bytes to c starting at dest. This can be used to clear a memory region for example if c is 0.
|
||||
\param dest The pointer to the destination memory region
|
||||
\param c The integer used as an unsigned char to assign to each byte
|
||||
\param n The number of bytes to set
|
||||
|
||||
\typedef size_t
|
||||
\brief size as an unsigned integer
|
||||
|
||||
@}
|
||||
|
||||
@defgroup StandardIO Format
|
||||
\brief Standard formatting. If you're looking for input/output functions, check out the \ref Logging API.
|
||||
|
||||
@addtogroup StandardIO
|
||||
@{
|
||||
|
||||
\fn int snprintf(char *str, size_t n, const *fmt, ...);
|
||||
\brief Format a string into a buffer. The Pebble-supported format specifiers are displayed below.
|
||||
|
||||
\param str The string buffer to write the formatted string into
|
||||
\param n The maximum size of the buffer
|
||||
\param fmt The C formatting string
|
||||
\return The number of bytes written
|
||||
|
||||
\htmlonly
|
||||
<style type="text/css">
|
||||
.tg {border-collapse:collapse;border-spacing:0;}
|
||||
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
|
||||
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
|
||||
</style>
|
||||
<table class="tg">
|
||||
<tr>
|
||||
<th class="tg-031e">Specifier</th>
|
||||
<th class="tg-031e">Output</th>
|
||||
<th class="tg-031e">Example</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">d or i</td>
|
||||
<td class="tg-031e">Signed decimal integer</td>
|
||||
<td class="tg-031e">294<br>-294</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">u</td>
|
||||
<td class="tg-031e">Unsigned decimal integer</td>
|
||||
<td class="tg-031e">7235</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">o</td>
|
||||
<td class="tg-031e">Unsigned octal</td>
|
||||
<td class="tg-031e">610</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">x</td>
|
||||
<td class="tg-031e">Unsigned hexadecimal integer</td>
|
||||
<td class="tg-031e">8b2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">X</td>
|
||||
<td class="tg-031e">Unsigned hexadecimal integer (uppercase)</td>
|
||||
<td class="tg-031e">8B2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">c</td>
|
||||
<td class="tg-031e">Character</td>
|
||||
<td class="tg-031e">h</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">s</td>
|
||||
<td class="tg-031e">Null-terminated string of characters</td>
|
||||
<td class="tg-031e">pebble</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">p</td>
|
||||
<td class="tg-031e">Pointer address</td>
|
||||
<td class="tg-031e">0xb8000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">%</td>
|
||||
<td class="tg-031e">A % followed by another % character will write a single % to the stream.</td>
|
||||
<td class="tg-031e">%</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
\endhtmlonly
|
||||
|
||||
\details Length specifiers can also be combined with the format specifiers above:
|
||||
|
||||
\htmlonly
|
||||
<style type="text/css">
|
||||
.tg {border-collapse:collapse;border-spacing:0;}
|
||||
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
|
||||
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
|
||||
.tg .tg-s6z2{text-align:center}
|
||||
</style>
|
||||
<table class="tg">
|
||||
<tr>
|
||||
<th class="tg-031e"></th>
|
||||
<th class="tg-s6z2">u o x X</th>
|
||||
<th class="tg-s6z2">c</th>
|
||||
<th class="tg-s6z2">s</th>
|
||||
<th class="tg-s6z2">p</th>
|
||||
<th class="tg-s6z2">n</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">(none)</td>
|
||||
<td class="tg-031e">unsigned int</td>
|
||||
<td class="tg-031e">int</td>
|
||||
<td class="tg-031e">char*</td>
|
||||
<td class="tg-031e">void*</td>
|
||||
<td class="tg-031e">int*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">h</td>
|
||||
<td class="tg-031e">unsigned short int</td>
|
||||
<td class="tg-031e"></td>
|
||||
<td class="tg-031e"></td>
|
||||
<td class="tg-031e"></td>
|
||||
<td class="tg-031e">short int*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-031e">l</td>
|
||||
<td class="tg-031e">unsigned long int</td>
|
||||
<td class="tg-031e">wint_t</td>
|
||||
<td class="tg-031e">wchar_t*</td>
|
||||
<td class="tg-031e"></td>
|
||||
<td class="tg-031e">long int*</td>
|
||||
</tr>
|
||||
</table>
|
||||
\endhtmlonly
|
||||
|
||||
@}
|
||||
|
||||
@defgroup StandardString String
|
||||
\brief Standard C-string manipulation.
|
||||
|
||||
@addtogroup StandardString
|
||||
@{
|
||||
|
||||
\fn int strcmp(const char *str1, const char *str2)
|
||||
\brief Compares the null terminated strings str1 and str2 to each other.
|
||||
\param str1 The first C string to compare
|
||||
\param str2 The second C string to compare
|
||||
\return The difference of the first differing pair of bytes or 0 if the strings are identical
|
||||
|
||||
\fn int strncmp(const char *str1, const char *str2, size_t n)
|
||||
\brief Compares the null terminated strings str1 and str2 to each other for up to n bytes. Comparison ends when a null is read or when n bytes are read, whichever happens first.
|
||||
\param str1 The first C string to compare
|
||||
\param str2 The second C string to compare
|
||||
\param n The maximum number of bytes to compare
|
||||
\return The difference of the first differing pair of bytes or the final pair of bytes read or 0 if the portions of the strings read are identical
|
||||
|
||||
\fn char *strcpy(char *dest, const char *src)
|
||||
\brief Copies the string in src into dest and null terminates dest. There should be no overlap of dest and src in memory.
|
||||
\param dest The destination buffer with enough space for src
|
||||
\param src The source C string
|
||||
\return The destination buffer dest
|
||||
|
||||
\fn char *strncpy(char *dest, const char *src, size_t n)
|
||||
\brief Copies up to n bytes from the string in src into dest and null terminates dest. If dest is null terminated before n bytes have been written, null bytes will continue to be written until n bytes total were written. There should be no overlap of dest and src in memory.
|
||||
\param dest The destination buffer with enough space for n bytes
|
||||
\param src The source string
|
||||
\param n The number of bytes to copy
|
||||
\return The destination buffer dest
|
||||
|
||||
\fn char *strcat(char *dest, const char *src)
|
||||
\brief Concatenates the string in src to the end of the string pointed by dest and null terminates dest. There should be no overlap of dest and src.
|
||||
\param dest The destination buffer with enough space for src beyond the null character
|
||||
\param src The source C string
|
||||
\return The destination buffer dest
|
||||
|
||||
\fn char *strncat(char *dest, const char *src, size_t n)
|
||||
\brief Concatenates up to n bytes from the string in src to the end of the string pointed by dest and null terminates dest. There should be no overlap of dest and src in memeory.
|
||||
\param dest The destination buffer with enough space for src beyond the null character
|
||||
\param src The source string
|
||||
\param n The maximum number of bytes to copy
|
||||
\return The destination buffer dest
|
||||
|
||||
\fn size_t strlen(const char *str)
|
||||
\brief Calculates the length of a null terminated string.
|
||||
\param str The C string.
|
||||
\return The length of the C string str.
|
||||
|
||||
@}
|
||||
|
||||
@addtogroup StandardTime
|
||||
@{
|
||||
|
||||
\typedef time_t
|
||||
time in seconds since the epoch, January 1st 1970
|
||||
|
||||
@}
|
||||
|
||||
\typedef unsigned int uint32_t
|
||||
\brief 32-bit unsigned integer number
|
||||
|
||||
\typedef unsigned int uint16_t
|
||||
\brief 16-bit unsigned integer number
|
||||
|
||||
@}
|
||||
|
||||
@defgroup Misc Miscellaneous
|
||||
\brief Miscellaneous
|
||||
|
||||
Useful helper functionality for building your pebble application that doesn't fit in any other category.
|
||||
|
||||
*/
|
||||
|
||||
/* stdio.h */
|
||||
int snprintf(char *str, size_t n, const *fmt, ...);
|
||||
|
||||
/* stdlib.h */
|
||||
#define RAND_MAX
|
||||
int rand();
|
||||
void srand(unsigned int seed);
|
||||
void *malloc(size_t size);
|
||||
void *calloc(size_t count, size_t size);
|
||||
void *realloc(void *ptr, size_t size);
|
||||
void free(void *ptr);
|
||||
|
||||
/* string.h */
|
||||
typedef unsigned int size_t;
|
||||
int memcmp(const void *ptr1, const void *ptr2, size_t n);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
void *memset(void *dest, int c, size_t n);
|
||||
int strcmp(const char *str1, const char *str2);
|
||||
int strncmp(const char *str1, const char *str2, size_t n);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
char *strncpy(char *dest, const char *src, size_t n);
|
||||
char *strcat(char *dest, const char *src);
|
||||
char *strncat(char *dest, const char *src, size_t n);
|
||||
size_t strlen(const char *str);
|
||||
|
||||
/* locale.h */
|
||||
char *setlocale(int category, char *locale);
|
||||
|
||||
/* time.h */
|
||||
typedef unsigned int time_t;
|
||||
|
||||
/* C99 integer types */
|
||||
typedef int int8_t;
|
||||
typedef int uint8_t;
|
||||
typedef int int16_t;
|
||||
typedef int uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef int uint32_t;
|
||||
typedef int int64_t;
|
||||
typedef int uint64_t;
|
11
docs/docstring-help.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
Doxygen pro tips
|
||||
---
|
||||
|
||||
- Define top-level groups and other doxygen constructs in `docs/common.dox`.
|
||||
- The main page can be found in `docs/mainpage_sdk.dox`
|
||||
- Use \ref to create a cross reference in the documentation to another group, function, struct, or any kind of symbol, for example: `Use \ref app_event_loop() to do awesome shit.` will create a clickable link to the documentation of app_event_loop. Don't forget to add the () parens if the symbol is a function! Using angle brackets like <app_event_loop()> doesn't seem to work reliably, nor does the automatic detection of symbols.
|
||||
- Use the directive `@internal` to indicate that a piece of documentation is internal and should not be included in the public SDK documentation. You can add the @internal halfway, so that the first part of your docstrings will be included in the public SDK documentation, and the part after the @internal directive will also get included in our internal docs.
|
||||
- Use `@param param_name Description of param` to document a function parameter.
|
||||
- Use `@return Description of return value` to document the return value of a function.
|
||||
- If you need to add a file or directory that doxygen should index, add its path to `INPUT` in the Doxyfile-SDK configuration file.
|
||||
- If you want to make a cross-reference to an external doc page (the conceptual pages on developer.getpebble.com), create an .html file in /docs/external_refs, containing only a <a> link to the page. Then use `\htmlinclude my_ref.html` to include that link in the docs. This extra level of indirection will make it easy to relocate external pages later on.
|
17
docs/external_refs/UiFramework.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<a href="https://developer.getpebble.com/guides/pebble-apps/display-and-animations/layers/">User Interface Layers chapter in the Pebble Developer Guides</a>
|
17
docs/external_refs/UsingResources.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<a href="https://developer.getpebble.com/guides/pebble-apps/resources/">App Resources in the Pebble Developer Guides</a>
|
17
docs/external_refs/app-phone-communication.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<a href="http://developer.getpebble.com/guides/pebble-apps/communications/">App Communication in the Pebble Developer Guides</a>
|
17
docs/external_refs/migration-guide.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<a href="http://developer.getpebble.com/sdk/migration-guide/">2.0 Migration Guide</a>
|
BIN
docs/images/action_bar_layer.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
docs/images/animations.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
docs/images/app_loop.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
docs/images/app_message.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
docs/images/app_sync.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
docs/images/bitmap_layer.png
Normal file
After Width: | Height: | Size: 103 KiB |
BIN
docs/images/compops.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
docs/images/fonts.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
docs/images/galign.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/images/gbitmap.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
docs/images/inverter_layer.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
docs/images/menu_layer.png
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
docs/images/number_window.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
docs/images/pixel_bit_values.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
docs/images/scroll_layer.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
docs/images/simple_menu_layer.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
docs/images/text_layer.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
docs/images/window_stack.png
Normal file
After Width: | Height: | Size: 62 KiB |
85
docs/legacy_flash_imaging.txt
Normal file
|
@ -0,0 +1,85 @@
|
|||
SPI Flash Imaging Using The Serial Console
|
||||
==========================================
|
||||
|
||||
NOTE: This document describes the original method of flash imaging
|
||||
over the serial console. It is no longer used and has been superseded by
|
||||
newer, faster methods.
|
||||
|
||||
By default the serial console is in logging mode, where log messages
|
||||
are echoed to the screen as they are issued. To enter the serial
|
||||
prompt, send a CTRL-C character to the serial console. The prompt
|
||||
looks like a single right angle bracket ('>'). Commands may be typed
|
||||
at this prompt and executed using the enter key.
|
||||
|
||||
There are several commands available that can be used to manipulate
|
||||
the SPI flash contents.
|
||||
|
||||
dump flash <address> <length>
|
||||
=============================
|
||||
|
||||
This command will dump a section of SPI flash. The address must be specified
|
||||
in hex with a leading '0x'. The length is in bytes.
|
||||
|
||||
Ex:
|
||||
|
||||
>dump flash 0x200000 128
|
||||
[00:26:38.263] ../src/core/console/prompt.c:115> Data at address 0x200000
|
||||
[00:26:38.271] ../src/core/util/hexdump.c:11> 0000 0c 00 00 00 74 bf 03 00 32 9a 8a 4b 90 81 00 20 ....t... 2..K...
|
||||
[00:26:38.283] ../src/core/util/hexdump.c:11> 0010 2d a0 01 08 7d a0 01 08 19 93 01 08 7d a0 01 08 -...}... ....}...
|
||||
[00:26:38.294] ../src/core/util/hexdump.c:11> 0020 7d a0 01 08 7d a0 01 08 00 00 00 00 00 00 00 00 }...}... ........
|
||||
[00:26:38.307] ../src/core/util/hexdump.c:11> 0030 00 00 00 00 00 00 00 00 01 8a 01 08 7d a0 01 08 ........ ....}...
|
||||
[00:26:38.319] ../src/core/util/hexdump.c:11> 0040 00 00 00 00 9d 8a 01 08 d9 8a 01 08 7d a0 01 08 ........ ....}...
|
||||
[00:26:38.332] ../src/core/util/hexdump.c:11> 0050 7d a0 01 08 7d a0 01 08 7d c9 01 08 7d a0 01 08 }...}... }...}...
|
||||
[00:26:38.343] ../src/core/util/hexdump.c:11> 0060 7d a0 01 08 29 59 01 08 3b 59 01 08 4d 59 01 08 }...)Y.. ;Y..MY..
|
||||
[00:26:38.355] ../src/core/util/hexdump.c:11> 0070 5f 59 01 08 7d a0 01 08 7d a0 01 08 7d a0 01 08 _Y..}... }...}...
|
||||
>
|
||||
|
||||
erase flash <address> <length>
|
||||
==============================
|
||||
|
||||
This command will erase a section of SPI flash in 64k chunks. The address must be
|
||||
specified in hex with a leading '0x'. The address must be 64k aligned. The length
|
||||
is in bytes, and will be rounded up to the next 64k boundary. 'OK' will be echoed to
|
||||
the console once the erase operation is complete.
|
||||
|
||||
Ex:
|
||||
|
||||
>erase flash 0x0 128
|
||||
Erasing 64k flash sectors starting at address 0x0 for 128 bytes (rounded up to 65536 bytes)
|
||||
OK
|
||||
>
|
||||
|
||||
write flash <address>
|
||||
=====================
|
||||
|
||||
This command allows a user to write bytes to SPI flash. Please ensure
|
||||
the region being written to has already been erased. The address must
|
||||
be specified in hex with a leading '0x'.
|
||||
|
||||
Bytes must be written using base64 encoding. The base64 characters are
|
||||
not echoed back to the console as they are written. Bytes are written
|
||||
to flash in chunks of 1024 base64 characters, corresponding to 768
|
||||
decoded bytes. The watch will echo a '#' character to acknowledge
|
||||
receipt of a chunk, followed by echoing 'OK' when the watch is ready
|
||||
to receive the next chunk. The end of the final chunk is indicated by
|
||||
sending a CTRL-D character (EOF). The current chunk will be flushed to
|
||||
SPI flash upon receiving an EOF character. Remember to pad the final
|
||||
chunk with '=' characters if it's not a multiple of 3 bytes, as per
|
||||
the base64 encoding standard. To exit the 'write flash' mode without
|
||||
flushing the current chunk, enter a CTRL-C character.
|
||||
|
||||
If a chunk is malformed due to invalid characters or incorrect
|
||||
padding, 'Decoding Error' will be printed to the serial port and the
|
||||
normal serial prompt will return. Note that any previous chunks that
|
||||
were well formed have already been written to SPI flash.
|
||||
|
||||
Ex:
|
||||
|
||||
>write flash 0x0
|
||||
Flash imaging mode, CTRL-D to stop
|
||||
#OK
|
||||
>
|
||||
|
||||
(NB: Your base64 data is not echoed back when writing to flash. The #OK will show up
|
||||
when a chunk is complete or CTRL-D is used.)
|
||||
|
0
docs/mainpage_sdk.dox
Normal file
135
docs/pulse2/flash-imaging.md
Normal file
|
@ -0,0 +1,135 @@
|
|||
PULSE Flash Imaging
|
||||
===================
|
||||
|
||||
This document describes the PULSE flash imaging protocol. This protocol
|
||||
was originally designed for use over PULSEv1, but also works over the
|
||||
PULSEv2 Best-Effort transport.
|
||||
|
||||
The flash imaging protocol is used to write raw data directly to the
|
||||
external flash. It is a message-oriented protocol encapsulated in PULSE
|
||||
frames. The primary goals of the protocol are reliability and speed over
|
||||
high-latency links.
|
||||
|
||||
* All client-sent commands elicit responses
|
||||
|
||||
* As much as possible, any command can be resent without corrupting the
|
||||
flashing process. This is to accommodate the situation where the
|
||||
command was received and acted upon but the response was lost, and the
|
||||
client retried the command.
|
||||
|
||||
* Any notification (server→client message which is not a response to a
|
||||
command) can be lost without holding up the flashing process. There
|
||||
must be a way to poll for the status of all operations which elicit
|
||||
notifications.
|
||||
|
||||
* Most of the state is tracked by the client. The server only has to
|
||||
maintain a minimal, fixed-size amount of state.
|
||||
|
||||
> The idempotence of writing to flash is leveraged in the design of this
|
||||
> protocol to effectively implement a [Selective Repeat ARQ](http://en.wikipedia.org/wiki/Selective_Repeat_ARQ)
|
||||
> with an unlimited window size without requiring the server to keep
|
||||
> track of which frames are missing. Any Write Data command to the same
|
||||
> location in flash can be repeated any number of times with no ill
|
||||
> effects.
|
||||
|
||||
## Message format
|
||||
|
||||
All fields in a message which are more than one octet in length are
|
||||
transmitted least-significant octet (LSB) first.
|
||||
|
||||
All messages begin with a 1-octet Opcode, followed by zero or more data
|
||||
fields depending on the message. All Address fields are offsets from the
|
||||
beginning of flash. Address and Length fields are specified in units of
|
||||
bytes.
|
||||
|
||||
### Client Commands
|
||||
|
||||
#### 1 - Erase flash region
|
||||
|
||||
Address: 4 octets
|
||||
Length: 4 octets
|
||||
|
||||
#### 2 - Write data to flash
|
||||
|
||||
Address: 4 octets
|
||||
Data: 1+ octets
|
||||
|
||||
The data length is implied.
|
||||
|
||||
#### 3 - Checksum flash region
|
||||
|
||||
Address: 4 octets
|
||||
Length: 4 octets
|
||||
|
||||
#### 4 - Query flash region geometry
|
||||
|
||||
Region: 1 octet
|
||||
|
||||
Region | Description
|
||||
-------|-------------------
|
||||
1 | PRF
|
||||
2 | Firmware resources
|
||||
|
||||
#### 5 - Finalize flash region
|
||||
|
||||
Region: 1 octet
|
||||
|
||||
Inform the server that writing is complete and perform whatever task is
|
||||
necessary to finalize the data written to the region. This may be a
|
||||
no-op.
|
||||
|
||||
Region numbers are the same as for the "Query flash region geometry"
|
||||
message.
|
||||
|
||||
### Server Responses
|
||||
|
||||
#### 128 - ACKnowledge erase command
|
||||
|
||||
Address: 4 octets
|
||||
Length: 4 octets
|
||||
Complete?: 1 octet
|
||||
|
||||
Complete field is zero if the erase is in progress, nonzero when the
|
||||
erase is complete.
|
||||
|
||||
#### 129 - ACKnowledge write command
|
||||
|
||||
Address: 4 octets
|
||||
Length: 4 octets
|
||||
Complete?: 1 octet
|
||||
|
||||
#### 130 - Checksum result
|
||||
|
||||
Address: 4 octets
|
||||
Length: 4 octets
|
||||
Checksum: 4 octets
|
||||
|
||||
The legacy Pebble checksum ("STM32 CRC") of the specified memory is
|
||||
returned.
|
||||
|
||||
#### 131 - Flash region geometry
|
||||
|
||||
Region: 1 octet
|
||||
Address: 4 octets
|
||||
Length: 4 octets
|
||||
|
||||
A length of zero indicates that the region does not exist.
|
||||
|
||||
#### 132 - ACKnowledge finalize flash region command
|
||||
|
||||
Region: 1 octet
|
||||
|
||||
#### 192 - Malformed command
|
||||
|
||||
Bad message: 9 octets
|
||||
Error string: 0+ octets
|
||||
|
||||
#### 193 - Internal error
|
||||
|
||||
Error string: 0+ octets
|
||||
|
||||
Something has gone terribly wrong which prevents flashing from
|
||||
proceeding.
|
||||
|
||||
|
||||
<!-- vim: set tw=72: -->
|
165
docs/pulse2/history.md
Normal file
|
@ -0,0 +1,165 @@
|
|||
History of PULSEv2
|
||||
==================
|
||||
|
||||
This document describes the history of the Pebble dbgserial console
|
||||
leading up to the design of PULSEv2.
|
||||
|
||||
In The Beginning
|
||||
----------------
|
||||
|
||||
In the early days of Pebble, the dbgserial port was used to print out
|
||||
log messages in order to assist in debugging the firmware. These logs
|
||||
were plain text and could be viewed with a terminal emulator such as
|
||||
minicom. An interactive prompt was added so that firmware developers and
|
||||
the manufacturing line could interact with the running firmware. The
|
||||
prompt mode could be accessed by pressing CTRL-C at the terminal, and
|
||||
could be exited by pressing CTRL-D. Switching the console to prompt mode
|
||||
suppressed the printing of log messages. Data could be written into the
|
||||
external flash memory over the console port by running a prompt command
|
||||
to switch the console to a special "flash imaging" mode and sending it
|
||||
base64-encoded data.
|
||||
|
||||
This setup worked well enough, though it was slow and a little
|
||||
cumbersome to use at times. Some hacks were tacked on as time went on,
|
||||
like a "hybrid" prompt mode which allowed commands to be executed
|
||||
without suppressing log messages. These hacks didn't work terribly well.
|
||||
But it didn't really matter as the prompt was only used internally and
|
||||
it was good enough to let people get stuff done.
|
||||
|
||||
First Signs of Trouble
|
||||
----------------------
|
||||
|
||||
The problems with the serial console started becoming apparent when
|
||||
we started building out automated integration testing. The test
|
||||
automation infrastructure made extensive use of the serial console to
|
||||
issue commands to simulate actions such as button clicks, inspect the
|
||||
firmware state, install applications, and capture screenshots and log
|
||||
messages. From the very beginning the serial console proved to be very
|
||||
unreliable for test automation's uses, dropping commands, corrupting
|
||||
screenshots and other data, and hiding log messages. The test automation
|
||||
harness which interacted with the dbgserial port became full of hacks
|
||||
and workarounds, but was still very unreliable. While we wanted to have
|
||||
functional and reliable automated testing, we didn't have the manpower
|
||||
at the time to improve the serial console for test automation's use
|
||||
cases. And so test automation remained frustratingly unreliable for a
|
||||
long time.
|
||||
|
||||
PULSEv1
|
||||
-------
|
||||
|
||||
During the development of Pebble Time, the factory was complaining that
|
||||
imaging the recovery firmware onto external flash over the dbgserial
|
||||
port was taking too long and was causing a manufacturing bottleneck. The
|
||||
old flash imaging mode had many issues and was in need of a replacement
|
||||
anyway, and improving the throughput to reduce manufacturing costs
|
||||
finally motivated us to allocate engineering time to replace it.
|
||||
|
||||
The biggest reason the flash imaging protocol was so slow was that it
|
||||
was extremely latency sensitive. After every 768 data bytes sent, the
|
||||
sender was required to wait for the receiver to acknowledge the data
|
||||
before continuing. USB-to-serial adapter ICs are used at both the
|
||||
factory and by developers to interface the watches' dbgserial ports to
|
||||
modern computers, and these adapters can add up to 16 ms latency to
|
||||
communications in each direction. The vast majority of the flash imaging
|
||||
time was wasted with the dbgserial port idle, waiting for the sender to
|
||||
receive and respond to an acknowledgement.
|
||||
|
||||
There were other problems too, such as a lack of checksums. If line
|
||||
noise (which wasn't uncommon at the factory) corrupted a byte into
|
||||
another valid base64 character, the corruption would go unnoticed and be
|
||||
written out to flash. It would only be after the writing was complete
|
||||
that the integrity was verified, and the entire transfer would have to
|
||||
be restarted from the beginning.
|
||||
|
||||
Instead of designing a new flash imaging protocol directly on top of the
|
||||
raw dbgserial console, as the old flash imaging protocol did, a
|
||||
link-layer protocol was designed which the new flash imaging protocol
|
||||
would operate on top of. This new protocol, PULSE version 1, provided
|
||||
best-effort multiprotocol datagram delivery with integrity assurance to
|
||||
any applications built on top of it. That is, PULSE allowed
|
||||
applications to send and receive packets over dbgserial, without
|
||||
interfering with other applications simultaneously using the link, with
|
||||
the guarantee that the packets either will arrive at the receiver intact
|
||||
or not be delivered at all. It was designed around the use-case of flash
|
||||
imaging, with the hope that other protocols could be implemented over
|
||||
PULSE later on. The hope was that this was the first step to making test
|
||||
automation reliable.
|
||||
|
||||
Flash imaging turns out to be rather unique, with affordances that make
|
||||
it easy to implement a performant protocol without protocol features
|
||||
that many other applications would require. Writing to flash memory is
|
||||
an idempotent operation: writing the same bytes to the same flash
|
||||
address _n_ times has the same effect as writing it just once. And
|
||||
writes to different addresses can be performed in any order. Because
|
||||
of these features of flash, each write operation can be treated as a
|
||||
wholly independent operation, and the data written to flash will be
|
||||
complete as long as every write is performed at least once. The
|
||||
communications channel for flash writes does not need to be reliable,
|
||||
only error-free. The protocol is simple: send a write command packet
|
||||
with the target address and data. The receiver performs the write and
|
||||
sends an acknowledgement with the address. If the sender doesn't receive
|
||||
an acknowledgement within some timeout, it re-sends the write command.
|
||||
Any number of write commands and acknowledgements can be in-flight
|
||||
simulatneously. If a write completes but the acknowledgement is lost in
|
||||
transit, the sender can re-send the same write command and the receiver
|
||||
can naively overwrite the data without issue due to the idempotence of
|
||||
flash writes.
|
||||
|
||||
The new PULSE flash imaging protocol was a great success, reducing
|
||||
imaging time from over sixty seconds down to ten, with the bottleneck
|
||||
being the speed at which the flash memory could be erased or written.
|
||||
After the success of PULSE flash imaging, attempts were made to
|
||||
implement other protocols on top of it, with varying degrees of success.
|
||||
A protocol for streaming log messages over PULSE was implemented, as
|
||||
well as a protocol for reading data from external flash. There were
|
||||
attempts to implement prompt commands and even an RPC system using
|
||||
dynamically-loaded binary modules over PULSE, but they required reliable
|
||||
and in-order delivery, and implementing a reliable transmission scheme
|
||||
separately for each application protocol proved to be very
|
||||
time-consuming and bug-prone.
|
||||
|
||||
Other flaws in PULSE became apparent as it came into wider use. The
|
||||
checksum used to protect the integrity of PULSE frames was discovered to
|
||||
have a serious flaw, where up to three trailing 0x00 bytes could be
|
||||
appended to or dropped from a packet without changing the checksum
|
||||
value. This flaw, combined with the lack of explicit length fields in
|
||||
the protocol headers, made it much more likely for PULSE flash imaging
|
||||
to write corrupted data. This was discovered shortly after test
|
||||
automation switched over to PULSE flash imaging.
|
||||
|
||||
Make TA Green Again
|
||||
-------------------
|
||||
|
||||
Around January 2016, it was decided that the issues with PULSE that were
|
||||
preventing test automation from fully dropping use of the legacy serial
|
||||
console would best be resolved by taking the lessons learned from PULSE
|
||||
and designing a successor. This new protocol suite, appropriately
|
||||
enough, is called PULSEv2. It is designed with test automation in mind,
|
||||
with the intention of completely replacing the legacy serial console for
|
||||
test automation, developers and the factory. It is much better at
|
||||
communicating and synchronizing link state, which solves problems that
|
||||
test automation was running into with the firmware crashing and
|
||||
rebooting getting the test harness confused. It uses a standard checksum
|
||||
without the flaws of its predecessor, and packet lengths are explicit.
|
||||
And it is future-proofed by having an option-negotiation mechanism,
|
||||
allowing us to add new features to the protocol while allowing old and
|
||||
new implementations to interoperate.
|
||||
|
||||
Applications can choose to communicate with either best-effort datagram
|
||||
service (like PULSEv1), or reliable datagram service that guarantees
|
||||
in-order datagram delivery. Having the reliable transport available
|
||||
made it very easy to implement prompt commands over PULSEv2. And it was
|
||||
also suprisingly easy to implement a PULSEv2 transport for the Pebble
|
||||
Protocol, which allows developers and test automation to interact with
|
||||
bigboards using libpebble2 and pebble-tool, exactly like they can with
|
||||
emulators and sealed watches connected to phones.
|
||||
|
||||
Test automation switched over to PULSEv2 on 2016 May 31. It immediately
|
||||
cut down test run times and, once some bugs got shaken out, measurably
|
||||
improved the reliability of test automation. It also made the captured
|
||||
logs from test runs much more useful as messages were no longer getting
|
||||
dropped. PULSEv2 was made the default for all firmware developers at the
|
||||
end of September 2016.
|
||||
|
||||
|
||||
<!-- vim: set tw=72: -->
|
419
docs/pulse2/pulse2.md
Normal file
|
@ -0,0 +1,419 @@
|
|||
PULSEv2 Protocol Suite
|
||||
======================
|
||||
|
||||
Motivation
|
||||
----------
|
||||
|
||||
The initial design of PULSE was shaped by its initial use case of flash
|
||||
imaging. Flash imaging has a few properties which allowed it to be
|
||||
implemented on top of a very simplistic wire protocol. Writing to flash
|
||||
can be split up into any number of atomic write operations that can be
|
||||
applied in arbitrary order. Flash writes are idempotent: repeatedly
|
||||
writing the same data to the same flash address does not corrupt the
|
||||
written data. Because of these properties, it was possible to implement
|
||||
the flash imaging protocol in a stateless manner simply by ensuring that
|
||||
every write was applied at least once without concern for out of order
|
||||
delivery or duplicated datagrams. The PULSE link layer was designed as
|
||||
simply as possible, guaranteeing only datagram integrity with only
|
||||
best-effort reliability and sequencing, since it was all that the flash
|
||||
imaging protocol needed.
|
||||
|
||||
As we try to use PULSE for more applications, it has become clear that
|
||||
flash imaging is a special case. Most applications have some manner of
|
||||
statefulness or non-idempotent operations, so they need guarantees about
|
||||
reliable delivery and sequencing of datagrams in order to operate
|
||||
correctly in the face of lost or corrupted datagrams. The lack of such
|
||||
guarantees in PULSE has forced these applications to bake sequencing and
|
||||
retransmissions into the application protocols in an ad-hoc manner,
|
||||
poorly. This has made the design and implementation of prompt and file
|
||||
transfer protocols more complex than necessary, and no attempt has yet
|
||||
been made to tunnel Pebble Protocol over PULSE. It's the [waterbed
|
||||
theory](http://wiki.c2.com/?WaterbedTheory) at work.
|
||||
|
||||
Adding support for reliable, ordered delivery of datagrams will allow
|
||||
for any application to make use of reliable service simply by requesting
|
||||
it. Implementation of chatty protocols will be greatly simplified.
|
||||
|
||||
Protocol Stack
|
||||
--------------
|
||||
|
||||
PULSEv2 is a layered protocol stack. The link layer provides
|
||||
integrity-assured delivery of packet data. On top of the link layer is a
|
||||
suite of transport protocols which provide multiprotocol delivery of
|
||||
application datagrams with or without guaranteed reliable in-order
|
||||
delivery. Application protocols use one or more of the available
|
||||
transports to exchange datagrams between the firmware running on a board
|
||||
and a host workstation.
|
||||
|
||||
Physical Layer
|
||||
--------------
|
||||
|
||||
PULSEv2 supports asynchronous serial byte-oriented full duplex links,
|
||||
8-N-1, octets transmitted LSB first. The link must transparently pass
|
||||
all octet values. The baud rate is 1,000,000 bps.
|
||||
|
||||
> **Why that baud rate?**
|
||||
>
|
||||
> 1 Mbaud is a convenient choice as it is the highest frequency which
|
||||
> divides perfectly into a 16 MHz core clock at 16x oversampling, and
|
||||
> works with zero error at 64, 80 and 100 MHz (with only 100 MHz
|
||||
> requiring any fractional division at all). The only downside is that
|
||||
> it is not a "standard" baud rate, but this is unlikely to be a problem
|
||||
> as FTDI, PL2303, CP2102 (but not CP2101) and likely others will handle
|
||||
> 1 Mbaud rates (at least in hardware). YMMV with Windows drivers...
|
||||
|
||||
Link Layer
|
||||
----------
|
||||
|
||||
The link layer, in a nutshell, is PPP with custom framing. The entirety
|
||||
of [RFC 1661](https://tools.ietf.org/html/rfc1661) is normative, except
|
||||
as noted in this document.
|
||||
|
||||
### Encapsulation
|
||||
|
||||
PPP encapsulation (RFC 1661, Section 2) is used. The Padding field of
|
||||
the PPP encapsulation must be empty.
|
||||
|
||||
A summary of the frame structure is shown below. This figure does not
|
||||
include octets inserted for transparency. The fields are transmitted
|
||||
from left to right.
|
||||
|
||||
Flag | Protocol | Information | FCS | Flag
|
||||
-----|----------|-------------|----------|-----
|
||||
0x55 | 2 octets | * | 4 octets | 0x55
|
||||
|
||||
#### Flag field
|
||||
|
||||
Each frame begins and ends with a Flag sequence, which is the octet 0x55
|
||||
hexadecimal. The flag is used for frame synchronization.
|
||||
|
||||
> **Why 0x55?**
|
||||
>
|
||||
> It is transmitted as bit pattern `(1)0101010101`, which is really easy
|
||||
> to spot on an oscilloscope trace or logic analyzer capture, and it
|
||||
> allows for auto baud rate detection. The STM32F7 USART supports auto
|
||||
> baud rate detection with an 0x55 character in hardware.
|
||||
|
||||
Only one Flag sequence is required between two frames. Two consecutive
|
||||
Flag sequences constitute and empty frame, which is silently discarded.
|
||||
|
||||
#### Protocol field
|
||||
|
||||
The Protocol field is used as prescribed by RFC 1661, Section 2. PPP
|
||||
assigned protocol numbers and their respective assigned protocols should
|
||||
be used wherever it makes sense. Custom protocols must not be assigned
|
||||
protocol numbers which overlap any [existing PPP assigned protocol](http://www.iana.org/assignments/ppp-numbers/ppp-numbers.xhtml).
|
||||
|
||||
#### Frame Check Sequence field
|
||||
|
||||
The Frame Check Sequence is transmitted least significant octet first.
|
||||
The check sequence is calculated using the [CRC-32](http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32)
|
||||
checksum. The parameters of the CRC algorithm are:
|
||||
|
||||
width=32 poly=0x04c11db7 init=0xffffffff refin=true refout=true
|
||||
xorout=0xffffffff check=0xcbf43926 name="CRC-32"
|
||||
|
||||
The FCS field is calculated over all bits of the Protocol and
|
||||
Information fields, not including any start and stop bits, or octets
|
||||
inserted for transparency. This also does not include the Flag sequence
|
||||
nor the FCS field itself.
|
||||
|
||||
### Transparency
|
||||
|
||||
Transparency is achieved by applying [COBS](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing)
|
||||
encoding to the Protocol, Information and FCS fields, then replacing any
|
||||
instances of 0x55 in the COBS-encoded data with 0x00.
|
||||
|
||||
### Link Operation
|
||||
|
||||
The Link Control Protocol packet format, assigned numbers and state
|
||||
machine are the same as PPP (RFC 1661), with minor exceptions.
|
||||
|
||||
> Do not be put off by the length of the RFC document. Only a small
|
||||
> subset of the protocol needs to be implemented (especially if there
|
||||
> are no negotiable options) for an implementation to be conforming.
|
||||
|
||||
> All multi-byte fields in LCP packets are transmitted in Network
|
||||
> (big-endian) byte order. The burden of converting from big-endian to
|
||||
> little-endian is very minimal, and it lets Wireshark dissectors work
|
||||
> on PULSEv2 LCP packets just like any other PPP LCP packet.
|
||||
|
||||
By prior agreement, peers MAY transmit or receive packets of certain
|
||||
protocols while the link is in any phase. This is contrary to the PPP
|
||||
standard, which requires that all non-LCP packets be rejected before the
|
||||
link reaches the Authentication phase.
|
||||
|
||||
Transport Layer
|
||||
---------------
|
||||
|
||||
### Best-Effort Application Transport (BEAT) protocol
|
||||
|
||||
Best-effort delivery with very little overhead, similar to PULSEv1.
|
||||
|
||||
#### Packet format
|
||||
|
||||
Application Protocol | Length | Information
|
||||
---------------------|----------|------------
|
||||
2 octets | 2 octets | *
|
||||
|
||||
All multibyte fields are in big-endian byte order.
|
||||
|
||||
The Length field encodes the number of octets in the Application
|
||||
Protocol, Length and Information fields of the packet. The minimum value
|
||||
of the Length field in a valid packet is 4.
|
||||
|
||||
BEAT application protocol 0x0001 is assigned to the PULSE Control
|
||||
Message Protocol (PCMP). When a BEAT packet is received by a conforming
|
||||
implementation with the Application Protocol field set to an
|
||||
unrecognized value, a PCMP Unknown Protocol message MUST be sent.
|
||||
|
||||
#### BEAT Control Protocol (BECP)
|
||||
|
||||
BECP uses the same packet exchange mechanism as the Link Control
|
||||
Protocol. BECP packets may not be exchanged until LCP is in the Opened
|
||||
state. BECP packets received before this state is reached should be
|
||||
silently discarded.
|
||||
|
||||
BECP is exactly the same as the Link Control Protocol with the following
|
||||
exceptions:
|
||||
|
||||
* Exactly one BECP packet is encapsulated in the Information field of
|
||||
Link Layer frames where the Protocol field indicates type 0xBA29 hex.
|
||||
|
||||
* Only codes 1 through 7 (Configure-Request, Configure-Ack,
|
||||
Configure-Nak, Configure-Reject, Terminate-Request, Terminate-Ack and
|
||||
Code-Reject) are used. Other codes should be treated as unrecognized
|
||||
and should result in Code-Rejects.
|
||||
|
||||
* A distinct set of configure options are used. There are currently no
|
||||
options defined.
|
||||
|
||||
#### Sending BEAT packets
|
||||
|
||||
Before any BEAT protocol packets may be communicated, both LCP and BECP
|
||||
must reach the Opened state. Exactly one BEAT protocol packet is
|
||||
encapsulated in the Information field of Link Layer frames where the
|
||||
Protocol field indicates type 0x3A29 hex.
|
||||
|
||||
### PUSH (Simplex) transport
|
||||
|
||||
Simplex best-effort delivery of datagrams. It is designed for log
|
||||
messages and other status updates from the firmware to the host. There
|
||||
is no NCP, no options, no negotiation.
|
||||
|
||||
#### Packet format
|
||||
|
||||
Application Protocol | Length | Information
|
||||
---------------------|----------|------------
|
||||
2 octets | 2 octets | *
|
||||
|
||||
All multibyte fields are in big-endian byte order.
|
||||
|
||||
The Length field encodes the number of octets in the Application
|
||||
Protocol, Length and Information fields of the packet. The minimum value
|
||||
of the Length field in a valid packet is 4.
|
||||
|
||||
#### Sending PUSH packets
|
||||
|
||||
Packets can be sent at any time regardless of the state of the link,
|
||||
including link closed. Exactly one PUSH packet is encapsulated in the
|
||||
Information field of Link Layer frames where the Protocol field
|
||||
indicates type 0x5021 hex.
|
||||
|
||||
### Reliable transport (TRAIN)
|
||||
|
||||
The Reliable transport provides reliable in-order delivery service of
|
||||
multiprotocol application datagrams. The protocol is heavily based on
|
||||
the [ITU-T Recommendation X.25](https://www.itu.int/rec/T-REC-X.25-199610-I/en)
|
||||
LAPB data-link layer. The remainder of this section relies heavily on
|
||||
the terminology used in Recommendation X.25. Readers are also assumed to
|
||||
have some familiarity with section 2 of the Recommendation.
|
||||
|
||||
#### Packet formats
|
||||
|
||||
The packet format is, in a nutshell, LAPB in extended mode carrying BEAT
|
||||
packets.
|
||||
|
||||
**Information command packets**
|
||||
|
||||
Control | Application Protocol | Length | Information
|
||||
---------|----------------------|----------|------------
|
||||
2 octets | 2 octets | 2 octets | *
|
||||
|
||||
**Supervisory commands and responses**
|
||||
|
||||
Control |
|
||||
---------|
|
||||
2 octets |
|
||||
|
||||
##### Control field
|
||||
|
||||
The control field is basically the same as LAPB in extended mode. Only
|
||||
Information transfer and Supervisory formats are supported. The
|
||||
Unnumbered format is not used as such signalling is performed
|
||||
out-of-band using the TRCP control protocol. The Information command and
|
||||
the Receive Ready, Receive Not Ready, and Reject commands and responses
|
||||
are permitted in the control field.
|
||||
|
||||
The format and meaning of the subfields in the Control field are
|
||||
described in ITU-T Recommendation X.25.
|
||||
|
||||
##### Application Protocol field
|
||||
|
||||
The protocol number for the message contained in the Information field.
|
||||
This field is only present in Information packets. The Application
|
||||
Protocol field is transmitted most-significant octet first.
|
||||
|
||||
##### Length field
|
||||
|
||||
The Length field specifies the number of octets covering the Control,
|
||||
Application Protocol, Length and Information fields. The Length field is
|
||||
only present in Information packets. The content of a valid Information
|
||||
packet must be no less than six. The Length field is transmitted
|
||||
most-significant octet first.
|
||||
|
||||
##### Information field
|
||||
|
||||
The application datagram itself. This field is only present in
|
||||
Information packets.
|
||||
|
||||
#### TRAIN Control Protocol
|
||||
|
||||
The TRAIN Control Protocol, or TRCP for short, is used to set up and
|
||||
tear down the communications channel between the two peers. TRCP uses
|
||||
the same packet exchange mechanism as the Link Control Protocol. TRCP
|
||||
packets may not be exchanged until LCP is in the Opened state. TRCP
|
||||
packets received before this state is reached should be silently
|
||||
discarded.
|
||||
|
||||
TRCP is exactly the same as the Link Control Protocol with the following
|
||||
exceptions:
|
||||
|
||||
* Exactly one TRCP packet is encapsulated in the Information field of
|
||||
Link Layer frames where the Protocol field indicates type 0xBA33 hex.
|
||||
|
||||
* Only codes 1 through 7 (Configure-Request, Configure-Ack,
|
||||
Configure-Nak, Configure-Reject, Terminate-Request, Terminate-Ack and
|
||||
Code-Reject) are used. Other codes should be treated as unrecognized
|
||||
and should result in Code-Rejects.
|
||||
|
||||
* A distinct set of configure options are used. There are currently no
|
||||
options defined.
|
||||
|
||||
The `V(S)` and `V(R)` state variables shall be reset to zero when the
|
||||
TRCP automaton signals the This-Layer-Up event. All packets in the TRAIN
|
||||
send queue are discarded when the TRCP automaton signals the
|
||||
This-Layer-Finished event.
|
||||
|
||||
#### LAPB system parameters
|
||||
|
||||
The LAPB system parameters used in information transfer have the default
|
||||
values described below. Some parameter values may be altered through the
|
||||
TRCP option negotiation mechanism. (NB: there are currently no options
|
||||
defined, so there is currently no way to alter the default values during
|
||||
the protocol negotiation phase)
|
||||
|
||||
**Maximum number of bits in an I packet _N1_** is equal to eight times
|
||||
the MRU of the link, minus the overhead imposed by the Link Layer
|
||||
framing and the TRAIN header. This parameter is not negotiable.
|
||||
|
||||
**Maximum number of outstanding I packets _k_** defaults to 1 for both
|
||||
peers. This parameter is (to be) negotiable. If left at the default, the
|
||||
protocol will operate with a Stop-and-Wait ARQ.
|
||||
|
||||
#### Transfer of application datagrams
|
||||
|
||||
Exactly one TRAIN packet is encapsulated in the Information field of
|
||||
Link Layer frames. A command packet is encapsulated in a Link Layer
|
||||
frame where the Protocol field indicates 0x3A33 hex, and a response
|
||||
packet is encapsulated in a Link Layer frame where the Protocol field
|
||||
indicates 0x3A35 hex. Transfer of datagrams shall follow the procedures
|
||||
described in Recommendation X.25 §2.4.5 _LAPB procedures for information
|
||||
transfer_. A cut-down set of procedures for a compliant implementation
|
||||
which only supports _k=1_ operation can be found in
|
||||
[reliable-transport.md](reliable-transport.md).
|
||||
|
||||
In the event of a frame rejection condition (as defined in
|
||||
Recommendation X.25), the TRCP automaton must be issued a Down event
|
||||
followed by an Up event to cause an orderly renegotiation of the
|
||||
transport protocol and reset the state variables. This is the same as
|
||||
the Restart option described in RFC 1661. A FRMR response MUST NOT be
|
||||
sent.
|
||||
|
||||
TRAIN application protocol 0x0001 is assigned to the PULSE Control
|
||||
Message Protocol (PCMP). When a TRAIN packet is received by a conforming
|
||||
implementation with the Application Protocol field set to an
|
||||
unrecognized value, a PCMP Unknown Protocol message MUST be sent.
|
||||
|
||||
### PULSE Control Message Protocol
|
||||
|
||||
The PULSE Control Message Protocol (PCMP) is used for signalling of
|
||||
control messages by the transport protocols. PCMP messages must be
|
||||
encapsulated in a transport protocol, and are interpreted within the
|
||||
context of the encapsulated transport protocol.
|
||||
|
||||
> **Why a separate protocol?**
|
||||
>
|
||||
> Many of the transports need to communicate the same types of control
|
||||
> messages. Rather than defining a different way of communicating these
|
||||
> messages for each protocol, they can use PCMP and share a single
|
||||
> definition (and implementation!) of these messages.
|
||||
|
||||
#### Packet format
|
||||
|
||||
Code | Information
|
||||
--------|------------
|
||||
1 octet | *
|
||||
|
||||
#### Defined codes
|
||||
|
||||
##### 1 - Echo Request
|
||||
|
||||
When the transport is in the Opened state, the recipient MUST respond
|
||||
with an Echo-Reply packet. When the transport is not Opened, any
|
||||
received Echo-Request packets MUST be silently discarded.
|
||||
|
||||
##### 2 - Echo Reply
|
||||
|
||||
A reply to an Echo-Request packet. The Information field MUST be copied
|
||||
from the received Echo-Request.
|
||||
|
||||
##### 3 - Discard Request
|
||||
|
||||
The receiver MUST silently discard any Discard-Request packet that it
|
||||
receives.
|
||||
|
||||
##### 129 - Port Closed
|
||||
|
||||
A packet has been received with a port number unrecognized by the
|
||||
recipient. The Information field must be filled with the port number
|
||||
copied from the received packet (without endianness conversion).
|
||||
|
||||
##### 130 - Unknown PCMP Code
|
||||
|
||||
A PCMP packet has been received with a Code field which is unknown to
|
||||
the recipient. The Information field must be filled with the Code field
|
||||
copied from the received packet.
|
||||
|
||||
----
|
||||
|
||||
Useful Links
|
||||
------------
|
||||
|
||||
* [The design document for PULSEv2](https://docs.google.com/a/pulse-dev.net/document/d/1ZlSRz5-BSQDsmutLhUjiIiDfVXTcI53QmrqENJXuCu4/edit?usp=sharing),
|
||||
which includes a draft of this documentation along with a lot of
|
||||
notes about the design decisions.
|
||||
* [Python implementation of PULSEv2](https://github.com/pebble/pulse2)
|
||||
* [Wireshark plugin for dissecting PULSEv2 packet captures](https://github.com/pebble/pulse2-wireshark-plugin)
|
||||
* [RFC 1661 - The Point to Point Protocol (PPP)](https://tools.ietf.org/html/rfc1661)
|
||||
* [RFC 1662 - PPP in HDLC-like Framing](https://tools.ietf.org/html/rfc1662)
|
||||
* [RFC 1663 - PPP Reliable Transmission](https://tools.ietf.org/html/rfc1663)
|
||||
* [RFC 1570 - PPP LCP Extensions](https://tools.ietf.org/html/rfc1570)
|
||||
* [RFC 2153 - PPP Vendor Extensions](https://tools.ietf.org/html/rfc2153)
|
||||
* [RFC 3772 - Point-to-Point Protocol (PPP) Vendor Protocol](https://tools.ietf.org/html/rfc3772)
|
||||
* [PPP Consistent Overhead Byte Stuffing (COBS)](https://tools.ietf.org/html/draft-ietf-pppext-cobs)
|
||||
* [ITU-T Recommendation X.25](https://www.itu.int/rec/T-REC-X.25-199610-I/en)
|
||||
* [Digital Data Communications Message Protocol](http://www.ibiblio.org/pub/historic-linux/early-ports/Mips/doc/DEC/ddcmp-4.1.txt)
|
||||
|
||||
|
||||
<!-- vim: set tw=72: -->
|
96
docs/pulse2/reliable-transport.md
Normal file
|
@ -0,0 +1,96 @@
|
|||
PULSEv2 Reliable Transport
|
||||
==========================
|
||||
|
||||
The purpose of this document is to describe the procedures for the PULSEv2
|
||||
reliable transport (TRAIN) to be used in the initial implementations, with
|
||||
support for only Stop-and-Wait ARQ (Automatic Repeat reQuest). Hopefully,
|
||||
limiting the scope in this way will make it simpler to implement compared to a
|
||||
more performant Go-Back-N ARQ. This document is a supplement to the description
|
||||
of TRAIN in [pulse2.md](pulse2.md).
|
||||
|
||||
The PULSEv2 reliable transport (TRAIN) is based on X.25 LAPB, which implements
|
||||
reliable datagram delivery using a Go-Back-N ARQ (Automatic Repeat reQuest)
|
||||
procedure. Since a Stop-and-Wait ARQ is equivalent to Go-Back-N with a window
|
||||
size of 1, LAPB can be readily adapted for Stop-and-Wait ARQ. The description in
|
||||
this document should hopefully be compatible with an implementation supporting
|
||||
the full Go-Back-N LAPB procedures when that implementation is configured with a
|
||||
window size of 1, so that there is a smooth upgrade path which doesn't require
|
||||
special cases or compatibility breakages.
|
||||
|
||||
Documentation conventions
|
||||
-------------------------
|
||||
|
||||
This document relies heavily on the terminology used in [ITU-T Recommendation
|
||||
X.25](https://www.itu.int/rec/T-REC-X.25-199610-I/en). Readers are also assumed
|
||||
to have some familiarity with section 2 of that document.
|
||||
|
||||
The term "station" is used in this document to mean "DCE or DTE".
|
||||
|
||||
Procedures for information transfer
|
||||
-----------------------------------
|
||||
|
||||
There is no support for communicating a busy condition. It is assumed that a
|
||||
station in a busy condition will silently drop packets, and that the timer
|
||||
recovery procedure will be sufficient to ensure reliable delivery of the dropped
|
||||
packets once the busy condition is cleared. An implementation need not support
|
||||
sending or receiving RNR packets.
|
||||
|
||||
Sending I packets
|
||||
-----------------
|
||||
|
||||
All Information transfer packets must be sent with the Poll bit set to 1. The
|
||||
procedures from X.25 §2.4.5.1 apply otherwise.
|
||||
|
||||
Receiving an I packet
|
||||
---------------------
|
||||
|
||||
When the DCE receives a valid I packet whose send sequence number N(S) is equal
|
||||
to the DCE receive state variable V(R), the DCE will accept the information
|
||||
fields of this packet, increment by one its receive state variable V(R), and
|
||||
transmit an RR response packet with N(R) equal to the value of the DCE receive
|
||||
state variable V(R). If the received I packet has the Poll bit set to 1, the
|
||||
transmitted RR packet must be a response packet with Final bit set to 1.
|
||||
Otherwise the transmitted RR packet should have the Final bit set to 0.
|
||||
|
||||
Reception of out-of-sequence I packets
|
||||
--------------------------------------
|
||||
|
||||
Since the DTE should not have more than one packet in-flight at once, an
|
||||
out-of-sequence I packet would be due to a retransmit: RR response for the most
|
||||
recently received I packet got lost, so the DTE re-sent the I packet. Discard
|
||||
the information fields of the packet and send an RR packet with N(R)=V(R).
|
||||
|
||||
Receiving acknowledgement
|
||||
-------------------------
|
||||
|
||||
When correctly receiving a RR packet, the DCE will consider this packet as an
|
||||
acknowledgement of the most recently-sent I packet if N(S) of the most
|
||||
recently-sent I packet is equal to the received N(R)-1. The DCE will stop timer
|
||||
T1 when it correctly receives an acknowledgement of the most recently-sent I
|
||||
packet.
|
||||
|
||||
Since all I packets are sent with P=1, the receiving station is obligated to
|
||||
respond with a supervisory packet. Therefore it is unnecessary to support
|
||||
acknowledgements embedded in I packets.
|
||||
|
||||
Receiving an REJ packet
|
||||
-----------------------
|
||||
|
||||
Since only one I packet may be in-flight at once, the REJ packet is due to the
|
||||
RR acknowledgement from the DTE getting lost and the DCE retransmitting the I
|
||||
packet. Treat it like an RR.
|
||||
|
||||
Waiting acknowledgement
|
||||
-----------------------
|
||||
|
||||
The DCE maintains an internal transmission attempt variable which is set to 0
|
||||
when the transport NCP signals a This-Layer-Up event, and when the DCE correctly
|
||||
receives an acknowledgement of a sent I packet.
|
||||
|
||||
If Timer T1 runs out waiting for the acknowledgement from the DTE for an I
|
||||
packet transmitted, the DCE will add one to its transmission attempt variable,
|
||||
restart Timer T1 and retransmit the unacknowledged I packet.
|
||||
|
||||
If the transmission attempt variable is equal to N2 (a system parameter), the
|
||||
DCE will initiate a restart of the transport link.
|
||||
|
37
docs/tasks.txt
Normal file
|
@ -0,0 +1,37 @@
|
|||
FreeRTOS lets us create tasks, which are independant threads of execution. We create a few ourselves, and more are created internally by FreeRTOS. We have pre-emption enabled in our FreeRTOS configuration, so we must be mindful of which other tasks are mucking with the same data. This document describes the tasks that exist in our system.
|
||||
|
||||
FreeRTOS Tasks
|
||||
==============
|
||||
Tasks defined internally by FreeRTOS.
|
||||
|
||||
"Tmr Svc" - The timer task
|
||||
--------------------------
|
||||
Timers that are registered using our timer infrastructure are executed on this task. This is a FreeRTOS subsystem that we've wrapped with the goodies in fw/timers.h.
|
||||
|
||||
"IDLE" - The idle task
|
||||
----------------------
|
||||
This is a special task used by the FreeRTOS scheduler. It's defined at it's own priority level which is at the lowest priority. If no other task is ready to run, either due to waiting on a semaphore or waiting using vTaskDelay (or something like that), the idle task is chosen to run instead.
|
||||
|
||||
We have modified FreeRTOS such that if we're in the idle task, we enter a lower power mode, either sleep or stop. Stop mode is special in that peripheral clocks are shut down when we go into stop and are not automatically turned back on when we leave stop mode. This means we have to go through and turn them all back on. This is what the `register_stop_mode_resume_callback` function does. It allows individual drivers to register callbacks that are called when we leave stop from the idle thread. This comes with a caveat though. Since the idle thread only ever runs when there's nothing else to run, the scheduler assumes that there is always a task to run. This means that if the idle task is stopped or delayed for any reason, the scheduler will explode. Therefore you are not permitted to do operations that may stop the task's execution from within the resume callback.
|
||||
|
||||
Pebble Tasks
|
||||
============
|
||||
|
||||
"main" - The main task
|
||||
----------------------
|
||||
The first task in our system. Runs the all the driver initialization code, and then gets taken over by the main launcher loop. The launcher event queue is then serviced forever in a loop.
|
||||
|
||||
"system_task" - The system task
|
||||
-------------------------------
|
||||
A lower priority task that services callbacks from a worker queue. If you are doing something that may take more than a few milliseconds, it makes sense to delegate it to this queue. For example, flash writes and reads during firmware updates are done on this task.
|
||||
|
||||
"app" - The application task
|
||||
----------------------------
|
||||
This task is created for the currently running app. No task is created for the launcher "app", as it's not a real app and just uses the main task. This task's lifetime is limited to the lifetime of the app.
|
||||
|
||||
???
|
||||
|
||||
Open Questions
|
||||
==============
|
||||
|
||||
Which tasks are allowed to manipulate the window state? What if the launcher wants to push a notification window at the same time as an app pushes it's own window?
|
BIN
docs/template/bg-navbar.png
vendored
Normal file
After Width: | Height: | Size: 298 B |
38
docs/template/footer.html
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
</div>
|
||||
<!-- start footer part -->
|
||||
<!--BEGIN GENERATE_TREEVIEW-->
|
||||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||||
<ul>
|
||||
$navpath
|
||||
<li class="footer">$generatedby
|
||||
<a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath$doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--END GENERATE_TREEVIEW-->
|
||||
<!--BEGIN !GENERATE_TREEVIEW-->
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
$generatedby  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath$doxygen.png" alt="doxygen"/>
|
||||
</a> $doxygenversion
|
||||
</small></address>
|
||||
<!--END !GENERATE_TREEVIEW-->
|
||||
|
||||
</body>
|
||||
</html>
|
78
docs/template/header.html
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!--[if IEMobile 7 ]><html class="no-js iem7"><![endif]-->
|
||||
<!--[if lt IE 9]><html class="no-js lte-ie8"><![endif]-->
|
||||
<!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js" lang="en"><!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||
|
||||
<link href='$relpath$bootstrap.css' media='screen' rel='stylesheet' type='text/css' />
|
||||
<link href='$relpath$pebble-developer.css' media='screen' rel='stylesheet' type='text/css' />
|
||||
|
||||
<link href="$relpath$tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="$relpath$jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath$dynsections.js"></script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath$$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-30638158-4']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="top" ><!-- do not remove this div, it is closed by doxygen! -->
|
||||
<div class="navbar navbar-inverse ">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
<li><a class="first" href="#"><span></span></a></li>
|
||||
<li><a href="http://developer.getpebble.com/">Develop for Pebble</a></li>
|
||||
</ul>
|
||||
<ul class="nav pull-right">
|
||||
<li class="doc-nav-searchbox">$searchbox</li>
|
||||
<li><a href="http://forums.getpebble.com/">Forum</a></li>
|
||||
<li><a href="http://developer.getpebble.com/2/api-reference/modules.html">API Documentation</a></li>
|
||||
<li><a href="http://developer.getpebble.com/2/">Guides</a></li>
|
||||
<li><a href="http://developer.getpebble.com/blog/">Developer Blog</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
BIN
docs/template/navbar-brdr.png
vendored
Normal file
After Width: | Height: | Size: 128 B |
BIN
docs/template/navbar-icon.png
vendored
Normal file
After Width: | Height: | Size: 4 KiB |