1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include "syscfg/syscfg.h"
21 #include "sysinit/sysinit.h"
22 #include "sysflash/sysflash.h"
23 #include <os/os.h>
24 #include <bsp/bsp.h>
25 #include <hal/hal_gpio.h>
26 #include <hal/hal_flash.h>
27 #include <console/console.h>
28 #include <shell/shell.h>
29 #include <log/log.h>
30 #include <stats/stats.h>
31 #include <config/config.h>
32 #include "flash_map_backend/flash_map_backend.h"
33 #include <hal/hal_system.h>
34 #if MYNEWT_VAL(SPLIT_LOADER)
35 #include "split/split.h"
36 #endif
37 #include <newtmgr/newtmgr.h>
38 #include <bootutil/image.h>
39 #include <bootutil/bootutil.h>
40 #include <imgmgr/imgmgr.h>
41 #include <assert.h>
42 #include <string.h>
43 #include <reboot/log_reboot.h>
44 #include <os/os_time.h>
45 #include <id/id.h>
46 
47 #ifdef ARCH_sim
48 #include <mcu/mcu_sim.h>
49 #endif
50 
51 /* Task 1 */
52 #define TASK1_PRIO (8)
53 #define TASK1_STACK_SIZE    OS_STACK_ALIGN(192)
54 #define MAX_CBMEM_BUF 600
55 static struct os_task task1;
56 static volatile int g_task1_loops;
57 
58 /* Task 2 */
59 #define TASK2_PRIO (9)
60 #define TASK2_STACK_SIZE    OS_STACK_ALIGN(64)
61 static struct os_task task2;
62 
63 static struct log my_log;
64 
65 static volatile int g_task2_loops;
66 
67 /* Global test semaphore */
68 static struct os_sem g_test_sem;
69 
70 /* For LED toggling */
71 static int g_led_pin;
72 
73 STATS_SECT_START(gpio_stats)
74 STATS_SECT_ENTRY(toggles)
75 STATS_SECT_END
76 
77 static STATS_SECT_DECL(gpio_stats) g_stats_gpio_toggle;
78 
79 static STATS_NAME_START(gpio_stats)
80 STATS_NAME(gpio_stats, toggles)
81 STATS_NAME_END(gpio_stats)
82 
83 static char *test_conf_get(int argc, char **argv, char *val, int max_len);
84 static int test_conf_set(int argc, char **argv, char *val);
85 static int test_conf_commit(void);
86 static int test_conf_export(void (*export_func)(char *name, char *val),
87   enum conf_export_tgt tgt);
88 
89 static struct conf_handler test_conf_handler = {
90     .ch_name = "test",
91     .ch_get = test_conf_get,
92     .ch_set = test_conf_set,
93     .ch_commit = test_conf_commit,
94     .ch_export = test_conf_export
95 };
96 
97 static uint8_t test8;
98 static uint8_t test8_shadow;
99 static char test_str[32];
100 static uint32_t cbmem_buf[MAX_CBMEM_BUF];
101 static struct cbmem cbmem;
102 
103 static char *
test_conf_get(int argc,char ** argv,char * buf,int max_len)104 test_conf_get(int argc, char **argv, char *buf, int max_len)
105 {
106     if (argc == 1) {
107         if (!strcmp(argv[0], "8")) {
108             return conf_str_from_value(CONF_INT8, &test8, buf, max_len);
109         } else if (!strcmp(argv[0], "str")) {
110             return test_str;
111         }
112     }
113     return NULL;
114 }
115 
116 static int
test_conf_set(int argc,char ** argv,char * val)117 test_conf_set(int argc, char **argv, char *val)
118 {
119     if (argc == 1) {
120         if (!strcmp(argv[0], "8")) {
121             return CONF_VALUE_SET(val, CONF_INT8, test8_shadow);
122         } else if (!strcmp(argv[0], "str")) {
123             return CONF_VALUE_SET(val, CONF_STRING, test_str);
124         }
125     }
126     return OS_ENOENT;
127 }
128 
129 static int
test_conf_commit(void)130 test_conf_commit(void)
131 {
132     test8 = test8_shadow;
133 
134     return 0;
135 }
136 
137 static int
test_conf_export(void (* func)(char * name,char * val),enum conf_export_tgt tgt)138 test_conf_export(void (*func)(char *name, char *val), enum conf_export_tgt tgt)
139 {
140     char buf[4];
141 
142     conf_str_from_value(CONF_INT8, &test8, buf, sizeof(buf));
143     func("test/8", buf);
144     func("test/str", test_str);
145     return 0;
146 }
147 
148 static void
task1_handler(void * arg)149 task1_handler(void *arg)
150 {
151     struct os_task *t;
152     int prev_pin_state, curr_pin_state;
153     struct image_version ver;
154 
155     /* Set the led pin for the E407 devboard */
156     g_led_pin = LED_BLINK_PIN;
157     hal_gpio_init_out(g_led_pin, 1);
158 
159     if (imgr_my_version(&ver) == 0) {
160         console_printf("\nSlinky %u.%u.%u.%u\n",
161           ver.iv_major, ver.iv_minor, ver.iv_revision,
162           (unsigned int)ver.iv_build_num);
163     } else {
164         console_printf("\nSlinky\n");
165     }
166 
167     while (1) {
168         t = os_sched_get_current_task();
169         assert(t->t_func == task1_handler);
170 
171         ++g_task1_loops;
172 
173         /* Wait one second */
174         os_time_delay(OS_TICKS_PER_SEC / MYNEWT_VAL(BLINKY_TICKS_PER_SEC));
175 
176         /* Toggle the LED */
177         prev_pin_state = hal_gpio_read(g_led_pin);
178         curr_pin_state = hal_gpio_toggle(g_led_pin);
179         LOG_INFO(&my_log, LOG_MODULE_DEFAULT, "GPIO toggle from %u to %u",
180             prev_pin_state, curr_pin_state);
181         STATS_INC(g_stats_gpio_toggle, toggles);
182 
183         /* Release semaphore to task 2 */
184         os_sem_release(&g_test_sem);
185     }
186 }
187 
188 static void
task2_handler(void * arg)189 task2_handler(void *arg)
190 {
191     struct os_task *t;
192 
193     while (1) {
194         /* just for debug; task 2 should be the running task */
195         t = os_sched_get_current_task();
196         assert(t->t_func == task2_handler);
197 
198         /* Increment # of times we went through task loop */
199         ++g_task2_loops;
200 
201         /* Wait for semaphore from ISR */
202         os_sem_pend(&g_test_sem, OS_TIMEOUT_NEVER);
203     }
204 }
205 
206 /**
207  * init_tasks
208  *
209  * Called by main.c after sysinit(). This function performs initializations
210  * that are required before tasks are running.
211  *
212  * @return int 0 success; error otherwise.
213  */
214 static void
init_tasks(void)215 init_tasks(void)
216 {
217     os_stack_t *pstack;
218 
219     /* Initialize global test semaphore */
220     os_sem_init(&g_test_sem, 0);
221 
222     pstack = malloc(sizeof(os_stack_t)*TASK1_STACK_SIZE);
223     assert(pstack);
224 
225     os_task_init(&task1, "task1", task1_handler, NULL,
226             TASK1_PRIO, OS_WAIT_FOREVER, pstack, TASK1_STACK_SIZE);
227 
228     pstack = malloc(sizeof(os_stack_t)*TASK2_STACK_SIZE);
229     assert(pstack);
230 
231     os_task_init(&task2, "task2", task2_handler, NULL,
232             TASK2_PRIO, OS_WAIT_FOREVER, pstack, TASK2_STACK_SIZE);
233 }
234 
235 int read_random_data(void);
236 
237 /**
238  * main
239  *
240  * The main task for the project. This function initializes the packages, calls
241  * init_tasks to initialize additional tasks (and possibly other objects),
242  * then starts serving events from default event queue.
243  *
244  * @return int NOTE: this function should never return!
245  */
246 int
main(int argc,char ** argv)247 main(int argc, char **argv)
248 {
249     int rc;
250 
251 #ifdef ARCH_sim
252     mcu_sim_parse_args(argc, argv);
253 #endif
254 
255     sysinit();
256 
257     rc = conf_register(&test_conf_handler);
258     assert(rc == 0);
259 
260     cbmem_init(&cbmem, cbmem_buf, MAX_CBMEM_BUF);
261     log_register("log", &my_log, &log_cbmem_handler, &cbmem, LOG_SYSLEVEL);
262 
263     stats_init(STATS_HDR(g_stats_gpio_toggle),
264                STATS_SIZE_INIT_PARMS(g_stats_gpio_toggle, STATS_SIZE_32),
265                STATS_NAME_INIT_PARMS(gpio_stats));
266 
267     stats_register("gpio_toggle", STATS_HDR(g_stats_gpio_toggle));
268 
269     conf_load();
270 
271     reboot_start(hal_reset_cause());
272 
273     (void) read_random_data();
274 
275     init_tasks();
276 
277     /* If this app is acting as the loader in a split image setup, jump into
278      * the second stage application instead of starting the OS.
279      */
280 #if MYNEWT_VAL(SPLIT_LOADER)
281     {
282         void *entry;
283         rc = split_app_go(&entry, true);
284         if(rc == 0) {
285             hal_system_restart(entry);
286         }
287     }
288 #endif
289 
290     /*
291      * As the last thing, process events from default event queue.
292      */
293     while (1) {
294         os_eventq_run(os_eventq_dflt_get());
295     }
296 }
297