text: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you 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.
   */
  
  #include "os/mynewt.h"
  #include <bsp/bsp.h>
  #include <hal/hal_gpio.h>
  #include <hal/hal_flash.h>
  #include <console/console.h>
  #include <log/log.h>
  #include <stats/stats.h>
  #include <config/config.h>
  #if MYNEWT_VAL(SPLIT_LOADER)
  #include "split/split.h"
  #endif
  #include <bootutil/image.h>
  #include <imgmgr/imgmgr.h>
  #include <mgmt/mgmt.h>
  #include <oic/oc_api.h>
  #include <assert.h>
  #include <string.h>
  #include <reboot/log_reboot.h>
  
  #ifdef ARCH_sim
  #include <mcu/mcu_sim.h>
  #endif
  
  /* Task 1 */
  #define TASK1_PRIO (8)
  #define TASK1_STACK_SIZE    OS_STACK_ALIGN(192)
  #define MAX_CBMEM_BUF 600
  static struct os_task task1;
  static volatile int g_task1_loops;
  
  /* Task 2 */
  #define TASK2_PRIO (9)
  #define TASK2_STACK_SIZE    OS_STACK_ALIGN(64)
  static struct os_task task2;
  
  static struct log my_log;
  
  static volatile int g_task2_loops;
  
  /* Global test semaphore */
  static struct os_sem g_test_sem;
  
  /* For LED toggling */
  static int g_led_pin;
  
  STATS_SECT_START(gpio_stats)
  STATS_SECT_ENTRY(toggles)
  STATS_SECT_END
  
  static STATS_SECT_DECL(gpio_stats) g_stats_gpio_toggle;
  
  static STATS_NAME_START(gpio_stats)
  STATS_NAME(gpio_stats, toggles)
  STATS_NAME_END(gpio_stats)
  
  static char *test_conf_get(int argc, char **argv, char *val, int max_len);
  static int test_conf_set(int argc, char **argv, char *val);
  static int test_conf_commit(void);
  static int test_conf_export(void (*export_func)(char *name, char *val),
    enum conf_export_tgt tgt);
  
  static struct conf_handler test_conf_handler = {
      .ch_name = "test",
      .ch_get = test_conf_get,
      .ch_set = test_conf_set,
      .ch_commit = test_conf_commit,
      .ch_export = test_conf_export
  };
  
  static uint8_t test8;
  static uint8_t test8_shadow;
  static char test_str[32];
  static uint32_t cbmem_buf[MAX_CBMEM_BUF];
  static struct cbmem cbmem;
  
  static char *
  test_conf_get(int argc, char **argv, char *buf, int max_len)
  {
      if (argc == 1) {
          if (!strcmp(argv[0], "8")) {
              return conf_str_from_value(CONF_INT8, &test8, buf, max_len);
          } else if (!strcmp(argv[0], "str")) {
              return test_str;
          }
      }
      return NULL;
  }
  
  static int
  test_conf_set(int argc, char **argv, char *val)
  {
      if (argc == 1) {
          if (!strcmp(argv[0], "8")) {
              return CONF_VALUE_SET(val, CONF_INT8, test8_shadow);
          } else if (!strcmp(argv[0], "str")) {
              return CONF_VALUE_SET(val, CONF_STRING, test_str);
          }
      }
      return OS_ENOENT;
  }
  
  static int
  test_conf_commit(void)
  {
      test8 = test8_shadow;
  
      return 0;
  }
  
  static int
  test_conf_export(void (*func)(char *name, char *val), enum conf_export_tgt tgt)
  {
      char buf[4];
  
      conf_str_from_value(CONF_INT8, &test8, buf, sizeof(buf));
      func("test/8", buf);
      func("test/str", test_str);
      return 0;
  }
  
  void
  task1_handler(void *arg)
  {
      struct os_task *t;
      int prev_pin_state, curr_pin_state;
      struct image_version ver;
  
      /* Set the led pin for the E407 devboard */
      g_led_pin = LED_BLINK_PIN;
      hal_gpio_init_out(g_led_pin, 1);
  
      if (imgr_my_version(&ver) == 0) {
          console_printf("\nSlinky_OIC %u.%u.%u.%u\n",
            ver.iv_major, ver.iv_minor, ver.iv_revision,
            (unsigned int)ver.iv_build_num);
      } else {
          console_printf("\nSlinky\n");
      }
  
      while (1) {
          t = os_sched_get_current_task();
          assert(t->t_func == task1_handler);
  
          ++g_task1_loops;
  
          /* Wait one second */
          os_time_delay(OS_TICKS_PER_SEC);
  
          /* Toggle the LED */
          prev_pin_state = hal_gpio_read(g_led_pin);
          curr_pin_state = hal_gpio_toggle(g_led_pin);
          DFLT_LOG_INFO("GPIO toggle from %u to %u",
                      prev_pin_state, curr_pin_state);
          STATS_INC(g_stats_gpio_toggle, toggles);
  
          /* Release semaphore to task 2 */
          os_sem_release(&g_test_sem);
      }
  }
  
  void
  task2_handler(void *arg)
  {
      struct os_task *t;
  
      while (1) {
          /* just for debug; task 2 should be the running task */
          t = os_sched_get_current_task();
          assert(t->t_func == task2_handler);
  
          /* Increment # of times we went through task loop */
          ++g_task2_loops;
  
          /* Wait for semaphore from ISR */
          os_sem_pend(&g_test_sem, OS_TIMEOUT_NEVER);
      }
  }
  
  /*
   * OIC platform/resource registration.
   */
  static void
  omgr_app_init(void)
  {
      oc_init_platform("MyNewt", NULL, NULL);
      /*
        oc_add_device("/oic/d", "oic.d.light", "MynewtLed", "1.0", "1.0", NULL,
                    NULL);
      */
  }
  
  static const oc_handler_t omgr_oc_handler = {
      .init = omgr_app_init,
  };
  
  /**
   * init_tasks
   *
   * Called by main.c after sysinit(). This function performs initializations
   * that are required before tasks are running.
   *
   * @return int 0 success; error otherwise.
   */
  static void
  init_tasks(void)
  {
      os_stack_t *pstack;
      /* Initialize global test semaphore */
      os_sem_init(&g_test_sem, 0);
  
      pstack = malloc(sizeof(os_stack_t)*TASK1_STACK_SIZE);
      assert(pstack);
  
      os_task_init(&task1, "task1", task1_handler, NULL,
              TASK1_PRIO, OS_WAIT_FOREVER, pstack, TASK1_STACK_SIZE);
  
      pstack = malloc(sizeof(os_stack_t)*TASK2_STACK_SIZE);
      assert(pstack);
  
      os_task_init(&task2, "task2", task2_handler, NULL,
              TASK2_PRIO, OS_WAIT_FOREVER, pstack, TASK2_STACK_SIZE);
  
      oc_main_init((oc_handler_t *)&omgr_oc_handler);
  }
  
  /**
   * main
   *
   * The main task for the project. This function initializes the packages, calls
   * init_tasks to initialize additional tasks (and possibly other objects),
   * then starts serving events from default event queue.
   *
   * @return int NOTE: this function should never return!
   */
  int
  main(int argc, char **argv)
  {
      int rc;
  
  #ifdef ARCH_sim
      mcu_sim_parse_args(argc, argv);
  #endif
  
      sysinit();
  
      rc = conf_register(&test_conf_handler);
      assert(rc == 0);
  
      cbmem_init(&cbmem, cbmem_buf, MAX_CBMEM_BUF);
      log_register("log", &my_log, &log_cbmem_handler, &cbmem, LOG_SYSLEVEL);
  
      /* Point the default module at the cbmem log just registered. */
      rc = modlog_register(LOG_MODULE_DEFAULT, &my_log, LOG_LEVEL_DEBUG, NULL);
      assert(rc == 0);
  
      stats_init(STATS_HDR(g_stats_gpio_toggle),
                 STATS_SIZE_INIT_PARMS(g_stats_gpio_toggle, STATS_SIZE_32),
                 STATS_NAME_INIT_PARMS(gpio_stats));
  
      stats_register("gpio_toggle", STATS_HDR(g_stats_gpio_toggle));
  
      reboot_start(hal_reset_cause());
  
  #if MYNEWT_VAL(SPLIT_LOADER)
      {
          void *entry;
          rc = split_app_go(&entry, true);
          if(rc == 0) {
              hal_system_start(entry);
          }
      }
  #endif
  
      init_tasks();
  
      while (1) {
          os_eventq_run(os_eventq_dflt_get());
      }
      /* Never returns */
  
      return rc;
  }
  