1 #include <pb_encode.h>
2 #include <pb_decode.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <stdio.h>
6 #include "stackusage.pb.h"
7 
8 static uint8_t g_msgbuf[256];
9 static size_t g_msglen;
10 
11 /* This is a hacky way to measure actual stack usage of functions.
12  * It works by copying the stack to a global variable, and then
13  * finding the lowest location that has been modified.
14  * Currently this assumes that the platform uses a descending stack.
15  */
16 #define MAX_STACK_ENTRIES 1024
17 static uint32_t g_stackbuf[MAX_STACK_ENTRIES];
18 static volatile uint32_t *g_stackptr;
19 
start_stack_measuring()20 void start_stack_measuring()
21 {
22     uint32_t i = 0;
23     g_stackptr = (volatile uint32_t*)((uintptr_t)&i - MAX_STACK_ENTRIES * sizeof(uint32_t));
24     for (i = 0; i < MAX_STACK_ENTRIES; i++)
25     {
26         g_stackbuf[i] = g_stackptr[i];
27     }
28 }
29 
end_stack_measuring()30 int end_stack_measuring()
31 {
32     uint32_t i = 0;
33     for (i = 0; i < MAX_STACK_ENTRIES; i++)
34     {
35         if (g_stackbuf[i] != g_stackptr[i])
36         {
37             return (MAX_STACK_ENTRIES - i) * sizeof(uint32_t);
38         }
39     }
40     assert(false);
41     return 0;
42 }
43 
do_encode()44 void do_encode()
45 {
46     pb_ostream_t stream = pb_ostream_from_buffer(g_msgbuf, sizeof(g_msgbuf));
47     SettingsGroup msg = SettingsGroup_init_zero;
48     bool status;
49 
50     msg.has_settings = true;
51     msg.settings.id = 1;
52     strcpy(msg.settings.name, "abcd");
53     msg.settings.en = true;
54     msg.settings.has_begin = true;
55     msg.settings.begin.label = 1234;
56     msg.settings.begin.properties_count = 1;
57     msg.settings.begin.properties[0].which_field = Property_DeviceA_Mode_tag;
58     msg.settings.begin.properties[0].field.DeviceA_Mode = 2;
59 
60     status = pb_encode(&stream, SettingsGroup_fields, &msg);
61     g_msglen = stream.bytes_written;
62     assert(status);
63     assert(g_msglen > 10);
64 }
65 
do_decode()66 void do_decode()
67 {
68     pb_istream_t stream = pb_istream_from_buffer(g_msgbuf, g_msglen);
69     SettingsGroup msg = SettingsGroup_init_zero;
70     bool status;
71 
72     status = pb_decode(&stream, SettingsGroup_fields, &msg);
73     assert(status);
74     assert(msg.settings.begin.properties[0].field.DeviceA_Mode == 2);
75 }
76 
main()77 int main()
78 {
79     int stack_encode, stack_decode;
80 
81     start_stack_measuring();
82     do_encode();
83     stack_encode = end_stack_measuring();
84 
85     start_stack_measuring();
86     do_decode();
87     stack_decode = end_stack_measuring();
88 
89     /* Print machine-readable to stdout and user-readable to stderr */
90     printf("%d %d\n", stack_encode, stack_decode);
91     fprintf(stderr, "Stack usage: encode %d bytes, decode %d bytes\n",
92             stack_encode, stack_decode);
93     return 0;
94 }
95