Fabio Utzig | d7f6c76 | 2017-07-27 20:50:50 -0300 | [diff] [blame] | 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> |
Andrzej Puzdrowski | b788c71 | 2018-04-12 12:42:49 +0200 | [diff] [blame] | 32 | #include "flash_map_backend/flash_map_backend.h" |
Fabio Utzig | d7f6c76 | 2017-07-27 20:50:50 -0300 | [diff] [blame] | 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 * |
| 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 |
| 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 |
| 130 | test_conf_commit(void) |
| 131 | { |
| 132 | test8 = test8_shadow; |
| 133 | |
| 134 | return 0; |
| 135 | } |
| 136 | |
| 137 | static int |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 | } |