1 /*
2 * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <stdarg.h>
9
10 #include "amp_config.h"
11 #include "amp_utils.h"
12 #include "aos_system.h"
13 #include "amp_defines.h"
14 #include "aos_hal_uart.h"
15 #include "aos_hal_gpio.h"
16 #include "aos/kernel.h"
17
18 #include "amp_board_config.h"
19 #include "amp_boot_recovery.h"
20 #include "app_mgr.h"
21
22 #define MOD_STR "AMP_BOOT_RECOVERY"
23
24 static gpio_dev_t amp_status_led;
25 static gpio_dev_t amp_rec_switch;
26
27 /* status led mode */
28 static AMP_STATUS amp_status = AMP_STATUS_NORMAL;
29
30 extern int download_apppack(uint8_t *buf, int32_t buf_len);
31 extern int ymodem_upgrade(void (*func)(unsigned char *, int));
32 extern int write_app_pack(const char *filename, int32_t file_size, int32_t type,
33 int32_t offset, uint8_t *buf, int32_t buf_len,
34 int32_t complete);
35
ymodem_appbin_init(void)36 static void ymodem_appbin_init(void)
37 {
38 apppack_init(write_app_pack);
39 }
40
amp_status_set(AMP_STATUS mode)41 static void amp_status_set(AMP_STATUS mode)
42 {
43 if (mode >= AMP_STATUS_END) {
44 return;
45 }
46 amp_status = mode;
47 }
48
ymodem_appbin_finish(void)49 static void ymodem_appbin_finish(void)
50 {
51 apppack_final();
52 amp_status_set(AMP_STATUS_NORMAL);
53 amp_debug(MOD_STR, "ymodem_appbin_finish");
54 }
55
ymodem_appbin_write(unsigned char * buf,int size)56 static void ymodem_appbin_write(unsigned char *buf, int size)
57 {
58 //hexdump("ymodem data", buf, size);
59 amp_status_set(AMP_STATUS_UPDATING);
60 download_apppack(buf, size);
61 }
62
_amp_status_led_on(void)63 static void _amp_status_led_on(void)
64 {
65 AMP_STATUS_IO_ON ? aos_hal_gpio_output_high(&_status_led) : aos_hal_gpio_output_low(&_status_led);
66 }
67
_amp_status_led_off(void)68 static void _amp_status_led_off(void)
69 {
70 AMP_STATUS_IO_ON ? aos_hal_gpio_output_low(&_status_led) : aos_hal_gpio_output_high(&_status_led);
71 }
72
_amp_status_led_task(void * param)73 static void _amp_status_led_task(void *param)
74 {
75
76 while (1) {
77 // amp_debug(MOD_STR, "status_led_mode set");
78 switch (amp_status) {
79 case AMP_STATUS_NORMAL:
80 /* normal running */
81 _amp_status_led_on();
82 aos_msleep(500);
83 _amp_status_led_off();
84 aos_msleep(2500);
85 break;
86 case AMP_STATUS_SERVICE_AVAILABLE:
87 /* service available */
88 _amp_status_led_on();
89 aos_msleep(2500);
90 _amp_status_led_off();
91 aos_msleep(500);
92 break;
93 case AMP_STATUS_RECOVERY:
94 /* recovery mode */
95 _amp_status_led_on();
96 aos_msleep(100);
97 _amp_status_led_off();
98 aos_msleep(100);
99 _amp_status_led_on();
100 aos_msleep(100);
101 _amp_status_led_off();
102 aos_msleep(850);
103 break;
104 case AMP_STATUS_UPDATING:
105 /* upgrading */
106 _amp_status_led_on();
107 aos_msleep(50);
108 _amp_status_led_off();
109 aos_msleep(50);
110 _amp_status_led_on();
111 aos_msleep(50);
112 _amp_status_led_off();
113 aos_msleep(50);
114 break;
115 case AMP_STATUS_JSERROR:
116 /* JS Error */
117 _amp_status_led_on();
118 aos_msleep(1000);
119 break;
120 case AMP_STATUS_COREDUMP:
121 /* JS Error */
122 _amp_status_led_on();
123 aos_msleep(1000);
124 break;
125 default:
126 amp_debug(MOD_STR, "wrong status mode");
127 break;
128 }
129 }
130 return;
131 }
132
amp_recovery_init(void)133 int amp_recovery_init(void)
134 {
135 int delay = 0, ret = -1, status_off = 1;
136 uint32_t value = 0;
137 aos_task_t amp_stat_task;
138
139 amp_debug(MOD_STR, "recovery entry");
140 amp_rec_switch.port = AMP_REC_IO;
141 amp_rec_switch.config = INPUT_PULL_UP;
142 amp_status_led.port = AMP_STATUS_IO;
143 amp_status_led.config = OUTPUT_OPEN_DRAIN_PULL_UP;
144
145 amp_error(MOD_STR, "recovery switch io is %d led port is %d", AMP_REC_IO, AMP_STATUS_IO);
146 /* configure GPIO with the given settings */
147
148 ret = aos_hal_gpio_init(&_rec_switch);
149 if (ret != 0) {
150 amp_error(MOD_STR, "recovery switch gpio init error!");
151 return 0;
152 }
153
154 // for debounce
155 while (delay++ <= 10) {
156 aos_hal_gpio_input_get(&_rec_switch, &value);
157 // recovery switch
158 if (value == !AMP_REC_IO_ON) {
159 status_off = 0;
160 }
161
162 amp_debug(MOD_STR, "gpio status: %d", value);
163 aos_msleep(10);
164 delay += 1;
165 }
166
167 if (status_off) {
168 /* enter to recovery mode */
169 amp_debug(MOD_STR, "enter to recovery, not to start JS code");
170 ret = aos_hal_gpio_init(&_status_led);
171 if (ret != 0) {
172 amp_error(MOD_STR, "recovery status gpio init error!");
173 return 0;
174 }
175 aos_task_new_ext(&_stat_task, "amp status task", _amp_status_led_task, NULL, 1024, ADDON_TSK_PRIORRITY);
176
177 amp_status_set(AMP_STATUS_RECOVERY);
178 aos_hal_gpio_finalize(&_rec_switch);
179 return -1;
180 }
181 aos_hal_gpio_finalize(&_rec_switch);
182 return 0;
183 }
184
amp_recovery_entry(void)185 int amp_recovery_entry(void)
186 {
187 ymodem_appbin_init();
188 ymodem_upgrade(ymodem_appbin_write);
189 ymodem_appbin_finish();
190 amp_debug(MOD_STR, "ymodem_upgrade done");
191 while (1) {
192 aos_msleep(1000);
193 }
194
195 return 0;
196 }
197
amp_recovery_appbin(void)198 int amp_recovery_appbin(void)
199 {
200 ymodem_appbin_init();
201 ymodem_upgrade(ymodem_appbin_write);
202 ymodem_appbin_finish();
203 return 0;
204 }
205